@logic-pad/core 0.4.4 → 0.4.6

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.
@@ -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;
@@ -26,7 +26,9 @@ class BanPatternRule extends Rule {
26
26
  });
27
27
  this.pattern = pattern
28
28
  // unlock all tiles
29
- .withTiles(tiles => tiles.map(row => row.map(t => t.withFixed(false))))
29
+ .withTiles(tiles => tiles.map(row => row.map(t => t.exists
30
+ ? t.withFixed(false)
31
+ : t.copyWith({ exists: true, color: Color.Gray, fixed: false }))))
30
32
  // strip all symbols and rules
31
33
  .withRules([])
32
34
  .withSymbols(new Map());
@@ -49,7 +49,7 @@ Object.defineProperty(Row, "CONFIGS", {
49
49
  },
50
50
  {
51
51
  type: ConfigType.NullableNumber,
52
- default: 0.6,
52
+ default: 0.5,
53
53
  min: 0,
54
54
  max: 1,
55
55
  step: 0.2,
@@ -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', 0.6),
10
- new Row('B4', 0.6),
11
- new Row('A4', 0.6),
12
- new Row('G4', 0.6),
13
- new Row('F4', 0.6),
14
- new Row('E4', 0.6),
15
- new Row('D4', 0.6),
16
- new Row('C4', 0.6),
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", {
@@ -173,8 +173,10 @@ export default class SerializerV0 extends SerializerBase {
173
173
  parseConfig(configs, entry) {
174
174
  const [key, value] = entry.split('=');
175
175
  const config = configs.find(x => x.field === key);
176
- if (!config)
177
- throw new Error(`Unknown config: ${key}`);
176
+ if (!config) {
177
+ console.warn(`Unknown config: ${key} when parsing ${entry}`);
178
+ return [key, value];
179
+ }
178
180
  switch (config.type) {
179
181
  case ConfigType.Boolean:
180
182
  return [config.field, value === '1'];
@@ -42,7 +42,6 @@ export default class DirectionLinkerBTModule extends BTModule {
42
42
  this.initialPositions = this.getInitialPositions();
43
43
  const tilesNeedCheck = IntArray2D.create(grid.width, grid.height);
44
44
  const ratings = [];
45
- let checkable = false;
46
45
  for (const pos of this.initialPositions) {
47
46
  const tile = grid.isInBound(pos.x, pos.y)
48
47
  ? grid.getTile(pos.x, pos.y)
@@ -53,6 +52,10 @@ export default class DirectionLinkerBTModule extends BTModule {
53
52
  grid.getTile(oppoPos.x, oppoPos.y) === BTTile.NonExist)
54
53
  return false;
55
54
  else {
55
+ if (grid.getTile(oppoPos.x, oppoPos.y) === BTTile.Empty) {
56
+ tilesNeedCheck.set(oppoPos.x, oppoPos.y, 1);
57
+ ratings.push({ pos: oppoPos, score: 1 });
58
+ }
56
59
  tilesNeedCheck.set(pos.x, pos.y, 1);
57
60
  ratings.push({ pos, score: 1 });
58
61
  }
@@ -69,20 +72,18 @@ export default class DirectionLinkerBTModule extends BTModule {
69
72
  if (oppoPos !== null) {
70
73
  const oppoTile = grid.getTile(oppoPos.x, oppoPos.y);
71
74
  if (oppoTile === BTTile.Empty) {
72
- tilesNeedCheck.set(pos.x, pos.y, 1);
73
- ratings.push({ pos, score: 1 });
75
+ tilesNeedCheck.set(oppoPos.x, oppoPos.y, 1);
76
+ ratings.push({ pos: oppoPos, score: 1 });
74
77
  }
75
78
  else if (oppoTile === BTTile.NonExist)
76
79
  return false;
77
- else
78
- checkable = true;
79
80
  }
80
81
  else {
81
82
  return false;
82
83
  }
83
84
  }
84
85
  }
85
- if (!checkable) {
86
+ if (ratings.length > 0) {
86
87
  return { tilesNeedCheck, ratings };
87
88
  }
88
89
  const queue = this.initialPositions