feat(server): extend InventionTimeline with full invention data and getSummaries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-03-09 00:41:11 +00:00
parent f362619c5f
commit 0ff4c24bd6
2 changed files with 73 additions and 6 deletions
@@ -15,6 +15,11 @@ describe('InventionTimeline', () => {
inventorName: 'Gwen',
tick: 500,
day: 2,
name: 'Rope',
category: 'material',
inputs: [{ itemId: 'plant_fiber', quantity: 3 }],
workshopType: null,
toolRequired: null,
});
const all = timeline.getAll();
expect(all).toHaveLength(1);
@@ -24,9 +29,9 @@ describe('InventionTimeline', () => {
it('counts inventions per entity', () => {
const timeline = createInventionTimeline();
timeline.record({ itemId: 'rope', inventorEntityId: 1, inventorName: 'Gwen', tick: 500, day: 2 });
timeline.record({ itemId: 'clay', inventorEntityId: 1, inventorName: 'Gwen', tick: 600, day: 2 });
timeline.record({ itemId: 'kiln', inventorEntityId: 2, inventorName: 'Bram', tick: 700, day: 3 });
timeline.record({ itemId: 'rope', inventorEntityId: 1, inventorName: 'Gwen', tick: 500, day: 2, name: 'Item', category: 'resource' as const, inputs: [], workshopType: null, toolRequired: null });
timeline.record({ itemId: 'clay', inventorEntityId: 1, inventorName: 'Gwen', tick: 600, day: 2, name: 'Item', category: 'resource' as const, inputs: [], workshopType: null, toolRequired: null });
timeline.record({ itemId: 'kiln', inventorEntityId: 2, inventorName: 'Bram', tick: 700, day: 3, name: 'Item', category: 'resource' as const, inputs: [], workshopType: null, toolRequired: null });
expect(timeline.countByEntity(1)).toBe(2);
expect(timeline.countByEntity(2)).toBe(1);
@@ -35,10 +40,53 @@ describe('InventionTimeline', () => {
it('returns entries in insertion order', () => {
const timeline = createInventionTimeline();
timeline.record({ itemId: 'a', inventorEntityId: 1, inventorName: 'X', tick: 300, day: 1 });
timeline.record({ itemId: 'b', inventorEntityId: 2, inventorName: 'Y', tick: 100, day: 1 });
timeline.record({ itemId: 'a', inventorEntityId: 1, inventorName: 'X', tick: 300, day: 1, name: 'Item', category: 'resource' as const, inputs: [], workshopType: null, toolRequired: null });
timeline.record({ itemId: 'b', inventorEntityId: 2, inventorName: 'Y', tick: 100, day: 1, name: 'Item', category: 'resource' as const, inputs: [], workshopType: null, toolRequired: null });
const all = timeline.getAll();
expect(all[0].tick).toBe(300);
expect(all[1].tick).toBe(100);
});
it('stores and returns full invention summary data', () => {
const timeline = createInventionTimeline();
timeline.record({
itemId: 'rope',
inventorEntityId: 1,
inventorName: 'Gwen',
tick: 500,
day: 2,
name: 'Rope',
category: 'material',
inputs: [{ itemId: 'plant_fiber', quantity: 3 }],
workshopType: null,
toolRequired: null,
});
const summaries = timeline.getSummaries();
expect(summaries).toHaveLength(1);
expect(summaries[0]).toEqual({
itemId: 'rope',
name: 'Rope',
category: 'material',
inputs: [{ itemId: 'plant_fiber', quantity: 3 }],
workshopType: null,
toolRequired: null,
inventorName: 'Gwen',
day: 2,
});
});
it('getSummaries returns entries in insertion order', () => {
const timeline = createInventionTimeline();
timeline.record({
itemId: 'a', inventorEntityId: 1, inventorName: 'X', tick: 300, day: 1,
name: 'A Item', category: 'tool', inputs: [], workshopType: null, toolRequired: null,
});
timeline.record({
itemId: 'b', inventorEntityId: 2, inventorName: 'Y', tick: 100, day: 1,
name: 'B Item', category: 'resource', inputs: [], workshopType: null, toolRequired: null,
});
const summaries = timeline.getSummaries();
expect(summaries[0].itemId).toBe('a');
expect(summaries[1].itemId).toBe('b');
});
});
+20 -1
View File
@@ -1,4 +1,4 @@
import type { EntityId } from '@dflike/shared';
import type { EntityId, InventionSummary } from '@dflike/shared';
export interface InventionEntry {
itemId: string;
@@ -6,11 +6,17 @@ export interface InventionEntry {
inventorName: string;
tick: number;
day: number;
name: string;
category: 'resource' | 'tool' | 'material' | 'structure';
inputs: { itemId: string; quantity: number }[];
workshopType: string | null;
toolRequired: string | null;
}
export interface InventionTimeline {
record(entry: InventionEntry): void;
getAll(): InventionEntry[];
getSummaries(): InventionSummary[];
countByEntity(entityId: EntityId): number;
}
@@ -26,6 +32,19 @@ export function createInventionTimeline(): InventionTimeline {
return [...entries];
},
getSummaries(): InventionSummary[] {
return entries.map(e => ({
itemId: e.itemId,
name: e.name,
category: e.category,
inputs: e.inputs,
workshopType: e.workshopType,
toolRequired: e.toolRequired,
inventorName: e.inventorName,
day: e.day,
}));
},
countByEntity(entityId: EntityId): number {
return entries.filter(e => e.inventorEntityId === entityId).length;
},