boardgame-core/src/core/part-factory.ts

97 lines
2.1 KiB
TypeScript

import {Part} from "./part";
export type PartTemplate<TMeta = {}> = Omit<Partial<Part<TMeta>>, 'id'> & TMeta;
export type PartPool<TMeta = {}> = {
parts: Record<string, Part<TMeta>>;
template: PartTemplate<TMeta>;
draw(): Part<TMeta> | undefined;
return(part: Part<TMeta>): void;
remaining(): number;
};
export function createPart<TMeta = {}>(
template: PartTemplate<TMeta>,
id: string
): Part<TMeta> {
return {
regionId: '',
position: [],
...template,
id,
} as Part<TMeta>;
}
export function createParts<TMeta = {}>(
template: PartTemplate<TMeta>,
count: number,
idPrefix: string
): Part<TMeta>[] {
const parts: Part<TMeta>[] = [];
for (let i = 0; i < count; i++) {
parts.push(createPart(template, `${idPrefix}-${i + 1}`));
}
return parts;
}
export function createPartPool<TMeta = {}>(
template: PartTemplate<TMeta>,
count: number,
idPrefix: string
): PartPool<TMeta> {
const partsArray = createParts(template, count, idPrefix);
const parts: Record<string, Part<TMeta>> = {};
for (const part of partsArray) {
parts[part.id] = part;
}
const available = [...partsArray];
return {
parts,
template,
draw() {
return available.pop();
},
return(part: Part<TMeta>) {
part.regionId = '';
part.position = [];
available.push(part);
},
remaining() {
return available.length;
},
};
}
export function mergePartPools<TMeta = {}>(
...pools: PartPool<TMeta>[]
): PartPool<TMeta> {
if (pools.length === 0) {
return createPartPool({} as PartTemplate<TMeta>, 0, 'merged');
}
const allPartsArray = pools.flatMap(p => Object.values(p.parts));
const allParts: Record<string, Part<TMeta>> = {};
for (const part of allPartsArray) {
allParts[part.id] = part;
}
const template = pools[0].template;
const available = allPartsArray.filter(p => p.regionId === '');
return {
parts: allParts,
template,
draw() {
return available.pop();
},
return(part: Part<TMeta>) {
part.regionId = '';
part.position = [];
available.push(part);
},
remaining() {
return available.length;
},
};
}