장수 목록 기본 정렬 순서를 통일
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
export type GeneralOrderIdentity = {
|
||||
id: number;
|
||||
name: string;
|
||||
npcState: number;
|
||||
};
|
||||
|
||||
const koreanNameCollator = new Intl.Collator('ko-KR', { numeric: true, sensitivity: 'base' });
|
||||
|
||||
/**
|
||||
* Ref의 npc 값은 0 유저장, 1 빙의장, 2 N장, 3 M장, 4 의병장,
|
||||
* 5 부대장 순으로 장수 종류 자체의 표시 우선순위를 표현한다.
|
||||
*/
|
||||
export const compareGeneralTypeThenName = <T extends GeneralOrderIdentity>(left: T, right: T): number =>
|
||||
left.npcState - right.npcState || koreanNameCollator.compare(left.name, right.name) || left.id - right.id;
|
||||
|
||||
export const sortGeneralsByTypeThenName = <T extends GeneralOrderIdentity>(generals: readonly T[]): T[] =>
|
||||
[...generals].sort(compareGeneralTypeThenName);
|
||||
@@ -7,6 +7,7 @@ import BattleGeneralCard from '../components/battle/BattleGeneralCard.vue';
|
||||
import { useGameFeedback } from '../composables/useGameFeedback';
|
||||
import { trpc } from '../utils/trpc';
|
||||
import { getNpcColor } from '../utils/npcColor';
|
||||
import { compareGeneralTypeThenName } from '../utils/generalOrder';
|
||||
import type { BattleSimOptions, GeneralDraft, InheritBuff } from '../utils/battleSimulatorTypes';
|
||||
import { BattleSimulatorWorkerClient } from '../utils/battleSimulatorWorkerClient';
|
||||
import { formatSeoulDateTime } from '../utils/legacyDateTime';
|
||||
@@ -953,12 +954,7 @@ const generalGroups = computed(() => {
|
||||
.map((nationId) => {
|
||||
const nation = nationMap.get(nationId) ?? { id: nationId, name: '재야', color: '#000000' };
|
||||
const generals = [...(generalList.value?.generalsByNation[nationId] ?? [])];
|
||||
generals.sort((lhs, rhs) => {
|
||||
if (lhs.npcState !== rhs.npcState) {
|
||||
return lhs.npcState - rhs.npcState;
|
||||
}
|
||||
return lhs.name.localeCompare(rhs.name);
|
||||
});
|
||||
generals.sort(compareGeneralTypeThenName);
|
||||
return { nation, generals };
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import PanelCard from '../components/ui/PanelCard.vue';
|
||||
import SkeletonLines from '../components/ui/SkeletonLines.vue';
|
||||
import MapViewer from '../components/main/MapViewer.vue';
|
||||
import { trpc } from '../utils/trpc';
|
||||
import { sortGeneralsByTypeThenName } from '../utils/generalOrder';
|
||||
import { useSessionStore } from '../stores/session';
|
||||
import { cityLevelMap, formatOfficerLevelText, regionMap } from '../utils/nationFormat';
|
||||
import { getNpcColor } from '../utils/npcColor';
|
||||
@@ -247,14 +248,14 @@ const npcGeneralRows = computed<NpcGeneralRow[]>(() => {
|
||||
const visibleNpcGeneralRows = computed(() => npcGeneralRows.value.slice(0, npcGeneralListVisibleCount.value));
|
||||
const filteredPublicGenerals = computed(() => {
|
||||
const keyword = publicGeneralFilter.value.trim().toLocaleLowerCase('ko-KR');
|
||||
if (!keyword) {
|
||||
return publicGenerals.value;
|
||||
}
|
||||
return publicGenerals.value.filter(
|
||||
(general) =>
|
||||
general.name.toLocaleLowerCase('ko-KR').includes(keyword) ||
|
||||
general.nationName.toLocaleLowerCase('ko-KR').includes(keyword)
|
||||
);
|
||||
const filtered = keyword
|
||||
? publicGenerals.value.filter(
|
||||
(general) =>
|
||||
general.name.toLocaleLowerCase('ko-KR').includes(keyword) ||
|
||||
general.nationName.toLocaleLowerCase('ko-KR').includes(keyword)
|
||||
)
|
||||
: publicGenerals.value;
|
||||
return sortGeneralsByTypeThenName(filtered);
|
||||
});
|
||||
const npcValidColor = computed(() => {
|
||||
const remaining = npcValidUntilMs.value - nowMs.value;
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { CommandTable } from '../components/command/types';
|
||||
import LegacySortControls from '../components/ui/LegacySortControls.vue';
|
||||
import { useGameFeedback } from '../composables/useGameFeedback';
|
||||
import { getNpcColor } from '../utils/npcColor';
|
||||
import { sortGeneralsByTypeThenName } from '../utils/generalOrder';
|
||||
import { legacyNationTextColor } from '../utils/legacyNationColor';
|
||||
import { cityLevelMap, regionMap } from '../utils/nationFormat';
|
||||
import { trpc } from '../utils/trpc';
|
||||
@@ -62,9 +63,10 @@ const sortOptions = [
|
||||
const officerLabels: Record<OfficerLevel, string> = { 4: '태수', 3: '군사', 2: '종사' };
|
||||
const appointmentDescription = (city: City, general: SecretGeneral, level: OfficerLevel): string =>
|
||||
`${JosaUtil.put(general.name, '을')} ${city.name} ${JosaUtil.put(officerLabels[level], '으로')} 임명`;
|
||||
const generalsForCity = (cityId: number) => data.value?.generals.filter((general) => general.cityId === cityId) ?? [];
|
||||
const generalsForCity = (cityId: number) =>
|
||||
sortGeneralsByTypeThenName(data.value?.generals.filter((general) => general.cityId === cityId) ?? []);
|
||||
const secretGeneralsForCity = (cityId: number) =>
|
||||
secretData.value?.generals.filter((general) => general.cityId === cityId) ?? [];
|
||||
sortGeneralsByTypeThenName(secretData.value?.generals.filter((general) => general.cityId === cityId) ?? []);
|
||||
const displayGeneralName = (general: Result['generals'][number]) =>
|
||||
general.npcState > 0 && !/^[ⓜⓝ]/u.test(general.name) ? `ⓝ${general.name}` : general.name;
|
||||
const displaySecretGeneralName = (general: SecretGeneral) =>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { formatReservedCommandBrief } from '../components/command/reservedComman
|
||||
import type { CommandTable } from '../components/command/types';
|
||||
import { formatOfficerLevelText } from '../utils/nationFormat';
|
||||
import { getNpcColor } from '../utils/npcColor';
|
||||
import { compareGeneralTypeThenName } from '../utils/generalOrder';
|
||||
import { resolveGeneralIconUrl } from '../utils/generalIcon';
|
||||
import {
|
||||
DISPLAY_SETTINGS_KEY,
|
||||
@@ -587,7 +588,7 @@ const generals = computed(() => {
|
||||
const compared = compareGridValues(sortValue(left, sort.colId), sortValue(right, sort.colId));
|
||||
if (compared) return sort.sort === 'asc' ? compared : -compared;
|
||||
}
|
||||
return left.id - right.id;
|
||||
return compareGeneralTypeThenName(left, right);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
|
||||
import GeneralDirectoryTable from '../components/directory/GeneralDirectoryTable.vue';
|
||||
import type { GeneralDirectoryGeneral } from '../types/directory';
|
||||
import { sortGeneralsByTypeThenName } from '../utils/generalOrder';
|
||||
import { formatNationLevelText, formatOfficerLevelText } from '../utils/nationFormat';
|
||||
import { getNpcColor } from '../utils/npcColor';
|
||||
import { legacyNationTextColor } from '../utils/legacyNationColor';
|
||||
@@ -46,6 +47,7 @@ const officerName = (nation: Nation, officerLevel: number) =>
|
||||
nation.officers.find((officer) => officer.officerLevel === officerLevel)?.general;
|
||||
const displayGeneralName = (general: { name: string; npcState: number }) =>
|
||||
general.npcState > 0 && !/^[ⓜⓝ㉥]/u.test(general.name) ? `ⓝ${general.name}` : general.name;
|
||||
const orderedNationGenerals = (nation: Nation) => sortGeneralsByTypeThenName(nation.generals);
|
||||
const displayAnalyzedGeneralColor = (general: { npcState: number; accessGrade: 'normal' | 'medium' | 'high' }) => {
|
||||
if (general.accessGrade === 'high') return 'yellow';
|
||||
if (general.accessGrade === 'medium') return 'lightgreen';
|
||||
@@ -344,7 +346,7 @@ onBeforeUnmount(() => {
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
장수 일람 :
|
||||
<template v-for="general in nation.generals" :key="general.id">
|
||||
<template v-for="general in orderedNationGenerals(nation)" :key="general.id">
|
||||
<button
|
||||
type="button"
|
||||
class="general-preview-trigger"
|
||||
|
||||
@@ -6,6 +6,7 @@ import SkeletonLines from '../components/ui/SkeletonLines.vue';
|
||||
import MapViewer from '../components/main/MapViewer.vue';
|
||||
import RecentLogList from '../components/main/RecentLogList.vue';
|
||||
import { trpc } from '../utils/trpc';
|
||||
import { sortGeneralsByTypeThenName } from '../utils/generalOrder';
|
||||
import { useSessionStore } from '../stores/session';
|
||||
|
||||
type MapData = Awaited<ReturnType<typeof trpc.public.getCachedMap.query>>;
|
||||
@@ -30,15 +31,12 @@ const generalFilter = ref('');
|
||||
|
||||
const filteredGenerals = computed(() => {
|
||||
const keyword = generalFilter.value.trim().toLowerCase();
|
||||
if (!keyword) {
|
||||
return generalList.value;
|
||||
}
|
||||
return generalList.value.filter((general) => {
|
||||
return (
|
||||
general.name.toLowerCase().includes(keyword) ||
|
||||
general.nationName.toLowerCase().includes(keyword)
|
||||
);
|
||||
});
|
||||
const filtered = keyword
|
||||
? generalList.value.filter((general) => {
|
||||
return general.name.toLowerCase().includes(keyword) || general.nationName.toLowerCase().includes(keyword);
|
||||
})
|
||||
: generalList.value;
|
||||
return sortGeneralsByTypeThenName(filtered);
|
||||
});
|
||||
|
||||
const resolveErrorMessage = (value: unknown): string => {
|
||||
|
||||
Reference in New Issue
Block a user