From 547237277d3c9f2d7932a3d8d5cc284590132d19 Mon Sep 17 00:00:00 2001 From: Terry Truong Date: Tue, 24 Jan 2023 21:03:32 +1100 Subject: For search, jump to 'appropriate' scale --- src/components/TimeLine.vue | 11 ++++------- src/lib.ts | 30 +++++++++++++++++++++++++++++- tests/lib.test.ts | 18 +++++++++++++++++- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue index 373439a..18ae107 100644 --- a/src/components/TimeLine.vue +++ b/src/components/TimeLine.vue @@ -88,7 +88,8 @@ import {moduloPositive, animateWithClass, getTextWidth} from '../util'; import { getDaysInMonth, MIN_CAL_DATE, MONTH_NAMES, HistDate, HistEvent, getImagePath, dateToYearStr, dateToTickStr, MIN_DATE, MAX_DATE, MONTH_SCALE, DAY_SCALE, SCALES, - stepDate, getScaleRatio, getNumSubUnits, getUnitDiff, getEventPrecision, dateToUnit, dateToScaleDate, + stepDate, getScaleRatio, getNumSubUnits, getUnitDiff, getEventPrecision, getScaleForJump, + dateToUnit, dateToScaleDate, TimelineState, } from '../lib'; import {useStore} from '../store'; @@ -1332,12 +1333,8 @@ watch(() => props.searchTarget, () => { if (!idToPos.value.has(event.id)){ // If not already visible // Determine new time range - let tempScale = scale.value; - let targetDate = event.start; - if (targetDate.isEarlier(MIN_CAL_DATE) && tempScale < 1){ // Account for jumping out of calendar limits - tempScale = getEventPrecision(event); - } - targetDate = dateToScaleDate(targetDate, tempScale); + let tempScale = getScaleForJump(event); + let targetDate = dateToScaleDate(event.start, tempScale); const startEndDiff = getUnitDiff(startDate.value, endDate.value, scale.value); let targetStart = stepDate(targetDate, tempScale, {forward: false, count: Math.floor(startEndDiff / 2)}); if (targetStart.isEarlier(MIN_DATE)){ diff --git a/src/lib.ts b/src/lib.ts index 051a449..1067119 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -628,7 +628,7 @@ export function getUnitDiff(date: HistDate, date2: HistDate, scale: number): num } } -// Returns smallest scale at which 'event's start-startUpper range is within one unit, or infinity +// Returns smallest scale at which 'event's start-startUpper range is within one unit, or infinity if there is none export function getEventPrecision(event: HistEvent): number { // Note: Intentionally not adding an exception for century and millenia ranges like // 101 to 200 (as opposed to 100 to 199) being interpreted as 'within' one 100/1000-year scale unit @@ -649,6 +649,34 @@ export function getEventPrecision(event: HistEvent): number { return Number.POSITIVE_INFINITY; } +// Returns an 'appropriate' scale to use when jumping to a target date +export function getScaleForJump(event: HistEvent): number { + const start = event.start; + const startUpper = event.startUpper; + if (start.gcal != null){ + if (start.day > 1){ + return MONTH_SCALE; // Intentionally not using DAY_SCALE + } else if (start.month > 1 + || startUpper != null // Account for month-precision events + && gregorianToJdn(start.year, start.month+1, 0) + == gregorianToJdn(startUpper.year, startUpper.month, startUpper.day)){ + return MONTH_SCALE; + } + } + for (let scaleIdx = 0; scaleIdx < SCALES.length - 2; scaleIdx++){ + const scale = SCALES[scaleIdx]; + if ((scale == 100 || scale == 1e3) // Account for century/millenium-precision events + && moduloPositive(start.year - 1, scale) == 0 && startUpper != null + && startUpper.year == start.year + scale - 1 || start.year + scale - 1 == 0){ // Account for no 0 BC + return scale; + } + if (moduloPositive(start.year, scale) == 0){ + return scale; + } + } + throw new Error('Invalid state'); +} + export function dateToUnit(date: HistDate, scale: number): number { // For a YearDate and sub-yearly scale, uses the first day of the YearDate's year if (scale >= 1){ diff --git a/tests/lib.test.ts b/tests/lib.test.ts index 4810c55..5f602d3 100644 --- a/tests/lib.test.ts +++ b/tests/lib.test.ts @@ -6,7 +6,7 @@ import { dateToDisplayStr, boundedDateToStr, queryServer, jsonToHistDate, jsonToHistEvent, DAY_SCALE, MONTH_SCALE, stepDate, inDateScale, getScaleRatio, getUnitDiff, - getEventPrecision, dateToUnit, dateToScaleDate, + getEventPrecision, getScaleForJump, dateToUnit, dateToScaleDate, DateRangeTree, } from '/src/lib.ts'; @@ -233,6 +233,22 @@ test('getEventPrecision', () => { expect(getEventPrecision(new HistEvent(1, 'one', new CalDate(1, 2, 3), new CalDate(1, 2, 3)))).toBe(DAY_SCALE) }) +test('getScaleForJump', () => { + expect(getScaleForJump(new HistEvent(1, '1', new CalDate(1970, 2, 3), null))).toBe(DAY_SCALE) + expect(getScaleForJump(new HistEvent(1, '1', new CalDate(1970, 2, 1), null))).toBe(MONTH_SCALE) + expect(getScaleForJump(new HistEvent(1, '1', new CalDate(100, 1, 1), new CalDate(100, 1, 31)))).toBe(MONTH_SCALE) + expect(getScaleForJump(new HistEvent(1, '1', new CalDate(12, 1, 1), null))).toBe(1) + expect(getScaleForJump(new HistEvent(1, '1', new YearDate(-20), null))).toBe(10) + expect(getScaleForJump(new HistEvent(1, '1', new YearDate(-100), null))).toBe(100) + expect(getScaleForJump(new HistEvent(1, '1', new YearDate(-99), new CalDate(-1, 1, 1)))).toBe(100) + expect(getScaleForJump(new HistEvent(1, '1', new YearDate(1501), new CalDate(1600, 1, 1)))).toBe(100) + expect(getScaleForJump(new HistEvent(1, '1', new YearDate(1500), new CalDate(1599, 1, 1)))).toBe(100) + expect(getScaleForJump(new HistEvent(1, '1', new YearDate(1001), null))).toBe(1) + expect(getScaleForJump(new HistEvent(1, '1', new YearDate(1001), new YearDate(2000)))).toBe(1000) + expect(getScaleForJump(new HistEvent(1, '1', new CalDate(1e5, 1, 1), null))).toBe(1e5) + expect(getScaleForJump(new HistEvent(1, '1', new CalDate(1e5+1, 1, 1), null))).toBe(1) +}) + test('dateToUnit', () => { expect(dateToUnit(new CalDate(2013), 1e3)).toBe(2) expect(dateToUnit(new CalDate(2013), 100)).toBe(20) -- cgit v1.2.3