From 6b8d7fcda5dc884086bfb5df914e3f13dca5ac3c Mon Sep 17 00:00:00 2001
From: Terry Truong <terry06890@gmail.com>
Date: Wed, 28 Dec 2022 13:52:12 +1100
Subject: Don't re-query server for same range and scale

---
 src/App.vue | 86 ++++++++++++++++++++++++-------------------------------------
 1 file changed, 33 insertions(+), 53 deletions(-)

(limited to 'src/App.vue')

diff --git a/src/App.vue b/src/App.vue
index e50c980..eacc73f 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -21,8 +21,7 @@
 		<time-line v-for="(state, idx) in timelines" :key="state.id"
 			:vert="vert" :initialState="state" :closeable="timelines.length > 1" :eventTree="eventTree"
 			class="grow basis-full min-h-0 outline outline-1"
-			@remove="onTimelineRemove(idx)" @state-chg="onTimelineChg($event, idx)"
-			@event-req="onEventReq" @event-display="onEventDisplay($event, idx)"/>
+			@remove="onTimelineRemove(idx)" @state-chg="onTimelineChg($event, idx)" @event-display="onEventDisplay"/>
 		<base-line :vert="vert" :timelines="timelines" class='m-1 sm:m-2'/>
 	</div>
 </div>
@@ -39,8 +38,8 @@ import PlusIcon from './components/icon/PlusIcon.vue';
 import SettingsIcon from './components/icon/SettingsIcon.vue';
 import HelpIcon from './components/icon/HelpIcon.vue';
 // Other
-import {timeout, HistDate, YearDate, HistEvent, queryServer, HistEventJson, jsonToHistEvent,
-	TimelineState, cmpHistEvent, DateRangeTree} from './lib';
+import {timeout, HistDate, HistEvent, queryServer, HistEventJson, jsonToHistEvent,
+	SCALES, TimelineState, cmpHistEvent, DateRangeTree} from './lib';
 import {useStore} from './store';
 import {RBTree, rbtree_shallow_copy} from './rbtree';
 
@@ -102,49 +101,54 @@ function onTimelineRemove(idx: number){
 // For storing and looking up events
 const eventTree: ShallowRef<RBTree<HistEvent>> = shallowRef(new RBTree(cmpHistEvent));
 let idToEvent: Map<number, HistEvent> = new Map();
-let exhaustedRanges = new DateRangeTree(); // Holds ranges for which the server has no more events
+// For keeping event data under a memory limit
+const EXCESS_EVENTS_THRESHOLD = 10000;
+let displayedEvents: Map<number, number[]> = new Map(); // Maps TimeLine IDs to IDs of displayed events
+function reduceEvents(){
+	// Get events to keep
+	let eventsToKeep: Map<number, HistEvent> = new Map();
+	for (let [, ids] of displayedEvents){
+		for (let id of ids){
+			eventsToKeep.set(id, idToEvent.get(id)!);
+		}
+	}
+	// Create new event tree
+	let newTree = new RBTree(cmpHistEvent);
+	for (let [, event] of eventsToKeep){
+		newTree.insert(event);
+	}
+	// Replace old data
+	eventTree.value = newTree;
+	idToEvent = eventsToKeep;
+}
 // For getting events from server
-const EVENT_REQ_LIMIT = 30;
-const REQ_EXCLS_LIMIT = 100;
+const EVENT_REQ_LIMIT = 100;
+let queriedRanges: DateRangeTree[] = SCALES.map(() => new DateRangeTree());
+	// For each scale, holds date ranges for which data has already been queried fromm the server
 let pendingReq = false; // Used to serialise event-req handling
-async function onEventReq(startDate: HistDate, endDate: HistDate){
+async function onEventDisplay(
+		timelineId: number, eventIds: number[], firstDate: HistDate, lastDate: HistDate, scaleIdx: number){
 	while (pendingReq){
 		await timeout(100);
 	}
 	pendingReq = true;
 	// Skip if exhausted range
-	if (exhaustedRanges.has([startDate, endDate])){
-		pendingReq = false;
-		return;
-	}
-	// Get existing events in range
-	let existingEventIds: number[] = [];
-	let itr = eventTree.value.lowerBound(new HistEvent(0, '', startDate));
-	while (itr.data() != null){
-		let event = itr.data()!;
-		itr.next();
-		if (endDate.isEarlier(event.start)){
-			break;
-		}
-		existingEventIds.push(event.id);
-	}
-	if (existingEventIds.length > REQ_EXCLS_LIMIT){
-		console.log('WARNING: Exceeded request exclusions limit');
+	if (queriedRanges[scaleIdx].has([firstDate, lastDate])){
 		pendingReq = false;
 		return;
 	}
 	// Get events from server
 	let urlParams = new URLSearchParams({
 		type: 'events',
-		range: `${startDate}.${endDate}`,
+		range: `${firstDate}.${lastDate}`,
 		limit: String(EVENT_REQ_LIMIT),
-		excl: existingEventIds.join('.'),
 	});
 	let responseObj: HistEventJson[] = await queryServer(urlParams);
 	if (responseObj == null){
 		pendingReq = false;
 		return;
 	}
+	queriedRanges[scaleIdx].add([firstDate, lastDate]);
 	// Add to map
 	let added = false;
 	for (let eventObj of responseObj){
@@ -158,39 +162,15 @@ async function onEventReq(startDate: HistDate, endDate: HistDate){
 	// Notify components if new events were added
 	if (added){
 		eventTree.value = rbtree_shallow_copy(eventTree.value); // Note: triggerRef(eventTree) does not work here
-	} else {
-		exhaustedRanges.add([startDate, endDate]); // Mark as exhausted range
 	}
 	// Check memory limit
+	displayedEvents.set(timelineId, eventIds);
 	if (eventTree.value.size > EXCESS_EVENTS_THRESHOLD){
 		reduceEvents();
+		queriedRanges.forEach((t: DateRangeTree) => t.clear());
 	}
 	pendingReq = false;
 }
-// For keeping event data under a memory limit
-const EXCESS_EVENTS_THRESHOLD = 10000;
-let displayedEvents: Map<number, number[]> = new Map(); // Maps TimeLine IDs to IDs of displayed events
-function onEventDisplay(eventIds: number[], timelineId: number){
-	displayedEvents.set(timelineId, eventIds);
-}
-function reduceEvents(){
-	// Get events to keep
-	let eventsToKeep: Map<number, HistEvent> = new Map();
-	for (let [, ids] of displayedEvents){
-		for (let id of ids){
-			eventsToKeep.set(id, idToEvent.get(id)!);
-		}
-	}
-	// Create new event tree
-	let newTree = new RBTree(cmpHistEvent);
-	for (let [, event] of eventsToKeep){
-		newTree.insert(event);
-	}
-	// Replace old data
-	eventTree.value = newTree;
-	idToEvent = eventsToKeep;
-	exhaustedRanges.clear();
-}
 
 // For resize handling
 let lastResizeHdlrTime = 0; // Used to throttle resize handling
-- 
cgit v1.2.3

