feat: eslint 적용 및 관련 코드 일괄 수정
This commit is contained in:
@@ -1,14 +1,5 @@
|
||||
import type {
|
||||
City,
|
||||
General,
|
||||
GeneralTriggerState,
|
||||
Nation,
|
||||
TriggerValue,
|
||||
} from '@sammo-ts/logic/domain/entities.js';
|
||||
import type {
|
||||
ScenarioDefinition,
|
||||
ScenarioGeneral,
|
||||
} from '@sammo-ts/logic/scenario/types.js';
|
||||
import type { City, General, GeneralTriggerState, Nation, TriggerValue } from '@sammo-ts/logic/domain/entities.js';
|
||||
import type { ScenarioDefinition, ScenarioGeneral } from '@sammo-ts/logic/scenario/types.js';
|
||||
import type {
|
||||
CitySeed,
|
||||
GeneralSeed,
|
||||
@@ -97,35 +88,17 @@ const addTriggerMeta = (
|
||||
meta[key] = value;
|
||||
};
|
||||
|
||||
const resolveMapDefaults = (
|
||||
map: MapDefinition,
|
||||
options?: ScenarioBootstrapOptions
|
||||
): MapDefaults => {
|
||||
const resolveMapDefaults = (map: MapDefinition, options?: ScenarioBootstrapOptions): MapDefaults => {
|
||||
const override = options?.mapDefaults ?? {};
|
||||
return {
|
||||
trust:
|
||||
override.trust ??
|
||||
map.defaults?.trust ??
|
||||
DEFAULT_CITY_TRUST,
|
||||
trade:
|
||||
override.trade ??
|
||||
map.defaults?.trade ??
|
||||
DEFAULT_CITY_TRADE,
|
||||
supplyState:
|
||||
override.supplyState ??
|
||||
map.defaults?.supplyState ??
|
||||
DEFAULT_CITY_SUPPLY_STATE,
|
||||
frontState:
|
||||
override.frontState ??
|
||||
map.defaults?.frontState ??
|
||||
DEFAULT_CITY_FRONT_STATE,
|
||||
trust: override.trust ?? map.defaults?.trust ?? DEFAULT_CITY_TRUST,
|
||||
trade: override.trade ?? map.defaults?.trade ?? DEFAULT_CITY_TRADE,
|
||||
supplyState: override.supplyState ?? map.defaults?.supplyState ?? DEFAULT_CITY_SUPPLY_STATE,
|
||||
frontState: override.frontState ?? map.defaults?.frontState ?? DEFAULT_CITY_FRONT_STATE,
|
||||
};
|
||||
};
|
||||
|
||||
const resolveNationType = (
|
||||
rawType: string,
|
||||
prefix: string
|
||||
): string => {
|
||||
const resolveNationType = (rawType: string, prefix: string): string => {
|
||||
const trimmed = rawType.trim();
|
||||
if (!trimmed) {
|
||||
return `${prefix}중립`;
|
||||
@@ -136,10 +109,7 @@ const resolveNationType = (
|
||||
return `${prefix}${trimmed}`;
|
||||
};
|
||||
|
||||
const resolveBirthYear = (
|
||||
birthYear: number,
|
||||
startYear: number | null
|
||||
): number => {
|
||||
const resolveBirthYear = (birthYear: number, startYear: number | null): number => {
|
||||
if (birthYear > 0) {
|
||||
return birthYear;
|
||||
}
|
||||
@@ -149,11 +119,7 @@ const resolveBirthYear = (
|
||||
return 0;
|
||||
};
|
||||
|
||||
const resolveDeathYear = (
|
||||
deathYear: number,
|
||||
birthYear: number,
|
||||
startYear: number | null
|
||||
): number => {
|
||||
const resolveDeathYear = (deathYear: number, birthYear: number, startYear: number | null): number => {
|
||||
if (deathYear > 0) {
|
||||
return deathYear;
|
||||
}
|
||||
@@ -253,24 +219,10 @@ const buildGeneralSeeds = (
|
||||
const id = nextId;
|
||||
nextId += 1;
|
||||
|
||||
const nationId = resolveNationId(
|
||||
row.nation,
|
||||
nationNameToId,
|
||||
warnings,
|
||||
row.name
|
||||
);
|
||||
const cityId = resolveCityId(
|
||||
row.city,
|
||||
cityByName,
|
||||
warnings,
|
||||
row.name
|
||||
);
|
||||
const nationId = resolveNationId(row.nation, nationNameToId, warnings, row.name);
|
||||
const cityId = resolveCityId(row.city, cityByName, warnings, row.name);
|
||||
const birthYear = resolveBirthYear(row.birthYear, scenario.startYear);
|
||||
const deathYear = resolveDeathYear(
|
||||
row.deathYear,
|
||||
birthYear,
|
||||
scenario.startYear
|
||||
);
|
||||
const deathYear = resolveDeathYear(row.deathYear, birthYear, scenario.startYear);
|
||||
const officerLevel = resolveOfficerLevel(row.officerLevel, nationId);
|
||||
const age = resolveAge(scenario.startYear, birthYear);
|
||||
const stats = {
|
||||
@@ -346,11 +298,7 @@ const buildGeneralSeeds = (
|
||||
addTriggerMeta(generalMeta, 'personality', row.personality ?? undefined);
|
||||
addTriggerMeta(generalMeta, 'special', row.special ?? undefined);
|
||||
addTriggerMeta(generalMeta, 'picture', row.picture ?? undefined);
|
||||
addTriggerMeta(
|
||||
generalMeta,
|
||||
'specialWar',
|
||||
row.specialWar ?? undefined
|
||||
);
|
||||
addTriggerMeta(generalMeta, 'specialWar', row.specialWar ?? undefined);
|
||||
addTriggerMeta(generalMeta, 'horse', row.horse ?? undefined);
|
||||
addTriggerMeta(generalMeta, 'weapon', row.weapon ?? undefined);
|
||||
addTriggerMeta(generalMeta, 'book', row.book ?? undefined);
|
||||
@@ -398,9 +346,7 @@ const buildGeneralSeeds = (
|
||||
};
|
||||
|
||||
// 시나리오, 맵, 유닛셋을 묶어 초기 월드 스냅샷과 시드 데이터를 만든다.
|
||||
export const buildScenarioBootstrap = (
|
||||
input: ScenarioBootstrapInput
|
||||
): ScenarioBootstrapResult => {
|
||||
export const buildScenarioBootstrap = (input: ScenarioBootstrapInput): ScenarioBootstrapResult => {
|
||||
const { scenario, map, unitSet, options } = input;
|
||||
const warnings: ScenarioBootstrapWarning[] = [];
|
||||
|
||||
@@ -411,11 +357,7 @@ export const buildScenarioBootstrap = (
|
||||
message: `Scenario mapName ${environment.mapName} does not match map definition ${map.id}.`,
|
||||
});
|
||||
}
|
||||
if (
|
||||
unitSet &&
|
||||
unitSet.id !== environment.unitSet &&
|
||||
unitSet.name !== environment.unitSet
|
||||
) {
|
||||
if (unitSet && unitSet.id !== environment.unitSet && unitSet.name !== environment.unitSet) {
|
||||
warnings.push({
|
||||
code: 'unit_set_mismatch',
|
||||
message: `Scenario unitSet ${environment.unitSet} does not match unit set ${unitSet.id}.`,
|
||||
@@ -467,15 +409,13 @@ export const buildScenarioBootstrap = (
|
||||
}
|
||||
|
||||
const scenarioMeta = createScenarioMeta(scenario);
|
||||
const typePrefix =
|
||||
options?.nationTypePrefix ?? `${environment.mapName}_`;
|
||||
const typePrefix = options?.nationTypePrefix ?? `${environment.mapName}_`;
|
||||
|
||||
const seedNations: NationSeed[] = [];
|
||||
const domainNations: Nation[] = [];
|
||||
|
||||
const includeNeutralNation = options?.includeNeutralNation ?? true;
|
||||
const includeNeutralNationInSeed =
|
||||
options?.includeNeutralNationInSeed ?? false;
|
||||
const includeNeutralNationInSeed = options?.includeNeutralNationInSeed ?? false;
|
||||
if (includeNeutralNation) {
|
||||
const neutralNation: Nation = {
|
||||
id: 0,
|
||||
@@ -550,10 +490,7 @@ export const buildScenarioBootstrap = (
|
||||
}
|
||||
|
||||
const mapDefaults = resolveMapDefaults(map, options);
|
||||
const defaultCrewTypeId =
|
||||
unitSet?.defaultCrewTypeId ??
|
||||
options?.defaultCrewTypeId ??
|
||||
DEFAULT_CREWTYPE_ID;
|
||||
const defaultCrewTypeId = unitSet?.defaultCrewTypeId ?? options?.defaultCrewTypeId ?? DEFAULT_CREWTYPE_ID;
|
||||
const seedCities: CitySeed[] = [];
|
||||
const domainCities: City[] = [];
|
||||
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
import type { City, General, Nation, Troop } from '@sammo-ts/logic/domain/entities.js';
|
||||
import type { ScenarioConfig, ScenarioDiplomacy } from '@sammo-ts/logic/scenario/types.js';
|
||||
import type { ScenarioConfigSource, WorldStateSnapshotSource } from '@sammo-ts/logic/ports/worldSnapshot.js';
|
||||
import type {
|
||||
MapDefinition,
|
||||
ScenarioMeta,
|
||||
UnitSetDefinition,
|
||||
WorldSnapshot,
|
||||
} from './types.js';
|
||||
import type { MapDefinition, ScenarioMeta, UnitSetDefinition, WorldSnapshot } from './types.js';
|
||||
|
||||
export interface WorldSnapshotLoadInput<
|
||||
GeneralType extends General = General,
|
||||
CityType extends City = City,
|
||||
NationType extends Nation = Nation,
|
||||
TroopType extends Troop = Troop
|
||||
TroopType extends Troop = Troop,
|
||||
> {
|
||||
worldSource: WorldStateSnapshotSource<
|
||||
GeneralType,
|
||||
CityType,
|
||||
NationType,
|
||||
TroopType
|
||||
>;
|
||||
worldSource: WorldStateSnapshotSource<GeneralType, CityType, NationType, TroopType>;
|
||||
scenarioConfig?: ScenarioConfig;
|
||||
scenarioMeta?: ScenarioMeta;
|
||||
scenarioSource?: ScenarioConfigSource;
|
||||
@@ -35,29 +25,20 @@ export const loadWorldSnapshot = async <
|
||||
GeneralType extends General,
|
||||
CityType extends City,
|
||||
NationType extends Nation,
|
||||
TroopType extends Troop
|
||||
TroopType extends Troop,
|
||||
>(
|
||||
input: WorldSnapshotLoadInput<
|
||||
GeneralType,
|
||||
CityType,
|
||||
NationType,
|
||||
TroopType
|
||||
>
|
||||
input: WorldSnapshotLoadInput<GeneralType, CityType, NationType, TroopType>
|
||||
): Promise<WorldSnapshot> => {
|
||||
const { worldSource, scenarioSource } = input;
|
||||
|
||||
const scenarioConfig =
|
||||
input.scenarioConfig ??
|
||||
(scenarioSource ? await scenarioSource.loadScenarioConfig() : undefined);
|
||||
input.scenarioConfig ?? (scenarioSource ? await scenarioSource.loadScenarioConfig() : undefined);
|
||||
if (!scenarioConfig) {
|
||||
throw new Error('Scenario config is required to load world snapshot.');
|
||||
}
|
||||
|
||||
const scenarioMeta =
|
||||
input.scenarioMeta ??
|
||||
(scenarioSource?.loadScenarioMeta
|
||||
? await scenarioSource.loadScenarioMeta()
|
||||
: undefined);
|
||||
input.scenarioMeta ?? (scenarioSource?.loadScenarioMeta ? await scenarioSource.loadScenarioMeta() : undefined);
|
||||
|
||||
const [generals, cities, nations, troops] = await Promise.all([
|
||||
worldSource.listGenerals(),
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
import type {
|
||||
City,
|
||||
General,
|
||||
Nation,
|
||||
StatBlock,
|
||||
Troop,
|
||||
} from '@sammo-ts/logic/domain/entities.js';
|
||||
import type {
|
||||
ScenarioConfig,
|
||||
ScenarioDiplomacy,
|
||||
} from '@sammo-ts/logic/scenario/types.js';
|
||||
import type { City, General, Nation, StatBlock, Troop } from '@sammo-ts/logic/domain/entities.js';
|
||||
import type { ScenarioConfig, ScenarioDiplomacy } from '@sammo-ts/logic/scenario/types.js';
|
||||
|
||||
export interface ScenarioMeta {
|
||||
title: string;
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import type { City, General, Nation } from '@sammo-ts/logic/domain/entities.js';
|
||||
import type {
|
||||
CrewTypeDefinition,
|
||||
CrewTypeRequirement,
|
||||
MapDefinition,
|
||||
UnitSetDefinition,
|
||||
} from './types.js';
|
||||
import type { CrewTypeDefinition, CrewTypeRequirement, MapDefinition, UnitSetDefinition } from './types.js';
|
||||
|
||||
const DEFAULT_REGION_MAP: Record<string, number> = {
|
||||
하북: 1,
|
||||
@@ -22,19 +17,15 @@ const DEFAULT_MAX_TECH_LEVEL = 12;
|
||||
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
||||
value !== null && typeof value === 'object' && !Array.isArray(value);
|
||||
|
||||
const asRecord = (value: unknown): Record<string, unknown> =>
|
||||
isRecord(value) ? value : {};
|
||||
const asRecord = (value: unknown): Record<string, unknown> => (isRecord(value) ? value : {});
|
||||
|
||||
const asNumber = (value: unknown, fallback: number): number =>
|
||||
typeof value === 'number' && Number.isFinite(value) ? value : fallback;
|
||||
|
||||
const asString = (value: unknown, fallback: string): string =>
|
||||
typeof value === 'string' ? value : fallback;
|
||||
const asString = (value: unknown, fallback: string): string => (typeof value === 'string' ? value : fallback);
|
||||
|
||||
const asStringArray = (value: unknown): string[] =>
|
||||
Array.isArray(value)
|
||||
? value.filter((item): item is string => typeof item === 'string')
|
||||
: [];
|
||||
Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : [];
|
||||
|
||||
const asNullableStringArray = (value: unknown): string[] | null => {
|
||||
if (value === null || value === undefined) {
|
||||
@@ -88,11 +79,7 @@ const parseRequirement = (value: unknown): CrewTypeRequirement | null => {
|
||||
type,
|
||||
key: asString(value.key, ''),
|
||||
op: asString(value.op, '=='),
|
||||
value:
|
||||
typeof value.value === 'number' ||
|
||||
typeof value.value === 'string'
|
||||
? value.value
|
||||
: 0,
|
||||
value: typeof value.value === 'number' || typeof value.value === 'string' ? value.value : 0,
|
||||
};
|
||||
case 'ReqMinRelYear':
|
||||
return { type, year: asNumber(value.year, 0) };
|
||||
@@ -114,9 +101,7 @@ const parseCrewType = (value: unknown): CrewTypeDefinition | null => {
|
||||
return null;
|
||||
}
|
||||
const requirements = Array.isArray(value.requirements)
|
||||
? value.requirements
|
||||
.map(parseRequirement)
|
||||
.filter((entry): entry is CrewTypeRequirement => entry !== null)
|
||||
? value.requirements.map(parseRequirement).filter((entry): entry is CrewTypeRequirement => entry !== null)
|
||||
: [];
|
||||
|
||||
return {
|
||||
@@ -149,20 +134,15 @@ export const parseUnitSetDefinition = (value: unknown): UnitSetDefinition => {
|
||||
? data.defaultCrewTypeId
|
||||
: null;
|
||||
const armTypes = isRecord(data.armTypes)
|
||||
? Object.entries(data.armTypes).reduce<Record<string, string>>(
|
||||
(acc, [key, entry]) => {
|
||||
if (typeof entry === 'string') {
|
||||
acc[key] = entry;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
)
|
||||
? Object.entries(data.armTypes).reduce<Record<string, string>>((acc, [key, entry]) => {
|
||||
if (typeof entry === 'string') {
|
||||
acc[key] = entry;
|
||||
}
|
||||
return acc;
|
||||
}, {})
|
||||
: undefined;
|
||||
const crewTypes = Array.isArray(data.crewTypes)
|
||||
? data.crewTypes
|
||||
.map(parseCrewType)
|
||||
.filter((entry): entry is CrewTypeDefinition => entry !== null)
|
||||
? data.crewTypes.map(parseCrewType).filter((entry): entry is CrewTypeDefinition => entry !== null)
|
||||
: [];
|
||||
|
||||
const result: UnitSetDefinition = {
|
||||
@@ -182,9 +162,7 @@ export const parseUnitSetDefinition = (value: unknown): UnitSetDefinition => {
|
||||
return result;
|
||||
};
|
||||
|
||||
export const buildCrewTypeIndex = (
|
||||
unitSet: UnitSetDefinition | null | undefined
|
||||
): Map<number, CrewTypeDefinition> => {
|
||||
export const buildCrewTypeIndex = (unitSet: UnitSetDefinition | null | undefined): Map<number, CrewTypeDefinition> => {
|
||||
const index = new Map<number, CrewTypeDefinition>();
|
||||
for (const crewType of unitSet?.crewTypes ?? []) {
|
||||
index.set(crewType.id, crewType);
|
||||
@@ -202,10 +180,7 @@ export const findCrewTypeById = (
|
||||
return unitSet.crewTypes.find((crewType) => crewType.id === crewTypeId) ?? null;
|
||||
};
|
||||
|
||||
export const getTechLevel = (
|
||||
tech: number,
|
||||
maxLevel = DEFAULT_MAX_TECH_LEVEL
|
||||
): number => {
|
||||
export const getTechLevel = (tech: number, maxLevel = DEFAULT_MAX_TECH_LEVEL): number => {
|
||||
if (!Number.isFinite(tech)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -263,7 +238,9 @@ const resolveRegionMap = (map: MapDefinition): Record<string, number> => {
|
||||
return Object.keys(extracted).length > 0 ? extracted : DEFAULT_REGION_MAP;
|
||||
};
|
||||
|
||||
const buildCityIndex = (map: MapDefinition): {
|
||||
const buildCityIndex = (
|
||||
map: MapDefinition
|
||||
): {
|
||||
nameToId: Map<string, number>;
|
||||
regionById: Map<number, number>;
|
||||
} => {
|
||||
@@ -276,23 +253,10 @@ const buildCityIndex = (map: MapDefinition): {
|
||||
return { nameToId, regionById };
|
||||
};
|
||||
|
||||
const compareAuxValue = (
|
||||
actual: unknown,
|
||||
op: string,
|
||||
expected: number | string
|
||||
): boolean => {
|
||||
const actualNum =
|
||||
typeof actual === 'number'
|
||||
? actual
|
||||
: typeof actual === 'string'
|
||||
? Number(actual)
|
||||
: Number.NaN;
|
||||
const compareAuxValue = (actual: unknown, op: string, expected: number | string): boolean => {
|
||||
const actualNum = typeof actual === 'number' ? actual : typeof actual === 'string' ? Number(actual) : Number.NaN;
|
||||
const expectedNum =
|
||||
typeof expected === 'number'
|
||||
? expected
|
||||
: typeof expected === 'string'
|
||||
? Number(expected)
|
||||
: Number.NaN;
|
||||
typeof expected === 'number' ? expected : typeof expected === 'string' ? Number(expected) : Number.NaN;
|
||||
|
||||
if (!Number.isNaN(actualNum) && !Number.isNaN(expectedNum)) {
|
||||
switch (op) {
|
||||
@@ -314,9 +278,7 @@ const compareAuxValue = (
|
||||
}
|
||||
|
||||
if (op === '!=' || op === '==') {
|
||||
return op === '!='
|
||||
? String(actual ?? '') !== String(expected)
|
||||
: String(actual ?? '') === String(expected);
|
||||
return op === '!=' ? String(actual ?? '') !== String(expected) : String(actual ?? '') === String(expected);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -333,10 +295,7 @@ export const isCrewTypeAvailable = (
|
||||
}
|
||||
|
||||
const nationId = context.nation?.id ?? context.general.nationId;
|
||||
const ownedCities =
|
||||
nationId !== undefined
|
||||
? context.cities.filter((city) => city.nationId === nationId)
|
||||
: [];
|
||||
const ownedCities = nationId !== undefined ? context.cities.filter((city) => city.nationId === nationId) : [];
|
||||
const ownedCityMap = new Map<number, City>();
|
||||
for (const city of ownedCities) {
|
||||
ownedCityMap.set(city.id, city);
|
||||
@@ -359,19 +318,12 @@ export const isCrewTypeAvailable = (
|
||||
for (const requirement of crewType.requirements) {
|
||||
switch (requirement.type) {
|
||||
case 'ReqTech':
|
||||
if (
|
||||
tech <
|
||||
(requirement as Extract<CrewTypeRequirement, { type: 'ReqTech' }>).tech
|
||||
) {
|
||||
if (tech < (requirement as Extract<CrewTypeRequirement, { type: 'ReqTech' }>).tech) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'ReqRegions': {
|
||||
const req =
|
||||
requirement as Extract<
|
||||
CrewTypeRequirement,
|
||||
{ type: 'ReqRegions' }
|
||||
>;
|
||||
const req = requirement as Extract<CrewTypeRequirement, { type: 'ReqRegions' }>;
|
||||
const resolved = req.regions
|
||||
.map((name: string) => regionMap[name])
|
||||
.filter((id): id is number => typeof id === 'number');
|
||||
@@ -381,11 +333,7 @@ export const isCrewTypeAvailable = (
|
||||
break;
|
||||
}
|
||||
case 'ReqCities': {
|
||||
const req =
|
||||
requirement as Extract<
|
||||
CrewTypeRequirement,
|
||||
{ type: 'ReqCities' }
|
||||
>;
|
||||
const req = requirement as Extract<CrewTypeRequirement, { type: 'ReqCities' }>;
|
||||
const resolved = req.cities
|
||||
.map((name: string) => nameToId.get(name))
|
||||
.filter((id): id is number => typeof id === 'number');
|
||||
@@ -395,11 +343,7 @@ export const isCrewTypeAvailable = (
|
||||
break;
|
||||
}
|
||||
case 'ReqCitiesWithCityLevel': {
|
||||
const req =
|
||||
requirement as Extract<
|
||||
CrewTypeRequirement,
|
||||
{ type: 'ReqCitiesWithCityLevel' }
|
||||
>;
|
||||
const req = requirement as Extract<CrewTypeRequirement, { type: 'ReqCitiesWithCityLevel' }>;
|
||||
const resolved = req.cities
|
||||
.map((name: string) => nameToId.get(name))
|
||||
.filter((id): id is number => typeof id === 'number');
|
||||
@@ -414,25 +358,15 @@ export const isCrewTypeAvailable = (
|
||||
break;
|
||||
}
|
||||
case 'ReqHighLevelCities': {
|
||||
const req =
|
||||
requirement as Extract<
|
||||
CrewTypeRequirement,
|
||||
{ type: 'ReqHighLevelCities' }
|
||||
>;
|
||||
const count = ownedCities.filter(
|
||||
(city) => city.level >= req.level
|
||||
).length;
|
||||
const req = requirement as Extract<CrewTypeRequirement, { type: 'ReqHighLevelCities' }>;
|
||||
const count = ownedCities.filter((city) => city.level >= req.level).length;
|
||||
if (count < req.count) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'ReqNationAux': {
|
||||
const req =
|
||||
requirement as Extract<
|
||||
CrewTypeRequirement,
|
||||
{ type: 'ReqNationAux' }
|
||||
>;
|
||||
const req = requirement as Extract<CrewTypeRequirement, { type: 'ReqNationAux' }>;
|
||||
const value = aux[req.key];
|
||||
if (!compareAuxValue(value, req.op, req.value)) {
|
||||
return false;
|
||||
@@ -440,10 +374,7 @@ export const isCrewTypeAvailable = (
|
||||
break;
|
||||
}
|
||||
case 'ReqMinRelYear':
|
||||
if (
|
||||
relYear <
|
||||
(requirement as Extract<CrewTypeRequirement, { type: 'ReqMinRelYear' }>).year
|
||||
) {
|
||||
if (relYear < (requirement as Extract<CrewTypeRequirement, { type: 'ReqMinRelYear' }>).year) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user