fix(api): align scenario 2601 reference data

This commit is contained in:
2026-08-04 05:29:12 +00:00
parent 87965a39d6
commit 9cfeaed3fe
10 changed files with 212 additions and 78 deletions
@@ -27,6 +27,8 @@ export const getBattleCenter = accessAuthedProcedure.query(async ({ ctx }) => {
select: {
id: true,
name: true,
picture: true,
imageServer: true,
npcState: true,
officerLevel: true,
cityId: true,
@@ -43,6 +45,16 @@ export const getBattleCenter = accessAuthedProcedure.query(async ({ ctx }) => {
crew: true,
train: true,
atmos: true,
age: true,
crewTypeId: true,
weaponCode: true,
bookCode: true,
horseCode: true,
itemCode: true,
personalCode: true,
specialCode: true,
special2Code: true,
meta: true,
},
orderBy: { id: 'asc' },
}),
@@ -79,29 +91,62 @@ export const getBattleCenter = accessAuthedProcedure.query(async ({ ctx }) => {
}
}
const generals = generalRows.map((general) => ({
id: general.id,
name: general.name,
npcState: general.npcState,
officerLevel: general.officerLevel,
cityId: general.cityId,
turnTime: formatDateTime(general.turnTime),
recentWar: formatDateTime(general.recentWarTime),
warnum: battleCountMap.get(general.id) ?? 0,
stats: {
leadership: general.leadership,
strength: general.strength,
intelligence: general.intel,
},
experience: general.experience,
dedication: general.dedication,
injury: general.injury,
gold: general.gold,
rice: general.rice,
crew: general.crew,
train: general.train,
atmos: general.atmos,
}));
const generals = generalRows.map((general) => {
const meta =
general.meta && typeof general.meta === 'object' && !Array.isArray(general.meta)
? (general.meta as Record<string, unknown>)
: {};
const metaNumber = (key: string): number => {
const value = meta[key];
return typeof value === 'number' && Number.isFinite(value) ? value : 0;
};
return {
id: general.id,
name: general.name,
picture: general.picture,
imageServer: general.imageServer,
npcState: general.npcState,
officerLevel: general.officerLevel,
cityId: general.cityId,
turnTime: formatDateTime(general.turnTime),
recentWar: formatDateTime(general.recentWarTime),
warnum: battleCountMap.get(general.id) ?? 0,
stats: {
leadership: general.leadership,
strength: general.strength,
intelligence: general.intel,
},
experience: general.experience,
dedication: general.dedication,
injury: general.injury,
gold: general.gold,
rice: general.rice,
crew: general.crew,
train: general.train,
atmos: general.atmos,
age: general.age,
crewTypeId: general.crewTypeId,
equipment: {
weapon: general.weaponCode,
book: general.bookCode,
horse: general.horseCode,
item: general.itemCode,
},
traits: {
personal: general.personalCode,
specialDomestic: general.specialCode,
specialWar: general.special2Code,
},
battleStats: {
kills: metaNumber('rank_killnum') || metaNumber('killnum'),
deaths: metaNumber('deathnum'),
fire: metaNumber('firenum'),
killCrew: metaNumber('killcrew'),
deathCrew: metaNumber('deathcrew'),
dex: [1, 2, 3, 4, 5].map((index) => metaNumber(`dex${index}`)),
},
};
});
return {
me: {
@@ -5,7 +5,13 @@ import { LogCategory, LogScope } from '@sammo-ts/infra';
import { authedProcedure } from '../../../trpc.js';
import { getMyGeneral } from '../../shared/general.js';
import { assertNationAccess, resolveNationPermission, zGeneralLogType, type GeneralLogType } from '../shared.js';
import {
assertNationAccess,
formatDateTime,
resolveNationPermission,
zGeneralLogType,
type GeneralLogType,
} from '../shared.js';
export const getGeneralLog = authedProcedure
.input(
@@ -75,6 +81,9 @@ export const getGeneralLog = authedProcedure
logs: logs.map((entry) => ({
id: entry.id,
text: entry.text,
year: entry.year,
month: entry.month,
createdAt: formatDateTime(entry.createdAt),
})),
};
});
@@ -30,7 +30,7 @@ export const getNationInfo = authedProcedure.query(async ({ ctx }) => {
nationId: me.nationId,
},
select: { id: true, year: true, month: true, text: true },
orderBy: { id: 'asc' },
orderBy: { id: 'desc' },
}),
]);
if (!nation) {
@@ -2,6 +2,7 @@ import { TRPCError } from '@trpc/server';
import { asRecord } from '@sammo-ts/common';
import { loadUnitSetDefinitionByName } from '../../../battleSim/unitSetLoader.js';
import { accessAuthedProcedure } from '../../../trpc.js';
import { getMyGeneral } from '../../shared/general.js';
import { assertNationAccess, resolveNationPermission } from '../shared.js';
@@ -41,7 +42,7 @@ export const getSecretGeneralList = accessAuthedProcedure.query(async ({ ctx })
});
}
const [cities, troops, generalRows] = await Promise.all([
const [cities, troops, generalRows, worldState] = await Promise.all([
ctx.db.city.findMany({ select: { id: true, name: true } }),
ctx.db.troop.findMany({
where: { nationId: me.nationId },
@@ -51,7 +52,14 @@ export const getSecretGeneralList = accessAuthedProcedure.query(async ({ ctx })
where: { nationId: me.nationId },
orderBy: [{ turnTime: 'asc' }, { id: 'asc' }],
}),
ctx.db.worldState.findFirst({ select: { config: true } }),
]);
const worldConfig = asRecord(worldState?.config);
const environment = asRecord(worldConfig.environment ?? worldConfig.map);
const unitSetName =
typeof environment.unitSet === 'string' && environment.unitSet.trim() ? environment.unitSet : ctx.profile.id;
const unitSet = await loadUnitSetDefinitionByName(unitSetName);
const crewTypeNames = new Map((unitSet.crewTypes ?? []).map((crewType) => [crewType.id, crewType.name]));
const generalIds = generalRows.map((general) => general.id);
const turns = generalIds.length
? await ctx.db.generalTurn.findMany({
@@ -92,6 +100,7 @@ export const getSecretGeneralList = accessAuthedProcedure.query(async ({ ctx })
defenceTrain,
defenceTrainText: defenceTrainText(defenceTrain),
crewTypeId: general.crewTypeId,
crewTypeName: crewTypeNames.get(general.crewTypeId) ?? '-',
crew: general.crew,
train: general.train,
atmos: general.atmos,
@@ -1,7 +1,14 @@
import { TRPCError } from '@trpc/server';
import { asRecord } from '@sammo-ts/common';
import { getGoldIncome, getOutcome, getRiceIncome, getWallIncome, getWarGoldIncome, type NationIncomeContext } from '@sammo-ts/logic';
import {
getGoldIncome,
getOutcome,
getRiceIncome,
getWallIncome,
getWarGoldIncome,
type NationIncomeContext,
} from '@sammo-ts/logic';
import { accessAuthedProcedure } from '../../../trpc.js';
import { getMyGeneral } from '../../shared/general.js';
@@ -171,13 +178,7 @@ export const getStratFinan = accessAuthedProcedure.query(async ({ ctx }) => {
const cityStatsByNation = new Map<number, { popSum: number; valueSum: number; maxSum: number }>();
for (const city of cityRows) {
const entry = cityStatsByNation.get(city.nationId) ?? { popSum: 0, valueSum: 0, maxSum: 0 };
const valueSum =
city.population +
city.agriculture +
city.commerce +
city.security +
city.wall +
city.defence;
const valueSum = city.population + city.agriculture + city.commerce + city.security + city.wall + city.defence;
const maxSum =
city.populationMax +
city.agricultureMax +
@@ -222,22 +223,24 @@ export const getStratFinan = accessAuthedProcedure.query(async ({ ctx }) => {
);
}
const nationsList = nationRows.map((nationItem) => {
const diplomacy =
nationItem.id === nation.id
? { state: 7, term: null }
: diplomacyMap.get(nationItem.id) ?? { state: 2, term: 0 };
return {
id: nationItem.id,
name: nationItem.name,
color: nationItem.color,
level: nationItem.level,
power: powerByNation.get(nationItem.id) ?? 0,
generalCount: generalCountMap.get(nationItem.id) ?? 0,
cityCount: cityCountMap.get(nationItem.id) ?? 0,
diplomacy,
};
});
const nationsList = nationRows
.filter((nationItem) => nationItem.id > 0)
.map((nationItem) => {
const diplomacy =
nationItem.id === nation.id
? { state: 7, term: null }
: (diplomacyMap.get(nationItem.id) ?? { state: 2, term: 0 });
return {
id: nationItem.id,
name: nationItem.name,
color: nationItem.color,
level: nationItem.level,
power: powerByNation.get(nationItem.id) ?? 0,
generalCount: generalCountMap.get(nationItem.id) ?? 0,
cityCount: cityCountMap.get(nationItem.id) ?? 0,
diplomacy,
};
});
const nationCities = cityRows.filter((city) => city.nationId === nation.id);
const nationGenerals = generalRows.filter((general) => general.nationId === nation.id);