import { AFFINITY_PROGRESS_MARKERS, AFFINITY_PROGRESS_MAX, AFFINITY_PROGRESS_MIN, getAffinityLevelMeta, } from '../data/affinityLevels'; type AffinityProgressMarker = (typeof AFFINITY_PROGRESS_MARKERS)[number]; function clamp(value: number, min: number, max: number) { return Math.min(max, Math.max(min, value)); } function getNextAffinityMarker(affinity: number) { const currentLevel = getAffinityLevelMeta(affinity); if (currentLevel.nextAffinity == null) return null; return ( AFFINITY_PROGRESS_MARKERS.find( (marker) => marker.value === currentLevel.nextAffinity, ) ?? null ); } function getAffinityProgressRatio(value: number) { return clamp( (value - AFFINITY_PROGRESS_MIN) / (AFFINITY_PROGRESS_MAX - AFFINITY_PROGRESS_MIN), 0, 1, ); } function getAnchorTransform(ratio: number) { if (ratio <= 0.02) return 'translateX(0)'; if (ratio >= 0.98) return 'translateX(-100%)'; return 'translateX(-50%)'; } function isMarkerReached(marker: AffinityProgressMarker, affinity: number) { if (marker.value < 0) { return affinity < 0; } return affinity >= marker.value; } export function AffinityStatusCard({ affinity }: { affinity: number }) { const currentLevel = getAffinityLevelMeta(affinity); const nextLevel = getNextAffinityMarker(affinity); const currentRatio = getAffinityProgressRatio(affinity); const zeroRatio = getAffinityProgressRatio(0); const activeMarkerValue = currentLevel.minAffinity <= AFFINITY_PROGRESS_MIN ? AFFINITY_PROGRESS_MIN : currentLevel.minAffinity; const fillLeftRatio = Math.min(currentRatio, zeroRatio); const fillWidthRatio = Math.abs(currentRatio - zeroRatio); const fillWidthPercent = fillWidthRatio > 0 ? `${Math.max(fillWidthRatio * 100, 1)}%` : '0%'; const currentPointerTone = affinity < 0 ? 'border-rose-100/90 bg-rose-300 shadow-[0_0_16px_rgba(251,113,133,0.45)]' : 'border-sky-50/90 bg-sky-300 shadow-[0_0_18px_rgba(125,211,252,0.35)]'; const fillGradient = affinity < 0 ? 'linear-gradient(90deg, rgba(251,113,133,0.92) 0%, rgba(253,164,175,0.98) 100%)' : 'linear-gradient(90deg, rgba(125,211,252,0.92) 0%, rgba(251,191,36,0.94) 60%, rgba(251,113,133,0.96) 100%)'; return (
好感等级
{currentLevel.label} 当前好感 {affinity}
{nextLevel ? ( <>
下一节点
{nextLevel.label} · {nextLevel.value}
) : ( <>
已达最高节点
继续提升可稳固关系优势
)}

{currentLevel.description}

好感进度
0 是战斗分界线,低于 0 会直接进入对战;其余节点表示进入对应阶段所需的最低好感。
{AFFINITY_PROGRESS_MARKERS.map((marker) => { const markerRatio = getAffinityProgressRatio(marker.value); const isReached = isMarkerReached(marker, affinity); const isActive = marker.value === activeMarkerValue; return (
{isActive ? (
) : null}
{marker.label}
{marker.value}
); })}
); }