This commit is contained in:
2025-04-23 20:24:12 +07:00
parent f933b5aad5
commit ef52d632bd
63 changed files with 3911 additions and 138 deletions
+28
View File
@@ -0,0 +1,28 @@
import useBattleDataStore from "@/stores/battleDataStore";
import { useMemo } from "react";
export function useCalcTotalDmgAvatar(avatarId: number) {
const { turnHistory } = useBattleDataStore.getState();
return useMemo(() => {
return turnHistory
.filter(t => t.avatarId === avatarId)
.reduce((sum, turn) => sum + turn.totalDamage, 0);
}, [avatarId, turnHistory]);
}
export function useCalcTotalTurnAvatar(avatarId: number) {
const { turnHistory } = useBattleDataStore.getState();
return useMemo(() => {
const uniqueActionValues = new Set<number>();
turnHistory.forEach(turn => {
if (turn.avatarId === avatarId) {
uniqueActionValues.add(turn.actionValue);
}
});
return uniqueActionValues.size;
}, [avatarId, turnHistory]);
}
+4
View File
@@ -0,0 +1,4 @@
import { useContext } from "react";
import { ThemeContext } from "@/components/themeController";
export const useChangeTheme = () => useContext(ThemeContext);
+31
View File
@@ -0,0 +1,31 @@
import useBattleDataStore from "@/stores/battleDataStore";
import { useMemo } from "react";
export function useDamageLineForOne(avatarId: number, mode: 0 | 1 = 0) {
const { turnHistory } = useBattleDataStore.getState();
return useMemo(() => {
const map = new Map<number, number>();
for (const turn of turnHistory) {
if (turn.avatarId !== avatarId) continue;
const prev = map.get(turn.actionValue) || 0;
map.set(turn.actionValue, prev + turn.totalDamage);
}
const points = Array.from(map.entries())
.map(([x, y]) => ({ x, y }))
.sort((a, b) => a.x - b.x);
if (mode === 1) {
let cumulative = 0;
return points.map(p => {
cumulative += p.y;
return { x: p.x, y: Number(cumulative.toFixed(2)) };
});
}
return points.map(p => ({ x: p.x, y: Number(p.y.toFixed(2)) }));
}, [avatarId, turnHistory, mode]);
}
+43
View File
@@ -0,0 +1,43 @@
import useBattleDataStore from "@/stores/battleDataStore";
import { useMemo } from "react";
export function useDamageLinesForAll(mode: 0 | 1 = 0) {
const { turnHistory } = useBattleDataStore.getState();
return useMemo(() => {
const avatarMap = new Map<number, Map<number, number>>();
for (const turn of turnHistory) {
if (!avatarMap.has(turn.avatarId)) {
avatarMap.set(turn.avatarId, new Map());
}
const charMap = avatarMap.get(turn.avatarId)!;
const prev = charMap.get(turn.actionValue) || 0;
charMap.set(turn.actionValue, prev + turn.totalDamage);
}
const result: Record<number, { x: number; y: number }[]> = {};
for (const [avatarId, damageMap] of avatarMap.entries()) {
const points = Array.from(damageMap.entries())
.map(([x, y]) => ({ x, y }))
.sort((a, b) => a.x - b.x);
if (mode === 1) {
let cumulative = 0;
result[avatarId] = points.map(p => {
cumulative += p.y;
return { x: p.x, y: Number(cumulative.toFixed(2)) };
});
} else {
result[avatarId] = points.map(p => ({
x: p.x,
y: Number(p.y.toFixed(2)),
}));
}
}
return result;
}, [turnHistory, mode]);
}
+79
View File
@@ -0,0 +1,79 @@
import useBattleDataStore from "@/stores/battleDataStore";
import { useMemo } from "react";
type Mode = 0 | 1 | 2;
function getChunkIndex(av: number, mode: Mode): number {
let sum = 0;
let idx = 0;
if (mode === 0) {
while (sum <= av) {
sum += 100;
idx++;
}
} else if (mode === 1) {
if (av < 150) return 0;
sum = 150;
idx = 1;
while (sum <= av) {
sum += 100;
idx++;
}
} else {
if (av < 150) return 0;
if (av < 300) return 1;
sum = 300;
idx = 2;
while (sum <= av) {
sum += 100;
idx++;
}
}
return idx - 1;
}
export function useDamagePerCycleForOne(avatarId: number, mode: Mode) {
const { turnHistory } = useBattleDataStore.getState();
return useMemo(() => {
const damageMap = new Map<number, number>();
turnHistory
.filter(t => t.avatarId === avatarId)
.forEach(t => {
const idx = getChunkIndex(t.actionValue, mode);
damageMap.set(idx, (damageMap.get(idx) || 0) + t.totalDamage);
});
const maxIndex = Math.max(...Array.from(damageMap.keys()), 0);
return Array.from({ length: maxIndex + 1 }).map((_, i) => ({
x: `${i + 1}`,
y: damageMap.get(i) || 0,
}));
}, [avatarId, mode, turnHistory]);
}
export function useDamagePerCycleForAll(mode: Mode) {
const { turnHistory } = useBattleDataStore.getState();
return useMemo(() => {
const damageMap = new Map<number, number>();
turnHistory.forEach(t => {
const idx = getChunkIndex(t.actionValue, mode);
damageMap.set(idx, (damageMap.get(idx) || 0) + t.totalDamage);
});
const maxIndex = Math.max(...Array.from(damageMap.keys()), 0);
return Array.from({ length: maxIndex + 1 }).map((_, i) => ({
x: `${i + 1}`,
y: damageMap.get(i) || 0,
}));
}, [mode, turnHistory]);
}
+21
View File
@@ -0,0 +1,21 @@
import useBattleDataStore from "@/stores/battleDataStore";
import { useMemo } from "react";
export function useDamagePercentPerAvatar() {
const { turnHistory } = useBattleDataStore.getState();
return useMemo(() => {
const dmgByAvatar = new Map<number, number>();
turnHistory.forEach(t => {
dmgByAvatar.set(t.avatarId, (dmgByAvatar.get(t.avatarId) || 0) + t.totalDamage);
});
const totalDmg = Array.from(dmgByAvatar.values()).reduce((sum, v) => sum + v, 0);
return Array.from(dmgByAvatar.entries()).map(([avatarId, dmg]) => ({
avatarId,
percent: totalDmg > 0 ? (dmg / totalDmg) * 100 : 0,
}));
}, [turnHistory]);
}
+25
View File
@@ -0,0 +1,25 @@
"use client";
import { useMemo } from "react";
import useBattleDataStore from "@/stores/battleDataStore";
export function useSkillDamageByAvatar(avatarId: number) {
const { turnHistory } = useBattleDataStore.getState();
return useMemo(() => {
const skillTypes = ['technique', 'talent', 'basic', 'skill', 'ultimate', 'servant'];
const dmgMap = new Map<string, number>();
skillTypes.forEach((type) => dmgMap.set(type, 0));
for (const turn of turnHistory) {
const type = turn.skillType.toLowerCase();
if (turn.avatarId === avatarId && dmgMap.has(type)) {
dmgMap.set(type, dmgMap.get(type)! + turn.totalDamage);
}
}
const labels = Array.from(dmgMap.keys());
const damageValues = Array.from(dmgMap.values());
return { labels, damageValues };
}, [avatarId, turnHistory]);
}