61 lines
1.5 KiB
TypeScript
61 lines
1.5 KiB
TypeScript
export type TeamSearchTarget =
|
|
| "all"
|
|
| "team"
|
|
| "character"
|
|
| "weapon"
|
|
| "artifact";
|
|
|
|
export interface TeamSearchValues {
|
|
team: string[];
|
|
character: string[];
|
|
weapon: string[];
|
|
artifact: string[];
|
|
}
|
|
|
|
export interface DpsTeam {
|
|
rotationSeconds: string | number;
|
|
members: Array<{ damage: string | number }>;
|
|
}
|
|
|
|
export type DpsOrder = "best" | "worst" | null;
|
|
|
|
export function teamDps(team: DpsTeam): number {
|
|
const seconds = Number(team.rotationSeconds);
|
|
if (!(seconds > 0)) return 0;
|
|
return team.members.reduce((sum, member) => sum + Number(member.damage), 0) / seconds;
|
|
}
|
|
|
|
export function sortTeamsByDps<Team extends DpsTeam>(
|
|
teams: readonly Team[],
|
|
order: DpsOrder,
|
|
): Team[] {
|
|
if (!order) return [...teams];
|
|
|
|
return teams
|
|
.map((team, index) => ({ team, index }))
|
|
.sort((left, right) => {
|
|
const difference = order === "best"
|
|
? teamDps(right.team) - teamDps(left.team)
|
|
: teamDps(left.team) - teamDps(right.team);
|
|
return difference || left.index - right.index;
|
|
})
|
|
.map(({ team }) => team);
|
|
}
|
|
|
|
export function matchesTeamSearch(
|
|
values: TeamSearchValues,
|
|
query: string,
|
|
target: TeamSearchTarget,
|
|
): boolean {
|
|
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
if (!normalizedQuery) return true;
|
|
|
|
const candidates = target === "all"
|
|
? Object.values(values).flat()
|
|
: values[target];
|
|
|
|
return candidates.some((value) =>
|
|
value.toLocaleLowerCase().includes(normalizedQuery),
|
|
);
|
|
}
|