@@ -6,161 +6,123 @@ const example = '[0[3216291:t;9219219;4608:s[156546;1612196;219621:~;321965149:4
66export interface ChartPoint {
77 patp: string,
88 dominion: ('l1' | 'l2' | 'spawn'),
9− picked: boolean,
10− pickedChildren?: boolean,
11− pickedSponsees?: boolean,
129 sponsor?: string,
1310 parent?: string,
1411 children?: ChartPoint[],
1512 sponsees?: ChartPoint[],
1613}
1714
18−interface ChartSubs {
19− children: ChartPoint[],
20− sponsees: ChartPoint[],
21−}
22−
23−class ChartDataParser {
24− filter: Set<string>;
25−
26− constructor(filter: Set<string>) {
27− this.filter = filter;
15+function parseMetaString(metaString: string): ChartPoint {
16+ let idString, subMetaString = '';
17+ const colIndex = metaString.indexOf(':');
18+ if (colIndex === -1) {
19+ idString = metaString;
20+ } else {
21+ idString = metaString.slice(0, colIndex);
22+ subMetaString = metaString.slice(colIndex + 1);
2823 }
29−
30− parseMetaString(metaString: string): ChartPoint {
31− let idString, subMetaString = '';
32− const colIndex = metaString.indexOf(':');
33− if (colIndex === -1) {
34− idString = metaString;
35− } else {
36− idString = metaString.slice(0, colIndex);
37− subMetaString = metaString.slice(colIndex + 1);
38− }
39− const patp = '~' + idString;
40− const meta: ChartPoint = {
41− patp,
42− picked: !this.filter ? true : (this.filter.has(patp)),
43− dominion: 'l1',
24+ const meta: ChartPoint = {
25+ patp: '~' + idString,
26+ dominion: 'l1',
27+ }
28+ if (subMetaString) {
29+ const firstChar = subMetaString[0];
30+ if (firstChar === 't') {
31+ meta.dominion = 'l2';
32+ subMetaString = subMetaString.slice(1);
33+ } else if (firstChar === 's') {
34+ meta.dominion = 'spawn';
35+ subMetaString = subMetaString.slice(1);
4436 }
4537 if (subMetaString) {
46− const firstChar = subMetaString[0];
47− if (firstChar === 't') {
48− meta.dominion = 'l2';
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] === '~') {
56− meta.sponsor = null;
57− } else {
58− let [sponsor, parent] = subMetaString.slice(1).split('!');
59− meta.sponsor = '~' + sponsor;
60− meta.parent = '~' + parent;
61− }
38+ if (subMetaString[0] === '~') {
39+ meta.sponsor = null;
40+ } else {
41+ let [sponsor, parent] = subMetaString.slice(1).split('!');
42+ meta.sponsor = '~' + sponsor;
43+ meta.parent = '~' + parent;
6244 }
6345 }
64− return meta;
6546 }
47+ return meta;
48+}
6649
67− extractMeta(data: string): [ChartPoint, string] {
68− const index = data.search(/[[;]/);
69− if (index === -1) {
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];
50+function extractMeta(data: string): [ChartPoint, string] {
51+ const index = data.search(/[[;]/);
52+ if (index === -1) {
53+ throw new Error(`No point meta present in ${data}`);
7554 }
55+ const metaString = data.slice(0, index);
56+ data = data.slice(index);
57+ return [parseMetaString(metaString), data];
58+}
7659
77− extractChildren(data: string, sup: string = undefined): [ChartSubs, string] {
78− if (data[0] === ';')
79− return [{
80− children: [],
81− sponsees: [],
82− }, data.slice(1)];
83− if (data[0] !== '[') throw new Error('Invalid children in data: ' + data.slice(0, 20));
60+function extractChildren(data: string, sup: string = undefined): [ChartPoint[], ChartPoint[], string] {
61+ if (data[0] === ';') return [[], [], data.slice(1)];
62+ if (data[0] !== '[') throw new Error('Invalid children in data: ' + data.slice(0, 20));
8463
85− let endFound = false;
86− let counter = 0;
87− data = data.slice(1);
88− const children = [];
89− const sponsees = [];
90− while (!endFound && data.length && counter < 20000) {
91− if (data[0] === ']') {
92− endFound = true;
93− data = data.slice(1);
94− } else {
95− let sub;
96− [sub, data] = this.extractChartPoint(data);
97− if (!sub.parent || sub.parent === sup)
98− children.push(sub);
99− if (sub.sponsor === undefined || sub.sponsor === sup)
100− sponsees.push(sub);
101− }
102− counter++;
64+ let endFound = false;
65+ let counter = 0;
66+ data = data.slice(1);
67+ const children = [];
68+ const sponsees = [];
69+ while (!endFound && data.length && counter < 20000) {
70+ if (data[0] === ']') {
71+ endFound = true;
72+ data = data.slice(1);
73+ } else {
74+ let sub;
75+ [sub, data] = extractChartPoint(data);
76+ if (!sub.parent || sub.parent === sup)
77+ children.push(sub);
78+ if (sub.sponsor === undefined || sub.sponsor === sup)
79+ sponsees.push(sub);
10380 }
104− return [{ children, sponsees }, data];
105− }
106−
107− extractChartPoint(data: string): [ChartPoint, string] {
108− let point, subs;
109− [point, data] = this.extractMeta(data);
110− [subs, data] = this.extractChildren(data, point.patp);
111− point = {
112− ...point,
113− ...subs,
114− };
115− return [point, data];
81+ counter++;
11682 }
83+ return [children, sponsees, data];
84+}
11785
118− linkChartData(points: ChartPoint[], store: any): ChartPoint[] {
119− if (!points) return points;
120− return points.map(point => {
121− if (!store[point.patp]) return point;
122− if (!point.children?.length) {
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;
126− }
127− if (!point.sponsees?.length) {
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;
131− }
132− return point;
133− });
134− }
86+function extractChartPoint(data: string): [ChartPoint, string] {
87+ let point, children, sponsees;
88+ [point, data] = extractMeta(data);
89+ [children, sponsees, data] = extractChildren(data, point.patp);
90+ point.children = children;
91+ point.sponsees = sponsees;
92+ return [point, data];
93+}
13594
136− parse(str: string): ChartSubs {
137− if (!str) return { children: [], sponsees: [] };
138− let [{ children: baseChildren }, _] = this.extractChildren(str, undefined);
139− let store = {};
140− baseChildren.forEach(child => {
141− store[child.patp] = {
142− children: child.children,
143− sponsees: child.sponsees,
144− };
145− });
146− let base: ChartPoint = {
147− patp: '~base',
148− dominion: 'l1',
149− picked: true,
95+function linkChartData(points: ChartPoint[], store: any): ChartPoint[] {
96+ if (!points) return points;
97+ return points.map(point => {
98+ if (!store[point.patp]) return point;
99+ if (!point.children?.length) {
100+ point.children = linkChartData(store[point.patp].children, store);
150101 }
151−
152− let points = this.linkChartData([base], store);
153− return {
154− children: points[0].children || [],
155− sponsees: points[0].sponsees || [],
102+ if (!point.sponsees?.length) {
103+ point.sponsees = linkChartData(store[point.patp].sponsees, store);
156104 }
157− }
105+ return point;
106+ });
158107}
159108
160−export function parseChartData(data: string, filter: Set<string>): ChartSubs {
109+function _parseChartData(str: string): ChartPoint[] {
110+ if (!str) return [];
111+ let [baseChildren, _] = extractChildren(str);
112+ let store = {};
113+ baseChildren.forEach(child => {
114+ store[child.patp] = {
115+ children: child.children,
116+ sponsees: child.sponsees,
117+ };
118+ });
119+
120+ return linkChartData(store['~base'].children, store);
121+}
122+
123+export function parseChartData(data: string): ChartPoint[] {
161124 let start = Date.now();
162− let parser = new ChartDataParser(filter);
163− let parsed = parser.parse(data);
125+ let parsed = _parseChartData(data);
164126 // console.log(`finished parsing chart data to js object in ${Date.now() - start} ms`);
165127 return parsed;
166128}
@@ -226,23 +188,16 @@ export function arrangePointsInSpirals(
226188 minDistanceBetween,
227189 };
228190}
229−type childKey = ('sponsees' | 'children');
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];
239− if (!(points instanceof Array)) return;
191+
192+export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: boolean, callback?): Graph {
193+ if (!(chartData instanceof Array)) return;
240194 if (!g) {
241195 g = new Graph();
242196 } else {
243197 g.clear();
244198 }
245199
200+ let subsKey = bySponsor ? 'sponsees' : 'children';
246201 let sponsorEdges = [];
247202
248203 let offsetX = 0;
@@ -252,7 +207,7 @@ export function populateGraph(g: Graph, chartSubs: ChartSubs, subsKey: childKey,
252207 let b = 9000000;
253208 let theta = 0;
254209
255− points.forEach((galaxy, gi) => {
210+ chartData.forEach((galaxy, gi) => {
256211 offsetX = 0 + (a + b * theta) * Math.cos(theta);
257212 offsetY = 0 + (a + b * theta) * Math.sin(theta);
258213
@@ -262,7 +217,7 @@ export function populateGraph(g: Graph, chartSubs: ChartSubs, subsKey: childKey,
262217 g.addNode(gPatp, {
263218 label: gPatp,
264219 size: 3,
265− color: itsYou ? colors.YOU : pickedColor(galaxy, colors.WHITE),
220+ color: itsYou ? colors.YOU : colors.WHITE,
266221 x: offsetX,
267222 y: offsetY,
268223 zIndex: 10,
@@ -287,7 +242,6 @@ export function populateGraph(g: Graph, chartSubs: ChartSubs, subsKey: childKey,
287242 });
288243 let lastStarArm = null;
289244 let lastStarPatp = null;
290− let GSarmColor = pickedArmColor(galaxy, colors.LGREY)
291245 stars.forEach((star, si) => {
292246 const sPatp = star.patp;
293247
@@ -302,20 +256,20 @@ export function populateGraph(g: Graph, chartSubs: ChartSubs, subsKey: childKey,
302256 g.addNode(sPatp, {
303257 label: sPatp,
304258 size: starSize,
305− color: itsYou ? colors.YOU : pickedColor(star, colors.GOLDT2),
259+ color: itsYou ? colors.YOU : colors.GOLDT2,
306260 x: starX,
307261 y: starY,
308262 zIndex: 8,
309263 });
310264 if (lastStarArm == arm) {
311265 g.addEdge(sPatp, lastStarPatp, {
312− color: GSarmColor,
266+ color: colors.LGREY,
313267 size: 0.1,
314268 zIndex: 7,
315269 });
316270 } else {
317271 g.addEdge(sPatp, gPatp, {
318− color: GSarmColor,
272+ color: colors.LGREY,
319273 size: 0.2,
320274 zIndex: 9,
321275 });
@@ -350,8 +304,7 @@ export function populateGraph(g: Graph, chartSubs: ChartSubs, subsKey: childKey,
350304 });
351305 let lastPlanetArm = null;
352306 let lastPlanetPatp = null;
353− let SParmColor = pickedArmColor(star, colors.DGREY)
354− planets.forEach((planet, pi) => {
307+ planets.forEach((planet, pi) => {
355308 const pPatp = planet.patp;
356309 const [planetX, planetY] = planetCoords[pi].coords;
357310 const arm = planetCoords[pi].arm;
@@ -366,21 +319,21 @@ export function populateGraph(g: Graph, chartSubs: ChartSubs, subsKey: childKey,
366319 g.addNode(pPatp, {
367320 label: pPatp,
368321 size: planetSize,
369− color: itsYou ? colors.YOU : pickedColor(planet, planet.dominion == 'l2' ? colors.GREEN : colors.BLUE),
322+ color: itsYou ? colors.YOU : (planet.dominion == 'l2' ? colors.GREEN : colors.BLUE),
370323 x: planetX,
371324 y: planetY,
372325 zIndex: 6,
373326 });
374327 if (lastPlanetArm == arm) {
375328 g.addEdge(pPatp, lastPlanetPatp, {
376− color: SParmColor,
329+ color: colors.DGREY,
377330 size: planetEdgeSize,
378331 zIndex: 5,
379332 });
380333 } else {
381334 if (numPlanetArms == 1) {
382335 g.addEdge(pPatp, sPatp, {
383− color: SParmColor,
336+ color: colors.DGREY,
384337 size: planetEdgeSize,
385338 zIndex: 5,
386339 });