|
@@ -55,10 +55,56 @@ function downloadStringAsFile(filename, text) {
|
|
URL.revokeObjectURL(link.href);
|
|
URL.revokeObjectURL(link.href);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function ydkeEncode(d) {
|
|
|
|
+ let deck = [];
|
|
|
|
+ for (let card of d) {
|
|
|
|
+ let num = parseInt(card);
|
|
|
|
+ if (isNaN(num)) continue;
|
|
|
|
+ deck.push(num);
|
|
|
|
+ }
|
|
|
|
+ const buffer = new ArrayBuffer(deck.length * 4);
|
|
|
|
+ const view = new DataView(buffer);
|
|
|
|
+ for (let i = 0; i < deck.length; i++) {
|
|
|
|
+ // Little-endian
|
|
|
|
+ view.setUint32(i * 4, deck[i], true);
|
|
|
|
+ }
|
|
|
|
+ return btoa(String.fromCharCode(...new Uint8Array(buffer)));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function ydkeDecode(encodedDeck) {
|
|
|
|
+ const binaryString = atob(encodedDeck);
|
|
|
|
+ const buffer = new ArrayBuffer(binaryString.length);
|
|
|
|
+ const view = new DataView(buffer);
|
|
|
|
+ for (let i = 0; i < binaryString.length; i++) {
|
|
|
|
+ view.setUint8(i, binaryString.charCodeAt(i));
|
|
|
|
+ }
|
|
|
|
+ const deck = [];
|
|
|
|
+ for (let i = 0; i < buffer.byteLength; i += 4) {
|
|
|
|
+ deck.push(String(view.getUint32(i, true))); // Little-endian
|
|
|
|
+ }
|
|
|
|
+ return deck;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function parseYdke(ydkeString) {
|
|
|
|
+ const [mainEncoded, extraEncoded, sideEncoded] = ydkeString.split('!');
|
|
|
|
+ const main = ydkeDecode(mainEncoded);
|
|
|
|
+ const extra = ydkeDecode(extraEncoded);
|
|
|
|
+ const side = ydkeDecode(sideEncoded);
|
|
|
|
+ return { main, extra, side };
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function genYdke(deck) {
|
|
|
|
+ const mainEncoded = ydkeEncode(deck.main);
|
|
|
|
+ const extraEncoded = ydkeEncode(deck.extra);
|
|
|
|
+ const sideEncoded = ydkeEncode(deck.side);
|
|
|
|
+ return `${mainEncoded}!${extraEncoded}!${sideEncoded}`;
|
|
|
|
+}
|
|
|
|
|
|
export {
|
|
export {
|
|
parseYdk,
|
|
parseYdk,
|
|
genYdk,
|
|
genYdk,
|
|
|
|
+ parseYdke,
|
|
|
|
+ genYdke,
|
|
downloadStringAsFile,
|
|
downloadStringAsFile,
|
|
};
|
|
};
|
|
|
|
|