fix: 커맨드 차등 생명주기와 로그 그래프를 보강
장수 55종과 수뇌 35종의 상태, 로그, 메시지, 예약 턴 비교를 닫습니다. 실제 시나리오 프로필과 대표 PostgreSQL 수명주기, 즉시 외교와 출병 회귀를 추가하고 발견된 Ref 로그 및 생성 장수 저장 차이를 교정합니다.
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
import type { CanonicalTurnSnapshot, TurnSnapshotSelector } from './canonical.js';
|
||||
import type { TurnCommandFixtureRequest } from './coreCommandTrace.js';
|
||||
|
||||
const asRecord = (value: unknown): Record<string, unknown> =>
|
||||
typeof value === 'object' && value !== null && !Array.isArray(value) ? (value as Record<string, unknown>) : {};
|
||||
|
||||
const semanticTimestamp = (value: unknown): number => {
|
||||
const raw = String(value);
|
||||
const normalized = raw.includes('T') ? raw : `${raw.replace(' ', 'T').replace(/\.(\d{3})\d*$/, '.$1')}Z`;
|
||||
return new Date(normalized).getTime();
|
||||
};
|
||||
|
||||
const semanticTurnArgs = (value: unknown): unknown => (Array.isArray(value) && value.length === 0 ? {} : value);
|
||||
|
||||
export const fullLifecycleGeneralTurns = Array.from({ length: 30 }, (_, turnIndex) => ({
|
||||
generalId: 1,
|
||||
turnIndex,
|
||||
action: turnIndex === 0 ? 'che_훈련' : '휴식',
|
||||
args: {},
|
||||
}));
|
||||
|
||||
export const fullLifecycleNationTurns = Array.from({ length: 12 }, (_, turnIndex) => ({
|
||||
nationId: 1,
|
||||
officerLevel: 12,
|
||||
turnIndex,
|
||||
action: turnIndex === 0 ? 'che_국호변경' : '휴식',
|
||||
args: turnIndex === 0 ? { nationName: '수명주기국' } : {},
|
||||
}));
|
||||
|
||||
export const fullLifecycleSnapshotSelector: TurnSnapshotSelector = {
|
||||
generalIds: [1],
|
||||
cityIds: [3],
|
||||
nationIds: [1],
|
||||
allGenerals: true,
|
||||
allCities: true,
|
||||
allNations: true,
|
||||
allTroops: true,
|
||||
includeRankMirrors: true,
|
||||
logAfterId: 0,
|
||||
messageAfterId: 0,
|
||||
includeNationHistoryLogs: true,
|
||||
includeGlobalHistoryLogs: true,
|
||||
};
|
||||
|
||||
export const fullLifecycleTurnCommandRequest: TurnCommandFixtureRequest = {
|
||||
kind: 'general',
|
||||
actorGeneralId: 1,
|
||||
action: 'che_훈련',
|
||||
args: {},
|
||||
includeLifecycle: true,
|
||||
setup: {
|
||||
isolateWorld: true,
|
||||
world: {
|
||||
startYear: 180,
|
||||
year: 190,
|
||||
month: 1,
|
||||
hiddenSeed: 'turn-command-full-lifecycle-v1',
|
||||
freezeClock: true,
|
||||
},
|
||||
nations: [
|
||||
{
|
||||
id: 1,
|
||||
name: '아국',
|
||||
color: '#777777',
|
||||
capitalCityId: 3,
|
||||
gold: 1_000_000,
|
||||
rice: 1_000_000,
|
||||
tech: 1_000,
|
||||
level: 1,
|
||||
typeCode: 'che_명가',
|
||||
generalCount: 1,
|
||||
meta: { can_국호변경: 1 },
|
||||
},
|
||||
],
|
||||
cities: [
|
||||
{
|
||||
id: 3,
|
||||
nationId: 1,
|
||||
level: 5,
|
||||
population: 100_000,
|
||||
populationMax: 200_000,
|
||||
agriculture: 1_000,
|
||||
agricultureMax: 2_000,
|
||||
commerce: 1_000,
|
||||
commerceMax: 2_000,
|
||||
security: 1_000,
|
||||
securityMax: 2_000,
|
||||
supplyState: 1,
|
||||
frontState: 0,
|
||||
defence: 1_000,
|
||||
defenceMax: 2_000,
|
||||
wall: 1_000,
|
||||
wallMax: 2_000,
|
||||
state: 0,
|
||||
term: 0,
|
||||
trust: 80,
|
||||
trade: 100,
|
||||
},
|
||||
],
|
||||
generals: [
|
||||
{
|
||||
id: 1,
|
||||
name: '수명주기장수',
|
||||
nationId: 1,
|
||||
cityId: 3,
|
||||
troopId: 0,
|
||||
leadership: 90,
|
||||
strength: 80,
|
||||
intelligence: 70,
|
||||
leadershipExp: 0,
|
||||
strengthExp: 0,
|
||||
intelExp: 0,
|
||||
experience: 1_000,
|
||||
dedication: 1_000,
|
||||
expLevel: 0,
|
||||
officerLevel: 12,
|
||||
officerCityId: 3,
|
||||
belong: 10,
|
||||
permission: 'normal',
|
||||
injury: 0,
|
||||
age: 30,
|
||||
gold: 100_000,
|
||||
rice: 100_000,
|
||||
crew: 1_000,
|
||||
crewTypeId: 1_100,
|
||||
train: 50,
|
||||
atmos: 50,
|
||||
killTurn: 24,
|
||||
npcState: 0,
|
||||
blockState: 0,
|
||||
personality: 'None',
|
||||
specialDomestic: 'None',
|
||||
specialWar: 'None',
|
||||
itemHorse: 'None',
|
||||
itemWeapon: 'None',
|
||||
itemBook: 'None',
|
||||
itemExtra: 'None',
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
generalTurns: fullLifecycleGeneralTurns,
|
||||
nationTurns: fullLifecycleNationTurns,
|
||||
},
|
||||
observe: fullLifecycleSnapshotSelector,
|
||||
};
|
||||
|
||||
export const projectFullLifecycleSnapshotGraph = (snapshot: CanonicalTurnSnapshot): Record<string, unknown> => {
|
||||
const general = snapshot.generals.find((entry) => entry.id === 1);
|
||||
const nation = snapshot.nations.find((entry) => entry.id === 1);
|
||||
return {
|
||||
actor: general
|
||||
? {
|
||||
nationId: general.nationId,
|
||||
cityId: general.cityId,
|
||||
train: general.train,
|
||||
atmos: general.atmos,
|
||||
experience: general.experience,
|
||||
dedication: general.dedication,
|
||||
leadershipExp: general.leadershipExp,
|
||||
expLevel: general.expLevel,
|
||||
dedLevel: general.dedLevel,
|
||||
killTurn: general.killTurn,
|
||||
mySet: general.mySet,
|
||||
turnTime: semanticTimestamp(general.turnTime),
|
||||
lastTurn: general.lastTurn,
|
||||
}
|
||||
: null,
|
||||
nation: nation
|
||||
? {
|
||||
name: nation.name,
|
||||
gold: nation.gold,
|
||||
rice: nation.rice,
|
||||
canRename: asRecord(nation.meta).can_국호변경 ?? 0,
|
||||
}
|
||||
: null,
|
||||
actorRankData: snapshot.rankData
|
||||
.filter((row) => row.generalId === 1)
|
||||
.sort((left, right) => String(left.type).localeCompare(String(right.type)))
|
||||
.map((row) => ({
|
||||
nationId: row.nationId,
|
||||
type: row.type,
|
||||
value: row.value,
|
||||
})),
|
||||
generalTurns: snapshot.generalTurns
|
||||
.filter((turn) => turn.generalId === 1)
|
||||
.sort((left, right) => Number(left.turnIndex) - Number(right.turnIndex))
|
||||
.map((turn) => ({
|
||||
turnIndex: turn.turnIndex,
|
||||
action: turn.action,
|
||||
args: semanticTurnArgs(turn.args),
|
||||
})),
|
||||
nationTurns: snapshot.nationTurns
|
||||
.filter((turn) => turn.nationId === 1 && turn.officerLevel === 12)
|
||||
.sort((left, right) => Number(left.turnIndex) - Number(right.turnIndex))
|
||||
.map((turn) => ({
|
||||
turnIndex: turn.turnIndex,
|
||||
action: turn.action,
|
||||
args: semanticTurnArgs(turn.args),
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
||||
export const addedFullLifecycleReferenceLogs = (
|
||||
before: CanonicalTurnSnapshot,
|
||||
after: CanonicalTurnSnapshot
|
||||
): Array<Record<string, unknown>> =>
|
||||
after.logs.filter((entry) => {
|
||||
const scope = String(entry.scope).toLowerCase();
|
||||
const category = String(entry.category).toLowerCase();
|
||||
const usesWorldHistory = scope === 'nation' || (scope === 'system' && category === 'history');
|
||||
const watermark = usesWorldHistory ? before.watermarks.historyLogId : before.watermarks.logId;
|
||||
return Number(entry.id) > watermark;
|
||||
});
|
||||
Reference in New Issue
Block a user