@logic-pad/core 0.4.2 → 0.4.5
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/assets/logic-core.global.d.ts +37 -20
- package/dist/data/events/onSetGrid.d.ts +1 -0
- package/dist/data/events/onSetGrid.js +15 -0
- package/dist/data/events/onSymbolDisplay.d.ts +2 -1
- package/dist/data/grid.d.ts +0 -8
- package/dist/data/grid.js +0 -23
- package/dist/data/instruction.d.ts +5 -0
- package/dist/data/primitives.d.ts +2 -1
- package/dist/data/primitives.js +1 -0
- package/dist/data/rules/cellCountPerZoneRule.d.ts +1 -1
- package/dist/data/rules/cellCountPerZoneRule.js +7 -2
- package/dist/data/rules/foresightRule.d.ts +2 -1
- package/dist/data/rules/foresightRule.js +8 -1
- package/dist/data/rules/musicControlLine.js +1 -1
- package/dist/data/rules/musicGridRule.d.ts +5 -2
- package/dist/data/rules/musicGridRule.js +26 -11
- package/dist/data/rules/perfectionRule.d.ts +11 -3
- package/dist/data/rules/perfectionRule.js +69 -13
- package/dist/data/rules/rule.d.ts +2 -1
- package/dist/data/rules/rule.js +3 -0
- package/dist/data/serializer/serializer_v0.js +4 -2
- package/dist/data/symbols/hiddenSymbol.d.ts +5 -9
- package/dist/data/symbols/hiddenSymbol.js +19 -29
- package/dist/data/symbols/symbol.d.ts +3 -2
- package/dist/data/symbols/symbol.js +3 -0
- package/dist/data/validate.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/assets/z3-built.js +0 -14723
- package/assets/z3-built.wasm +0 -0
- package/assets/z3-built.worker.js +0 -206
|
@@ -111,6 +111,7 @@ declare global {
|
|
|
111
111
|
export declare enum Mode {
|
|
112
112
|
Create = 'create',
|
|
113
113
|
Solve = 'solve',
|
|
114
|
+
Perfection = 'perfection',
|
|
114
115
|
}
|
|
115
116
|
export declare class GridZones {
|
|
116
117
|
readonly edges: readonly Edge[];
|
|
@@ -320,6 +321,10 @@ declare global {
|
|
|
320
321
|
get validateWithSolution(): boolean;
|
|
321
322
|
get necessaryForCompletion(): boolean;
|
|
322
323
|
get visibleWhenSolving(): boolean;
|
|
324
|
+
/**
|
|
325
|
+
* Return a variant of this instruction that is suitable for the given mode.
|
|
326
|
+
*/
|
|
327
|
+
abstract modeVariant(mode: Mode): Instruction | null;
|
|
323
328
|
/**
|
|
324
329
|
* Check if this instruction is equal to another instruction by comparing their IDs and configs.
|
|
325
330
|
*
|
|
@@ -336,6 +341,7 @@ declare global {
|
|
|
336
341
|
abstract validateGrid(grid: GridData): RuleState;
|
|
337
342
|
abstract get searchVariants(): SearchVariant[];
|
|
338
343
|
searchVariant(): SearchVariant;
|
|
344
|
+
modeVariant(_mode: Mode): Rule | null;
|
|
339
345
|
/**
|
|
340
346
|
* Whether only one instance of this rule is allowed in a grid.
|
|
341
347
|
*/
|
|
@@ -362,7 +368,8 @@ declare global {
|
|
|
362
368
|
readonly x: number;
|
|
363
369
|
readonly y: number;
|
|
364
370
|
constructor(x: number, y: number);
|
|
365
|
-
abstract validateSymbol(grid: GridData): State;
|
|
371
|
+
abstract validateSymbol(grid: GridData, solution: GridData | null): State;
|
|
372
|
+
modeVariant(_mode: Mode): Symbol$1 | null;
|
|
366
373
|
onGridResize(
|
|
367
374
|
_grid: GridData,
|
|
368
375
|
mode: 'insert' | 'remove',
|
|
@@ -426,6 +433,11 @@ declare global {
|
|
|
426
433
|
export declare function handlesSetGrid<T extends Instruction>(
|
|
427
434
|
val: T
|
|
428
435
|
): val is T & SetGridHandler;
|
|
436
|
+
export declare function invokeSetGrid(
|
|
437
|
+
oldGrid: GridData,
|
|
438
|
+
newGrid: GridData,
|
|
439
|
+
solution: GridData | null
|
|
440
|
+
): GridData;
|
|
429
441
|
export declare class Row extends Configurable {
|
|
430
442
|
/**
|
|
431
443
|
* The note to play at this row, or null to keep the current note from the previous control line.
|
|
@@ -509,6 +521,7 @@ declare global {
|
|
|
509
521
|
{
|
|
510
522
|
readonly controlLines: readonly ControlLine[];
|
|
511
523
|
readonly track: GridData | null;
|
|
524
|
+
readonly normalizeVelocity: boolean;
|
|
512
525
|
private static readonly EXAMPLE_GRID;
|
|
513
526
|
private static readonly CONFIGS;
|
|
514
527
|
private static readonly SEARCH_VARIANTS;
|
|
@@ -516,8 +529,13 @@ declare global {
|
|
|
516
529
|
* **Music Grid: Listen to the solution**
|
|
517
530
|
* @param controlLines Denote changes in the playback settings. At least one control line at column 0 should be present to enable playback.
|
|
518
531
|
* @param track The grid to be played when "listen" is clicked. Set as null to play the solution.
|
|
532
|
+
* @param normalizeVelocity Whether to normalize the velocity of the notes by their pitch such that lower notes are played softer.
|
|
519
533
|
*/
|
|
520
|
-
constructor(
|
|
534
|
+
constructor(
|
|
535
|
+
controlLines: readonly ControlLine[],
|
|
536
|
+
track: GridData | null,
|
|
537
|
+
normalizeVelocity?: boolean
|
|
538
|
+
);
|
|
521
539
|
get id(): string;
|
|
522
540
|
get explanation(): string;
|
|
523
541
|
get configs(): readonly AnyConfig[] | null;
|
|
@@ -546,9 +564,11 @@ declare global {
|
|
|
546
564
|
copyWith({
|
|
547
565
|
controlLines,
|
|
548
566
|
track,
|
|
567
|
+
normalizeVelocity,
|
|
549
568
|
}: {
|
|
550
569
|
controlLines?: readonly ControlLine[];
|
|
551
570
|
track?: GridData | null;
|
|
571
|
+
normalizeVelocity?: boolean;
|
|
552
572
|
}): this;
|
|
553
573
|
get validateWithSolution(): boolean;
|
|
554
574
|
get isSingleton(): boolean;
|
|
@@ -980,14 +1000,6 @@ declare global {
|
|
|
980
1000
|
* @returns True if the grids are equal in size and tile colors, false otherwise.
|
|
981
1001
|
*/
|
|
982
1002
|
colorEquals(grid: GridData): boolean;
|
|
983
|
-
/**
|
|
984
|
-
* Check if this grid conforms to the given solution, or an incomplete version of the solution.
|
|
985
|
-
* Symbols and rules are not validated.
|
|
986
|
-
*
|
|
987
|
-
* @param solution The solution to compare with.
|
|
988
|
-
* @returns True if the grid conforms to the solution, false otherwise.
|
|
989
|
-
*/
|
|
990
|
-
solutionMatches(solution: GridData): boolean;
|
|
991
1003
|
/**
|
|
992
1004
|
* Check if this grid is equal to another grid in terms of size, tile colors, connections, symbols, and rules.
|
|
993
1005
|
*
|
|
@@ -1190,12 +1202,14 @@ declare global {
|
|
|
1190
1202
|
* Controls whether a symbol should be visible in the grid.
|
|
1191
1203
|
*
|
|
1192
1204
|
* @param grid The grid that is being displayed.
|
|
1205
|
+
* @param solution The solution grid, if it is available.
|
|
1193
1206
|
* @param symbol The symbol that is being displayed.
|
|
1194
1207
|
* @param editing Whether the grid is being edited.
|
|
1195
1208
|
* @returns True if the symbol should be displayed, false otherwise. The symbol will not be displayed if any handler returns false.
|
|
1196
1209
|
*/
|
|
1197
1210
|
onSymbolDisplay(
|
|
1198
1211
|
grid: GridData,
|
|
1212
|
+
solution: GridData | null,
|
|
1199
1213
|
symbol: Symbol$1,
|
|
1200
1214
|
editing: boolean
|
|
1201
1215
|
): boolean;
|
|
@@ -1368,7 +1382,7 @@ declare global {
|
|
|
1368
1382
|
private static readonly EXAMPLE_GRID_GRAY;
|
|
1369
1383
|
private static readonly SEARCH_VARIANTS;
|
|
1370
1384
|
/**
|
|
1371
|
-
* **
|
|
1385
|
+
* **Zones of the same size have the same number of <color> cells.**
|
|
1372
1386
|
*
|
|
1373
1387
|
* @param color - The color of the cells to count.
|
|
1374
1388
|
*/
|
|
@@ -1483,6 +1497,7 @@ declare global {
|
|
|
1483
1497
|
validateGrid(_grid: GridData): RuleState;
|
|
1484
1498
|
get necessaryForCompletion(): boolean;
|
|
1485
1499
|
get isSingleton(): boolean;
|
|
1500
|
+
modeVariant(mode: Mode): Rule | null;
|
|
1486
1501
|
copyWith({
|
|
1487
1502
|
count,
|
|
1488
1503
|
regenInterval,
|
|
@@ -1573,12 +1588,15 @@ declare global {
|
|
|
1573
1588
|
extends Rule
|
|
1574
1589
|
implements SetGridHandler, FinalValidationHandler
|
|
1575
1590
|
{
|
|
1591
|
+
readonly editor: boolean;
|
|
1576
1592
|
private static readonly EXAMPLE_GRID;
|
|
1577
1593
|
private static readonly SEARCH_VARIANTS;
|
|
1578
1594
|
/**
|
|
1579
1595
|
* **Quest for Perfection: cell colors are final**
|
|
1596
|
+
*
|
|
1597
|
+
* @param editor - whether to enable editor mode. This field is automatically set by the editor.
|
|
1580
1598
|
*/
|
|
1581
|
-
constructor();
|
|
1599
|
+
constructor(editor?: boolean);
|
|
1582
1600
|
get id(): string;
|
|
1583
1601
|
get explanation(): string;
|
|
1584
1602
|
get configs(): readonly AnyConfig[] | null;
|
|
@@ -1586,6 +1604,7 @@ declare global {
|
|
|
1586
1604
|
get searchVariants(): SearchVariant[];
|
|
1587
1605
|
get necessaryForCompletion(): boolean;
|
|
1588
1606
|
get isSingleton(): boolean;
|
|
1607
|
+
modeVariant(mode: Mode): Rule | null;
|
|
1589
1608
|
validateGrid(grid: GridData): RuleState;
|
|
1590
1609
|
/**
|
|
1591
1610
|
* If the grid passes validation but is different from the solution, indicate the error in the final state.
|
|
@@ -1596,6 +1615,8 @@ declare global {
|
|
|
1596
1615
|
state: GridState
|
|
1597
1616
|
): GridState;
|
|
1598
1617
|
private fixTiles;
|
|
1618
|
+
private isValid;
|
|
1619
|
+
private findSingleError;
|
|
1599
1620
|
/**
|
|
1600
1621
|
* Force all tiles to be fixed.
|
|
1601
1622
|
*
|
|
@@ -1606,7 +1627,7 @@ declare global {
|
|
|
1606
1627
|
newGrid: GridData,
|
|
1607
1628
|
solution: GridData | null
|
|
1608
1629
|
): GridData;
|
|
1609
|
-
copyWith(
|
|
1630
|
+
copyWith({ editor }: { editor?: boolean }): this;
|
|
1610
1631
|
}
|
|
1611
1632
|
export declare class RegionAreaRule extends Rule {
|
|
1612
1633
|
readonly color: Color;
|
|
@@ -6017,7 +6038,6 @@ declare global {
|
|
|
6017
6038
|
{
|
|
6018
6039
|
readonly x: number;
|
|
6019
6040
|
readonly y: number;
|
|
6020
|
-
readonly color: Color;
|
|
6021
6041
|
readonly revealLocation: boolean;
|
|
6022
6042
|
private static readonly CONFIGS;
|
|
6023
6043
|
private static readonly EXAMPLE_GRID;
|
|
@@ -6026,10 +6046,9 @@ declare global {
|
|
|
6026
6046
|
*
|
|
6027
6047
|
* @param x - The x-coordinate of the symbol.
|
|
6028
6048
|
* @param y - The y-coordinate of the symbol.
|
|
6029
|
-
* @param color - The target color of the cell.
|
|
6030
6049
|
* @param revealLocation - Whether to reveal the location of the symbol.
|
|
6031
6050
|
*/
|
|
6032
|
-
constructor(x: number, y: number,
|
|
6051
|
+
constructor(x: number, y: number, revealLocation?: boolean);
|
|
6033
6052
|
get id(): string;
|
|
6034
6053
|
get explanation(): string;
|
|
6035
6054
|
get configs(): readonly AnyConfig[] | null;
|
|
@@ -6037,24 +6056,22 @@ declare global {
|
|
|
6037
6056
|
get necessaryForCompletion(): boolean;
|
|
6038
6057
|
get visibleWhenSolving(): boolean;
|
|
6039
6058
|
get sortOrder(): number;
|
|
6040
|
-
validateSymbol(grid: GridData): State;
|
|
6059
|
+
validateSymbol(grid: GridData, solution: GridData | null): State;
|
|
6041
6060
|
onSymbolDisplay(
|
|
6042
6061
|
grid: GridData,
|
|
6062
|
+
solution: GridData | null,
|
|
6043
6063
|
symbol: Symbol$1,
|
|
6044
6064
|
editing: boolean
|
|
6045
6065
|
): boolean;
|
|
6046
6066
|
copyWith({
|
|
6047
6067
|
x,
|
|
6048
6068
|
y,
|
|
6049
|
-
color,
|
|
6050
6069
|
revealLocation,
|
|
6051
6070
|
}: {
|
|
6052
6071
|
x?: number;
|
|
6053
6072
|
y?: number;
|
|
6054
|
-
color?: Color;
|
|
6055
6073
|
revealLocation?: boolean;
|
|
6056
6074
|
}): this;
|
|
6057
|
-
withColor(color: Color): this;
|
|
6058
6075
|
withRevealLocation(revealLocation: boolean): this;
|
|
6059
6076
|
}
|
|
6060
6077
|
export declare const allSymbols: Map<string, Symbol$1>;
|
|
@@ -4,3 +4,4 @@ export interface SetGridHandler {
|
|
|
4
4
|
onSetGrid(oldGrid: GridData, newGrid: GridData, solution: GridData | null): GridData;
|
|
5
5
|
}
|
|
6
6
|
export declare function handlesSetGrid<T extends Instruction>(val: T): val is T & SetGridHandler;
|
|
7
|
+
export declare function invokeSetGrid(oldGrid: GridData, newGrid: GridData, solution: GridData | null): GridData;
|
|
@@ -2,3 +2,18 @@ import { isEventHandler } from './eventHelper.js';
|
|
|
2
2
|
export function handlesSetGrid(val) {
|
|
3
3
|
return isEventHandler(val, 'onSetGrid');
|
|
4
4
|
}
|
|
5
|
+
export function invokeSetGrid(oldGrid, newGrid, solution) {
|
|
6
|
+
newGrid.symbols.forEach(list => {
|
|
7
|
+
list.forEach(symbol => {
|
|
8
|
+
if (handlesSetGrid(symbol)) {
|
|
9
|
+
newGrid = symbol.onSetGrid(oldGrid, newGrid, solution);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
newGrid.rules.forEach(rule => {
|
|
14
|
+
if (handlesSetGrid(rule)) {
|
|
15
|
+
newGrid = rule.onSetGrid(oldGrid, newGrid, solution);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return newGrid;
|
|
19
|
+
}
|
|
@@ -6,10 +6,11 @@ export interface SymbolDisplayHandler {
|
|
|
6
6
|
* Controls whether a symbol should be visible in the grid.
|
|
7
7
|
*
|
|
8
8
|
* @param grid The grid that is being displayed.
|
|
9
|
+
* @param solution The solution grid, if it is available.
|
|
9
10
|
* @param symbol The symbol that is being displayed.
|
|
10
11
|
* @param editing Whether the grid is being edited.
|
|
11
12
|
* @returns True if the symbol should be displayed, false otherwise. The symbol will not be displayed if any handler returns false.
|
|
12
13
|
*/
|
|
13
|
-
onSymbolDisplay(grid: GridData, symbol: Symbol, editing: boolean): boolean;
|
|
14
|
+
onSymbolDisplay(grid: GridData, solution: GridData | null, symbol: Symbol, editing: boolean): boolean;
|
|
14
15
|
}
|
|
15
16
|
export declare function handlesSymbolDisplay<T extends Instruction>(val: T): val is T & SymbolDisplayHandler;
|
package/dist/data/grid.d.ts
CHANGED
|
@@ -332,14 +332,6 @@ export default class GridData {
|
|
|
332
332
|
* @returns True if the grids are equal in size and tile colors, false otherwise.
|
|
333
333
|
*/
|
|
334
334
|
colorEquals(grid: GridData): boolean;
|
|
335
|
-
/**
|
|
336
|
-
* Check if this grid conforms to the given solution, or an incomplete version of the solution.
|
|
337
|
-
* Symbols and rules are not validated.
|
|
338
|
-
*
|
|
339
|
-
* @param solution The solution to compare with.
|
|
340
|
-
* @returns True if the grid conforms to the solution, false otherwise.
|
|
341
|
-
*/
|
|
342
|
-
solutionMatches(solution: GridData): boolean;
|
|
343
335
|
/**
|
|
344
336
|
* Check if this grid is equal to another grid in terms of size, tile colors, connections, symbols, and rules.
|
|
345
337
|
*
|
package/dist/data/grid.js
CHANGED
|
@@ -855,29 +855,6 @@ export default class GridData {
|
|
|
855
855
|
this.tiles.every((row, y) => row.every((tile, x) => (!tile.exists && !grid.getTile(x, y).exists) ||
|
|
856
856
|
tile.color === grid.getTile(x, y).color)));
|
|
857
857
|
}
|
|
858
|
-
/**
|
|
859
|
-
* Check if this grid conforms to the given solution, or an incomplete version of the solution.
|
|
860
|
-
* Symbols and rules are not validated.
|
|
861
|
-
*
|
|
862
|
-
* @param solution The solution to compare with.
|
|
863
|
-
* @returns True if the grid conforms to the solution, false otherwise.
|
|
864
|
-
*/
|
|
865
|
-
solutionMatches(solution) {
|
|
866
|
-
if (this.width !== solution.width)
|
|
867
|
-
return false;
|
|
868
|
-
if (this.height !== solution.height)
|
|
869
|
-
return false;
|
|
870
|
-
return this.tiles.every((row, y) => row.every((tile, x) => {
|
|
871
|
-
const solutionTile = solution.getTile(x, y);
|
|
872
|
-
if (!solutionTile.exists)
|
|
873
|
-
return true;
|
|
874
|
-
if (tile.color === Color.Gray)
|
|
875
|
-
return true;
|
|
876
|
-
if (solutionTile.color !== tile.color)
|
|
877
|
-
return false;
|
|
878
|
-
return true;
|
|
879
|
-
}));
|
|
880
|
-
}
|
|
881
858
|
/**
|
|
882
859
|
* Check if this grid is equal to another grid in terms of size, tile colors, connections, symbols, and rules.
|
|
883
860
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Configurable from './configurable.js';
|
|
2
2
|
import GridData from './grid.js';
|
|
3
|
+
import { Mode } from './primitives.js';
|
|
3
4
|
export default abstract class Instruction extends Configurable {
|
|
4
5
|
abstract get id(): string;
|
|
5
6
|
abstract get explanation(): string;
|
|
@@ -10,6 +11,10 @@ export default abstract class Instruction extends Configurable {
|
|
|
10
11
|
get validateWithSolution(): boolean;
|
|
11
12
|
get necessaryForCompletion(): boolean;
|
|
12
13
|
get visibleWhenSolving(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Return a variant of this instruction that is suitable for the given mode.
|
|
16
|
+
*/
|
|
17
|
+
abstract modeVariant(mode: Mode): Instruction | null;
|
|
13
18
|
/**
|
|
14
19
|
* Check if this instruction is equal to another instruction by comparing their IDs and configs.
|
|
15
20
|
*
|
package/dist/data/primitives.js
CHANGED
|
@@ -10,7 +10,7 @@ export default class CellCountPerZoneRule extends Rule {
|
|
|
10
10
|
private static readonly EXAMPLE_GRID_GRAY;
|
|
11
11
|
private static readonly SEARCH_VARIANTS;
|
|
12
12
|
/**
|
|
13
|
-
* **
|
|
13
|
+
* **Zones of the same size have the same number of <color> cells.**
|
|
14
14
|
*
|
|
15
15
|
* @param color - The color of the cells to count.
|
|
16
16
|
*/
|
|
@@ -6,7 +6,7 @@ import { Color, State } from '../primitives.js';
|
|
|
6
6
|
import Rule from './rule.js';
|
|
7
7
|
class CellCountPerZoneRule extends Rule {
|
|
8
8
|
/**
|
|
9
|
-
* **
|
|
9
|
+
* **Zones of the same size have the same number of <color> cells.**
|
|
10
10
|
*
|
|
11
11
|
* @param color - The color of the cells to count.
|
|
12
12
|
*/
|
|
@@ -24,7 +24,7 @@ class CellCountPerZoneRule extends Rule {
|
|
|
24
24
|
return `zone_cell_count`;
|
|
25
25
|
}
|
|
26
26
|
get explanation() {
|
|
27
|
-
return `
|
|
27
|
+
return `Zones of the same size have the same number of ${this.color} cells`;
|
|
28
28
|
}
|
|
29
29
|
get configs() {
|
|
30
30
|
return CellCountPerZoneRule.CONFIGS;
|
|
@@ -91,6 +91,7 @@ class CellCountPerZoneRule extends Rule {
|
|
|
91
91
|
}
|
|
92
92
|
else {
|
|
93
93
|
const errorZone = zones.find(z => zones.some(zz => zz !== z &&
|
|
94
|
+
zz.positions.length === z.positions.length &&
|
|
94
95
|
(zz.completed > z.completed + z.possible ||
|
|
95
96
|
zz.completed + zz.possible < z.completed)));
|
|
96
97
|
if (errorZone) {
|
|
@@ -137,6 +138,10 @@ Object.defineProperty(CellCountPerZoneRule, "EXAMPLE_GRID_LIGHT", {
|
|
|
137
138
|
{ x1: 2, y1: 1, x2: 2, y2: 2 },
|
|
138
139
|
{ x1: 3, y1: 1, x2: 3, y2: 2 },
|
|
139
140
|
{ x1: 4, y1: 1, x2: 4, y2: 2 },
|
|
141
|
+
{ x1: 1, y1: 0, x2: 2, y2: 0 },
|
|
142
|
+
{ x1: 1, y1: 1, x2: 2, y2: 1 },
|
|
143
|
+
{ x1: 2, y1: 2, x2: 3, y2: 2 },
|
|
144
|
+
{ x1: 2, y1: 3, x2: 3, y2: 3 },
|
|
140
145
|
]))
|
|
141
146
|
.addRule(new CellCountPerZoneRule(Color.Light)))
|
|
142
147
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnyConfig } from '../config.js';
|
|
2
2
|
import GridData from '../grid.js';
|
|
3
|
-
import { RuleState, Position } from '../primitives.js';
|
|
3
|
+
import { RuleState, Position, Mode } from '../primitives.js';
|
|
4
4
|
import Rule, { SearchVariant } from './rule.js';
|
|
5
5
|
export default class ForesightRule extends Rule {
|
|
6
6
|
readonly count: number;
|
|
@@ -23,6 +23,7 @@ export default class ForesightRule extends Rule {
|
|
|
23
23
|
validateGrid(_grid: GridData): RuleState;
|
|
24
24
|
get necessaryForCompletion(): boolean;
|
|
25
25
|
get isSingleton(): boolean;
|
|
26
|
+
modeVariant(mode: Mode): Rule | null;
|
|
26
27
|
copyWith({ count, regenInterval, startFull, solvePath, }: {
|
|
27
28
|
count?: number;
|
|
28
29
|
regenInterval?: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConfigType } from '../config.js';
|
|
2
2
|
import GridData from '../grid.js';
|
|
3
|
-
import { State } from '../primitives.js';
|
|
3
|
+
import { State, Mode } from '../primitives.js';
|
|
4
4
|
import CustomIconSymbol from '../symbols/customIconSymbol.js';
|
|
5
5
|
import Rule from './rule.js';
|
|
6
6
|
class ForesightRule extends Rule {
|
|
@@ -65,6 +65,13 @@ class ForesightRule extends Rule {
|
|
|
65
65
|
get isSingleton() {
|
|
66
66
|
return true;
|
|
67
67
|
}
|
|
68
|
+
modeVariant(mode) {
|
|
69
|
+
// foresight is disabled in perfection mode
|
|
70
|
+
if (mode === Mode.Perfection) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
68
75
|
copyWith({ count, regenInterval, startFull, solvePath, }) {
|
|
69
76
|
return new ForesightRule(count ?? this.count, regenInterval ?? this.regenInterval, startFull ?? this.startFull, solvePath ?? this.solvePath);
|
|
70
77
|
}
|
|
@@ -9,6 +9,7 @@ import Rule, { SearchVariant } from './rule.js';
|
|
|
9
9
|
export default class MusicGridRule extends Rule implements GridChangeHandler, SetGridHandler, GridResizeHandler {
|
|
10
10
|
readonly controlLines: readonly ControlLine[];
|
|
11
11
|
readonly track: GridData | null;
|
|
12
|
+
readonly normalizeVelocity: boolean;
|
|
12
13
|
private static readonly EXAMPLE_GRID;
|
|
13
14
|
private static readonly CONFIGS;
|
|
14
15
|
private static readonly SEARCH_VARIANTS;
|
|
@@ -16,8 +17,9 @@ export default class MusicGridRule extends Rule implements GridChangeHandler, Se
|
|
|
16
17
|
* **Music Grid: Listen to the solution**
|
|
17
18
|
* @param controlLines Denote changes in the playback settings. At least one control line at column 0 should be present to enable playback.
|
|
18
19
|
* @param track The grid to be played when "listen" is clicked. Set as null to play the solution.
|
|
20
|
+
* @param normalizeVelocity Whether to normalize the velocity of the notes by their pitch such that lower notes are played softer.
|
|
19
21
|
*/
|
|
20
|
-
constructor(controlLines: readonly ControlLine[], track: GridData | null);
|
|
22
|
+
constructor(controlLines: readonly ControlLine[], track: GridData | null, normalizeVelocity?: boolean);
|
|
21
23
|
get id(): string;
|
|
22
24
|
get explanation(): string;
|
|
23
25
|
get configs(): readonly AnyConfig[] | null;
|
|
@@ -34,9 +36,10 @@ export default class MusicGridRule extends Rule implements GridChangeHandler, Se
|
|
|
34
36
|
*/
|
|
35
37
|
setControlLine(controlLine: ControlLine): this;
|
|
36
38
|
withTrack(track: GridData | null): this;
|
|
37
|
-
copyWith({ controlLines, track, }: {
|
|
39
|
+
copyWith({ controlLines, track, normalizeVelocity, }: {
|
|
38
40
|
controlLines?: readonly ControlLine[];
|
|
39
41
|
track?: GridData | null;
|
|
42
|
+
normalizeVelocity?: boolean;
|
|
40
43
|
}): this;
|
|
41
44
|
get validateWithSolution(): boolean;
|
|
42
45
|
get isSingleton(): boolean;
|
|
@@ -6,22 +6,23 @@ import CustomIconSymbol from '../symbols/customIconSymbol.js';
|
|
|
6
6
|
import { ControlLine, Row } from './musicControlLine.js';
|
|
7
7
|
import Rule from './rule.js';
|
|
8
8
|
const DEFAULT_SCALLE = [
|
|
9
|
-
new Row('C5',
|
|
10
|
-
new Row('B4',
|
|
11
|
-
new Row('A4',
|
|
12
|
-
new Row('G4',
|
|
13
|
-
new Row('F4',
|
|
14
|
-
new Row('E4',
|
|
15
|
-
new Row('D4',
|
|
16
|
-
new Row('C4',
|
|
9
|
+
new Row('C5', null),
|
|
10
|
+
new Row('B4', null),
|
|
11
|
+
new Row('A4', null),
|
|
12
|
+
new Row('G4', null),
|
|
13
|
+
new Row('F4', null),
|
|
14
|
+
new Row('E4', null),
|
|
15
|
+
new Row('D4', null),
|
|
16
|
+
new Row('C4', null),
|
|
17
17
|
];
|
|
18
18
|
class MusicGridRule extends Rule {
|
|
19
19
|
/**
|
|
20
20
|
* **Music Grid: Listen to the solution**
|
|
21
21
|
* @param controlLines Denote changes in the playback settings. At least one control line at column 0 should be present to enable playback.
|
|
22
22
|
* @param track The grid to be played when "listen" is clicked. Set as null to play the solution.
|
|
23
|
+
* @param normalizeVelocity Whether to normalize the velocity of the notes by their pitch such that lower notes are played softer.
|
|
23
24
|
*/
|
|
24
|
-
constructor(controlLines, track) {
|
|
25
|
+
constructor(controlLines, track, normalizeVelocity = true) {
|
|
25
26
|
super();
|
|
26
27
|
Object.defineProperty(this, "controlLines", {
|
|
27
28
|
enumerable: true,
|
|
@@ -35,8 +36,15 @@ class MusicGridRule extends Rule {
|
|
|
35
36
|
writable: true,
|
|
36
37
|
value: track
|
|
37
38
|
});
|
|
39
|
+
Object.defineProperty(this, "normalizeVelocity", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
writable: true,
|
|
43
|
+
value: normalizeVelocity
|
|
44
|
+
});
|
|
38
45
|
this.controlLines = MusicGridRule.deduplicateControlLines(controlLines);
|
|
39
46
|
this.track = track;
|
|
47
|
+
this.normalizeVelocity = normalizeVelocity;
|
|
40
48
|
}
|
|
41
49
|
get id() {
|
|
42
50
|
return MajorRule.MusicGrid;
|
|
@@ -134,8 +142,8 @@ class MusicGridRule extends Rule {
|
|
|
134
142
|
withTrack(track) {
|
|
135
143
|
return this.copyWith({ track });
|
|
136
144
|
}
|
|
137
|
-
copyWith({ controlLines, track, }) {
|
|
138
|
-
return new MusicGridRule(controlLines ?? this.controlLines, track !== undefined ? track : this.track);
|
|
145
|
+
copyWith({ controlLines, track, normalizeVelocity, }) {
|
|
146
|
+
return new MusicGridRule(controlLines ?? this.controlLines, track !== undefined ? track : this.track, normalizeVelocity ?? this.normalizeVelocity);
|
|
139
147
|
}
|
|
140
148
|
get validateWithSolution() {
|
|
141
149
|
return true;
|
|
@@ -197,6 +205,13 @@ Object.defineProperty(MusicGridRule, "CONFIGS", {
|
|
|
197
205
|
description: 'Track',
|
|
198
206
|
configurable: true,
|
|
199
207
|
},
|
|
208
|
+
{
|
|
209
|
+
type: ConfigType.Boolean,
|
|
210
|
+
default: true,
|
|
211
|
+
field: 'normalizeVelocity',
|
|
212
|
+
description: 'Normalize Velocity',
|
|
213
|
+
configurable: true,
|
|
214
|
+
},
|
|
200
215
|
])
|
|
201
216
|
});
|
|
202
217
|
Object.defineProperty(MusicGridRule, "SEARCH_VARIANTS", {
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { AnyConfig } from '../config.js';
|
|
2
2
|
import GridData from '../grid.js';
|
|
3
|
-
import { GridState, RuleState } from '../primitives.js';
|
|
3
|
+
import { GridState, RuleState, Mode } from '../primitives.js';
|
|
4
4
|
import Rule, { SearchVariant } from './rule.js';
|
|
5
5
|
import { SetGridHandler } from '../events/onSetGrid.js';
|
|
6
6
|
import { FinalValidationHandler } from '../events/onFinalValidation.js';
|
|
7
7
|
export default class PerfectionRule extends Rule implements SetGridHandler, FinalValidationHandler {
|
|
8
|
+
readonly editor: boolean;
|
|
8
9
|
private static readonly EXAMPLE_GRID;
|
|
9
10
|
private static readonly SEARCH_VARIANTS;
|
|
10
11
|
/**
|
|
11
12
|
* **Quest for Perfection: cell colors are final**
|
|
13
|
+
*
|
|
14
|
+
* @param editor - whether to enable editor mode. This field is automatically set by the editor.
|
|
12
15
|
*/
|
|
13
|
-
constructor();
|
|
16
|
+
constructor(editor?: boolean);
|
|
14
17
|
get id(): string;
|
|
15
18
|
get explanation(): string;
|
|
16
19
|
get configs(): readonly AnyConfig[] | null;
|
|
@@ -18,18 +21,23 @@ export default class PerfectionRule extends Rule implements SetGridHandler, Fina
|
|
|
18
21
|
get searchVariants(): SearchVariant[];
|
|
19
22
|
get necessaryForCompletion(): boolean;
|
|
20
23
|
get isSingleton(): boolean;
|
|
24
|
+
modeVariant(mode: Mode): Rule | null;
|
|
21
25
|
validateGrid(grid: GridData): RuleState;
|
|
22
26
|
/**
|
|
23
27
|
* If the grid passes validation but is different from the solution, indicate the error in the final state.
|
|
24
28
|
*/
|
|
25
29
|
onFinalValidation(grid: GridData, solution: GridData | null, state: GridState): GridState;
|
|
26
30
|
private fixTiles;
|
|
31
|
+
private isValid;
|
|
32
|
+
private findSingleError;
|
|
27
33
|
/**
|
|
28
34
|
* Force all tiles to be fixed.
|
|
29
35
|
*
|
|
30
36
|
* If the grid is already wrong, prevent the player from changing it further.
|
|
31
37
|
*/
|
|
32
38
|
onSetGrid(oldGrid: GridData, newGrid: GridData, solution: GridData | null): GridData;
|
|
33
|
-
copyWith(
|
|
39
|
+
copyWith({ editor }: {
|
|
40
|
+
editor?: boolean;
|
|
41
|
+
}): this;
|
|
34
42
|
}
|
|
35
43
|
export declare const instance: PerfectionRule;
|