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 +4 -4
- data/lib/public/js/muzzle-editor.js +0 -1
- data/lib/public/js/muzzle.js +67 -47
- data/lib/public/vendor/headbreaker.d.ts +215 -61
- data/lib/public/vendor/headbreaker.js +1 -1
- data/lib/public/vendor/headbreaker.js.map +1 -1
- data/lib/version_hook.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 725586c41840661a2deeb9f2cb179b0ca4181e9e7116f72d5a91cc0deaf2ac44
|
4
|
+
data.tar.gz: db8a8081c4f4f13e95300abce70767e2fe54649c98da2f0686c5712634fbf71f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98d5444f8a2ad9430ed1bb744770e522225a9295c3b1d1a478767c5bf255cb542e27ddfa1ba7ee2f625dc1536f37fe9850715b30501094649073d02caddb683a
|
7
|
+
data.tar.gz: a69f232d47d551d976d854856b4c40e5be94e8312e0dc2e32db2f8c16321136845fa6aca1565282ed66fe1728f0602142c05452313335fc3e8ba996936eb7016
|
data/lib/public/js/muzzle.js
CHANGED
@@ -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
|
-
*
|
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.
|
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:
|
149
|
-
proximity:
|
150
|
-
borderFill: this.borderFill === null ?
|
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(
|
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 {
|
322
|
+
* @param {any} config
|
287
323
|
* @return {Canvas}
|
288
324
|
*/
|
289
|
-
_createCanvas(
|
290
|
-
return new headbreaker.Canvas(this.canvasId, this.
|
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
|
-
|
31
|
+
asPair(): Pair;
|
32
32
|
/**
|
33
|
-
* Converts this anchor into a
|
33
|
+
* Converts this anchor into a vector
|
34
34
|
*/
|
35
|
-
|
36
|
-
export():
|
35
|
+
asVector(): Vector;
|
36
|
+
export(): Vector;
|
37
37
|
static atRandom(maxX: number, maxY: number): Anchor;
|
38
|
-
static import(
|
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?:
|
80
|
-
currentPosition?:
|
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#
|
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 =
|
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
|
-
|
235
|
-
|
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?:
|
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
|
-
|
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:
|
423
|
-
|
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(
|
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
|
-
|
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
|
-
|
687
|
+
pieceRadio: Vector;
|
601
688
|
proximity: number;
|
602
689
|
pieces: PieceDump[];
|
603
690
|
};
|
604
691
|
|
605
692
|
declare type Settings = {
|
606
|
-
|
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 [
|
707
|
+
* @param [structure] - the piece structure
|
708
|
+
* @param [config] - the piece config
|
621
709
|
* @returns the new piece
|
622
710
|
*/
|
623
|
-
newPiece(
|
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#
|
793
|
+
* This is the double of the {@link Puzzle#pieceRadio}
|
705
794
|
*/
|
706
|
-
|
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?:
|
763
|
-
currentPosition?:
|
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:
|
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
|
+
|