Prepare reserve drill assignment state

This commit is contained in:
2026-07-09 13:36:59 +09:00
parent 6351c7b285
commit 053536fd20
2 changed files with 86 additions and 2 deletions

View File

@@ -246,6 +246,8 @@ export type CampaignReserveTrainingFocusDefinition = {
bondExpGained: number;
};
export type CampaignReserveTrainingAssignments = Partial<Record<string, CampaignReserveTrainingFocusId>>;
export const defaultCampaignReserveTrainingFocusId: CampaignReserveTrainingFocusId = 'balanced';
const defaultEquipmentBySlot: Record<EquipmentSlot, string> = {
@@ -274,6 +276,7 @@ const maxCampaignBattleObjectiveEntries = 24;
const maxCampaignBattleUnitEntries = 96;
const maxCampaignBattleBondEntries = 96;
const maxCampaignReserveTrainingEntries = 96;
const maxCampaignReserveTrainingAssignmentUnits = 96;
const maxCampaignSortieAssignmentUnits = 96;
const maxCampaignDisplayTextLength = 180;
const maxCampaignNumericValue = 999999;
@@ -335,6 +338,7 @@ export type CampaignState = {
sortieFormationAssignments: SortieFormationAssignments;
sortieItemAssignments: CampaignSortieItemAssignments;
reserveTrainingFocus: CampaignReserveTrainingFocusId;
reserveTrainingAssignments: CampaignReserveTrainingAssignments;
completedCampDialogues: string[];
completedCampVisits: string[];
battleHistory: Record<string, CampaignBattleSettlement>;
@@ -535,6 +539,7 @@ export function createInitialCampaignState(): CampaignState {
sortieFormationAssignments: {},
sortieItemAssignments: {},
reserveTrainingFocus: defaultCampaignReserveTrainingFocusId,
reserveTrainingAssignments: {},
completedCampDialogues: [],
completedCampVisits: [],
battleHistory: {}
@@ -623,6 +628,27 @@ export function setCampaignReserveTrainingFocus(focusId: CampaignReserveTraining
return cloneCampaignState(state);
}
export function normalizeCampaignReserveTrainingAssignments(
assignments?: Record<string, unknown>,
allowedUnitIds?: Set<string>
): CampaignReserveTrainingAssignments {
return Object.entries(assignments ?? {}).reduce<CampaignReserveTrainingAssignments>((next, [unitId, focusId]) => {
const normalizedUnitId = normalizeKeyString(unitId);
if (
!normalizedUnitId ||
next[normalizedUnitId] ||
(allowedUnitIds && !allowedUnitIds.has(normalizedUnitId)) ||
(!allowedUnitIds && Object.keys(next).length >= maxCampaignReserveTrainingAssignmentUnits) ||
!isReserveTrainingFocusId(focusId)
) {
return next;
}
next[normalizedUnitId] = focusId;
return next;
}, {});
}
export function setFirstBattleReport(report: FirstBattleReport) {
const state = ensureCampaignState();
const reportClone = cloneReport(report);
@@ -867,6 +893,7 @@ function normalizeCampaignState(state: Partial<CampaignState>): CampaignState {
normalized.sortieFormationAssignments = normalizeSortieFormationAssignments(recordOrEmpty(normalized.sortieFormationAssignments), sortieUnitFilter);
normalized.sortieItemAssignments = normalizeCampaignSortieItemAssignments(recordOrEmpty(normalized.sortieItemAssignments), sortieUnitFilter);
normalized.reserveTrainingFocus = normalizeReserveTrainingFocusId(normalized.reserveTrainingFocus);
normalized.reserveTrainingAssignments = normalizeCampaignReserveTrainingAssignments(recordOrEmpty(normalized.reserveTrainingAssignments), sortieUnitFilter);
normalized.battleHistory = normalizeBattleHistory(normalized.battleHistory);
if (sortieUnitFilter) {
normalized.battleHistory = filterBattleHistoryRosterReferences(
@@ -1256,11 +1283,15 @@ export function normalizeCampaignSortieItemAssignments(assignments?: Record<stri
}
function normalizeReserveTrainingFocusId(focusId?: string): CampaignReserveTrainingFocusId {
return campaignReserveTrainingFocusDefinitions.some((focus) => focus.id === focusId)
return isReserveTrainingFocusId(focusId)
? focusId as CampaignReserveTrainingFocusId
: defaultCampaignReserveTrainingFocusId;
}
function isReserveTrainingFocusId(value: unknown): value is CampaignReserveTrainingFocusId {
return typeof value === 'string' && campaignReserveTrainingFocusDefinitions.some((focus) => focus.id === value);
}
export function isCampaignStep(value: unknown): value is CampaignStep {
return typeof value === 'string' && campaignStepIds.has(value as CampaignStep);
}