mumuki-puzzle-runner 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
+