Last active
June 24, 2024 17:46
-
-
Save depperm/b488262529cd216d7d8db0f75affb09a to your computer and use it in GitHub Desktop.
PaCK System
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
<html> | |
<style> | |
table { | |
line-height: 120%; | |
font-family: Consolas, monaco, monospace; | |
/*72pt:1in*/ | |
font-size: 9pt; | |
} | |
.good { | |
background: greenyellow; | |
} | |
.error { | |
background: red; | |
} | |
.globaltd { | |
width: 18pt; | |
text-align: center; | |
line-height: 9pt; | |
} | |
.normal tr td.globaltd { | |
border-bottom: 1px solid #8c8; | |
} | |
.color{ | |
background:#8c8; | |
} | |
.normal td:first-child { | |
border-left: 1px solid #8c8; | |
} | |
.normal tr:first-child td { | |
border-top: 1px solid #8c8; | |
} | |
.normal td:last-child { | |
border-right: 1px solid #8c8; | |
} | |
.char2 { | |
background: #ddffdd; | |
} | |
</style> | |
<body> | |
Seed <input type="text" id="seed" value="test" onkeyup="generateTable()"> Curr Entropy: <span id="entropy"></span> (Will turn green with 80+ entropy) | |
<br> | |
<p> | |
<b>Recommended Size:</b> | |
<ul> | |
<li>Keychain (1 1/8"x2 7/8"): 4x9</li> | |
<li>Credit Card (2 1/4"x3 1/2"): 8x14</li> | |
<li>Business Card (2"x3 1/2"): TODO</li> | |
<li>Index Card (3"x5"): TODO</li> | |
</ul> | |
</p> | |
Width <input type="number" id="width" minimum="2" class="dimensions" value="7" onchange="generateTable()"> | |
<br> | |
Height <input type="number" id="height" minimum="2" class="dimensions" value="4" onchange="generateTable()"> | |
<br> | |
<br> | |
<div id="grid-container"> | |
</div> | |
<span>https://codepen.io/depperm/pen/PogvaYN</span> | |
</body> | |
<script> | |
// Copyright (c) 2017-2020, W. "Mac" McMeans | |
// All rights reserved. | |
// https://github.com/macmcmeans/aleaPRNG | |
function Mash() { | |
var n = 0xefc8249d; | |
var mash = function (data) { | |
data = data.toString(); | |
for (var i = 0; i < data.length; i++) { | |
n += data.charCodeAt(i); | |
var h = 0.02519603282416938 * n; | |
n = h >>> 0; | |
h -= n; | |
h *= n; | |
n = h >>> 0; | |
h -= n; | |
n += h * 0x100000000; // 2^32 | |
} | |
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 | |
}; | |
mash.version = "Mash 0.9"; | |
return mash; | |
} | |
function Alea(...args) { | |
let s0 = 0; | |
let s1 = 0; | |
let s2 = 0; | |
let c = 1; | |
if (args.length == 0) { | |
args = [+new Date()]; | |
} | |
var mash = Mash(); | |
s0 = mash(" "); | |
s1 = mash(" "); | |
s2 = mash(" "); | |
for (var i = 0; i < args.length; i++) { | |
s0 -= mash(args[i]); | |
if (s0 < 0) { | |
s0 += 1; | |
} | |
s1 -= mash(args[i]); | |
if (s1 < 0) { | |
s1 += 1; | |
} | |
s2 -= mash(args[i]); | |
if (s2 < 0) { | |
s2 += 1; | |
} | |
} | |
mash = null; | |
var random = function () { | |
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 | |
s0 = s1; | |
s1 = s2; | |
return (s2 = t - (c = t | 0)); | |
}; | |
random.int = function (max) { | |
return Math.floor(random() * max); | |
}; | |
random.uint32 = function () { | |
return random() * 0x100000000; // 2^32 | |
}; | |
random.fract53 = function () { | |
return random() + ((random() * 0x200000) | 0) * 1.1102230246251565e-16; // 2^-53 | |
}; | |
random.args = args; | |
return random; | |
} | |
function switchRow(table, pos1, pos2) { | |
let temp = table[pos1]; | |
table[pos1] = [...table[pos2]]; | |
table[pos2] = [...temp]; | |
} | |
function switchCol(table, pos1, pos2) { | |
table = table.map((row) => { | |
let temp = row[pos1]; | |
row[pos1] = row[pos2]; | |
row[pos2] = temp; | |
}); | |
} | |
function shuffle(array, random) { | |
let currentIndex = array.length; | |
// While there remain elements to shuffle... | |
while (currentIndex != 0) { | |
// Pick a remaining element... | |
let randomIndex = Math.floor(random() * currentIndex); | |
currentIndex--; | |
// And swap it with the current element. | |
[array[currentIndex], array[randomIndex]] = [ | |
array[randomIndex], | |
array[currentIndex] | |
]; | |
} | |
} | |
const alphabet = "abcdefghijklmnopqrstuvwxyz"; | |
const numbers = "0123456789"; | |
const symbols = "-.~*[]$;|>{}'?:+#^%\"&/<>,=!()"; | |
//https://nordvpn.com/blog/what-is-password-entropy/ | |
function calcEntroy(seed) { | |
let range = 0; | |
if (seed.match(/[a-z]/g)) range += 26; | |
if (seed.match(/[A-Z]/g)) range += 26; | |
if (seed.match(/[\d]/g)) range += 10; | |
if (seed.match(/[^a-zA-Z\d]/g)) range += symbols.length; | |
return Math.log2(Math.pow(range, seed.length)); | |
} | |
function outputGrid(table) { | |
table.forEach((row) => { | |
console.log(row.join("")); | |
}); | |
} | |
function generateTable() { | |
let grid = []; | |
let salt = "WHATEVERYOUWANT"; | |
let seed = document.getElementById("seed")?.value || "seed"; | |
let width = +document.getElementById("width")?.value; | |
let height = +document.getElementById("height")?.value; | |
if (width * height < 26) { | |
console.log(document.getElementsByClassName("dimensions")); | |
document.getElementsByClassName("dimensions")[0].classList.add("error"); | |
document.getElementsByClassName("dimensions")[1].classList.add("error"); | |
} else { | |
document.getElementsByClassName("dimensions")[0].classList.remove("error"); | |
document.getElementsByClassName("dimensions")[1].classList.remove("error"); | |
} | |
let entropy = calcEntroy(seed); | |
document.getElementById('entropy').textContent =entropy.toFixed(2) | |
if (entropy > 80) { | |
document.getElementById("seed").classList.add("good"); | |
} else { | |
document.getElementById("seed").classList.remove("good"); | |
} | |
let prng = new Alea(`${salt}${seed}`); | |
let initialLower = alphabet; | |
let initialUpper = alphabet.toUpperCase(); | |
let initialNumbers = numbers; | |
let initialSymbols = symbols; | |
const order = [0, 1, 2, 3]; | |
let roundOrder = [...order]; | |
let r, temp, cell; | |
for (let i = 0; i < width * height; i++) { | |
shuffle(roundOrder, prng); | |
cell = []; | |
for (let j = 0; j < roundOrder.length; j++) { | |
if (roundOrder[j] === 0) { | |
//lower | |
if (initialLower.length) { | |
r = Math.floor(prng() * initialLower.length); | |
temp = initialLower[r]; | |
initialLower = initialLower.slice(0, r) + initialLower.slice(r + 1); | |
cell.push(temp); | |
} else { | |
r = Math.floor(prng() * alphabet.length); | |
cell.push(alphabet[r]); | |
} | |
} else if (roundOrder[j] === 1) { | |
//upper | |
if (initialUpper.length) { | |
r = Math.floor(prng() * initialUpper.length); | |
temp = initialUpper[r]; | |
initialUpper = initialUpper.slice(0, r) + initialUpper.slice(r + 1); | |
cell.push(temp); | |
} else { | |
r = Math.floor(prng() * alphabet.length); | |
cell.push(alphabet[r].toUpperCase()); | |
} | |
} else if (roundOrder[j] === 2) { | |
//number | |
if (initialNumbers.length) { | |
r = Math.floor(prng() * initialNumbers.length); | |
temp = initialNumbers[r]; | |
initialNumbers = | |
initialNumbers.slice(0, r) + initialNumbers.slice(r + 1); | |
cell.push(temp); | |
} else { | |
r = Math.floor(prng() * numbers.length); | |
cell.push(numbers[r].toUpperCase()); | |
} | |
} else if (roundOrder[j] === 3) { | |
//symbol | |
if (initialSymbols.length) { | |
r = Math.floor(prng() * initialSymbols.length); | |
temp = initialSymbols[r]; | |
initialSymbols = | |
initialSymbols.slice(0, r) + initialSymbols.slice(r + 1); | |
cell.push(temp); | |
} else { | |
r = Math.floor(prng() * symbols.length); | |
cell.push(symbols[r].toUpperCase()); | |
} | |
} | |
} | |
grid.push(cell); | |
} | |
// shuffle to ensure the first 26 non-repeating letters are scrambled through dimensions | |
shuffle(grid, prng); | |
//put into table | |
var table = document.createElement("table"); | |
table.cellPadding = 0; | |
table.cellSpacing = 0; | |
table.border = 0; | |
table.classList.add("normal"); | |
for (var i = 0; i < height; i++) { | |
var tr = document.createElement("tr"); | |
for (var j = 0; j < width; j++) { | |
var td = document.createElement("td"); | |
var text = document.createTextNode( | |
`${grid[i * width + j][0]}${grid[i * width + j][1]}\n${ | |
grid[i * width + j][2] | |
}${grid[i * width + j][3]}` | |
); | |
td.appendChild(text); | |
if (i%2 == 0 && j%2 == 1) { | |
td.classList.add("color"); | |
} else if (i%2 == 1 && j%2 == 0) { | |
td.classList.add("color"); | |
} | |
td.classList.add("globaltd"); | |
td.classList.add("char3"); | |
tr.appendChild(td); | |
} | |
table.appendChild(tr); | |
} | |
while (document.getElementById("grid-container").firstChild) { | |
document | |
.getElementById("grid-container") | |
.removeChild(document.getElementById("grid-container").firstChild); | |
} | |
document.getElementById("grid-container").appendChild(table); | |
} | |
generateTable(); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment