rubik-cipher
Version:
Simple rubik cube cipher
263 lines • 9.65 kB
JavaScript
"use strict";
const Cube = require('bedard-cube');
const rubikHelpers_1 = require("./helpers/rubikHelpers");
var FillAlpabet;
(function (FillAlpabet) {
FillAlpabet["default"] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
FillAlpabet["czech"] = "a\u00E1bc\u010Dd\u010Fe\u00E9\u011Bfghi\u00EDjklmn\u0148o\u00F3pqr\u0159s\u0161t\u0165u\u00FA\u016Fvwxy\u00FDz\u017EA\u00C1BC\u010CD\u010EE\u00C9\u011AFGHI\u00CDJKLMN\u0147O\u00D3PQR\u0158S\u0160T\u0164U\u00DA\u016EVWXY\u00DDZ\u017D0123456789";
})(FillAlpabet || (FillAlpabet = {}));
class RubikCipher {
constructor(text, config) {
this.text = '';
this.cube = undefined;
this.currentScramble = [];
this.size = 2;
this.groupSize = 1;
this.fillRest = true;
this.fillWithRandom = false;
this.fillAlphabet = FillAlpabet.default;
if (text === '') {
throw new Error('Text cannot be empty');
}
this.text = text;
if (config) {
if (typeof config === 'string') {
this.setupFromKey(config);
}
else {
if (typeof config.cubeSize !== 'undefined') {
if (config.cubeSize < 2) {
throw new Error('Cube size must be larger than 2');
}
if (!rubikHelpers_1.canFitInCube(this.text, config.cubeSize)) {
throw new Error(`Text of length ${this.text.length} cant fit in cube with size ${config.cubeSize}`);
}
this.size = config.cubeSize;
}
else {
this.size = rubikHelpers_1.minimalSizeByText(text);
}
if (typeof config.groupSize !== 'undefined') {
if (config.groupSize < 1) {
throw new Error('Group size must be larger than 0');
}
this.groupSize = config.groupSize;
}
else {
this.groupSize = 1;
}
if (typeof config.fillRest !== 'undefined') {
this.fillRest = config.fillRest;
}
else {
this.fillRest = true;
}
if (typeof config.fillWithRandom !== 'undefined') {
this.fillWithRandom = config.fillWithRandom;
}
else {
this.fillWithRandom = false;
}
this.reset();
}
}
else {
this.size = rubikHelpers_1.minimalSizeByText(text);
this.reset();
}
}
setupFromKey(key) {
const { combinationText, config } = this.getKeyParts(key);
this.size = config.cubeSize;
this.groupSize = config.groupSize;
this.fillRest = config.fillRest;
this.fillWithRandom = config.fillWithRandom;
this.reset();
this.applyReverseCombination(this.combinationTextToObject(combinationText));
}
isValidKey(key) {
if (!(/^[^+](\+{0,1}[- a-zA-Z0-9]+)+[^+]$/.test(key))) {
return false;
}
const keyParts = key.split('+');
if (keyParts.length !== 5) {
return false;
}
const cubeSize = Number(keyParts[0]);
const groupSize = Number(keyParts[1]);
if (cubeSize < 2) {
return false;
}
if (groupSize < 1) {
return false;
}
if (!rubikHelpers_1.canFitInCube(this.text, cubeSize)) {
return false;
}
return true;
}
getKeyParts(key) {
if (this.isValidKey(key)) {
const keyParts = key.split('+');
return {
config: {
cubeSize: Number(keyParts[0]),
groupSize: Number(keyParts[1]),
fillRest: (keyParts[2] === '1'),
fillWithRandom: (keyParts[3] === '1'),
},
combinationText: keyParts[4],
};
}
throw new Error('Key is invalid');
}
combinationTextToObject(combination) {
return combination.split(' ').map(rubikHelpers_1.decodeScramble);
}
applyReverseCombination(combination) {
this.turn(rubikHelpers_1.getInverseCombination(combination));
}
/**
* Function for cube scrambling
* @param {number} count How many times you want to scramble
*/
scramble(count = 0) {
this.reset();
const newScramble = this.cube.generateScramble(count);
this.currentScramble = newScramble;
this.cube.turn(this.currentScramble);
}
/**
* Function for additional cube scrambling
* @param {number} count How many times you want to scramble
*/
addScramble(count = 0) {
const newScramble = this.cube.generateScramble(count);
this.currentScramble = this.currentScramble.concat(newScramble);
this.cube.turn(this.currentScramble);
}
/**
* Function to manually turn the cube
* @param {string | Array<ScrambleObject>} turnKey selected sequence of turns
*/
turn(turnKey) {
const newScramble = [];
if (typeof turnKey === 'string') {
const turnKeys = turnKey.split(' ').map(rubikHelpers_1.decodeScramble);
newScramble.push(...turnKeys);
}
else {
newScramble.push(...turnKey);
}
this.currentScramble = this.currentScramble.concat(newScramble);
this.cube.turn(newScramble);
}
/**
* Reset the cube or create new one when cube is undefined
*/
reset() {
if (typeof this.cube !== 'undefined') {
this.cube.reset();
}
else {
this.cube = new Cube(this.size, { useObjects: true });
}
}
/**
* Getter for current cube Combination string
* @returns {string}
*/
get Combination() {
return this.currentScramble.map(rubikHelpers_1.encodeScramble).join(' ');
}
get InverseCombination() {
if (this.currentScramble.length > 0) {
return rubikHelpers_1.getInverseCombination(this.currentScramble);
}
return [];
}
/**
* Getter for current text from cube stickers
* @returns {string}
*/
get Text() {
const cubeIndexes = rubikHelpers_1.getAllIndexes(this.cube, this.size);
const textSplit = this.text.split('');
const alphabetSplit = this.fillAlphabet.split('');
let returnString = '';
if (this.groupSize > 1) {
const groups = rubikHelpers_1.chunkString(this.text, this.groupSize);
if (groups[groups.length - 1].length < this.groupSize) {
while (groups[groups.length - 1].length < this.groupSize) {
if (this.fillRest) {
if (this.fillWithRandom) {
groups[groups.length - 1] += alphabetSplit[Math.floor(Math.random() * alphabetSplit.length)];
}
else {
groups[groups.length - 1] += 'x';
}
}
else {
break;
}
}
}
while (groups.length < this.CubeTileCount) {
let textGroup = '';
for (let i = 0; i < this.groupSize; i++) {
if (this.fillRest) {
if (this.fillWithRandom) {
textGroup += alphabetSplit[Math.floor(Math.random() * alphabetSplit.length)];
}
else {
textGroup += 'x';
}
}
else {
continue;
}
}
groups.push(textGroup);
}
const mappedString = cubeIndexes.map(i => groups[i]);
returnString = mappedString.join('');
}
else {
const mappedString = cubeIndexes.map((i) => {
if (textSplit[i] !== undefined) {
return textSplit[i];
}
if (this.fillRest) {
if (this.fillWithRandom) {
return alphabetSplit[Math.floor(Math.random() * alphabetSplit.length)];
}
return 'x';
}
return '';
});
returnString = mappedString.join('');
}
return returnString;
}
get Indexes() {
return rubikHelpers_1.getAllIndexes(this.cube, this.size);
}
/**
* Gets current cube key in format size+groupSize+fillRest(0 or 1)+fillRandom(0 or 1)+combination
* @returns {string} key
*/
get Key() {
return [
this.size,
this.groupSize,
(this.fillRest ? 1 : 0),
(this.fillWithRandom ? 1 : 0),
this.Combination,
].join('+');
}
get CubeTileCount() {
return 6 * (this.size ** 2);
}
}
module.exports = RubikCipher;
//# sourceMappingURL=RubikCipher.js.map