@@ -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'),
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[],
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,
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;
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 = {
42+ picked: !this.filter ? true : (this.filter.has(patp)),
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);
55+ if (subMetaString[0] === '~') {
39− meta.sponsor = null;
56+ meta.sponsor = null;
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;
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}`);
72+ const metaString = data.slice(0, index);
73+ data = data.slice(index);
74+ return [this.parseMetaString(metaString), data];
55− const metaString = data.slice(0, index);
56− data = data.slice(index);
57− return [parseMetaString(metaString), data];
60−function extractChildren(data: string, sup: string = undefined): [ChartPoint[], ChartPoint[], string] {
77+ extractChildren(data: string, sup: string = undefined): [ChartSubs, string] {
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));
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);
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);
81− counter++;
104+ return [{ children, sponsees }, data];
83− return [children, sponsees, data];
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,
92− return [point, data];
115+ return [point, data];
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;
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;
105− return point;
132+ return point;
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,
146+ let base: ChartPoint = {
120− return linkChartData(store['~base'].children, store);
152+ let points = this.linkChartData([base], store);
154+ children: points[0].children || [],
155+ sponsees: points[0].sponsees || [],
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;
@@ -188,16 +226,23 @@ export function arrangePointsInSpirals(
188 minDistanceBetween,
226 minDistanceBetween,
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);
235+ function pickedArmColor(point: ChartPoint, normal: string) {
236+ return point[pickedSubsKey] ? normal : colors.NOT_PICKED;
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();
197 g.clear();
243 g.clear();
200− let subsKey = bySponsor ? 'sponsees' : 'children';
201 let sponsorEdges = [];
246 let sponsorEdges = [];
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;
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);
@@ -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,
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
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;
@@ -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,
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,
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,
@@ -304,7 +350,8 @@ export function populateGraph(g: Graph, chartData: ChartPoint[], bySponsor: bool
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,
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,
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,