Skip to content

Instantly share code, notes, and snippets.

@westc
Last active May 22, 2020 01:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westc/229ab706ddf29c4694ddc03b23c8ba16 to your computer and use it in GitHub Desktop.
Save westc/229ab706ddf29c4694ddc03b23c8ba16 to your computer and use it in GitHub Desktop.
Can create stubs that look random to the average Joe.
var encodeStub, decodeStub;
(function() {
function encodeNumber(number, minNumber, maxNumber, maxPerSeries) {
var offset = minNumber;
var limitNumber = maxNumber - offset + 1;
var maxMaxPerSeries = Math.ceil(limitNumber / 2);
maxPerSeries = Math.floor(maxPerSeries);
if (!(1 <= maxPerSeries && maxPerSeries <= maxMaxPerSeries)) {
throw new Error('Since there are ' + limitNumber + ' possible values the maxPerSeries must be between 1 and ' + maxMaxPerSeries + '.');
}
var step = Math.ceil(limitNumber / maxPerSeries);
number = ((number - offset) % limitNumber + limitNumber) % limitNumber;
var series = Math.floor(number / maxPerSeries);
var positionInSeries = number % maxPerSeries;
return series + positionInSeries * step + offset;
}
function encode(number, maxPerSeries, alphabet, length) {
var alphabetLength = alphabet.length;
var minNumber = 0;
var maxNumber = Math.pow(alphabet.length, length) - 1;
if (maxNumber > Number.MAX_SAFE_INTEGER) {
var maxLength = Math.log(Number.MAX_SAFE_INTEGER) / Math.log(alphabetLength);
throw new Error('The maximum code length is ' + maxLength + ' for the given alphabet.');
}
number = encodeNumber(number, minNumber, maxNumber, maxPerSeries) - minNumber;
for (var code = '', i = 0; i < length; i++) {
var charIndex = number % alphabetLength;
number = Math.floor(number / alphabetLength);
code += alphabet.charAt(charIndex);
}
return code;
}
function decodeNumber(number, minNumber, maxNumber, maxPerSeries) {
var offset = minNumber;
var limitNumber = maxNumber - offset + 1;
var maxMaxPerSeries = Math.ceil(limitNumber / 2);
maxPerSeries = Math.floor(maxPerSeries);
if (!(1 <= maxPerSeries && maxPerSeries <= maxMaxPerSeries)) {
throw new Error('Since there are ' + limitNumber + ' possible values the maxPerSeries must be between 1 and ' + maxMaxPerSeries + '.');
}
var step = Math.ceil(limitNumber / maxPerSeries); // 3
number = ((number - offset) % limitNumber + limitNumber) % limitNumber; // 5
var series = Math.floor(number / step); // 1
var positionInSeries = number % step; // 2
return series + positionInSeries * maxPerSeries + offset;
}
function decode(code, maxPerSeries, alphabet) {
var alphabetLength = alphabet.length;
var length = code.length;
var minNumber = 0;
var maxNumber = Math.pow(alphabet.length, length) - 1;
if (maxNumber > Number.MAX_SAFE_INTEGER) {
throw new Error('This code cannot be decoded reliably due to JavaScript integer limitation.');
}
for (var number = 0, i = length; i--; ) {
var char = code.charAt(i);
number = number * alphabetLength + alphabet.indexOf(char);
}
return decodeNumber(number, minNumber, maxNumber, maxPerSeries);
}
// Some lower case letters and digits 2-9.
// Omit some characters to avoid confusion when writing down by hand.
// var STUB_ALPHABET = 'abcdefghijkmnopqrstuvwxyz23456789';
var STUB_ALPHABET = 'h6y2fusga8ben3dpwij95qm7vktoxcz4r';
var STUB_CODE_LENGTH = 6;
var STUB_MAX_PER_SERIES = 29;
encodeStub = function(id) {
return encode(id - 1, STUB_MAX_PER_SERIES, STUB_ALPHABET, STUB_CODE_LENGTH).replace(/^(...)(...)$/, '$1-$2');
}
decodeStub = function(stub) {
return decode(stub.replace(/-/g, ''), STUB_MAX_PER_SERIES, STUB_ALPHABET) + 1;
}
})();
// HIDE \\
console.load('local://encodeStub-decodeStub.js');
//\\
for (var id = 1; id <= 25; id++) {
var stub = encodeStub(id);
var decodedId = decodeStub(stub);
console.log(`${id} \u21E8 ${stub} \u21E8 ${decodedId}`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment