Adds the lib/base service layer: hire/fire staff, set labor headcount, storage consumption helpers, and structure upgrade handling, all with event logging and permission checks. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import type { Payload } from "payload";
|
|
import type { GameStructure, Resource } from "@/payload-types";
|
|
|
|
type StorageEntry = NonNullable<GameStructure["storedResources"]>[number];
|
|
|
|
export function relationshipId(
|
|
value: number | { id: number } | null | undefined,
|
|
): number | null {
|
|
if (typeof value === "number") return value;
|
|
return value?.id ?? null;
|
|
}
|
|
|
|
export function storedAmount(entries: readonly StorageEntry[], resourceId: number): number {
|
|
return entries.reduce((total, entry) => {
|
|
return total + (relationshipId(entry.resource) === resourceId ? entry.amount : 0);
|
|
}, 0);
|
|
}
|
|
|
|
export function consumeStorage(
|
|
entries: readonly StorageEntry[],
|
|
resourceId: number,
|
|
requested: number,
|
|
): { readonly entries: StorageEntry[]; readonly remaining: number } {
|
|
let remaining = requested;
|
|
const updated = entries
|
|
.map((entry) => {
|
|
if (remaining <= 0 || relationshipId(entry.resource) !== resourceId) return entry;
|
|
const consumed = Math.min(entry.amount, remaining);
|
|
remaining -= consumed;
|
|
return { ...entry, amount: entry.amount - consumed };
|
|
})
|
|
.filter((entry) => entry.amount > 0);
|
|
return { entries: updated, remaining };
|
|
}
|
|
|
|
export async function resourceName(payload: Payload, resource: number | Resource): Promise<string> {
|
|
if (typeof resource === "object") return resource.name;
|
|
const document = await payload
|
|
.findByID({ collection: "resources", id: resource, depth: 0, overrideAccess: true })
|
|
.catch(() => null);
|
|
return document?.name ?? `Resource #${resource}`;
|
|
}
|