on main help sign in
fix a bunch of madness in star chart and add peer and pal filtering
e735a6cJohn Hyde
desk/app/astrolabe.hoon+1−1
@@ -26,7 +26,7 @@
26 ^- (quip card _this)
26 ^- (quip card _this)
27 =/ old !<(versioned-state old-state)
27 =/ old !<(versioned-state old-state)
28 =/ [cards-01=(list card) new=state-latest]
28 =/ [cards-01=(list card) new=state-latest]
29− ?. ?=(?(%0 %1 %2 %3) -.old) `old
29+ ?. |(?=(?(%0 %1 %2 %3) -.old) (lth bump.old bump)) `old
30 (on-naive-state:hc get-nas:hc)
30 (on-naive-state:hc get-nas:hc)
31 ?> ?=(%4 -.new)
31 ?> ?=(%4 -.new)
32 =/ cards=(list card)
32 =/ cards=(list card)
desk/lib/state.hoon+5−7
@@ -8,15 +8,13 @@
8 ?: =(parent child) s
8 ?: =(parent child) s
9 ?: (is-npoint-locked npoint) s
9 ?: (is-npoint-locked npoint) s
10 =/ pdata (pdata:smel (pmeta:smel child npoint) ~)
10 =/ pdata (pdata:smel (pmeta:smel child npoint) ~)
11+ =. spam.s (~(put bi spam.s) parent child pdata)
11 =* spo sponsor.net.npoint
12 =* spo sponsor.net.npoint
12 =/ prev (~(gut by prev-spo.s) child parent)
13 =/ prev (~(gut by prev-spo.s) child parent)
13− =/ unsponsored-state
14− =. prev-spo.s (~(del by prev-spo.s) child)
14+ =. prev-spo.s (~(del by prev-spo.s) child)
15+ =? spam.s !=(parent prev)
15− =. spam.s (~(del bi spam.s) prev child)
16+ (~(del bi spam.s) prev child)
16− s
17− ?. has.spo unsponsored-state
17+ ?. has.spo s
18− =? s !=(prev who.spo)
19− unsponsored-state
20 =. prev-spo.s (~(put by prev-spo.s) child who.spo)
18 =. prev-spo.s (~(put by prev-spo.s) child who.spo)
21 =. spam.s (~(put bi spam.s) who.spo child pdata)
19 =. spam.s (~(put bi spam.s) who.spo child pdata)
22 s
20 s
desk/sur/astrolabe.hoon+1−1
@@ -29,7 +29,7 @@
29 ==
29 ==
30+$ state-4
30+$ state-4
31 $: %4
31 $: %4
32− bump=@ud :: bump to update state without changing the type
32+ bump=_1 :: bump to update state without changing the type
33 prev-spo=(map ship ship) :: so we know who the old sponsor was when sponsor changes
33 prev-spo=(map ship ship) :: so we know who the old sponsor was when sponsor changes
34 spam=spawn-mip
34 spam=spawn-mip
35 fropoints-1
35 fropoints-1
desk/tests/lib/state.hoon+10−10
@@ -1,5 +1,5 @@
1/- *astrolabe
1/- *astrolabe
2−/+ *astrolabe, *state, *test
2+/+ *astrolabe, *state, *mip, *test
3|%
3|%
4++ test-put-in-spawn-mip
4++ test-put-in-spawn-mip
5 =| state=state-latest
5 =| state=state-latest
@@ -13,18 +13,18 @@
13 %+ expect-eq
13 %+ expect-eq
14 !> :-
14 !> :-
15 `~zod :: new prev-spo
15 `~zod :: new prev-spo
16− %.y :: spawn-mip has something under ~zod
16+ "marzod:s;" :: spawn-mip has something under ~zod
17 !> =- :-
17 !> =- :-
18 (~(get by prev-spo) ~marzod)
18 (~(get by prev-spo) ~marzod)
19− (~(has by spam) ~zod)
19+ (~(gut bi spam) ~zod ~marzod "nothing!")
20 (put-in-spawn-mip ~marzod *npoint state)
20 (put-in-spawn-mip ~marzod *npoint state)
21 ::
21 ::
22 %+ expect-eq
22 %+ expect-eq
23 !> :*
23 !> :*
24 `~hec :: new prev-spo
24 `~hec :: new prev-spo
25− %.n :: nothing under ~zod
25+ "marzod:s:hec!zod;" :: under ~zod
26 %.n :: nothing under ~bus
26 %.n :: nothing under ~bus
27− %.y :: something under ~hec
27+ "marzod:s:hec!zod;" :: under ~hec
28 ==
28 ==
29 !>
29 !>
30 =. state (put-in-spawn-mip ~marzod *npoint state)
30 =. state (put-in-spawn-mip ~marzod *npoint state)
@@ -32,17 +32,17 @@
32 =+ (put-in-spawn-mip ~marzod moved-to-hec state)
32 =+ (put-in-spawn-mip ~marzod moved-to-hec state)
33 :*
33 :*
34 (~(get by prev-spo) ~marzod)
34 (~(get by prev-spo) ~marzod)
35− (~(has by spam) ~zod)
35+ (~(gut bi spam) ~zod ~marzod "nothing!")
36 (~(has by spam) ~bus)
36 (~(has by spam) ~bus)
37− (~(has by spam) ~hec)
37+ (~(gut bi spam) ~hec ~marzod "nothing!")
38 ==
38 ==
39 ::
39 ::
40 %+ expect-eq
40 %+ expect-eq
41 !> :*
41 !> :*
42 `~zod :: new prev-spo
42 `~zod :: new prev-spo
43− %.y :: something under ~zod
43+ "marzod:s;" :: under ~zod
44 %.n :: nothing under ~bus
44 %.n :: nothing under ~bus
45− %.n :: something under ~hec
45+ %.n :: nothing under ~hec
46 ==
46 ==
47 !>
47 !>
48 =. state (put-in-spawn-mip ~marzod *npoint state)
48 =. state (put-in-spawn-mip ~marzod *npoint state)
@@ -51,7 +51,7 @@
51 =+ (put-in-spawn-mip ~marzod *npoint state)
51 =+ (put-in-spawn-mip ~marzod *npoint state)
52 :*
52 :*
53 (~(get by prev-spo) ~marzod)
53 (~(get by prev-spo) ~marzod)
54− (~(has by spam) ~zod)
54+ (~(gut bi spam) ~zod ~marzod "nothing!")
55 (~(has by spam) ~bus)
55 (~(has by spam) ~bus)
56 (~(has by spam) ~hec)
56 (~(has by spam) ~hec)
57 ==
57 ==
ui/package-lock.json+9−9
@@ -16,7 +16,7 @@
16 "bn.js": "^5.2.0",
16 "bn.js": "^5.2.0",
17 "graphology": "^0.24.1",
17 "graphology": "^0.24.1",
18 "lodash": "^4.17.21",
18 "lodash": "^4.17.21",
19− "sigma": "^2.3.1",
19+ "sigma-jh": "^2.4.2",
20 "svelte-copy-to-clipboard": "^0.2.5",
20 "svelte-copy-to-clipboard": "^0.2.5",
21 "svelte-markdown": "^0.2.3",
21 "svelte-markdown": "^0.2.3",
22 "tippy.js": "^6.3.7",
22 "tippy.js": "^6.3.7",
@@ -2467,10 +2467,10 @@
2467 "node": ">=8"
2467 "node": ">=8"
2468 }
2468 }
2469 },
2469 },
2470− "node_modules/sigma": {
2470+ "node_modules/sigma-jh": {
2471− "version": "2.3.1",
2471+ "version": "2.4.2",
2472− "resolved": "https://registry.npmjs.org/sigma/-/sigma-2.3.1.tgz",
2472+ "resolved": "https://registry.npmjs.org/sigma-jh/-/sigma-jh-2.4.2.tgz",
2473− "integrity": "sha512-YfQsVZf78CeIUv8EYLqp/yvhMwwBXGrbpy+rD1N2X9IqtJ11+VfQRjWfVqHDhjM8oPfWPsaJMtpWFQ8pIflvCA==",
2473+ "integrity": "sha512-viB4M5Y79N5rAgs0z3M4Gff4HX53S+UMwblPDEH/Nkwwe7AcmcWwsEYsGv/xL/TNQzLIBBb0NaNAg5ZhnbEm8g==",
2474 "dependencies": {
2474 "dependencies": {
2475 "@yomguithereal/helpers": "^1.1.1",
2475 "@yomguithereal/helpers": "^1.1.1",
2476 "events": "^3.3.0",
2476 "events": "^3.3.0",
@@ -4782,10 +4782,10 @@
4782 "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
4782 "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
4783 "dev": true
4783 "dev": true
4784 },
4784 },
4785− "sigma": {
4785+ "sigma-jh": {
4786− "version": "2.3.1",
4786+ "version": "2.4.2",
4787− "resolved": "https://registry.npmjs.org/sigma/-/sigma-2.3.1.tgz",
4787+ "resolved": "https://registry.npmjs.org/sigma-jh/-/sigma-jh-2.4.2.tgz",
4788− "integrity": "sha512-YfQsVZf78CeIUv8EYLqp/yvhMwwBXGrbpy+rD1N2X9IqtJ11+VfQRjWfVqHDhjM8oPfWPsaJMtpWFQ8pIflvCA==",
4788+ "integrity": "sha512-viB4M5Y79N5rAgs0z3M4Gff4HX53S+UMwblPDEH/Nkwwe7AcmcWwsEYsGv/xL/TNQzLIBBb0NaNAg5ZhnbEm8g==",
4789 "requires": {
4789 "requires": {
4790 "@yomguithereal/helpers": "^1.1.1",
4790 "@yomguithereal/helpers": "^1.1.1",
4791 "events": "^3.3.0",
4791 "events": "^3.3.0",
ui/package.json+1−1
@@ -51,7 +51,7 @@
51 "bn.js": "^5.2.0",
51 "bn.js": "^5.2.0",
52 "graphology": "^0.24.1",
52 "graphology": "^0.24.1",
53 "lodash": "^4.17.21",
53 "lodash": "^4.17.21",
54− "sigma": "^2.3.1",
54+ "sigma-jh": "^2.4.2",
55 "svelte-copy-to-clipboard": "^0.2.5",
55 "svelte-copy-to-clipboard": "^0.2.5",
56 "svelte-markdown": "^0.2.3",
56 "svelte-markdown": "^0.2.3",
57 "tippy.js": "^6.3.7",
57 "tippy.js": "^6.3.7",
ui/src/components/StarChart.svelte+20−9
@@ -3,11 +3,12 @@
3
3
4 import { push } from 'svelte-spa-router'
4 import { push } from 'svelte-spa-router'
5
5
6− import Sigma from 'sigma';
6+ import Sigma from 'sigma-jh';
7 import Graph from 'graphology';
7 import Graph from 'graphology';
8
8
9 import { clan } from 'urbit-ob';
9 import { clan } from 'urbit-ob';
10 import DocLink from './docs/DocLink.svelte';
10 import DocLink from './docs/DocLink.svelte';
11+ import store from 'stores/store';
11 import { cite, normalizeId } from 'lib/id';
12 import { cite, normalizeId } from 'lib/id';
12 import { parseChartData, populateGraph } from 'lib/graph';
13 import { parseChartData, populateGraph } from 'lib/graph';
13 import { getChartData } from 'lib/api';
14 import { getChartData } from 'lib/api';
@@ -33,7 +34,7 @@
33 allowInvalidContainer: true,
34 allowInvalidContainer: true,
34 // labelColor: { color: WHITE },
35 // labelColor: { color: WHITE },
35 labelFont: 'monospace',
36 labelFont: 'monospace',
36− labelRenderedSizeThreshold: 9,
37+ labelRenderedSizeThreshold: 2.2,
37 zIndex: true,
38 zIndex: true,
38 maxCameraRatio: 10,
39 maxCameraRatio: 10,
39 });
40 });
@@ -93,8 +94,8 @@
93 rawChartData = { error };
94 rawChartData = { error };
94 });
95 });
95 }
96 }
96− $: parsedChartData = parseChartData(rawChartData);
97+ $: parsedChartData = parseChartData(rawChartData, filterSet);
97− $: [parsedChartData, bySponsor], populateGraph(g, parsedChartData, bySponsor, () => {
98+ $: [parsedChartData, childKey], populateGraph(g, parsedChartData, childKey, () => {
98 searchFunc();
99 searchFunc();
99 });
100 });
100
101
@@ -145,7 +146,10 @@
145 "w-full" :
146 "w-full" :
146 "border-r";
147 "border-r";
147 }
148 }
148− let bySponsor = true;
149+ let childKey: ('sponsees' | 'children') = 'sponsees';
150+ let filterSet: Set<string> = null;
151+ $: peersSet = new Set($store.peers);
152+ $: palsSet = new Set(Object.keys($store.pals.outgoing));
149</script>
153</script>
150
154
151<div class="border border-gold bg-navy w-full grow flex flex-col relative">
155<div class="border border-gold bg-navy w-full grow flex flex-col relative">
@@ -187,13 +191,20 @@
187 on:click={() => push('/') }>
191 on:click={() => push('/') }>
188 X
192 X
189 </div>
193 </div>
190− <div class="flex flex-col absolute -bottom-2 inset-x-0 text-white z-10 2xs:-bottom-3.5">
194+ <div class="flex absolute -bottom-2 inset-x-0 text-white z-10 2xs:-bottom-3.5">
191 <!-- <div class="ml-8 px-4 py-1 flex gap-x-1 items-center text-white"> -->
195 <!-- <div class="ml-8 px-4 py-1 flex gap-x-1 items-center text-white"> -->
192 <!-- <span>Arrange by</span> -->
196 <!-- <span>Arrange by</span> -->
193− <InlineSelect bind:value={bySponsor}
197+ <InlineSelect bind:value={childKey}
194 options={[
198 options={[
195− ['Sponsors', true],
199+ ['Sponsors', 'sponsees'],
196− ['Parents', false]
200+ ['Parents', 'children']
201+ ]}
202+ ></InlineSelect>
203+ <InlineSelect bind:value={filterSet}
204+ options={[
205+ ['All', null],
206+ ['Peers', peersSet],
207+ ['Pals', palsSet],
197 ]}
208 ]}
198 ></InlineSelect>
209 ></InlineSelect>
199 <!-- </div> -->
210 <!-- </div> -->
ui/src/lib/colors.ts+3
@@ -6,9 +6,12 @@ export const GOLDS2 = '#caa93e';
6export const WHITE = '#FFF';
6export const WHITE = '#FFF';
7export const LGREY = '#BBB';
7export const LGREY = '#BBB';
8export const DGREY = '#777';
8export const DGREY = '#777';
9+export const DDGREY = '#555';
9export const BLUE = '#1792c7';
10export const BLUE = '#1792c7';
10export const GREEN = '#17c76a';
11export const GREEN = '#17c76a';
11export const YOU_ARE_HERE = '#802';
12export const YOU_ARE_HERE = '#802';
12export const YOU = '#b01';
13export const YOU = '#b01';
13export const YOUR_STAR = '#d71';
14export const YOUR_STAR = '#d71';
14export const YOUR_GAL = '#fb1';
15export const YOUR_GAL = '#fb1';
16+export const SUB_PICKED = LGREY;
17+export const NOT_PICKED = DDGREY;
ui/src/lib/graph.ts+152−105
@@ -6,123 +6,161 @@ const example = '[0[3216291:t;9219219;4608:s[156546;1612196;219621:~;321965149:4
6export interface ChartPoint {
6export interface ChartPoint {
7 patp: string,
7 patp: string,
8 dominion: ('l1' | 'l2' | 'spawn'),
8 dominion: ('l1' | 'l2' | 'spawn'),
9+ picked: boolean,
10+ pickedChildren?: boolean,
11+ pickedSponsees?: boolean,
9 sponsor?: string,
12 sponsor?: string,
10 parent?: string,
13 parent?: string,
11 children?: ChartPoint[],
14 children?: ChartPoint[],
12 sponsees?: ChartPoint[],
15 sponsees?: ChartPoint[],
13}
16}
14
17
15−function parseMetaString(metaString: string): ChartPoint {
18+interface ChartSubs {
16− let idString, subMetaString = '';
19+ children: ChartPoint[],
17− const colIndex = metaString.indexOf(':');
20+ sponsees: ChartPoint[],
18− if (colIndex === -1) {
21+}
19− idString = metaString;
22+
20− } else {
23+class ChartDataParser {
21− idString = metaString.slice(0, colIndex);
24+ filter: Set<string>;
22− subMetaString = metaString.slice(colIndex + 1);
25+
23− }
26+ constructor(filter: Set<string>) {
24− const meta: ChartPoint = {
27+ this.filter = filter;
25− patp: '~' + idString,
26− dominion: 'l1',
27 }
28 }
28− if (subMetaString) {
29+
29− const firstChar = subMetaString[0];
30+ parseMetaString(metaString: string): ChartPoint {
30− if (firstChar === 't') {
31+ let idString, subMetaString = '';
31− meta.dominion = 'l2';
32+ const colIndex = metaString.indexOf(':');
33+ if (colIndex === -1) {
34+ idString = metaString;
35+ } else {
36+ idString = metaString.slice(0, colIndex);
32− subMetaString = subMetaString.slice(1);
37+ subMetaString = metaString.slice(colIndex + 1);
33− } else if (firstChar === 's') {
38+ }
34− meta.dominion = 'spawn';
39+ const patp = '~' + idString;
35− subMetaString = subMetaString.slice(1);
40+ const meta: ChartPoint = {
41+ patp,
42+ picked: !this.filter ? true : (this.filter.has(patp)),
43+ dominion: 'l1',
36 }
44 }
37 if (subMetaString) {
45 if (subMetaString) {
46+ const firstChar = subMetaString[0];
47+ if (firstChar === 't') {
48+ meta.dominion = 'l2';
38− if (subMetaString[0] === '~') {
49+ subMetaString = subMetaString.slice(1);
50+ } else if (firstChar === 's') {
51+ meta.dominion = 'spawn';
52+ subMetaString = subMetaString.slice(1);
53+ }
54+ if (subMetaString) {
55+ if (subMetaString[0] === '~') {
39− meta.sponsor = null;
56+ meta.sponsor = null;
40− } else {
57+ } else {
41− let [sponsor, parent] = subMetaString.slice(1).split('!');
58+ let [sponsor, parent] = subMetaString.slice(1).split('!');
42− meta.sponsor = '~' + sponsor;
59+ meta.sponsor = '~' + sponsor;
43− meta.parent = '~' + parent;
60+ meta.parent = '~' + parent;
61+ }
44 }
62 }
45 }
63 }
64+ return meta;
46 }
65 }
47− return meta;
48−}
49
66
50−function extractMeta(data: string): [ChartPoint, string] {
67+ extractMeta(data: string): [ChartPoint, string] {
51− const index = data.search(/[[;]/);
68+ const index = data.search(/[[;]/);
52− if (index === -1) {
69+ if (index === -1) {
53− throw new Error(`No point meta present in ${data}`);
70+ throw new Error(`No point meta present in ${data}`);
71+ }
72+ const metaString = data.slice(0, index);
73+ data = data.slice(index);
74+ return [this.parseMetaString(metaString), data];
54 }
75 }
55− const metaString = data.slice(0, index);
56− data = data.slice(index);
57− return [parseMetaString(metaString), data];
58−}
59
76
60−function extractChildren(data: string, sup: string = undefined): [ChartPoint[], ChartPoint[], string] {
77+ extractChildren(data: string, sup: string = undefined): [ChartSubs, string] {
78+ if (data[0] === ';')
79+ return [{
80+ children: [],
81+ sponsees: [],
61− if (data[0] === ';') return [[], [], data.slice(1)];
82+ }, data.slice(1)];
62− if (data[0] !== '[') throw new Error('Invalid children in data: ' + data.slice(0, 20));
83+ if (data[0] !== '[') throw new Error('Invalid children in data: ' + data.slice(0, 20));
63
84
64− let endFound = false;
85+ let endFound = false;
65− let counter = 0;
86+ let counter = 0;
66− data = data.slice(1);
87+ data = data.slice(1);
67− const children = [];
88+ const children = [];
68− const sponsees = [];
89+ const sponsees = [];
69− while (!endFound && data.length && counter < 20000) {
90+ while (!endFound && data.length && counter < 20000) {
70− if (data[0] === ']') {
91+ if (data[0] === ']') {
71− endFound = true;
92+ endFound = true;
72− data = data.slice(1);
93+ data = data.slice(1);
73− } else {
94+ } else {
74− let sub;
95+ let sub;
75− [sub, data] = extractChartPoint(data);
96+ [sub, data] = this.extractChartPoint(data);
76− if (!sub.parent || sub.parent === sup)
97+ if (!sub.parent || sub.parent === sup)
77− children.push(sub);
98+ children.push(sub);
78− if (sub.sponsor === undefined || sub.sponsor === sup)
99+ if (sub.sponsor === undefined || sub.sponsor === sup)
79− sponsees.push(sub);
100+ sponsees.push(sub);
101+ }
102+ counter++;
80 }
103 }
81− counter++;
104+ return [{ children, sponsees }, data];
82 }
105 }
83− return [children, sponsees, data];
84−}
85
106
86−function extractChartPoint(data: string): [ChartPoint, string] {
107+ extractChartPoint(data: string): [ChartPoint, string] {
87− let point, children, sponsees;
108+ let point, subs;
88− [point, data] = extractMeta(data);
109+ [point, data] = this.extractMeta(data);
89− [children, sponsees, data] = extractChildren(data, point.patp);
110+ [subs, data] = this.extractChildren(data, point.patp);
90− point.children = children;
111+ point = {
91− point.sponsees = sponsees;
112+ ...point,
113+ ...subs,
114+ };
92− return [point, data];
115+ return [point, data];
93−}
116+ }
94
117
95−function linkChartData(points: ChartPoint[], store: any): ChartPoint[] {
118+ linkChartData(points: ChartPoint[], store: any): ChartPoint[] {
96− if (!points) return points;
119+ if (!points) return points;
97− return points.map(point => {
120+ return points.map(point => {
98− if (!store[point.patp]) return point;
121+ if (!store[point.patp]) return point;
99− if (!point.children?.length) {
122+ if (!point.children?.length) {
100− point.children = linkChartData(store[point.patp].children, store);
123+ point.children = this.linkChartData(store[point.patp].children, store);
124+ let picked = point.children.filter(child => child.picked || child.pickedChildren);
125+ point.pickedChildren = picked.length > 0;
101− }
126+ }
102− if (!point.sponsees?.length) {
127+ if (!point.sponsees?.length) {
103− point.sponsees = linkChartData(store[point.patp].sponsees, store);
128+ point.sponsees = this.linkChartData(store[point.patp].sponsees, store);
129+ let picked = point.sponsees.filter(child => child.picked || child.pickedSponsees);
130+ point.pickedSponsees = picked.length > 0;
104− }
131+ }
105− return point;
132+ return point;
106− });
133+ });
107−}
134+ }
108
135
109−function _parseChartData(str: string): ChartPoint[] {
136+ parse(str: string): ChartSubs {
110− if (!str) return [];
137+ if (!str) return { children: [], sponsees: [] };
111− let [baseChildren, _] = extractChildren(str);
138+ let [{ children: baseChildren }, _] = this.extractChildren(str, undefined);
112− let store = {};
139+ let store = {};
113− baseChildren.forEach(child => {
140+ baseChildren.forEach(child => {
114− store[child.patp] = {
141+ store[child.patp] = {
115− children: child.children,
142+ children: child.children,
116− sponsees: child.sponsees,
143+ sponsees: child.sponsees,
117− };
144+ };
118− });
145+ });
146+ let base: ChartPoint = {
147+ patp: '~base',
148+ dominion: 'l1',
149+ picked: true,
150+ }
119
151
120− return linkChartData(store['~base'].children, store);
152+ let points = this.linkChartData([base], store);
153+ return {
154+ children: points[0].children || [],
155+ sponsees: points[0].sponsees || [],
156+ }
157+ }
121}
158}
122
159
123−export function parseChartData(data: string): ChartPoint[] {
160+export function parseChartData(data: string, filter: Set<string>): ChartSubs {
124 let start = Date.now();
161 let start = Date.now();
125− let parsed = _parseChartData(data);
162+ let parser = new ChartDataParser(filter);
163+ let parsed = parser.parse(data);
126 // console.log(`finished parsing chart data to js object in ${Date.now() - start} ms`);
164 // console.log(`finished parsing chart data to js object in ${Date.now() - start} ms`);
127 return parsed;
165 return parsed;
128}
166}
@@ -188,16 +226,23 @@ export function arrangePointsInSpirals(
188 minDistanceBetween,
226 minDistanceBetween,
189 };
227 };
190}
228}
191−
229+type childKey = ('sponsees' | 'children');
192−export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: boolean, callback?): Graph {
230+export function populateGraph(g: Graph, chartSubs: ChartSubs, subsKey: childKey, callback?): Graph {
231+ let pickedSubsKey = subsKey == 'children' ? 'pickedChildren' : 'pickedSponsees';
232+ function pickedColor(point: ChartPoint, normal: string) {
233+ return point.picked ? normal : (point[pickedSubsKey] ? colors.SUB_PICKED : colors.NOT_PICKED);
234+ }
235+ function pickedArmColor(point: ChartPoint, normal: string) {
236+ return point[pickedSubsKey] ? normal : colors.NOT_PICKED;
237+ }
238+ let points = chartSubs[subsKey];
193− if (!(chartData instanceof Array)) return;
239+ if (!(points instanceof Array)) return;
194 if (!g) {
240 if (!g) {
195 g = new Graph();
241 g = new Graph();
196 } else {
242 } else {
197 g.clear();
243 g.clear();
198 }
244 }
199
245
200− let subsKey = bySponsor ? 'sponsees' : 'children';
201 let sponsorEdges = [];
246 let sponsorEdges = [];
202
247
203 let offsetX = 0;
248 let offsetX = 0;
@@ -207,7 +252,7 @@ export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: bool
207 let b = 9000000;
252 let b = 9000000;
208 let theta = 0;
253 let theta = 0;
209
254
210− chartData.forEach((galaxy, gi) => {
255+ points.forEach((galaxy, gi) => {
211 offsetX = 0 + (a + b * theta) * Math.cos(theta);
256 offsetX = 0 + (a + b * theta) * Math.cos(theta);
212 offsetY = 0 + (a + b * theta) * Math.sin(theta);
257 offsetY = 0 + (a + b * theta) * Math.sin(theta);
213
258
@@ -217,7 +262,7 @@ export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: bool
217 g.addNode(gPatp, {
262 g.addNode(gPatp, {
218 label: gPatp,
263 label: gPatp,
219 size: 3,
264 size: 3,
220− color: itsYou ? colors.YOU : colors.WHITE,
265+ color: itsYou ? colors.YOU : pickedColor(galaxy, colors.WHITE),
221 x: offsetX,
266 x: offsetX,
222 y: offsetY,
267 y: offsetY,
223 zIndex: 10,
268 zIndex: 10,
@@ -242,6 +287,7 @@ export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: bool
242 });
287 });
243 let lastStarArm = null;
288 let lastStarArm = null;
244 let lastStarPatp = null;
289 let lastStarPatp = null;
290+ let GSarmColor = pickedArmColor(galaxy, colors.LGREY)
245 stars.forEach((star, si) => {
291 stars.forEach((star, si) => {
246 const sPatp = star.patp;
292 const sPatp = star.patp;
247
293
@@ -256,20 +302,20 @@ export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: bool
256 g.addNode(sPatp, {
302 g.addNode(sPatp, {
257 label: sPatp,
303 label: sPatp,
258 size: starSize,
304 size: starSize,
259− color: itsYou ? colors.YOU : colors.GOLDT2,
305+ color: itsYou ? colors.YOU : pickedColor(star, colors.GOLDT2),
260 x: starX,
306 x: starX,
261 y: starY,
307 y: starY,
262 zIndex: 8,
308 zIndex: 8,
263 });
309 });
264 if (lastStarArm == arm) {
310 if (lastStarArm == arm) {
265 g.addEdge(sPatp, lastStarPatp, {
311 g.addEdge(sPatp, lastStarPatp, {
266− color: colors.LGREY,
312+ color: GSarmColor,
267 size: 0.1,
313 size: 0.1,
268 zIndex: 7,
314 zIndex: 7,
269 });
315 });
270 } else {
316 } else {
271 g.addEdge(sPatp, gPatp, {
317 g.addEdge(sPatp, gPatp, {
272− color: colors.LGREY,
318+ color: GSarmColor,
273 size: 0.2,
319 size: 0.2,
274 zIndex: 9,
320 zIndex: 9,
275 });
321 });
@@ -304,7 +350,8 @@ export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: bool
304 });
350 });
305 let lastPlanetArm = null;
351 let lastPlanetArm = null;
306 let lastPlanetPatp = null;
352 let lastPlanetPatp = null;
353+ let SParmColor = pickedArmColor(star, colors.DGREY)
307− planets.forEach((planet, pi) => {
354+ planets.forEach((planet, pi) => {
308 const pPatp = planet.patp;
355 const pPatp = planet.patp;
309 const [planetX, planetY] = planetCoords[pi].coords;
356 const [planetX, planetY] = planetCoords[pi].coords;
310 const arm = planetCoords[pi].arm;
357 const arm = planetCoords[pi].arm;
@@ -319,21 +366,21 @@ export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: bool
319 g.addNode(pPatp, {
366 g.addNode(pPatp, {
320 label: pPatp,
367 label: pPatp,
321 size: planetSize,
368 size: planetSize,
322− color: itsYou ? colors.YOU : (planet.dominion == 'l2' ? colors.GREEN : colors.BLUE),
369+ color: itsYou ? colors.YOU : pickedColor(planet, planet.dominion == 'l2' ? colors.GREEN : colors.BLUE),
323 x: planetX,
370 x: planetX,
324 y: planetY,
371 y: planetY,
325 zIndex: 6,
372 zIndex: 6,
326 });
373 });
327 if (lastPlanetArm == arm) {
374 if (lastPlanetArm == arm) {
328 g.addEdge(pPatp, lastPlanetPatp, {
375 g.addEdge(pPatp, lastPlanetPatp, {
329− color: colors.DGREY,
376+ color: SParmColor,
330 size: planetEdgeSize,
377 size: planetEdgeSize,
331 zIndex: 5,
378 zIndex: 5,
332 });
379 });
333 } else {
380 } else {
334 if (numPlanetArms == 1) {
381 if (numPlanetArms == 1) {
335 g.addEdge(pPatp, sPatp, {
382 g.addEdge(pPatp, sPatp, {
336− color: colors.DGREY,
383+ color: SParmColor,
337 size: planetEdgeSize,
384 size: planetEdgeSize,
338 zIndex: 5,
385 zIndex: 5,
339 });
386 });
ui/src/styles/tailwind-output.css+9−9
@@ -650,15 +650,15 @@ Ensure the default browser behavior of the `hidden` attribute.
650.ml-\[22px\] {
650.ml-\[22px\] {
651 margin-left: 22px;
651 margin-left: 22px;
652}
652}
653−.mr-4 {
654− margin-right: 1rem;
655−}
656.mr-1 {
653.mr-1 {
657 margin-right: 0.25rem;
654 margin-right: 0.25rem;
658}
655}
659.ml-8 {
656.ml-8 {
660 margin-left: 2rem;
657 margin-left: 2rem;
661}
658}
659+.mr-4 {
660+ margin-right: 1rem;
661+}
662.ml-1 {
662.ml-1 {
663 margin-left: 0.25rem;
663 margin-left: 0.25rem;
664}
664}
@@ -764,15 +764,15 @@ Ensure the default browser behavior of the `hidden` attribute.
764.h-full {
764.h-full {
765 height: 100%;
765 height: 100%;
766}
766}
767−.h-12 {
768− height: 3rem;
769−}
770.h-3 {
767.h-3 {
771 height: 0.75rem;
768 height: 0.75rem;
772}
769}
773.h-\[100vh\] {
770.h-\[100vh\] {
774 height: 100vh;
771 height: 100vh;
775}
772}
773+.h-12 {
774+ height: 3rem;
775+}
776.h-5 {
776.h-5 {
777 height: 1.25rem;
777 height: 1.25rem;
778}
778}
@@ -857,9 +857,6 @@ Ensure the default browser behavior of the `hidden` attribute.
857 width: -moz-min-content;
857 width: -moz-min-content;
858 width: min-content;
858 width: min-content;
859}
859}
860−.w-12 {
861− width: 3rem;
862−}
863.w-3 {
860.w-3 {
864 width: 0.75rem;
861 width: 0.75rem;
865}
862}
@@ -869,6 +866,9 @@ Ensure the default browser behavior of the `hidden` attribute.
869.w-\[100vw\] {
866.w-\[100vw\] {
870 width: 100vw;
867 width: 100vw;
871}
868}
869+.w-12 {
870+ width: 3rem;
871+}
872.w-5 {
872.w-5 {
873 width: 1.25rem;
873 width: 1.25rem;
874}
874}