Types to more systematically interface data in scenes

This commit is contained in:
Ruben van de Ven 2024-05-26 21:05:42 +02:00
parent 1789731ab9
commit c8187f3f5e
3 changed files with 56 additions and 24 deletions

View file

@ -10,6 +10,9 @@
type Item, type Item,
type Motion, type Motion,
get_path_d, get_path_d,
type Data,
type VizData,
type Log,
} from "./lib/types"; } from "./lib/types";
// these are passed from main.ts (or vice versaas) // these are passed from main.ts (or vice versaas)
@ -55,25 +58,24 @@
// filter nodes with only having both Latitude and Longitude. // filter nodes with only having both Latitude and Longitude.
// then map these coordinates to the canvas space // then map these coordinates to the canvas space
const locations = _nodes const locations = new Map(_nodes
.filter((n) => n.lat && n.lon) .filter((n) => n.lat && n.lon)
.map((node) => { .map((node) => {
node["x"] = node_positions[node.code][0]; node["x"] = node_positions[node.code][0];
node["y"] = node_positions[node.code][1]; node["y"] = node_positions[node.code][1];
return node; return node;
}); })
.map((d) => [d["name"], d])
// create an index to access the node objects by their name
const nodeMap: Map<String, Location> = new Map(
locations.map((d) => [d["name"], d]),
); );
_requests _requests
// remove entries that stay at the same place
.filter((n) => n['Owning Library Name'] != n['Pickup Location']) .filter((n) => n['Owning Library Name'] != n['Pickup Location'])
.filter( .filter(
(l) => (l) =>
nodeMap.has(l["Owning Library Name"]) && locations.has(l["Owning Library Name"]) &&
nodeMap.has(l["Pickup Location"]), locations.has(l["Pickup Location"]),
) )
.forEach((r, idx) => { .forEach((r, idx) => {
const identifier: String = r["Barcode"]; const identifier: String = r["Barcode"];
@ -87,8 +89,8 @@
}); });
} }
let movement: Movement = { let movement: Movement = {
source: nodeMap.get(r["Owning Library Name"]), source: locations.get(r["Owning Library Name"]),
target: nodeMap.get(r["Pickup Location"]), target: locations.get(r["Pickup Location"]),
nr: idx, nr: idx,
item: items.get(identifier), item: items.get(identifier),
_original: r, _original: r,
@ -154,10 +156,23 @@
occurences.set(movement.item, movements); occurences.set(movement.item, movements);
}); });
const data: Data = {
locations: locations,
items: items,
movements: movements,
occurences: occurences
}
let drawn_motions = writable(<Motion[]>[]); //.filter((m, i) => i < 100); let drawn_motions = writable(<Motion[]>[]); //.filter((m, i) => i < 100);
$: opacity = Math.max(0.055, Math.min(1, 200 / $drawn_motions.length)); $: opacity = Math.max(0.055, Math.min(1, 200 / $drawn_motions.length));
let overlay_motions = writable(<Motion[]>[]); //.filter((m, i) => i < 100); let overlay_motions = writable(<Motion[]>[]); //.filter((m, i) => i < 100);
let events = writable(<Event[]>[]); //.filter((m, i) => i < 100); let events = writable(<Log[]>[]); //.filter((m, i) => i < 100);
const viz_data: VizData = {
drawn_motions: drawn_motions,
overlay_motions: overlay_motions,
events: events,
}
import { onMount, onDestroy } from "svelte"; import { onMount, onDestroy } from "svelte";
import { writable } from "svelte/store"; import { writable } from "svelte/store";
@ -173,10 +188,9 @@
console.log("Next scene", currentSceneI); console.log("Next scene", currentSceneI);
currentScene = new scenes[currentSceneI]( currentScene = new scenes[currentSceneI](
movements, data,
drawn_motions, viz_data,
nextScene, nextScene,
occurences,
); );
currentSceneI = (currentSceneI + 1) % scenes.length; currentSceneI = (currentSceneI + 1) % scenes.length;
} }
@ -234,7 +248,7 @@
{/each} {/each}
</g> </g>
<g id="libraries"> <g id="libraries">
{#each locations as node} {#each locations.values() as node}
<g id={node.code} transform="translate({node.x}, {node.y})"> <g id={node.code} transform="translate({node.x}, {node.y})">
<circle r="5"></circle> <circle r="5"></circle>
<circle r="20"></circle> <circle r="20"></circle>

View file

@ -1,3 +1,5 @@
import type { Writable } from "svelte/store";
export type Location = Object; export type Location = Object;
// disambiguated (physical or online) library object // disambiguated (physical or online) library object
@ -20,6 +22,14 @@ export type Movement = {
d: String d: String
}; };
export type Occurences = Map<Item, Movement[]>
export interface Data {
locations: Map<String, Location>,
items: Map<string, Item>,
movements: Movement[],
occurences: Occurences
}
// An event to trigger drawing an Edge // An event to trigger drawing an Edge
@ -28,12 +38,20 @@ export type Motion = {
movement: Movement, movement: Movement,
} }
export type Event = { export type Log = {
date: Date, date: Date,
title: String, title: String,
description: String description: String
} }
// Type used by the scenes with all reactive Writables for drawable objects
export type VizData = {
drawn_motions: Writable<Motion[]>,
overlay_motions: Writable<Motion[]>,
events: Writable<Log[]>
}
export function get_path_d(movement: Movement) { export function get_path_d(movement: Movement) {
const m = movement; const m = movement;
// console.log(m) // console.log(m)

View file

@ -1,5 +1,5 @@
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import type { Item, Motion, Movement } from "../lib/types"; import type { Data, Item, Motion, Movement, VizData } from "../lib/types";
export class Scene { export class Scene {
rendered_elements: String[] = [] rendered_elements: String[] = []
@ -16,16 +16,16 @@ export class All extends Scene {
nextScene: CallableFunction nextScene: CallableFunction
locationCounts = new Map<Location, { in: number, out: number }>() locationCounts = new Map<Location, { in: number, out: number }>()
constructor(movements: Movement[], motions: Writable<Motion[]>, nextScene: CallableFunction, occurences: Map<Item, Movements[]>) { constructor(data: Data, viz_data: VizData, nextScene: CallableFunction) {
super() super()
this.nextScene = nextScene this.nextScene = nextScene
// start setInterval to trigger additions per 100 or so to drawn_movements (rendered on map) // start setInterval to trigger additions per 100 or so to drawn_movements (rendered on map)
// when done, trigger parent.done() // when done, trigger parent.done()
this.allMovements = movements; this.allMovements = data.movements;
this.motions = motions this.motions = viz_data.drawn_motions
// TODO: group by hour and have it last nr-of-hours * interval // TODO: group by hour and have it last nr-of-hours * interval
// TODO: then, add a timeline // TODO: then, add a timeline
// TODO: then, add an overlay with relevant events, e.g. // TODO: then, add an overlay with relevant events, e.g.
@ -74,20 +74,20 @@ export class Timeline extends Scene {
nextScene: CallableFunction nextScene: CallableFunction
locationCounts = new Map<Location, { in: number, out: number }>() locationCounts = new Map<Location, { in: number, out: number }>()
constructor(allMovements: Movement[], motions: Writable<Motion[]>, nextScene: CallableFunction, occurences: Map<Item, Movements[]>) { constructor(data: Data, viz_data: VizData, nextScene: CallableFunction) {
super() super()
this.nextScene = nextScene this.nextScene = nextScene
// start setInterval to trigger additions per 100 or so to drawn_movements (rendered on map) // start setInterval to trigger additions per 100 or so to drawn_movements (rendered on map)
// when done, trigger parent.done() // when done, trigger parent.done()
console.log('s',occurences) console.log('s',data.occurences)
const [ item, movements ]= this.pickMovements(occurences); const [ item, movements ]= this.pickMovements(data.occurences);
this.item = item this.item = item
this.movements = movements this.movements = movements
console.log(item, movements) console.log(item, movements)
this.motions = motions this.motions = viz_data.drawn_motions
this.motions.update(items => []) this.motions.update(items => [])
this.interval = setInterval(this.tick.bind(this), 3000); this.interval = setInterval(this.tick.bind(this), 3000);