@logic-pad/core 0.26.2 → 0.26.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/assets/logic-core.global.d.ts +3264 -3264
  2. package/dist/benchmark/helper.d.ts +21 -0
  3. package/dist/benchmark/helper.js +34 -0
  4. package/dist/benchmark/prepareBench.d.ts +1 -0
  5. package/dist/benchmark/prepareBench.js +140 -0
  6. package/dist/benchmark/runBench.d.ts +1 -0
  7. package/dist/benchmark/runBench.js +206 -0
  8. package/dist/src/data/config.d.ts +119 -0
  9. package/dist/src/data/config.js +72 -0
  10. package/dist/src/data/configurable.d.ts +14 -0
  11. package/dist/src/data/configurable.js +26 -0
  12. package/dist/src/data/dataHelper.d.ts +92 -0
  13. package/dist/src/data/dataHelper.js +217 -0
  14. package/dist/src/data/events/eventHelper.d.ts +1 -0
  15. package/dist/src/data/events/eventHelper.js +6 -0
  16. package/dist/src/data/events/onFinalValidation.d.ts +14 -0
  17. package/dist/src/data/events/onFinalValidation.js +4 -0
  18. package/dist/src/data/events/onGetTile.d.ts +7 -0
  19. package/dist/src/data/events/onGetTile.js +4 -0
  20. package/dist/src/data/events/onGridChange.d.ts +6 -0
  21. package/dist/src/data/events/onGridChange.js +4 -0
  22. package/dist/src/data/events/onGridResize.d.ts +9 -0
  23. package/dist/src/data/events/onGridResize.js +4 -0
  24. package/dist/src/data/events/onSetGrid.d.ts +7 -0
  25. package/dist/src/data/events/onSetGrid.js +19 -0
  26. package/dist/src/data/events/onSymbolDisplay.d.ts +16 -0
  27. package/dist/src/data/events/onSymbolDisplay.js +4 -0
  28. package/dist/src/data/events/onSymbolMerge.d.ts +10 -0
  29. package/dist/src/data/events/onSymbolMerge.js +4 -0
  30. package/dist/src/data/events/onSymbolValidation.d.ts +18 -0
  31. package/dist/src/data/events/onSymbolValidation.js +4 -0
  32. package/dist/src/data/grid.d.ts +410 -0
  33. package/dist/src/data/grid.js +1106 -0
  34. package/dist/src/data/gridConnections.d.ts +25 -0
  35. package/dist/src/data/gridConnections.js +309 -0
  36. package/dist/src/data/gridZones.d.ts +26 -0
  37. package/dist/src/data/gridZones.js +117 -0
  38. package/dist/src/data/instruction.d.ts +26 -0
  39. package/dist/src/data/instruction.js +29 -0
  40. package/dist/src/data/primitives.d.ts +138 -0
  41. package/dist/src/data/primitives.js +177 -0
  42. package/dist/src/data/puzzle.d.ts +73 -0
  43. package/dist/src/data/puzzle.js +105 -0
  44. package/dist/src/data/rules/banPatternRule.d.ts +30 -0
  45. package/dist/src/data/rules/banPatternRule.js +125 -0
  46. package/dist/src/data/rules/cellCountPerZoneRule.d.ts +23 -0
  47. package/dist/src/data/rules/cellCountPerZoneRule.js +39 -0
  48. package/dist/src/data/rules/cellCountRule.d.ts +33 -0
  49. package/dist/src/data/rules/cellCountRule.js +138 -0
  50. package/dist/src/data/rules/completePatternRule.d.ts +24 -0
  51. package/dist/src/data/rules/completePatternRule.js +46 -0
  52. package/dist/src/data/rules/connectAllRule.d.ts +29 -0
  53. package/dist/src/data/rules/connectAllRule.js +88 -0
  54. package/dist/src/data/rules/connectZonesRule.d.ts +29 -0
  55. package/dist/src/data/rules/connectZonesRule.js +111 -0
  56. package/dist/src/data/rules/containsShapeRule.d.ts +34 -0
  57. package/dist/src/data/rules/containsShapeRule.js +125 -0
  58. package/dist/src/data/rules/customRule.d.ts +34 -0
  59. package/dist/src/data/rules/customRule.js +74 -0
  60. package/dist/src/data/rules/differentCountPerZoneRule.d.ts +30 -0
  61. package/dist/src/data/rules/differentCountPerZoneRule.js +96 -0
  62. package/dist/src/data/rules/exactCountPerZoneRule.d.ts +33 -0
  63. package/dist/src/data/rules/exactCountPerZoneRule.js +99 -0
  64. package/dist/src/data/rules/foresightRule.d.ts +36 -0
  65. package/dist/src/data/rules/foresightRule.js +107 -0
  66. package/dist/src/data/rules/index.d.ts +3 -0
  67. package/dist/src/data/rules/index.js +10 -0
  68. package/dist/src/data/rules/lyingSymbolRule.d.ts +31 -0
  69. package/dist/src/data/rules/lyingSymbolRule.js +207 -0
  70. package/dist/src/data/rules/musicControlLine.d.ts +82 -0
  71. package/dist/src/data/rules/musicControlLine.js +167 -0
  72. package/dist/src/data/rules/musicGridRule.d.ts +51 -0
  73. package/dist/src/data/rules/musicGridRule.js +212 -0
  74. package/dist/src/data/rules/mysteryRule.d.ts +39 -0
  75. package/dist/src/data/rules/mysteryRule.js +146 -0
  76. package/dist/src/data/rules/noLoopsRule.d.ts +29 -0
  77. package/dist/src/data/rules/noLoopsRule.js +218 -0
  78. package/dist/src/data/rules/offByXRule.d.ts +32 -0
  79. package/dist/src/data/rules/offByXRule.js +124 -0
  80. package/dist/src/data/rules/perfectionRule.d.ts +45 -0
  81. package/dist/src/data/rules/perfectionRule.js +158 -0
  82. package/dist/src/data/rules/regionAreaRule.d.ts +34 -0
  83. package/dist/src/data/rules/regionAreaRule.js +149 -0
  84. package/dist/src/data/rules/regionShapeRule.d.ts +22 -0
  85. package/dist/src/data/rules/regionShapeRule.js +58 -0
  86. package/dist/src/data/rules/rule.d.ts +18 -0
  87. package/dist/src/data/rules/rule.js +19 -0
  88. package/dist/src/data/rules/rules.gen.d.ts +23 -0
  89. package/dist/src/data/rules/rules.gen.js +27 -0
  90. package/dist/src/data/rules/sameCountPerZoneRule.d.ts +30 -0
  91. package/dist/src/data/rules/sameCountPerZoneRule.js +95 -0
  92. package/dist/src/data/rules/sameShapeRule.d.ts +28 -0
  93. package/dist/src/data/rules/sameShapeRule.js +68 -0
  94. package/dist/src/data/rules/symbolsPerRegionRule.d.ts +38 -0
  95. package/dist/src/data/rules/symbolsPerRegionRule.js +181 -0
  96. package/dist/src/data/rules/undercluedRule.d.ts +24 -0
  97. package/dist/src/data/rules/undercluedRule.js +53 -0
  98. package/dist/src/data/rules/uniqueShapeRule.d.ts +28 -0
  99. package/dist/src/data/rules/uniqueShapeRule.js +65 -0
  100. package/dist/src/data/rules/wrapAroundRule.d.ts +36 -0
  101. package/dist/src/data/rules/wrapAroundRule.js +241 -0
  102. package/dist/src/data/serializer/allSerializers.d.ts +35 -0
  103. package/dist/src/data/serializer/allSerializers.js +78 -0
  104. package/dist/src/data/serializer/compressor/allCompressors.d.ts +14 -0
  105. package/dist/src/data/serializer/compressor/allCompressors.js +43 -0
  106. package/dist/src/data/serializer/compressor/checksumCompressor.d.ts +6 -0
  107. package/dist/src/data/serializer/compressor/checksumCompressor.js +21 -0
  108. package/dist/src/data/serializer/compressor/compressorBase.d.ts +16 -0
  109. package/dist/src/data/serializer/compressor/compressorBase.js +2 -0
  110. package/dist/src/data/serializer/compressor/deflateCompressor.d.ts +7 -0
  111. package/dist/src/data/serializer/compressor/deflateCompressor.js +17 -0
  112. package/dist/src/data/serializer/compressor/gzipCompressor.d.ts +5 -0
  113. package/dist/src/data/serializer/compressor/gzipCompressor.js +9 -0
  114. package/dist/src/data/serializer/compressor/streamCompressor.d.ts +6 -0
  115. package/dist/src/data/serializer/compressor/streamCompressor.js +41 -0
  116. package/dist/src/data/serializer/serializerBase.d.ts +32 -0
  117. package/dist/src/data/serializer/serializerBase.js +2 -0
  118. package/dist/src/data/serializer/serializer_checksum.d.ts +35 -0
  119. package/dist/src/data/serializer/serializer_checksum.js +179 -0
  120. package/dist/src/data/serializer/serializer_v0.d.ts +55 -0
  121. package/dist/src/data/serializer/serializer_v0.js +484 -0
  122. package/dist/src/data/shapes.d.ts +19 -0
  123. package/dist/src/data/shapes.js +137 -0
  124. package/dist/src/data/solver/allSolvers.d.ts +3 -0
  125. package/dist/src/data/solver/allSolvers.js +13 -0
  126. package/dist/src/data/solver/auto/autoSolver.d.ts +18 -0
  127. package/dist/src/data/solver/auto/autoSolver.js +156 -0
  128. package/dist/src/data/solver/backtrack/backtrackSolver.d.ts +11 -0
  129. package/dist/src/data/solver/backtrack/backtrackSolver.js +54 -0
  130. package/dist/src/data/solver/backtrack/backtrackWorker.d.ts +1 -0
  131. package/dist/src/data/solver/backtrack/backtrackWorker.js +312 -0
  132. package/dist/src/data/solver/backtrack/data.d.ts +47 -0
  133. package/dist/src/data/solver/backtrack/data.js +151 -0
  134. package/dist/src/data/solver/backtrack/rules/banPattern.d.ts +9 -0
  135. package/dist/src/data/solver/backtrack/rules/banPattern.js +77 -0
  136. package/dist/src/data/solver/backtrack/rules/cellCount.d.ts +7 -0
  137. package/dist/src/data/solver/backtrack/rules/cellCount.js +25 -0
  138. package/dist/src/data/solver/backtrack/rules/connectAll.d.ts +7 -0
  139. package/dist/src/data/solver/backtrack/rules/connectAll.js +44 -0
  140. package/dist/src/data/solver/backtrack/rules/regionArea.d.ts +8 -0
  141. package/dist/src/data/solver/backtrack/rules/regionArea.js +71 -0
  142. package/dist/src/data/solver/backtrack/rules/regionShape.d.ts +8 -0
  143. package/dist/src/data/solver/backtrack/rules/regionShape.js +57 -0
  144. package/dist/src/data/solver/backtrack/rules/sameShape.d.ts +8 -0
  145. package/dist/src/data/solver/backtrack/rules/sameShape.js +14 -0
  146. package/dist/src/data/solver/backtrack/rules/symbolsPerRegion.d.ts +10 -0
  147. package/dist/src/data/solver/backtrack/rules/symbolsPerRegion.js +82 -0
  148. package/dist/src/data/solver/backtrack/rules/uniqueShape.d.ts +8 -0
  149. package/dist/src/data/solver/backtrack/rules/uniqueShape.js +14 -0
  150. package/dist/src/data/solver/backtrack/symbols/areaNumber.d.ts +9 -0
  151. package/dist/src/data/solver/backtrack/symbols/areaNumber.js +75 -0
  152. package/dist/src/data/solver/backtrack/symbols/dart.d.ts +8 -0
  153. package/dist/src/data/solver/backtrack/symbols/dart.js +45 -0
  154. package/dist/src/data/solver/backtrack/symbols/directionLinker.d.ts +11 -0
  155. package/dist/src/data/solver/backtrack/symbols/directionLinker.js +121 -0
  156. package/dist/src/data/solver/backtrack/symbols/focus.d.ts +9 -0
  157. package/dist/src/data/solver/backtrack/symbols/focus.js +48 -0
  158. package/dist/src/data/solver/backtrack/symbols/galaxy.d.ts +9 -0
  159. package/dist/src/data/solver/backtrack/symbols/galaxy.js +14 -0
  160. package/dist/src/data/solver/backtrack/symbols/letter.d.ts +9 -0
  161. package/dist/src/data/solver/backtrack/symbols/letter.js +95 -0
  162. package/dist/src/data/solver/backtrack/symbols/lotus.d.ts +11 -0
  163. package/dist/src/data/solver/backtrack/symbols/lotus.js +55 -0
  164. package/dist/src/data/solver/backtrack/symbols/minesweeper.d.ts +9 -0
  165. package/dist/src/data/solver/backtrack/symbols/minesweeper.js +44 -0
  166. package/dist/src/data/solver/backtrack/symbols/myopia.d.ts +7 -0
  167. package/dist/src/data/solver/backtrack/symbols/myopia.js +73 -0
  168. package/dist/src/data/solver/backtrack/symbols/viewpoint.d.ts +7 -0
  169. package/dist/src/data/solver/backtrack/symbols/viewpoint.js +51 -0
  170. package/dist/src/data/solver/cspuz/cspuzSolver.d.ts +13 -0
  171. package/dist/src/data/solver/cspuz/cspuzSolver.js +124 -0
  172. package/dist/src/data/solver/cspuz/cspuzWorker.d.ts +1 -0
  173. package/dist/src/data/solver/cspuz/cspuzWorker.js +82 -0
  174. package/dist/src/data/solver/cspuz/jsonify.d.ts +3 -0
  175. package/dist/src/data/solver/cspuz/jsonify.js +215 -0
  176. package/dist/src/data/solver/eventIteratingSolver.d.ts +8 -0
  177. package/dist/src/data/solver/eventIteratingSolver.js +54 -0
  178. package/dist/src/data/solver/solver.d.ts +77 -0
  179. package/dist/src/data/solver/solver.js +59 -0
  180. package/dist/src/data/solver/universal/universalSolver.d.ts +7 -0
  181. package/dist/src/data/solver/universal/universalSolver.js +13 -0
  182. package/dist/src/data/solver/universal/universalWorker.d.ts +1 -0
  183. package/dist/src/data/solver/universal/universalWorker.js +128 -0
  184. package/dist/src/data/symbols/areaNumberSymbol.d.ts +31 -0
  185. package/dist/src/data/symbols/areaNumberSymbol.js +80 -0
  186. package/dist/src/data/symbols/customIconSymbol.d.ts +35 -0
  187. package/dist/src/data/symbols/customIconSymbol.js +94 -0
  188. package/dist/src/data/symbols/customSymbol.d.ts +25 -0
  189. package/dist/src/data/symbols/customSymbol.js +45 -0
  190. package/dist/src/data/symbols/customTextSymbol.d.ts +35 -0
  191. package/dist/src/data/symbols/customTextSymbol.js +95 -0
  192. package/dist/src/data/symbols/dartSymbol.d.ts +36 -0
  193. package/dist/src/data/symbols/dartSymbol.js +96 -0
  194. package/dist/src/data/symbols/directionLinkerSymbol.d.ts +29 -0
  195. package/dist/src/data/symbols/directionLinkerSymbol.js +232 -0
  196. package/dist/src/data/symbols/everyLetterSymbol.d.ts +32 -0
  197. package/dist/src/data/symbols/everyLetterSymbol.js +119 -0
  198. package/dist/src/data/symbols/focusSymbol.d.ts +40 -0
  199. package/dist/src/data/symbols/focusSymbol.js +159 -0
  200. package/dist/src/data/symbols/galaxySymbol.d.ts +27 -0
  201. package/dist/src/data/symbols/galaxySymbol.js +61 -0
  202. package/dist/src/data/symbols/hiddenSymbol.d.ts +38 -0
  203. package/dist/src/data/symbols/hiddenSymbol.js +113 -0
  204. package/dist/src/data/symbols/houseSymbol.d.ts +33 -0
  205. package/dist/src/data/symbols/houseSymbol.js +104 -0
  206. package/dist/src/data/symbols/index.d.ts +3 -0
  207. package/dist/src/data/symbols/index.js +10 -0
  208. package/dist/src/data/symbols/letterSymbol.d.ts +32 -0
  209. package/dist/src/data/symbols/letterSymbol.js +118 -0
  210. package/dist/src/data/symbols/lotusSymbol.d.ts +30 -0
  211. package/dist/src/data/symbols/lotusSymbol.js +132 -0
  212. package/dist/src/data/symbols/minesweeperSymbol.d.ts +33 -0
  213. package/dist/src/data/symbols/minesweeperSymbol.js +106 -0
  214. package/dist/src/data/symbols/myopiaSymbol.d.ts +37 -0
  215. package/dist/src/data/symbols/myopiaSymbol.js +182 -0
  216. package/dist/src/data/symbols/numberSymbol.d.ts +19 -0
  217. package/dist/src/data/symbols/numberSymbol.js +32 -0
  218. package/dist/src/data/symbols/symbol.d.ts +29 -0
  219. package/dist/src/data/symbols/symbol.js +87 -0
  220. package/dist/src/data/symbols/symbols.gen.d.ts +15 -0
  221. package/dist/src/data/symbols/symbols.gen.js +19 -0
  222. package/dist/src/data/symbols/unsupportedSymbol.d.ts +23 -0
  223. package/dist/src/data/symbols/unsupportedSymbol.js +47 -0
  224. package/dist/src/data/symbols/viewpointSymbol.d.ts +32 -0
  225. package/dist/src/data/symbols/viewpointSymbol.js +95 -0
  226. package/dist/src/data/tile.d.ts +26 -0
  227. package/dist/src/data/tile.js +56 -0
  228. package/dist/src/data/tileConnections.d.ts +25 -0
  229. package/dist/src/data/tileConnections.js +74 -0
  230. package/dist/src/data/validate.d.ts +5 -0
  231. package/dist/src/data/validate.js +131 -0
  232. package/dist/src/data/validateAsync.d.ts +15 -0
  233. package/dist/src/data/validateAsync.js +71 -0
  234. package/dist/src/data/validateAsyncWorker.d.ts +1 -0
  235. package/dist/src/data/validateAsyncWorker.js +9 -0
  236. package/dist/src/index.d.ts +109 -0
  237. package/dist/src/index.js +112 -0
  238. package/dist/src/polyfill/streamPolyfill.d.ts +2 -0
  239. package/dist/src/polyfill/streamPolyfill.js +1 -0
  240. package/package.json +1 -1
