@@ -1,10 +1,7 @@
1−import without from 'lodash/without';
2−import uniq from 'lodash/uniq';
3−
41export const CLANS = ['galaxy', 'star', 'planet'] as const;
52export type Clan = typeof CLANS[number];
63
7−export const PART_TYPES = ['geon', 'line', 'arc', 'circle', 'donut', 'bezier'] as const;
4+export const PART_TYPES = ['geon', 'line', 'arc', 'bezier', 'circle', 'donut'] as const;
85export type PartType = typeof PART_TYPES[number];
96
107export const GEONS = ['gci', 'gsq', 'ghl', 'ghr', 'ght', 'ghb', 'gq1', 'gq2', 'gq3', 'gq4', 'gfs', 'gbs'];
@@ -12,85 +9,140 @@ export type Geon = typeof GEONS[number];
129
1310export type SymbolType = ('prefix' | 'suffix');
1411
15−function getComplementaryCircleId(circleId: string): string {
16− let newId = circleId.replace(/m(?=.$)/, 'l');
17− if (newId === circleId) {
18− newId = circleId.replace(/l(?=.$)/, 'm');
19− }
20− circleId = newId;
21− circleId = circleId.replace(/f$/, 'b');
22− if (newId === circleId) {
23− circleId = circleId.replace(/b$/, 'f');
24− }
25− return circleId;
12+export interface ModeDef {
13+ modes?: ModeDefs;
14+ displayParts?: string[];
15+ parts?: string[];
2616}
2717
28−function getPartTypeIndex(partId: string): number {
29− return PART_TYPES.findIndex(p => p[0] === partId[0]);
18+export interface ModeDefs {
19+ [mode: string]: ModeDef
3020}
3121
32−export class SymbolQuery {
33− symbolType: SymbolType;
34− components: string[];
35−
36− constructor(symbolType: SymbolType = 'suffix', components = []) {
37− this.symbolType = symbolType;
38− this.components = components;
39− this.cleanupParts();
40− }
41−
42− set geon(geon: Geon) {
43− this.components = this.components.filter(c => c[0] !== 'g');
44− if (geon)
45− this.components = [geon, ...this.components];
46− }
4722
48− get geon(): Geon {
49− return this.components.find(c => c[0] === 'g');
50− }
51−
52− cleanupParts() {
53− this.components = uniq(this.components);
54− this.components = this.components.sort((c1, c2) => {
55− let i1 = getPartTypeIndex(c1);
56− let i2 = getPartTypeIndex(c2);
57− let diff = i1 - i2;
58− if (diff !== 0) return diff;
59− if (c1[0] === 'c') {
60− return c1.localeCompare(c2);
61− } else {
62− return c2.localeCompare(c1);
23+export const MODE_DEFS: ModeDefs = {
24+ geon: {
25+ modes: {},
26+ displayParts: ['ghb'],
27+ },
28+ line: {
29+ modes: {
30+ mainFulls: {
31+ parts: ['lvf', 'lhf', 'lff', 'lbf'],
32+ },
33+ halvesFulls: {
34+ parts: ['lvfl', 'lvfr', 'lhft', 'lhfb', 'lfht', 'lfhb', 'lbht', 'lbhb'],
35+ },
36+ forwards: {
37+ parts: ['lff', 'lfft', 'lffb'],
38+ },
39+ backwards: {
40+ parts: ['lbf', 'lbft'],
41+ },
42+ weirds: {
43+ parts: ['lbhtf', 'lbrf', 'lfhm'],
6344 }
64− });
65− }
66−
67− clearPartType(partType: PartType) {
68− this.components = this.components.filter(c => c[0] !== partType[0]);
69− return this;
70− }
71−
72− clear() {
73− this.components = [];
74− return this;
75− }
76−
77− addPart(partId: string) {
78− this.components = [...this.components, partId];
79− if (partId[0] === 'c') {
80− const otherPartId = getComplementaryCircleId(partId);
81− this.components = [...this.components, otherPartId];
82− }
83− this.cleanupParts();
84− return this;
85− }
86−
87− removePart(partId: string) {
88− this.components = without(this.components, partId);
89− if (partId[0] === 'c') {
90− const otherPartId = getComplementaryCircleId(partId);
91− this.components = without(this.components, otherPartId);
92− }
93− this.cleanupParts();
94− return this;
95− }
96−}
45+ },
46+ parts: ['lvf', 'lvfl', 'lvfr', 'lhf', 'lhft', 'lhfb', 'lff', 'lbf'],
47+ },
48+ arcCorner: {
49+ modes: {
50+ trFulls: {
51+ parts: ['atrf8', 'atrf6', 'atrf4', 'atrf2'],
52+ },
53+ trHalves: {
54+ parts: [/*'atra8',*/ 'atra6', 'atra4', 'atra2', 'atrb8', 'atrb6', 'atrb4', 'atrb2'],
55+ displayParts: ['atrb8', 'atrb6', 'atrb4', 'atrb2'],
56+ },
57+ tlFulls: {
58+ parts: ['atlf8', 'atlf6', 'atlf4', 'atlf2'],
59+ },
60+ tlHalves: {
61+ parts: ['atla8', 'atla6', 'atla4', 'atla2', 'atlb8', 'atlb6', 'atlb4', 'atlb2'],
62+ displayParts: ['atlb8', 'atlb6', 'atlb4', 'atlb2'],
63+ },
64+ blFulls: {
65+ parts: ['ablf8', 'ablf6', 'ablf4', 'ablf2'],
66+ },
67+ blHalves: {
68+ parts: ['ablb8', 'ablb6', 'ablb4', 'ablb2'],
69+ displayParts: ['ablb8', 'ablb6', 'ablb4', 'ablb2'],
70+ },
71+ brFulls: {
72+ parts: ['abrf8', 'abrf6', 'abrf4', 'abrf2'],
73+ },
74+ brHalves: {
75+ parts: ['abrb8', 'abrb6', 'abrb4', 'abrb2'],
76+ displayParts: ['abrb8', 'abrb6', 'abrb4', 'abrb2'],
77+ },
78+ },
79+ parts: ['ablf8', 'ablf6', 'ablf4', 'ablf2'],
80+ },
81+ arc: {
82+ modes: {
83+ rings: {
84+ parts: ['am081', 'am082', 'am083', 'am08s'],
85+ },
86+ diagonals: {
87+ parts: ['am741', 'am742', 'am743', 'am422', 'am423'],
88+ },
89+ topsBottoms: {
90+ parts: ['ab2', 'ab3', 'ab4', 'at1', 'at3', 'at4'],
91+ },
92+ leftsRights: {
93+ parts: ['al2', 'al3', 'al4', 'ar1', 'ar2', 'ar4'/*, 'arb2'*/],
94+ },
95+ rights: {
96+ parts: ['am642', 'am643'],
97+ },
98+ middles: {
99+ parts: ['am222', 'am223', 'am622', 'am623'],
100+ },
101+ middless: {
102+ parts: ['am142', 'am443'],
103+ },
104+ topRights: {
105+ parts: ['am021', 'am022', 'am023', 'am242', 'arb2'],
106+ },
107+ },
108+ parts: ['am222', 'am223', 'ar4', 'ar2', 'ar1'],
109+ },
110+ circle: {
111+ modes: {
112+ mediums: {
113+ parts: [
114+ 'cmmb',
115+ 'ctl3mb', 'cbl3mb',
116+ 'ct2mb', 'cb2mb', 'cl2mb', 'cr2mb', 'ctl2mb', 'ctr2mb', 'cbl2mb', 'cbr2mb',
117+ 'ctl1mb', 'ctr1mb', 'cbl1mb', 'cbr1mb',
118+ 'cbl3mf', 'ctr3mf', 'ctl3mf',
119+ ],
120+ displayParts: [
121+ 'cmmb',
122+ 'ctl3mb', 'cbl3mb',
123+ 'ct2mb', 'cb2mb', 'cl2mb', 'cr2mb', 'ctl2mb', 'ctr2mb', 'cbl2mb', 'cbr2mb',
124+ 'ctl1mb', 'ctr1mb', 'cbl1mb', 'cbr1mb',
125+ 'ctr3mf',
126+ ],
127+ },
128+ sides: {
129+ parts: ['cl1mb', 'cr1mb', 'cl3mb', 'cr3mb'],
130+ },
131+ smalls: {
132+ parts: ['cr1sb', 'cr2sb'],
133+ },
134+ },
135+ displayParts: [
136+ 'cbr3mb', 'ctl3mb',
137+ 'cmmb',
138+ 'ct2mb', 'cl2mb', 'cb2mb', 'cr2mb',
139+ ],
140+ },
141+ donut: {
142+ parts: ['dbl', 'dl', 'dm', 'dtl', 'dtr'],
143+ displayParts: ['dbl', /*'dl',*/ 'dm', 'dtl', 'dtr'],
144+ },
145+ bezier: {
146+ parts: ['b1l1', 'b1l2', 'b1l3', 'b4t2', 'b4t3'],
147+ },
148+};