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 | 70x 62x 1x 4x 1x 2x 70x 62x 1x 4x 1x 2x 3x 70x 70x 70x 70x 70x 70x 70x | /**
* 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 from "react";
import { DifficultyTier } from "../../../../../systems/ai";
import { FONT_FAMILY, KOREAN_COLORS } from "../../../../../types/constants";
import { hexColorToCSS, hexToRgbaString } from "../../../../../utils/colorUtils";
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 KOREAN_COLORS constants
* Maps tiers to existing color scheme for consistency
*/
function getTierColorValue(tier: DifficultyTier): number {
switch (tier) {
case DifficultyTier.BEGINNER:
return KOREAN_COLORS.POSITIVE_GREEN; // Green - Easy
case DifficultyTier.NOVICE:
return KOREAN_COLORS.ACCENT_GREEN; // Light Green
case DifficultyTier.INTERMEDIATE:
return KOREAN_COLORS.ACCENT_GOLD; // Gold - Medium
case DifficultyTier.ADVANCED:
return KOREAN_COLORS.SECONDARY_ORANGE; // Orange
case DifficultyTier.EXPERT:
return KOREAN_COLORS.NEGATIVE_RED; // Red - Hard
default:
return KOREAN_COLORS.ACCENT_GOLD; // Default to medium
}
}
/**
* DifficultyIndicator - Visual feedback for current AI difficulty tier
*
* Positioned below Player 2 HUD to avoid overlap
* Calculates vertical offset based on HUD height (name + health + stamina + stance)
*/
export const DifficultyIndicator: React.FC<DifficultyIndicatorProps> = ({
tier,
isMobile,
}) => {
const tierName = getTierName(tier);
const tierColorValue = getTierColorValue(tier);
const tierColor = hexColorToCSS(tierColorValue);
// Responsive sizing
const fontSize = isMobile ? 11 : 13;
const padding = isMobile ? "6px 10px" : "8px 12px";
// Position below Player 2 HUD to avoid overlap
// NOTE: This uses a calculated offset based on typical HUD height.
// If Player HUD layout changes, this may need adjustment.
// Consider using CSS Grid or exported HUD constants for better maintainability.
// Current estimate: name (20px) + health bar (20px) + stamina bar (20px) + stance (15px) + gaps (18px) ≈ 93px
const topOffset = isMobile ? 100 : 110;
return (
<div
data-testid="difficulty-indicator"
style={{
position: "absolute",
top: `${topOffset}px`,
right: isMobile ? "8px" : "12px",
padding,
background: hexToRgbaString(tierColorValue, 0.13), // 13% opacity background
border: `2px solid ${tierColor}`,
borderRadius: "4px",
fontFamily: FONT_FAMILY.KOREAN,
fontSize: `${fontSize}px`,
color: tierColor,
textShadow: "0 0 4px rgba(0,0,0,0.8)",
pointerEvents: "none",
zIndex: 100,
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "2px",
transition: "all 0.3s ease-in-out", // Smooth color/border transitions
boxShadow: `0 0 8px ${hexToRgbaString(tierColorValue, 0.27)}`, // Subtle glow effect (27% opacity)
}}
>
<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>
);
};
|