Commit ee8b98be authored by nanahira's avatar nanahira

add noCompact mode

parent 770e2a87
import { fromBase64Url, toBase64Url } from './src/base64'; import { fromBase64Url, toBase64Url } from './src/base64';
import { BufferReader, BufferWriter, countItems } from './src/utils'; import { BufferReader, BufferWriter, countConsecutiveItems, countItems } from './src/utils';
import { fromYdkeURL, toYdkeURL } from './src/ydke'; import { fromYdkeURL, toYdkeURL } from './src/ydke';
import { fromYGOMobileDeckURL, toYGOMobileDeckURL } from './src/ygom'; import { fromYGOMobileDeckURL, toYGOMobileDeckURL } from './src/ygom';
...@@ -9,23 +9,23 @@ export default class YGOProDeck { ...@@ -9,23 +9,23 @@ export default class YGOProDeck {
side: number[] = []; side: number[] = [];
name?: string; name?: string;
bufferLength() { bufferLength(noCompact = false) {
const counted = [this.main, this.extra, this.side].map(countItems); const counted = [this.main, this.extra, this.side].map(noCompact ? countConsecutiveItems : countItems);
return counted.reduce((a, b) => a + b.size * 4, 0); return counted.reduce((a, b) => a + b.length * 4, 0);
} }
toUint8Array() { toUint8Array(noCompact = false) {
const counted = [this.main, this.extra, this.side].map(countItems); const counted = [this.main, this.extra, this.side].map(noCompact ? countConsecutiveItems : countItems);
const writer = new BufferWriter( const writer = new BufferWriter(
counted.reduce((a, b) => a + b.size * 4, 0), counted.reduce((a, b) => a + b.length * 4, 0),
); );
const writeCards = (countMap: Map<number, number>, type: number) => { const writeCards = (countMap: { item: number, count: number }[], type: number) => {
// each card: 28 bits for id, 2 bits(0, 1, 2, 3) for type(0: main, 1: extra, 2: side, 3: unknown), 2 bits for count (0: 1, 1: 2, 2: 3, 3: 4) // each card: 28 bits for id, 2 bits(0, 1, 2, 3) for type(0: main, 1: extra, 2: side, 3: unknown), 2 bits for count (0: 1, 1: 2, 2: 3, 3: 4)
for (const [id, count] of countMap.entries()) { for (const { item, count } of countMap) {
if (count > 4) { if (count > 4) {
throw new Error(`Too many cards: ${id}`); throw new Error(`Too many cards: ${item}`);
} }
const value = (id & 0xfffffff) | (type << 28) | ((count - 1) << 30); const value = (item & 0xfffffff) | (type << 28) | ((count - 1) << 30);
writer.writeUint32LE(value); writer.writeUint32LE(value);
} }
}; };
...@@ -33,12 +33,12 @@ export default class YGOProDeck { ...@@ -33,12 +33,12 @@ export default class YGOProDeck {
return writer.buffer; return writer.buffer;
} }
toEncodedString() { toEncodedString(noCompact = false) {
return toBase64Url(this.toUint8Array()); return toBase64Url(this.toUint8Array(noCompact));
} }
toString() { toString(noCompact = false) {
return this.toEncodedString(); return this.toEncodedString(noCompact);
} }
fromUint8Array(buf: Uint8Array) { fromUint8Array(buf: Uint8Array) {
......
...@@ -3,8 +3,37 @@ export function countItems<T>(arr: T[]) { ...@@ -3,8 +3,37 @@ export function countItems<T>(arr: T[]) {
for (const item of arr) { for (const item of arr) {
map.set(item, (map.get(item) || 0) + 1); map.set(item, (map.get(item) || 0) + 1);
} }
return map; const blocks: { item: T, count: number }[] = [];
for (const [item, count] of map.entries()) {
blocks.push({ item, count });
}
return blocks;
}
export function countConsecutiveItems<T>(arr: T[]) {
const result: { item: T; count: number }[] = [];
if (arr.length === 0) return result;
let currentItem = arr[0];
let count = 1;
for (let i = 1; i < arr.length; i++) {
if (arr[i] === currentItem) {
count++;
} else {
result.push({ item: currentItem, count });
currentItem = arr[i];
count = 1;
}
}
// 推入最后一组
result.push({ item: currentItem, count });
return result;
} }
abstract class BufferCursor { abstract class BufferCursor {
buffer: Uint8Array; buffer: Uint8Array;
pointer = 0; pointer = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment