mumuki-puzzle-runner 0.3.0 → 0.4.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/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
|