dont quite Chart.js properly yet
[letz.git] / src / lib / treeing / Betimes.ts
blob29c677c2ba549bab94bb38f1dc4f894ef59fa371
2 import { ac, ahsk,ahk,theone,hak,haks,havs, dec,dig, sha256,sex,ex,nex,now,grep,grop,armap,map,sum,ksaf,hashkv,flatten,fatal,heq,reverse } from "$lib/Y/Pic.ts"
3 import { pit,C_,i_,o_,pito,o_path,o_up,inlace } from "$lib/St"
4 import {diff,enj,enL,deL,indents} from "$lib/Y/Text"
6 import { mkReco,electReco,
7     Recolink,Recolink_stillness,host_Recolink_stillness,
8     makeso,slupath} from "$lib/treeing/data";
9 import { generate_diff} from "$lib/treeing/diff";
10 import { upload_to_ipfs} from "$lib/treeing/ipfs";
11 export { Recolink,Recolink_stillness,host_Recolink_stillness,makeso};
13 # Recollect Reco <- guest ...
14     # Rec.svelte may be given Record/in/$guest-Rec
15     # g is Record, and it is Construct()ing around this:
16     export async function Recollect(g,s) {
17         $This = sc&This
18         $C = This?.C || s
19         # always encode the latest thing (working dir state -> staging)
20         $Reco = await mkReco(C)
21         # pool it in sy&collect/-Reco, picking one to be now
22         Reco = electReco(s,Reco,g)
23         s.y.Reco = Reco
25         # tell Record that it has an s ready
26         g.o_done(s)
27         # went via component for no reason
28         # g.output_to(Reco)
29     }
32 # Aroundiness
33     # note: things compile: '$N =' -> 'var N =', '...and...' -> 'if(...) { ... }'
34     # a picture looking back through kommit:s/**
35     # < when to make sure everything is stored
36     export function Aroundiness(g,s) {
37         # tumble down s/* and sy&be=s@origin
38         #  looking back through the i ... that advanced it
39         $links_by_depth = {}
40         $deps_by_dige = {}
41         $N = inroundce(s,{
42             a_link: &sd{
43                 # collect all storables
44                 ahk(links_by_depth,[d.d],s)
46                 # track dependencies
47                 d.was_link = d
48                 $dependant = d.up?.was_link?.s
49                 if (dependant) {
50                     # by the time we fine this, s should be stored anyway
51                     #  the schema has that ipfs_in joint
52                     $dige = dependant.sc['░']
53                     ahk(deps_by_dige,[dige],s)
54                 }
55             },
56             climbs: &sdN{
57                 # do only the latest /been/Arounding
58                 d.d == 0 and N.splice(0,hak(N)-1)
59             }
60         })
61         # deepest layers first
62         $layers = reverse(havs(links_by_depth))
63         # go async
64         Around_layers(g,s,layers,deps_by_dige)
66         # < drive an event now
68         $by_path = map(N => hashkv(N.map(s => [slupath(s), s])), layers)
69         return {deps_by_dige,layers}
70     }
71     # asyncily PUT each layers of requests
72     async function Around_layers(g,s,layers,deps_by_dige) {
73         each iN layers {
74             $waits = map(s => upload_to_ipfs(s,deps_by_dige), N)
75             await Promise.all(waits)
76             # < handling errors?
77         }
78         g.o_done(s)
79     }
81     # tumble down s/* or sy&be=s@origin
82     #  the latter are given to d.a_link()
83     function inroundce(s,d) {
84         fatal.isC(s)
85         !d.a_link and debugger
86         # tumble down s/* and sy&be=s@origin
87         return inlace(s,{
88             ...d,
89             # include the first node, s|kommit
90             inc:1,
91             climb: &sd{
92                 # they sy&be=s@origin and s%░
93                 $linkish = sum(sy&be && 1, s.sc['░'] && 1)
94                 $z = o_(s)
95                 if (linkish) {
96                     hak(z) and debugger
98                     d.a_link and d.a_link(s,d)
100                     # go to its origin
101                     return [sy&be]
102                 }
103                 # have a This at the end our link trail
104                 if (sc&This) {
105                     hak(z) and debugger
106                     return []
107                 }
108                 # nothing but links and lists of links
109                 !hak(z) and debugger
110                 return z
111             }
112         })
113     }
114     
115 # Betime, the UI functions
116         # switch planes
117         let beof = (s) => fatal.isC(s.y.be)
118   # Betime per -Kom
119     # Record B/items|times** iterates here (at do_Pi_early) 
120     export function Betime({C,s,d,times}) {
121         # < inheritable C%somethings, targeting
122         # the Con-Kom(s)/s-Kom
123         let Con = C.y.up
124         fatal.isC(times)
126         Inspherical({Con,s})
128         let uC = C.y.up?.c.Kom
129         let us = s.y.up
130         if (times == us) {
131             # B/times/*
132             o_times_star(s)
133         }
134         # us && console.log("Seeing "+us.t+"/"+s.t, {C,s})
135     }
137     # B/times/*
138     function o_times_star(s) {
139         let prev = null
140         if (!timeses_realthing(s)) {
141             # someone has deleted s, and it's just hanging around...
142             # leave diff as it was, commit log is lies until its gone
143         }
144         else {
145             # find previous real commit
146             prev = timeses_prev_realthing(s)
147         }
148         if (prev) {
149             # to the previous (parent commit)
150             # < make specific to -Kom somehow...
151             o_times_Kom__pairwise(prev,s)
152         }
153     }
154     # to the previous (parent commit)
155     function o_times_Kom__pairwise(prev,s) {
156         # time difference
157         # times/*%delta = pairwise *//@be%time 
158         let [a,b] = grep(map(s => beof(s).sc.time, [prev,s]))
159         a && b and s.sc.delta = dec(b - a,0)
161         # text difference
162         # times/*%diff = pairwise *(//@be)+:treeh/**(//@be)+:bloub
163         s.sc.diff ||= generate_diff(prev,s)
164     }
167     # B/times/* only diff things that are real
168     function timeses_prev_realthing(s,direction) {
169         $times = sy&up
170         # things
171         !timess&z and return
172         # in order of proximity
173         $c = {near:1}
174         # either direction from s
175         direction ||= 'bow'
176         c[direction] = s
177         return ksaf(timess&z,c)
178             # that could be diffed to
179             .filter(s => timeses_realthing(s)) [0]
180     }
181     # B/times/* only diff things that are real
182     function timeses_realthing(s) {
183         return !(ss&going || ss&goable)
184     }
186   # Betimes altogether
187     # Record B finishes up here (at do_later)
188     $disable_other_cull_process = 1
189     export function Betimes({items,times,kommit}) {
190         $N = o_(times)
191         hak(N) < 8 and return
192         # these times/* are from kommit/*
193         $one = N[0]
194         $ori = oney&be
195         $kommit = oriy&up
196         $desired_number = 6
197         # how to change times/*
198         $add = []
199         $remove = []
200         
201         # not things already going
202         $maybe = grep(s => !(ss&going || ss&goable), N)
203         # separate just the data we want to look at
204         #  and our o.delta is now looking the other way
205         #   just to avoid having to look at the stayer's delta when considering a merge...
206         # < another layer of C for this
207         $look = make_look_from_times(maybe)
208         $delook = N => map(o => o.s, N)
210         # find unconscious commits
211         $would_cull = times_cullable(look)
212         $couldda_culled = would_cull
214         # see if those rules alproduce enough squishing
215         $desired_reduction = hak(look) - desired_number
216         if (hak(would_cull) < desired_reduction) {
217             # subbranch
218             #   < we finally replace them with a Recolink to the kommit including them
219             $would_subbranch = agoodchunkof(look)
220             remove.push(...delook(would_subbranch))
221             # < find a /kommit including them
222             $branch = C_('TODO kommit')
223             add.push(branch)
224         }
225         else {
226             # only so many
227             would_cull = would_cull.slice(0, desired_reduction)
228             remove.push(...delook(would_cull))
229         }
233         # < wake certain of them
234         #   atm in bop() / Betimes(),Construct() 
235         #    ie we wake|compute everything in B**
236         #     all Kom.svelte getting a new $C with mostly the same in it
237         #    > reConstruct() a subset of B** depending on what's happening
238         #      would need to subset resolve $n, or insert into branched times/-Kom**
239         map(&s{
240             # the pairs of things
241             $ne = timeses_prev_realthing(s,'aft')
242             !ne and debugger
243             
244             # sanity check which two are involved...
245             #  we can't possibly be merging across conscious (%msg|level) things
246                 # < define all these subselects, make one "main"
247             $o = theone(grep(o => o.s == s,couldda_culled))
248             !o and debugger
249             if (ne != o.mergible_with.s) {
250                 # avoid merging anywhere near conscious (%msg|level) things
251                 # which the ne doesn't know about 
252                 debugger
253                 ne = o.mergible_with.s
254             }
256             if (ne) {
257                 # drop diff cache
258                 delete nes&diff
260                 # < GOING we dont have to wake anyone?
261                 # ney&wake && ney&wake()
262                 
263                 # the earlier thing (s) goes away
264                 #  but gives its earlier %time to ne
265                 # < %time is a range, delta is computed for a pair
266                 $earlier = sy&be.sc.time
267                 $later = ney&be.sc.time
268                 earlier > later and debugger
269                 ney&be.sc.time = earlier
270             }
271         },remove)
272         # < GOING we dont have to wake everyone?
273         # o_(times).map(s => sy&wake && sy&wake())
277         # apply the change
278         map(&s{
279             debugger
280             # top-post this grouper thing
281             kommits&z.unshift(s)
282         },add)
283         # properly delete one round later
284         grop(s => ss&goable && ss&going, timess&z)
285         map(&s{
286             $be = sy&be
287             # allow delete from times/*, becomes translucent
288             ss&goable = now()
289             # delete from kommit/*
290             $ko = bey&up
291             grop(be,kos&z)
292         },remove)
295         $c = {desired_reduction,couldda_culled,add,remove}
296         c.times = times
297         c.kommit = kommit
298         # timesc&look = c
299         # console.log("Betimes", c)
300     }
301     function make_look_from_times (N) {
302         $look = map(s => sex({t:s.t,s},s.sc,'msg,level'),N)
303         $prev_o = null
304         map((o) => {
305             if (prev_o) {
306                 $s = o.s
307                 let [a,b] = grep(map(s => beof(s).sc.time, [prev_o.s,s]))
308                 !(a && b) and debugger
309                 # this o.delta is to the next thing now
310                 #  whereas s%delta is to the previous (see o_times_Kom__pairwise())
311                 prev_o.delta = dec(b - a,0)
312             }
313             prev_o = o
314         }, look)
315         return look
316     }
319     # find sequences (>1) of unconscious commits
320     #  we never squish into conscious commits
321     #  only the vague units of time between events with potentially minimal meaning
322     function times_cullable(look) {
323         # go in reverse to throw away the earlier of the two
324         #  the going patch merges into the next one with|based-on it
325         $la = null
326         $la_o = null
327         look = reverse(look)
328         $cullable = grep(&o{
329             $conscious = o.msg || o.level
330             $yup = !conscious && !la
331             # this is actually next (reverse)
332             yup and o.mergible_with = la_o
333             la = conscious
334             la_o = o
335             return yup
336         }, look)
337         # max delta before a commit should be subbranched rather than squished
338         #  otherwise with no %msg or %level we would never leave a trail
339         $max_delta = 30
340         cullable = grep(&o{
341             return o.delta < max_delta
342         },cullable)
343         $most_cullable = cullable.sort((a, b) => a.delta - b.delta)
344         $would_cull = agoodchunkof(most_cullable)
345         return would_cull
346     }
347     # a bit more than most of them, eg 20->12, 12->7
348     function agoodchunkof(N) {
349         return N.slice(0,Math.floor(hak(N) / 1.618))
350     }
352     
353     # < treeh//@collect/* garbage collect where times says
355 # Inspherical
356     # a mode, complements I.Pi
357     #  suppose they (s**) don't all have c&pi, so dont Pi, but would this...
358     function Inspherical({Con,s}) {
359         # give ^-Conz/-Con better names
360         #  from s.t, the insphere - rather than its position in the -Conz%z array indice, which is senile
361         #   see 'atm we use the array indices to individuate [C,C,C]'
362         Con.t = s.t
363         fatal.isC(s)
365         # do some Con%$style hacks to not double-label it, etc
366         $Cont = Conc&Cont
367         if (Con.t == Conts&Ct) {
368             # avoid stating this twice (as Con.t and Cont%Ct)
369             Con.sc.avoid_restating_Ct = 1
370         }
371         # make coming and going smooth
372         Con.sc.animal = 1
373     }
375 #  cull*
376     # deletes history
377     # < shrinking ooze
378     #   
379     export function cull_around(s) {
380         hak(ss&z) < 10 and return
381         # we have many moments of "out"
382         $cull = ss&z
383         # keep any commits we made
384         # < commit when we type into any of the Record** things
385         # < folding it all up into a book after a while, %we and all
386         cull = cull.filter(n => !ns&we)
387         # < keep definitive moments in time
388         #    ie before and after a bunch of stuff changed
389         #     aggregating many rapid moments of stuff changing
390         # < content-awareness is now all over there in Reco pools
391         cull = cull.slice(1,-4)
392         grop((s,i) => i%2,cull)
393         
394         !hak(cull) and debugger
395         !disable_other_cull_process and grop(cull,ss&z)
396     }