Commit Graph

61 Commits

Author SHA1 Message Date
dbaa1d2492 feat(backend): let players ask for a rematch
RematchOffers keeps an offer open for ten minutes after a game nobody
left. A request goes to the opponent; when both have asked the next game
of the series starts with the other player moving first. Requests end on
no, withdrawal, a minute without answer, going offline or looking for
another game. The bot accepts at once.
2026-10-17 02:03:16 +03:00
ee9e5261eb feat(backend): keep the series a live game belongs to
Every game starts a series; a game created in a series gets its seat to
move first. Clients get the series and the first seat with the game, the
end message the series with the ended game; snapshots keep the series.
2026-10-17 02:00:44 +03:00
c56d1f2c33 docs(rematch): add the spec
Rematch from the game over card, alternating first moves and a series
strip with the score of the games the same two players played in a row.
2026-10-17 01:58:58 +03:00
acd60816f7 docs: describe the tutorial
AGENTS.md and TODO.md notes for the tutorial, and the end-to-end results. A
move that ends the game is no longer explained as giving an extra turn.
2026-10-16 15:00:44 +03:00
636127dae4 feat(mobile): show the rules
A How to play screen with the same rules and examples as the web app, opened
from the help screen and from the game screen's help button.
2026-10-16 14:59:33 +03:00
f8ce8f215f feat(frontend): show hints in games against the bot
With hints on, the player's pits show whether their move gives an extra turn
or how many stones it takes, and a line under the board says what the last
move did and why. A Hints switch appears only in games against the bot.
2026-10-16 14:58:56 +03:00
d444447425 feat(frontend): offer the tutorial to newcomers and a practice game
The home page shows newcomers a banner to start the lessons; it goes away for
good after Not now, a lesson or a game. The lessons end with a practice game
against the Easy bot with hints on.
2026-10-16 14:55:51 +03:00
9beb8ba7d4 feat(frontend): add the lessons
Six lessons, one per rule, on the real board with the TypeScript engine: a
task, the move animated, praise or an explanation and a retry. Completed
lessons are remembered on the device.
2026-10-16 14:55:07 +03:00
8511e0b3f2 feat(frontend): show the rules
A How to play page with every rule and a before/after board computed by the
engine, a help button in the header, and the rules in a side panel over the
game page so a game can go on while a rule is looked up.
2026-10-16 14:53:18 +03:00
3a46833e86 feat(core): add the rules, lessons and move explanations
RULES defines every rule with an example and a lesson; getMoveOutcome works
out a move's effect with the engine, explainMove says what happened, and
describeMove now tells the kind of capture and how many stones it took.
2026-10-16 14:50:42 +03:00
9522224bf9 docs(tutorial): add the spec
Requirements, design and tasks for a rules page, interactive lessons and a
practice game with hints against the Easy bot.
2026-10-16 14:46:50 +03:00
f7a76c861e docs: describe the game bot
The bot in the backend README with the calibration command, AGENTS.md notes on
bot ids and test tags, and the open work in TODO.md.
2026-10-16 14:27:49 +03:00
d1918fed10 feat(mobile): offer games against the bot
The lobby offers the bot levels after 10 seconds without an opponent, the
home screen has Play with bot, the bot is shown with its level, and a new
game after a bot game is one at the same level.
2026-10-16 14:23:22 +03:00
e66c4a3a41 feat(frontend): offer games against the bot
The lobby offers the bot levels after 10 seconds without an opponent, the
home page has a Play with bot menu, and a game against the bot ends with
Play again at the same level.
2026-10-16 14:22:04 +03:00
32d1ec98e7 feat(core): add bot levels, the bot game channel and bot names
getPlayerDisplayName shows the bot as e.g. "Bot · Medium" from its id.
2026-10-16 14:21:06 +03:00
4a018c7b53 feat(backend): save how the bot played
Saved games against the bot keep the bot's level, strength and seed in a new
bot column, so the levels can later be tuned from real games.
2026-10-16 14:19:56 +03:00
f0b75e5cee feat(backend): play games against the bot
new_bot_game starts a game against the bot at the chosen level and ends the
search for an opponent. BotPlayer works out the bot's moves on its own thread
pool and plays them on the game loop after the previous move's animation and a
thinking time. Bot games keep their settings across restarts.
2026-10-16 14:18:45 +03:00
31b51d04af feat(backend): choose bot moves by strength
Negamax with alpha-beta on Position scores every move; the strength sets the
depth, the softmax temperature and the chance of a random move. The levels
are ranges of strengths drawn per game. A calibration tournament checks that
each level beats the one below.
2026-10-16 14:18:00 +03:00
f9a96fc5f5 feat(backend): add a compact board for searching moves
Position keeps the board as 14 stone counts and plays the Mangala rules on
it without allocating. Tested against MancalaGame with the recorded games and
random games.
2026-10-16 12:47:32 +03:00
91577c0898 docs(game-bot): add the spec
Requirements, design and tasks for playing against a bot with four levels
and a strength drawn per game.
2026-10-16 12:46:20 +03:00
0903f61455 docs: describe the Java backend
The backend README, how to run and test it, what is easy to get wrong
with the game loop and the shared data formats, and the deployment note.
The web app was played against it in Chrome: a full game with a
spectator, a reload, a restart mid-game, the replay and a game lost on
time.
2026-10-16 11:53:13 +03:00
6aeff37eb8 feat(backend): replace the Node backend with the Quarkus backend
The Quarkus project moves to apps/backend and the Express sources go.
The image is built from the repo root as before, with Temurin 25, and
runs as a non-root user on port 6000. Compose passes the database as a
JDBC URL with the same MANCALA_DB_PASSWORD.
2026-10-16 11:47:40 +03:00
0c112eb716 feat(backend): serve the WebSocket protocol and the HTTP API
RtmtServer ports the WebSocket protocol (auth handshake, sockets per
user, ping) and runs on the game loop; the websockets-next endpoint at /
only forwards socket events. The HTTP routes, CORS and the access log
match the Express app. Backend wires everything and restores live games
before handling socket events. End-to-end tests play games over real
sockets against Postgres and Valkey.
2026-10-16 11:33:07 +03:00
d86fca8c54 feat(backend): save games in Postgres and live state in Valkey
The Node backend's migrations, runner, queries, keys and JSON, so the
same database and Valkey serve either backend. Integration tests run
Postgres and Valkey with Quarkus Dev Services, including a game row the
Node backend wrote and an unreachable Valkey.
2026-10-16 11:26:28 +03:00
219b50b491 feat(backend): port the game logic to Java
GameManager, matchmaking, the game clock, live game snapshots, saving
finished games and live previews, ported from the Node backend with its
tests. Snapshots keep the Node backend's format; a test restores one the
Node backend wrote. Valkey writes and saves run off the game loop.
2026-10-16 11:23:35 +03:00
f0246cca61 feat(backend): add the wire types, the game loop and token verification
Records for the JSON the clients read, leaving out only the fields
TypeScript leaves undefined. GameLoop is the single thread that owns live
state; ManualScheduler replaces Jest's fake timers in tests. Keycloak
tokens are verified with jose4j and the same checks as before.
2026-10-16 11:09:16 +03:00
f0ffd6ba87 feat(backend): add the Quarkus project with a Java port of the engine
Quarkus 3.40 on Java 25, built with the Maven wrapper. The engine is a
line-by-line port of packages/mancala.js; a parity test replays games
recorded with the TypeScript engine, including illegal moves, and
compares every board, turn, error and the game JSON.
2026-10-16 11:06:43 +03:00
ec833b4ec5 docs(backend): spec the move to Java and Quarkus
Requirements, design and tasks for rewriting the backend in Java 25 with
Quarkus while keeping the protocol, the API and the stored data.
2026-10-16 11:00:44 +03:00
6b08fef1e6 docs: document the web redesign
AGENTS.md notes on the themes, plain CSS for container queries and
driving the app in Chrome; TODO.md gets the mobile app and rematch as
open work; the spec is marked implemented.
2026-10-16 10:26:59 +03:00
9619825605 feat(frontend): lay out the home page in the new design
The game in progress comes first with a large mini board; live,
popular and recent games are grids of cards with the score, a mini
board and a status pill. Live and popular games are shown together;
live games are hidden while nothing is being played.
2026-10-16 10:21:46 +03:00
ce27c71176 feat(frontend): lay out the replay page in the new design
A summary card with the result, date, duration, move count, players and
score; players and the move number beside the board; a controls card
with the transport buttons, speed, timeline and the shown move with its
tags; the landing pit of the shown move is ringed.
2026-10-16 10:19:57 +03:00
efe97da0b7 feat(frontend): lay out the game page in the new design
Players beside the board with avatar, online status, store count and
clock, the turn between them, a game-over card over the board, and a
move list with the newest move first and tags for extra turns,
captures and store gains. On phones the bottom player is shown below
the board.
2026-10-16 09:41:47 +03:00
e3e7916265 feat(frontend): draw the new board
Pits and stores are wells with scattered stones and count badges, the
viewer's store on the right. Below 600 px the board stands upright.
Playable pits preview their move on hover, animated pits are ringed and
the pit of the last move has a dashed ring.
2026-10-16 09:37:50 +03:00
6279b5a820 feat(frontend): add the new themes and header
Ceviz, Gece and Yeşim themes as CSS variables on <html>, Bricolage
Grotesque, shared styles, and one header for every page with theme
swatches, the account menu and the page's main action. The lobby,
privacy page and status panels use the new look.
2026-10-16 09:35:39 +03:00
193efd1458 feat(backend): list popular finished games while games are live
GET /games/popular?kind=finished returns the most watched finished
games even when games are being played, so the web app can show live
and popular games together.
2026-10-16 09:31:44 +03:00
8ad833cdbb feat(core): add what the web redesign needs
ThemeManager takes its list of themes, PitAnimator marks animated pits
with PitViewModel.highlight, getSowingPath lists the pits a move sows
into, and new texts in English and Turkish.
2026-10-16 09:31:28 +03:00
61d169ecdc docs(web-redesign): add the spec
Requirements, design and tasks for implementing the new web design
(themes, board, game, replay and home pages).
2026-10-16 09:30:28 +03:00
b472c2813c docs: document the game clock
Backend README (GAME_CLOCK_MS), AGENTS.md notes, TODO items for the open points and the mobile release order; game-history R3.3 and R3.4 marked as replaced. Checked end to end in Chrome: moves, a backend restart, a timeout and the replay.
2026-10-16 01:54:01 +03:00
f9ea00d138 feat(mobile): show the game clocks
Both clocks next to the players, counting down in server time with the same running and low-time styles as the web app. The game screen now handles on_game_end, so a game that ends on time ends on the phone too and says why.
2026-10-16 01:50:39 +03:00
8671bb2553 feat(frontend): show the clocks in replays
Each player's clock after the shown move, from the saved move times; games saved before the game clock show none.
2026-10-16 01:40:05 +03:00
20359b7a8f feat(frontend): show the game clocks in live games
Both clocks sit next to the players' names and count down in server time; the running one is highlighted and turns red under 30 seconds. They replace the offline countdown, so core drops TURN_TIMEOUT_MS, INACTIVE_TIMEOUT_MS, offlineSince and its text. Long info texts wrap on phones.
2026-10-16 01:39:36 +03:00
c610844e26 feat(backend): keep the game clock across restarts and in saved games
Live game snapshots become version 2 with the clock and each move's time left. On restore the running clock goes on from the start of the turn, so downtime is not charged; version 1 snapshots get a new clock. Saved games keep the initial time (migration 002_clock) and each move's time left.
2026-10-16 01:30:39 +03:00
3d4f5d7d59 feat(backend): end games on time with a scheduled service
GameClockScheduler checks every live game once a second and ends those whose running clock has reached zero, whether or not anyone is connected. The clock replaces the offline turn timeout and the inactivity rule, so both are removed with the offline times they used.
2026-10-16 01:29:22 +03:00
999ae79279 feat(backend): run a game clock for each player
Each player starts with GAME_CLOCK_MS (5 minutes). A move deducts the turn's time from the mover; a move that arrives after the time has run out is not played and the opponent wins on time. Every ending stops the clock, and clients get the clock and the server time with each game message.
2026-10-16 01:27:28 +03:00
03e1543d5d feat(core): add game clock types and helpers
GameClock and optional clock fields on live games, end messages, move records and finished games; getClockTimes, ClockSync, getClockAtMove and formatClock with tests.
2026-10-16 01:25:15 +03:00
cb34c03246 docs: add game clock spec
Each player has 5 minutes; the server keeps the time and a scheduled service ends games whose running clock reaches zero. Replaces the offline turn and inactivity rules.
2026-10-16 01:23:32 +03:00
862c57da5e Merge branch 'feature/keycloak-auth' into feature/game-history 2026-10-16 00:40:57 +03:00
ab2424b648 docs: add Keycloak login spec
Requirements, design decisions and tasks for the Keycloak login, written
after the implementation; mobile login and turning off legacy userKey
login remain open.
2026-10-16 00:40:57 +03:00
b94c9336dd docs: document game history and update the TODO
- Backend README: DATABASE_URL, VALKEY_URL, the new routes and how the
  backend behaves when Postgres or Valkey is down
- TODO: drop the fixed spectator and memory bugs, add game history on
  mobile, a page with all games, single-instance limits, backups and the
  new .env variables
- Spec marked as implemented, all tasks ticked
2026-10-16 00:36:48 +03:00
3bb151dbed feat(frontend): replay finished games move by move
- Opening a finished game shows its final position, result, score, date
  and duration, with Watch from start
- First / previous / play-pause / next / last, speed 1x, 2x, 4x, a
  timeline, the move list and arrow keys and space
- Stepping forward animates the move like a live game; jumps show the
  position directly
- ?move=n links to a move and follows the shown move
- Players see the board from their own side
- PitAnimator takes its step interval as a parameter
2026-10-16 00:34:49 +03:00