Created
March 13, 2018 13:45
-
-
Save anonymous/c03066092f346bcd42dd2f3a9799fae9 to your computer and use it in GitHub Desktop.
Print an 11"x8.5" page of fiduciary symbols for the Shaper Origin.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="266.7mm" height="203.2mm" viewBox="0 0 266.7 203.2"> | |
<g class="domino"> | |
<rect x="0" y="0" width="43" height="12.7" rx="2.5" ry="2.5" fill="black"/> | |
<circle r="1.25" cx="4" cy="3.8" fill="white" /> | |
<circle r="1.25" cx="4" cy="8.9" fill="white" /> | |
<g class="inner-dots"> | |
<circle r="1.25" cx="9" cy="3.8" fill="white" /> | |
<circle r="1.25" cx="14" cy="3.8" fill="white" /> | |
<circle r="1.25" cx="19" cy="3.8" fill="white" /> | |
<circle r="1.25" cx="24" cy="3.8" fill="white" /> | |
<circle r="1.25" cx="29" cy="3.8" fill="white" /> | |
<circle r="1.25" cx="34" cy="3.8" fill="white" /> | |
<circle r="1.25" cx="9" cy="8.9" fill="white" /> | |
<circle r="1.25" cx="14" cy="8.9" fill="white" /> | |
<circle r="1.25" cx="19" cy="8.9" fill="white" /> | |
<circle r="1.25" cx="24" cy="8.9" fill="white" /> | |
<circle r="1.25" cx="29" cy="8.9" fill="white" /> | |
<circle r="1.25" cx="34" cy="8.9" fill="white" /> | |
</g> | |
<circle r="1.25" cx="39" cy="3.8" fill="white" /> | |
<circle r="1.25" cx="39" cy="8.9" fill="white" /> | |
</g> | |
<text class="page" x="261" y="6" style="font-size: 6"></text> | |
<script>//<![CDATA[ | |
/** | |
* Convert a number from 0..4095 to a 12-character sequence of 1's and 0's | |
*/ | |
let bitStream = num => { | |
let bits = num.toString(2); | |
while (bits.length < 12) { | |
bits = '0' + bits; | |
} | |
return bits; | |
}; | |
/** | |
* Hash a number from 0..4095 to a bit, using a linear feedback shift register | |
* The LFSR is used because the numbers we'll feed into this will always have 6 | |
* high bits; the introduction of a shift-modulo messes with that, so each number | |
* will have a different value - one that's not necessarily tied to the LSB. | |
*/ | |
let checkSum = num => { | |
let low = num & 1; | |
num = ((num >> 1) ^ 7185 || low << 12) & 0xFFF; | |
return num.toString(2).replace(/0/g, '').length & 1; | |
}; | |
/** | |
* Test the fiduciary features of a number. | |
*/ | |
let isValid = num => { | |
let bits = bitStream(num); | |
let top = bits.substr(0, 6); | |
let btm = bits.substr(6); | |
// Six interior dots must be filled | |
if (bits.replace(/0/g, '').length !== 6) { | |
return false; | |
} | |
// At least one bit must be in each row | |
if (top === '111111') return false; | |
if (top === '000000') return false; | |
// Must not be rotational inverse of self | |
let flp = parseInt(btm.split('').reverse().join('') + top.split('').reverse().join(''), 2); | |
if (flp === num) { | |
return false; | |
} | |
// Using checksum to arbitrarily decide wheter to take high or low of rotational pair | |
let sum = checkSum(num); | |
if ((sum === 1 && flp < num) || (sum === 0 && flp > num)) { | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* Run through the possible space | |
*/ | |
let generateAll = () => { | |
let e = {}; | |
for (var i = 0; i < 4096; i++) { | |
if (isValid(i)) { | |
e[i] = true; | |
} | |
} | |
return e; | |
} | |
// 'cept we can pre-generate them, and should. | |
// let all = Object.keys(generateAll()).sort(() => Math.random() > 0.5 ? 1 : -1).map(n=>parseInt(n)); | |
let all = [2158,3920,1988,1000,3603,1260,3780,2841,3496,2358,2282,3636,3132,2412,3274,3237,1904,2744,3270,1776,2764,3752,3040,3250,2222,3724,2978,2292,3729,3684,2166,2738,3658,3282,2900,3784,1944,2792,2892,2230,3597,1650,3372,2262,3524,2481,2502,3102,984,3504,3905,3849,3157,2830,1954,3736,3370,3412,3746,2665,3425,3473,3267,1706,2842,3349,3745,2474,888,3249,3808,2673,948,2390,3906,2284,3312,1644,2268,996,2956,2506,3612,3459,3440,1490,2776,3118,2730,3777,3970,3341,2914,2652,3606,2529,1720,2110,2666,1594,1768,3912,3117,3846,2857,3696,1458,1512,2364,2897,1738,2890,3626,1692,2949,1862,3297,3158,3012,2904,3748,2476,1482,2737,3474,1436,3908,1508,3363,3241,1496,3969,1932,1866,1708,2516,3528,3860,2236,1450,3288,3621,3490,1746,2614,2713,1842,3369,3625,2418,2674,2992,1520,2858,3876,3552,2762,1212,2785,3350,1748,3228,3235,2732,3428,3651,2646,3864,3409,3880,3634,2886,3242,3221,2837,2638,2446,1734,2514,1764,3410,3850,2680,1820,3226,1740,3009,3843,2482,1492,2770,3858,1896,1400,3173,1596,3404,3342,1830,2962,3380,2980,3888,3416,1834,3465,3402,2668,3213,2420,2488,3354,3192,3298,2254,1818,2000,3304,2606,3468,2800,2761,1396,3521,2710,3225,3185,2484,940,2916,3721,3010,760,3622,3480,2206,1960,1628,3300,2968,2530,1814,2473,3101,2618,2872,1968,1848,3149,2868,1626,1394,3857,3972,1752,1874,2729,2786,3522,2508,2865,2757,3873,2961,2953,1460,2266,2920,2702,2650,2460,2838,3760,1642,2290,1992,3653,3366,3188,2142,1340,2725,1452,2788,1690,2362,2758,3398,3353,2513,3276,3633,3640,3214,1244,3126,3476,2977,3462,3162,3395,3466,3281,2885,3180,3284,2662,2454,3688,2382,2544,884,2716,1762,3718,3717,3252,3666,2532,1956,2649,3130,3244,2913,1656,3161,3609,3492,3672,3384,3125,1652,1836,980,1388,2505,1890,1272,2296,1008,3715,2860,3365,2866,1372,1986,3668,3976,2590,2617,2234,3461,4000,2394,3536,2417,3730,1484,1702,2676,3269,1938,3426,3150,3936,972,3852,3682,3129,1876,2772,3177,3874,1506,2458,3598,3665,2726,2620,2854,2898,2278,2016,1940,1844,1268,2844,2954,2769,3778,2410,3378,3792,1930,2406,2350,2172,3845,3164,3660,3722,3401,2853,3377,3984,3256,3273,3619,3174,2424,1926,3186,1868,952,2470,3605,3657,3610,2950,3432,2740,2984,3222,3595,3178,3238,2396,3356,1716,1892,2889,3681,2334,3628,2520,3654,2714,1148,1880,2170,3397,3732,1714,3016,2964,2536,3489,3024,2928,1464,3347]; | |
let tpl = document.querySelector('g.domino'); | |
let pageNo = document.querySelector('text.page'); | |
tpl.parentNode.removeChild(tpl); | |
pageNo.parentNode.removeChild(pageNo); | |
let addDomino = (column, row, index) => { | |
let inst = tpl.cloneNode(true); | |
let num = all[index % all.length]; | |
inst.setAttribute('transform', `translate(${53*column+5}, ${17.7*row})`); | |
[].forEach.call(inst.querySelectorAll('g.inner-dots circle'), (dot, index) => { | |
if (((num >> index) & 1) === 0) { | |
dot.parentNode.removeChild(dot); | |
} | |
}); | |
document.documentElement.appendChild(inst); | |
}; | |
let pageWidth = 5; | |
let pageHeight = 11; | |
let drawPage = page => { | |
while (document.documentElement.childNodes.length) { | |
document.documentElement.removeChild(document.documentElement.childNodes[0]); | |
} | |
for (var row = 0; row < pageHeight; row++) { | |
for (var column = 0; column < pageWidth; column++) { | |
addDomino(column, row, row*pageWidth+column + page * pageWidth * pageHeight); | |
} | |
} | |
let ns = document.documentElement.namespaceURI; | |
let ctr = pageNo.cloneNode(true); | |
ctr.textContent = page; | |
document.documentElement.appendChild(ctr); | |
}; | |
let page = 0; | |
drawPage(page); | |
document.documentElement.addEventListener('keydown', e => { | |
if (e.key === 'PageUp') { | |
if (page > 0) { page -= 1; drawPage(page); } | |
} | |
if (e.key === 'PageDown') { | |
page += 1; drawPage(page); | |
} | |
}); | |
//]]></script> | |
</svg> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment