Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | 80x 63x 1x 12x 1x 3x 80x 63x 1x 12x 1x 3x 3x 80x 80x 80x 80x 50x 80x 50x 80x 50x 80x 80x 80x | /**
* DifficultyIndicator Component - AI Difficulty Tier Display
*
* Shows the current AI difficulty tier with Korean-English bilingual text
* and color-coded visual feedback based on tier level.
*
* **Korean Philosophy (난이도 표시)**:
* Provides transparent feedback to player about AI challenge level,
* helping them understand their skill progression.
*/
import React, { useMemo } from "react";
import { DifficultyTier } from "../../../../../systems/ai";
import {
hexColorToCSS,
hexToRgbaString,
} from "../../../../../utils/colorUtils";
import { useKoreanTheme } from "../../../../shared/base/useKoreanTheme";
export interface DifficultyIndicatorProps {
/** Current difficulty tier (1-5) */
readonly tier: DifficultyTier;
/** Whether to use mobile-optimized sizing */
readonly isMobile: boolean;
}
/**
* Get tier display name with Korean and English
*/
function getTierName(tier: DifficultyTier): {
korean: string;
english: string;
} {
switch (tier) {
case DifficultyTier.BEGINNER:
return { korean: "초보", english: "Beginner" };
case DifficultyTier.NOVICE:
return { korean: "입문", english: "Novice" };
case DifficultyTier.INTERMEDIATE:
return { korean: "중급", english: "Intermediate" };
case DifficultyTier.ADVANCED:
return { korean: "고급", english: "Advanced" };
case DifficultyTier.EXPERT:
return { korean: "전문", english: "Expert" };
default:
return { korean: "중급", english: "Intermediate" };
}
}
/**
* Get numeric color for difficulty tier using theme colors
* Maps tiers to existing color scheme for consistency
*/
function getTierColorValue(
tier: DifficultyTier,
theme: ReturnType<typeof useKoreanTheme>,
): number {
switch (tier) {
case DifficultyTier.BEGINNER:
return theme.colors.POSITIVE_GREEN; // Green - Easy
case DifficultyTier.NOVICE:
return theme.colors.ACCENT_GREEN; // Light Green
case DifficultyTier.INTERMEDIATE:
return theme.colors.ACCENT_GOLD; // Gold - Medium
case DifficultyTier.ADVANCED:
return theme.colors.SECONDARY_ORANGE; // Orange
case DifficultyTier.EXPERT:
return theme.colors.NEGATIVE_RED; // Red - Hard
default:
return theme.colors.ACCENT_GOLD; // Default to medium
}
}
/**
* DifficultyIndicator - Visual feedback for current AI difficulty tier
*
* Uses relative positioning for embedding in container HUDs
*/
export const DifficultyIndicator: React.FC<DifficultyIndicatorProps> = ({
tier,
isMobile,
}) => {
const theme = useKoreanTheme({ variant: "primary", size: "small", isMobile });
const tierName = getTierName(tier);
const tierColorValue = getTierColorValue(tier, theme);
// Memoize color calculations
const tierColor = useMemo(
() => hexColorToCSS(tierColorValue),
[tierColorValue],
);
const tierBackground = useMemo(
() => hexToRgbaString(tierColorValue, 0.13),
[tierColorValue],
);
const tierBoxShadow = useMemo(
() => hexToRgbaString(tierColorValue, 0.27),
[tierColorValue],
);
// Responsive sizing
const fontSize = isMobile ? 11 : 13;
const padding = isMobile ? "6px 10px" : "8px 12px";
return (
<div
data-testid="difficulty-indicator"
style={{
position: "relative",
padding,
background: tierBackground, // 13% opacity background
border: `2px solid ${tierColor}`,
borderRadius: "4px",
fontFamily: theme.fontFamily.KOREAN,
fontSize: `${fontSize}px`,
color: tierColor,
textShadow: "0 0 4px rgba(0,0,0,0.8)",
pointerEvents: "none",
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "2px",
transition: "all 0.3s ease-in-out", // Smooth color/border transitions
boxShadow: `0 0 8px ${tierBoxShadow}`, // Subtle glow effect (27% opacity)
width: "100%",
boxSizing: "border-box" as const,
}}
>
<div
data-testid="difficulty-label"
style={{
fontSize: isMobile ? "9px" : "10px",
opacity: 0.8,
letterSpacing: "0.5px",
}}
>
AI Difficulty
</div>
<div
data-testid="difficulty-tier"
style={{
fontWeight: "bold",
whiteSpace: "nowrap",
letterSpacing: "0.5px",
}}
>
{tierName.korean} | {tierName.english}
</div>
</div>
);
};
|