Загрузка данных


Ты — senior-разработчик на Go с большим опытом создания сетевых игр, WebSocket-серверов и конкурентных систем, и твоя задача — спроектировать и реализовать полноценную онлайн-игру «Пэчворк» для двух игроков, где серверная логика написана на Go, а клиент представляет собой одностраничное веб-приложение на HTML, CSS и JavaScript, работающее в реальном времени через WebSocket. Игра должна быть полностью рабочей, компилируемой и запускаемой без дополнительных правок, с идиоматичным Go-кодом, использованием горутин, каналов, мьютексов и контекстов для безопасной конкурентной работы, а также с unit-тестами для игровой логики и интеграционными тестами для WebSocket-соединения. Сервер должен управлять игровыми сессиями в памяти, поддерживать лобби, ожидание двух игроков, кнопку готовности, старт игры, валидацию всех ходов на сервере, переподключение игрока в течение пяти минут, простой текстовый чат между игроками и корректное завершение игры с подсчётом очков. Клиент должен отображать планшет 9 на 9 с выложенными тайлами, круг тайлов с подсветкой трёх доступных, трек времени с двумя фишками и напёрстком, панель игрока с пуговицами и кнопкой паса, модальное окно выбора поворота и позиции тайла, чат-бокс и индикатор текущего хода. Тебе нужно предоставить полный исходный код проекта: структуру директорий, go.mod с зависимостями, серверную часть с main.go, пакетами game, lobby и ws, клиентскую часть с index.html, style.css и game.js, тесты game_test.go и README.md с инструкцией по запуску и игре. Все зависимости указывай явно, ошибки логируй с контекстом, а клиенту отправляй понятные сообщения об ошибках. Если какой-то момент в правилах требует уточнения, выбери наиболее логичный вариант и прокомментируй его в коде. Теперь подробно о правилах игры «Пэчворк», которые ты должен реализовать. В игре два планшета для шитья размером 9 на 9 клеток, 33 лоскута-полиомино разной формы, 50 фишек пуговиц, напёрсток как нейтральный маркер на треке времени, две фишки игроков чёрного и белого цвета для трека времени, один бонусный тайл 7 на 7 и трек времени как общее поле-счётчик. При подготовке все 33 тайла выкладываются случайным образом по кругу вокруг трека времени, на трек помещаются пять специальных тайлов 1 на 1 на определённые клетки, напёрсток ставится перед тайлом, состоящим из двух клеток, каждый игрок берёт пять пуговиц и планшет 9 на 9, а первый игрок определяется случайно. Ходят игроки не по очереди, а по принципу отстающего: право хода всегда у того, чья фишка на треке времени позади или на том же поле, но снизу, поэтому один игрок может сделать несколько ходов подряд. В свой ход игрок выбирает одно из двух действий. Первое действие — купить тайл: доступны три тайла, расположенных по часовой стрелке сразу за напёрстком, игрок платит пуговицами стоимость тайла, указанную на нём, продвигает свою фишку по треку времени на число клеток, равное значению времени тайла, напёрсток перемещается на место купленного тайла в круге, а сам тайл размещается на планшете 9 на 9 без наложений на уже выложенные тайлы с возможностью поворота. Если фишка пересекает клетку с символом пуговицы на треке времени, игрок получает доход в размере суммы пуговиц на всех его выложенных тайлах. Второе действие — пас: игрок перемещает свою фишку на одну клетку вперёд от фишки соперника и за каждую пройденную клетку берёт одну пуговицу из банка, при этом если фишка пересекает символ пуговицы, доход также начисляется. На треке времени есть пять клеток с изображением тайла 1 на 1, и первый игрок, чья фишка проходит такую клетку, забирает этот тайл и сразу размещает его на своём планшете бесплатно. Первый игрок, полностью заполнивший квадрат 7 на 7 на своём планшете, забирает бонусный тайл, дающий 7 очков в конце игры. Игра заканчивается, когда обе фишки достигают центральной клетки трека времени. Подсчёт очков происходит так: одна пуговица равна одному очку, бонусный тайл добавляет 7 очков, а за каждую незакрытую клетку на планшете вычитается 2 очка. Побеждает игрок с наибольшим количеством очков. Для реализации тебе нужно продумать модели данных: тайл с идентификатором, координатами клеток относительно нуля, стоимостью в пуговицах, затрачиваемым временем, доходом и текущим поворотом от нуля до трёх; планшет игрока с сеткой 9 на 9, где ноль означает пусто, а иначе идентификатор тайла; игрок с идентификатором, именем, количеством пуговиц, позицией на треке, планшетом, списком тайлов, флагом наличия бонуса и флагом готовности; игровая сессия с идентификатором, двумя игроками, кругом тайлов, позицией напёрстка, треком времени, индексом текущего игрока и состоянием игры, которое может быть ожиданием, игрой или завершением. Протокол WebSocket должен принимать от клиента сообщения типа join с gameId и playerName, ready, buyPatch с индексом тайла, поворотом и позицией, pass и chat с сообщением, а отправлять клиенту state с полным игровым состоянием, error с сообщением, gameOver с победителем и счетами и chat с отправителем и сообщением. Серверная часть должна обеспечивать создание игры, ожидание двух игроков, старт, случайную раскладку тайлов, определение первого игрока, валидацию ходов на достаточность пуговиц, возможность размещения без наложений и корректность номера тайла из трёх доступных за напёрстком, обновление состояния после каждого хода с рассылкой обоим игрокам, обработку дохода при пересечении символа пуговицы, автоматическую выдачу специальных тайлов 1 на 1 при прохождении клетки, проверку заполнения квадрата 7 на 7 после каждого размещения тайла, завершение игры при достижении обеими фишками центра, подсчёт очков и объявление победителя, а также переподключение и чат. Клиентская часть должна визуализировать всё перечисленное и позволять игроку выбирать тайл, поворачивать его, размещать на планшете, видеть доступные ходы, свой счёт, доход, текущий ход и общаться в чате. Ты должен предоставить полный исходный код с файлами go.mod, main.go, пакетами game, lobby и ws, статическими файлами index.html, style.css, game.js, тестами game_test.go и README.md. Код должен быть рабочим, компилируемым и запускаемым, с явными зависимостями, логированием ошибок и понятными сообщениями об ошибках для клиента. Начни с проектирования структуры и моделей, затем реализуй серверную логику, после — WebSocket-слой и в конце — клиент.