aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTerry Truong <terry06890@gmail.com>2022-10-20 15:31:05 +1100
committerTerry Truong <terry06890@gmail.com>2022-10-20 15:31:05 +1100
commit83366605d1bd43c245c4c110fadfd1a6fd05d3c2 (patch)
treea7d0352d2a4d4e14b8113dcfdf28d06a06af20d4 /src
parentf09bfa345519f7d070ae9c7474ef8b4f91b22bae (diff)
Add gcal to client-side HistDates
Add YearDate and CalDate Restrict non-calendar HistDates to years before 4713 BC
Diffstat (limited to 'src')
-rw-r--r--src/App.vue8
-rw-r--r--src/components/TimeLine.vue7
-rw-r--r--src/lib.ts74
-rw-r--r--src/store.ts6
4 files changed, 63 insertions, 32 deletions
diff --git a/src/App.vue b/src/App.vue
index 4eed256..c3cf6bf 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -39,7 +39,7 @@ import PlusIcon from './components/icon/PlusIcon.vue';
import SettingsIcon from './components/icon/SettingsIcon.vue';
import HelpIcon from './components/icon/HelpIcon.vue';
// Other
-import {HistDate, TimelineState, HistEvent, queryServer, HistEventJson, jsonToHistEvent, cmpHistEvent,
+import {HistDate, YearDate, TimelineState, HistEvent, queryServer, HistEventJson, jsonToHistEvent, cmpHistEvent,
timeout} from './lib';
import {useStore} from './store';
import {RBTree, rbtree_shallow_copy} from './rbtree';
@@ -109,7 +109,7 @@ function cmpDatePairs(datePair1: [HistDate, HistDate], datePair2: [HistDate, His
}
function isExhaustedRange(startDate: HistDate, endDate: HistDate): boolean {
// Check if input range is contained in a stored exhausted range
- let itr = exhaustedRanges.lowerBound([startDate, new HistDate(1)]);
+ let itr = exhaustedRanges.lowerBound([startDate, new YearDate()]);
let datePair = itr.data();
if (datePair == null){
datePair = itr.prev();
@@ -129,7 +129,7 @@ function isExhaustedRange(startDate: HistDate, endDate: HistDate): boolean {
function addExhaustedRange(startDate: HistDate, endDate: HistDate){
let rangesToRemove: HistDate[] = []; // Holds starts of ranges to remove
// Find ranges to remove
- let itr = exhaustedRanges.lowerBound([startDate, new HistDate(1)]);
+ let itr = exhaustedRanges.lowerBound([startDate, new YearDate()]);
let prevRange = itr.prev();
if (prevRange != null){ // Check for start-overlapping range
if (prevRange[1].isEarlier(startDate)){
@@ -153,7 +153,7 @@ function addExhaustedRange(startDate: HistDate, endDate: HistDate){
}
// Remove included/overlapping ranges
for (let start of rangesToRemove){
- exhaustedRanges.remove([start, new HistDate(1)]);
+ exhaustedRanges.remove([start, new YearDate()]);
}
// Add possibly-merged range
if (prevRange != null){
diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue
index 5aec9b2..8a6ddc4 100644
--- a/src/components/TimeLine.vue
+++ b/src/components/TimeLine.vue
@@ -63,9 +63,9 @@ import IconButton from './IconButton.vue';
// Icons
import MinusIcon from './icon/MinusIcon.vue';
// Other
-import {WRITING_MODE_HORZ, MIN_DATE, MAX_DATE, MONTH_SCALE, DAY_SCALE, SCALES, MIN_CAL_DATE,
- HistDate, stepDate, inDateScale, getScaleRatio, getUnitDiff, getDaysInMonth, moduloPositive, TimelineState,
- HistEvent, getImagePath} from '../lib';
+import {WRITING_MODE_HORZ, MIN_DATE, MAX_DATE, MONTH_SCALE, DAY_SCALE, SCALES,
+ MIN_CAL_YEAR, HistDate, CalDate, stepDate, inDateScale, getScaleRatio, getUnitDiff, getDaysInMonth,
+ moduloPositive, TimelineState, HistEvent, getImagePath} from '../lib';
import {useStore} from '../store';
import {RBTree} from '../rbtree';
@@ -132,6 +132,7 @@ const mainlineOffset = computed(() => { // Distance mainline-area line to side o
// Timeline data
const ID = props.initialState.id as number;
+const MIN_CAL_DATE = new CalDate(MIN_CAL_YEAR, 1, 1);
const startDate = ref(props.initialState.startDate); // Earliest date to display
const endDate = ref(props.initialState.endDate);
const startOffset = ref(store.defaultEndTickOffset); // Fraction of a scale unit before startDate to show
diff --git a/src/lib.ts b/src/lib.ts
index 2dda2ec..fa803bc 100644
--- a/src/lib.ts
+++ b/src/lib.ts
@@ -75,11 +75,14 @@ export function getDaysInMonth(year: number, month: number){
}
// For date representation
+export const MIN_CAL_YEAR = -4713; // Year after which months/day scales are usable
export class HistDate {
+ gcal: boolean | null;
year: number;
month: number;
day: number;
- constructor(year: number, month=1, day=1){
+ constructor(gcal: boolean | null, year: number, month: number, day: number){
+ this.gcal = gcal;
this.year = year;
this.month = month;
this.day = day;
@@ -93,15 +96,6 @@ export class HistDate {
return Math.floor(this.year / scale) == Math.floor(other.year / scale);
}
}
- cmp(other: HistDate, scale=DAY_SCALE){
- if (this.isEarlier(other, scale)){
- return -1;
- } else if (!this.equals(other, scale)){
- return 1;
- } else {
- return 0;
- }
- }
isEarlier(other: HistDate, scale=DAY_SCALE){
const yearlyScale = scale != DAY_SCALE && scale != MONTH_SCALE;
const thisYear = yearlyScale ? Math.floor(this.year / scale) : this.year;
@@ -116,14 +110,23 @@ export class HistDate {
}
}
}
+ cmp(other: HistDate, scale=DAY_SCALE){
+ if (this.isEarlier(other, scale)){
+ return -1;
+ } else if (!this.equals(other, scale)){
+ return 1;
+ } else {
+ return 0;
+ }
+ }
toInt(){
return this.day + this.month * 50 + this.year * 1000;
}
toString(){
- if (this.isEarlier(MIN_CAL_DATE)){
- return `${this.year}`;
- } else {
+ if (this.gcal != null){
return `${this.year}-${this.month}-${this.day}`;
+ } else {
+ return `${this.year}`;
}
}
toDisplayString(){
@@ -161,7 +164,7 @@ export class HistDate {
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
return monthNames[this.month - 1];
} else {
- if (this.day == 1){ // TODO: Show instead of just month name when at day-scale?
+ if (this.day == 1){
return '1st';
} else if (this.day == 2){
return '2nd';
@@ -172,7 +175,7 @@ export class HistDate {
}
}
}
- getDayDiff(other: HistDate){
+ getDayDiff(other: HistDate){ // Assumes neither date has gcal=null
const jdn2 = gregorianToJdn(this.year, this.month, this.day);
const jdn1 = gregorianToJdn(other.year, other.month, other.day);
return Math.abs(jdn1 - jdn2);
@@ -201,15 +204,38 @@ export class HistDate {
return yearDiff;
}
clone(){
- return new HistDate(this.year, this.month, this.day);
+ return new HistDate(this.gcal, this.year, this.month, this.day);
+ }
+}
+export class YearDate extends HistDate {
+ declare gcal: null;
+ declare year: number;
+ declare month: 1;
+ declare day: 1;
+ constructor(year=MIN_CAL_YEAR-1){
+ if (year >= MIN_CAL_YEAR){
+ throw new Error(`Year must be before ${MIN_CAL_YEAR}`);
+ }
+ super(null, year, 1, 1);
+ }
+}
+export class CalDate extends HistDate {
+ declare gcal: boolean;
+ declare year: number;
+ declare month: number;
+ declare day: number;
+ constructor(year: number, month: number, day: number, gcal=true){
+ if (year < MIN_CAL_YEAR){
+ throw new Error(`Year must not be before ${MIN_CAL_YEAR}`);
+ }
+ super(gcal, year, month, day);
}
}
// Timeline parameters
const currentDate = new Date();
-export const MIN_DATE = new HistDate(-13.8e9);
-export const MAX_DATE = new HistDate(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
-export const MIN_CAL_DATE = new HistDate(-4700, 1, 1); // Date after which months/day scales are usable
+export const MIN_DATE = new YearDate(-13.8e9);
+export const MAX_DATE = new CalDate(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
export const MONTH_SCALE = -1;
export const DAY_SCALE = -2;
export const SCALES = [1e9, 1e8, 1e7, 1e6, 1e5, 1e4, 1e3, 100, 10, 1, MONTH_SCALE, DAY_SCALE];
@@ -412,8 +438,8 @@ export function getImagePath(imgId: number): string {
export type HistDateJson = {
gcal: boolean | null,
year: number,
- month: number | null,
- day: number | null,
+ month: number,
+ day: number,
}
export type HistEventJson = {
id: number,
@@ -427,7 +453,11 @@ export type HistEventJson = {
pop: number,
}
export function jsonToHistDate(json: HistDateJson){
- return new HistDate(json.year, json.month == null ? 1 : json.month, json.day == null ? 1 : json.day);
+ if (json.gcal == null){
+ return new YearDate(json.year);
+ } else {
+ return new CalDate(json.year, json.month, json.day, json.gcal);
+ }
}
export function jsonToHistEvent(json: HistEventJson){
return {
diff --git a/src/store.ts b/src/store.ts
index 7cf815f..66d73ac 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -3,7 +3,7 @@
*/
import {defineStore} from 'pinia';
-import {HistDate} from './lib';
+import {CalDate} from './lib';
export const useStore = defineStore('store', {
state: () => {
@@ -37,8 +37,8 @@ export const useStore = defineStore('store', {
zoomRatio: 1.5, // Ratio of timeline expansion upon zooming out
dragInertia: 0.1, // Multiplied by final-drag-speed (pixels-per-sec) to get extra scroll distance
//
- initialStartDate: new HistDate(1900, 1, 1),
- initialEndDate: new HistDate(2000, 1, 1),
+ initialStartDate: new CalDate(1900, 1, 1),
+ initialEndDate: new CalDate(2000, 1, 1),
color,
transitionDuration: 300,
};