aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbackend/histplorer.py11
-rw-r--r--backend/tests/test_histplorer.py4
-rw-r--r--src/App.vue46
-rw-r--r--src/components/TimeLine.vue4
-rw-r--r--src/lib.ts2
-rw-r--r--tests/lib.test.ts10
6 files changed, 57 insertions, 20 deletions
diff --git a/backend/histplorer.py b/backend/histplorer.py
index b8dc40e..830705b 100755
--- a/backend/histplorer.py
+++ b/backend/histplorer.py
@@ -9,7 +9,7 @@ Expected HTTP query parameters:
- range: With type=events, specifies a historical-date range
If absent, the default is 'all of time'.
Examples:
- range=1000.1910-10-09 means '1000 AD to 09/10/1910 (inclusive)'
+ range=1000.1910-10-09 means '1000 AD up to and excluding 09/10/1910'
range=-13000. means '13000 BC onwards'
- scale: With type=events, specifies a date scale
- incl: With type=events, specifies an event to include, as an event ID
@@ -230,7 +230,9 @@ def lookupEvents(start: HistDate | None, end: HistDate | None, scale: int, ctg:
year = start.year if start.month == 1 and start.day == 1 else start.year + 1
params.extend([startJdn, year])
if end is not None:
- constraint = '(start <= ? AND fmt > 0 OR start <= ? AND fmt = 0)'
+ constraint = '(start < ? AND fmt > 0 OR start < ? AND fmt = 0)'
+ if scale < 1 and (end.month > 1 or end.day > 1):
+ constraint = '(start < ? AND fmt > 0 OR start <= ? AND fmt = 0)'
if end.gcal is None:
endJdn = gregorianToJdn(end.year, 1, 1) if end.year >= MIN_CAL_YEAR else -1
constraints.append(constraint)
@@ -238,8 +240,7 @@ def lookupEvents(start: HistDate | None, end: HistDate | None, scale: int, ctg:
else:
endJdn = gregorianToJdn(end.year, end.month, end.day)
constraints.append(constraint)
- year = end.year if end.month == 12 and end.day == 31 else end.year - 1
- params.extend([endJdn, year])
+ params.extend([endJdn, end.year])
# Constrain by event category
if ctg is not None:
constraints.append('ctg = ?')
@@ -289,7 +290,7 @@ def lookupUnitCounts(
query += ' AND unit >= ?'
params.append(dateToUnit(start, scale))
if end:
- query += ' AND unit <= ?'
+ query += ' AND unit < ?'
params.append(dateToUnit(end, scale))
query += ' ORDER BY unit ASC LIMIT ' + str(MAX_REQ_UNIT_COUNTS + 1)
# Get results
diff --git a/backend/tests/test_histplorer.py b/backend/tests/test_histplorer.py
index 592d534..68aae8f 100644
--- a/backend/tests/test_histplorer.py
+++ b/backend/tests/test_histplorer.py
@@ -2,7 +2,7 @@ import unittest
import tempfile, os
from tests.common import createTestDbTable
-from histplorer import handleReq, HistDate, Event, EventResponse, ImgInfo, EventInfo, SuggResponse
+from histplorer import handleReq, HistDate, Event, ImgInfo, EventInfo, SuggResponse
def initTestDb(dbFile: str) -> None:
createTestDbTable(
@@ -115,7 +115,7 @@ class TestHandleReq(unittest.TestCase):
Event(3, 'event three', HistDate(True, 1990, 10, 10), HistDate(True, 2000, 10, 10), None, None,
'discovery', 30, 0),
])
- self.assertEqual(response.unitCounts, {1900: 2, 1990: 1, 2000: 1, 2001: 1, 2002: 1})
+ self.assertEqual(response.unitCounts, {1900: 2, 1990: 1, 2000: 1, 2001: 1})
response = handleReq(self.dbFile, {'QUERY_STRING': 'type=events&range=.1999-11-27&scale=1&ctg=event'})
self.assertEqual(response.events, [
Event(4, 'event four', HistDate(False, -2000, 10, 10), None, HistDate(False, 1, 10, 10), None,
diff --git a/src/App.vue b/src/App.vue
index b97e55a..de127f6 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -102,7 +102,8 @@ 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();
-const unitCountMaps: Ref<Map<number, number>[]> = ref(SCALES.map(() => new Map())); // For each scale, maps units to event counts
+const unitCountMaps: Ref<Map<number, number>[]> = ref(SCALES.map(() => new Map()));
+ // For each scale, maps units to event counts
// 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
@@ -143,6 +144,7 @@ function reduceEvents(){
}
// For getting events from server
const EVENT_REQ_LIMIT = 300;
+const MAX_EVENTS_PER_UNIT = 4; // Should equal MAX_DISPLAYED_PER_UNIT in backend gen_disp_data.py
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
@@ -152,10 +154,44 @@ async function onEventDisplay(
await timeout(100);
}
pendingReq = true;
- // Skip if exhausted range
- if (queriedRanges[scaleIdx].has([firstDate, lastDate])){
- pendingReq = false;
- return;
+ // Skip if range has been queried, and enough of its events have been obtained
+ if (queriedRanges[scaleIdx].contains([firstDate, lastDate])){
+ // Get number of events in range, server-side
+ let fullCount = 0;
+ let date = firstDate.clone();
+ let eventCounts: Map<number, number> = new Map(); // For calculating number of events, client-side
+ while (date.isEarlier(lastDate)){
+ let unit = dateToUnit(date, SCALES[scaleIdx]);
+ if (unitCountMaps.value[scaleIdx].has(unit)){
+ fullCount += Math.min(MAX_EVENTS_PER_UNIT, unitCountMaps.value[scaleIdx].get(unit)!);
+ }
+ eventCounts.set(unit, 0);
+ stepDate(date, SCALES[scaleIdx], {inplace: true});
+ }
+ if (fullCount > 0){
+ // Get number of events, client-side
+ let eventCount = 0;
+ let itr = eventTree.value.lowerBound(new HistEvent(0, '', firstDate))
+ while (itr.data() != null){
+ let event = itr.data()!;
+ itr.next();
+ if (!event.start.isEarlier(lastDate)){
+ break;
+ }
+ let unit = dateToUnit(event.start, SCALES[scaleIdx]);
+ if (eventCounts.has(unit)){
+ eventCounts.set(unit, eventCounts.get(unit)! + 1);
+ }
+ }
+ for (let [, count] of eventCounts.entries()){
+ eventCount += Math.min(MAX_EVENTS_PER_UNIT, count);
+ }
+ // If we have enough events
+ if (eventCount >= fullCount || eventCount >= EVENT_REQ_LIMIT){
+ pendingReq = false;
+ return;
+ }
+ }
}
// Get events from server
let urlParams = new URLSearchParams({
diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue
index 6595bed..76d78d0 100644
--- a/src/components/TimeLine.vue
+++ b/src/components/TimeLine.vue
@@ -407,7 +407,7 @@ const endIsLastVisible = computed(() => {
function dateToOffset(date: HistDate){ // Assumes 'date' is >=firstDate and <=lastDate
// Find containing major tick
let tickIdx = firstIdx.value;
- for (let i = tickIdx + 1; i <= lastIdx.value; i++){
+ for (let i = tickIdx + 1; i < lastIdx.value; i++){
if (ticks.value[i].major){
if (!date.isEarlier(ticks.value[i].date)){
tickIdx = i;
@@ -436,7 +436,7 @@ const idToEvent = computed(() => { // Maps visible event IDs to HistEvents
while (itr.data() != null){
let event = itr.data()!;
itr.next();
- if (lastDate.value.isEarlier(event.start)){
+ if (!event.start.isEarlier(lastDate.value)){
break;
}
map.set(event.id, event);
diff --git a/src/lib.ts b/src/lib.ts
index da18d94..eef06cd 100644
--- a/src/lib.ts
+++ b/src/lib.ts
@@ -584,7 +584,7 @@ export class DateRangeTree {
const endDate = nextRange != null ? nextRange[1] : range[1];
this.tree.insert([startDate, endDate]);
}
- has(range: DateRange): boolean {
+ contains(range: DateRange): boolean {
const itr = this.tree.lowerBound([range[0], new YearDate()]);
let r = itr.data();
if (r == null){
diff --git a/tests/lib.test.ts b/tests/lib.test.ts
index 85e17bc..2ab5503 100644
--- a/tests/lib.test.ts
+++ b/tests/lib.test.ts
@@ -163,14 +163,14 @@ test('DateRangeTree', () => {
ranges.add([new CalDate(100, 1, 1), new CalDate(200, 1, 1)])
ranges.add([new CalDate(300, 1, 1), new CalDate(400, 1, 1)])
expect(ranges.tree.size).toBe(2)
- expect(ranges.has([new CalDate(300, 1, 1), new CalDate(400, 1, 1)])).toBe(true)
+ expect(ranges.contains([new CalDate(300, 1, 1), new CalDate(400, 1, 1)])).toBe(true)
ranges.add([new CalDate(-100, 1, 1), new CalDate(150, 1, 1)])
ranges.add([new CalDate(400, 1, 1), new CalDate(500, 1, 1)])
expect(ranges.tree.size).toBe(2)
- expect(ranges.has([new CalDate(-100, 1, 1), new CalDate(200, 1, 1)])).toBe(true)
- expect(ranges.has([new CalDate(300, 1, 1), new CalDate(500, 1, 1)])).toBe(true)
+ expect(ranges.contains([new CalDate(-100, 1, 1), new CalDate(200, 1, 1)])).toBe(true)
+ expect(ranges.contains([new CalDate(300, 1, 1), new CalDate(500, 1, 1)])).toBe(true)
ranges.add([new CalDate(-1000, 1, 1), new CalDate(310, 10, 2)])
expect(ranges.tree.size).toBe(1)
- expect(ranges.has([new CalDate(-1000, 1, 1), new CalDate(500, 1, 1)])).toBe(true)
- expect(ranges.has([new CalDate(-1, 1, 1), new CalDate(1, 1, 1)])).toBe(true)
+ expect(ranges.contains([new CalDate(-1000, 1, 1), new CalDate(500, 1, 1)])).toBe(true)
+ expect(ranges.contains([new CalDate(-1, 1, 1), new CalDate(1, 1, 1)])).toBe(true)
})