internal/relation_failures/routing.bend
bendvy-ecs-core@0.1.0.0 · 55 lines · 0 definitions
1import Base
2import queue.bend as Q
3import domains.bend as D
4import bendvy-ecs-core@0.1.0.0/world.bend as W
5
6type PendingBatch<S: Data,E: Data> is Data:
7 PendingBatch{key: D.DescriptorKey<S>,reversed: List<&2,E>}
8type Partition<S: Data,E: Data> is Data:
9 Partition{ordinary: List<&2,E>,batches: List<&2,PendingBatch<S,E>>}
10
11def group_found(~S: Data,~E: Data,same: Bool,+key: D.DescriptorKey<S>,items: List<&2,E>,+rest: List<&2,PendingBatch<S,E>>,+item: E,ih: Unit -> List<&2,PendingBatch<S,E>>) -> List<&2,PendingBatch<S,E>>:
12 match same:
13 case True{}: PendingBatch{key,item <> items} <> rest
14 case False{}: PendingBatch{key,items} <> ih(Unit{})
15
16def group(~S: Data,~E: Data,batches: List<&2,PendingBatch<S,E>>,+wanted: D.DescriptorKey<S>,+item: E) -> List<&2,PendingBatch<S,E>>:
17 match batches:
18 case []: [PendingBatch{wanted,[item]}]
19 case PendingBatch{+key,+items} <> +rest: group_found(~S,~E,D.key_equal(~S,key,wanted),key,items,rest,item,_ => group(~S,~E,rest,wanted,item))
20
21def partition_selected(~S: Data,~E: Data,key: Maybe<D.DescriptorKey<S>>,item: E,ordinary: List<&2,E>,batches: List<&2,PendingBatch<S,E>>) -> Partition<S,E>:
22 match key:
23 case None{}: Partition{item <> ordinary,batches}
24 case Some{wanted}: Partition{ordinary,group(~S,~E,batches,wanted,item)}
25
26def partition_loop(~S: Data,~E: Data,~classify: E -> Maybe<D.DescriptorKey<S>>,items: List<&2,E>,acc: Partition<S,E>) -> Partition<S,E>:
27 match items acc:
28 case Nil{} acc: acc
29 case +item <> rest Partition{ordinary,batches}: partition_loop(~S,~E,~classify,rest,partition_selected(~S,~E,classify(item),item,ordinary,batches))
30
31def publish_found(~S: Data,~E: Data,same: Bool,+key: D.DescriptorKey<S>,queue: Q.Queue<E>,ids: List<&2,U32>,+rest: List<&2,D.Domain<S,E>>,tick: Nat,items: List<&2,E>,ih: Unit -> List<&2,D.Domain<S,E>>) -> List<&2,D.Domain<S,E>>:
32 match same:
33 case True{}: D.Domain{key,Q.publish(~E,queue,tick,items),ids} <> rest
34 case False{}: D.Domain{key,queue,ids} <> ih(Unit{})
35
36def publish_one(~S: Data,~E: Data,domains: List<&2,D.Domain<S,E>>,+wanted: D.DescriptorKey<S>,+tick: Nat,+items: List<&2,E>) -> List<&2,D.Domain<S,E>>:
37 match domains:
38 case []: [D.Domain{wanted,Q.publish(~E,Q.empty(~E),tick,items),[]}]
39 case D.Domain{+key,+queue,+ids} <> +rest: publish_found(~S,~E,D.key_equal(~S,key,wanted),key,queue,ids,rest,tick,items,_ => publish_one(~S,~E,rest,wanted,tick,items))
40
41def publish_batches(~S: Data,~E: Data,batches: List<&2,PendingBatch<S,E>>,+tick: Nat,domains: List<&2,D.Domain<S,E>>) -> List<&2,D.Domain<S,E>>:
42 match batches:
43 case []: domains
44 case PendingBatch{key,reversed} <> rest: publish_batches(~S,~E,rest,tick,publish_one(~S,~E,domains,key,tick,List.reverse(&2,E,reversed)))
45
46def collected(~S: Data,~C: Type,~R: Type,~E: Data,world: W.World<S,C,R,E>,partition: Partition<S,E>,tick: Nat,domains: List<&2,D.Domain<S,E>>) -> W.World<S,C,R,E> & List<&2,D.Domain<S,E>>:
47 match partition:
48 case Partition{ordinary,batches}: (W.events_replace(~S,~C,~R,~E,world,List.reverse(&2,E,ordinary)),publish_batches(~S,~E,batches,tick,domains))
49
50def collect_view(~S: Data,~C: Type,~R: Type,~E: Data,~classify: E -> Maybe<D.DescriptorKey<S>>,view: W.World<S,C,R,E> & List<&2,E>,tick: Nat,domains: List<&2,D.Domain<S,E>>) -> W.World<S,C,R,E> & List<&2,D.Domain<S,E>>:
51 (world,items) = view
52 collected(~S,~C,~R,~E,world,partition_loop(~S,~E,~classify,items,Partition{[],[]}),tick,domains)
53
54def collect(~S: Data,~C: Type,~R: Type,~E: Data,~classify: E -> Maybe<D.DescriptorKey<S>>,world: W.World<S,C,R,E>,tick: Nat,domains: List<&2,D.Domain<S,E>>) -> W.World<S,C,R,E> & List<&2,D.Domain<S,E>>:
55 collect_view(~S,~C,~R,~E,~classify,W.events_view(~S,~C,~R,~E,world),tick,domains)