mumuki-puzzle-runner 0.1.2 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 441d4b26b7b8308cc9ed1ec7aca6de3c03905a6018af2db5d1d5e9889b72b55d
4
- data.tar.gz: 5ccb1d263bc6e5c60f62d247006faa81d9a5647518939c0e9b2159092a3fdc45
3
+ metadata.gz: 725586c41840661a2deeb9f2cb179b0ca4181e9e7116f72d5a91cc0deaf2ac44
4
+ data.tar.gz: db8a8081c4f4f13e95300abce70767e2fe54649c98da2f0686c5712634fbf71f
5
5
  SHA512:
6
- metadata.gz: d68ffd2617b06416d0e377a46c0bbb89f2728267d79866e31dc7afbaea88d9c22f1df2390ae0bac3a662c610ecc1f8234dec6bd9ca658d9714eea4412ef8e2fb
7
- data.tar.gz: 5c83e99fc78f6f4043e65b5da66a1587a4398a3247d322985d5140976601d69feec3ebadcf9c1de0e86b1ce2208055414af1c87da08e97bf809ee256ff856877
6
+ metadata.gz: 98d5444f8a2ad9430ed1bb744770e522225a9295c3b1d1a478767c5bf255cb542e27ddfa1ba7ee2f625dc1536f37fe9850715b30501094649073d02caddb683a
7
+ data.tar.gz: a69f232d47d551d976d854856b4c40e5be94e8312e0dc2e32db2f8c16321136845fa6aca1565282ed66fe1728f0602142c05452313335fc3e8ba996936eb7016
@@ -31,7 +31,6 @@ $(() => {
31
31
  // mumuki's solution processing
32
32
  const _onSubmit = Muzzle.onSubmit;
33
33
  Muzzle.onSubmit = (submission) => {
34
- console.log(`submitting ${submission}`)
35
34
  mumuki.submission.processSolution(submission);
36
35
  _onSubmit(submission);
37
36
  }
@@ -73,6 +73,14 @@ class MuzzleCanvas {
73
73
  */
74
74
  this.canvasHeight = 600;
75
75
 
76
+ /**
77
+ * Wether canvas shoud **not** be resized.
78
+ * Default is `false`
79
+ *
80
+ * @type {boolean}
81
+ */
82
+ this.fixedDimensions = false;
83
+
76
84
  /**
77
85
  * Size of fill. Set null for perfect-match
78
86
  *
@@ -95,11 +103,20 @@ class MuzzleCanvas {
95
103
  this.pieceSize = 100;
96
104
 
97
105
  /**
98
- * * Whether image's width should be scaled to piece
106
+ * The x:y aspect ratio of the piece. Set null for automatic
107
+ * aspectRatio
108
+ *
109
+ * @type {number}
110
+ */
111
+ this.aspectRatio = null;
112
+
113
+ /**
114
+ * If the images should be adjusted vertically instead of horizontally
115
+ * to puzzle dimensions. `false` by default
99
116
  *
100
117
  * @type {boolean}
101
118
  */
102
- this.scaleImageWidthToFit = true;
119
+ this.fitImagesVertically = false;
103
120
 
104
121
  /**
105
122
  * Callback that will be executed
@@ -142,17 +159,27 @@ class MuzzleCanvas {
142
159
  /**
143
160
  */
144
161
  get baseConfig() {
162
+ const aspectRatio = this.aspectRatio || 1;
163
+ const pieceSize = headbreaker.vector(this.pieceSize / aspectRatio, this.pieceSize);
145
164
  return {
146
165
  width: this.canvasWidth,
147
166
  height: this.canvasHeight,
148
- pieceSize: this.pieceSize,
149
- proximity: this.pieceSize / 5,
150
- borderFill: this.borderFill === null ? this.pieceSize / 10 : this.borderFill,
167
+ pieceSize: pieceSize,
168
+ proximity: pieceSize.x / 5,
169
+ borderFill: this.borderFill === null ? headbreaker.Vector.divide(pieceSize, 10) : this.borderFill,
151
170
  strokeWidth: this.strokeWidth,
152
171
  lineSoftness: 0.18
153
172
  };
154
173
  }
155
174
 
175
+ /**
176
+ * @type {Axis}
177
+ */
178
+ get imageAdjustmentAxis() {
179
+ console.log(this.fitImagesVertically)
180
+ return this.fitImagesVertically ? headbreaker.Vertical : headbreaker.Horizontal;
181
+ }
182
+
156
183
  /**
157
184
  * The currently active canvas, or null if
158
185
  * it has not yet initialized
@@ -195,15 +222,21 @@ class MuzzleCanvas {
195
222
  * @returns {Promise<Canvas>} the promise of the built canvas
196
223
  */
197
224
  async basic(x, y, imagePath) {
225
+ if (!this.aspectRatio) {
226
+ this.aspectRatio = x / y;
227
+ }
228
+
198
229
  /**
199
230
  * @todo take all container size
200
231
  **/
201
232
  const image = await this._loadImage(imagePath);
202
233
  /** @type {Canvas} */
203
234
  // @ts-ignore
204
- const canvas = this._createCanvas(image);
235
+ const canvas = this._createCanvas({ image: image });
236
+ canvas.adjustImagesToPuzzle(this.imageAdjustmentAxis);
205
237
  canvas.autogenerate({ horizontalPiecesCount: x, verticalPiecesCount: y });
206
238
  this._attachBasicValidator(canvas);
239
+ canvas.shuffleGrid(0.8);
207
240
  this._configCanvas(canvas);
208
241
  canvas.onValid(() => {
209
242
  setTimeout(() => {
@@ -225,7 +258,7 @@ class MuzzleCanvas {
225
258
  const count = imagePaths.length;
226
259
  const images = await Promise.all(imagePaths.map(imagePath => this._loadImage(imagePath)));
227
260
 
228
- const canvas = this._createCanvas(null);
261
+ const canvas = this._createCanvas();
229
262
  canvas.autogenerate({ horizontalPiecesCount: x, verticalPiecesCount: y * count });
230
263
 
231
264
  // todo validate
@@ -256,17 +289,20 @@ class MuzzleCanvas {
256
289
  const leftId = `l${i}`;
257
290
  const rightId = `r${i}`;
258
291
 
259
- pushTemplate(leftUrls[i], {id: leftId, left: true, rightTargetId: rightId});
260
- pushTemplate(rightUrls[i], {id: rightId});
292
+ pushTemplate(leftUrls[i], {id: leftId, targetPosition: { x: this.pieceSize, y: this.pieceSize * (i + 1) }, left: true, rightTargetId: rightId});
293
+ pushTemplate(rightUrls[i], {id: rightId, targetPosition: { x: 2 * this.pieceSize, y: this.pieceSize * (i + 1) }});
261
294
  }
262
295
 
263
- leftOddUrls.forEach((it, i) => pushTemplate(it, {id: `lo${i}`, left: true, odd: true}));
264
- rightOddUrls.forEach((it, i) => pushTemplate(it, {id: `ro${i}`, odd: true}));
296
+ leftOddUrls.forEach((it, i) => pushTemplate(it, {id: `lo${i}`, left: true, odd: true, targetPosition: { x: this.pieceSize, y: this.pieceSize * (i + leftUrls.length) }, }));
297
+ rightOddUrls.forEach((it, i) => pushTemplate(it, {id: `ro${i}`, odd: true, targetPosition: { x: 2 * this.pieceSize, y: this.pieceSize * (i + rightUrls.length) },}));
265
298
 
299
+ // + Math.max(leftOddUrls.length, rightOddUrls.length)
266
300
  const templates = await Promise.all(templatePromises);
267
301
  /** @type {Canvas} */
268
- const canvas = this._createCanvas();
302
+ const canvas = this._createCanvas({ maxPiecesCount: {x: 2, y: leftUrls.length} });
303
+ canvas.adjustImagesToPiece(this.imageAdjustmentAxis);
269
304
  templates.forEach(it => canvas.sketchPiece(it));
305
+ canvas.shuffleColumns(0.8);
270
306
  this._attachMatchValidator(canvas);
271
307
  this._configCanvas(canvas);
272
308
  return canvas;
@@ -283,19 +319,11 @@ class MuzzleCanvas {
283
319
 
284
320
  /**
285
321
  * @private
286
- * @param {HTMLImageElement} image
322
+ * @param {any} config
287
323
  * @return {Canvas}
288
324
  */
289
- _createCanvas(image = null) {
290
- return new headbreaker.Canvas(this.canvasId, this._canvasConfig(image));
291
- }
292
-
293
- /**
294
- * @private
295
- * @param {HTMLImageElement} image
296
- */
297
- _canvasConfig(image) {
298
- return Object.assign({ image }, this.baseConfig);
325
+ _createCanvas(config = {}) {
326
+ return new headbreaker.Canvas(this.canvasId, Object.assign(config, this.baseConfig));
299
327
  }
300
328
 
301
329
  /**
@@ -339,37 +367,17 @@ class MuzzleCanvas {
339
367
  * @param {object} options
340
368
  * @returns {Promise<object>}
341
369
  */
342
- _createMatchTemplate(imagePath, {id, left = false, rightTargetId = null, odd = false}) {
370
+ _createMatchTemplate(imagePath, {id, left = false, targetPosition = null, rightTargetId = null, odd = false}) {
343
371
  const structure = left ? 'T-N-' : `N-S-`;
344
372
 
345
373
  return this._loadImage(imagePath).then((image) => {
346
- const scale = this._imageScale(image);
347
- const offset = this.baseConfig.borderFill / scale;
348
374
  return {
349
375
  structure,
350
- metadata: {
351
- id,
352
- left,
353
- odd,
354
- rightTargetId,
355
- image: {
356
- scale,
357
- content: image,
358
- offset: { x: offset, y: offset }
359
- }
360
- }
376
+ metadata: { id, left, odd, rightTargetId, image, targetPosition }
361
377
  }
362
378
  });
363
379
  }
364
380
 
365
- /**
366
- * @private
367
- * @param {HTMLImageElement} image
368
- */
369
- _imageScale(image) {
370
- return this.scaleImageWidthToFit ? this.pieceSize / image.width : 1;
371
- }
372
-
373
381
  /**
374
382
  * @private
375
383
  * @param {Canvas} canvas
@@ -379,9 +387,23 @@ class MuzzleCanvas {
379
387
  this._canvas.onValid(() => {
380
388
  setTimeout(() => this.onValid(), 0);
381
389
  });
390
+ this._setupResponsiveness();
382
391
  this.ready();
383
392
  }
384
393
 
394
+ _setupResponsiveness() {
395
+ if (this.fixedDimensions) return;
396
+
397
+ ['resize', 'load'].forEach((event) => {
398
+ window.addEventListener(event, () => {
399
+ var container = document.getElementById(this.canvasId);
400
+ this.canvas.resize(container.offsetWidth, container.scrollHeight);
401
+ this.canvas.redraw();
402
+ });
403
+ });
404
+ }
405
+
406
+
385
407
  /**
386
408
  * Mark Muzzle as ready, loading previous solution
387
409
  * and drawing the canvas
@@ -426,8 +448,6 @@ class MuzzleCanvas {
426
448
  } catch (e) {
427
449
  console.warn("Ignoring unparseabe editor value");
428
450
  }
429
- } else {
430
- this.canvas.shuffle(0.8);
431
451
  }
432
452
  }
433
453
 
@@ -28,14 +28,14 @@ declare class Anchor {
28
28
  /**
29
29
  * Converts this anchor into a point
30
30
  */
31
- asPoint(): Pair;
31
+ asPair(): Pair;
32
32
  /**
33
- * Converts this anchor into a position
33
+ * Converts this anchor into a vector
34
34
  */
35
- asPosition(): Position;
36
- export(): Position;
35
+ asVector(): Vector;
36
+ export(): Vector;
37
37
  static atRandom(maxX: number, maxY: number): Anchor;
38
- static import(position: Position): Anchor;
38
+ static import(vector: Vector): Anchor;
39
39
  }
40
40
 
41
41
  /**
@@ -43,6 +43,8 @@ declare class Anchor {
43
43
  */
44
44
  declare function anchor(x: number, y: number): Anchor;
45
45
 
46
+ declare type Axis = Vertical | Horizontal;
47
+
46
48
  declare type Label = any;
47
49
 
48
50
  declare type Figure = {
@@ -76,9 +78,10 @@ declare type LabelMetadata = {
76
78
 
77
79
  declare type CanvasMetadata = {
78
80
  id?: string;
79
- targetPosition?: Position;
80
- currentPosition?: Position;
81
+ targetPosition?: Vector;
82
+ currentPosition?: Vector;
81
83
  color?: string;
84
+ fixed?: boolean;
82
85
  strokeColor?: string;
83
86
  image?: ImageLike;
84
87
  label?: LabelMetadata;
@@ -86,6 +89,7 @@ declare type CanvasMetadata = {
86
89
 
87
90
  declare type Template = {
88
91
  structure: StructureLike;
92
+ size?: Size;
89
93
  metadata: CanvasMetadata;
90
94
  };
91
95
 
@@ -93,25 +97,37 @@ declare type Template = {
93
97
  * An HTML graphical area where puzzles and pieces can be rendered. No assumption of the rendering backend is done - it may be
94
98
  * and be a plain HTML SVG or canvas element, or a higher-level library - and this task is fully delegated to {@link Painter}
95
99
  * @param id - the html id of the element where to place the canvas
100
+ * @param [options.pieceSize] - the piece size expresed as it edge-to-edge diameter
96
101
  * @param [options.borderFill] - the broder fill of the pieces, expresed in pixels. 0 means no border fill, 0.5 * pieceSize means full fill
97
102
  * @param [options.lineSoftness] - how soft the line will be
98
103
  * @param [options.image] - an optional background image for the puzzle that will be split across all pieces.
104
+ * @param [options.fixed] - whether the canvas can is fixed or can be dragged
99
105
  * @param [options.painter] - the Painter object used to actually draw figures in canvas
106
+ * @param [options.puzzleDiameter] - the puzzle diameter used to calculate the maximal width and height
107
+ * You only need to specify this option when pieces are manually sketched and images must be adjusted
108
+ * @param [options.maxPiecesCount] - the maximal amount of pieces used to calculate the maximal width and height.
109
+ * You only need to specify this option when pieces are manually sketched and images must be adjusted
100
110
  */
101
111
  declare class Canvas {
102
112
  constructor(id: string, options: {
103
113
  width: number;
104
114
  height: number;
105
- pieceSize?: number;
115
+ pieceSize?: Vector | number;
106
116
  proximity?: number;
107
- borderFill?: number;
117
+ borderFill?: Vector | number;
108
118
  strokeWidth?: number;
109
119
  strokeColor?: string;
110
120
  lineSoftness?: number;
111
121
  image?: ImageLike;
122
+ fixed?: boolean;
112
123
  painter?: Painter;
124
+ puzzleDiameter?: Vector | number;
125
+ maxPiecesCount?: Vector | number;
113
126
  });
114
127
  _painter: Painter;
128
+ _maxPiecesCount: Vector;
129
+ _puzzleDiameter: Vector;
130
+ _imageAdjuster: any;
115
131
  _puzzle: Puzzle;
116
132
  figures: {
117
133
  [key: string]: Figure;
@@ -133,7 +149,7 @@ declare class Canvas {
133
149
  renderPieces(pieces: Piece[]): void;
134
150
  /**
135
151
  * Renders a previously created puzzle object. This method
136
- * overrides this canvas' {@link Canvas#pieceSize} and {@link Canvas#proximity}
152
+ * overrides this canvas' {@link Canvas#pieceDiameter} and {@link Canvas#proximity}
137
153
  */
138
154
  renderPuzzle(puzzle: Puzzle): void;
139
155
  /**
@@ -157,9 +173,17 @@ declare class Canvas {
157
173
  */
158
174
  sketchPieceUsingTemplate(id: string, templateName: string): void;
159
175
  /**
160
- * @param farness - from 0 to 1, how far pieces will be placed from x = pieceSize, y = pieceSize
176
+ * @param farness - from 0 to 1, how far pieces will be placed from x = pieceDiameter.x, y = pieceDiameter.y
161
177
  */
162
178
  shuffle(farness?: number): void;
179
+ /**
180
+ * **Warning**: this method requires {@code maxPiecesCount} to be set.
181
+ */
182
+ shuffleColumns(farness?: number): void;
183
+ /**
184
+ * **Warning**: this method requires {@code maxPiecesCount} to be set.
185
+ */
186
+ shuffleGrid(farness?: number): void;
163
187
  /**
164
188
  * Draws this canvas for the first time
165
189
  */
@@ -222,6 +246,14 @@ declare class Canvas {
222
246
  * Answers the visual representation for the given piece id.
223
247
  */
224
248
  getFigureById(id: string): Figure;
249
+ /**
250
+ * Sets the new width and height of the canvas
251
+ */
252
+ resize(width: number, height: number): void;
253
+ /**
254
+ * Scales the canvas contents to the given factor
255
+ */
256
+ scale(factor: Vector | number): void;
225
257
  _annotatePiecePosition(piece: Piece): void;
226
258
  /**
227
259
  * Configures updates from piece into group
@@ -231,8 +263,59 @@ declare class Canvas {
231
263
  * * Configures updates from group into piece
232
264
  */
233
265
  _bindPieceToGroup(piece: Piece, group: Group): void;
234
- _imageMetadataFor(model: Piece): ImageMetadata;
235
- _newPiece(structureLike: StructureLike, metadata: CanvasMetadata): void;
266
+ _baseImageMetadataFor(piece: Piece): ImageMetadata;
267
+ imageMetadataFor(piece: Piece): ImageMetadata;
268
+ /**
269
+ * Configures canvas to adjust images axis to puzzle's axis.
270
+ *
271
+ * **Warning**: this method requires {@code maxPiecesCount} or {@code puzzleDiameter} to be set.
272
+ */
273
+ adjustImagesToPuzzle(axis: Axis): void;
274
+ /**
275
+ * Configures canvas to adjust images width to puzzle's width
276
+ *
277
+ * **Warning**: this method requires {@code maxPiecesCount} or {@code puzzleDiameter} to be set.
278
+ */
279
+ adjustImagesToPuzzleWidth(): void;
280
+ /**
281
+ * Configures canvas to adjust images height to puzzle's height
282
+ *
283
+ * **Warning**: this method requires {@code maxPiecesCount} or {@code puzzleDiameter} to be set.
284
+ */
285
+ adjustImagesToPuzzleHeight(): void;
286
+ /**
287
+ * Configures canvas to adjust images axis to pieces's axis
288
+ *
289
+ * **Warning**: this method requires {@code maxPiecesCount} or {@code puzzleDiameter} to be set.
290
+ */
291
+ adjustImagesToPiece(axis: Axis): void;
292
+ /**
293
+ * Configures canvas to adjust images width to pieces's width
294
+ *
295
+ * **Warning**: this method requires {@code maxPiecesCount} or {@code puzzleDiameter} to be set.
296
+ */
297
+ adjustImagesToPieceWidth(): void;
298
+ /**
299
+ * Configures canvas to adjust images height to pieces's height
300
+ *
301
+ * **Warning**: this method requires {@code maxPiecesCount} or {@code puzzleDiameter} to be set.
302
+ */
303
+ adjustImagesToPieceHeight(): void;
304
+ /**
305
+ * @param structureLike - the piece structure
306
+ */
307
+ _newPiece(structureLike: StructureLike, size: Size, metadata: CanvasMetadata): void;
308
+ /**
309
+ * The puzzle diameter, using the
310
+ * configured puzzle diameter or the estimated one, if the first is not available.
311
+ */
312
+ puzzleDiameter: Vector;
313
+ /**
314
+ * The estimated puzzle diameter calculated using the the max pieces count.
315
+ */
316
+ estimatedPuzzleDiameter: Vector;
317
+ pieceRadio: Vector;
318
+ pieceDiameter: Vector;
236
319
  /**
237
320
  * The puzzle rendered by this canvas
238
321
  */
@@ -254,7 +337,7 @@ declare class DummyPainter implements Painter {
254
337
 
255
338
  declare type ImageMetadata = {
256
339
  content: HTMLImageElement;
257
- offset?: Position;
340
+ offset?: Vector;
258
341
  scale?: number;
259
342
  };
260
343
 
@@ -284,6 +367,8 @@ declare class KonvaPainter implements Painter {
284
367
  initialize(canvas: Canvas, id: string): void;
285
368
  draw(canvas: Canvas): void;
286
369
  reinitialize(canvas: Canvas): void;
370
+ resize(canvas: Canvas, width: number, height: number): void;
371
+ scale(canvas: Canvas, factor: Vector): void;
287
372
  sketch(canvas: Canvas, piece: Piece, figure: Figure): void;
288
373
  label(_canvas: Canvas, piece: Piece, figure: Figure): void;
289
374
  physicalTranslate(_canvas: Canvas, group: Group, piece: Piece): void;
@@ -326,6 +411,8 @@ declare class Manufacturer {
326
411
 
327
412
  declare class Positioner {
328
413
  constructor(puzzle: Puzzle, headAnchor: Anchor);
414
+ initializeOffset(headAnchor: Anchor): void;
415
+ offset: Vector;
329
416
  naturalAnchor(x: number, y: number): void;
330
417
  }
331
418
 
@@ -344,7 +431,7 @@ declare module "Metadata" {
344
431
  */
345
432
  declare module "Outline" {
346
433
  function select(insert: Insert, t: number, s: number, n: number): void;
347
- function draw(piece: Piece, size?: number): number[];
434
+ function draw(piece: Piece, size?: Vector | number, borderFill?: Vector | number): number[];
348
435
  }
349
436
 
350
437
  declare type VectorAction = (dx: number, dy: number) => void;
@@ -356,6 +443,7 @@ declare type Action = () => void;
356
443
  * order to create UI representations of a puzzle.
357
444
  */
358
445
  declare interface Painter {
446
+ resize(canvas: Canvas, width: number, height: number): void;
359
447
  /**
360
448
  * Creates the rendering backend, initializig all its contents.
361
449
  * After this call, painter is ready to receive any other messages
@@ -371,6 +459,10 @@ declare interface Painter {
371
459
  * Draws the canvas figures in the rendering backend
372
460
  */
373
461
  draw(canvas: Canvas): void;
462
+ /**
463
+ * Scales the canvas contents
464
+ */
465
+ scale(canvas: Canvas, factor: Vector): void;
374
466
  /**
375
467
  * Adds a piece to the rendering backend, so that it is ready to be drawn
376
468
  * @param figure - the rendering backend information for this piece. This method may mutate it if necessary
@@ -404,7 +496,10 @@ declare module "Pair" {
404
496
  * Tells whether this pair is (0, 0)
405
497
  */
406
498
  function isNull(x: number, y: number): boolean;
407
- function equal(x1: number, y1: number, x2: number, y2: number): boolean;
499
+ /**
500
+ * @param [delta = 0] - tolerance in comparison
501
+ */
502
+ function equal(x1: number, y1: number, x2: number, y2: number, delta?: number): boolean;
408
503
  /**
409
504
  * Calculates the difference of two vectors
410
505
  */
@@ -415,25 +510,39 @@ declare type TranslationListener = (piece: Piece, dx: number, dy: number) => voi
415
510
 
416
511
  declare type ConnectionListener = (piece: Piece, target: Piece) => void;
417
512
 
513
+ declare type PieceConfig = {
514
+ centralAnchor?: Vector;
515
+ size?: Size;
516
+ metadata?: any;
517
+ };
518
+
418
519
  /**
419
520
  * A piece primitive representation that can be easily stringified, exchanged and persisted
420
521
  */
421
522
  declare type PieceDump = {
422
- centralAnchor: Position;
423
- structure: string;
424
- connections?: Orthogonal<object>;
523
+ centralAnchor: Vector;
524
+ size?: Size;
425
525
  metadata: any;
526
+ connections?: Orthogonal<object>;
527
+ structure: string;
426
528
  };
427
529
 
428
530
  /**
429
531
  * A jigsaw piece
430
532
  */
431
533
  declare class Piece {
432
- constructor(options?: Structure);
534
+ constructor(structure?: Structure, config?: PieceConfig);
535
+ metadata: any;
433
536
  centralAnchor: Anchor;
537
+ _size: Size;
434
538
  translateListeners: TranslationListener[];
435
539
  connectListeners: ConnectionListener[];
436
540
  disconnectListeners: ConnectionListener[];
541
+ /**
542
+ * Runs positining, sizing and metadata configurations
543
+ * in a single step
544
+ */
545
+ configure(config: PieceConfig): void;
437
546
  /**
438
547
  * Adds unestructured user-defined metadata on this piece.
439
548
  */
@@ -523,7 +632,16 @@ declare class Piece {
523
632
  rightAnchor: Anchor;
524
633
  upAnchor: Anchor;
525
634
  leftAnchor: Anchor;
526
- size: number;
635
+ /**
636
+ * Defines this piece's own dimmension, overriding puzzle's
637
+ * default dimmension
638
+ */
639
+ resize(size: Size): void;
640
+ radio: Vector;
641
+ /**
642
+ * The double of the radio
643
+ */
644
+ diameter: Vector;
527
645
  proximity: number;
528
646
  /**
529
647
  * This piece id. It is extracted from metadata
@@ -543,37 +661,6 @@ declare class Piece {
543
661
  static import(dump: PieceDump): Piece;
544
662
  }
545
663
 
546
- declare type Position = {
547
- x: number;
548
- y: number;
549
- };
550
-
551
- declare function position(x: number, y: number): Position;
552
-
553
- /**
554
- * This module contains functions for dealing with objects with x and y
555
- * coordinates that represent or include point data
556
- */
557
- declare module "Position" {
558
- /**
559
- * Returns a new (0, 0) position
560
- */
561
- function origin(): Position;
562
- /**
563
- * Compares two points
564
- */
565
- function equal(one: Position, other: Position): boolean;
566
- /**
567
- * Creates a copy of the given point
568
- */
569
- function copy(one: Position): Position;
570
- function update(position: Position, x: any, y: any): void;
571
- /**
572
- * @returns ;
573
- */
574
- function diff(one: Position, other: Position): Pair;
575
- }
576
-
577
664
  declare type Orthogonal = {
578
665
  up: A;
579
666
  down: A;
@@ -597,13 +684,13 @@ declare module "Prelude" {
597
684
  * A puzzle primitive representation that can be easily stringified, exchanged and persisted
598
685
  */
599
686
  declare type PuzzleDump = {
600
- pieceSize: number;
687
+ pieceRadio: Vector;
601
688
  proximity: number;
602
689
  pieces: PieceDump[];
603
690
  };
604
691
 
605
692
  declare type Settings = {
606
- pieceSize?: number;
693
+ pieceRadio?: Vector | number;
607
694
  proximity?: number;
608
695
  };
609
696
 
@@ -617,10 +704,11 @@ declare class Puzzle {
617
704
  validator: Validator;
618
705
  /**
619
706
  * Creates and adds to this puzzle a new piece
620
- * @param [options] - the piece structure
707
+ * @param [structure] - the piece structure
708
+ * @param [config] - the piece config
621
709
  * @returns the new piece
622
710
  */
623
- newPiece(options?: Structure): Piece;
711
+ newPiece(structure?: Structure, config?: PieceConfig): Piece;
624
712
  addPiece(piece: Piece): void;
625
713
  addPieces(pieces: Piece[]): void;
626
714
  /**
@@ -646,6 +734,7 @@ declare class Puzzle {
646
734
  */
647
735
  autoconnectWith(piece: Piece): void;
648
736
  shuffle(maxX: number, maxY: number): void;
737
+ shuffleWith(shuffler: Shuffler): void;
649
738
  translate(dx: number, dy: number): void;
650
739
  onTranslate(f: TranslationListener): void;
651
740
  onConnect(f: ConnectionListener): void;
@@ -701,9 +790,13 @@ declare class Puzzle {
701
790
  connected: boolean;
702
791
  /**
703
792
  * The piece width, from edge to edge.
704
- * This is the double of the {@link Puzzle#pieceSize}
793
+ * This is the double of the {@link Puzzle#pieceRadio}
705
794
  */
706
- pieceWidth: number;
795
+ pieceDiameter: Vector;
796
+ /**
797
+ * The piece width, from center to edge
798
+ */
799
+ pieceRadio: Vector;
707
800
  /**
708
801
  * Converts this piece into a plain, stringify-ready object.
709
802
  * Pieces should have ids
@@ -758,9 +851,30 @@ declare module "sequence" {
758
851
  }
759
852
  }
760
853
 
854
+ declare function random(maxX: number, maxY: number): Shuffler;
855
+
856
+ declare function grid(): void;
857
+
858
+ declare function columns(): void;
859
+
860
+ declare function padder(padding: number, width: number, height: number): Shuffler;
861
+
862
+ declare function noise(maxDistance: Vector): Shuffler;
863
+
864
+ declare function noop(): void;
865
+
866
+ declare type Size = {
867
+ radio: Vector;
868
+ diameter: Vector;
869
+ };
870
+
871
+ declare function radio(value: Vector | number): Size;
872
+
873
+ declare function diameter(value: Vector | number): Size;
874
+
761
875
  declare type SpatialMetadata = {
762
- targetPosition?: Position;
763
- currentPosition?: Position;
876
+ targetPosition?: Vector;
877
+ currentPosition?: Vector;
764
878
  };
765
879
 
766
880
  /**
@@ -768,10 +882,11 @@ declare type SpatialMetadata = {
768
882
  * and pieces and puzzles that are annotated with it
769
883
  */
770
884
  declare module "SpatialMetadata" {
885
+ function diffToTarget(piece: Piece): void;
771
886
  function solved(): void;
772
887
  function relativePosition(): void;
773
888
  function absolutePosition(): void;
774
- function initialize(metadata: SpatialMetadata, target: Position, current?: Position): void;
889
+ function initialize(metadata: SpatialMetadata, target: Vector, current?: Vector): void;
775
890
  }
776
891
 
777
892
  declare type Structure = {
@@ -852,3 +967,42 @@ declare class NullValidator {
852
967
  isNull: boolean;
853
968
  }
854
969
 
970
+ declare type Vector = {
971
+ x: number;
972
+ y: number;
973
+ };
974
+
975
+ declare function vector(x: number, y: number): Vector;
976
+
977
+ declare function cast(value: Vector | number): Vector;
978
+
979
+ /**
980
+ * This module contains functions for dealing with objects with x and y
981
+ * coordinates that represent or include point data
982
+ */
983
+ declare module "Vector" {
984
+ /**
985
+ * Returns a new (0, 0) vector
986
+ */
987
+ function zero(): Vector;
988
+ /**
989
+ * Compares two points
990
+ * @param [delta = 0] - the tolance in comparison
991
+ */
992
+ function equal(one: Vector, other: Vector, delta?: number): boolean;
993
+ /**
994
+ * Creates a copy of the given point
995
+ */
996
+ function copy(one: Vector): Vector;
997
+ function update(vector: Vector, x: any, y: any): void;
998
+ /**
999
+ * @returns ;
1000
+ */
1001
+ function diff(one: Vector, other: Vector): Pair;
1002
+ function multiply(one: Vector | number, other: Vector | number): Vector;
1003
+ function divide(one: Vector | number, other: Vector | number): Vector;
1004
+ function plus(one: Vector | number, other: Vector | number): Vector;
1005
+ function minus(one: Vector | number, other: Vector | number): Vector;
1006
+ function apply(one: Vector | number, other: Vector | number, f: any): Vector;
1007
+ }
1008
+