733 lines
30 KiB
JavaScript
733 lines
30 KiB
JavaScript
import LZString from 'lz-string';
|
||
import store from './store';
|
||
|
||
// 0 => 'white',
|
||
// 1 => 'black',
|
||
// 2 => 'navy',
|
||
// 3 => 'green',
|
||
// 4 => 'red',
|
||
// 5 => 'brown',
|
||
// 6 => 'purple',
|
||
// 7 => 'olive',
|
||
// 8 => 'yellow', # dark yellow
|
||
// 9 => 'lime', # ltgreen
|
||
// 10 => 'teal',
|
||
// 11 => 'cyan',
|
||
// 12 => 'blue', # ltblue,
|
||
// 13 => 'fuchsia', # pink
|
||
// 14 => 'grey',
|
||
// 15 => 'lightgrey',
|
||
export const mircColours99 = [
|
||
'rgb(255,255,255)',
|
||
'rgb(0,0,0)',
|
||
'rgb(0,0,127)',
|
||
'rgb(0,147,0)',
|
||
'rgb(255,0,0)',
|
||
'rgb(127,0,0)',
|
||
'rgb(156,0,156)',
|
||
'rgb(252,127,0)',
|
||
'rgb(255,255,0)',
|
||
'rgb(0,252,0)',
|
||
'rgb(0,147,147)',
|
||
'rgb(0,255,255)',
|
||
'rgb(0,0,252)',
|
||
'rgb(255,0,255)',
|
||
'rgb(127,127,127)',
|
||
'rgb(210,210,210)',
|
||
|
||
"#470000",
|
||
"#472100",
|
||
"#474700",
|
||
"#324700",
|
||
"#004700",
|
||
"#00472c",
|
||
"#004747",
|
||
"#002747",
|
||
"#000047",
|
||
"#2e0047",
|
||
"#470047",
|
||
"#47002a",
|
||
"#740000",
|
||
"#743a00",
|
||
"#747400",
|
||
"#517400",
|
||
"#007400",
|
||
"#007449",
|
||
"#007474",
|
||
"#004074",
|
||
"#000074",
|
||
"#4b0074",
|
||
"#740074",
|
||
"#740045",
|
||
"#b50000",
|
||
"#b56300",
|
||
"#b5b500",
|
||
"#7db500",
|
||
"#00b500",
|
||
"#00b571",
|
||
"#00b5b5",
|
||
"#0063b5",
|
||
"#0000b5",
|
||
"#7500b5",
|
||
"#b500b5",
|
||
"#b5006b",
|
||
"#ff0000",
|
||
"#ff8c00",
|
||
"#ffff00",
|
||
"#b2ff00",
|
||
"#00ff00",
|
||
"#00ffa0",
|
||
"#00ffff",
|
||
"#008cff",
|
||
"#0000ff",
|
||
"#a500ff",
|
||
"#ff00ff",
|
||
"#ff0098",
|
||
"#ff5959",
|
||
"#ffb459",
|
||
"#ffff71",
|
||
"#cfff60",
|
||
"#6fff6f",
|
||
"#65ffc9",
|
||
"#6dffff",
|
||
"#59b4ff",
|
||
"#5959ff",
|
||
"#c459ff",
|
||
"#ff66ff",
|
||
"#ff59bc",
|
||
"#ff9c9c",
|
||
"#ffd39c",
|
||
"#ffff9c",
|
||
"#e2ff9c",
|
||
"#9cff9c",
|
||
"#9cffdb",
|
||
"#9cffff",
|
||
"#9cd3ff",
|
||
"#9c9cff",
|
||
"#dc9cff",
|
||
"#ff9cff",
|
||
"#ff94d3",
|
||
"#000000",
|
||
"#131313",
|
||
"#282828",
|
||
"#363636",
|
||
"#4d4d4d",
|
||
"#656565",
|
||
"#818181",
|
||
"#9f9f9f",
|
||
"#bcbcbc",
|
||
"#e2e2e2",
|
||
"#ffffff",
|
||
];
|
||
|
||
// How big the brush size can get
|
||
export const maxBrushSize = 15;
|
||
|
||
// Chars that end up in the toolbar
|
||
export const charCodes = [' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-',
|
||
'.', '/',
|
||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A',
|
||
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
|
||
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e',
|
||
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
|
||
'x', 'y', 'z', '{', '|', '}', '~', 'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç', 'ê', 'ë', 'è',
|
||
'ï', 'î', 'ì', 'Ä', 'Å', 'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù', 'ÿ', 'Ö', 'Ü', 'ø', '£',
|
||
'Ø', '×', 'ƒ', 'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º', '¿', '®', '¬', '½', '¼', '¡', '«',
|
||
'»', '░', '▒', '▓', '│', '┤', 'Á', 'Â', 'À', '©', '╣', '║', '╗', '╝', '¢', '¥', '┐', '└',
|
||
'┴', '┬', '├', '─', '┼', 'ã', 'Ã', '╚', '╔', '╩', '╦', '╠', '═', '╬', '¤', 'ð', 'Ð', 'Ê',
|
||
'Ë', 'È', 'ı', 'Í', 'Î', 'Ï', '┘', '┌', '█', '▄', '¦', 'Ì', '▀', 'Ó', 'ß', 'Ô', 'Ò', 'õ',
|
||
'Õ', 'µ', 'þ', 'Þ', 'Ú', 'Û', 'Ù', 'ý', 'Ý', '¯', '´', '≡', '±', '‗', '¾', '¶', '§', '÷',
|
||
'¸', '°', '¨', '·', '¹', '³', '²',
|
||
];
|
||
|
||
// Toolbar icons
|
||
export const toolbarIcons = [{
|
||
name: 'default',
|
||
icon: 'mouse-pointer',
|
||
fa: 'fas',
|
||
},
|
||
{
|
||
name: 'select',
|
||
icon: 'square',
|
||
fa: 'far',
|
||
},
|
||
{
|
||
name: 'text',
|
||
icon: 'font',
|
||
fa: 'fas',
|
||
},
|
||
{
|
||
name: 'fill',
|
||
icon: 'fill-drip',
|
||
fa: 'fas',
|
||
},
|
||
{
|
||
name: 'brush',
|
||
icon: 'paint-brush',
|
||
fa: 'fas',
|
||
},
|
||
{
|
||
name: 'dropper',
|
||
icon: 'eye-dropper',
|
||
fa: 'fas',
|
||
},
|
||
{
|
||
name: 'eraser',
|
||
icon: 'eraser',
|
||
fa: 'fas',
|
||
},
|
||
{
|
||
name: 'fill-eraser',
|
||
icon: 'fill',
|
||
fa: 'fas',
|
||
},
|
||
];
|
||
|
||
export const emptyBlock = {
|
||
bg: null,
|
||
fg: null,
|
||
char: null,
|
||
};
|
||
|
||
export const create2DArray = (rows) => {
|
||
const arr = [];
|
||
|
||
for (let i = 0; i < rows; i++) {
|
||
arr[i] = [];
|
||
}
|
||
|
||
return arr;
|
||
};
|
||
|
||
// Width and height of the ASCII blocks
|
||
// they seem to be 8x15 in asciiblaster
|
||
export const blockWidth = 8;
|
||
export const blockHeight = 15;
|
||
|
||
export const parseMircAscii = async (content, title) => {
|
||
const MIRC_MAX_COLOURS = mircColours99.length;
|
||
|
||
// The current state of the Colours
|
||
let curBlock = {
|
||
...emptyBlock,
|
||
};
|
||
|
||
const contents = content;
|
||
const filename = title;
|
||
|
||
// set asciiImport as the entire file contents as a string
|
||
const asciiImport = contents
|
||
.split('\u0003\u0003')
|
||
.join('\u0003')
|
||
.split('\u000F').join('')
|
||
.split('\u0003\n')
|
||
.join('\n')
|
||
.split('\u0002\u0003')
|
||
.join('\u0003');
|
||
|
||
// This will end up in the asciibirdMeta
|
||
const finalAscii = {
|
||
title: filename,
|
||
// key: store.getters.nextTabValue,
|
||
// blockWidth: blockWidth * store.getters.blockSizeMultiplier,
|
||
// blockHeight: blockHeight * store.getters.blockSizeMultiplier,
|
||
blocks: [{
|
||
label: filename,
|
||
visible: true,
|
||
data: create2DArray(asciiImport.split('\n').length),
|
||
width: false, // defined in: switch (curChar) case "\n":
|
||
height: asciiImport.split('\n').length,
|
||
}],
|
||
history: [],
|
||
redo: [],
|
||
x: blockWidth * 35, // the dragable ascii canvas x
|
||
y: blockHeight * 2, // the dragable ascii canvas y
|
||
selectedLayer: 0,
|
||
};
|
||
|
||
// Turn the entire ascii string into an array
|
||
let asciiStringArray = asciiImport.split('');
|
||
const linesArray = asciiImport.split('\n');
|
||
|
||
// The proper X and Y value of the block inside the ASCII
|
||
let asciiX = 0;
|
||
let asciiY = 0;
|
||
|
||
// used to determine colours
|
||
let colourChar1 = null;
|
||
let colourChar2 = null;
|
||
let parsedColour = null;
|
||
|
||
// This variable just counts the amount of colour and char codes to minus
|
||
// to get the real width
|
||
let widthOfColCodes = 0;
|
||
|
||
// Better for colourful asciis
|
||
let maxWidthLoop = 0;
|
||
|
||
// Used before the loop, better for plain text
|
||
let maxWidthFound = 0;
|
||
|
||
for (let i = 0; i < linesArray.length; i++) {
|
||
if (linesArray[i].length > maxWidthFound) {
|
||
maxWidthFound = linesArray[i].length;
|
||
}
|
||
}
|
||
|
||
while (asciiStringArray.length) {
|
||
const curChar = asciiStringArray[0];
|
||
|
||
// Defining a small finite state machine
|
||
// to detect the colour code
|
||
switch (curChar) {
|
||
case '\n':
|
||
// Reset the colours here on a new line
|
||
curBlock = {
|
||
...emptyBlock,
|
||
};
|
||
|
||
if (linesArray[asciiY] && linesArray[asciiY].length > maxWidthLoop) {
|
||
maxWidthLoop = linesArray[asciiY].length;
|
||
}
|
||
|
||
// the Y value of the ascii
|
||
asciiY++;
|
||
|
||
// Calculate widths mirc asciis vs plain text
|
||
if (!finalAscii.blocks[0].width && widthOfColCodes > 0) {
|
||
finalAscii.blocks[0].width = maxWidthLoop - widthOfColCodes;
|
||
}
|
||
|
||
if (!finalAscii.blocks[0].width && widthOfColCodes === 0) {
|
||
// Plain text
|
||
finalAscii.blocks[0].width = maxWidthFound;
|
||
}
|
||
|
||
// Resets the X value
|
||
asciiX = 0;
|
||
|
||
asciiStringArray.shift();
|
||
widthOfColCodes = 0;
|
||
break;
|
||
|
||
case '\u0003':
|
||
// Remove the colour char
|
||
asciiStringArray.shift();
|
||
widthOfColCodes++;
|
||
|
||
// Attempt to work out bg
|
||
colourChar1 = `${asciiStringArray[0]}`;
|
||
colourChar2 = `${asciiStringArray[1]}`;
|
||
parsedColour = parseInt(`${colourChar1}${colourChar2}`);
|
||
|
||
// Work out the 01, 02 double digit codes
|
||
if (parseInt(colourChar1) === 0 && parseInt(colourChar2) >= 0) {
|
||
asciiStringArray.shift();
|
||
}
|
||
|
||
if (Number.isNaN(parsedColour)) {
|
||
curBlock.bg = parseInt(colourChar1);
|
||
widthOfColCodes += 1;
|
||
asciiStringArray.shift();
|
||
} else if (parsedColour <= MIRC_MAX_COLOURS && parsedColour >= 0) {
|
||
curBlock.fg = parseInt(parsedColour);
|
||
widthOfColCodes += parsedColour.toString().length;
|
||
|
||
asciiStringArray = asciiStringArray.slice(
|
||
parsedColour.toString().length,
|
||
asciiStringArray.length,
|
||
);
|
||
}
|
||
|
||
// No background colour
|
||
if (asciiStringArray[0] !== ',') {
|
||
break;
|
||
} else {
|
||
// Remove , from array
|
||
widthOfColCodes += 1;
|
||
asciiStringArray.shift();
|
||
}
|
||
|
||
// Attempt to work out bg
|
||
colourChar1 = `${asciiStringArray[0]}`;
|
||
colourChar2 = `${asciiStringArray[1]}`;
|
||
parsedColour = parseInt(`${colourChar1}${colourChar2}`);
|
||
|
||
if (
|
||
!Number.isNaN(colourChar1) &&
|
||
!Number.isNaN(colourChar2) &&
|
||
parseInt(colourChar2) > parseInt(colourChar1) &&
|
||
!Number.isNaN(parsedColour) &&
|
||
parseInt(parsedColour) < 10
|
||
) {
|
||
parsedColour = parseInt(colourChar2);
|
||
widthOfColCodes += 1;
|
||
asciiStringArray.shift();
|
||
}
|
||
|
||
if (
|
||
parseInt(colourChar2) === parseInt(colourChar1) &&
|
||
parseInt(parsedColour) < 10
|
||
) {
|
||
parsedColour = parseInt(colourChar1);
|
||
asciiStringArray.shift();
|
||
asciiStringArray.shift();
|
||
widthOfColCodes += 2;
|
||
|
||
curBlock.bg = parseInt(colourChar1);
|
||
|
||
break;
|
||
}
|
||
|
||
if (Number.isNaN(parsedColour)) {
|
||
curBlock.bg = parseInt(colourChar1);
|
||
widthOfColCodes += 1;
|
||
asciiStringArray.shift();
|
||
} else if (parsedColour <= MIRC_MAX_COLOURS && parsedColour >= 0) {
|
||
curBlock.bg = parseInt(parsedColour);
|
||
widthOfColCodes += parsedColour.toString().length;
|
||
|
||
asciiStringArray = asciiStringArray.slice(
|
||
parsedColour.toString().length,
|
||
asciiStringArray.length,
|
||
);
|
||
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
curBlock.char = curChar;
|
||
asciiStringArray.shift();
|
||
asciiX++;
|
||
|
||
finalAscii.blocks[0].data[asciiY][asciiX - 1] = {
|
||
...curBlock,
|
||
};
|
||
break;
|
||
} // End Switch
|
||
} // End loop charPos
|
||
|
||
finalAscii.blocks = [...fillNullBlocks(finalAscii.blocks[0].height, finalAscii.blocks[0]
|
||
.width, finalAscii.blocks)];
|
||
// Store the ASCII and ensure we have no null blocks
|
||
finalAscii.blocks = LZString.compressToUTF16(
|
||
JSON.stringify(finalAscii.blocks),
|
||
);
|
||
|
||
// We need to also store in the first undo history the original state
|
||
finalAscii.history.push(finalAscii.blocks);
|
||
|
||
// Save ASCII to storage
|
||
store.commit('newAsciibirdMeta', finalAscii);
|
||
|
||
return true;
|
||
};
|
||
|
||
// Creates new blank ASCII
|
||
export const createNewAscii = (forms) => {
|
||
const newAscii = {
|
||
title: forms.createAscii.title,
|
||
history: [],
|
||
redo: [],
|
||
x: 247, // the dragable ascii canvas x
|
||
y: 24, // the dragable ascii canvas y
|
||
blocks: [{
|
||
label: forms.createAscii.title,
|
||
visible: true,
|
||
data: create2DArray(forms.createAscii.height),
|
||
width: forms.createAscii.width,
|
||
height: forms.createAscii.height,
|
||
}],
|
||
selectedLayer: 0,
|
||
};
|
||
|
||
// Push all the default ASCII blocks
|
||
for (let x = 0; x < newAscii.blocks[0].width; x++) {
|
||
for (let y = 0; y < newAscii.blocks[0].height; y++) {
|
||
newAscii.blocks[0].data[y].push({
|
||
...emptyBlock,
|
||
});
|
||
}
|
||
}
|
||
|
||
newAscii.blocks = LZString.compressToUTF16(JSON.stringify(newAscii.blocks));
|
||
newAscii.history.push(newAscii.blocks);
|
||
store.commit('newAsciibirdMeta', newAscii);
|
||
store.commit('closeModal', 'new-ascii');
|
||
|
||
return true;
|
||
};
|
||
|
||
// Converts ASCIIBIRD blocks to mIRC colours
|
||
export const exportMirc = () => {
|
||
const {
|
||
currentAscii
|
||
} = store.getters;
|
||
const blocks = [...store.getters.currentAsciiLayers];
|
||
const output = [];
|
||
let curBlock = false;
|
||
let currentLayer = 0;
|
||
let prevBlock = {
|
||
bg: -1,
|
||
fg: -1
|
||
};
|
||
|
||
for (let y = 0; y <= blocks[0].data.length - 1; y++) {
|
||
if (y >= currentAscii.height) {
|
||
continue;
|
||
}
|
||
|
||
for (let x = 0; x <= blocks[0].data[y].length - 1; x++) {
|
||
if (x >= currentAscii.width) {
|
||
continue;
|
||
}
|
||
|
||
for (let i = blocks.length - 1; i >= 0; i--) {
|
||
if (blocks[i].visible === true) {
|
||
currentLayer = i;
|
||
|
||
if (
|
||
blocks[i].data &&
|
||
blocks[i].data[y] &&
|
||
blocks[i].data[y][x] &&
|
||
i > 0 &&
|
||
JSON.stringify(blocks[i].data[y][x]) ===
|
||
JSON.stringify(emptyBlock)
|
||
) {
|
||
continue;
|
||
} else if (
|
||
// Otherwise if we are on the very first layer we need to render it
|
||
blocks[i].data &&
|
||
blocks[i].data[y] &&
|
||
blocks[i].data[y][x]
|
||
) {
|
||
|
||
curBlock = {
|
||
...blocks[i].data[y][x]
|
||
};
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// If we have a difference between our previous block
|
||
// we'll put a colour codes and continue as normal
|
||
if (curBlock.bg !== prevBlock.bg || curBlock.fg !== prevBlock.fg) {
|
||
curBlock = {
|
||
...blocks[currentLayer].data[y][x]
|
||
};
|
||
const zeroPad = (num, places) => String(num).padStart(places, '0');
|
||
output.push(
|
||
`\u0003${zeroPad(
|
||
curBlock.fg ?? store.getters.options.defaultFg,
|
||
2,
|
||
)},${zeroPad(curBlock.bg ?? store.getters.options.defaultBg, 2)}`,
|
||
);
|
||
}
|
||
|
||
// null .chars will end up as space
|
||
output.push(curBlock.char ?? ' ');
|
||
prevBlock = blocks[currentLayer].data[y][x];
|
||
}
|
||
|
||
// We can never have a -1 colour code so we'll always
|
||
// write one at the start of each line
|
||
prevBlock = {
|
||
bg: -1,
|
||
fg: -1
|
||
};
|
||
|
||
// New line except for the very last line
|
||
if (y < blocks[currentLayer].data[y].length - 1) {
|
||
output.push('\n');
|
||
}
|
||
}
|
||
|
||
// Download to a txt file
|
||
// Check if txt already exists and append it
|
||
const filename = currentAscii.title.slice(currentAscii.title.length - 3) === 'txt' ?
|
||
currentAscii.title :
|
||
`${currentAscii.title}.txt`;
|
||
|
||
return {
|
||
filename,
|
||
output
|
||
}
|
||
}
|
||
|
||
// Download a string to a file with a filename
|
||
export const downloadFile = (content, filename, contentType) => {
|
||
const a = document.createElement('a');
|
||
const file = new Blob([content], {
|
||
type: contentType
|
||
});
|
||
|
||
a.href = URL.createObjectURL(file);
|
||
a.download = filename;
|
||
a.click();
|
||
|
||
URL.revokeObjectURL(a.href);
|
||
};
|
||
|
||
export const checkForGetRequest = async () => {
|
||
const asciiUrlCdn = new URL(location.href).searchParams.get('ascii');
|
||
if (asciiUrlCdn) {
|
||
const res = await fetch(`https://ascii.jewbird.live/${asciiUrlCdn}`, {
|
||
method: 'GET',
|
||
headers: {
|
||
Accept: 'text/plain',
|
||
},
|
||
});
|
||
|
||
const asciiData = await res.text();
|
||
parseMircAscii(asciiData, asciiUrlCdn);
|
||
return;
|
||
}
|
||
|
||
const asciiUrl = new URL(location.href).searchParams.get('ircwatch');
|
||
if (asciiUrl) {
|
||
const res = await fetch(`https://irc.watch/ascii/txt/${asciiUrl}`, {
|
||
method: 'GET',
|
||
headers: {
|
||
Accept: 'text/plain',
|
||
},
|
||
});
|
||
|
||
const asciiData = await res.text();
|
||
parseMircAscii(asciiData, asciiUrl);
|
||
return;
|
||
}
|
||
|
||
const haxAscii = new URL(location.href).searchParams.get('haxAscii');
|
||
if (haxAscii) {
|
||
const res = await fetch(`https://art.h4x.life/${haxAscii}`, {
|
||
method: 'GET',
|
||
headers: {
|
||
Accept: 'text/plain',
|
||
},
|
||
});
|
||
|
||
// Considers paths
|
||
const asciiName = haxAscii.split('/').pop();
|
||
const asciiData = await res.text();
|
||
parseMircAscii(asciiData, asciiName);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Hashing algo to detect duplicate brushes
|
||
// from https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript
|
||
export const cyrb53 = function (str, seed = 1337) {
|
||
let h1 = 0xdeadbeef ^ seed,
|
||
h2 = 0x41c6ce57 ^ seed;
|
||
for (let i = 0, ch; i < str.length; i++) {
|
||
ch = str.charCodeAt(i);
|
||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||
h2 = Math.imul(h2 ^ ch, 1597334677);
|
||
}
|
||
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
||
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
||
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
||
};
|
||
|
||
// Mostly plain text asciis wont have all their blocks
|
||
// so this will fix that
|
||
export const fillNullBlocks = function (height, width, layerData = null) {
|
||
// Probably used on irc import to make the blocks proper,
|
||
// especially with plain text ascii
|
||
|
||
if (layerData === null) {
|
||
var layers = [...store.getters.currentAsciiLayers]
|
||
} else {
|
||
var layers = [...layerData]
|
||
}
|
||
|
||
for (let i = 0; i <= layers.length - 1; i++) {
|
||
let blocks = layers[i].data;
|
||
|
||
for (let y = 0; y < height; y++) {
|
||
// New row
|
||
if (!blocks[y]) {
|
||
blocks[y] = [];
|
||
for (let x = 0; x < width; x++) {
|
||
blocks[y][x] = {
|
||
...emptyBlock
|
||
};
|
||
}
|
||
} else {
|
||
// no new rows but new cols
|
||
for (let x = 0; x < width; x++) {
|
||
if (blocks[y] && !blocks[y][x]) {
|
||
blocks[y][x] = {
|
||
...emptyBlock
|
||
};
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Update layer with new blocks
|
||
layers[i].data = [...blocks]
|
||
layers[i].width = width
|
||
layers[i].height = height
|
||
}
|
||
|
||
return layers
|
||
}
|
||
|
||
// Sometimes if we copy blocks the initial Y values will be null
|
||
// and cause an error when trying to calculate width
|
||
// So we get the longest x length
|
||
export const getBlocksWidth = function (blocks) {
|
||
let maxWidth = 0;
|
||
|
||
for (let y = 0; y < blocks.length; y++) {
|
||
if (!blocks[y]) {
|
||
continue
|
||
}
|
||
|
||
if (blocks[y] && blocks[y].length > maxWidth) {
|
||
maxWidth = blocks[y].length
|
||
}
|
||
}
|
||
|
||
return maxWidth
|
||
}
|
||
|
||
// This removes the null blocks from our copy and paste
|
||
// to make sure it's centered better
|
||
export const filterNullBlocks = function (blocks) {
|
||
let newBlocks = [];
|
||
let y;
|
||
|
||
blocks = blocks.filter(function (item) {
|
||
return item !== null
|
||
});
|
||
|
||
for (y = 0; y < blocks.length; y++) {
|
||
newBlocks[y] = (blocks[y].filter(function (item) {
|
||
return item !== null
|
||
}))
|
||
}
|
||
|
||
return newBlocks
|
||
}
|
||
|
||
// Function to check if the left and top values are visible on the screen
|
||
export const checkVisible = function (bottom, top) {
|
||
var viewHeight = Math.max(
|
||
document.documentElement.clientHeight,
|
||
window.innerHeight
|
||
);
|
||
return !(bottom < 0 || top - viewHeight >= 0);
|
||
}
|
||
|
||
export const splashAscii = JSON.parse(LZString.decompressFromEncodedURIComponent(
|
||
"NrDeCICMHNwLgAwBpwDNaJQYwBYEMAnecAAnAF8kIZ5k0M7dDizLqGV1bt8i5SKVKB3rdwTPgLbCxXTON4tB7WSIlLpNeXMaL+rIVro6ezfcpna1eqYZEmFZ2yqtj15zfetODL498lfS383GyCjTgCNO1VQnwsI0Xl3Z2DIuMCErwzov3TksKzYgvjPYt1SmNcSzLLqitqqkJrctKSG1sSHFPDslo8m-I6BvPbTRtHuwrrm4dSuqJG2qcrJxfm+ud7y8c7N3aWFnMP9xwnl9e36g42ds727nqLr+5PH6cGx19uXp5mhm5XWaA57A75AgHg0GQv6fFbnI79H5g2FrY7ImEfNFIiFfVEXdG4+EPX5Ygk46F4smIraU4lvUmrcm0-5Upk0kGs+kYtkI074jlQrmXOki4WE0US8UU6UsuFi+VSxUy5Vy7Fq5mc1Va9U6zVC7UG3VG-UC-nU83sy1895W202xkOlEW+0k512x1uzEe91O71+3lewMM31B7lEhXGs2ukP+sOR00uz2x4M88PPAB2AFcADY5-LZvMHQs58gAXSQYETPrjKfTsr1gujybTCabSdDdbb1vjSqjHdrrb71YD9cNzc7Q5V-ZrqYjw-bs7HM9H3ZjU41i9XC57XZ36-n05HvaPW5Pm93G8bl8PF4PktPN4fd5bt+v94bJrPe8fH-HA7nZ931fICvyfT8J0HN8wL-Fdz2AydoMgwCIIA5djx-F9ENA5D0O-K8YJA1ClzXIj-xI-cyLgzCEKgnC0NI7DiO3X8qIwgjcMYujmPgwimPIlisO4gTeM4yj+OojiGPE4TJKQ6TWIk9j5Io1iSwLXN81eEty0rOT6NUoSUJEmi+Nk5SDME2jjP0njTObABOcz8JUqyzJsiy7KkwzrLw8CTO8h0nNTQBE0meYLuTCuoIq4jyXMs0SFKMvzYM8gLXMSnz3JStj4q8jL7KS3zYpypS8vShLCqysTFOc-zbIq-LKsCzK3Jq5KSs6mS4vqtKGv6vrBvKgbhqG3rRom8aptSyaZum3L5rKxa6rm1aFrWpaNpW9ads23btr2w6DuOnqttO-bzqO871KSG73B0isq1mi7SpO17Lrerrao+n6cpiyj-qRKKqkBuZgZcUGbnBsazveuGvo67q-u2yHCNRlJoa0dGbExjBsacXH4HxyRCbgYnWopqq2qK7KEeKpG6dphmAcHUmrvh5nvo5rnGfa4Dyf4NnPs5xGeZF+mxcl0WXwF8BSdlgqWqpymldVxX1eajWmu1xrdZG5bft5mm+aZqWJel83LdNi3ratk37eNx3qqd6nnbd12PZVrW9Zhl6jfdr3NaDuobrkO69AevTffZ-3PeV+O1eDn2sdZ8LU+i9OQcziHs8sWX5dzlPDfF23S4dj0FbT8786ryLa-WAvQvrkvy7jxOdf12HY8DjPq5Rwu8YHomh79luXZ75P5pr3u65nhuk870ezbL8eE6uaes6buf0Ub5Gt8nrux4DteF+j4Xl9bifF5jo+2+96-8gARhuQAQ0gfZ-vkAANJ35ub-pQ-lIf9lQAJsEA7EICnBgPJBAyQUDEQwOIHAvoAAOYKKQ37SlQRLLBpscE1TwQpAhqkiEsRISeMhP4KFTioYeGhD46GYLQYQphxCWGkLYeQjhlCuHUJ4bQvh9CBEd0sKHDA4czCRyegbbmNtL4n2EUXWem8lE533qolRecR4b3UfPbeQNm76L0WDAxMtz6yNXu3ZRpFtGaLUbYjRiju7yIPkvcxx9LEP2LqxSuRj+ZaP8XYxxO8TF2wsffM+fdIkOMHoEmJ0TD4XzCafZ6N9EkVwCfEsmGTdFWOCQo6RTiPERJkaE9x4T4Gvx-l-KpgDBGVP-vUqoH85AIIZM0jArSfjtPgJ0q43S4C9OeP0wZdRhnATGYRCZzYplJhmR6OZDoFkkn6VQpBPSn6NPARLEZwDtl7NNjsrZBz9k1UOdAk5CkzkVOOTc05FyynJLEZpDSRZtKaV0lIhJbi76POHrEv5mSbFBMMbkkFOi8mguMfkr5fj-lZLhT4yFsKSkrweb4tG2SIXgrBcUwp5SCm3yvriwlDJEXYtMQizFOLgVQqRain50LXGlIZXSxyVLaWeJRXIopKSzHMqJTSqGITvi7xyeSoV6KMa-KZfSgVBLJadIwU0jZkyVXTLVbMjV8ytWLJ1csvVbSDVdKNX0k1QyzWjItcqpIVyOlWpcEsw1Nrxn2ssI641SRVnmudaqn16q-WaoDdqz1PC1lwBwXIBhVQI0YCoUqlwMb4BerqIm8Noa6m4KEcqKN2Ic3kjzYiAtKCs25pLfmsthaK3FuwVWtaoj4DiL4JIzleLpVAriWK+xnbBUiuFVKyVOM+1JMZakilgL2UStZcOlxo7+Wkonb2gdBMh3pKia2kdfLZXOMXmSrtLNKUHsybOrdPL5XfLlTCk968F39qncujdXjz3buJWkllO7+6Hu7R2-dR7N3csPIqmpoDvUtJdUG3V4H9WQadaB31sH-XwcDYh4NyGIOoag+hmDdq4PYYQ7hpD+GUOEbQ8RjDpGsPrJw5RvD1GCO0aI-RkjjGyPMYowMsDmGPWcdNdBrj5G+OsYE+xqjwmaNpt-iB-j8a3X5DjRm-BtbqhFuKMppTinmiqb2vWuAjaG3vMei2klp6AVfpM1ivd1Lv2WbM94v907xUYrXT+0z8Lx2fqM-iy9-6203sHUukmK6gq+dXb+pzr6L07V3T2tl7nrOuZc8e7zD6uX2ZfU+4z8XzPRb83egLyX10zrs2iwrj650-Ci1ZsdLn202Y5b7d1PHuOScE41-jrWWvNdE3RrrDGetMb6yxgbbHbWUaa5a3j7WhtCZG8Jsb1q5sOtdVoBrnWZsrfGwtmTE3VscbaztkTa2luxsBp0sNqbTvPHOxJlNJ3rvRtu9Um7RqzsPdqU93jL3nuXde8B97nHPsfe+7JxTqa5OMJrRDq9mZnm3Rh-dfTUdeWlcc251H1WP17zR1lyryL0exbq9l+9uXiCiux7VydDmkslZS8Vwztn8cU4swTnHi7ieC0CyTjn7P-Mkgq15pMfPMv06x3FmrMqqd0-S558XqXnpi-l8Ft9aWyvS8S7Ls9KuuflcV5znn3PQWdNJut+be2Num5Nx1s3luLdTcm4d7bVvbf7bE-bzby2jujfN4th3NvXde62277DgfPfW+98H2b-v3c+7D5HoPseQ9O8d370PAfjt3Zj0m9NSfNmp8E2GlZPDpOVshwpkvzCy+sIr+wqvnCa-Pq0Np3TOmEefJl7TpnjPCd5bZ9rsLzPyes8pzlofROR-d7H7rnvpPRc6-1xPufyuof5Y89KtXIWEsY7xyL-vQud8K+RxL32gv9-b87yzw-SOadK8vwVyXuOye77PwP298+Mtr+vxrpf1Pb9H834JovVmhuBiQBeiIBvuu2KeUe4exuGeie4BB2EBcBsByeSBueqBUB8eEekBce2BCeKB+BiBBBCBxBLuhBZBJB3WM2V2j292X2f2-GAO-2zulB5BpBFBvWgG2eNBRydytyly9yLEM2zQQhHuO0jecOEcLed+KOW+shD+gu7+vOs+csPmDOg+He6hXek+76ahL+GhehN+K+y+4W9en+F+U8f+M+uhw++hAuRWH+a0x+yh0+e+I8ihph-O7ehhJhGWJ+chcW7hb+9hEWgRquwRw29+6BgBkRYB2KsRFm8RGBuBWBUReBrBLB7B-WRBbBORGRuRHB6RHooOIOgMqmxRwE5RmRg22ReRtRBRfBqkIh0e5yDRghAhJ4TRkaWeuy3BLRb2PR-RPB-BrRHR7RP4nRmBoR0OryYcEhEiUhi+5hz+NhWh86B+6unhDhbeWxe0Th1ho+thBx3hUuq+4RQR6xXhFh+x4+hxNxqxKheuveV+IRlhVW8hzhWuLhT+j+Mh7x1x2htxAJxxmuxhbxVhp+mh5+KxZhGx2xLxFxWRhRQWzRwKM2P2Rx0RkJNmiROBqRKRNR9R+RiJVRERJJ02SJ1RFJpJzYlRYmyaNu9JyBVJ5JZJduzJAGYxU4ExyRwhnJHJIx4xfJQGjRQpDSApXJopAxwxvBMpsJ4hry8OeYHy0hSxkWZxYRCJ8JzxHhcJOpfhfxEJqpUxoJIJ3+zmBp-hrh-xC+9x16mpOpxpLiexhpdh1pDxU+nxnpjxXxWJPxBhMJlxjhrx3x+p4JG+9p5x2pkZUmzBhJdRyJ4e6JdxmJ-p2J3xMBaBBJxJRJlJrJsZ2Z8ZuZOZ1JhZJZcZ5ZBZFZRZpZ4AYavJ4p-JspIpDZwpbRLZYpTZbZnZox7ZUpzZ3ZgpvZQx-Z0pcpMOsxCpkhSpBmixsJjpKpc56ppxEZGpUZ0uoZVpoWa5y5253pqhLpGJyxh5fp0JR5yZZ5ShK5O5P+wJX+C56+5pYZj5m5lpIZyhq5N5AZCZ1iHxJpd5s5I5TgABCejJmZ7J+Z1ZVZZZ35gmRuohGZSReJCFuJWZkFlZ6FaFmF0FWFLJxZuFNZbJZJ+edBfZXZo5gFZFFFPZA5EpQ5fR5FlFjF1FDFzFVFg5NFjZLF7FXFtFqp8pWkippYM5t5RpS5f5olV54li5klZpwur5vpYu85AFMFT5qlL5FpGlalb5Ml95OxYlslJxUlgZupvhwZvxPhH5RhBlppulWpX0nBDJ3RTJeZXBeFhFblEF2FXl+FUFPlGF3l7lBFnlflOFgVvlYV-lIVAVwVEVOFdZoh9ZHFrZrFTF3FbFvFPFnF6VWVqVGV2VyVaVuVOVKVJVhVpVeVRVBVGW-FxYCxIl0lu51l-59VxlSlLVelfe2lB555JlllFlXpTpbh+ltlDpw1yldlVlI10Zk141o1Ols101-VRl1e3wwF1QDlzlHlrlQV214VMVwB6Z8FR1KJKF4Fu1kVsV0V51oV+111V18BW1D1O1T1e1oBXV-GcFJ1xQ3JeJiVmVVVxVZVQNFV5VgNINwNYNkNAN0NHZ-1sN+V8NlViNoNMNpFKNjKNVby05iOX5E1S1TVEljVU1fVhlBNrp3VQJUJx5bVuNc1RNC1JNNlDN15M17VeNpNxNLN+NnNy17NTN3hG1aBoFiFwtuJotaRLlL1F1B1vpyFaZClRq0+OJ8tqZQuyt+JZ1Buh1X1Gtktm1z1+tr1UtN1d1UVZtl1TxH1MtqtSZlNKtp561kpw5Kl6tttNpKZDtbt7pcR71sFqNzt6NaNEN-t9FCNQd4NEdUNyNwd0dkdId1ySVGN45Tyk58x2NreNNmxfNzVtNi1HNzNvNdNP5cKmdvV+5xd9NbNRdrNudjNOdWd1d3NBdg1bpddhNn5KmhenW4tutj1ht0tptFtdpnGStvtU2o9CtvGE9Ntit1tnts9b1k9I9c9x5Xt09Dtctat2t0Bx1O9Otm9B9u9mB1BgxYFetCRY9rtwOY9VCQsIakRt9Bij9eiz9oKr92K79Fmn9wK39Vmv9Nm-9QugDpRPCd9XRdeltme3xGm6m19maED-CCD8m5e8DqDpeaDY5MxKdAlU5QlONDded-NtdXN+dVdhD9dZdhd5DMWmOFddDz5kRpDxDVDbdDVHdlDZNrVY19xPpM9bpYD7DMDOeItTlZ9fdQtojIj6eYjBtMjD549K9PVa9ijdtW9stR9yRyji9fDy92jG9ohWjWtS9Vtejq9C9RjOjJjxt91-dJt1j5tQO9959iFqFaxujFj89U9Kj7t9tZjXjpjSj5jPtxjftATqjhjwTljoTHjfj7jkTnjcTF9ITCjYTPjjtdFCdcN4dUd2T8dfQP1L4mNglypzdPNnDHVldzD5T2d7dNdBDw99DclDD5lYJrTRDF5bjjTbTFDpdvT3DVTZTOhFNaTG5l929aevRP9imBe0jLjmttjNjcjA99jQ93j3tSTUTKTMTPVtJsjczzjp1BzEt4jqJYzvpJ9v22z4TQTGzCTVj8Tx5uzRRXtxF+9GjSF7zrjPwFzkCaz69sT9ztzAL0TAdMduTsdOTDzgT-jVzIzNzpzyTV9MLUL1zyLQL0LiTCLmzSLmLHt1NCVBLOtf1xlRTuDJTZDrDXD81FLJD7THDgzpTjLtpWuDTzTqpChZlNDXTjDPLLTvLXLbLbDdT9LTLAzX9oDfzkrqT6zWL5NmBXtqzg9t1tBgOSrarKzjjTB9BeemrDBT9ErL9Brb9RrCaLzurUDhEPzsC5r4mlrIDFR9rdrcDNJjrLrzrSYTzDoqaDkcwYarrdzFrmzwD7rwLtrqtMzkzhzJzUbezMbRtoLcd0r-zGLgLsr+LRLhL4exLSN4LubCbkLodLtZz2LxbAbWzKLcLaLabKbIL6LqLuL31TthbEWpLadeDGd-T9TtLPTnbIrNLLD3btTTdcunLcrgrVLlTHTkDTTM73TArs7-LY7w7Yr-bslgt+z0bvjNb5bdblbDbajJb5laJ7zPdEbp9G7sbFr4DTrTjbrt7Hr-r8jwb97obOLEz4bJ7kjf9Jr4rN9P7Uzf7gHyTwDzQPrkRDkb7RM6lYbZbz7+7h9bziHe9yHmB7q8VGbOtETu7MreL276t2bgd+beTjbGT+TTbmTYdRHELxHB7DtBHYLFbOHW79bqbuHLHtb1bqj9HibLirbTadVK7gnXbA7In1TjdTDwnYn1DQrC7fLcnQ7EnfbQnJ58jc7S7infTL7kga13Ha1CHKHyR+n8r8LbHe7rHzHZnHHpn07x7SHx9Zrjup7Ib1rjnX7xzl7vdS7kHO7nHlnPn1nyb7HMHobcH77sH-737Y9YHyT0XmzsX4XQHh7QbEXIFbnnn8bSzdjCztZNH3HBbvnTHtHr7pbxXvpeXuXmbkxlXPJ1Xv1tXP1DX5HZHpHJHidsLhXWHBXgXfn+HtXhTydemqd-H6dDLq7o3ynmnk7Snkn43M3orQZnV8nsJzp3LS3qni763a3KlanE7MZrnszcbyz2XirGr6rx3yr53SbUr7X3XHXJnFnQmTndnhnnz8zmXizXX13jHt30+oXgbZb8XobgP27f3wXIPKXQuwP4ToHYJUPfnoPCPEPZ7lzl3p3aPqP2X6HWb9XTXD3P3X32H+P1HxPebzbDHZPPHVHpPFHObVPdPFP+XzXbX9Pn3V3bPN3FX10A3zeQ3g37bs303gvk3gjvbwvwrYvy7c3Y3gJnT4727O323G3ivW3l5tDj5YO4denr3N7Wr6P73DjZ3+vJ3GPRvF3pv7P33BPrPHPhvF7GXdvR35vevWgnrJIrvsvYPQXiP3x7v3zj7Kl3vwHEP-vQXcPhXvvVwEf3daXyPvztvh3WXTvJvLvDn1PTPWTLP6flHhPVvAXufePnP2PGHRfJfVXxfZfpfNX5fVflfdX1fdftfjXLXRXeHJXPVWm3PTeza83Qvovff1LE3-fU3EvGnQ-7DK3ml0HU-SvQX0-KvfnDkAATMI3jP0mH36-kGH794pqn6ayRcnwnx94fwb878f8b0nxfw74n1fx7953f236o0Zy989x8y-ygU99e+e2f-n0A0j854gtHwO6pcgBLfILvf0RYP8eu4zZ-gZ1f6wCvmFtLHhX2QE18UBDfNAU33nbgCkuZbXrvX0wEZ8GehfDAbj3SbM8iBJPTPq10IE09COFAtPtQPkZ4Da+-XLBnz1qojce+I-OltwJ7YD8peg-fgb3yEGl0J+WlZJnP02aSDcBUXaDoHxwGlcFBrfI9m9xv4n8D+7ne3t-3j6aDHeUjSNroOv7aCbeJgy3joPS56DjBGgiwUYMMG39IBd3KtlYMv7OC1BrLfzgXwt458vBbgs3r4PMGx8XO2aWBlp1rwYNK84Qlaug2iEoN528ghLmV3-7cIkG4OSIWEJiERCMhUQ2ITkMyG5DsheQwoQUOKHpCl28QkLhDw75sCeeODNtuS0EHD8x+4vJoZL2EGNCRBLQ0fkINGYSCx6O+XYvd1AFQCVBEAkYUoLAEOCiepg7wafzsHqCXBcw8-v4NmE2Cj+iwvwa4Lz4+Cth0wgrksM2HrCAh2vLAZMJ-5P84BqHY4R50647CzBuwg4ba115UCyBNArPrT3oHPDyulAj4T8NoH2DRh4wtJl8IYEvDs+fwynr8LeF0DwRjPRge8JhHEDUBSI9AZo0GE3DPBIIqoVpAnK1Dhu-PLgZ0J4GEi+B7Q0kSLw6EUiyRwrHoVIL6HQCLhMAy4W-1UEPD0RQwmzolwSGAjHB8HK4VoMOErDzhCAjYQKOsFCiYipw7YQ93cHCijhzIo5uyKmF3CxRfIywaKIWGrCORAImQdqMUF0ccezfYEZ8INHkCER3ws0SCLZFWi0Rgwo0ZCLhHQioR5PC0caPwGkC7RLo+0aCPhFOiIR1vZUTMIDHPQ+OfPeoQIPDFtDyRVI1obwIU5EjKRUY8flSmwE6juR+w9UcsJVHyjN2moybD3QVY-9rRTgjMQ8PFEKiyxOYisR5ytYAC5RiZG0cWMVFrN0xuYkUa2PMFFj92bIqsfyPbGCjVRtgpsVKKHH3CMRroxvu6JNGvCHRzo30bCO9Gq9zOI4oMXOMREoj1xBAsEauPNHbjMRU4rcTOL9G7jnhnYpcaeKs51pO+cxPEWGMjHNCEx946MV0KfHxiXxJIxMf-iqqvN6xjY88XiV36WAo++3AwX2KzHwCWRJYyCaBMDEwT-RsE0sQOLWHQSU++-QCSHyQmb0gJKrJ4RqM3oFjhx+E9ri2J7Fqjlx8EscbhMQnzDMxlE7MTWSQGojfxDYrscxKXEejjxXo9iYePnFcSFxs47iWuNs4sSmJjY3iWJP3E+iBJO4qSXuLdGGiJJjomSSeNYkXiyJcE4MVeN541DbxsYmTs+I-ExjiRcY98Y+IMnrsEJdE3sYRMY4yiJR5YqicRNEI1j+AjBPVnWOM6YcDGKkjwchIsnh5nJOXdyckSwl79QhGEhyW2JImDi-xQkpkeBPsmeSRJwk3kZZNIlRTwpL-HukIzSHJDzK5Q8HpyIqHQMkhvCFIcELKmloKp5aKqcXhynTt8pXvSoSVMQZ1SWpWQ0oUUI6klDcp7UnqfkK6kDSPeDU+HsHxKnb9ipYU6qppNxGhjhKDQgyfpNMlLTDJD4ladzA14JsteqUwcelOonWdbJuonZgBJol7DCxEU7VlNg35JSzx3klMXqPunKDKxJU78WFzj79idaIUiRiAN2mOTtpSEmKZKKIk2sLsF0kGdhLcngydWoMkAWyICkvTGRCMhkUjNlGQzLpgkycXJNNG3DyJak7GZ6PUl4zCZSkziQpP4l8StR3IpUSTMxnTjyZPE0mUeOJn4yiZuMiiQTLZksy2R4kmmSS2mkcD8R0vQWfNOWmLS1pBkjaRTy2nxS6SMfc6e9OlnXDvJw0nka9MeledAZK46UWdOumqSAZh0iYfrOGEfs-pfvVCShNVYrC4ZwMkAVbOhkgSfpkUpycdM5kMz6ZPMySXTPRk69VZO0uWWBJ9kuTkGnUvqcHNKmtSg53U+qaNMmnjSg+hUgqXHMTmq1spvUsOanLallDo5n-LkTnKKlJz9Rk09wcrNjnJd45jUsuSNIrkqz-uec0ufnPTbZzQ5Gc3bpRBDHaS5pEY3SS3LFkizXxe3Ryt9L9m0T-Jzsq9hDNCk4TzZjcr1qPMeHjzh5AcwKcayrmfVp5tYlYdZJxmbzTp0rA6ZTO1nJSbpOsz3pXPrnt9mpEcwaWnP6khzI5zc3KvDORkQTPZ0kl+bJInHyT3ZiktTIPI+mzzMJs87mR-KxlMyOJzM0BRArfnKTj5d0tWQ9INn7zhxQCkgZ-J-GHzdZt0jWVvMwWGzq5PkvWYgtHGsziFBCgucAtpldyHQbc7vkLM7lGSb54AHTs9MAH2yh5J0h4bbNRlgyJ5i8yPuhNNmFybWZRfhXmNlmTTH5KM-2YjMkULzpFz8-+cwtSFxCQha82+YuJrkJy65WishbwsvlqL9F18puXosMV3zjF98t3gosyld0lFDC8xQYrsUmKr5Di5xWYuMWuSoONskRUIpUW6KbFRivxaYoCVOLXFQS+xSEvKl5Ss5i8kubnPPmCLDWE01RY4rCWhLklaSouVEo0Xlyz52S7RbXNiW5KClp8vJZoqKWFcU5ti8JZVPDmpKXFonReNQoE50LVpEsqeb4tRmqZAh686wZwp4VQyuFnii+RdOEVDKOlJRUZX0pPkCKklfCiZWhLmVtL+lky7hV9NYUmzfpCs3sWhxYVf9O6NU6tDUoiXpyql1Uw5dUuOW1KTltUi5UcsqWXL7lty-xY8sCXh0JFzJJhV-LJnILkRm4j2d8o3EQM3lImVpQcpuXnK7lzy4JQ8vBVPKYVLyuFVCuXmJD4lkKlJaivSVXLQVEKhFWio-qZKplAjLJUNPxWAMKlsK05WCopXYqqV5K65dSrpW0qsVjKvZSZNaGNLOBtCnaJ9MWVTLZlKK5ZYMv5WrLdlKRD-ovPcW8rvFDrBZRMxmVSrvZRK6Ze0smUjKhVPK1VXKuAkirelsip+URR2Uo8aV8Ko1YipxUYroVJq3FZavNXoq6ltqzFSyspUMrjVzq01dartVmqPV7qh1T-LWUjyZVjq+lUypdXBq3Vrqq1eGptWeqfVOqnleZMgX-Lfl38xNRjPIUHioF1MtNX8tdleyQFGa8BfmrAVFqE1Oa1+SmtQUoK815aqtaWvfloDRZrA7Edg35k6T6FvWMVYqqBUyzf5SSrtQ+wDVzzFVfKzVQPJAmxrZVyq4VYavVXjK1VE6odQarek9KvFwy2dSOoFVjr+FDEyVRasjVeq91PqslSGsDXMrfVTq0NRGovVRrvVu6q9furvWHqB1R6sNQ+tvUnrj1Z6oNe+u6XzK51Y8hdaupX7frL1wG69QerfWfrT1z6kDZBofmLqghsBEFaBvvXIbH1f62DS+tQ0QboNYG19fauw1PrCN6GnDShow0waSNaG9dTevw00bo1BG4jURqo3gbaN1GujSxuY1sbONrGgkVz2qFd8mld4nuVMu3VZSzZfkuKRJsRkdq9VT09ZY7JNmPzpNomhjSpqY14auNHG7jZpu03qatNumnTVhvY36bjNhmjTSZrI24bTNemqzQZos2kaKN9GtTTZqvUfLe1lGxeWtWi6Ty8YOGv1r5vCg4bPN-m6KMFpBihaIY4WvOKB3jVkxotMMmHkBuqBh9DwyWh8Klq1XTr51O6sLYopy1JAw+rmnzRLHS3KgSt2IMreSAq2IgqtfQGrcUDq1JbRYDWhLabGa2b8mtHW4rZ1ta3daaobW-Lb1oUj9a5Aw2orT1q60TbxtU2vrYNtUijaPF02obbNpYjzbYtfc3uYRHZUCzhZQmhtetoVSCrvN-6tGXbO1Wzzx1x2lZTOpAEOajNzm+7XZvc0Aa7tj2xzZOts23azND2z7dZte0vaftH2xje9vM0A6QdQO57V9r+2Q7Qd328Hdluh25aE2fa3sdyqy3r8bW6OwDZusR2-q3NF0zHajIJ2TKiduO8VRjt9bk6bt7WybTNpp02A1qqOhbXjsJ0U78drOsZfzEi1YwWt6CALdTpAleaxtIqwXQtuF087Mt9W5bSeFW0y6pdP4WXXTrm1y6pwCuxbUrsV0rbldKWrXWlp13ShVdtOtXZro13S69dpWs3QLyxEvIZp7c-BoJr22sqHdxk53XpP21O7Xdjut3V7s90+6Xd3c93f7u91+6KmC0oPR7uD01Nw9UewPb7uj0h6NtEenUozsHVraBda-NEmv3Z0QxM9MMrpYHOih56l52esTUTEL1+sy94UCvQXv53C6c9IE8XerqN2m6Td8ui3ZVrb3VaO9tWrvZLpb0q6e9jWvvdrqH266R9+ugfQ3uN1N7W9Y+83bPvK2Kcttra1aQHvj27aw9MexPdJ031x7I9O+-fWvtX177D9G+k-bHoP3H7L94nU-Vfu31n6t9lLe-bvuv3n6n9F+l-Q-sHbP679t+x-b-q-3v6f9H+7-X-uAOAHQDQByAxAegMAG39VCvmVjW23NK3xn++pTxpQMgHYD-+tA5ysoXYGpOMBnAztqP1gG4D+By3W2rIOkHyD6B0Pa-poO4HKDDB4gzfuoNsGoDWB9g4QYIOcGODRB5A3QdQM8H+D9u1g3weEO8cEDxTDuaIfoNcHeD3BigyvrEOKHaDCezAyIbwPyHNDTB7QxIaUMYHwDCh4wzoeUNyHxDBhwQxof0NqH195h1Q4wbMNCHLD6how6YcMNUGLDthkg14ccMeHmDl4vjdeNmllggAA"
|
||
));
|
||
|
||
export default createNewAscii;
|