speakid-hangman 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speakid-hangman.cjs.js","sources":["../src/styles/style.ts","../src/components/HangmanLobbyGame.tsx"],"sourcesContent":["import { CSSProperties } from \"react\";\n\n// ===== Стили согласно визуальному гайдлайну: Onest, минималистичный, дружелюбный =====\n// Шрифт: Onest (Regular, Medium, SemiBold)\n// Стиль: Плоский, минималистичный, воздушный, без излишеств\n// Цвета: Мягкий контраст, дружелюбная палитра\n\nexport const styles: Record<string, CSSProperties> = {\n gmCenterScreen: {\n position: \"relative\",\n zIndex: 1,\n minHeight: \"100%\",\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n textAlign: \"center\",\n color: \"#1f2937\", // colorTextPrimary\n padding: \"24px 16px\",\n boxSizing: \"border-box\",\n fontFamily: '\"Onest\", system-ui, -apple-system, \"Segoe UI\", Roboto, Arial, sans-serif',\n background: \"transparent\", // Прозрачный по умолчанию, переопределяется в компоненте\n },\n // Desktop: Headline 1 - Onest SemiBold 32px, line-height 110%\n gmHeadline1: {\n fontWeight: 600, // SemiBold\n fontSize: \"clamp(30px, 4vw, 32px)\", // Mobile 30px, Desktop 32px\n lineHeight: \"110%\",\n marginBottom: \"24px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Headline 2 - Onest Medium 24px, line-height 110%\n gmHeadline2: {\n fontWeight: 500, // Medium\n fontSize: \"24px\",\n lineHeight: \"110%\",\n marginBottom: \"16px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Headline 3 - Onest Medium 24px, line-height 110%\n // Mobile: Headline 3 - Onest Medium 16px, line-height 110%\n gmHeadline3: {\n fontWeight: 500, // Medium\n fontSize: \"clamp(16px, 2vw, 24px)\", // Mobile 16px, Desktop 24px\n lineHeight: \"110%\",\n marginBottom: \"12px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Body L - Onest Regular 18px, line-height 120%\n gmBodyL: {\n fontWeight: 400, // Regular\n fontSize: \"18px\",\n lineHeight: \"120%\",\n marginBottom: \"12px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Body M - Onest Regular 16px, line-height 120%\n // Mobile: Body M - Onest Regular 14px, line-height 120%\n gmBodyM: {\n fontWeight: 400, // Regular\n fontSize: \"clamp(14px, 1.5vw, 16px)\", // Mobile 14px, Desktop 16px\n lineHeight: \"120%\",\n marginBottom: \"8px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Body S - Onest Regular 14px, line-height 120%\n // Mobile: Body S - Onest Regular 12px, line-height 120%\n gmBodyS: {\n fontWeight: 400, // Regular\n fontSize: \"clamp(12px, 1.5vw, 14px)\", // Mobile 12px, Desktop 14px\n lineHeight: \"120%\",\n color: \"#6b7280\", // colorTextSecondary\n marginBottom: \"8px\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Button: Onest Regular 16px, line-height 100%\n gmButton: {\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontWeight: 400, // Regular\n fontSize: \"16px\",\n lineHeight: \"100%\",\n padding: \"10px 16px\",\n borderRadius: \"8px\", // Более мягкие углы для минималистичного стиля\n border: \"1px solid #e5e7eb\", // colorSeparator\n background: \"#ec4c44\", // colorAccent (Default)\n color: \"#ffffff\", // colorTextContrast\n cursor: \"pointer\",\n boxShadow: \"none\", // Плоский стиль без теней\n transition: \"background-color 0.2s ease, opacity 0.2s ease, transform 0.1s ease\",\n margin: \"4px\",\n },\n gmButtonActive: {\n background: \"#333\", // colorAccent Active\n color: \"#fff\", // colorTextContrast\n boxShadow: \"none\", // Плоский стиль\n },\n gmButtonSecondary: {\n background: \"#f9f9f9\", // colorBackgroundAccent\n color: \"#1f2937\", // colorTextPrimary\n border: \"1px solid #e5e7eb\", // colorSeparator\n boxShadow: \"none\", // Плоский стиль\n },\n gmButtonGroup: {\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"8px\",\n justifyContent: \"center\",\n marginBottom: \"24px\",\n },\n gmWordDisplay: {\n fontSize: \"clamp(20px, 5vw, 28px)\",\n fontWeight: 500, // Medium\n letterSpacing: \"6px\",\n margin: \"32px 0\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n lineHeight: \"120%\",\n },\n gmGuessedLetters: {\n fontSize: \"clamp(12px, 1.5vw, 16px)\", // Body S / Body M\n color: \"#6b7280\", // colorTextSecondary\n marginTop: \"16px\",\n minHeight: \"24px\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n lineHeight: \"120%\",\n },\n gmStatusWin: {\n color: \"#10b981\", // colorTextPositive / colorIconPositive\n fontWeight: 500, // Medium\n fontSize: \"clamp(14px, 1.5vw, 18px)\", // Body M / Body L\n lineHeight: \"120%\",\n margin: \"16px 0\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n gmStatusLose: {\n color: \"#ec4c44\", // colorTextNegative / colorIconNegative\n fontWeight: 500, // Medium\n fontSize: \"clamp(14px, 1.5vw, 18px)\", // Body M / Body L\n lineHeight: \"120%\",\n margin: \"16px 0\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n gmInfoBox: {\n background: \"#f9f9f9\", // colorBackgroundAccent\n border: \"1px solid #e5e7eb\", // colorSeparator\n borderRadius: \"8px\", // Мягкие углы\n padding: \"16px\",\n marginBottom: \"24px\",\n maxWidth: \"500px\",\n width: \"100%\",\n boxShadow: \"none\", // Плоский стиль\n },\n gmSection: {\n marginBottom: \"32px\",\n width: \"100%\",\n maxWidth: \"500px\",\n },\n // ✅ Обновлено только для качества логотипа (размер как в magic-sentence)\n gmLogoFixed: {\n position: \"absolute\",\n top: \"16px\",\n left: \"16px\",\n width: \"auto\",\n zIndex: 10,\n pointerEvents: \"none\",\n background: \"transparent\",\n transform: \"none\",\n willChange: \"auto\",\n },\n gmLogoImg: {\n height: \"28px\",\n width: \"auto\",\n background: \"transparent\",\n objectFit: \"contain\",\n imageRendering: \"auto\",\n transform: \"translateZ(0)\",\n backfaceVisibility: \"hidden\",\n WebkitFontSmoothing: \"antialiased\",\n display: \"block\",\n },\n gmLogoFallback: {\n height: \"28px\",\n width: \"auto\",\n background: \"transparent\",\n color: \"#ec4c44\",\n fontSize: \"16px\",\n fontWeight: 700,\n display: \"block\",\n },\n};\n\n// ===== Цветовая палитра для справки =====\n// colorTextPrimary: #1f2937\n// colorTextSecondary: #6b7280\n// colorTextNegative: #ec4c44\n// colorTextPositive: #10b981\n// colorBackgroundAccent: #f9f9f9\n// colorSeparator: #e5e7eb\n// colorAccent (Default): #ec4c44\n// colorAccent (Active): #333\n\n","import React, { useState, useEffect, useCallback, useMemo } from \"react\";\nimport { styles } from \"../styles/style\";\n\n// Компонент визуализации виселицы\nfunction HangmanDrawing({ \n mistakes, \n maxMistakes, \n size = 200 \n}: { \n mistakes: number; \n maxMistakes: number;\n size?: number;\n}) {\n // Адаптивные размеры SVG\n const svgWidth = size;\n const svgHeight = size * 1.25; // Соотношение 200:250\n const strokeWidth = Math.max(2, size / 100); // Адаптивная толщина линий\n \n // Координаты (пропорциональные исходному размеру 200x250)\n const baseX1 = 10 * (svgWidth / 200);\n const baseY = 240 * (svgHeight / 250);\n const baseX2 = 150 * (svgWidth / 200);\n \n const poleX = 80 * (svgWidth / 200);\n const poleY1 = 20 * (svgHeight / 250);\n const poleY2 = 240 * (svgHeight / 250);\n \n const topX1 = 80 * (svgWidth / 200);\n const topY = 20 * (svgHeight / 250);\n const topX2 = 150 * (svgWidth / 200);\n \n const ropeX = 150 * (svgWidth / 200);\n const ropeY1 = 20 * (svgHeight / 250);\n const ropeY2 = 50 * (svgHeight / 250);\n \n const headCX = 150 * (svgWidth / 200);\n const headCY = 70 * (svgHeight / 250);\n const headR = 20 * (svgWidth / 200);\n \n const bodyX = 150 * (svgWidth / 200);\n const bodyY1 = 90 * (svgHeight / 250);\n const bodyY2 = 150 * (svgHeight / 250);\n \n const leftArmX1 = 150 * (svgWidth / 200);\n const leftArmY1 = 110 * (svgHeight / 250);\n const leftArmX2 = 130 * (svgWidth / 200);\n const leftArmY2 = 130 * (svgHeight / 250);\n \n const rightArmX1 = 150 * (svgWidth / 200);\n const rightArmY1 = 110 * (svgHeight / 250);\n const rightArmX2 = 170 * (svgWidth / 200);\n const rightArmY2 = 130 * (svgHeight / 250);\n \n const leftLegX1 = 150 * (svgWidth / 200);\n const leftLegY1 = 150 * (svgHeight / 250);\n const leftLegX2 = 130 * (svgWidth / 200);\n const leftLegY2 = 190 * (svgHeight / 250);\n \n const rightLegX1 = 150 * (svgWidth / 200);\n const rightLegY1 = 150 * (svgHeight / 250);\n const rightLegX2 = 170 * (svgWidth / 200);\n const rightLegY2 = 190 * (svgHeight / 250);\n\n // Цвет в зависимости от количества ошибок\n const getStrokeColor = () => {\n if (mistakes === 0) return \"#1f2937\"; // colorTextPrimary\n if (mistakes <= maxMistakes * 0.5) return \"#1f2937\"; // Окей\n if (mistakes <= maxMistakes * 0.75) return \"#f59e0b\"; // Предупреждение\n return \"#ec4c44\"; // colorTextNegative - опасно\n };\n\n const strokeColor = getStrokeColor();\n\n return (\n <svg \n width={svgWidth} \n height={svgHeight} \n style={{ \n display: \"block\",\n margin: \"0 auto\",\n }}\n >\n {/* Виселица рисуется пошагово с ошибками */}\n {/* 1-я ошибка: Основание */}\n {mistakes > 0 && (\n <line \n x1={baseX1} \n y1={baseY} \n x2={baseX2} \n y2={baseY} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n\n {/* 2-я ошибка: Стойка */}\n {mistakes > 1 && (\n <line \n x1={poleX} \n y1={poleY1} \n x2={poleX} \n y2={poleY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n\n {/* 3-я ошибка: Верхняя перекладина */}\n {mistakes > 2 && (\n <line \n x1={topX1} \n y1={topY} \n x2={topX2} \n y2={topY} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n\n {/* 4-я ошибка: Веревка */}\n {mistakes > 3 && (\n <line \n x1={ropeX} \n y1={ropeY1} \n x2={ropeX} \n y2={ropeY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n\n {/* 5-я ошибка: Голова */}\n {mistakes > 4 && (\n <circle \n cx={headCX} \n cy={headCY} \n r={headR} \n stroke={strokeColor} \n fill=\"none\" \n strokeWidth={strokeWidth}\n />\n )}\n \n {/* 6-я ошибка: Тело */}\n {mistakes > 5 && (\n <line \n x1={bodyX} \n y1={bodyY1} \n x2={bodyX} \n y2={bodyY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n \n {/* Дополнительные части (если maxMistakes больше 6) */}\n {mistakes > 6 && (\n <line \n x1={leftArmX1} \n y1={leftArmY1} \n x2={leftArmX2} \n y2={leftArmY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n \n {mistakes > 7 && (\n <line \n x1={rightArmX1} \n y1={rightArmY1} \n x2={rightArmX2} \n y2={rightArmY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n \n {mistakes > 8 && (\n <line \n x1={leftLegX1} \n y1={leftLegY1} \n x2={leftLegX2} \n y2={leftLegY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n \n {mistakes > 9 && (\n <line \n x1={rightLegX1} \n y1={rightLegY1} \n x2={rightLegX2} \n y2={rightLegY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n </svg>\n );\n}\n\nexport interface HangmanLobbyGameProps {\n gameCubeSize?: number;\n screenHeight?: number;\n screenWidth?: number;\n logoUrl?: string;\n showLogo?: boolean;\n baseURL?: string;\n}\n\nexport default function HangmanLobbyGame({\n gameCubeSize = 400,\n screenHeight = 800,\n screenWidth = 800,\n logoUrl,\n showLogo = true,\n baseURL,\n}: HangmanLobbyGameProps = {}) {\n const categories = {\n Professions: [\"teacher\", \"doctor\", \"nurse\", \"driver\", \"police\", \"firefighter\", \"cook\", \"waiter\", \"farmer\", \"builder\", \"singer\", \"actor\", \"dentist\", \"pilot\", \"vet\", \"artist\", \"cleaner\", \"student\", \"baker\", \"mechanic\"],\n Family: [\"mother\", \"father\", \"sister\", \"brother\", \"grandmother\", \"grandfather\", \"aunt\", \"uncle\", \"cousin\", \"baby\", \"parents\", \"children\", \"wife\", \"husband\", \"son\", \"daughter\", \"family\", \"twins\", \"relatives\"],\n \"Farm animals\": [\"cow\", \"pig\", \"horse\", \"sheep\", \"goat\", \"duck\", \"chicken\", \"rooster\", \"turkey\", \"goose\", \"rabbit\", \"mouse\", \"donkey\", \"bee\", \"hen\", \"lamb\", \"bull\", \"pony\"],\n Food: [\"apple\", \"banana\", \"bread\", \"cheese\", \"milk\", \"egg\", \"rice\", \"soup\", \"fish\", \"meat\", \"potato\", \"carrot\", \"tomato\", \"cucumber\", \"butter\", \"cake\", \"salad\", \"pasta\", \"pizza\", \"juice\"],\n Hobbies: [\"reading\", \"drawing\", \"painting\", \"dancing\", \"singing\", \"cooking\", \"swimming\", \"fishing\", \"running\", \"cycling\", \"skating\", \"writing\", \"camping\", \"photography\", \"hiking\", \"games\"],\n Christmas: [\"tree\", \"present\", \"gift\", \"santa\", \"snow\", \"snowman\", \"bell\", \"star\", \"lights\", \"card\", \"cookies\", \"elf\", \"sleigh\", \"reindeer\", \"candle\", \"stocking\"],\n Halloween: [\"pumpkin\", \"costume\", \"candy\", \"ghost\", \"witch\", \"spider\", \"bat\", \"skeleton\", \"mask\", \"monster\", \"mummy\", \"cat\", \"broom\", \"zombie\", \"trick\", \"treat\", \"candle\", \"night\", \"party\"],\n Sport: [\"football\", \"basketball\", \"tennis\", \"swimming\", \"running\", \"baseball\", \"skiing\", \"skating\", \"volleyball\", \"hockey\", \"golf\", \"boxing\", \"cycling\", \"rugby\", \"karate\", \"yoga\", \"surfing\", \"climbing\", \"dancing\", \"gym\", \"chess\"],\n \"Body parts\": [\"head\", \"hair\", \"eyes\", \"ears\", \"nose\", \"mouth\", \"teeth\", \"tongue\", \"neck\", \"shoulder\", \"arm\", \"hand\", \"finger\", \"leg\", \"knee\", \"foot\", \"toe\", \"back\", \"stomach\", \"heart\", \"legs\", \"nails\", \"chin\", \"beard\"],\n \"School subjects\": [\"math\", \"english\", \"history\", \"geography\", \"art\", \"music\", \"science\", \"biology\", \"chemistry\", \"physics\", \"pe\", \"literature\", \"drama\", \"design\", \"economics\"],\n Animals: [\"cat\", \"dog\", \"rabbit\", \"elephant\", \"lion\", \"tiger\", \"monkey\", \"bear\", \"fox\", \"wolf\", \"giraffe\", \"zebra\", \"crocodile\", \"dolphin\", \"whale\", \"shark\", \"frog\", \"parrot\", \"mouse\", \"penguin\", \"deer\", \"lizard\", \"turtle\", \"snake\"],\n Countries: [\"russia\", \"canada\", \"china\", \"japan\", \"france\", \"germany\", \"italy\", \"spain\", \"brazil\", \"india\", \"australia\", \"america\", \"england\", \"korea\", \"mexico\", \"egypt\", \"turkey\", \"vietnam\", \"norway\", \"finland\", \"thailand\", \"georgia\", \"kazakhstan\"],\n Clothes: [\"shirt\", \"dress\", \"skirt\", \"trousers\", \"jeans\", \"coat\", \"jacket\", \"sweater\", \"socks\", \"shoes\", \"boots\", \"hat\", \"scarf\", \"gloves\", \"shorts\", \"cap\", \"belt\", \"tie\", \"uniform\", \"pants\", \"underwear\"],\n Traveling: [\"ticket\", \"luggage\", \"suitcase\", \"airport\", \"flight\", \"passport\", \"visa\", \"map\", \"guide\", \"hotel\", \"reservation\", \"bus\", \"train\", \"taxi\", \"tourist\", \"sightseeing\", \"backpack\", \"journey\", \"adventure\", \"beach\", \"tour\", \"souvenir\"],\n Environment: [\"tree\", \"forest\", \"air\", \"water\", \"pollution\", \"recycle\", \"nature\", \"clean\", \"waste\", \"plastic\", \"energy\", \"animal\", \"climate\", \"earth\", \"ocean\", \"river\", \"planet\", \"save\", \"green\", \"environment\", \"litter\", \"organic\"],\n Space: [\"planet\", \"star\", \"sun\", \"moon\", \"astronaut\", \"rocket\", \"space\", \"galaxy\", \"universe\", \"telescope\", \"comet\", \"asteroid\", \"orbit\", \"gravity\", \"alien\", \"spaceship\", \"mars\", \"satellite\", \"sky\", \"eclipse\"],\n Devices: [\"computer\", \"laptop\", \"phone\", \"tablet\", \"tv\", \"keyboard\", \"mouse\", \"printer\", \"camera\", \"headphones\", \"charger\", \"screen\", \"watch\", \"microphone\", \"speaker\", \"console\", \"router\", \"battery\", \"cable\", \"remote\"],\n };\n\n const [stage, setStage] = useState<\"lobby\" | \"category\" | \"rounds\" | \"game\" | \"result\">(\"lobby\");\n const [category, setCategory] = useState<keyof typeof categories | \"\">(\"\");\n const [difficulty] = useState<\"Easy\" | \"Normal\" | \"Hard\">(\"Normal\"); // Фиксированная сложность\n const [rounds, setRounds] = useState(0); // 0 означает \"не выбрано\"\n const [currentRound, setCurrentRound] = useState(1);\n const [word, setWord] = useState(\"\");\n const [guessed, setGuessed] = useState<string[]>([]);\n const [mistakes, setMistakes] = useState(0);\n const [wins, setWins] = useState(0);\n const [roundResult, setRoundResult] = useState<\"win\" | \"lose\" | null>(null);\n const [containerSize, setContainerSize] = useState<number | null>(null);\n const [scale, setScale] = useState(1);\n const [usedWords, setUsedWords] = useState<string[]>([]); // Отслеживание использованных слов\n\n const maxMistakes = difficulty === \"Easy\" ? 8 : difficulty === \"Normal\" ? 6 : 4;\n\n // Вычисляем baseURL для изображений\n const imagesBaseURL = baseURL || (typeof window !== \"undefined\" && window.origin \n ? `${window.origin}/cloud/speakid/games/hangman`\n : \"/cloud/speakid/games/hangman\");\n\n // Определение мобильного устройства - используем window напрямую (как в magic-sentence)\n const [isMobile, setIsMobile] = useState(false);\n const [isNestHub, setIsNestHub] = useState(false);\n\n // Адаптивные размеры относительно gameCubeSize согласно визуальному гайдлайну\n // Desktop базовые размеры: Headline 1 - 32px, Headline 2 - 24px, Body M - 16px, Button - 16px\n // Mobile базовые размеры: Headline 1 - 30px, Headline 3 - 16px, Body M - 14px\n const baseFontSize = useMemo(() => {\n const fontSizeScale = (containerSize || gameCubeSize || 1000) / 400; // базовый размер 400px\n return {\n headline1: isMobile \n ? Math.max(24, Math.min(30, 30 * fontSizeScale)) // Mobile: 30px\n : Math.max(28, Math.min(32, 32 * fontSizeScale)), // Desktop: 32px\n headline2: Math.max(20, Math.min(28, 24 * fontSizeScale)), // Desktop: 24px\n headline3: isMobile\n ? Math.max(14, Math.min(18, 16 * fontSizeScale)) // Mobile: 16px\n : Math.max(20, Math.min(26, 24 * fontSizeScale)), // Desktop: 24px\n bodyL: Math.max(14, Math.min(20, 18 * fontSizeScale)), // Desktop: 18px\n bodyM: isMobile\n ? Math.max(12, Math.min(16, 14 * fontSizeScale)) // Mobile: 14px\n : Math.max(14, Math.min(18, 16 * fontSizeScale)), // Desktop: 16px\n bodyS: isMobile\n ? Math.max(10, Math.min(14, 12 * fontSizeScale)) // Mobile: 12px\n : Math.max(12, Math.min(16, 14 * fontSizeScale)), // Desktop: 14px\n wordDisplay: Math.max(18, Math.min(32, 26 * fontSizeScale)), // Адаптивный размер\n button: Math.max(12, Math.min(18, 16 * fontSizeScale)), // Desktop: 16px\n };\n }, [isMobile, containerSize, gameCubeSize]);\n\n // Адаптивные отступы и размеры (минималистичный стиль - мягкие углы)\n // Специальные настройки для Nest Hub (1024x600)\n const padding = useMemo(() => {\n const fontSizeScale = (containerSize || gameCubeSize || 1000) / 400;\n return isNestHub \n ? Math.max(8, Math.min(12, 10 * fontSizeScale))\n : Math.max(12, Math.min(24, 16 * fontSizeScale));\n }, [isNestHub, containerSize, gameCubeSize]);\n const gap = useMemo(() => {\n const fontSizeScale = (containerSize || gameCubeSize || 1000) / 400;\n return isNestHub\n ? Math.max(3, Math.min(6, 5 * fontSizeScale))\n : Math.max(4, Math.min(12, 8 * fontSizeScale));\n }, [isNestHub, containerSize, gameCubeSize]);\n const borderRadius = useMemo(() => {\n const fontSizeScale = (containerSize || gameCubeSize || 1000) / 400;\n return Math.max(6, Math.min(10, 8 * fontSizeScale));\n }, [containerSize, gameCubeSize]); // Мягкие углы для плоского стиля\n\n // Функции вдохновленные открытым кодом Hangman\n const isWordGuessed = (secretWord: string, lettersGuessed: string[]): boolean => {\n // Проверяем, все ли буквы слова угаданы\n return secretWord.split(\"\").every(letter => lettersGuessed.includes(letter));\n };\n\n const getGuessedWord = (secretWord: string, lettersGuessed: string[]): string => {\n // Возвращает строку с угаданными буквами и подчеркиваниями\n return secretWord\n .split(\"\")\n .map(letter => (lettersGuessed.includes(letter) ? letter : \"_\"))\n .join(\" \");\n };\n\n const getAvailableLetters = (lettersGuessed: string[]): string[] => {\n // Возвращает массив доступных букв (не угаданных)\n const alphabet = \"abcdefghijklmnopqrstuvwxyz\".split(\"\");\n return alphabet.filter(letter => !lettersGuessed.includes(letter));\n };\n\n const pickRandomCategory = (): keyof typeof categories => {\n const categoryKeys = Object.keys(categories) as Array<keyof typeof categories>;\n \n // Используем crypto.getRandomValues для более надежной случайности\n let randomIndex: number;\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const array = new Uint32Array(1);\n crypto.getRandomValues(array);\n randomIndex = array[0] % categoryKeys.length;\n } else {\n // Fallback на Math.random если crypto недоступен\n randomIndex = Math.floor(Math.random() * categoryKeys.length);\n }\n \n return categoryKeys[randomIndex];\n };\n\n const pickRandomWord = (cat: keyof typeof categories, avoidWords: string[] = []): string => {\n if (!cat || !categories[cat]) {\n // Fallback если категория пустая или не существует\n const firstCategory = Object.keys(categories)[0] as keyof typeof categories;\n return categories[firstCategory]?.[0] || \"\";\n }\n \n const words = categories[cat];\n if (!words || words.length === 0) {\n // Fallback если слова пустые\n return \"\";\n }\n \n // Если есть доступные слова (не использованные), выбираем из них\n const availableWords = words.filter(w => !avoidWords.includes(w));\n const wordsToChooseFrom = availableWords.length > 0 ? availableWords : words;\n \n if (wordsToChooseFrom.length === 0) {\n return \"\";\n }\n \n // Используем crypto.getRandomValues для более надежной случайности\n // Преобразуем в дробное число от 0 до 1 для равномерного распределения\n let randomIndex: number;\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const array = new Uint32Array(1);\n crypto.getRandomValues(array);\n // Преобразуем в дробное число от 0 до 1 для равномерного распределения\n const randomFloat = array[0] / 0xFFFFFFFF;\n randomIndex = Math.floor(randomFloat * wordsToChooseFrom.length);\n } else {\n // Fallback на Math.random если crypto недоступен\n randomIndex = Math.floor(Math.random() * wordsToChooseFrom.length);\n }\n \n return wordsToChooseFrom[randomIndex];\n };\n\n const startGame = () => {\n if (!category) return;\n setUsedWords([]); // Сбрасываем список использованных слов при новой игре\n const randomWord = pickRandomWord(category, []);\n if (!randomWord) {\n // Если не удалось выбрать слово, возвращаемся к выбору категории\n setStage(\"category\");\n return;\n }\n setWord(randomWord);\n setUsedWords([randomWord]); // Запоминаем первое слово\n setGuessed([]);\n setMistakes(0);\n setCurrentRound(1);\n setWins(0);\n setRoundResult(null);\n setStage(\"game\");\n };\n\n // Функция для обработки выбора буквы (используется и для клавиатуры, и для кликов)\n const handleLetterSelect = useCallback((letter: string) => {\n if (stage !== \"game\" || roundResult !== null) return;\n \n const lowerLetter = letter.toLowerCase();\n \n // Проверка: только буквы английского алфавита\n if (!/^[a-z]$/.test(lowerLetter)) return;\n \n // Проверяем, была ли буква уже угадана\n setGuessed((prevGuessed) => {\n if (prevGuessed.includes(lowerLetter)) {\n return prevGuessed;\n }\n \n // Добавляем букву в список угаданных\n return [...prevGuessed, lowerLetter];\n });\n \n // Проверяем, есть ли буква в текущем слове (используем функциональное обновление)\n setWord((currentWord) => {\n if (currentWord && !currentWord.includes(lowerLetter)) {\n setMistakes((m) => m + 1);\n }\n return currentWord;\n });\n }, [stage, roundResult]);\n\n const handleKey = useCallback((e: KeyboardEvent) => {\n handleLetterSelect(e.key);\n }, [handleLetterSelect]);\n\n useEffect(() => {\n if (stage === \"game\") {\n window.addEventListener(\"keydown\", handleKey);\n return () => window.removeEventListener(\"keydown\", handleKey);\n }\n }, [stage, handleKey]);\n\n // Используем функцию из открытого кода\n const masked = word ? getGuessedWord(word, guessed) : \"\";\n const isWin = word ? isWordGuessed(word, guessed) : false;\n // Игра проиграна когда виселица полностью нарисована (10 частей: основание, стойка, перекладина, веревка, голова, тело, левая рука, правая рука, левая нога, правая нога)\n const isLose = mistakes >= 10;\n const availableLetters = getAvailableLetters(guessed);\n\n // Функция для перехода к следующему раунду (вынесена для избежания дублирования)\n const moveToNextRound = useCallback(() => {\n if (!category || currentRound >= rounds) {\n setStage(\"result\");\n return;\n }\n \n setCurrentRound((r) => r + 1);\n setUsedWords((prev) => {\n const newWord = pickRandomWord(category as keyof typeof categories, prev);\n if (newWord) {\n setWord(newWord);\n return [...prev, newWord];\n }\n return prev;\n });\n setGuessed([]);\n setMistakes(0);\n setRoundResult(null);\n }, [category, currentRound, rounds]);\n\n useEffect(() => {\n if (isWin && roundResult === null) {\n setRoundResult(\"win\");\n setWins((w) => w + 1);\n \n const timer = setTimeout(() => {\n moveToNextRound();\n }, 2000);\n \n return () => clearTimeout(timer);\n }\n \n if (isLose && roundResult === null) {\n setRoundResult(\"lose\");\n \n const timer = setTimeout(() => {\n moveToNextRound();\n }, 2000);\n \n return () => clearTimeout(timer);\n }\n }, [isWin, isLose, roundResult, moveToNextRound]);\n\n const nextRound = () => {\n if (!category || currentRound >= rounds) {\n setStage(\"result\");\n return;\n }\n \n setCurrentRound((r) => r + 1);\n setUsedWords((prev) => {\n const newWord = pickRandomWord(category as keyof typeof categories, prev);\n if (newWord) {\n setWord(newWord);\n return [...prev, newWord]; // Добавляем новое слово в список использованных\n }\n return prev;\n });\n setGuessed([]);\n setMistakes(0);\n setRoundResult(null);\n };\n\n // ✅ Адаптив под мобилки, планшеты и десктоп (как в magic-sentence)\n useEffect(() => {\n const resize = () => {\n const width = window.innerWidth;\n const height = window.innerHeight;\n const mobile = width < 768 || (width === 926 && height === 428) || (width === 932 && height === 430);\n const isSmallHeight = height < 700;\n const isWideScreen = width / height > 1.8;\n const nestHub = width === 1024 && height === 600;\n \n setIsMobile(mobile);\n setIsNestHub(nestHub);\n\n // ✅ Адаптивные размеры контейнера\n // Если передан gameCubeSize, используем его (но с ограничениями)\n if (gameCubeSize && gameCubeSize >= 320) {\n const minSize = 320;\n const maxSize = 1200;\n const finalSize = Math.max(minSize, Math.min(maxSize, gameCubeSize));\n setContainerSize(finalSize);\n setScale(1);\n } else if (mobile) {\n setContainerSize(null);\n setScale(1);\n } else if (isSmallHeight) {\n setContainerSize(null);\n setScale(1);\n } else if (isWideScreen) {\n // ✅ Широкие экраны: используем стандартный размер но уменьшаем масштаб\n const minSize = 400;\n const maxSize = 1200;\n const finalSize = Math.min(1000, Math.min(width, height) * 0.9);\n setContainerSize(finalSize);\n setScale(0.85);\n } else {\n const minSize = 400;\n const maxSize = 1200;\n const finalSize = Math.min(1000, Math.min(width, height) * 0.9);\n setContainerSize(finalSize);\n setScale(1);\n }\n };\n resize();\n window.addEventListener(\"resize\", resize);\n return () => window.removeEventListener(\"resize\", resize);\n }, [gameCubeSize]);\n\n // SVG с детскими каракулями для фона (более резкие и яркие)\n const kidsDoodlesSvg = `\n <svg width=\"100%\" height=\"100%\" xmlns=\"http://www.w3.org/2000/svg\" style=\"position: absolute; top: 0; left: 0; pointer-events: none; opacity: 0.2;\">\n <!-- Каракули мелками и фломастерами -->\n \n <!-- Сердечко -->\n <path d=\"M 85% 15% Q 85% 10%, 90% 10% Q 95% 10%, 95% 15% Q 95% 20%, 90% 25% Q 85% 30%, 85% 15%\" \n fill=\"none\" stroke=\"#FF69B4\" stroke-width=\"3\" stroke-linecap=\"round\"/>\n \n <!-- Звезда -->\n <path d=\"M 10% 85% L 12% 80% L 14% 85% L 18% 85% L 13% 88% L 15% 92% L 10% 89% L 5% 92% L 7% 88% L 2% 85% Z\" \n fill=\"#FFA500\" stroke=\"#FF8C00\" stroke-width=\"1.5\"/>\n \n <!-- Волнистые линии (мелки) -->\n <path d=\"M 20% 25% Q 22% 23%, 24% 25% T 28% 25% T 32% 25%\" \n fill=\"none\" stroke=\"#FF6B6B\" stroke-width=\"3.5\" stroke-linecap=\"round\"/>\n <path d=\"M 60% 30% Q 62% 28%, 64% 30% T 68% 30% T 72% 30%\" \n fill=\"none\" stroke=\"#4ECDC4\" stroke-width=\"3.5\" stroke-linecap=\"round\"/>\n \n <!-- Спираль -->\n <path d=\"M 5% 45% Q 8% 42%, 10% 45% Q 12% 48%, 10% 50% Q 8% 52%, 5% 50% Q 3% 48%, 5% 45%\" \n fill=\"none\" stroke=\"#9B59B6\" stroke-width=\"3\" stroke-linecap=\"round\"/>\n \n <!-- Зигзаг -->\n <path d=\"M 88% 55% L 92% 50% L 94% 55% L 96% 50% L 98% 55%\" \n fill=\"none\" stroke=\"#E74C3C\" stroke-width=\"3.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n \n <!-- Ромашка -->\n <circle cx=\"25%\" cy=\"70%\" r=\"15\" fill=\"none\" stroke=\"#FFD700\" stroke-width=\"2.5\"/>\n <circle cx=\"25%\" cy=\"70%\" r=\"8\" fill=\"#FFD700\"/>\n <line x1=\"25%\" y1=\"70%\" x2=\"22%\" y2=\"65%\" stroke=\"#FFFFFF\" stroke-width=\"2.5\"/>\n <line x1=\"25%\" y1=\"70%\" x2=\"28%\" y2=\"65%\" stroke=\"#FFFFFF\" stroke-width=\"2.5\"/>\n <line x1=\"25%\" y1=\"70%\" x2=\"22%\" y2=\"75%\" stroke=\"#FFFFFF\" stroke-width=\"2.5\"/>\n <line x1=\"25%\" y1=\"70%\" x2=\"28%\" y2=\"75%\" stroke=\"#FFFFFF\" stroke-width=\"2.5\"/>\n \n <!-- Каляки-маляки (случайные линии) -->\n <path d=\"M 40% 20% Q 42% 22%, 40% 24% T 40% 28%\" \n fill=\"none\" stroke=\"#32CD32\" stroke-width=\"3\" stroke-linecap=\"round\"/>\n <path d=\"M 50% 60% L 53% 57% L 55% 60% L 57% 57%\" \n fill=\"none\" stroke=\"#FF1493\" stroke-width=\"3\" stroke-linecap=\"round\"/>\n \n <!-- Еще волнистые линии -->\n <path d=\"M 35% 85% Q 37% 83%, 39% 85% T 43% 85% T 47% 85%\" \n fill=\"none\" stroke=\"#FF4500\" stroke-width=\"3.5\" stroke-linecap=\"round\"/>\n </svg>\n `;\n\n // Адаптивные стили для контента (без фиксированных размеров)\n const containerStyle: React.CSSProperties = {\n ...styles.gmCenterScreen,\n width: \"100%\",\n height: \"100%\",\n padding: `${padding}px`,\n overflow: \"auto\",\n position: \"relative\",\n boxSizing: \"border-box\",\n background: \"transparent\",\n };\n\n // Условие для отображения логотипа (на desktop и планшетах)\n const shouldShowLogo = !isMobile && showLogo;\n\n // Мемоизированный логотип (рендерится вне условных блоков)\n const MemoizedLogo = useMemo(\n () => {\n // Скрываем логотип на мобильных устройствах в landscape режиме и на малых экранах\n const width = window.innerWidth;\n const height = window.innerHeight;\n if ((isMobile && width > height) || height < 700) {\n return null;\n }\n \n if (!shouldShowLogo) {\n return null;\n }\n \n const logoBaseUrl = logoUrl || (typeof window !== \"undefined\" && window.origin \n ? `${window.origin}/cloud/speakid/games/hangman/logo`\n : \"/cloud/speakid/games/hangman/logo\");\n \n return (\n <div style={{ ...styles.gmLogoFixed, position: \"absolute\", top: 16, left: 16, zIndex: 30 }}>\n <picture>\n <source\n srcSet={`${logoBaseUrl}.svg`}\n type=\"image/svg+xml\"\n />\n <img\n src={`${logoBaseUrl}.png`}\n alt=\"SPEAKID Logo\"\n style={styles.gmLogoImg}\n loading=\"lazy\"\n />\n </picture>\n </div>\n );\n },\n [isMobile, shouldShowLogo, logoUrl]\n );\n\n // Общая структура рендеринга (как в magic-sentence)\n const renderContent = () => {\n // Начальный экран лобби\n if (stage === \"lobby\") {\n return (\n <>\n {MemoizedLogo}\n <div dangerouslySetInnerHTML={{ __html: kidsDoodlesSvg }} />\n <h1 style={{ \n ...styles.gmHeadline1, \n fontSize: `${baseFontSize.headline1}px`, \n marginBottom: `${gap * 3}px`,\n position: \"relative\",\n zIndex: 1,\n }}>\n HANGMAN\n </h1>\n <button\n onClick={() => setStage(\"category\")}\n style={{\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontWeight: 500, // Medium для более заметности\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap * 1.2}px ${gap * 3}px`,\n borderRadius: `${borderRadius * 1.5}px`,\n position: \"relative\",\n zIndex: 1,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"#ec4c44\",\n color: \"#ffffff\",\n border: \"none\",\n cursor: \"pointer\",\n transition: \"background 0.2s ease, transform 0.1s ease\",\n boxShadow: \"0 2px 8px rgba(236, 76, 68, 0.2)\",\n minWidth: \"120px\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"#d43a32\";\n e.currentTarget.style.transform = \"translateY(-2px)\";\n e.currentTarget.style.boxShadow = \"0 4px 12px rgba(236, 76, 68, 0.3)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"#ec4c44\";\n e.currentTarget.style.transform = \"translateY(0)\";\n e.currentTarget.style.boxShadow = \"0 2px 8px rgba(236, 76, 68, 0.2)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.transform = \"translateY(0)\";\n }}\n >\n <svg\n width={`${baseFontSize.button * 1.3}px`}\n height={`${baseFontSize.button * 1.3}px`}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ display: \"block\", marginRight: `${gap}px` }}\n >\n <path\n d=\"M8 5V19L19 12L8 5Z\"\n fill=\"#ffffff\"\n stroke=\"none\"\n />\n </svg>\n <span style={{ fontWeight: 500 }}>PLAY</span>\n </button>\n <div style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n zIndex: 0,\n }}>\n <img\n src={`${imagesBaseURL}/sun.png`}\n alt=\"Sun\"\n style={{\n position: \"absolute\",\n left: isMobile ? \"-10%\" : \"5%\",\n top: \"20%\",\n width: \"auto\",\n height: isMobile \n ? `${Math.min(window.innerHeight * 0.33, 200)}px`\n : `${Math.min((containerSize || gameCubeSize || 1000) * 0.33, 300)}px`,\n maxHeight: \"33vh\",\n objectFit: \"contain\",\n opacity: 0.6,\n }}\n />\n <img\n src={`${imagesBaseURL}/character.png`}\n alt=\"Hangman character\"\n style={{\n position: \"absolute\",\n right: isMobile ? \"5%\" : \"10%\",\n bottom: \"10%\",\n width: \"auto\",\n height: isMobile \n ? `${Math.min(window.innerHeight * 0.33, 200)}px`\n : `${Math.min((containerSize || gameCubeSize || 1000) * 0.33, 300)}px`,\n maxHeight: \"33vh\",\n objectFit: \"contain\",\n opacity: 0.6,\n }}\n />\n </div>\n </>\n );\n }\n\n // Экран выбора категории\n if (stage === \"category\") {\n return (\n <>\n {MemoizedLogo}\n <div dangerouslySetInnerHTML={{ __html: kidsDoodlesSvg }} />\n <button\n onClick={() => setStage(\"lobby\")}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#e5e7eb\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#f9f9f9\";\n }}\n style={{\n ...styles.gmButton,\n ...styles.gmButtonSecondary,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n position: \"absolute\",\n top: `${padding}px`,\n left: `${padding + 100}px`, // ✅ Смещаем правее логотипа\n zIndex: 10,\n }}\n >\n ←\n </button>\n\n <div style={{ ...styles.gmButtonGroup, gap: `${gap}px`, marginBottom: `${gap * 3}px`, marginTop: `${gap * 4}px`, position: \"relative\", zIndex: 1 }}>\n {Object.keys(categories).map((cat) => {\n // Облачки с border вместо заливки\n return (\n <button\n key={cat}\n onClick={() => {\n setCategory(cat as keyof typeof categories);\n setStage(\"rounds\");\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#f0f0f0\";\n e.currentTarget.style.borderColor = \"#1f2937\";\n e.currentTarget.style.transform = \"scale(1.05)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"transparent\";\n e.currentTarget.style.borderColor = \"#e5e7eb\";\n e.currentTarget.style.transform = \"scale(1)\";\n }}\n style={{\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontWeight: 500,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap * 1.2}px ${gap * 2}px`,\n borderRadius: `${borderRadius * 2}px`, // Более округлые для облачков\n margin: `${gap / 2}px`,\n background: \"transparent\",\n border: \"2px solid #e5e7eb\",\n color: \"#1f2937\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease\",\n boxShadow: \"none\",\n }}\n >\n {cat}\n </button>\n );\n })}\n </div>\n </>\n );\n }\n\n // Экран выбора количества раундов\n if (stage === \"rounds\") {\n return (\n <>\n {MemoizedLogo}\n <div dangerouslySetInnerHTML={{ __html: kidsDoodlesSvg }} />\n <button\n onClick={() => setStage(\"category\")}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#e5e7eb\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#f9f9f9\";\n }}\n style={{\n ...styles.gmButton,\n ...styles.gmButtonSecondary,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n position: \"absolute\",\n top: `${padding}px`,\n left: `${padding + 100}px`, // ✅ Смещаем правее логотипа\n zIndex: 10,\n }}\n >\n ←\n </button>\n\n <h1 style={{ ...styles.gmHeadline1, fontSize: `${baseFontSize.headline1}px`, marginBottom: `${gap * 2}px`, position: \"relative\", zIndex: 1 }}>\n Choose rounds\n </h1>\n\n <div style={{ ...styles.gmButtonGroup, gap: `${gap}px`, marginBottom: `${gap * 3}px`, position: \"relative\", zIndex: 1 }}>\n {[1, 3, 5].map((r) => {\n // Облачки с border вместо заливки\n return (\n <button\n key={r}\n onClick={() => {\n setRounds(r);\n startGame();\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#f0f0f0\";\n e.currentTarget.style.borderColor = \"#1f2937\";\n e.currentTarget.style.transform = \"scale(1.05)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"transparent\";\n e.currentTarget.style.borderColor = \"#e5e7eb\";\n e.currentTarget.style.transform = \"scale(1)\";\n }}\n style={{\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontWeight: 500,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap * 1.2}px ${gap * 2}px`,\n borderRadius: `${borderRadius * 2}px`, // Более округлые для облачков\n margin: `${gap / 2}px`,\n background: \"transparent\",\n border: \"2px solid #e5e7eb\",\n color: \"#1f2937\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease\",\n boxShadow: \"none\",\n }}\n >\n {r}\n </button>\n );\n })}\n </div>\n </>\n );\n }\n\n // Игровой экран\n if (stage === \"game\") {\n return (\n <>\n {MemoizedLogo}\n <div style={{\n ...styles.gmInfoBox,\n padding: `${gap * 0.8}px`,\n marginBottom: `${gap * 0.5}px`,\n maxWidth: `${(containerSize || gameCubeSize) * 0.9}px`,\n }}>\n <h3 style={{ ...styles.gmHeadline3, fontSize: `${baseFontSize.headline3}px`, marginBottom: `${gap * 0.5}px` }}>\n Category: {category}\n </h3>\n <p style={{ ...styles.gmBodyM, fontSize: `${baseFontSize.bodyM}px`, marginBottom: `0px` }}>\n Round {currentRound} of {rounds}\n </p>\n </div>\n\n {word && (\n <p style={{\n ...styles.gmBodyS,\n fontSize: `${baseFontSize.bodyS}px`,\n marginTop: `${gap * 0.5}px`,\n marginBottom: `${gap}px`,\n }}>\n I am thinking of a word that is <strong>{word.length}</strong> letters long\n </p>\n )}\n\n {/* Визуализация виселицы */}\n <div style={{\n margin: `${gap}px 0`,\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}>\n <HangmanDrawing \n mistakes={mistakes} \n maxMistakes={maxMistakes}\n size={isNestHub \n ? Math.max(80, Math.min(110, (containerSize || gameCubeSize) * 0.16))\n : Math.max(100, Math.min(150, (containerSize || gameCubeSize) * 0.2))}\n />\n </div>\n\n <div style={{\n ...styles.gmWordDisplay,\n fontSize: `${Math.max(16, Math.min(24, baseFontSize.wordDisplay * 0.9))}px`,\n margin: `${gap}px 0`,\n letterSpacing: `${gap * 0.8}px`,\n minHeight: `${Math.max(16, Math.min(24, baseFontSize.wordDisplay * 0.9)) * 1.2}px`,\n }}>{masked || \"Loading...\"}</div>\n\n {/* Алфавит - вдохновлено getAvailableLetters */}\n <div style={{\n ...styles.gmInfoBox,\n padding: `${gap}px`,\n marginTop: `${gap}px`,\n marginBottom: `${gap}px`,\n maxWidth: `${(containerSize || gameCubeSize) * 0.95}px`,\n }}>\n <p style={{\n ...styles.gmBodyS,\n fontSize: `${baseFontSize.bodyS}px`,\n marginBottom: `${gap}px`,\n fontWeight: 500, // Medium\n }}>\n Available letters:\n </p>\n <div style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: `${gap / 3}px`,\n justifyContent: \"center\",\n fontSize: `${Math.max(9, Math.min(12, baseFontSize.bodyS * 0.75))}px`,\n fontFamily: '\"Onest\", system-ui, sans-serif',\n }}>\n {availableLetters.map((letter) => (\n <button\n key={letter}\n onClick={() => handleLetterSelect(letter)}\n disabled={roundResult !== null}\n onMouseEnter={(e) => {\n if (roundResult === null) {\n e.currentTarget.style.backgroundColor = \"#e5e7eb\";\n e.currentTarget.style.cursor = \"pointer\";\n }\n }}\n onMouseLeave={(e) => {\n if (roundResult === null) {\n e.currentTarget.style.backgroundColor = \"#f9f9f9\";\n e.currentTarget.style.cursor = \"pointer\";\n }\n }}\n style={{\n padding: `${gap / 4}px ${gap / 3}px`,\n borderRadius: `${borderRadius * 0.5}px`,\n background: \"#f9f9f9\",\n color: \"#1f2937\",\n border: \"1px solid #e5e7eb\",\n minWidth: `${Math.max(gap * 1.5, (containerSize || gameCubeSize) * 0.04)}px`,\n textAlign: \"center\",\n display: \"inline-block\",\n cursor: roundResult === null ? \"pointer\" : \"default\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontSize: `${Math.max(9, Math.min(12, baseFontSize.bodyS * 0.75))}px`,\n transition: \"background-color 0.2s ease\",\n }}\n >\n {letter}\n </button>\n ))}\n </div>\n </div>\n\n {/* Уже угаданные буквы */}\n {guessed.length > 0 && (\n <div style={{\n ...styles.gmGuessedLetters,\n fontSize: `${Math.max(10, Math.min(12, baseFontSize.bodyS * 0.85))}px`,\n marginTop: `${gap * 0.5}px`,\n marginBottom: `2px`,\n }}>\n <span style={{ color: \"#6b7280\" }}>\n Guessed letters: <strong>{guessed.join(\", \")}</strong>\n </span>\n </div>\n )}\n\n {roundResult === \"win\" && (\n <div style={{\n ...styles.gmStatusWin,\n fontSize: `${baseFontSize.bodyL}px`,\n margin: `2px 0`,\n }}>\n 🎉 You won this round!\n </div>\n )}\n\n {roundResult === \"lose\" && (\n <div style={{\n ...styles.gmStatusLose,\n fontSize: `${baseFontSize.bodyL}px`,\n margin: `2px 0`,\n }}>\n The hangman is complete! The word was: <strong>{word}</strong>\n </div>\n )}\n\n {roundResult !== null && currentRound < rounds && (\n <div style={{ marginTop: `2px`, marginBottom: `${gap}px` }}>\n <button\n onClick={nextRound}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#d43a32\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#ec4c44\";\n }}\n style={{\n ...styles.gmButton,\n fontSize: `${Math.max(11, Math.min(14, baseFontSize.button * 0.85))}px`,\n padding: `${gap * 0.6}px ${gap * 1.2}px`,\n borderRadius: `${borderRadius}px`,\n }}\n >\n NEXT\n </button>\n </div>\n )}\n\n {roundResult !== null && currentRound >= rounds && (\n <div style={{ marginTop: `2px`, marginBottom: `${gap}px` }}>\n <button\n onClick={() => setStage(\"result\")}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#d43a32\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#ec4c44\";\n }}\n style={{\n ...styles.gmButton,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n }}\n >\n View Results →\n </button>\n </div>\n )}\n\n {roundResult === null && guessed.length === 0 && (\n <p style={{\n ...styles.gmBodyS,\n fontSize: `${baseFontSize.bodyS}px`,\n marginTop: `${gap}px`,\n marginBottom: `${gap}px`,\n }}>\n Type a letter on your keyboard\n </p>\n )}\n </>\n );\n }\n\n // Экран результатов\n if (stage === \"result\") {\n return (\n <>\n {MemoizedLogo}\n <h1 style={{\n ...styles.gmHeadline1,\n fontSize: `${baseFontSize.headline1}px`,\n marginBottom: `${gap * 2}px`,\n }}>\n 🎊 Game Finished!\n </h1>\n <p style={{\n ...styles.gmBodyL,\n fontSize: `${baseFontSize.bodyL}px`,\n marginBottom: `${gap * 2}px`,\n }}>\n You guessed <strong>{wins}</strong> out of <strong>{rounds}</strong> words correctly.\n </p>\n \n <div style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: `${gap}px`,\n alignItems: \"center\",\n }}>\n <button\n onClick={() => {\n // Сбрасываем состояние и запускаем новую игру с той же категорией и раундами\n if (!category || rounds === 0) {\n setStage(\"lobby\");\n return;\n }\n \n setUsedWords([]);\n const randomWord = pickRandomWord(category as keyof typeof categories, []);\n if (randomWord) {\n setWord(randomWord);\n setUsedWords([randomWord]);\n setGuessed([]);\n setMistakes(0);\n setCurrentRound(1);\n setWins(0);\n setRoundResult(null);\n setStage(\"game\");\n }\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#d43a32\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#ec4c44\";\n }}\n style={{\n ...styles.gmButton,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n minWidth: \"200px\",\n }}\n >\n Play again\n </button>\n \n <button\n onClick={() => setStage(\"lobby\")}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#e5e7eb\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#f9f9f9\";\n }}\n style={{\n ...styles.gmButton,\n ...styles.gmButtonSecondary,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n minWidth: \"200px\",\n }}\n >\n Exit\n </button>\n </div>\n </>\n );\n }\n\n return null;\n };\n\n // Единый return с трехуровневой структурой (как в magic-sentence)\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n background: \"transparent\",\n overflow: \"hidden\",\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n }}\n >\n <div\n style={{\n width: isMobile ? \"100%\" : (containerSize || gameCubeSize || 1000),\n height: isMobile ? \"100%\" : (containerSize || gameCubeSize || 1000),\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n overflow: \"hidden\",\n borderRadius: isMobile ? 0 : \"20px\",\n background: \"#ffffff\",\n boxShadow: isMobile ? \"none\" : \"0 0 40px rgba(0,0,0,0.1)\",\n margin: isMobile ? \"0 auto\" : \"unset\",\n position: \"relative\", // needed so absolute logo is inside the square\n transform: `scale(${scale})`,\n }}\n >\n <div\n style={{\n transform: \"translateZ(0)\",\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n <div style={containerStyle}>\n {renderContent()}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n"],"names":["styles","HangmanDrawing","mistakes","maxMistakes","size","svgWidth","svgHeight","strokeWidth","baseX1","baseY","baseX2","poleX","poleY1","poleY2","topX1","topY","topX2","ropeX","ropeY1","ropeY2","headCX","headCY","headR","bodyX","bodyY1","bodyY2","leftArmX1","leftArmY1","leftArmX2","leftArmY2","rightArmX1","rightArmY1","rightArmX2","rightArmY2","leftLegX1","leftLegY1","leftLegX2","leftLegY2","rightLegX1","rightLegY1","rightLegX2","rightLegY2","strokeColor","jsxs","jsx","HangmanLobbyGame","gameCubeSize","screenHeight","screenWidth","logoUrl","showLogo","baseURL","categories","stage","setStage","useState","category","setCategory","difficulty","rounds","setRounds","currentRound","setCurrentRound","word","setWord","guessed","setGuessed","setMistakes","wins","setWins","roundResult","setRoundResult","containerSize","setContainerSize","scale","setScale","usedWords","setUsedWords","imagesBaseURL","isMobile","setIsMobile","isNestHub","setIsNestHub","baseFontSize","useMemo","fontSizeScale","padding","gap","borderRadius","isWordGuessed","secretWord","lettersGuessed","letter","getGuessedWord","getAvailableLetters","pickRandomWord","cat","avoidWords","firstCategory","_a","words","availableWords","w","wordsToChooseFrom","randomIndex","array","randomFloat","startGame","randomWord","handleLetterSelect","useCallback","lowerLetter","prevGuessed","currentWord","m","handleKey","useEffect","masked","isWin","isLose","availableLetters","moveToNextRound","r","prev","newWord","timer","nextRound","resize","width","height","mobile","isSmallHeight","isWideScreen","nestHub","finalSize","kidsDoodlesSvg","containerStyle","shouldShowLogo","MemoizedLogo","logoBaseUrl","renderContent","Fragment","e"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"speakid-hangman.cjs.js","sources":["../src/styles/style.ts","../src/components/HangmanLobbyGame.tsx"],"sourcesContent":["import { CSSProperties } from \"react\";\n\n// ===== Стили согласно визуальному гайдлайну: Onest, минималистичный, дружелюбный =====\n// Шрифт: Onest (Regular, Medium, SemiBold)\n// Стиль: Плоский, минималистичный, воздушный, без излишеств\n// Цвета: Мягкий контраст, дружелюбная палитра\n\nexport const styles: Record<string, CSSProperties> = {\n gmCenterScreen: {\n position: \"relative\",\n zIndex: 1,\n minHeight: \"100%\",\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n textAlign: \"center\",\n color: \"#1f2937\", // colorTextPrimary\n padding: \"24px 16px\",\n boxSizing: \"border-box\",\n fontFamily: '\"Onest\", system-ui, -apple-system, \"Segoe UI\", Roboto, Arial, sans-serif',\n background: \"transparent\", // Прозрачный по умолчанию, переопределяется в компоненте\n },\n // Desktop: Headline 1 - Onest SemiBold 32px, line-height 110%\n gmHeadline1: {\n fontWeight: 600, // SemiBold\n fontSize: \"clamp(30px, 4vw, 32px)\", // Mobile 30px, Desktop 32px\n lineHeight: \"110%\",\n marginBottom: \"24px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Headline 2 - Onest Medium 24px, line-height 110%\n gmHeadline2: {\n fontWeight: 500, // Medium\n fontSize: \"24px\",\n lineHeight: \"110%\",\n marginBottom: \"16px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Headline 3 - Onest Medium 24px, line-height 110%\n // Mobile: Headline 3 - Onest Medium 16px, line-height 110%\n gmHeadline3: {\n fontWeight: 500, // Medium\n fontSize: \"clamp(16px, 2vw, 24px)\", // Mobile 16px, Desktop 24px\n lineHeight: \"110%\",\n marginBottom: \"12px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Body L - Onest Regular 18px, line-height 120%\n gmBodyL: {\n fontWeight: 400, // Regular\n fontSize: \"18px\",\n lineHeight: \"120%\",\n marginBottom: \"12px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Body M - Onest Regular 16px, line-height 120%\n // Mobile: Body M - Onest Regular 14px, line-height 120%\n gmBodyM: {\n fontWeight: 400, // Regular\n fontSize: \"clamp(14px, 1.5vw, 16px)\", // Mobile 14px, Desktop 16px\n lineHeight: \"120%\",\n marginBottom: \"8px\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Desktop: Body S - Onest Regular 14px, line-height 120%\n // Mobile: Body S - Onest Regular 12px, line-height 120%\n gmBodyS: {\n fontWeight: 400, // Regular\n fontSize: \"clamp(12px, 1.5vw, 14px)\", // Mobile 12px, Desktop 14px\n lineHeight: \"120%\",\n color: \"#6b7280\", // colorTextSecondary\n marginBottom: \"8px\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n // Button: Onest Regular 16px, line-height 100%\n gmButton: {\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontWeight: 400, // Regular\n fontSize: \"16px\",\n lineHeight: \"100%\",\n padding: \"10px 16px\",\n borderRadius: \"8px\", // Более мягкие углы для минималистичного стиля\n border: \"1px solid #e5e7eb\", // colorSeparator\n background: \"#ec4c44\", // colorAccent (Default)\n color: \"#ffffff\", // colorTextContrast\n cursor: \"pointer\",\n boxShadow: \"none\", // Плоский стиль без теней\n transition: \"background-color 0.2s ease, opacity 0.2s ease, transform 0.1s ease\",\n margin: \"4px\",\n },\n gmButtonActive: {\n background: \"#333\", // colorAccent Active\n color: \"#fff\", // colorTextContrast\n boxShadow: \"none\", // Плоский стиль\n },\n gmButtonSecondary: {\n background: \"#f9f9f9\", // colorBackgroundAccent\n color: \"#1f2937\", // colorTextPrimary\n border: \"1px solid #e5e7eb\", // colorSeparator\n boxShadow: \"none\", // Плоский стиль\n },\n gmButtonGroup: {\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"8px\",\n justifyContent: \"center\",\n marginBottom: \"24px\",\n },\n gmWordDisplay: {\n fontSize: \"clamp(20px, 5vw, 28px)\",\n fontWeight: 500, // Medium\n letterSpacing: \"6px\",\n margin: \"32px 0\",\n color: \"#1f2937\", // colorTextPrimary\n fontFamily: '\"Onest\", system-ui, sans-serif',\n lineHeight: \"120%\",\n },\n gmGuessedLetters: {\n fontSize: \"clamp(12px, 1.5vw, 16px)\", // Body S / Body M\n color: \"#6b7280\", // colorTextSecondary\n marginTop: \"16px\",\n minHeight: \"24px\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n lineHeight: \"120%\",\n },\n gmStatusWin: {\n color: \"#10b981\", // colorTextPositive / colorIconPositive\n fontWeight: 500, // Medium\n fontSize: \"clamp(14px, 1.5vw, 18px)\", // Body M / Body L\n lineHeight: \"120%\",\n margin: \"16px 0\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n gmStatusLose: {\n color: \"#ec4c44\", // colorTextNegative / colorIconNegative\n fontWeight: 500, // Medium\n fontSize: \"clamp(14px, 1.5vw, 18px)\", // Body M / Body L\n lineHeight: \"120%\",\n margin: \"16px 0\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n },\n gmInfoBox: {\n background: \"#f9f9f9\", // colorBackgroundAccent\n border: \"1px solid #e5e7eb\", // colorSeparator\n borderRadius: \"8px\", // Мягкие углы\n padding: \"16px\",\n marginBottom: \"24px\",\n maxWidth: \"500px\",\n width: \"100%\",\n boxShadow: \"none\", // Плоский стиль\n },\n gmSection: {\n marginBottom: \"32px\",\n width: \"100%\",\n maxWidth: \"500px\",\n },\n // ✅ Обновлено только для качества логотипа (размер как в magic-sentence)\n gmLogoFixed: {\n position: \"absolute\",\n top: \"16px\",\n left: \"16px\",\n width: \"auto\",\n zIndex: 10,\n pointerEvents: \"none\",\n background: \"transparent\",\n transform: \"none\",\n willChange: \"auto\",\n },\n gmLogoImg: {\n height: \"28px\",\n width: \"auto\",\n background: \"transparent\",\n objectFit: \"contain\",\n imageRendering: \"auto\",\n transform: \"translateZ(0)\",\n backfaceVisibility: \"hidden\",\n WebkitFontSmoothing: \"antialiased\",\n display: \"block\",\n },\n gmLogoFallback: {\n height: \"28px\",\n width: \"auto\",\n background: \"transparent\",\n color: \"#ec4c44\",\n fontSize: \"16px\",\n fontWeight: 700,\n display: \"block\",\n },\n};\n\n// ===== Цветовая палитра для справки =====\n// colorTextPrimary: #1f2937\n// colorTextSecondary: #6b7280\n// colorTextNegative: #ec4c44\n// colorTextPositive: #10b981\n// colorBackgroundAccent: #f9f9f9\n// colorSeparator: #e5e7eb\n// colorAccent (Default): #ec4c44\n// colorAccent (Active): #333\n\n","import React, { useState, useEffect, useCallback, useMemo } from \"react\";\nimport { styles } from \"../styles/style\";\n\n// Компонент визуализации виселицы\nfunction HangmanDrawing({ \n mistakes, \n maxMistakes, \n size = 200 \n}: { \n mistakes: number; \n maxMistakes: number;\n size?: number;\n}) {\n // Адаптивные размеры SVG\n const svgWidth = size;\n const svgHeight = size * 1.25; // Соотношение 200:250\n const strokeWidth = Math.max(2, size / 100); // Адаптивная толщина линий\n \n // Координаты (пропорциональные исходному размеру 200x250)\n const baseX1 = 10 * (svgWidth / 200);\n const baseY = 240 * (svgHeight / 250);\n const baseX2 = 150 * (svgWidth / 200);\n \n const poleX = 80 * (svgWidth / 200);\n const poleY1 = 20 * (svgHeight / 250);\n const poleY2 = 240 * (svgHeight / 250);\n \n const topX1 = 80 * (svgWidth / 200);\n const topY = 20 * (svgHeight / 250);\n const topX2 = 150 * (svgWidth / 200);\n \n const ropeX = 150 * (svgWidth / 200);\n const ropeY1 = 20 * (svgHeight / 250);\n const ropeY2 = 50 * (svgHeight / 250);\n \n const headCX = 150 * (svgWidth / 200);\n const headCY = 70 * (svgHeight / 250);\n const headR = 20 * (svgWidth / 200);\n \n const bodyX = 150 * (svgWidth / 200);\n const bodyY1 = 90 * (svgHeight / 250);\n const bodyY2 = 150 * (svgHeight / 250);\n \n const leftArmX1 = 150 * (svgWidth / 200);\n const leftArmY1 = 110 * (svgHeight / 250);\n const leftArmX2 = 130 * (svgWidth / 200);\n const leftArmY2 = 130 * (svgHeight / 250);\n \n const rightArmX1 = 150 * (svgWidth / 200);\n const rightArmY1 = 110 * (svgHeight / 250);\n const rightArmX2 = 170 * (svgWidth / 200);\n const rightArmY2 = 130 * (svgHeight / 250);\n \n const leftLegX1 = 150 * (svgWidth / 200);\n const leftLegY1 = 150 * (svgHeight / 250);\n const leftLegX2 = 130 * (svgWidth / 200);\n const leftLegY2 = 190 * (svgHeight / 250);\n \n const rightLegX1 = 150 * (svgWidth / 200);\n const rightLegY1 = 150 * (svgHeight / 250);\n const rightLegX2 = 170 * (svgWidth / 200);\n const rightLegY2 = 190 * (svgHeight / 250);\n\n // Цвет в зависимости от количества ошибок\n const getStrokeColor = () => {\n if (mistakes === 0) return \"#1f2937\"; // colorTextPrimary\n if (mistakes <= maxMistakes * 0.5) return \"#1f2937\"; // Окей\n if (mistakes <= maxMistakes * 0.75) return \"#f59e0b\"; // Предупреждение\n return \"#ec4c44\"; // colorTextNegative - опасно\n };\n\n const strokeColor = getStrokeColor();\n\n return (\n <svg \n width={svgWidth} \n height={svgHeight} \n style={{ \n display: \"block\",\n margin: \"0 auto\",\n }}\n >\n {/* Виселица рисуется пошагово с ошибками */}\n {/* 1-я ошибка: Основание */}\n {mistakes > 0 && (\n <line \n x1={baseX1} \n y1={baseY} \n x2={baseX2} \n y2={baseY} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n\n {/* 2-я ошибка: Стойка */}\n {mistakes > 1 && (\n <line \n x1={poleX} \n y1={poleY1} \n x2={poleX} \n y2={poleY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n\n {/* 3-я ошибка: Верхняя перекладина */}\n {mistakes > 2 && (\n <line \n x1={topX1} \n y1={topY} \n x2={topX2} \n y2={topY} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n\n {/* 4-я ошибка: Веревка */}\n {mistakes > 3 && (\n <line \n x1={ropeX} \n y1={ropeY1} \n x2={ropeX} \n y2={ropeY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n\n {/* 5-я ошибка: Голова */}\n {mistakes > 4 && (\n <circle \n cx={headCX} \n cy={headCY} \n r={headR} \n stroke={strokeColor} \n fill=\"none\" \n strokeWidth={strokeWidth}\n />\n )}\n \n {/* 6-я ошибка: Тело */}\n {mistakes > 5 && (\n <line \n x1={bodyX} \n y1={bodyY1} \n x2={bodyX} \n y2={bodyY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n \n {/* Дополнительные части (если maxMistakes больше 6) */}\n {mistakes > 6 && (\n <line \n x1={leftArmX1} \n y1={leftArmY1} \n x2={leftArmX2} \n y2={leftArmY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n \n {mistakes > 7 && (\n <line \n x1={rightArmX1} \n y1={rightArmY1} \n x2={rightArmX2} \n y2={rightArmY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n \n {mistakes > 8 && (\n <line \n x1={leftLegX1} \n y1={leftLegY1} \n x2={leftLegX2} \n y2={leftLegY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n \n {mistakes > 9 && (\n <line \n x1={rightLegX1} \n y1={rightLegY1} \n x2={rightLegX2} \n y2={rightLegY2} \n stroke={strokeColor} \n strokeWidth={strokeWidth}\n />\n )}\n </svg>\n );\n}\n\nexport interface HangmanLobbyGameProps {\n gameCubeSize?: number;\n screenHeight?: number;\n screenWidth?: number;\n logoUrl?: string;\n showLogo?: boolean;\n baseURL?: string;\n}\n\nexport default function HangmanLobbyGame({\n gameCubeSize = 400,\n screenHeight = 800,\n screenWidth = 800,\n logoUrl,\n showLogo = true,\n baseURL,\n}: HangmanLobbyGameProps = {}) {\n const categories = {\n Professions: [\"teacher\", \"doctor\", \"nurse\", \"driver\", \"police\", \"firefighter\", \"cook\", \"waiter\", \"farmer\", \"builder\", \"singer\", \"actor\", \"dentist\", \"pilot\", \"vet\", \"artist\", \"cleaner\", \"student\", \"baker\", \"mechanic\"],\n Family: [\"mother\", \"father\", \"sister\", \"brother\", \"grandmother\", \"grandfather\", \"aunt\", \"uncle\", \"cousin\", \"baby\", \"parents\", \"children\", \"wife\", \"husband\", \"son\", \"daughter\", \"family\", \"twins\", \"relatives\"],\n \"Farm animals\": [\"cow\", \"pig\", \"horse\", \"sheep\", \"goat\", \"duck\", \"chicken\", \"rooster\", \"turkey\", \"goose\", \"rabbit\", \"mouse\", \"donkey\", \"bee\", \"hen\", \"lamb\", \"bull\", \"pony\"],\n Food: [\"apple\", \"banana\", \"bread\", \"cheese\", \"milk\", \"egg\", \"rice\", \"soup\", \"fish\", \"meat\", \"potato\", \"carrot\", \"tomato\", \"cucumber\", \"butter\", \"cake\", \"salad\", \"pasta\", \"pizza\", \"juice\"],\n Hobbies: [\"reading\", \"drawing\", \"painting\", \"dancing\", \"singing\", \"cooking\", \"swimming\", \"fishing\", \"running\", \"cycling\", \"skating\", \"writing\", \"camping\", \"photography\", \"hiking\", \"games\"],\n Christmas: [\"tree\", \"present\", \"gift\", \"santa\", \"snow\", \"snowman\", \"bell\", \"star\", \"lights\", \"card\", \"cookies\", \"elf\", \"sleigh\", \"reindeer\", \"candle\", \"stocking\"],\n Halloween: [\"pumpkin\", \"costume\", \"candy\", \"ghost\", \"witch\", \"spider\", \"bat\", \"skeleton\", \"mask\", \"monster\", \"mummy\", \"cat\", \"broom\", \"zombie\", \"trick\", \"treat\", \"candle\", \"night\", \"party\"],\n Sport: [\"football\", \"basketball\", \"tennis\", \"swimming\", \"running\", \"baseball\", \"skiing\", \"skating\", \"volleyball\", \"hockey\", \"golf\", \"boxing\", \"cycling\", \"rugby\", \"karate\", \"yoga\", \"surfing\", \"climbing\", \"dancing\", \"gym\", \"chess\"],\n \"Body parts\": [\"head\", \"hair\", \"eyes\", \"ears\", \"nose\", \"mouth\", \"teeth\", \"tongue\", \"neck\", \"shoulder\", \"arm\", \"hand\", \"finger\", \"leg\", \"knee\", \"foot\", \"toe\", \"back\", \"stomach\", \"heart\", \"legs\", \"nails\", \"chin\", \"beard\"],\n \"School subjects\": [\"math\", \"english\", \"history\", \"geography\", \"art\", \"music\", \"science\", \"biology\", \"chemistry\", \"physics\", \"pe\", \"literature\", \"drama\", \"design\", \"economics\"],\n Animals: [\"cat\", \"dog\", \"rabbit\", \"elephant\", \"lion\", \"tiger\", \"monkey\", \"bear\", \"fox\", \"wolf\", \"giraffe\", \"zebra\", \"crocodile\", \"dolphin\", \"whale\", \"shark\", \"frog\", \"parrot\", \"mouse\", \"penguin\", \"deer\", \"lizard\", \"turtle\", \"snake\"],\n Countries: [\"russia\", \"canada\", \"china\", \"japan\", \"france\", \"germany\", \"italy\", \"spain\", \"brazil\", \"india\", \"australia\", \"america\", \"england\", \"korea\", \"mexico\", \"egypt\", \"turkey\", \"vietnam\", \"norway\", \"finland\", \"thailand\", \"georgia\", \"kazakhstan\"],\n Clothes: [\"shirt\", \"dress\", \"skirt\", \"trousers\", \"jeans\", \"coat\", \"jacket\", \"sweater\", \"socks\", \"shoes\", \"boots\", \"hat\", \"scarf\", \"gloves\", \"shorts\", \"cap\", \"belt\", \"tie\", \"uniform\", \"pants\", \"underwear\"],\n Traveling: [\"ticket\", \"luggage\", \"suitcase\", \"airport\", \"flight\", \"passport\", \"visa\", \"map\", \"guide\", \"hotel\", \"reservation\", \"bus\", \"train\", \"taxi\", \"tourist\", \"sightseeing\", \"backpack\", \"journey\", \"adventure\", \"beach\", \"tour\", \"souvenir\"],\n Environment: [\"tree\", \"forest\", \"air\", \"water\", \"pollution\", \"recycle\", \"nature\", \"clean\", \"waste\", \"plastic\", \"energy\", \"animal\", \"climate\", \"earth\", \"ocean\", \"river\", \"planet\", \"save\", \"green\", \"environment\", \"litter\", \"organic\"],\n Space: [\"planet\", \"star\", \"sun\", \"moon\", \"astronaut\", \"rocket\", \"space\", \"galaxy\", \"universe\", \"telescope\", \"comet\", \"asteroid\", \"orbit\", \"gravity\", \"alien\", \"spaceship\", \"mars\", \"satellite\", \"sky\", \"eclipse\"],\n Devices: [\"computer\", \"laptop\", \"phone\", \"tablet\", \"tv\", \"keyboard\", \"mouse\", \"printer\", \"camera\", \"headphones\", \"charger\", \"screen\", \"watch\", \"microphone\", \"speaker\", \"console\", \"router\", \"battery\", \"cable\", \"remote\"],\n };\n\n const [stage, setStage] = useState<\"lobby\" | \"category\" | \"rounds\" | \"game\" | \"result\">(\"lobby\");\n const [category, setCategory] = useState<keyof typeof categories | \"\">(\"\");\n const [difficulty] = useState<\"Easy\" | \"Normal\" | \"Hard\">(\"Normal\"); // Фиксированная сложность\n const [rounds, setRounds] = useState(0); // 0 означает \"не выбрано\"\n const [currentRound, setCurrentRound] = useState(1);\n const [word, setWord] = useState(\"\");\n const [guessed, setGuessed] = useState<string[]>([]);\n const [mistakes, setMistakes] = useState(0);\n const [wins, setWins] = useState(0);\n const [roundResult, setRoundResult] = useState<\"win\" | \"lose\" | null>(null);\n const [containerSize, setContainerSize] = useState<number | null>(null);\n const [scale, setScale] = useState(1);\n const [usedWords, setUsedWords] = useState<string[]>([]); // Отслеживание использованных слов\n\n const maxMistakes = difficulty === \"Easy\" ? 8 : difficulty === \"Normal\" ? 6 : 4;\n\n // Вычисляем baseURL для изображений\n const imagesBaseURL = baseURL || (typeof window !== \"undefined\" && window.origin \n ? `${window.origin}/cloud/speakid/games/hangman`\n : \"/cloud/speakid/games/hangman\");\n\n // Определение мобильного устройства - используем window напрямую (как в magic-sentence)\n const [isMobile, setIsMobile] = useState(false);\n const [isNestHub, setIsNestHub] = useState(false);\n\n // Адаптивные размеры относительно gameCubeSize согласно визуальному гайдлайну\n // Desktop базовые размеры: Headline 1 - 32px, Headline 2 - 24px, Body M - 16px, Button - 16px\n // Mobile базовые размеры: Headline 1 - 30px, Headline 3 - 16px, Body M - 14px\n const baseFontSize = useMemo(() => {\n const fontSizeScale = (containerSize || gameCubeSize || 1000) / 400; // базовый размер 400px\n return {\n headline1: isMobile \n ? Math.max(24, Math.min(30, 30 * fontSizeScale)) // Mobile: 30px\n : Math.max(28, Math.min(32, 32 * fontSizeScale)), // Desktop: 32px\n headline2: Math.max(20, Math.min(28, 24 * fontSizeScale)), // Desktop: 24px\n headline3: isMobile\n ? Math.max(14, Math.min(18, 16 * fontSizeScale)) // Mobile: 16px\n : Math.max(20, Math.min(26, 24 * fontSizeScale)), // Desktop: 24px\n bodyL: Math.max(14, Math.min(20, 18 * fontSizeScale)), // Desktop: 18px\n bodyM: isMobile\n ? Math.max(12, Math.min(16, 14 * fontSizeScale)) // Mobile: 14px\n : Math.max(14, Math.min(18, 16 * fontSizeScale)), // Desktop: 16px\n bodyS: isMobile\n ? Math.max(10, Math.min(14, 12 * fontSizeScale)) // Mobile: 12px\n : Math.max(12, Math.min(16, 14 * fontSizeScale)), // Desktop: 14px\n wordDisplay: Math.max(18, Math.min(32, 26 * fontSizeScale)), // Адаптивный размер\n button: Math.max(12, Math.min(18, 16 * fontSizeScale)), // Desktop: 16px\n };\n }, [isMobile, containerSize, gameCubeSize]);\n\n // Адаптивные отступы и размеры (минималистичный стиль - мягкие углы)\n // Специальные настройки для Nest Hub (1024x600)\n const padding = useMemo(() => {\n const fontSizeScale = (containerSize || gameCubeSize || 1000) / 400;\n return isNestHub \n ? Math.max(8, Math.min(12, 10 * fontSizeScale))\n : Math.max(12, Math.min(24, 16 * fontSizeScale));\n }, [isNestHub, containerSize, gameCubeSize]);\n const gap = useMemo(() => {\n const fontSizeScale = (containerSize || gameCubeSize || 1000) / 400;\n return isNestHub\n ? Math.max(3, Math.min(6, 5 * fontSizeScale))\n : Math.max(4, Math.min(12, 8 * fontSizeScale));\n }, [isNestHub, containerSize, gameCubeSize]);\n const borderRadius = useMemo(() => {\n const fontSizeScale = (containerSize || gameCubeSize || 1000) / 400;\n return Math.max(6, Math.min(10, 8 * fontSizeScale));\n }, [containerSize, gameCubeSize]); // Мягкие углы для плоского стиля\n\n // Функции вдохновленные открытым кодом Hangman\n const isWordGuessed = (secretWord: string, lettersGuessed: string[]): boolean => {\n // Проверяем, все ли буквы слова угаданы\n return secretWord.split(\"\").every(letter => lettersGuessed.includes(letter));\n };\n\n const getGuessedWord = (secretWord: string, lettersGuessed: string[]): string => {\n // Возвращает строку с угаданными буквами и подчеркиваниями\n return secretWord\n .split(\"\")\n .map(letter => (lettersGuessed.includes(letter) ? letter : \"_\"))\n .join(\" \");\n };\n\n const getAvailableLetters = (lettersGuessed: string[]): string[] => {\n // Возвращает массив доступных букв (не угаданных)\n const alphabet = \"abcdefghijklmnopqrstuvwxyz\".split(\"\");\n return alphabet.filter(letter => !lettersGuessed.includes(letter));\n };\n\n const pickRandomCategory = (): keyof typeof categories => {\n const categoryKeys = Object.keys(categories) as Array<keyof typeof categories>;\n \n // Используем crypto.getRandomValues для более надежной случайности\n let randomIndex: number;\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const array = new Uint32Array(1);\n crypto.getRandomValues(array);\n randomIndex = array[0] % categoryKeys.length;\n } else {\n // Fallback на Math.random если crypto недоступен\n randomIndex = Math.floor(Math.random() * categoryKeys.length);\n }\n \n return categoryKeys[randomIndex];\n };\n\n const pickRandomWord = (cat: keyof typeof categories, avoidWords: string[] = []): string => {\n if (!cat || !categories[cat]) {\n // Fallback если категория пустая или не существует\n const firstCategory = Object.keys(categories)[0] as keyof typeof categories;\n return categories[firstCategory]?.[0] || \"\";\n }\n \n const words = categories[cat];\n if (!words || words.length === 0) {\n // Fallback если слова пустые\n return \"\";\n }\n \n // Если есть доступные слова (не использованные), выбираем из них\n const availableWords = words.filter(w => !avoidWords.includes(w));\n const wordsToChooseFrom = availableWords.length > 0 ? availableWords : words;\n \n if (wordsToChooseFrom.length === 0) {\n return \"\";\n }\n \n // Используем crypto.getRandomValues для более надежной случайности\n // Преобразуем в дробное число от 0 до 1 для равномерного распределения\n let randomIndex: number;\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const array = new Uint32Array(1);\n crypto.getRandomValues(array);\n // Преобразуем в дробное число от 0 до 1 для равномерного распределения\n const randomFloat = array[0] / 0xFFFFFFFF;\n randomIndex = Math.floor(randomFloat * wordsToChooseFrom.length);\n } else {\n // Fallback на Math.random если crypto недоступен\n randomIndex = Math.floor(Math.random() * wordsToChooseFrom.length);\n }\n \n return wordsToChooseFrom[randomIndex];\n };\n\n const startGame = () => {\n if (!category) return;\n setUsedWords([]); // Сбрасываем список использованных слов при новой игре\n const randomWord = pickRandomWord(category, []);\n if (!randomWord) {\n // Если не удалось выбрать слово, возвращаемся к выбору категории\n setStage(\"category\");\n return;\n }\n setWord(randomWord);\n setUsedWords([randomWord]); // Запоминаем первое слово\n setGuessed([]);\n setMistakes(0);\n setCurrentRound(1);\n setWins(0);\n setRoundResult(null);\n setStage(\"game\");\n };\n\n // Функция для обработки выбора буквы (используется и для клавиатуры, и для кликов)\n const handleLetterSelect = useCallback((letter: string) => {\n if (stage !== \"game\" || roundResult !== null) return;\n \n const lowerLetter = letter.toLowerCase();\n \n // Проверка: только буквы английского алфавита\n if (!/^[a-z]$/.test(lowerLetter)) return;\n \n // Проверяем, была ли буква уже угадана\n setGuessed((prevGuessed) => {\n if (prevGuessed.includes(lowerLetter)) {\n return prevGuessed;\n }\n \n // Добавляем букву в список угаданных\n return [...prevGuessed, lowerLetter];\n });\n \n // Проверяем, есть ли буква в текущем слове (используем функциональное обновление)\n setWord((currentWord) => {\n if (currentWord && !currentWord.includes(lowerLetter)) {\n setMistakes((m) => m + 1);\n }\n return currentWord;\n });\n }, [stage, roundResult]);\n\n const handleKey = useCallback((e: KeyboardEvent) => {\n handleLetterSelect(e.key);\n }, [handleLetterSelect]);\n\n useEffect(() => {\n if (stage === \"game\") {\n window.addEventListener(\"keydown\", handleKey);\n return () => window.removeEventListener(\"keydown\", handleKey);\n }\n }, [stage, handleKey]);\n\n // Используем функцию из открытого кода\n const masked = word ? getGuessedWord(word, guessed) : \"\";\n const isWin = word ? isWordGuessed(word, guessed) : false;\n // Игра проиграна когда виселица полностью нарисована (10 частей: основание, стойка, перекладина, веревка, голова, тело, левая рука, правая рука, левая нога, правая нога)\n const isLose = mistakes >= 10;\n const availableLetters = getAvailableLetters(guessed);\n\n // Функция для перехода к следующему раунду (вынесена для избежания дублирования)\n const moveToNextRound = useCallback(() => {\n if (!category || currentRound >= rounds) {\n setStage(\"result\");\n return;\n }\n \n setCurrentRound((r) => r + 1);\n setUsedWords((prev) => {\n const newWord = pickRandomWord(category as keyof typeof categories, prev);\n if (newWord) {\n setWord(newWord);\n return [...prev, newWord];\n }\n return prev;\n });\n setGuessed([]);\n setMistakes(0);\n setRoundResult(null);\n }, [category, currentRound, rounds]);\n\n useEffect(() => {\n if (isWin && roundResult === null) {\n setRoundResult(\"win\");\n setWins((w) => w + 1);\n \n const timer = setTimeout(() => {\n moveToNextRound();\n }, 2000);\n \n return () => clearTimeout(timer);\n }\n \n if (isLose && roundResult === null) {\n setRoundResult(\"lose\");\n \n const timer = setTimeout(() => {\n moveToNextRound();\n }, 2000);\n \n return () => clearTimeout(timer);\n }\n }, [isWin, isLose, roundResult, moveToNextRound]);\n\n const nextRound = () => {\n if (!category || currentRound >= rounds) {\n setStage(\"result\");\n return;\n }\n \n setCurrentRound((r) => r + 1);\n setUsedWords((prev) => {\n const newWord = pickRandomWord(category as keyof typeof categories, prev);\n if (newWord) {\n setWord(newWord);\n return [...prev, newWord]; // Добавляем новое слово в список использованных\n }\n return prev;\n });\n setGuessed([]);\n setMistakes(0);\n setRoundResult(null);\n };\n\n // ✅ Адаптив под мобилки, планшеты и десктоп (как в magic-sentence)\n useEffect(() => {\n const resize = () => {\n const width = window.innerWidth;\n const height = window.innerHeight;\n const mobile = width < 768 || (width === 926 && height === 428) || (width === 932 && height === 430);\n const isSmallHeight = height < 700;\n const isWideScreen = width / height > 1.8;\n const nestHub = width === 1024 && height === 600;\n \n setIsMobile(mobile);\n setIsNestHub(nestHub);\n\n // ✅ Адаптивные размеры контейнера\n // Если передан gameCubeSize, используем его (но с ограничениями)\n if (gameCubeSize && gameCubeSize >= 320) {\n const minSize = 320;\n const maxSize = 1200;\n const finalSize = Math.max(minSize, Math.min(maxSize, gameCubeSize));\n setContainerSize(finalSize);\n setScale(1);\n } else if (mobile) {\n setContainerSize(null);\n setScale(1);\n } else if (isSmallHeight) {\n setContainerSize(null);\n setScale(1);\n } else if (isWideScreen) {\n // ✅ Широкие экраны: используем стандартный размер но уменьшаем масштаб\n const minSize = 400;\n const maxSize = 1200;\n const finalSize = Math.min(1000, Math.min(width, height) * 0.9);\n setContainerSize(finalSize);\n setScale(0.85);\n } else {\n const minSize = 400;\n const maxSize = 1200;\n const finalSize = Math.min(1000, Math.min(width, height) * 0.9);\n setContainerSize(finalSize);\n setScale(1);\n }\n };\n resize();\n window.addEventListener(\"resize\", resize);\n return () => window.removeEventListener(\"resize\", resize);\n }, [gameCubeSize]);\n\n // SVG с детскими каракулями для фона (более резкие и яркие)\n const kidsDoodlesSvg = `\n <svg width=\"100%\" height=\"100%\" xmlns=\"http://www.w3.org/2000/svg\" style=\"position: absolute; top: 0; left: 0; pointer-events: none; opacity: 0.2;\">\n <!-- Каракули мелками и фломастерами -->\n \n <!-- Сердечко -->\n <path d=\"M 85% 15% Q 85% 10%, 90% 10% Q 95% 10%, 95% 15% Q 95% 20%, 90% 25% Q 85% 30%, 85% 15%\" \n fill=\"none\" stroke=\"#FF69B4\" stroke-width=\"3\" stroke-linecap=\"round\"/>\n \n <!-- Звезда -->\n <path d=\"M 10% 85% L 12% 80% L 14% 85% L 18% 85% L 13% 88% L 15% 92% L 10% 89% L 5% 92% L 7% 88% L 2% 85% Z\" \n fill=\"#FFA500\" stroke=\"#FF8C00\" stroke-width=\"1.5\"/>\n \n <!-- Волнистые линии (мелки) -->\n <path d=\"M 20% 25% Q 22% 23%, 24% 25% T 28% 25% T 32% 25%\" \n fill=\"none\" stroke=\"#FF6B6B\" stroke-width=\"3.5\" stroke-linecap=\"round\"/>\n <path d=\"M 60% 30% Q 62% 28%, 64% 30% T 68% 30% T 72% 30%\" \n fill=\"none\" stroke=\"#4ECDC4\" stroke-width=\"3.5\" stroke-linecap=\"round\"/>\n \n <!-- Спираль -->\n <path d=\"M 5% 45% Q 8% 42%, 10% 45% Q 12% 48%, 10% 50% Q 8% 52%, 5% 50% Q 3% 48%, 5% 45%\" \n fill=\"none\" stroke=\"#9B59B6\" stroke-width=\"3\" stroke-linecap=\"round\"/>\n \n <!-- Зигзаг -->\n <path d=\"M 88% 55% L 92% 50% L 94% 55% L 96% 50% L 98% 55%\" \n fill=\"none\" stroke=\"#E74C3C\" stroke-width=\"3.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n \n <!-- Ромашка -->\n <circle cx=\"25%\" cy=\"70%\" r=\"15\" fill=\"none\" stroke=\"#FFD700\" stroke-width=\"2.5\"/>\n <circle cx=\"25%\" cy=\"70%\" r=\"8\" fill=\"#FFD700\"/>\n <line x1=\"25%\" y1=\"70%\" x2=\"22%\" y2=\"65%\" stroke=\"#FFFFFF\" stroke-width=\"2.5\"/>\n <line x1=\"25%\" y1=\"70%\" x2=\"28%\" y2=\"65%\" stroke=\"#FFFFFF\" stroke-width=\"2.5\"/>\n <line x1=\"25%\" y1=\"70%\" x2=\"22%\" y2=\"75%\" stroke=\"#FFFFFF\" stroke-width=\"2.5\"/>\n <line x1=\"25%\" y1=\"70%\" x2=\"28%\" y2=\"75%\" stroke=\"#FFFFFF\" stroke-width=\"2.5\"/>\n \n <!-- Каляки-маляки (случайные линии) -->\n <path d=\"M 40% 20% Q 42% 22%, 40% 24% T 40% 28%\" \n fill=\"none\" stroke=\"#32CD32\" stroke-width=\"3\" stroke-linecap=\"round\"/>\n <path d=\"M 50% 60% L 53% 57% L 55% 60% L 57% 57%\" \n fill=\"none\" stroke=\"#FF1493\" stroke-width=\"3\" stroke-linecap=\"round\"/>\n \n <!-- Еще волнистые линии -->\n <path d=\"M 35% 85% Q 37% 83%, 39% 85% T 43% 85% T 47% 85%\" \n fill=\"none\" stroke=\"#FF4500\" stroke-width=\"3.5\" stroke-linecap=\"round\"/>\n </svg>\n `;\n\n // Адаптивные стили для контента (без фиксированных размеров)\n const containerStyle: React.CSSProperties = {\n ...styles.gmCenterScreen,\n width: \"100%\",\n height: \"100%\",\n padding: `${padding}px`,\n overflow: \"auto\",\n position: \"relative\",\n boxSizing: \"border-box\",\n background: \"transparent\",\n };\n\n // Условие для отображения логотипа (на desktop и планшетах)\n const shouldShowLogo = !isMobile && showLogo;\n\n // Мемоизированный логотип (рендерится вне условных блоков)\n const MemoizedLogo = useMemo(\n () => {\n // Скрываем логотип на мобильных устройствах в landscape режиме и на малых экранах\n const width = window.innerWidth;\n const height = window.innerHeight;\n if ((isMobile && width > height) || height < 700) {\n return null;\n }\n \n if (!shouldShowLogo) {\n return null;\n }\n \n const logoBaseUrl = logoUrl || (typeof window !== \"undefined\" && window.origin \n ? `${window.origin}/cloud/speakid/games/hangman/logo`\n : \"/cloud/speakid/games/hangman/logo\");\n \n return (\n <div style={{ ...styles.gmLogoFixed, position: \"absolute\", top: 16, left: 16, zIndex: 30 }}>\n <picture>\n <source\n srcSet={`${logoBaseUrl}.svg`}\n type=\"image/svg+xml\"\n />\n <img\n src={`${logoBaseUrl}.png`}\n alt=\"SPEAKID Logo\"\n style={styles.gmLogoImg}\n loading=\"lazy\"\n />\n </picture>\n </div>\n );\n },\n [isMobile, shouldShowLogo, logoUrl]\n );\n\n // Общая структура рендеринга (как в magic-sentence)\n const renderContent = () => {\n // Начальный экран лобби\n if (stage === \"lobby\") {\n return (\n <>\n {MemoizedLogo}\n <div dangerouslySetInnerHTML={{ __html: kidsDoodlesSvg }} />\n <h1 style={{ \n ...styles.gmHeadline1, \n fontSize: `${baseFontSize.headline1}px`, \n marginBottom: `${gap * 3}px`,\n position: \"relative\",\n zIndex: 1,\n }}>\n HANGMAN\n </h1>\n <button\n onClick={() => setStage(\"category\")}\n style={{\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontWeight: 500, // Medium для более заметности\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap * 1.2}px ${gap * 3}px`,\n borderRadius: `${borderRadius * 1.5}px`,\n position: \"relative\",\n zIndex: 1,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"#ec4c44\",\n color: \"#ffffff\",\n border: \"none\",\n cursor: \"pointer\",\n transition: \"background 0.2s ease, transform 0.1s ease\",\n boxShadow: \"0 2px 8px rgba(236, 76, 68, 0.2)\",\n minWidth: \"120px\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"#d43a32\";\n e.currentTarget.style.transform = \"translateY(-2px)\";\n e.currentTarget.style.boxShadow = \"0 4px 12px rgba(236, 76, 68, 0.3)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"#ec4c44\";\n e.currentTarget.style.transform = \"translateY(0)\";\n e.currentTarget.style.boxShadow = \"0 2px 8px rgba(236, 76, 68, 0.2)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.transform = \"translateY(0)\";\n }}\n >\n <svg\n width={`${baseFontSize.button * 1.3}px`}\n height={`${baseFontSize.button * 1.3}px`}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ display: \"block\", marginRight: `${gap}px` }}\n >\n <path\n d=\"M8 5V19L19 12L8 5Z\"\n fill=\"#ffffff\"\n stroke=\"none\"\n />\n </svg>\n <span style={{ fontWeight: 500 }}>PLAY</span>\n </button>\n <div style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n zIndex: 0,\n }}>\n <img\n src={`${imagesBaseURL}/sun.png`}\n alt=\"Sun\"\n style={{\n position: \"absolute\",\n left: isMobile ? \"-10%\" : \"5%\",\n top: \"20%\",\n width: \"auto\",\n height: isMobile \n ? `${Math.min(window.innerHeight * 0.33, 200)}px`\n : `${Math.min((containerSize || gameCubeSize || 1000) * 0.33, 300)}px`,\n maxHeight: \"33vh\",\n objectFit: \"contain\",\n opacity: 0.6,\n }}\n />\n <img\n src={`${imagesBaseURL}/character.png`}\n alt=\"Hangman character\"\n style={{\n position: \"absolute\",\n right: isMobile ? \"5%\" : \"10%\",\n bottom: \"10%\",\n width: \"auto\",\n height: isMobile \n ? `${Math.min(window.innerHeight * 0.33, 200)}px`\n : `${Math.min((containerSize || gameCubeSize || 1000) * 0.33, 300)}px`,\n maxHeight: \"33vh\",\n objectFit: \"contain\",\n opacity: 0.6,\n }}\n />\n </div>\n </>\n );\n }\n\n // Экран выбора категории\n if (stage === \"category\") {\n return (\n <>\n {MemoizedLogo}\n <div dangerouslySetInnerHTML={{ __html: kidsDoodlesSvg }} />\n <button\n onClick={() => setStage(\"lobby\")}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#e5e7eb\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#f9f9f9\";\n }}\n style={{\n ...styles.gmButton,\n ...styles.gmButtonSecondary,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n position: \"absolute\",\n top: `${padding}px`,\n left: \"160px\", // ✅ Фиксированное смещение правее логотипа (16px + ~120px логотип + 24px отступ)\n zIndex: 10,\n }}\n >\n ←\n </button>\n\n <div style={{ ...styles.gmButtonGroup, gap: `${gap}px`, marginBottom: `${gap * 3}px`, marginTop: `${gap * 4}px`, position: \"relative\", zIndex: 1 }}>\n {Object.keys(categories).map((cat) => {\n // Облачки с border вместо заливки\n return (\n <button\n key={cat}\n onClick={() => {\n setCategory(cat as keyof typeof categories);\n setStage(\"rounds\");\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#f0f0f0\";\n e.currentTarget.style.borderColor = \"#1f2937\";\n e.currentTarget.style.transform = \"scale(1.05)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"transparent\";\n e.currentTarget.style.borderColor = \"#e5e7eb\";\n e.currentTarget.style.transform = \"scale(1)\";\n }}\n style={{\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontWeight: 500,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap * 1.2}px ${gap * 2}px`,\n borderRadius: `${borderRadius * 2}px`, // Более округлые для облачков\n margin: `${gap / 2}px`,\n background: \"transparent\",\n border: \"2px solid #e5e7eb\",\n color: \"#1f2937\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease\",\n boxShadow: \"none\",\n }}\n >\n {cat}\n </button>\n );\n })}\n </div>\n </>\n );\n }\n\n // Экран выбора количества раундов\n if (stage === \"rounds\") {\n return (\n <>\n {MemoizedLogo}\n <div dangerouslySetInnerHTML={{ __html: kidsDoodlesSvg }} />\n <button\n onClick={() => setStage(\"category\")}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#e5e7eb\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#f9f9f9\";\n }}\n style={{\n ...styles.gmButton,\n ...styles.gmButtonSecondary,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n position: \"absolute\",\n top: `${padding}px`,\n left: \"160px\", // ✅ Фиксированное смещение правее логотипа (16px + ~120px логотип + 24px отступ)\n zIndex: 10,\n }}\n >\n ←\n </button>\n\n <h1 style={{ ...styles.gmHeadline1, fontSize: `${baseFontSize.headline1}px`, marginBottom: `${gap * 2}px`, position: \"relative\", zIndex: 1 }}>\n Choose rounds\n </h1>\n\n <div style={{ ...styles.gmButtonGroup, gap: `${gap}px`, marginBottom: `${gap * 3}px`, position: \"relative\", zIndex: 1 }}>\n {[1, 3, 5].map((r) => {\n // Облачки с border вместо заливки\n return (\n <button\n key={r}\n onClick={() => {\n setRounds(r);\n startGame();\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#f0f0f0\";\n e.currentTarget.style.borderColor = \"#1f2937\";\n e.currentTarget.style.transform = \"scale(1.05)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"transparent\";\n e.currentTarget.style.borderColor = \"#e5e7eb\";\n e.currentTarget.style.transform = \"scale(1)\";\n }}\n style={{\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontWeight: 500,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap * 1.2}px ${gap * 2}px`,\n borderRadius: `${borderRadius * 2}px`, // Более округлые для облачков\n margin: `${gap / 2}px`,\n background: \"transparent\",\n border: \"2px solid #e5e7eb\",\n color: \"#1f2937\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease\",\n boxShadow: \"none\",\n }}\n >\n {r}\n </button>\n );\n })}\n </div>\n </>\n );\n }\n\n // Игровой экран\n if (stage === \"game\") {\n return (\n <>\n {MemoizedLogo}\n <div style={{\n ...styles.gmInfoBox,\n padding: `${gap * 0.8}px`,\n marginBottom: `${gap * 0.5}px`,\n maxWidth: `${(containerSize || gameCubeSize) * 0.9}px`,\n }}>\n <h3 style={{ ...styles.gmHeadline3, fontSize: `${baseFontSize.headline3}px`, marginBottom: `${gap * 0.5}px` }}>\n Category: {category}\n </h3>\n <p style={{ ...styles.gmBodyM, fontSize: `${baseFontSize.bodyM}px`, marginBottom: `0px` }}>\n Round {currentRound} of {rounds}\n </p>\n </div>\n\n {word && (\n <p style={{\n ...styles.gmBodyS,\n fontSize: `${baseFontSize.bodyS}px`,\n marginTop: `${gap * 0.5}px`,\n marginBottom: `${gap}px`,\n }}>\n I am thinking of a word that is <strong>{word.length}</strong> letters long\n </p>\n )}\n\n {/* Визуализация виселицы */}\n <div style={{\n margin: `${gap}px 0`,\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}>\n <HangmanDrawing \n mistakes={mistakes} \n maxMistakes={maxMistakes}\n size={isNestHub \n ? Math.max(80, Math.min(110, (containerSize || gameCubeSize) * 0.16))\n : Math.max(100, Math.min(150, (containerSize || gameCubeSize) * 0.2))}\n />\n </div>\n\n <div style={{\n ...styles.gmWordDisplay,\n fontSize: `${Math.max(16, Math.min(24, baseFontSize.wordDisplay * 0.9))}px`,\n margin: `${gap}px 0`,\n letterSpacing: `${gap * 0.8}px`,\n minHeight: `${Math.max(16, Math.min(24, baseFontSize.wordDisplay * 0.9)) * 1.2}px`,\n }}>{masked || \"Loading...\"}</div>\n\n {/* Алфавит - вдохновлено getAvailableLetters */}\n <div style={{\n ...styles.gmInfoBox,\n padding: `${gap}px`,\n marginTop: `${gap}px`,\n marginBottom: `${gap}px`,\n maxWidth: `${(containerSize || gameCubeSize) * 0.95}px`,\n }}>\n <p style={{\n ...styles.gmBodyS,\n fontSize: `${baseFontSize.bodyS}px`,\n marginBottom: `${gap}px`,\n fontWeight: 500, // Medium\n }}>\n Available letters:\n </p>\n <div style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: `${gap / 3}px`,\n justifyContent: \"center\",\n fontSize: `${Math.max(9, Math.min(12, baseFontSize.bodyS * 0.75))}px`,\n fontFamily: '\"Onest\", system-ui, sans-serif',\n }}>\n {availableLetters.map((letter) => (\n <button\n key={letter}\n onClick={() => handleLetterSelect(letter)}\n disabled={roundResult !== null}\n onMouseEnter={(e) => {\n if (roundResult === null) {\n e.currentTarget.style.backgroundColor = \"#e5e7eb\";\n e.currentTarget.style.cursor = \"pointer\";\n }\n }}\n onMouseLeave={(e) => {\n if (roundResult === null) {\n e.currentTarget.style.backgroundColor = \"#f9f9f9\";\n e.currentTarget.style.cursor = \"pointer\";\n }\n }}\n style={{\n padding: `${gap / 4}px ${gap / 3}px`,\n borderRadius: `${borderRadius * 0.5}px`,\n background: \"#f9f9f9\",\n color: \"#1f2937\",\n border: \"1px solid #e5e7eb\",\n minWidth: `${Math.max(gap * 1.5, (containerSize || gameCubeSize) * 0.04)}px`,\n textAlign: \"center\",\n display: \"inline-block\",\n cursor: roundResult === null ? \"pointer\" : \"default\",\n fontFamily: '\"Onest\", system-ui, sans-serif',\n fontSize: `${Math.max(9, Math.min(12, baseFontSize.bodyS * 0.75))}px`,\n transition: \"background-color 0.2s ease\",\n }}\n >\n {letter}\n </button>\n ))}\n </div>\n </div>\n\n {/* Уже угаданные буквы */}\n {guessed.length > 0 && (\n <div style={{\n ...styles.gmGuessedLetters,\n fontSize: `${Math.max(10, Math.min(12, baseFontSize.bodyS * 0.85))}px`,\n marginTop: `${gap * 0.5}px`,\n marginBottom: `2px`,\n }}>\n <span style={{ color: \"#6b7280\" }}>\n Guessed letters: <strong>{guessed.join(\", \")}</strong>\n </span>\n </div>\n )}\n\n {roundResult === \"win\" && (\n <div style={{\n ...styles.gmStatusWin,\n fontSize: `${baseFontSize.bodyL}px`,\n margin: `2px 0`,\n }}>\n 🎉 You won this round!\n </div>\n )}\n\n {roundResult === \"lose\" && (\n <div style={{\n ...styles.gmStatusLose,\n fontSize: `${baseFontSize.bodyL}px`,\n margin: `2px 0`,\n }}>\n The hangman is complete! The word was: <strong>{word}</strong>\n </div>\n )}\n\n {roundResult !== null && currentRound < rounds && (\n <div style={{ marginTop: `2px`, marginBottom: `${gap}px` }}>\n <button\n onClick={nextRound}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#d43a32\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#ec4c44\";\n }}\n style={{\n ...styles.gmButton,\n fontSize: `${Math.max(11, Math.min(14, baseFontSize.button * 0.85))}px`,\n padding: `${gap * 0.6}px ${gap * 1.2}px`,\n borderRadius: `${borderRadius}px`,\n }}\n >\n NEXT\n </button>\n </div>\n )}\n\n {roundResult !== null && currentRound >= rounds && (\n <div style={{ marginTop: `2px`, marginBottom: `${gap}px` }}>\n <button\n onClick={() => setStage(\"result\")}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#d43a32\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#ec4c44\";\n }}\n style={{\n ...styles.gmButton,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n }}\n >\n View Results →\n </button>\n </div>\n )}\n\n {roundResult === null && guessed.length === 0 && (\n <p style={{\n ...styles.gmBodyS,\n fontSize: `${baseFontSize.bodyS}px`,\n marginTop: `${gap}px`,\n marginBottom: `${gap}px`,\n }}>\n Type a letter on your keyboard\n </p>\n )}\n </>\n );\n }\n\n // Экран результатов\n if (stage === \"result\") {\n return (\n <>\n {MemoizedLogo}\n <h1 style={{\n ...styles.gmHeadline1,\n fontSize: `${baseFontSize.headline1}px`,\n marginBottom: `${gap * 2}px`,\n }}>\n 🎊 Game Finished!\n </h1>\n <p style={{\n ...styles.gmBodyL,\n fontSize: `${baseFontSize.bodyL}px`,\n marginBottom: `${gap * 2}px`,\n }}>\n You guessed <strong>{wins}</strong> out of <strong>{rounds}</strong> words correctly.\n </p>\n \n <div style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: `${gap}px`,\n alignItems: \"center\",\n }}>\n <button\n onClick={() => {\n // Сбрасываем состояние и запускаем новую игру с той же категорией и раундами\n if (!category || rounds === 0) {\n setStage(\"lobby\");\n return;\n }\n \n setUsedWords([]);\n const randomWord = pickRandomWord(category as keyof typeof categories, []);\n if (randomWord) {\n setWord(randomWord);\n setUsedWords([randomWord]);\n setGuessed([]);\n setMistakes(0);\n setCurrentRound(1);\n setWins(0);\n setRoundResult(null);\n setStage(\"game\");\n }\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#d43a32\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#ec4c44\";\n }}\n style={{\n ...styles.gmButton,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n minWidth: \"200px\",\n }}\n >\n Play again\n </button>\n \n <button\n onClick={() => setStage(\"lobby\")}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#e5e7eb\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#f9f9f9\";\n }}\n style={{\n ...styles.gmButton,\n ...styles.gmButtonSecondary,\n fontSize: `${baseFontSize.button}px`,\n padding: `${gap}px ${gap * 1.5}px`,\n borderRadius: `${borderRadius}px`,\n minWidth: \"200px\",\n }}\n >\n Exit\n </button>\n </div>\n </>\n );\n }\n\n return null;\n };\n\n // Единый return с трехуровневой структурой (как в magic-sentence)\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n background: \"transparent\",\n overflow: \"hidden\",\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n }}\n >\n <div\n style={{\n width: isMobile ? \"100%\" : (containerSize || gameCubeSize || 1000),\n height: isMobile ? \"100%\" : (containerSize || gameCubeSize || 1000),\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n overflow: \"hidden\",\n borderRadius: isMobile ? 0 : \"20px\",\n background: \"#ffffff\",\n boxShadow: isMobile ? \"none\" : \"0 0 40px rgba(0,0,0,0.1)\",\n margin: isMobile ? \"0 auto\" : \"unset\",\n position: \"relative\", // needed so absolute logo is inside the square\n transform: `scale(${scale})`,\n }}\n >\n <div\n style={{\n transform: \"translateZ(0)\",\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n <div style={containerStyle}>\n {renderContent()}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n"],"names":["styles","HangmanDrawing","mistakes","maxMistakes","size","svgWidth","svgHeight","strokeWidth","baseX1","baseY","baseX2","poleX","poleY1","poleY2","topX1","topY","topX2","ropeX","ropeY1","ropeY2","headCX","headCY","headR","bodyX","bodyY1","bodyY2","leftArmX1","leftArmY1","leftArmX2","leftArmY2","rightArmX1","rightArmY1","rightArmX2","rightArmY2","leftLegX1","leftLegY1","leftLegX2","leftLegY2","rightLegX1","rightLegY1","rightLegX2","rightLegY2","strokeColor","jsxs","jsx","HangmanLobbyGame","gameCubeSize","screenHeight","screenWidth","logoUrl","showLogo","baseURL","categories","stage","setStage","useState","category","setCategory","difficulty","rounds","setRounds","currentRound","setCurrentRound","word","setWord","guessed","setGuessed","setMistakes","wins","setWins","roundResult","setRoundResult","containerSize","setContainerSize","scale","setScale","usedWords","setUsedWords","imagesBaseURL","isMobile","setIsMobile","isNestHub","setIsNestHub","baseFontSize","useMemo","fontSizeScale","padding","gap","borderRadius","isWordGuessed","secretWord","lettersGuessed","letter","getGuessedWord","getAvailableLetters","pickRandomWord","cat","avoidWords","firstCategory","_a","words","availableWords","w","wordsToChooseFrom","randomIndex","array","randomFloat","startGame","randomWord","handleLetterSelect","useCallback","lowerLetter","prevGuessed","currentWord","m","handleKey","useEffect","masked","isWin","isLose","availableLetters","moveToNextRound","r","prev","newWord","timer","nextRound","resize","width","height","mobile","isSmallHeight","isWideScreen","nestHub","finalSize","kidsDoodlesSvg","containerStyle","shouldShowLogo","MemoizedLogo","logoBaseUrl","renderContent","Fragment","e"],"mappings":"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"}
|
|
@@ -206,7 +206,7 @@ function ve({
|
|
|
206
206
|
maxMistakes: Z,
|
|
207
207
|
size: G = 200
|
|
208
208
|
}) {
|
|
209
|
-
const l = G, d = G * 1.25, y = Math.max(2, G / 100), T = 10 * (l / 200), b = 240 * (d / 250), f = 150 * (l / 200), x = 80 * (l / 200), K = 20 * (d / 250), Q = 240 * (d / 250), w = 80 * (l / 200), N = 20 * (d / 250), $ = 150 * (l / 200), B = 150 * (l / 200), M = 20 * (d / 250), z = 50 * (d / 250), v = 150 * (l / 200), C = 70 * (d / 250), _ = 20 * (l / 200), S = 150 * (l / 200), q = 90 * (d / 250),
|
|
209
|
+
const l = G, d = G * 1.25, y = Math.max(2, G / 100), T = 10 * (l / 200), b = 240 * (d / 250), f = 150 * (l / 200), x = 80 * (l / 200), K = 20 * (d / 250), Q = 240 * (d / 250), w = 80 * (l / 200), N = 20 * (d / 250), $ = 150 * (l / 200), B = 150 * (l / 200), M = 20 * (d / 250), z = 50 * (d / 250), v = 150 * (l / 200), C = 70 * (d / 250), _ = 20 * (l / 200), S = 150 * (l / 200), q = 90 * (d / 250), E = 150 * (d / 250), h = 150 * (l / 200), F = 110 * (d / 250), g = 130 * (l / 200), W = 130 * (d / 250), J = 150 * (l / 200), H = 110 * (d / 250), ce = 170 * (l / 200), L = 130 * (d / 250), ee = 150 * (l / 200), V = 150 * (d / 250), p = 130 * (l / 200), te = 190 * (d / 250), I = 150 * (l / 200), ne = 150 * (d / 250), s = 170 * (l / 200), Y = 190 * (d / 250), c = r === 0 || r <= Z * 0.5 ? "#1f2937" : r <= Z * 0.75 ? "#f59e0b" : "#ec4c44";
|
|
210
210
|
return /* @__PURE__ */ u(
|
|
211
211
|
"svg",
|
|
212
212
|
{
|
|
@@ -278,7 +278,7 @@ function ve({
|
|
|
278
278
|
x1: S,
|
|
279
279
|
y1: q,
|
|
280
280
|
x2: S,
|
|
281
|
-
y2:
|
|
281
|
+
y2: E,
|
|
282
282
|
stroke: c,
|
|
283
283
|
strokeWidth: y
|
|
284
284
|
}
|
|
@@ -322,7 +322,7 @@ function ve({
|
|
|
322
322
|
x1: I,
|
|
323
323
|
y1: ne,
|
|
324
324
|
x2: s,
|
|
325
|
-
y2:
|
|
325
|
+
y2: Y,
|
|
326
326
|
stroke: c,
|
|
327
327
|
strokeWidth: y
|
|
328
328
|
}
|
|
@@ -357,7 +357,7 @@ function Le({
|
|
|
357
357
|
Environment: ["tree", "forest", "air", "water", "pollution", "recycle", "nature", "clean", "waste", "plastic", "energy", "animal", "climate", "earth", "ocean", "river", "planet", "save", "green", "environment", "litter", "organic"],
|
|
358
358
|
Space: ["planet", "star", "sun", "moon", "astronaut", "rocket", "space", "galaxy", "universe", "telescope", "comet", "asteroid", "orbit", "gravity", "alien", "spaceship", "mars", "satellite", "sky", "eclipse"],
|
|
359
359
|
Devices: ["computer", "laptop", "phone", "tablet", "tv", "keyboard", "mouse", "printer", "camera", "headphones", "charger", "screen", "watch", "microphone", "speaker", "console", "router", "battery", "cable", "remote"]
|
|
360
|
-
}, [b, f] = m("lobby"), [x, K] = m(""), [Q] = m("Normal"), [w, N] = m(0), [$, B] = m(1), [M, z] = m(""), [v, C] = m([]), [_, S] = m(0), [q,
|
|
360
|
+
}, [b, f] = m("lobby"), [x, K] = m(""), [Q] = m("Normal"), [w, N] = m(0), [$, B] = m(1), [M, z] = m(""), [v, C] = m([]), [_, S] = m(0), [q, E] = m(0), [h, F] = m(null), [g, W] = m(null), [J, H] = m(1), [ce, L] = m([]), ee = Q === "Easy" ? 8 : Q === "Normal" ? 6 : 4, V = y || (typeof window < "u" && window.origin ? `${window.origin}/cloud/speakid/games/hangman` : "/cloud/speakid/games/hangman"), [p, te] = m(!1), [I, ne] = m(!1), s = D(() => {
|
|
361
361
|
const e = (g || r || 1e3) / 400;
|
|
362
362
|
return {
|
|
363
363
|
headline1: p ? Math.max(24, Math.min(30, 30 * e)) : Math.max(28, Math.min(32, 32 * e)),
|
|
@@ -377,7 +377,7 @@ function Le({
|
|
|
377
377
|
button: Math.max(12, Math.min(18, 16 * e))
|
|
378
378
|
// Desktop: 16px
|
|
379
379
|
};
|
|
380
|
-
}, [p, g, r]),
|
|
380
|
+
}, [p, g, r]), Y = D(() => {
|
|
381
381
|
const e = (g || r || 1e3) / 400;
|
|
382
382
|
return I ? Math.max(8, Math.min(12, 10 * e)) : Math.max(12, Math.min(24, 16 * e));
|
|
383
383
|
}, [I, g, r]), o = D(() => {
|
|
@@ -395,18 +395,18 @@ function Le({
|
|
|
395
395
|
const i = T[e];
|
|
396
396
|
if (!i || i.length === 0)
|
|
397
397
|
return "";
|
|
398
|
-
const
|
|
399
|
-
if (
|
|
398
|
+
const R = i.filter((k) => !t.includes(k)), j = R.length > 0 ? R : i;
|
|
399
|
+
if (j.length === 0)
|
|
400
400
|
return "";
|
|
401
401
|
let O;
|
|
402
402
|
if (typeof crypto < "u" && crypto.getRandomValues) {
|
|
403
403
|
const k = new Uint32Array(1);
|
|
404
404
|
crypto.getRandomValues(k);
|
|
405
405
|
const ue = k[0] / 4294967295;
|
|
406
|
-
O = Math.floor(ue *
|
|
406
|
+
O = Math.floor(ue * j.length);
|
|
407
407
|
} else
|
|
408
|
-
O = Math.floor(Math.random() *
|
|
409
|
-
return
|
|
408
|
+
O = Math.floor(Math.random() * j.length);
|
|
409
|
+
return j[O];
|
|
410
410
|
}, xe = () => {
|
|
411
411
|
if (!x) return;
|
|
412
412
|
L([]);
|
|
@@ -415,11 +415,11 @@ function Le({
|
|
|
415
415
|
f("category");
|
|
416
416
|
return;
|
|
417
417
|
}
|
|
418
|
-
z(e), L([e]), C([]), S(0), B(1),
|
|
418
|
+
z(e), L([e]), C([]), S(0), B(1), E(0), F(null), f("game");
|
|
419
419
|
}, oe = ae((e) => {
|
|
420
420
|
if (b !== "game" || h !== null) return;
|
|
421
421
|
const t = e.toLowerCase();
|
|
422
|
-
/^[a-z]$/.test(t) && (C((i) => i.includes(t) ? i : [...i, t]), z((i) => (i && !i.includes(t) && S((
|
|
422
|
+
/^[a-z]$/.test(t) && (C((i) => i.includes(t) ? i : [...i, t]), z((i) => (i && !i.includes(t) && S((R) => R + 1), i)));
|
|
423
423
|
}, [b, h]), re = ae((e) => {
|
|
424
424
|
oe(e.key);
|
|
425
425
|
}, [oe]);
|
|
@@ -439,7 +439,7 @@ function Le({
|
|
|
439
439
|
}, [x, $, w]);
|
|
440
440
|
le(() => {
|
|
441
441
|
if (de && h === null) {
|
|
442
|
-
F("win"),
|
|
442
|
+
F("win"), E((t) => t + 1);
|
|
443
443
|
const e = setTimeout(() => {
|
|
444
444
|
ie();
|
|
445
445
|
}, 2e3);
|
|
@@ -465,13 +465,13 @@ function Le({
|
|
|
465
465
|
};
|
|
466
466
|
le(() => {
|
|
467
467
|
const e = () => {
|
|
468
|
-
const t = window.innerWidth, i = window.innerHeight,
|
|
469
|
-
if (te(
|
|
468
|
+
const t = window.innerWidth, i = window.innerHeight, R = t < 768 || t === 926 && i === 428 || t === 932 && i === 430, j = i < 700, O = t / i > 1.8, U = t === 1024 && i === 600;
|
|
469
|
+
if (te(R), ne(U), r && r >= 320) {
|
|
470
470
|
const $e = Math.max(320, Math.min(1200, r));
|
|
471
471
|
W($e), H(1);
|
|
472
|
-
} else if (
|
|
472
|
+
} else if (R)
|
|
473
473
|
W(null), H(1);
|
|
474
|
-
else if (
|
|
474
|
+
else if (j)
|
|
475
475
|
W(null), H(1);
|
|
476
476
|
else if (O) {
|
|
477
477
|
const k = Math.min(1e3, Math.min(t, i) * 0.9);
|
|
@@ -531,7 +531,7 @@ function Le({
|
|
|
531
531
|
...a.gmCenterScreen,
|
|
532
532
|
width: "100%",
|
|
533
533
|
height: "100%",
|
|
534
|
-
padding: `${
|
|
534
|
+
padding: `${Y}px`,
|
|
535
535
|
overflow: "auto",
|
|
536
536
|
position: "relative",
|
|
537
537
|
boxSizing: "border-box",
|
|
@@ -694,9 +694,9 @@ function Le({
|
|
|
694
694
|
padding: `${o}px ${o * 1.5}px`,
|
|
695
695
|
borderRadius: `${c}px`,
|
|
696
696
|
position: "absolute",
|
|
697
|
-
top: `${
|
|
698
|
-
left:
|
|
699
|
-
// ✅
|
|
697
|
+
top: `${Y}px`,
|
|
698
|
+
left: "160px",
|
|
699
|
+
// ✅ Фиксированное смещение правее логотипа (16px + ~120px логотип + 24px отступ)
|
|
700
700
|
zIndex: 10
|
|
701
701
|
},
|
|
702
702
|
children: "←"
|
|
@@ -753,9 +753,9 @@ function Le({
|
|
|
753
753
|
padding: `${o}px ${o * 1.5}px`,
|
|
754
754
|
borderRadius: `${c}px`,
|
|
755
755
|
position: "absolute",
|
|
756
|
-
top: `${
|
|
757
|
-
left:
|
|
758
|
-
// ✅
|
|
756
|
+
top: `${Y}px`,
|
|
757
|
+
left: "160px",
|
|
758
|
+
// ✅ Фиксированное смещение правее логотипа (16px + ~120px логотип + 24px отступ)
|
|
759
759
|
zIndex: 10
|
|
760
760
|
},
|
|
761
761
|
children: "←"
|
|
@@ -993,7 +993,7 @@ function Le({
|
|
|
993
993
|
}
|
|
994
994
|
L([]);
|
|
995
995
|
const e = P(x, []);
|
|
996
|
-
e && (z(e), L([e]), C([]), S(0), B(1),
|
|
996
|
+
e && (z(e), L([e]), C([]), S(0), B(1), E(0), F(null), f("game"));
|
|
997
997
|
},
|
|
998
998
|
onMouseEnter: (e) => {
|
|
999
999
|
e.currentTarget.style.backgroundColor = "#d43a32";
|