@@ -0,0 +1,484 @@
1
+ import GridData from '../grid.js';
2
+ import GridConnections from '../gridConnections.js';
3
+ import TileData from '../tile.js';
4
+ import { ConfigType, } from '../config.js';
5
+ import { Color, DIRECTIONS, ORIENTATIONS, Orientation, directionToggle, orientationToggle, INSTRUMENTS, } from '../primitives.js';
6
+ import { array, escape, unescape } from '../dataHelper.js';
7
+ import { allRules } from '../rules/index.js';
8
+ import { allSymbols } from '../symbols/index.js';
9
+ import SerializerBase from './serializerBase.js';
10
+ import { ControlLine, Row } from '../rules/musicControlLine.js';
11
+ import GridZones from '../gridZones.js';
12
+ export const OFFSETS = [
13
+ { x: 0, y: -1 },
14
+ { x: -1, y: 0 },
15
+ { x: 1, y: 0 },
16
+ { x: 0, y: 1 },
17
+ ];
18
+ export const orientationChars = {
19
+ [Orientation.Up]: 'u',
20
+ [Orientation.UpRight]: 'x',
21
+ [Orientation.Right]: 'r',
22
+ [Orientation.DownRight]: 'z',
23
+ [Orientation.Down]: 'd',
24
+ [Orientation.DownLeft]: 'y',
25
+ [Orientation.Left]: 'l',
26
+ [Orientation.UpLeft]: 'w',
27
+ };
28
+ export default class SerializerV0 extends SerializerBase {
29
+ version = 0;
30
+ stringifyTile(tile) {
31
+ if (!tile.exists)
32
+ return '.';
33
+ const char = tile.color === Color.Gray ? 'n' : tile.color === Color.Dark ? 'b' : 'w';
34
+ return tile.fixed ? char.toUpperCase() : char;
35
+ }
36
+ parseTile(str) {
37
+ return TileData.create(str);
38
+ }
39
+ stringifyControlLine(line) {
40
+ const result = [];
41
+ result.push(`c${line.column}`);
42
+ if (line.bpm !== null)
43
+ result.push(`b${line.bpm}`);
44
+ if (line.pedal !== null)
45
+ result.push(`p${line.pedal ? '1' : '0'}`);
46
+ if (line.checkpoint)
47
+ result.push('s');
48
+ result.push(`r${line.rows
49
+ .map(row => `i${row.instrument ?? ''}v${row.velocity ?? ''}n${row.note ?? ''}`)
50
+ .join(',')}`);
51
+ return result.join('|');
52
+ }
53
+ parseControlLine(str) {
54
+ let column = null;
55
+ let bpm = null;
56
+ let pedal = null;
57
+ let checkpoint = false;
58
+ const rows = [];
59
+ const data = str.split('|');
60
+ for (const entry of data) {
61
+ const key = entry.charAt(0);
62
+ const value = entry.slice(1);
63
+ switch (key) {
64
+ case 'c':
65
+ column = value === '' ? null : Number(value);
66
+ break;
67
+ case 'b':
68
+ bpm = value === '' ? null : Number(value);
69
+ break;
70
+ case 'p':
71
+ pedal = value === '1' ? true : value === '0' ? false : null;
72
+ break;
73
+ case 's':
74
+ checkpoint = true;
75
+ break;
76
+ case 'r':
77
+ rows.push(...value.split(',').map(row => {
78
+ const match = /^(?:i(\w*?))?v([\d.]*?)n(.*)$/.exec(row);
79
+ if (!match)
80
+ return new Row(null, null, null);
81
+ const [, instrument, velocity, note] = match;
82
+ return new Row(note === '' ? null : note, instrument === '' ||
83
+ !INSTRUMENTS.includes(instrument)
84
+ ? null
85
+ : instrument, velocity === '' ? null : Number(velocity));
86
+ }));
87
+ break;
88
+ }
89
+ }
90
+ return new ControlLine(column ?? 0, bpm, pedal, checkpoint, rows);
91
+ }
92
+ stringifyConfig(instruction, config) {
93
+ switch (config.type) {
94
+ case ConfigType.Boolean:
95
+ return (config.field +
96
+ '=' +
97
+ (instruction[config.field] ? '1' : '0'));
98
+ case ConfigType.Number:
99
+ case ConfigType.Color:
100
+ case ConfigType.Comparison:
101
+ case ConfigType.Wrapping:
102
+ case ConfigType.Direction:
103
+ case ConfigType.Orientation:
104
+ return (config.field +
105
+ '=' +
106
+ instruction[config.field]);
107
+ case ConfigType.NullableBoolean:
108
+ return (config.field +
109
+ '=' +
110
+ (instruction[config.field] === null
111
+ ? ''
112
+ : instruction[config.field]
113
+ ? '1'
114
+ : '0'));
115
+ case ConfigType.NullableNumber:
116
+ return (config.field +
117
+ '=' +
118
+ (instruction[config.field] === null
119
+ ? ''
120
+ : String(instruction[config.field])));
121
+ case ConfigType.DirectionToggle:
122
+ return (config.field +
123
+ '=' +
124
+ DIRECTIONS.filter(dir => instruction[config.field][dir])
125
+ .map(x => orientationChars[x])
126
+ .join(''));
127
+ case ConfigType.OrientationToggle:
128
+ return (config.field +
129
+ '=' +
130
+ ORIENTATIONS.filter(dir => instruction[config.field][dir])
131
+ .map(x => orientationChars[x])
132
+ .join(''));
133
+ case ConfigType.String:
134
+ case ConfigType.Icon:
135
+ return (config.field +
136
+ '=' +
137
+ escape(instruction[config.field]));
138
+ case ConfigType.NullableNote:
139
+ return (config.field +
140
+ '=' +
141
+ escape(instruction[config.field] === null
142
+ ? ''
143
+ : escape(String(instruction[config.field]))));
144
+ case ConfigType.NullableInstrument:
145
+ return (config.field +
146
+ '=' +
147
+ escape(instruction[config.field] === null
148
+ ? ''
149
+ : String(instruction[config.field])));
150
+ case ConfigType.Tile:
151
+ case ConfigType.Shape:
152
+ case ConfigType.Grid:
153
+ return (config.field +
154
+ '=' +
155
+ escape(this.stringifyGrid(instruction[config.field])));
156
+ case ConfigType.NullableGrid:
157
+ return (config.field +
158
+ '=' +
159
+ escape(instruction[config.field] === null
160
+ ? ''
161
+ : this.stringifyGrid(instruction[config.field])));
162
+ case ConfigType.ControlLines:
163
+ return (config.field +
164
+ '=' +
165
+ escape(instruction[config.field]
166
+ .map(line => this.stringifyControlLine(line))
167
+ .join(':')));
168
+ case ConfigType.SolvePath:
169
+ return (config.field +
170
+ '=' +
171
+ escape(instruction[config.field]
172
+ ?.map(pos => `${pos.x}_${pos.y}`)
173
+ .join('/') ?? ''));
174
+ }
175
+ }
176
+ parseConfig(configs, entry) {
177
+ const [key, value] = entry.split('=');
178
+ const config = configs.find(x => x.field === key);
179
+ if (!config) {
180
+ console.warn(`Unknown config: ${key} when parsing ${entry}`);
181
+ return [key, value];
182
+ }
183
+ switch (config.type) {
184
+ case ConfigType.Boolean:
185
+ return [config.field, value === '1'];
186
+ case ConfigType.NullableBoolean:
187
+ return [config.field, value === '' ? null : value === '1'];
188
+ case ConfigType.Number:
189
+ return [config.field, Number(value)];
190
+ case ConfigType.NullableNumber:
191
+ return [config.field, value === '' ? null : Number(value)];
192
+ case ConfigType.Color:
193
+ return [config.field, value];
194
+ case ConfigType.Comparison:
195
+ return [config.field, value];
196
+ case ConfigType.Wrapping:
197
+ return [config.field, value];
198
+ case ConfigType.Direction:
199
+ return [config.field, value];
200
+ case ConfigType.DirectionToggle: {
201
+ const toggle = directionToggle();
202
+ for (const dir of DIRECTIONS) {
203
+ toggle[dir] = value.includes(orientationChars[dir]);
204
+ }
205
+ return [config.field, toggle];
206
+ }
207
+ case ConfigType.Orientation:
208
+ return [config.field, value];
209
+ case ConfigType.OrientationToggle: {
210
+ const toggle = orientationToggle();
211
+ for (const dir of ORIENTATIONS) {
212
+ toggle[dir] = value.includes(orientationChars[dir]);
213
+ }
214
+ return [config.field, toggle];
215
+ }
216
+ case ConfigType.String:
217
+ case ConfigType.Icon:
218
+ return [config.field, unescape(value)];
219
+ case ConfigType.Tile:
220
+ case ConfigType.Shape:
221
+ case ConfigType.Grid:
222
+ return [config.field, this.parseGrid(unescape(value))];
223
+ case ConfigType.NullableGrid:
224
+ return [
225
+ config.field,
226
+ value === '' ? null : this.parseGrid(unescape(value)),
227
+ ];
228
+ case ConfigType.ControlLines:
229
+ return [
230
+ config.field,
231
+ unescape(value)
232
+ .split(':')
233
+ .map(line => this.parseControlLine(line)),
234
+ ];
235
+ case ConfigType.NullableNote:
236
+ return [config.field, value === '' ? null : unescape(value)];
237
+ case ConfigType.NullableInstrument:
238
+ return [
239
+ config.field,
240
+ value === '' ? null : unescape(value),
241
+ ];
242
+ case ConfigType.SolvePath:
243
+ return [
244
+ config.field,
245
+ value === ''
246
+ ? []
247
+ : value.split('/').map(pos => {
248
+ const [x, y] = pos.split('_');
249
+ return { x: Number(x), y: Number(y) };
250
+ }),
251
+ ];
252
+ }
253
+ }
254
+ stringifyInstruction(instruction) {
255
+ return `${instruction.id},${instruction.configs?.map(config => this.stringifyConfig(instruction, config)).join(',') ?? ''}`;
256
+ }
257
+ stringifyRule(rule) {
258
+ return this.stringifyInstruction(rule);
259
+ }
260
+ stringifySymbol(symbol) {
261
+ return this.stringifyInstruction(symbol);
262
+ }
263
+ parseRule(str) {
264
+ const [id, ...entries] = str.split(',');
265
+ const instruction = allRules.get(id);
266
+ if (!instruction)
267
+ throw new Error(`Unknown rule: ${id}`);
268
+ const configs = instruction.configs;
269
+ if (configs == null)
270
+ return instruction.copyWith({});
271
+ return instruction.copyWith(Object.fromEntries(entries
272
+ .filter(entry => entry !== '')
273
+ .map(entry => this.parseConfig(configs, entry))));
274
+ }
275
+ parseSymbol(str) {
276
+ const [id, ...entries] = str.split(',');
277
+ const instruction = allSymbols.get(id);
278
+ if (!instruction)
279
+ throw new Error(`Unknown symbol: ${id}`);
280
+ const configs = instruction.configs;
281
+ if (configs == null)
282
+ return instruction.copyWith({});
283
+ return instruction.copyWith(Object.fromEntries(entries.map(entry => this.parseConfig(configs, entry))));
284
+ }
285
+ stringifyConnections(connections) {
286
+ const maxX = connections.edges.reduce((max, edge) => Math.max(max, edge.x1, edge.x2), 0);
287
+ const maxY = connections.edges.reduce((max, edge) => Math.max(max, edge.y1, edge.y2), 0);
288
+ const result = array(maxX + 1, maxY + 1, () => '.');
289
+ for (let y = 0; y <= maxY; y++) {
290
+ for (let x = 0; x <= maxX; x++) {
291
+ if (result[y][x] !== '.') {
292
+ continue;
293
+ }
294
+ const tiles = connections.getConnectedTiles({ x, y });
295
+ if (tiles.length < 2) {
296
+ continue;
297
+ }
298
+ const existingChars = [];
299
+ for (const { x: tx, y: ty } of tiles) {
300
+ for (const { x: dx, y: dy } of OFFSETS) {
301
+ if (tx + dx > maxX ||
302
+ ty + dy > maxY ||
303
+ tx + dx < 0 ||
304
+ ty + dy < 0) {
305
+ continue;
306
+ }
307
+ if (result[ty + dy][tx + dx] !== '.')
308
+ existingChars.push(result[ty + dy][tx + dx]);
309
+ }
310
+ }
311
+ let char = 'A';
312
+ while (existingChars.includes(char)) {
313
+ char = String.fromCharCode(char.charCodeAt(0) + 1);
314
+ }
315
+ for (const connection of tiles) {
316
+ result[connection.y][connection.x] = char;
317
+ }
318
+ }
319
+ }
320
+ return `C${maxX + 1}:${result.map(row => row.join('')).join('')}`.replace(/\.+$/, '');
321
+ }
322
+ parseConnections(input) {
323
+ if (!input.startsWith('C')) {
324
+ throw new Error('Invalid grid connections\n' + input);
325
+ }
326
+ const [size, data] = input.slice(1).split(':');
327
+ const width = Number(size);
328
+ const tiles = array(width, Math.ceil(data.length / width), (x, y) => data[y * width + x]);
329
+ return GridConnections.create(tiles.map(row => row.join('')));
330
+ }
331
+ stringifyZones(zones) {
332
+ return `Z${zones.edges.map(edge => `${edge.x1}_${edge.y1}_${edge.x2 - edge.x1}_${edge.y2 - edge.y1}`).join(':')}`;
333
+ }
334
+ parseZones(input) {
335
+ if (!input.startsWith('Z')) {
336
+ throw new Error('Invalid grid zones\n' + input);
337
+ }
338
+ const data = input.slice(1).split(':');
339
+ return new GridZones(data.map(entry => {
340
+ const [x1, y1, w, h] = entry.split('_').map(Number);
341
+ return { x1, y1, x2: x1 + w, y2: y1 + h };
342
+ }));
343
+ }
344
+ stringifyTiles(tiles) {
345
+ return `T${tiles[0]?.length ?? 0}:${tiles.map(row => row.map(tile => this.stringifyTile(tile)).join('')).join('')}`;
346
+ }
347
+ parseTiles(input) {
348
+ if (!input.startsWith('T')) {
349
+ throw new Error('Invalid grid data\n' + input);
350
+ }
351
+ const [size, data] = input.slice(1).split(':');
352
+ const width = Number(size);
353
+ return array(width, Math.ceil(data.length / width), (x, y) => this.parseTile(data.charAt(y * width + x)));
354
+ }
355
+ stringifyRules(rules) {
356
+ return `R${rules.map(rule => this.stringifyRule(rule)).join(':')}`;
357
+ }
358
+ parseRules(input) {
359
+ if (!input.startsWith('R')) {
360
+ throw new Error('Invalid rules\n' + input);
361
+ }
362
+ return input
363
+ .slice(1)
364
+ .split(':')
365
+ .filter(rule => rule !== '')
366
+ .map(rule => this.parseRule(rule));
367
+ }
368
+ stringifySymbols(symbols) {
369
+ return `S${Array.from(symbols.values())
370
+ .flat()
371
+ .map(symbol => this.stringifySymbol(symbol))
372
+ .join(':')}`;
373
+ }
374
+ parseSymbols(input) {
375
+ if (!input.startsWith('S')) {
376
+ throw new Error('Invalid symbols\n' + input);
377
+ }
378
+ const symbols = new Map();
379
+ input
380
+ .slice(1)
381
+ .split(':')
382
+ .filter(symbol => symbol !== '')
383
+ .forEach(symbol => {
384
+ const parsed = this.parseSymbol(symbol);
385
+ if (symbols.has(parsed.id)) {
386
+ symbols.set(parsed.id, [...symbols.get(parsed.id), parsed]);
387
+ }
388
+ else {
389
+ symbols.set(parsed.id, [parsed]);
390
+ }
391
+ });
392
+ return symbols;
393
+ }
394
+ stringifyGrid(grid) {
395
+ const data = [
396
+ this.stringifyTiles(grid.tiles),
397
+ this.stringifyConnections(grid.connections),
398
+ this.stringifyZones(grid.zones),
399
+ this.stringifySymbols(grid.symbols),
400
+ this.stringifyRules(grid.rules),
401
+ ];
402
+ return `${grid.width}x${grid.height}|${data.join('|')}`;
403
+ }
404
+ parseGrid(input) {
405
+ const data = input.split('|');
406
+ let width;
407
+ let height;
408
+ let tiles;
409
+ let connections;
410
+ let zones;
411
+ let symbols;
412
+ let rules;
413
+ for (const d of data) {
414
+ if (/^\d+x\d+$/.test(d)) {
415
+ [width, height] = d.split('x').map(Number);
416
+ }
417
+ else if (d.startsWith('T')) {
418
+ tiles = this.parseTiles(d);
419
+ }
420
+ else if (d.startsWith('C')) {
421
+ connections = this.parseConnections(d);
422
+ }
423
+ else if (d.startsWith('Z')) {
424
+ zones = this.parseZones(d);
425
+ }
426
+ else if (d.startsWith('S')) {
427
+ symbols = this.parseSymbols(d);
428
+ }
429
+ else if (d.startsWith('R')) {
430
+ rules = this.parseRules(d);
431
+ }
432
+ else {
433
+ throw new Error(`Invalid data: ${d}`);
434
+ }
435
+ }
436
+ return GridData.create(width ?? tiles?.[0].length ?? 0, height ?? tiles?.length ?? 0, tiles, connections, zones, symbols, rules);
437
+ }
438
+ stringifyGridWithSolution(puzzle) {
439
+ let grid = puzzle.grid;
440
+ if (puzzle.solution !== null) {
441
+ const tiles = array(puzzle.grid.width, puzzle.grid.height, (x, y) => {
442
+ const tile = puzzle.grid.getTile(x, y);
443
+ const solutionTile = puzzle.solution.getTile(x, y);
444
+ return tile.exists &&
445
+ !tile.fixed &&
446
+ solutionTile.exists &&
447
+ solutionTile.color !== Color.Gray
448
+ ? tile.copyWith({
449
+ color: puzzle.solution.tiles[y][x].color,
450
+ })
451
+ : tile;
452
+ });
453
+ grid = puzzle.grid.copyWith({ tiles });
454
+ }
455
+ return this.stringifyGrid(grid);
456
+ }
457
+ parseGridWithSolution(input) {
458
+ const grid = this.parseGrid(input);
459
+ const reset = grid.resetTiles();
460
+ return {
461
+ grid: reset,
462
+ solution: grid.colorEquals(reset) ? null : grid,
463
+ };
464
+ }
465
+ stringifyPuzzle(puzzle) {
466
+ return JSON.stringify({
467
+ title: puzzle.title,
468
+ grid: this.stringifyGridWithSolution(puzzle),
469
+ difficulty: puzzle.difficulty,
470
+ author: puzzle.author,
471
+ description: puzzle.description,
472
+ });
473
+ }
474
+ parsePuzzle(input) {
475
+ const { grid: gridString, title, author, description, difficulty, } = JSON.parse(input);
476
+ return {
477
+ title,
478
+ author,
479
+ description,
480
+ difficulty,
481
+ ...this.parseGridWithSolution(gridString),
482
+ };
483
+ }
484
+ }
@@ -0,0 +1,19 @@
1
+ import GridData from './grid.js';
2
+ import { Color, Position } from './primitives.js';
3
+ import TileData from './tile.js';
4
+ export interface ShapeElement {
5
+ x: number;
6
+ y: number;
7
+ color: Color;
8
+ }
9
+ export interface Shape {
10
+ width: number;
11
+ height: number;
12
+ elements: ShapeElement[];
13
+ }
14
+ export declare function shapeEquals(a: Shape, b: Shape): boolean;
15
+ export declare function tilesToShape(tiles: readonly (readonly TileData[])[]): Shape;
16
+ export declare function positionsToShape(positions: Position[], color: Color): Shape;
17
+ export declare function getShapeVariants(shape: Shape): Shape[];
18
+ export declare function normalizeShape(shape: Shape): Shape;
19
+ export declare function sanitizePatternGrid(pattern: GridData, tileMapper?: (tile: TileData) => TileData): GridData;
@@ -0,0 +1,137 @@
1
+ import GridConnections from './gridConnections.js';
2
+ import GridZones from './gridZones.js';
3
+ import { Color } from './primitives.js';
4
+ const colorIndex = {
5
+ [Color.Dark]: 2,
6
+ [Color.Light]: 1,
7
+ [Color.Gray]: 0,
8
+ };
9
+ function compareColor(a, b) {
10
+ return colorIndex[a] - colorIndex[b];
11
+ }
12
+ function compareElement(a, b) {
13
+ if (!a && !b)
14
+ return 0;
15
+ if (!a)
16
+ return -1;
17
+ if (!b)
18
+ return 1;
19
+ return a.y - b.y || a.x - b.x || compareColor(a.color, b.color);
20
+ }
21
+ function compareShape(a, b) {
22
+ for (let i = 0; i < Math.max(a.elements.length, b.elements.length); i++) {
23
+ const cmp = compareElement(a.elements[i], b.elements[i]);
24
+ if (cmp !== 0)
25
+ return cmp;
26
+ }
27
+ return 0;
28
+ }
29
+ export function shapeEquals(a, b) {
30
+ return compareShape(a, b) === 0;
31
+ }
32
+ function recenterShape(shape) {
33
+ let minX = Number.POSITIVE_INFINITY;
34
+ let minY = Number.POSITIVE_INFINITY;
35
+ let maxX = Number.NEGATIVE_INFINITY;
36
+ let maxY = Number.NEGATIVE_INFINITY;
37
+ for (const element of shape.elements) {
38
+ minX = Math.min(minX, element.x);
39
+ minY = Math.min(minY, element.y);
40
+ maxX = Math.max(maxX, element.x);
41
+ maxY = Math.max(maxY, element.y);
42
+ }
43
+ for (const element of shape.elements) {
44
+ element.x -= minX;
45
+ element.y -= minY;
46
+ }
47
+ shape.width = maxX - minX + 1;
48
+ shape.height = maxY - minY + 1;
49
+ if (!Number.isFinite(shape.width)) {
50
+ shape.width = 0;
51
+ }
52
+ if (!Number.isFinite(shape.height)) {
53
+ shape.height = 0;
54
+ }
55
+ return shape;
56
+ }
57
+ export function tilesToShape(tiles) {
58
+ const shape = {
59
+ width: Math.max(...tiles.map(row => row.length)),
60
+ height: tiles.length,
61
+ elements: [],
62
+ };
63
+ for (let y = 0; y < tiles.length; y++) {
64
+ for (let x = 0; x < tiles[y].length; x++) {
65
+ const tile = tiles[y][x];
66
+ if (tile.exists && tile.color !== Color.Gray) {
67
+ shape.elements.push({ x, y, color: tile.color });
68
+ }
69
+ }
70
+ }
71
+ return recenterShape(shape);
72
+ }
73
+ export function positionsToShape(positions, color) {
74
+ return recenterShape({
75
+ width: 0,
76
+ height: 0,
77
+ elements: positions.map(p => ({ x: p.x, y: p.y, color })),
78
+ });
79
+ }
80
+ const shapeVariants = [
81
+ { x: 'x', y: 'y' },
82
+ { x: '-y', y: 'x' },
83
+ { x: '-x', y: '-y' },
84
+ { x: 'y', y: '-x' },
85
+ { x: '-x', y: 'y' },
86
+ { x: 'x', y: '-y' },
87
+ { x: 'y', y: 'x' },
88
+ { x: '-y', y: '-x' },
89
+ ];
90
+ function mapCoord(map, x, y, width, height) {
91
+ switch (map) {
92
+ case 'x':
93
+ return x;
94
+ case 'y':
95
+ return y;
96
+ case '-x':
97
+ return width - 1 - x;
98
+ case '-y':
99
+ return height - 1 - y;
100
+ }
101
+ }
102
+ export function getShapeVariants(shape) {
103
+ const variants = shapeVariants.map(({ x, y }) => ({
104
+ width: x.endsWith('x') ? shape.width : shape.height,
105
+ height: y.endsWith('y') ? shape.height : shape.width,
106
+ elements: shape.elements
107
+ .map(element => ({
108
+ x: mapCoord(x, element.x, element.y, shape.width, shape.height),
109
+ y: mapCoord(y, element.x, element.y, shape.width, shape.height),
110
+ color: element.color,
111
+ }))
112
+ .sort(compareElement),
113
+ }));
114
+ const uniqueVariants = [];
115
+ for (const variant of variants) {
116
+ if (!uniqueVariants.some(shape => shapeEquals(shape, variant))) {
117
+ uniqueVariants.push(variant);
118
+ }
119
+ }
120
+ return uniqueVariants;
121
+ }
122
+ export function normalizeShape(shape) {
123
+ const variants = getShapeVariants(shape);
124
+ return variants.reduce((min, variant) => (compareShape(variant, min) < 0 ? variant : min), variants[0]);
125
+ }
126
+ export function sanitizePatternGrid(pattern, tileMapper = t => t) {
127
+ return (pattern
128
+ // unlock all tiles
129
+ .withTiles(tiles => tiles.map(row => row.map(t => tileMapper(t.exists
130
+ ? t.withFixed(false)
131
+ : t.copyWith({ exists: true, color: Color.Gray, fixed: false })))))
132
+ // strip all symbols and rules
133
+ .withRules([])
134
+ .withSymbols(new Map())
135
+ .withConnections(new GridConnections())
136
+ .withZones(new GridZones()));
137
+ }
@@ -0,0 +1,3 @@
1
+ import Solver from './solver.js';
2
+ declare const allSolvers: Map<string, Solver>;
3
+ export { allSolvers };
@@ -0,0 +1,13 @@
1
+ import UniversalSolver from './universal/universalSolver.js';
2
+ import BacktrackSolver from './backtrack/backtrackSolver.js';
3
+ import CspuzSolver from './cspuz/cspuzSolver.js';
4
+ import AutoSolver from './auto/autoSolver.js';
5
+ const allSolvers = new Map();
6
+ function register(prototype) {
7
+ allSolvers.set(prototype.id, prototype);
8
+ }
9
+ register(new AutoSolver());
10
+ register(new CspuzSolver());
11
+ register(new BacktrackSolver());
12
+ register(new UniversalSolver());
13
+ export { allSolvers };
@@ -0,0 +1,18 @@
1
+ import GridData from '../../grid.js';
2
+ import Solver from '../solver.js';
3
+ import Instruction from '../../instruction.js';
4
+ export default class AutoSolver extends Solver {
5
+ readonly id = "auto";
6
+ readonly author = "various contributors";
7
+ readonly description = "Automatically select the fastest solver based on supported instructions and environment.";
8
+ readonly supportsCancellation = true;
9
+ private static readonly nonAdditiveInstructions;
10
+ isGridSupported(grid: GridData): boolean;
11
+ isInstructionSupported(grid: GridData, instruction: Instruction): boolean;
12
+ protected isEnvironmentSupported(): Promise<boolean>;
13
+ private fillSolution;
14
+ private fixGrid;
15
+ private solveWithProgress;
16
+ private solveOne;
17
+ solve(grid: GridData, abortSignal?: AbortSignal): AsyncGenerator<GridData | null>;
18
+ }