Skip to content

Instantly share code, notes, and snippets.

@depperm
Last active June 24, 2024 17:46
Show Gist options
  • Save depperm/b488262529cd216d7d8db0f75affb09a to your computer and use it in GitHub Desktop.
Save depperm/b488262529cd216d7d8db0f75affb09a to your computer and use it in GitHub Desktop.
PaCK System
<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