@logic-pad/core 0.23.0 → 0.23.2

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.
package/README.md CHANGED
@@ -8,7 +8,7 @@ This package is part of Logic Pad. [Bun >=v1.1.0](https://bun.sh/) is required f
8
8
 
9
9
  ```bash
10
10
  # 1. Clone this repository
11
- git clone https://github.com/hlysine/logic-pad.git
11
+ git clone https://github.com/logic-pad/logic-pad.git
12
12
 
13
13
  # 2. Restore dependencies
14
14
  cd logic-pad
@@ -2333,6 +2333,9 @@ declare global {
2333
2333
  * first iteration indicates that the grid is unsolvable. Yielding `null` on the second iteration indicates that the
2334
2334
  * solution is unique.
2335
2335
  *
2336
+ * If the solve finds the trivial solution of not filling any tiles, such as in the case of an underclued grid with
2337
+ * too many alternate solutions, it must yield the solution instead of yielding `null`.
2338
+ *
2336
2339
  * In the current UI implementation, the solver will be terminated after yielding `null`, or after 2 iterations if
2337
2340
  * `null` is never yielded. The solver should perform any necessary cleanup in the `finally` block of the generator.
2338
2341
  *
@@ -116,7 +116,6 @@ export function resize(array, newSize, defaultValue) {
116
116
  * @param values The values to compare.
117
117
  * @returns Whether all the values are equal.
118
118
  */
119
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
120
119
  export function allEqual(...values) {
121
120
  return values.every(value => value === values[0]);
122
121
  }
@@ -1,4 +1,3 @@
1
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
2
1
  export function isEventHandler(val, event) {
3
2
  if (typeof val !== 'object' || val === null || val === undefined)
4
3
  return false;
package/dist/data/grid.js CHANGED
@@ -924,34 +924,97 @@ export default class GridData {
924
924
  newTiles[origin.y + y][origin.x + x] = tile;
925
925
  });
926
926
  const connections = new GridConnections([
927
- ...this.connections.edges,
928
- ...grid.connections.edges.map(edge => ({
927
+ ...this.connections.edges.filter(edge => edge.x1 < origin.x ||
928
+ edge.y1 < origin.y ||
929
+ edge.x2 < origin.x ||
930
+ edge.y2 < origin.y ||
931
+ edge.x1 >= origin.x + grid.width ||
932
+ edge.y1 >= origin.y + grid.height ||
933
+ edge.x2 >= origin.x + grid.width ||
934
+ edge.y2 >= origin.y + grid.height),
935
+ ...grid.connections.edges
936
+ .map(edge => ({
929
937
  x1: edge.x1 + origin.x,
930
938
  y1: edge.y1 + origin.y,
931
939
  x2: edge.x2 + origin.x,
932
940
  y2: edge.y2 + origin.y,
933
- })),
941
+ }))
942
+ .filter(edge => edge.x1 >= 0 &&
943
+ edge.y1 >= 0 &&
944
+ edge.x2 >= 0 &&
945
+ edge.y2 >= 0 &&
946
+ edge.x1 < this.width &&
947
+ edge.y1 < this.height &&
948
+ edge.x2 < this.width &&
949
+ edge.y2 < this.height),
934
950
  ]);
935
951
  const zones = new GridZones([
936
- ...this.zones.edges,
937
- ...grid.zones.edges.map(edge => ({
952
+ ...this.zones.edges.filter(edge => edge.x1 < origin.x ||
953
+ edge.y1 < origin.y ||
954
+ edge.x2 < origin.x ||
955
+ edge.y2 < origin.y ||
956
+ edge.x1 >= origin.x + grid.width ||
957
+ edge.y1 >= origin.y + grid.height ||
958
+ edge.x2 >= origin.x + grid.width ||
959
+ edge.y2 >= origin.y + grid.height),
960
+ ...grid.zones.edges
961
+ .map(edge => ({
938
962
  x1: edge.x1 + origin.x,
939
963
  y1: edge.y1 + origin.y,
940
964
  x2: edge.x2 + origin.x,
941
965
  y2: edge.y2 + origin.y,
942
- })),
966
+ }))
967
+ .filter(edge => edge.x1 >= 0 &&
968
+ edge.y1 >= 0 &&
969
+ edge.x2 >= 0 &&
970
+ edge.y2 >= 0 &&
971
+ edge.x1 < this.width &&
972
+ edge.y1 < this.height &&
973
+ edge.x2 < this.width &&
974
+ edge.y2 < this.height),
943
975
  ]);
944
976
  const symbols = new Map(this.symbols);
945
977
  for (const [id, sourceList] of grid.symbols) {
946
- const symbolList = sourceList.map(symbol => symbol.copyWith({ x: symbol.x + origin.x, y: symbol.y + origin.y }));
978
+ const symbolList = sourceList
979
+ .filter(symbol => symbol.x + origin.x >= 0 &&
980
+ symbol.y + origin.y >= 0 &&
981
+ symbol.x + origin.x < this.width &&
982
+ symbol.y + origin.y < this.height)
983
+ .map(symbol => symbol.copyWith({ x: symbol.x + origin.x, y: symbol.y + origin.y }));
947
984
  if (symbols.has(id)) {
948
- symbols.set(id, [...symbols.get(id), ...symbolList]);
985
+ const newList = [
986
+ ...symbols
987
+ .get(id)
988
+ .filter(symbol => symbol.x < origin.x ||
989
+ symbol.y < origin.y ||
990
+ symbol.x >= origin.x + grid.width ||
991
+ symbol.y >= origin.y + grid.height),
992
+ ...symbolList,
993
+ ];
994
+ if (newList.length > 0)
995
+ symbols.set(id, newList);
996
+ else
997
+ symbols.delete(id);
949
998
  }
950
- else {
999
+ else if (symbolList.length > 0) {
951
1000
  symbols.set(id, symbolList);
952
1001
  }
953
1002
  }
954
- const rules = [...this.rules, ...grid.rules];
1003
+ for (const id of [...symbols.keys()]) {
1004
+ if (grid.symbols.has(id))
1005
+ continue;
1006
+ const newList = symbols
1007
+ .get(id)
1008
+ .filter(symbol => symbol.x < origin.x ||
1009
+ symbol.y < origin.y ||
1010
+ symbol.x >= origin.x + grid.width ||
1011
+ symbol.y >= origin.y + grid.height);
1012
+ if (newList.length > 0)
1013
+ symbols.set(id, newList);
1014
+ else
1015
+ symbols.delete(id);
1016
+ }
1017
+ const rules = GridData.deduplicateRules([...this.rules, ...grid.rules]);
955
1018
  return this.copyWith({
956
1019
  tiles: newTiles,
957
1020
  connections,
@@ -27,7 +27,6 @@ export default class StreamCompressor extends CompressorBase {
27
27
  }
28
28
  async decompress(input) {
29
29
  await ensureCompressionStream();
30
- // eslint-disable-next-line @typescript-eslint/no-deprecated
31
30
  const bytes = Uint8Array.from(atob(input), c => c.charCodeAt(0));
32
31
  const cs = new DecompressionStream(this.algorithm);
33
32
  const writer = cs.writable.getWriter();
@@ -97,7 +97,6 @@ class AutoSolver extends Solver {
97
97
  }
98
98
  }
99
99
  async solveOne(generator) {
100
- // eslint-disable-next-line no-unreachable-loop
101
100
  for await (const grid of generator) {
102
101
  return grid;
103
102
  }
@@ -293,12 +293,12 @@ onmessage = e => {
293
293
  let count = 0;
294
294
  solve(grid, solution => {
295
295
  // if (count === 0) console.timeLog('Solve time', 'First solution');
296
- if (solution) {
297
- if (solution.resetTiles().colorEquals(solution)) {
298
- postMessage(null);
299
- return false;
300
- }
301
- }
296
+ // if (solution) {
297
+ // if (solution.resetTiles().colorEquals(solution)) {
298
+ // postMessage(null);
299
+ // return false;
300
+ // }
301
+ // }
302
302
  postMessage(Serializer.stringifyGrid(solution));
303
303
  count += 1;
304
304
  return count < 2;
@@ -78,9 +78,8 @@ class CspuzSolver extends EventIteratingSolver {
78
78
  }
79
79
  async isEnvironmentSupported() {
80
80
  try {
81
- const abortController = new AbortController();
82
- for await (const _ of this.solve(GridData.create(['.']), abortController.signal)) {
83
- abortController.abort();
81
+ for await (const _ of this.solve(GridData.create(['.']))) {
82
+ // do nothing
84
83
  }
85
84
  return true;
86
85
  }
@@ -30,12 +30,7 @@ function postSolution(grid, solverResult) {
30
30
  }
31
31
  return tiles;
32
32
  });
33
- if (solution.resetTiles().colorEquals(solution)) {
34
- postMessage(null);
35
- }
36
- else {
37
- postMessage(Serializer.stringifyGrid(solution));
38
- }
33
+ postMessage(Serializer.stringifyGrid(solution));
39
34
  }
40
35
  }
41
36
  onmessage = e => {
@@ -32,6 +32,9 @@ export default abstract class Solver {
32
32
  * first iteration indicates that the grid is unsolvable. Yielding `null` on the second iteration indicates that the
33
33
  * solution is unique.
34
34
  *
35
+ * If the solve finds the trivial solution of not filling any tiles, such as in the case of an underclued grid with
36
+ * too many alternate solutions, it must yield the solution instead of yielding `null`.
37
+ *
35
38
  * In the current UI implementation, the solver will be terminated after yielding `null`, or after 2 iterations if
36
39
  * `null` is never yielded. The solver should perform any necessary cleanup in the `finally` block of the generator.
37
40
  *
@@ -115,11 +115,11 @@ onmessage = e => {
115
115
  const grid = Serializer.parseGrid(e.data);
116
116
  let count = 0;
117
117
  solve(grid, solution => {
118
- if (solution) {
119
- if (solution.resetTiles().colorEquals(solution)) {
120
- solution = null;
121
- }
122
- }
118
+ // if (solution) {
119
+ // if (solution.resetTiles().colorEquals(solution)) {
120
+ // solution = null;
121
+ // }
122
+ // }
123
123
  postMessage(solution ? Serializer.stringifyGrid(solution) : null);
124
124
  count += 1;
125
125
  return count < 2;
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@logic-pad/core",
3
- "version": "0.23.0",
3
+ "version": "0.23.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
7
7
  "assets"
8
8
  ],
9
- "homepage": "https://github.com/hlysine/logic-pad",
9
+ "homepage": "https://github.com/logic-pad/logic-pad",
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "https://github.com/hlysine/logic-pad.git"
12
+ "url": "https://github.com/logic-pad/logic-pad.git"
13
13
  },
14
14
  "keywords": [
15
15
  "logic",
@@ -42,13 +42,13 @@
42
42
  },
43
43
  "scripts": {
44
44
  "build": "rimraf dist/ && bun run codegen && bunx --bun tsc && bun run typegen",
45
- "lint": "cd ../../ && eslint ./packages/logic-core --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
46
45
  "codegen": "bun ./scripts/genImports.ts && bun ./scripts/genEntry.ts",
47
46
  "typegen": "bun ./scripts/genTypes.ts",
48
47
  "prepublishOnly": "bun run build"
49
48
  },
50
49
  "engines": {
51
- "bun": ">=1.1.0"
50
+ "bun": ">=1.1.0",
51
+ "node": ">=23.11.0"
52
52
  },
53
53
  "dependencies": {
54
54
  "compression-streams-polyfill": "^0.1.7",