mumuki-puzzle-runner 0.3.0 → 0.4.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/css/muzzle-editor.css +10 -1
- data/lib/public/js/muzzle-editor.js +26 -13
- data/lib/public/js/muzzle.js +58 -6
- 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: 5da4e03efe5edbeb4e6eadfaf79f5d37e4f5bea50127a26e91c5f6d2cedb2438
|
4
|
+
data.tar.gz: f0eeb8f873165d98ecfcc04854aa4fb781d4753fc4350bcfed90fd24c184744b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c98b0e5f9fe633c8fb0587b3c948ce0a6d6d79b80619befc28bc4c583578be596b1d8d2d9f61fddbb3241a320424b602af417fca96827c632a9537342d2a62e9
|
7
|
+
data.tar.gz: f40b2c76b102651f25ca76eda5b82d24f6cb037e92efcbd68299d634ec8a4f8a22477f4639893b780f6e8f44e790761189c43c12a925a5421f8e33416b3273af
|
@@ -1,5 +1,13 @@
|
|
1
1
|
// @ts-nocheck
|
2
2
|
$(() => {
|
3
|
+
function register(event, callback) {
|
4
|
+
const _event = Muzzle[event];
|
5
|
+
Muzzle[event] = (...args) => {
|
6
|
+
callback(...args);
|
7
|
+
_event(...args);
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
3
11
|
// ================
|
4
12
|
// Muzzle rendering
|
5
13
|
// ================
|
@@ -29,39 +37,44 @@ $(() => {
|
|
29
37
|
|
30
38
|
// Requiered to actually bind Muzzle's submit to
|
31
39
|
// mumuki's solution processing
|
32
|
-
|
33
|
-
Muzzle.onSubmit = (submission) => {
|
40
|
+
register('onSubmit', (submission) => {
|
34
41
|
mumuki.submission.processSolution(submission);
|
35
|
-
|
36
|
-
}
|
42
|
+
});
|
37
43
|
|
38
44
|
// ===========
|
39
45
|
// Kids config
|
40
46
|
// ===========
|
41
47
|
|
42
|
-
// Required to make scaler work
|
43
48
|
mumuki.kids.registerStateScaler(($state, fullMargin, preferredWidth, preferredHeight) => {
|
44
|
-
//
|
45
|
-
// no state scaling needed
|
49
|
+
// no manul image scalling. Leave it to css
|
46
50
|
});
|
51
|
+
|
47
52
|
mumuki.kids.registerBlocksAreaScaler(($blocks) => {
|
48
|
-
const
|
49
|
-
Muzzle.scale($blocks.width(), Math.min($blocks.height(),
|
53
|
+
const maxHeight = $('.mu-kids-exercise').height() - $('.mu-kids-exercise-description').height();
|
54
|
+
Muzzle.scale($blocks.width(), Math.min($blocks.height(), maxHeight));
|
50
55
|
});
|
51
56
|
|
52
57
|
Muzzle.manualScale = true;
|
53
58
|
|
59
|
+
// ====================
|
60
|
+
// Submit button hiding
|
61
|
+
// ====================
|
62
|
+
|
63
|
+
register('onReady', () => {
|
64
|
+
if (Muzzle.simple) {
|
65
|
+
$('.mu-kids-exercise-workspace').addClass('muzzle-simple');
|
66
|
+
}
|
67
|
+
});
|
68
|
+
|
54
69
|
// ==============
|
55
70
|
// Assets loading
|
56
71
|
// ==============
|
57
72
|
|
58
|
-
|
59
|
-
Muzzle.onReady = () => {
|
73
|
+
register('onReady', () => {
|
60
74
|
mumuki.assetsLoadedFor('editor');
|
61
75
|
// although layout assets
|
62
76
|
// are actually loaded before this script, puzzle runner is not aimed
|
63
77
|
// to be used without a custom editor
|
64
78
|
mumuki.assetsLoadedFor('layout');
|
65
|
-
|
66
|
-
};
|
79
|
+
});
|
67
80
|
});
|
data/lib/public/js/muzzle.js
CHANGED
@@ -136,7 +136,17 @@ class MuzzleCanvas {
|
|
136
136
|
*
|
137
137
|
* @type {string}
|
138
138
|
*/
|
139
|
-
this.previousSolutionContent = null
|
139
|
+
this.previousSolutionContent = null;
|
140
|
+
|
141
|
+
/**
|
142
|
+
* Whether the current puzzle can be solved in very few tries.
|
143
|
+
*
|
144
|
+
* Set null for automatic configuration of this property. Basic puzzles will be considered
|
145
|
+
* basic and match puzzles will be considered non-basic.
|
146
|
+
*
|
147
|
+
* @type {boolean}
|
148
|
+
*/
|
149
|
+
this.simple = null;
|
140
150
|
|
141
151
|
/**
|
142
152
|
* Callback to be executed when submitting puzzle.
|
@@ -167,7 +177,7 @@ class MuzzleCanvas {
|
|
167
177
|
width: this.canvasWidth,
|
168
178
|
height: this.canvasHeight,
|
169
179
|
pieceSize: pieceSize,
|
170
|
-
proximity: pieceSize.x / 5,
|
180
|
+
proximity: Math.min(pieceSize.x, pieceSize.y) / 5,
|
171
181
|
borderFill: this.borderFill === null ? headbreaker.Vector.divide(pieceSize, 10) : this.borderFill,
|
172
182
|
strokeWidth: this.strokeWidth,
|
173
183
|
lineSoftness: 0.18
|
@@ -228,6 +238,10 @@ class MuzzleCanvas {
|
|
228
238
|
this.aspectRatio = x / y;
|
229
239
|
}
|
230
240
|
|
241
|
+
if (this.simple === null) {
|
242
|
+
this.simple = true;
|
243
|
+
}
|
244
|
+
|
231
245
|
/**
|
232
246
|
* @todo take all container size
|
233
247
|
**/
|
@@ -389,11 +403,11 @@ class MuzzleCanvas {
|
|
389
403
|
this._canvas.onValid(() => {
|
390
404
|
setTimeout(() => this.onValid(), 0);
|
391
405
|
});
|
392
|
-
this.
|
406
|
+
this._setUpScaler();
|
393
407
|
this.ready();
|
394
408
|
}
|
395
409
|
|
396
|
-
|
410
|
+
_setUpScaler() {
|
397
411
|
if (this.manualScale) return;
|
398
412
|
|
399
413
|
['resize', 'load'].forEach((event) => {
|
@@ -405,10 +419,39 @@ class MuzzleCanvas {
|
|
405
419
|
}
|
406
420
|
|
407
421
|
scale(width, height) {
|
408
|
-
if (this.fixedDimensions) return;
|
422
|
+
if (this.fixedDimensions || !this.canvas) return;
|
423
|
+
const factor = this.optimalScaleFactor(width, height);
|
409
424
|
this.canvas.resize(width, height);
|
410
|
-
this.canvas.scale(
|
425
|
+
this.canvas.scale(factor);
|
411
426
|
this.canvas.redraw();
|
427
|
+
this.focus();
|
428
|
+
}
|
429
|
+
|
430
|
+
focus() {
|
431
|
+
const stage = this.canvas['__konvaLayer__'].getStage();
|
432
|
+
|
433
|
+
const area = headbreaker.Vector.divide(headbreaker.vector(stage.width(), stage.height()), stage.scaleX());
|
434
|
+
const realDiameter = (() => {
|
435
|
+
const [xs, ys] = this.coordinates;
|
436
|
+
|
437
|
+
const minX = Math.min(...xs);
|
438
|
+
const minY = Math.min(...ys);
|
439
|
+
|
440
|
+
const maxX = Math.max(...xs);
|
441
|
+
const maxY = Math.max(...ys);
|
442
|
+
|
443
|
+
return headbreaker.Vector.plus(headbreaker.vector(maxX - minX, maxY - minY), this.canvas.puzzle.pieceDiameter);
|
444
|
+
})();
|
445
|
+
const diff = headbreaker.Vector.minus(area, realDiameter);
|
446
|
+
const semi = headbreaker.Vector.divide(diff, -2);
|
447
|
+
|
448
|
+
stage.setOffset(semi);
|
449
|
+
stage.draw();
|
450
|
+
}
|
451
|
+
|
452
|
+
get coordinates() {
|
453
|
+
const points = this.canvas.puzzle.points;
|
454
|
+
return [points.map(([x, _y]) => x), points.map(([_x, y]) => y)];
|
412
455
|
}
|
413
456
|
|
414
457
|
optimalScaleFactor(width, height) {
|
@@ -422,6 +465,7 @@ class MuzzleCanvas {
|
|
422
465
|
*/
|
423
466
|
ready() {
|
424
467
|
this.loadPreviousSolution();
|
468
|
+
this.resetCoordinates();
|
425
469
|
this.draw();
|
426
470
|
this.onReady();
|
427
471
|
}
|
@@ -447,6 +491,7 @@ class MuzzleCanvas {
|
|
447
491
|
*/
|
448
492
|
loadSolution(solution) {
|
449
493
|
this.canvas.puzzle.relocateTo(solution.positions);
|
494
|
+
this.canvas.puzzle.autoconnect();
|
450
495
|
}
|
451
496
|
|
452
497
|
/**
|
@@ -463,6 +508,13 @@ class MuzzleCanvas {
|
|
463
508
|
}
|
464
509
|
}
|
465
510
|
|
511
|
+
resetCoordinates() {
|
512
|
+
const [xs, ys] = this.coordinates;
|
513
|
+
const minX = Math.min(...xs);
|
514
|
+
const minY = Math.min(...ys);
|
515
|
+
this.canvas.puzzle.translate(-minX, -minY);
|
516
|
+
}
|
517
|
+
|
466
518
|
// ==========
|
467
519
|
// Submitting
|
468
520
|
// ==========
|
data/lib/version_hook.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mumuki-puzzle-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Franco Leonardo Bulgarelli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mumukit
|