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 +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
|
+
|