450 lines
22 KiB
HTML
450 lines
22 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>🃏 Texas Hold'em Poker</title>
|
||
<link rel="stylesheet" href="styles.css">
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||
</head>
|
||
<body>
|
||
<!-- Главное меню -->
|
||
<div id="main-menu" class="screen active">
|
||
<div class="glass-container menu-container">
|
||
<div class="logo">
|
||
<span class="logo-icon">🃏</span>
|
||
<h1>Texas Hold'em</h1>
|
||
<p class="subtitle">No-Limit Poker</p>
|
||
</div>
|
||
|
||
<div class="menu-buttons">
|
||
<button class="btn btn-primary btn-large" onclick="showScreen('single-player-menu')">
|
||
<span class="btn-icon">🤖</span>
|
||
Одиночная игра
|
||
</button>
|
||
<button class="btn btn-secondary btn-large" onclick="showScreen('multiplayer-menu')">
|
||
<span class="btn-icon">👥</span>
|
||
Мультиплеер
|
||
</button>
|
||
<button class="btn btn-outline btn-large" onclick="showScreen('leaderboard-screen')">
|
||
<span class="btn-icon">🏆</span>
|
||
Таблица лидеров
|
||
</button>
|
||
</div>
|
||
|
||
<div class="settings-row">
|
||
<button class="btn btn-icon-only" onclick="toggleSound()" id="sound-toggle">
|
||
🔊
|
||
</button>
|
||
<button class="btn btn-icon-only" onclick="showScreen('settings-screen')">
|
||
⚙️
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Меню одиночной игры -->
|
||
<div id="single-player-menu" class="screen">
|
||
<div class="glass-container menu-container">
|
||
<button class="btn-back" onclick="showScreen('main-menu')">← Назад</button>
|
||
<h2>Одиночная игра</h2>
|
||
|
||
<div class="form-group">
|
||
<label>Ваше имя</label>
|
||
<input type="text" id="sp-player-name" class="input" placeholder="Введите имя" value="Игрок">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Количество ботов</label>
|
||
<div class="btn-group">
|
||
<button class="btn btn-option active" data-value="1" onclick="selectOption(this, 'bot-count')">1</button>
|
||
<button class="btn btn-option" data-value="2" onclick="selectOption(this, 'bot-count')">2</button>
|
||
<button class="btn btn-option" data-value="3" onclick="selectOption(this, 'bot-count')">3</button>
|
||
<button class="btn btn-option" data-value="4" onclick="selectOption(this, 'bot-count')">4</button>
|
||
<button class="btn btn-option" data-value="5" onclick="selectOption(this, 'bot-count')">5</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Сложность ИИ</label>
|
||
<div class="btn-group difficulty-group">
|
||
<button class="btn btn-option active" data-value="1" onclick="selectOption(this, 'ai-difficulty')">
|
||
<span class="diff-icon">🎲</span>
|
||
<span class="diff-name">Новичок</span>
|
||
</button>
|
||
<button class="btn btn-option" data-value="2" onclick="selectOption(this, 'ai-difficulty')">
|
||
<span class="diff-icon">🎯</span>
|
||
<span class="diff-name">Опытный</span>
|
||
</button>
|
||
<button class="btn btn-option" data-value="3" onclick="selectOption(this, 'ai-difficulty')">
|
||
<span class="diff-icon">🧠</span>
|
||
<span class="diff-name">Эксперт</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Начальный стек</label>
|
||
<div class="btn-group">
|
||
<button class="btn btn-option" data-value="500" onclick="selectOption(this, 'starting-stack')">500</button>
|
||
<button class="btn btn-option active" data-value="1000" onclick="selectOption(this, 'starting-stack')">1000</button>
|
||
<button class="btn btn-option" data-value="2000" onclick="selectOption(this, 'starting-stack')">2000</button>
|
||
<button class="btn btn-option" data-value="5000" onclick="selectOption(this, 'starting-stack')">5000</button>
|
||
</div>
|
||
</div>
|
||
|
||
<button class="btn btn-primary btn-large" onclick="startSinglePlayer()">
|
||
Начать игру
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Меню мультиплеера -->
|
||
<div id="multiplayer-menu" class="screen">
|
||
<div class="glass-container menu-container">
|
||
<button class="btn-back" onclick="showScreen('main-menu')">← Назад</button>
|
||
<h2>Мультиплеер</h2>
|
||
|
||
<div class="form-group">
|
||
<label>Ваше имя</label>
|
||
<input type="text" id="mp-player-name" class="input" placeholder="Введите имя" value="Игрок">
|
||
</div>
|
||
|
||
<div class="tabs">
|
||
<button class="tab active" onclick="switchTab('join-tab')">Присоединиться</button>
|
||
<button class="tab" onclick="switchTab('create-tab')">Создать комнату</button>
|
||
</div>
|
||
|
||
<div id="join-tab" class="tab-content active">
|
||
<div class="room-list" id="room-list">
|
||
<div class="room-list-loading">Подключение к серверу...</div>
|
||
</div>
|
||
<button class="btn btn-outline" onclick="refreshRooms()">🔄 Обновить</button>
|
||
</div>
|
||
|
||
<div id="create-tab" class="tab-content">
|
||
<div class="form-group">
|
||
<label>Название комнаты</label>
|
||
<input type="text" id="room-name" class="input" placeholder="Моя комната">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Блайнды</label>
|
||
<div class="btn-group">
|
||
<button class="btn btn-option active" data-value="5/10" onclick="selectOption(this, 'blinds')">5/10</button>
|
||
<button class="btn btn-option" data-value="10/20" onclick="selectOption(this, 'blinds')">10/20</button>
|
||
<button class="btn btn-option" data-value="25/50" onclick="selectOption(this, 'blinds')">25/50</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Макс. игроков</label>
|
||
<div class="btn-group">
|
||
<button class="btn btn-option" data-value="2" onclick="selectOption(this, 'max-players')">2</button>
|
||
<button class="btn btn-option" data-value="4" onclick="selectOption(this, 'max-players')">4</button>
|
||
<button class="btn btn-option active" data-value="6" onclick="selectOption(this, 'max-players')">6</button>
|
||
</div>
|
||
</div>
|
||
|
||
<button class="btn btn-primary btn-large" onclick="createRoom()">
|
||
Создать комнату
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Лобби комнаты -->
|
||
<div id="room-lobby" class="screen">
|
||
<div class="glass-container lobby-container">
|
||
<button class="btn-back" onclick="leaveRoom()">← Выйти</button>
|
||
<h2 id="lobby-room-name">Комната</h2>
|
||
|
||
<div class="lobby-players" id="lobby-players">
|
||
<!-- Игроки будут добавлены динамически -->
|
||
</div>
|
||
|
||
<div class="lobby-info">
|
||
<span>Блайнды: <strong id="lobby-blinds">5/10</strong></span>
|
||
<span>Игроки: <strong id="lobby-player-count">1/6</strong></span>
|
||
</div>
|
||
|
||
<button class="btn btn-primary btn-large" id="start-game-btn" onclick="startMultiplayerGame()">
|
||
Начать игру
|
||
</button>
|
||
|
||
<div class="lobby-chat">
|
||
<div class="chat-messages" id="lobby-chat-messages"></div>
|
||
<div class="chat-input-row">
|
||
<input type="text" id="lobby-chat-input" class="input" placeholder="Сообщение..." onkeypress="handleLobbyChatKey(event)">
|
||
<button class="btn btn-primary" onclick="sendLobbyChat()">→</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Игровой экран -->
|
||
<div id="game-screen" class="screen">
|
||
<div class="game-container">
|
||
<!-- Информация о столе -->
|
||
<div class="table-info">
|
||
<div class="pot-display glass-card">
|
||
<span class="pot-label">Банк</span>
|
||
<span class="pot-amount" id="pot-amount">0</span>
|
||
</div>
|
||
<div class="phase-display glass-card" id="game-phase">
|
||
Ожидание
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Покерный стол -->
|
||
<div class="poker-table">
|
||
<div class="table-felt">
|
||
<!-- Общие карты -->
|
||
<div class="community-cards" id="community-cards">
|
||
<!-- Карты будут добавлены динамически -->
|
||
</div>
|
||
|
||
<!-- Позиции игроков -->
|
||
<div class="player-positions" id="player-positions">
|
||
<!-- Игроки будут добавлены динамически -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Карты игрока -->
|
||
<div class="player-hand-container glass-card">
|
||
<div class="player-cards" id="player-cards">
|
||
<div class="card card-back"></div>
|
||
<div class="card card-back"></div>
|
||
</div>
|
||
<div class="hand-strength" id="hand-strength"></div>
|
||
</div>
|
||
|
||
<!-- Панель действий -->
|
||
<div class="action-panel glass-card" id="action-panel">
|
||
<div class="action-buttons">
|
||
<button class="btn btn-fold" onclick="playerAction('fold')">
|
||
Фолд
|
||
</button>
|
||
<button class="btn btn-check" onclick="playerAction('check')" id="btn-check">
|
||
Чек
|
||
</button>
|
||
<button class="btn btn-call" onclick="playerAction('call')" id="btn-call">
|
||
Колл <span id="call-amount"></span>
|
||
</button>
|
||
<button class="btn btn-bet" onclick="showBetSlider()" id="btn-bet">
|
||
Бет
|
||
</button>
|
||
<button class="btn btn-raise" onclick="showBetSlider()" id="btn-raise">
|
||
Рейз
|
||
</button>
|
||
<button class="btn btn-allin" onclick="playerAction('allin')">
|
||
All-In
|
||
</button>
|
||
</div>
|
||
|
||
<div class="bet-slider-container" id="bet-slider-container" style="display: none;">
|
||
<input type="range" id="bet-slider" class="bet-slider" min="0" max="1000" value="0" oninput="updateBetValue()">
|
||
<div class="bet-value-display">
|
||
<input type="number" id="bet-value" class="bet-input" value="0" onchange="updateSliderFromInput()">
|
||
</div>
|
||
<div class="bet-presets">
|
||
<button class="btn btn-small" onclick="setBetPreset(0.5)">½ Пот</button>
|
||
<button class="btn btn-small" onclick="setBetPreset(0.75)">¾ Пот</button>
|
||
<button class="btn btn-small" onclick="setBetPreset(1)">Пот</button>
|
||
</div>
|
||
<div class="bet-confirm">
|
||
<button class="btn btn-secondary" onclick="hideBetSlider()">Отмена</button>
|
||
<button class="btn btn-primary" onclick="confirmBet()">Подтвердить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Чат в игре -->
|
||
<div class="game-chat glass-card" id="game-chat">
|
||
<div class="chat-header" onclick="toggleChat()">
|
||
💬 Чат
|
||
<span class="chat-toggle">▼</span>
|
||
</div>
|
||
<div class="chat-body">
|
||
<div class="chat-messages" id="game-chat-messages"></div>
|
||
<div class="chat-input-row">
|
||
<input type="text" id="game-chat-input" class="input" placeholder="Сообщение..." onkeypress="handleGameChatKey(event)">
|
||
<button class="btn btn-primary" onclick="sendGameChat()">→</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Кнопки управления -->
|
||
<div class="game-controls">
|
||
<button class="btn btn-icon-only" onclick="toggleSound()">🔊</button>
|
||
<button class="btn btn-icon-only" onclick="leaveGame()">🚪</button>
|
||
</div>
|
||
|
||
<!-- Кнопка новой раздачи (для одиночной игры) -->
|
||
<button class="btn btn-primary btn-large new-hand-btn" id="new-hand-btn" style="display: none;" onclick="startNewHand()">
|
||
Новая раздача
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Таблица лидеров -->
|
||
<div id="leaderboard-screen" class="screen">
|
||
<div class="glass-container menu-container">
|
||
<button class="btn-back" onclick="showScreen('main-menu')">← Назад</button>
|
||
<h2>🏆 Таблица лидеров</h2>
|
||
|
||
<div class="leaderboard-tabs">
|
||
<button class="tab active" onclick="switchLeaderboardTab('local')">Локальные</button>
|
||
<button class="tab" onclick="switchLeaderboardTab('global')">Глобальные</button>
|
||
</div>
|
||
|
||
<div class="leaderboard-list" id="leaderboard-list">
|
||
<!-- Записи будут добавлены динамически -->
|
||
</div>
|
||
|
||
<button class="btn btn-outline" onclick="clearLeaderboard()">Очистить записи</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Настройки -->
|
||
<div id="settings-screen" class="screen">
|
||
<div class="glass-container menu-container">
|
||
<button class="btn-back" onclick="showScreen('main-menu')">← Назад</button>
|
||
<h2>⚙️ Настройки</h2>
|
||
|
||
<div class="settings-list">
|
||
<div class="setting-item">
|
||
<span>Звуковые эффекты</span>
|
||
<label class="switch">
|
||
<input type="checkbox" id="setting-sound" checked onchange="updateSettings()">
|
||
<span class="slider"></span>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="setting-item">
|
||
<span>Анимации</span>
|
||
<label class="switch">
|
||
<input type="checkbox" id="setting-animations" checked onchange="updateSettings()">
|
||
<span class="slider"></span>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="setting-item">
|
||
<span>Показывать силу руки</span>
|
||
<label class="switch">
|
||
<input type="checkbox" id="setting-hand-strength" checked onchange="updateSettings()">
|
||
<span class="slider"></span>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="setting-item">
|
||
<span>Автофолд при отключении</span>
|
||
<label class="switch">
|
||
<input type="checkbox" id="setting-autofold" checked onchange="updateSettings()">
|
||
<span class="slider"></span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<h3 style="margin-top: 24px; margin-bottom: 16px;">🎴 Рубашка карт</h3>
|
||
|
||
<div class="card-back-settings">
|
||
<div class="card-back-preview">
|
||
<div class="card card-back" id="card-back-preview">
|
||
<div class="card-back-pattern"></div>
|
||
</div>
|
||
<span class="preview-label">Превью</span>
|
||
</div>
|
||
|
||
<div class="card-back-options">
|
||
<div class="form-group">
|
||
<label>Выберите стиль рубашки</label>
|
||
<div class="btn-group card-back-styles">
|
||
<button class="btn btn-option active" data-style="default" onclick="selectCardBack(this)">🎰 Классика</button>
|
||
<button class="btn btn-option" data-style="red" onclick="selectCardBack(this)">🔴 Красная</button>
|
||
<button class="btn btn-option" data-style="blue" onclick="selectCardBack(this)">🔵 Синяя</button>
|
||
<button class="btn btn-option" data-style="custom" onclick="selectCardBack(this)">🖼️ Своя</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group" id="custom-card-back-group" style="display: none;">
|
||
<label>Загрузить изображение</label>
|
||
<input type="file" id="card-back-file" class="input" accept="image/*" onchange="loadCustomCardBack(this)">
|
||
<small style="color: var(--text-muted); display: block; margin-top: 4px;">Рекомендуемый размер: 70×100 px</small>
|
||
</div>
|
||
|
||
<div class="form-group" id="card-back-url-group" style="display: none;">
|
||
<label>Или вставьте URL изображения</label>
|
||
<input type="text" id="card-back-url" class="input" placeholder="https://example.com/card-back.png" onchange="setCardBackUrl(this.value)">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Сервер WebSocket</label>
|
||
<input type="text" id="server-url" class="input" value="ws://localhost:3000" onchange="updateSettings()">
|
||
</div>
|
||
|
||
<h3 style="margin-top: 24px; margin-bottom: 16px;">🤖 Настройки LLM чата</h3>
|
||
|
||
<div class="settings-list">
|
||
<div class="setting-item">
|
||
<span>Включить LLM чат</span>
|
||
<label class="switch">
|
||
<input type="checkbox" id="setting-llm-enabled" onchange="updateSettings()">
|
||
<span class="slider"></span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>LLM провайдер</label>
|
||
<input type="hidden" id="llm-provider" value="ollama">
|
||
<div class="btn-group">
|
||
<button class="btn btn-option active" data-value="ollama" onclick="selectLLMProvider(this)">Ollama</button>
|
||
<button class="btn btn-option" data-value="lmstudio" onclick="selectLLMProvider(this)">LM Studio</button>
|
||
<button class="btn btn-option" data-value="openai" onclick="selectLLMProvider(this)">OpenAI</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label id="llm-api-url-label">URL API</label>
|
||
<input type="text" id="llm-api-url" class="input" value="http://localhost:11434" onchange="updateSettings()" placeholder="http://localhost:11434">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Модель</label>
|
||
<input type="text" id="llm-model" class="input" value="llama3.2" onchange="updateSettings()" placeholder="llama3.2, mistral, etc.">
|
||
</div>
|
||
|
||
<div class="form-group" id="llm-api-key-group" style="display: none;">
|
||
<label>API Key (для OpenAI)</label>
|
||
<input type="password" id="llm-api-key" class="input" onchange="updateSettings()" placeholder="sk-...">
|
||
</div>
|
||
|
||
<button class="btn btn-secondary" id="test-llm-btn" onclick="testLLMConnection()">🔗 Проверить подключение</button>
|
||
|
||
<div style="margin-top: 16px;"></div>
|
||
<button class="btn btn-outline" onclick="resetSettings()">Сбросить настройки</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Результаты раздачи -->
|
||
<div id="hand-result-modal" class="modal">
|
||
<div class="modal-content glass-container">
|
||
<h3 id="result-title">Результат</h3>
|
||
<div class="result-details" id="result-details"></div>
|
||
<button class="btn btn-primary" onclick="closeResultModal()">Продолжить</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Уведомления -->
|
||
<div class="notifications" id="notifications"></div>
|
||
|
||
<script src="game.js"></script>
|
||
<script src="ai.js"></script>
|
||
<script src="main.js"></script>
|
||
</body>
|
||
</html>
|