1"use strict"; 2 3var image = (function() { 4 5 var img; 6 var hsq3 = Math.sqrt(3) / 2; 7 var PI = Math.PI; 8 9 var Rotate = $.ctxRotate; 10 var Transform = $.ctxTransform; 11 var drawPolygon = $.ctxDrawPolygon; 12 13 var clkImage = (function() { 14 function drawClock(svg, color, trans, time) { 15 var points = Transform(Rotate([ 16 [1, 1, 0, -1, -1, -1, 1, 0], 17 [0, -1, -8, -1, 0, 1, 1, 0] 18 ], time / 6 * PI), trans); 19 var x = points[0]; 20 var y = points[1]; 21 svg.addElem('<circle cx="' + x[7] + '" cy="' + y[7] + '" r="' + trans[0] * 9 + '" style="fill:' + color + '" />'); 22 var path = []; 23 path.push('M' + x[0] + ' ' + y[0]); 24 path.push('Q' + x[1] + ' ' + y[1] + ',' + x[2] + ' ' + y[2]); 25 path.push('Q' + x[3] + ' ' + y[3] + ',' + x[4] + ' ' + y[4]); 26 path.push('C' + x[5] + ' ' + y[5] + ',' + x[6] + ' ' + y[6] + ',' + x[0] + ' ' + y[0]); 27 svg.addElem('<path d="' + path.join(' ') + '" style="fill:' + colors[3] + ';stroke:' + colors[0] + '" />'); 28 } 29 30 function drawButton(svg, color, trans) { 31 var points = Transform([[0],[0]], trans); 32 svg.addElem('<circle cx="' + points[0][0] + '" cy="' + points[1][0] + 33 '" r="' + trans[0] * 3 + '" style="fill:' + color + ';stroke:#000;" />'); 34 } 35 36 var width = 3; 37 var movere = /([UD][RL]|ALL|[UDRLy]|all)(?:(\d[+-]?)|\((\d[+-]?),(\d[+-]?)\))?/ 38 var movestr = ['UR', 'DR', 'DL', 'UL', 'U', 'R', 'D', 'L', 'ALL'] 39 var colors = ['#f00', '#37b', '#5cf', '#ff0', '#850']; 40 41 return function(svg, moveseq) { 42 colors = kernel.getProp('colclk').match(colre); 43 var moves = moveseq.split(/\s+/); 44 var moveArr = clock.moveArr; 45 var flip = 9; 46 var buttons = [0, 0, 0, 0]; 47 var clks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 48 for (var i = 0; i < moves.length; i++) { 49 var m = movere.exec(moves[i]); 50 if (!m) { 51 continue; 52 } 53 if (m[0] == 'y2') { 54 flip = 9 - flip; 55 continue; 56 } 57 var axis = movestr.indexOf(m[1]) + flip; 58 if (m[2] == undefined && m[3] == undefined) { 59 buttons[axis % 9] = 1; 60 continue; 61 } 62 var power; 63 var actions = []; 64 if (m[1] == 'all') { 65 power = ~~m[2][0] * (m[2][1] == '+' ? -1 : 1) + 12; 66 actions.push(8 + 9 - flip, power); 67 } else if (m[2]) { 68 power = ~~m[2][0] * (m[2][1] == '+' ? 1 : -1) + 12; 69 actions.push(axis, power); 70 } else { 71 power = ~~m[3][0] * (m[3][1] == '+' ? 1 : -1) + 12; 72 actions.push(axis, power); 73 power = ~~m[4][0] * (m[4][1] == '+' ? -1 : 1) + 12; 74 axis = (10 - axis % 9) % 4 + 4 + 9 - flip; 75 actions.push(axis, power); 76 } 77 for (var k = 0; k < actions.length; k += 2) { 78 for (var j = 0; j < 14; j++) { 79 clks[j] = (clks[j] + moveArr[actions[k]][j] * actions[k + 1]) % 12; 80 } 81 } 82 } 83 clks = [clks[0], clks[3], clks[6], clks[1], clks[4], clks[7], clks[2], clks[5], clks[8], 84 12 - clks[2], clks[10], 12 - clks[8], clks[9], clks[11], clks[13], 12 - clks[0], clks[12], 12 - clks[6] 85 ]; 86 buttons = [buttons[3], buttons[2], buttons[0], buttons[1], 1 - buttons[0], 1 - buttons[1], 1 - buttons[3], 1 - buttons[2]]; 87 88 svg.width = 6.25 * 20 * width; 89 svg.height = 3 * 20 * width; 90 91 var y = [10, 30, 50]; 92 var x = [10, 30, 50, 75, 95, 115]; 93 for (var ii = 0; ii < 18; ii++) { 94 var i = (ii + flip) % 18; 95 drawClock(svg, [colors[1], colors[2]][~~(ii / 9)], [width, x[~~(i / 3)], y[i % 3]], clks[ii]); 96 } 97 98 y = [20, 40]; 99 x = [20, 40, 85, 105]; 100 for (var i = 0; i < 8; i++) { 101 drawButton(svg, [colors[4], colors[3]][buttons[i]], [width, x[~~(i / 2)], y[i % 2]]); 102 } 103 }; 104 })(); 105 106 var sq1Image = (function() { 107 108 var sqa = hsq3 + 1; 109 var sqb = sqa * Math.sqrt(2); 110 var ep = [ 111 [0, -0.5, 0.5], 112 [0, -sqa, -sqa] 113 ]; 114 var cp = [ 115 [0, -0.5, -sqa, -sqa], 116 [0, -sqa, -sqa, -0.5] 117 ]; 118 var cpr = [ 119 [0, -0.5, -sqa], 120 [0, -sqa, -sqa] 121 ]; 122 var cpl = [ 123 [0, -sqa, -sqa], 124 [0, -sqa, -0.5] 125 ]; 126 127 var eps = Transform(ep, [0.66, 0, 0]); 128 var cps = Transform(cp, [0.66, 0, 0]); 129 var cprs = Transform(cpr, [0.66, 0, 0]); 130 var cpls = Transform(cpl, [0.66, 0, 0]); 131 132 var udcol = 'UD'; 133 var ecol = 'R-B-L-F-F-L-B-R-'; 134 var ccol = 'RBBLLFFRRFFLLBBR'; 135 var colors = {
136 'U': '#ff0', 137 'R': '#f80', 138 'F': '#0f0', 139 'D': '#fff', 140 'L': '#f00', 141 'B': '#00f' 142 }; 143 144 var width = 45; 145 146 var movere = /^\s*\(\s*(-?\d+),\s*(-?\d+)\s*\)\s*$/; 147 148 function doMove(move, sc) { 149 if (move[0] != 0) { 150 sc.doMove(move[0]); 151 } 152 if (move[1] != 0) { 153 sc.doMove(-move[1]); 154 } 155 if (move[2] != 0) { 156 sc.doMove(0); 157 } 158 } 159 160 function drawPosit(svg, sc, colors, sq2sc, half) { 161 for (var i = 0; i < (half ? 12 : 24); i++) { 162 var trans = i < 12 ? [width, sqb, sqb] : [width, sqb * 3, sqb]; 163 var val = sc.pieceAt(i); 164 var colorUD = colors[udcol[val >= 8 ? 1 : 0]]; 165 var cRot = -(i < 12 ? (i - 1) : (i - 6)) * PI / 6; 166 var eRot = -(i < 12 ? (i) : (i - 5)) * PI / 6; 167 if (val % 2 == 1) { // corner 168 if (sq2sc) { 169 var cLR = sq2sc.pieceAt(i) & 1; 170 cRot += cLR ? 0 : PI / 6; 171 drawPolygon(svg, colors[ccol[val - cLR]], 172 Rotate(cLR ? cpr : cpl, cRot), trans); 173 drawPolygon(svg, colorUD, 174 Rotate(cLR ? cprs : cpls, cRot), trans); 175 } else { 176 drawPolygon(svg, colors[ccol[val - 1]], 177 Rotate(cpr, cRot), trans); 178 drawPolygon(svg, colors[ccol[val]], 179 Rotate(cpl, cRot), trans); 180 drawPolygon(svg, colorUD, 181 Rotate(cps, cRot), trans); 182 i++; 183 } 184 } else { // edge 185 drawPolygon(svg, colors[ecol[val]], 186 Rotate(ep, eRot), trans); 187 drawPolygon(svg, colorUD, 188 Rotate(eps, eRot), trans); 189 } 190 } 191 } 192 193 function llImage(sc, sq2sc, img) { 194 var svg = new $.svg(); 195 var cols = kernel.getProp('colsq1').match(colre); 196 colors = { 197 'U': cols[0], 198 'R': cols[1], 199 'F': cols[2], 200 'D': cols[3], 201 'L': cols[4], 202 'B': cols[5] 203 }; 204 svg.width = 2 * sqb * width; 205 svg.height = 2 * sqb * width; 206 drawPosit(svg, sc, colors, sq2sc, true); 207 if (img) { 208 img.attr('src', 'data:image/svg+xml;base64,' + btoa(svg.render())); 209 } 210 return svg; 211 } 212 213 function scrImage(svg, moveseq, isSQ2) { 214 var cols = kernel.getProp('colsq1').match(colre); 215 colors = { 216 'U': cols[0], 217 'R': cols[1], 218 'F': cols[2], 219 'D': cols[3], 220 'L': cols[4], 221 'B': cols[5] 222 }; 223 var sc = new sq1.SqCubie(); 224 var sq2sc = null; 225 if (isSQ2) { 226 sq2sc = new sq1.SqCubie(); 227 sq2sc.ul = sq2sc.ur = 0x010010; 228 sq2sc.dl = sq2sc.dr = 0x100100; 229 } 230 var moves = moveseq.split('/'); 231 var tomove = []; 232 for (var i = 0; i < moves.length; i++) { 233 if (/^\s*$/.exec(moves[i])) { 234 tomove.push([0, 0, 1]); 235 continue; 236 } 237 var m = movere.exec(moves[i]); 238 tomove.push([(~~m[1] + 12) % 12, (~~m[2] + 12) % 12, 1]); 239 } 240 tomove.push([0, 0, 1]); 241 for (var i = 0; i < tomove.length; i++) { 242 doMove(tomove[i], sc); 243 sq2sc && doMove(tomove[i], sq2sc); 244 } 245 246 svg.width = 4 * sqb * width; 247 svg.height = 2 * sqb * width; 248 249 //draw middle 250 for (var i = 0; i < 2; i++) { 251 var trans = i == 0 ? [width, sqb, sqb + sqa] : [width, sqb * 3, sqb - sqa - 0.7]; 252 drawPolygon(svg, colors['L'], [[-sqa, -sqa, -0.5, -0.5], [0, 0.7, 0.7, 0]], trans); 253 if (sc.ml == 0) { 254 drawPolygon(svg, colors['L'], [[sqa, sqa, -0.5, -0.5], [0, 0.7, 0.7, 0]], trans); 255 } else { 256 drawPolygon(svg, colors['R'], [[hsq3, hsq3, -0.5, -0.5], [0, 0.7, 0.7, 0]], trans); 257 } 258 } 259 //draw top and bottom 260 drawPosit(svg, sc, colors, sq2sc); 261 262 var recons = []; 263 for (var i = 0; i < moves.length; i++) { 264 if (/^\s*$/.exec(moves[i])) { 265 recons.push('/'); 266 continue; 267 } 268 var m = movere.exec(moves[i]); 269 if (~~m[1]) { 270 recons.push('(' + m[1] + ',0)'); 271 } 272 if (~~m[2]) { 273 recons.push('(0,' + m[2] + ')'); 274 } 275 recons.push('/'); 276 } 277 if (recons.at(-1) == '/') { 278 recons.pop(); 279 } else { 280 recons.push('/'); 281 } 282 return ["~", recons, 'sq1']; 283 } 284 285 return { 286 scrImage: scrImage, 287 llImage: llImage 288 } 289 })(); 290 291 var nnnImage = (function() { 292 var width = 30; 293 294 var posit = []; 295 var colors = ['#ff0', '#fa0', '#00f', '#fff', '#f00', '#0d0']; 296 297 function face(svg, f, size) { 298 var offx = 10 / 9, 299 offy = 10 / 9; 300 if (f == 0) { //D 301 offx *= size; 302 offy *= size * 2; 303 } else if (f == 1) { //L 304 offx *= 0; 305 offy *= size; 306 } else if (f == 2) { //B
307 offx *= size * 3; 308 offy *= size; 309 } else if (f == 3) { //U 310 offx *= size; 311 offy *= 0; 312 } else if (f == 4) { //R 313 offx *= size * 2; 314 offy *= size; 315 } else if (f == 5) { //F 316 offx *= size; 317 offy *= size; 318 } 319 320 for (var i = 0; i < size; i++) { 321 var x = (f == 1 || f == 2) ? size - 1 - i : i; 322 for (var j = 0; j < size; j++) { 323 var y = (f == 0) ? size - 1 - j : j; 324 drawPolygon(svg, colors[posit[(f * size + y) * size + x]], [ 325 [i, i, i + 1, i + 1], 326 [j, j + 1, j + 1, j] 327 ], [width, offx + 0.1, offy + 0.1]); 328 } 329 } 330 } 331 332 /** 333 * f: face, [ D L B U R F ] 334 * d: which slice, in [0, size-1) 335 * q: [ 2 '] 336 */ 337 function doslice(f, d, q, size) { 338 var f1, f2, f3, f4; 339 var s2 = size * size; 340 var c, i, j, k; 341 if (f > 5) f -= 6; 342 for (k = 0; k < q; k++) { 343 for (i = 0; i < size; i++) { 344 if (f == 0) { 345 f1 = 6 * s2 - size * d - size + i; 346 f2 = 2 * s2 - size * d - 1 - i; 347 f3 = 3 * s2 - size * d - 1 - i; 348 f4 = 5 * s2 - size * d - size + i; 349 } else if (f == 1) { 350 f1 = 3 * s2 + d + size * i; 351 f2 = 3 * s2 + d - size * (i + 1); 352 f3 = s2 + d - size * (i + 1); 353 f4 = 5 * s2 + d + size * i; 354 } else if (f == 2) { 355 f1 = 3 * s2 + d * size + i; 356 f2 = 4 * s2 + size - 1 - d + size * i; 357 f3 = d * size + size - 1 - i; 358 f4 = 2 * s2 - 1 - d - size * i; 359 } else if (f == 3) { 360 f1 = 4 * s2 + d * size + size - 1 - i; 361 f2 = 2 * s2 + d * size + i; 362 f3 = s2 + d * size + i; 363 f4 = 5 * s2 + d * size + size - 1 - i; 364 } else if (f == 4) { 365 f1 = 6 * s2 - 1 - d - size * i; 366 f2 = size - 1 - d + size * i; 367 f3 = 2 * s2 + size - 1 - d + size * i; 368 f4 = 4 * s2 - 1 - d - size * i; 369 } else if (f == 5) { 370 f1 = 4 * s2 - size - d * size + i; 371 f2 = 2 * s2 - size + d - size * i; 372 f3 = s2 - 1 - d * size - i; 373 f4 = 4 * s2 + d + size * i; 374 } 375 c = posit[f1]; 376 posit[f1] = posit[f2]; 377 posit[f2] = posit[f3]; 378 posit[f3] = posit[f4]; 379 posit[f4] = c; 380 } 381 if (d == 0) { 382 for (i = 0; i + i < size; i++) { 383 for (j = 0; j + j < size - 1; j++) { 384 f1 = f * s2 + i + j * size; 385 f3 = f * s2 + (size - 1 - i) + (size - 1 - j) * size; 386 if (f < 3) { 387 f2 = f * s2 + (size - 1 - j) + i * size; 388 f4 = f * s2 + j + (size - 1 - i) * size; 389 } else { 390 f4 = f * s2 + (size - 1 - j) + i * size; 391 f2 = f * s2 + j + (size - 1 - i) * size; 392 } 393 c = posit[f1]; 394 posit[f1] = posit[f2]; 395 posit[f2] = posit[f3]; 396 posit[f3] = posit[f4]; 397 posit[f4] = c; 398 } 399 } 400 } 401 } 402 } 403 404 function genPosit(size, moveseq) { 405 var cnt = 0; 406 posit = []; 407 for (var i = 0; i < 6; i++) { 408 for (var f = 0; f < size * size; f++) { 409 posit[cnt++] = i; 410 } 411 } 412 var moves = cubeutil.parseScramble(moveseq, "DLBURF", true); 413 for (var s = 0; s < moves.length; s++) { 414 for (var d = 0; d < moves[s][1]; d++) { 415 doslice(moves[s][0], d, moves[s][2], size) 416 } 417 if (moves[s][1] == -1) { 418 for (var d = 0; d < size - 1; d++) { 419 doslice(moves[s][0], d, -moves[s][2], size); 420 } 421 doslice((moves[s][0] + 3) % 6, 0, moves[s][2] + 4, size); 422 } 423 } 424 return posit; 425 } 426 427 function draw(svg, size, moveseq) { 428 genPosit(size, moveseq); 429 430 svg.width = (39 * size / 9 + 0.2) * width; 431 svg.height = (29 * size / 9 + 0.2) * width; 432 433 colors = kernel.getProp('colcube').match(colre); 434 for (var i = 0; i < 6; i++) { 435 face(svg, i, size); 436 } 437 438 var moves = moveseq.split(/\s+/); 439 var recons = []; 440 for (var i = 0; i < moves.length; i++) { 441 if (moves[i]) { 442 recons.push(moves[i]); 443 } 444 } 445 return ["~", recons, [size, size, size].join('')]; 446 } 447 448 return { 449 draw: draw, 450 genPosit: genPosit 451 } 452 })(); 453 454 var mrblImage = (function() { 455 // image for mirror block 456 var width = 30; 457 var posit = []; 458 var colors = []; 459 460 function getBoundOffset(f, size, i, j) { 461 if (i != 0 && i != size - 1 && j != 0 && j != size - 1) { 462 return [-1, -1, -1, -1]; 463 } 464 // 0 465 // 2 3 466 // 1 467 var D = 0, L = 4, B = 8, U = 12, R = 16, F = 20; 468 var neighbor = [ 469 [F + 1, B + 1, L + 1, R + 1], 470 [U + 2, D + 2, B + 3, F + 2], 471 [U + 0, D + 1, R + 3, L + 2], 472 [B + 0, F + 0, L + 0, R + 0], 473 [U + 3, D + 3, F + 3, B + 2], 474 [U + 1, D + 0, L + 3, R + 2] 475 ][f]; 476 var isBound = [i == 0, i == size - 1, j == 0, j == size - 1]; 477 var ret = [-1, -1, -1, -1]; 478 for (var i1 = 0; i1 < 4; i1++) { 479 if (!isBound[i1]) { 480 continue; 481 } 482 var idx = [size - 1 - j, j, i, size - 1 - i][i1]; 483 var rij = [[0, idx], [size - 1, size - 1 - idx], [size - 1 - idx, 0], [idx, size - 1]][neighbor[i1] & 0x3]; 484 var fidx = neighbor[i1] >> 2; 485 if (fidx == 1 || fidx == 2) { 486 rij[1] = size - 1 - rij[1]; 487 } 488 if (fidx == 0) { 489 rij[0] = size - 1 - rij[0]; 490 } 491 ret[i1] = posit[fidx * size * size + rij[0] * size + rij[1]]; 492 } 493 return ret; 494 } 495 496 function face(svg, f, size) { 497 var offx = (size + 1) / size, 498 offy = (size + 1) / size; 499 if (f == 0) { //D
500 offx *= size; 501 offy *= size * 2; 502 } else if (f == 1) { //L 503 offx *= 0; 504 offy *= size; 505 } else if (f == 2) { //B 506 offx *= size * 3; 507 offy *= size; 508 } else if (f == 3) { //U 509 offx *= size; 510 offy *= 0; 511 } else if (f == 4) { //R 512 offx *= size * 2; 513 offy *= size; 514 } else if (f == 5) { //F 515 offx *= size; 516 offy *= size; 517 } 518 var heights = [0.45, 0.15, 0.3, -0.45, -0.15, -0.3]; 519 for (var i = 0; i < size; i++) { 520 var x = (f == 1 || f == 2) ? size - 1 - i : i; 521 for (var j = 0; j < size; j++) { 522 var y = (f == 0) ? size - 1 - j : j; 523 var off = getBoundOffset(f, size, j, i); 524 for (var i1 = 0; i1 < 4; i1++) { 525 off[i1] = off[i1] == -1 ? 0 : heights[off[i1]]; 526 } 527 drawPolygon(svg, colors[posit[(f * size + y) * size + x]], [ 528 [i - off[2], i - off[2], i + 1 + off[3], i + 1 + off[3]], 529 [j - off[0], j + 1 + off[1], j + 1 + off[1], j - off[0]] 530 ], [width, offx + 0.6, offy + 0.6]); 531 } 532 } 533 } 534 535 return function(svg, size, moveseq) { 536 posit = nnnImage.genPosit(size, moveseq); 537 svg.width = (4 * size + 4 + 0.2) * width; 538 svg.height = (3 * size + 3 + 0.2) * width; 539 colors = kernel.getProp('colcube').match(colre); 540 for (var i = 0; i < 6; i++) { 541 face(svg, i, size); 542 } 543 } 544 })(); 545 546 var gearImage = (function() { 547 548 var moveMaps = [ 549 [3, 2, 1, 0, 4, 11, 12, 13, 14, 15, 16, 5, 6, 7, 8, 9, 10, 68, 69, 19, 20, 89, 73, 74, 75, 94, 95, 82, 28, 29, 30, 100, 101, 25, 85, 86, 36, 37, 21, 90, 91, 92, 26, 27, 99, 45, 46, 47, 32, 33, 42, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 17, 18, 70, 71, 38, 22, 23, 24, 43, 44, 31, 79, 80, 81, 49, 50, 76, 34, 35, 87, 88, 72, 39, 40, 41, 77, 78, 48, 96, 97, 98, 83, 84, 93], 550 [0, 52, 2, 54, 38, 40, 41, 11, 59, 60, 61, 46, 47, 56, 14, 15, 16, 20, 19, 18, 17, 21, 28, 29, 30, 31, 32, 33, 22, 23, 24, 25, 26, 27, 34, 87, 36, 85, 55, 57, 58, 45, 99, 100, 101, 63, 64, 96, 48, 49, 50, 51, 1, 53, 3, 89, 97, 98, 62, 8, 9, 10, 91, 92, 5, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 37, 86, 35, 88, 4, 12, 13, 39, 93, 94, 95, 6, 7, 90, 42, 43, 44], 551 [0, 1, 52, 51, 72, 5, 6, 7, 74, 75, 14, 56, 57, 58, 80, 81, 65, 71, 18, 69, 20, 4, 15, 16, 73, 25, 26, 27, 9, 10, 22, 76, 77, 78, 37, 36, 35, 34, 38, 45, 46, 47, 48, 49, 50, 39, 40, 41, 42, 43, 44, 3, 2, 53, 54, 21, 11, 12, 13, 23, 24, 8, 62, 63, 64, 29, 30, 59, 68, 19, 70, 17, 55, 66, 67, 79, 31, 32, 33, 60, 61, 28, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101] 552 ]; 553 554 return function(svg, moveseq) { 555 var width = 30; 556 svg.width = (39 * 3 / 9 + 0.2) * width; 557 svg.height = (29 * 3 / 9 + 0.2) * width; 558 var state = []; 559 for (var i = 0; i < 17 * 6; i++) { 560 state[i] = ~~(i / 17); 561 } 562 moveseq.replace(/([URF])([23456]?)('?)/g, function(m, g1, g2, g3) { 563 var move = moveMaps["URF".indexOf(g1)]; 564 var pow = ~~g2 || 1; 565 pow = g3 ? (12 - pow) : pow; 566 for (var p = 0; p < pow; p++) { 567 var tmp = []; 568 for (var i = 0; i < 17 * 6; i++) { 569 tmp[i] = state[move[i]]; 570 } 571 state = tmp; 572 } 573 }); 574 var colors = kernel.getProp('colcube').match(colre); 575 for (var f = 0; f < 6; f++) { 576 var offx = 10 / 3 * [1, 2, 1, 1, 0, 3][f], 577 offy = 10 / 3 * [0, 1, 1, 2, 1, 1][f]; 578 for (var s = 0; s < 5; s++) { 579 var x = [0, 2, 0, 2, 1][s], 580 y = [0, 0, 2, 2, 1][s];
581 drawPolygon(svg, colors[(state[f * 17 + s] + 3) % 6], [ 582 [x, x, x + 1, x + 1], 583 [y, y + 1, y + 1, y] 584 ], [width, offx + 0.1, offy + 0.1]); 585 } 586 for (var s = 0; s < 4; s++) { 587 var c1 = state[f * 17 + s * 3 + 5]; 588 var c2 = state[f * 17 + s * 3 + 6]; 589 var c3 = state[f * 17 + s * 3 + 7]; 590 var rot = [ 591 [1, 0, 0, 0, 1, 0], 592 [0, -1, 3, 1, 0, 0], 593 [-1, 0, 3, 0, -1, 3], 594 [0, 1, 0, -1, 0, 3] 595 ][s]; 596 if (c1 == c2 && c2 == c3) { 597 drawPolygon(svg, colors[(c1 + 3) % 6], Transform([ 598 [1, 1, 2, 2], 599 [0, 1, 1, 0] 600 ], rot), [width, offx + 0.1, offy + 0.1]); 601 } else if (c1 == c2) { 602 drawPolygon(svg, colors[(c1 + 3) % 6], Transform([ 603 [1, 1, 2, 1.5], 604 [0, 1, 1, 0] 605 ], rot), [width, offx + 0.1, offy + 0.1]); 606 drawPolygon(svg, colors[(c3 + 3) % 6], Transform([ 607 [1.5, 2, 2], 608 [0, 1, 0] 609 ], rot), [width, offx + 0.1, offy + 0.1]); 610 } else { 611 drawPolygon(svg, colors[(c1 + 3) % 6], Transform([ 612 [1, 1, 1.5], 613 [0, 1, 0] 614 ], rot), [width, offx + 0.1, offy + 0.1]);
615 drawPolygon(svg, colors[(c3 + 3) % 6], Transform([ 616 [1.5, 1, 2, 2], 617 [0, 1, 1, 0] 618 ], rot), [width, offx + 0.1, offy + 0.1]); 619 } 620 } 621 } 622 return svg; 623 } 624 })(); 625 626 /** 627 * last layer image 628 * pieces = U1U2...U9F1..F3R1..L3 629 * B3 B2 B1 630 * L1 U1 U2 U3 R3 631 * L2 U4 U5 U6 R2 632 * L3 U7 U8 U9 R1 633 * F1 F2 F3 634 */ 635 var llImage = (function() { 636 function drawImage(pieces, arrows, img) { 637 var svg = new $.svg(); 638 var colors = kernel.getProp('colcube').match(colre); 639 var dim = 3; 640 if (pieces.length == 12) { 641 dim = 2; 642 } else if (pieces.length == 32) { 643 dim = 4; 644 } 645 var width = 50; 646 svg.width = (dim + 1.2) * width; 647 svg.height = (dim + 1.2) * width; 648 for (var i = 0; i < dim * dim; i++) { 649 var x = i % dim + 0.5; 650 var y = ~~(i / dim) + 0.5; 651 drawPolygon(svg, colors["DLBURF".indexOf(pieces[i])] || '#888', [ 652 [x, x + 1, x + 1, x], 653 [y, y, y + 1, y + 1] 654 ], [width, 0.1, 0.1]); 655 } 656 for (var i = 0; i < dim * 4; i++) { 657 var x = i % dim; 658 var rot = ~~(i / dim); 659 drawPolygon(svg, colors["DLBURF".indexOf(pieces[i + dim * dim])] || '#888', Rotate([ 660 [x - dim / 2, x - dim / 2 + 1, (x - dim / 2 + 1) * 0.9, (x - dim / 2) * 0.9], 661 [dim / 2 + 0.05, dim / 2 + 0.05, dim / 2 + 0.5, dim / 2 + 0.5] 662 ], -rot * PI / 2), [width, 0.6 + dim / 2, 0.6 + dim / 2]); 663 } 664 arrows = arrows || []; 665 for (var i = 0; i < arrows.length; i++) { 666 var arrow = arrows[i]; 667 var x1, y1, x2, y2; 668 if (typeof arrow[0] === 'number') { 669 x1 = arrow[0] % dim + 1.1; 670 y1 = ~~(arrow[0] / dim) + 1.1; 671 } else { 672 x1 = arrow[0][0] + 1.1; 673 y1 = arrow[0][1] + 1.1; 674 } 675 if (typeof arrow[1] === 'number') { 676 x2 = arrow[1] % dim + 1.1; 677 y2 = ~~(arrow[1] / dim) + 1.1; 678 } else { 679 x2 = arrow[1][0] + 1.1; 680 y2 = arrow[1][1] + 1.1; 681 } 682 var length = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); 683 drawPolygon(svg, '#000', Rotate([ 684 [0.2, length - 0.4, length - 0.4, length - 0.1, length - 0.4, length - 0.4, 0.2], 685 [0.05, 0.05, 0.15, 0, -0.15, -0.05, -0.05] 686 ], Math.atan2(y2 - y1, x2 - x1)), [width, x1, y1]); 687 } 688 if (img) { 689 img.attr('src', 'data:image/svg+xml;base64,' + btoa(svg.render())); 690 } 691 return svg; 692 } 693 694 function draw(size, moveseq, img) { 695 var state = nnnImage.genPosit(size, moveseq); 696 var pieces = []; 697 for (var i = 0; i < size * size; i++) { 698 pieces.push("DLBURF"[state[3 * size * size + i]]); 699 } 700 for (var j = 0; j < 4; j++) { 701 var offset = [5, 4, 2, 1][j] * size * size; 702 for (var i = 0; i < size; i++) { 703 var ii = [i, i, size - 1 - i, size - 1 - i][j]; 704 pieces.push("DLBURF"[state[offset + ii]]); 705 } 706 } 707 return drawImage(pieces.join(''), [], img); 708 } 709 710 return { 711 drawImage: drawImage, 712 draw: draw 713 } 714 })(); 715 716 /** 717 * cube image of URF faces 718 * pieces = U1U2...U9R1..R9F1..F9 719 * U1 U3 R3 R9 720 * U7 U9 R1 R7 721 * F1 F3 722 * F7 F9 723 */ 724 var face3Image = (function() { 725 var width = 20; 726 var gap = 1; 727 var ftrans = [ 728 [width * hsq3, -width * hsq3, (width * 3 + gap) * hsq3, width / 2, width / 2, 0], 729 [width * hsq3, 0, (width * 3 + gap * 2) * hsq3, -width / 2, width, width * 3 + gap * 1.5], 730 [width * hsq3, 0, 0, width / 2, width, width * 1.5 + gap * 1.5], 731 ] 732 function drawImage(pieces, img) { 733 var svg = new $.svg(); 734 var colors = kernel.getProp('colcube').match(colre); 735 svg.width = (6 * width + gap * 2) * hsq3; 736 svg.height = (6 * width + gap * 1.5); 737 for (var i = 0; i < 27; i++) { 738 var x = i % 3; 739 var y = ~~(i / 3) % 3; 740 drawPolygon(svg, colors["DLBURF".indexOf(pieces[i])] || '#888', [ 741 [x, x + 1, x + 1, x], 742 [y, y, y + 1, y + 1] 743 ], ftrans[~~(i / 9)]); 744 } 745 if (img) { 746 img.attr('src', 'data:image/svg+xml;base64,' + btoa(svg.render())); 747 } 748 return svg; 749 } 750 return drawImage; 751 })(); 752 753 /** 754 * F1 R1 L1 F2 F3 F4 R L F5.. 755 */ 756 var pyrllImage = (function() { 757 var width = 20; 758 759 function drawImage(pieces, img) { 760 var svg = new $.svg(); 761 svg.width = 6 * hsq3 * width; 762 svg.height = 6 * hsq3 * width; 763 var colors = kernel.getProp('colpyr').match(colre); 764 var idx = 0; 765 for (var i = 0; i < 3; i++) { 766 for (var f = 0; f < 3; f++) { 767 for (var j = 0; j < (i * 2 + 1); j++) { 768 var piece; 769 var x = -hsq3 * i + hsq3 * j; 770 var y = i / 2; 771 if (j % 2 == 0) { 772 piece = [[x, x - hsq3, x + hsq3], [y, y + 0.5, y + 0.5]]; 773 } else { 774 piece = [[x - hsq3, x, x + hsq3], [y, y + 0.5, y]]; 775 } 776 drawPolygon(svg, colors["FLRD".indexOf(pieces[idx])] || '#888', Rotate(piece, PI / 3 * 4 * f), [width, 3 * hsq3, 3 + (6 * hsq3 - 4.5) / 2]); 777 idx++; 778 } 779 } 780 } 781 if (img) { 782 img.attr('src', 'data:image/svg+xml;base64,' + btoa(svg.render())); 783 } 784 return svg; 785 } 786 return drawImage; 787 })(); 788 789 var polyhedronImage = (function() { 790 var puzzleCache = {}; 791 792 return function(svg, type, moveseq, faceNameMask, minArea) { 793 var colors = []; 794 var moves = []; 795 minArea = minArea || 0; 796 var gap = 0.05; 797 var puzzle = puzzleCache[type]; 798 799 var params = poly3d.getFamousPuzzle(type); 800 if (params != null) { 801 puzzle = puzzle || poly3d.makePuzzle.apply(poly3d, params.polyParam); 802 params.parser = params.parser || poly3d.makePuzzleParser(puzzle); 803 moves = params.parser.parseScramble(moveseq); 804 gap = params.pieceGap; 805 colors = params.colors; 806 } else { 807 debugger; // unknown puzzle 808 } 809 810 DEBUG && console.log('[polyhedron image] puzzle=', puzzle, 'moves=', moves); 811 puzzleCache[type] = puzzle; 812 var poly2d = poly3d.renderNet(puzzle, gap, minArea); 813 var sizes = poly2d[0]; 814 var polys = poly2d[1]; 815 var faces = poly2d[2]; 816 var posit = []; 817 for (var i = 0; i < polys.length; i++) {
818 posit[i] = polys[i] && polys[i][2]; 819 } 820 for (var midx = 0; midx < moves.length; midx++) { 821 var move = moves[midx]; 822 var moveIdx = puzzle.getTwistyIdx(move[0]); 823 if (moveIdx == -1) { 824 debugger; // error, cannot find move permutations 825 } 826 var perm = puzzle.moveTable[moveIdx]; 827 var maxPow = puzzle.twistyDetails[moveIdx][1]; 828 var pow = (move[1] % maxPow + maxPow) % maxPow; 829 var posit2 = []; 830 for (var i = 0; i < posit.length; i++) { 831 var val = i; 832 for (var j = 0; j < pow; j++) { 833 val = perm[val] < 0 ? val : perm[val]; 834 } 835 posit2[i] = posit[val]; 836 } 837 posit = posit2; 838 } 839 if (type == 'skb') { 840 colors = $.col2std(kernel.getProp("colskb"), [0, 2, 4, 3, 5, 1]) 841 var trans = [ 842 [hsq3, -hsq3, hsq3 * 2, 0.5, 0.5, -1], 843 [hsq3, 0, 0, -0.5, 1, 2], 844 [hsq3, 0, 0, 0.5, 1, -2], 845 [hsq3, 0, 0, 0.5, 1, -2], 846 [hsq3, 0, 0, 0.5, 1, -2], 847 [hsq3, 0, 0, -0.5, 1, 2] 848 ]; 849 for (var i = 0; i < 6; i++) { 850 for (var j = 0; j < 6; j++) { 851 if (j % 3 != 2) { 852 trans[i][j] *= 8 / sizes[0]; 853 } 854 } 855 } 856 for (var i = 0; i < polys.length; i++) { 857 if (!polys[i]) { 858 continue; 859 } 860 var poly = Transform(polys[i], trans[polys[i][2]]); 861 polys[i][0] = poly[0]; 862 polys[i][1] = poly[1]; 863 } 864 sizes = [8 * hsq3, 6]; 865 } 866 var scale = Math.min(1.6 / sizes[0], 1.0 / sizes[1]) * 300; 867 svg.width = sizes[0] * scale; 868 svg.height = sizes[1] * scale; 869 for (var i = 0; i < colors.length; i++) { 870 colors[i] = '#' + colors[i].toString(16).padStart(6, '0'); 871 } 872 for (var i = 0; i < posit.length; i++) { 873 polys[i] && drawPolygon(svg, colors[posit[i]], polys[i], [scale, 0, 0, 0, scale, 0]); 874 } 875 for (var i = 0; i < faces.length; i++) { 876 if ((faceNameMask >> i & 1) == 0) { 877 continue; 878 } 879 var face = faces[i]; 880 svg.addText(face[2].toUpperCase(), [face[0] * scale, face[1] * scale], { 881 'font': '20px Arial', 882 'fill': kernel.getProp('col-font'), 883 'stroke': kernel.getProp('col-board'), 884 'stroke-width': '3px' 885 }); 886 } 887 var recons = []; 888 for (var midx = 0; midx < moves.length; midx++) { 889 recons.push(params.parser.move2str(moves[midx])); 890 } 891 return ["~", recons, type]; 892 } 893 })(); 894 895 896 var sldImage = (function() { 897 898 return function(svg, type, size, moveseq) { 899 var width = 50; 900 var gap = 0.05; 901 902 var state = []; 903 var effect = [ 904 [1, 0], 905 [0, 1], 906 [0, -1], 907 [-1, 0] 908 ]; 909 for (var i = 0; i < size * size; i++) { 910 state[i] = i; 911 } 912 var x = size - 1; 913 var y = size - 1; 914 915 var movere = /([ULRD\uFFEA\uFFE9\uFFEB\uFFEC])([\d]?)/; 916 moveseq = moveseq.split(' '); 917 for (var s = 0; s < moveseq.length; s++) { 918 var m = movere.exec(moveseq[s]); 919 if (!m) { 920 continue; 921 } 922 var turn = 'ULRD\uFFEA\uFFE9\uFFEB\uFFEC'.indexOf(m[1]) % 4; 923 var pow = ~~m[2] || 1; 924 var eff = effect[type == 'b' ? 3 - turn : turn]; 925 for (var p = 0; p < pow; p++) { 926 mathlib.circle(state, x * size + y, (x + eff[0]) * size + y + eff[1]); 927 x += eff[0]; 928 y += eff[1]; 929 } 930 } 931 932 svg.width = (size + gap * 4) * width; 933 svg.height = (size + gap * 4) * width; 934 935 var cols = kernel.getProp('col15p').match(colre); 936 cols[size - 1] = cols.at(-1); 937 for (var i = 0; i < size; i++) { 938 for (var j = 0; j < size; j++) { 939 var val = state[j * size + i]; 940 var colorIdx = Math.min(~~(val / size), val % size); 941 val++; 942 drawPolygon(svg, cols[colorIdx], [ 943 [i + gap, i + gap, i + 1 - gap, i + 1 - gap], 944 [j + gap, j + 1 - gap, j + 1 - gap, j + gap] 945 ], [width, gap * 2, gap * 2]); 946 if (val == size * size) { 947 continue; 948 } 949 svg.addText(val, [width * (i + 0.5 + gap * 2), width * (j + 0.5 + gap * 2)], { 950 'font': width * 0.6 + 'px Arial', 951 'fill': '#000' 952 }); 953 } 954 } 955 } 956 })(); 957 958 var types_nnn = ['222', '333', '444', '555', '666', '777', '888', '999', '101010', '111111']; 959
960 function renderSVG(svg, scramble) { 961 var type = scramble[0]; 962 if (type == 'input') { 963 type = tools.scrambleType(scramble[1]); 964 } 965 type = tools.puzzleType(type); 966 var size = types_nnn.indexOf(type); 967 var recons = 0; 968 if (size >= 0) { 969 recons = nnnImage.draw(svg, size + 2, scramble[1]); 970 } else if (type == "cubennn") { 971 nnnImage.draw(svg, scramble[2], scramble[1]); 972 } else if (poly3d.udpolyre.exec(type)) { 973 var faceNameMask = 0; 974 if (/^prc|giga|mgm|klm$/.exec(type)) { 975 faceNameMask = 0x3; 976 } else if (type == 'fto') { 977 faceNameMask = 0xff; 978 } else if (type == 'ctico') { 979 faceNameMask = 0xfffff; 980 } 981 recons = polyhedronImage(svg, type, scramble[1], faceNameMask, type == 'klm' ? 0.1 : 0); 982 } else if (type == "sq1" || type == "sq2") { 983 recons = sq1Image.scrImage(svg, scramble[1], type == "sq2"); 984 } else if (type == "clk") { 985 clkImage(svg, scramble[1]); 986 } else if (type == "gear") { 987 gearImage(svg, scramble[1]); 988 } else if (type == "mrbl") { 989 mrblImage(svg, 3, scramble[1]); 990 } else if (type == "15b" || type == "15p") { 991 sldImage(svg, type[2], 4, scramble[1]); 992 } else if (type == "8b" || type == "8p") { 993 sldImage(svg, type[1], 3, scramble[1]); 994 } else if (/^r(3(ni)?|23\d+w?|mngf)$/.exec(type)) { 995 var subScrs = []; 996 scramble[1].replaceAll(/(?:^|\n)\s*(\d+|3oh|pyr|skb|sq1|clk|mgm)\)\s*([^\0]*?)\s*(?=\n.*\)|$)/g, function(m, p1, p2) { 997 var subType = type.startsWith('r3') ? '333' : 998 type == 'rmngf' ? p1.replace('3oh', '333').padEnd(3, p1): 999 types_nnn[subScrs.length]; 1000 subScrs.push([subType, p2, 0]); 1001 }); 1002 var n_height = Math.ceil(Math.sqrt(subScrs.length)); 1003 var n_width = Math.ceil(subScrs.length / n_height); 1004 var GRID_WIDTH = 240; 1005 var GRID_HEIGHT = 150; 1006 svg.width = n_width * GRID_WIDTH; 1007 svg.height = n_height * GRID_HEIGHT; 1008 for (var i = 0; i < subScrs.length; i++) { 1009 var x = i % n_width * GRID_WIDTH; 1010 var y = ~~(i / n_width) * GRID_HEIGHT; 1011 var subSvg = new $.svg(); 1012 renderSVG(subSvg, subScrs[i]); 1013 svg.addElem(subSvg.renderGroup(x, y, GRID_WIDTH, GRID_HEIGHT)); 1014 svg.addText((i + 1).toString(), [x, y], { 1015 'font': '40px Arial', 1016 'fill': kernel.getProp('col-font') 1017 }, 1); 1018 } 1019 } else { 1020 return -1; 1021 } 1022 return recons; 1023 } 1024 1025 function genImage(scramble, renderTool) { 1026 var svg = new $.svg(); 1027 var recons = renderSVG(svg, scramble); 1028 if (recons == -1) { // not available 1029 return false; 1030 } 1031 if (!renderTool) { 1032 return svg; 1033 } 1034 var scale = Math.min(1.6 / svg.width, 1.0 / svg.height) * kernel.getProp('imgSize') * 0.6; 1035 img.attr('src', 'data:image/svg+xml;base64,' + btoa(svg.render())); 1036 img.width(svg.width * scale + 'em'); 1037 img.height(svg.height * scale + 'em'); 1038 1039 if (recons && kernel.getProp('imgRep')) { 1040 for (var i = 0; i < recons[1].length; i++) { 1041 recons[1][i] = recons[1][i] + '@' + (i + 1) * 1000; 1042 } 1043 recons[1] = recons[1].join(' '); 1044 img.click(function(recons) { 1045 replay.popupReplay.apply(null, recons); 1046 }.bind(null, recons)); 1047 } else { 1048 img.click(function(svg, scale) { 1049 var popImg = $('<img style="display:block;">'); 1050 popImg.attr('src', 'data:image/svg+xml;base64,' + btoa(svg.render())); 1051 popImg.css('object-fit', 'contain'); 1052 kernel.showDialog([popImg, $.noop, undefined, $.noop], 'share', TOOLS_IMAGE); 1053 }.bind(null, svg, scale)); 1054 } 1055 return true; 1056 } 1057 1058 ISCSTIMER && execMain(function() { 1059 function execFunc(fdiv) { 1060 if (!fdiv) { 1061 return; 1062 } 1063 img = img || $('<img style="display:block;">'); 1064 fdiv.empty().append(img); 1065 if (!genImage(tools.getCurScramble(), true)) { 1066 fdiv.html(IMAGE_UNAVAILABLE); 1067 } 1068 } 1069 1070 $(function() { 1071 tools.regTool('image', TOOLS_IMAGE, execFunc); 1072 }); 1073 }); 1074 1075 var colre = /#[0-9a-fA-F]{3}/g; 1076 1077 return { 1078 draw: genImage, 1079 llImage: llImage, 1080 pyrllImage: pyrllImage, 1081 face3Image: face3Image, 1082 sqllImage: sq1Image.llImage 1083 } 1084})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.