feat: 국가 멸망 처리 로직 추가 및 관련 테스트 케이스 작성

This commit is contained in:
2026-01-24 18:47:25 +00:00
parent 5627c80f4a
commit cc797c185d
3 changed files with 343 additions and 0 deletions
+18
View File
@@ -241,6 +241,7 @@ export const createDatabaseTurnHooks = async (
troops,
deletedTroops,
deletedGenerals,
deletedNations,
diplomacy,
logs,
createdGenerals,
@@ -309,6 +310,23 @@ export const createDatabaseTurnHooks = async (
});
}
if (deletedNations.length > 0) {
await prisma.diplomacy.deleteMany({
where: {
OR: [
{ srcNationId: { in: deletedNations } },
{ destNationId: { in: deletedNations } },
],
},
});
await prisma.nationTurn.deleteMany({
where: { nationId: { in: deletedNations } },
});
await prisma.nation.deleteMany({
where: { id: { in: deletedNations } },
});
}
await Promise.all([
...generals
.filter((general) => !createdIds.has(general.id))
+64
View File
@@ -183,6 +183,7 @@ export class InMemoryTurnWorld {
private readonly createdDiplomacyKeys = new Set<string>();
private readonly deletedTroopIds = new Set<number>();
private readonly deletedGeneralIds = new Set<number>();
private readonly deletedNationIds = new Set<number>();
private readonly logs: LogEntryDraft[] = [];
private readonly scenarioConfig: ScenarioConfig;
private checkpoint?: TurnCheckpoint;
@@ -376,6 +377,24 @@ export class InMemoryTurnWorld {
return true;
}
removeNation(id: number): boolean {
if (!this.nations.has(id)) {
return false;
}
this.nations.delete(id);
this.dirtyNationIds.delete(id);
this.createdNationIds.delete(id);
this.deletedNationIds.add(id);
for (const [key, entry] of this.diplomacy) {
if (entry.fromNationId === id || entry.toNationId === id) {
this.diplomacy.delete(key);
this.dirtyDiplomacyKeys.delete(key);
this.createdDiplomacyKeys.delete(key);
}
}
return true;
}
applyDiplomacyPatch(input: { srcNationId: number; destNationId: number; patch: DiplomacyPatch }): void {
const key = buildDiplomacyKey(input.srcNationId, input.destNationId);
const existed = this.diplomacy.has(key);
@@ -586,6 +605,8 @@ export class InMemoryTurnWorld {
}
}
this.removeCollapsedNations();
return nextTurnAt;
}
@@ -632,6 +653,7 @@ export class InMemoryTurnWorld {
troops: Troop[];
deletedTroops: number[];
deletedGenerals: number[];
deletedNations: number[];
diplomacy: TurnDiplomacy[];
logs: LogEntryDraft[];
createdGenerals: TurnGeneral[];
@@ -668,6 +690,7 @@ export class InMemoryTurnWorld {
.filter((entry): entry is TurnDiplomacy => Boolean(entry));
const deletedTroops = Array.from(this.deletedTroopIds);
const deletedGenerals = Array.from(this.deletedGeneralIds);
const deletedNations = Array.from(this.deletedNationIds);
const logs = this.logs.splice(0, this.logs.length);
this.dirtyGeneralIds.clear();
@@ -681,6 +704,7 @@ export class InMemoryTurnWorld {
this.createdDiplomacyKeys.clear();
this.deletedTroopIds.clear();
this.deletedGeneralIds.clear();
this.deletedNationIds.clear();
return {
generals,
@@ -689,6 +713,7 @@ export class InMemoryTurnWorld {
troops,
deletedTroops,
deletedGenerals,
deletedNations,
diplomacy,
logs,
createdGenerals,
@@ -698,6 +723,45 @@ export class InMemoryTurnWorld {
};
}
private removeCollapsedNations(): void {
const collapsedNationIds: number[] = [];
for (const nation of this.nations.values()) {
if (nation.id <= 0) {
continue;
}
const meta = nation.meta as Record<string, unknown>;
if (meta.collapsed !== true) {
continue;
}
const cityCount = Array.from(this.cities.values()).filter((city) => city.nationId === nation.id).length;
if (cityCount > 0) {
continue;
}
collapsedNationIds.push(nation.id);
}
for (const nationId of collapsedNationIds) {
for (const general of this.generals.values()) {
if (general.nationId !== nationId) {
continue;
}
const updated = applyGeneralPatch(general, {
nationId: 0,
officerLevel: 0,
troopId: 0,
});
this.generals.set(general.id, normalizeGeneralTurnTime(updated, this.state.lastTurnTime));
this.dirtyGeneralIds.add(general.id);
}
for (const troop of Array.from(this.troops.values())) {
if (troop.nationId === nationId) {
this.removeTroop(troop.id);
}
}
this.removeNation(nationId);
}
}
private ensureDiplomacyMatrix(): void {
const nationIds = Array.from(this.nations.keys());
for (const srcNationId of nationIds) {