Tới nội dung chính
Tất cả dự án

Năm

2026

Vai trò

Làm một mình — kiến trúc, engine luật, giao thức, service giải đấu, thuật toán tìm kiếm, triển khai

Công nghệ

  • TypeScript
  • Zod
  • ws
  • React
  • Vite
  • PostgreSQL
  • Docker
  • Cloud Run
  • GitHub Actions

Nền tảng realtime

Detoura

Game cờ đối kháng hai người thời gian thực, xây dựng như một nền tảng: lõi luật tất định, bộ schema vừa kiểm tra, vừa tài liệu hoá và kiểm thử API, cùng service giải đấu riêng cho bot.

Mở bản demo

detoura.ngwkhai.com

Hai người có thể chơi chung trên một máy, hoặc bạn mở phòng rồi gửi mã cho người khác.

  • Thiết kế monorepo TypeScript gồm chín package xoay quanh một lõi luật tất định, không phụ thuộc thư viện nào. Nhờ vậy cùng một đoạn code chạy được trên trình duyệt, trên server và khi phát lại ván đấu.
  • Tách nền tảng khỏi từng game cụ thể: luật game cắm vào qua một interface có kiểu duy nhất, còn server coi mỗi ván đấu là dữ liệu đóng, không đọc vào bên trong.
  • Dùng chung một bộ schema Zod để kiểm tra mọi tin nhắn và sinh đặc tả OpenAPI lẫn WebSocket. Một bộ kiểm thử chống lệch hợp đồng chạy trực tiếp trên bản đang triển khai.
  • Xây dựng server WebSocket giữ quyền quyết định cuối cùng, có giới hạn tần suất và đồng hồ do server quản lý, thêm service giải đấu trên Postgres, và pipeline triển khai lên Cloud Run không lưu khoá.
Giải thích cho
Workspace
9
Interface có hợp đồng
5
Tin nhắn giao thức
14

Lõi tất định

Package luật không phụ thuộc thư viện nào, không dùng đồng hồ và không dùng số ngẫu nhiên. Nhờ vậy, cùng một đoạn code vừa chạy trên trình duyệt để phản hồi tức thì, vừa chạy trên server với vai trò trọng tài. Ván đấu có thể lưu dưới dạng nhật ký nước đi rồi phát lại, và thuật toán tìm kiếm có thể mô phỏng trên chính bộ luật thật.

Một interface cho mọi game

Luật game cắm vào nền tảng qua một interface có kiểu duy nhất, gồm các bước: khởi tạo ván, áp dụng nước đi, liệt kê nước hợp lệ, báo kết quả, và chiếu trạng thái ra để hiển thị. Server không bao giờ đọc trực tiếp các trường bên trong một ván đấu, nên muốn thêm game mới chỉ cần viết một package luật và một lớp hiển thị.

Schema vừa là API vừa là test

Schema Zod kiểm tra mọi tin nhắn gửi đến server. Cũng từ những schema đó, hệ thống sinh ra /openapi.json và một trang đặc tả trực tiếp cho mười bốn loại tin nhắn WebSocket, phần mà OpenAPI không mô tả được. Ở mỗi lần phát hành, một bộ test chống lệch so sánh tài liệu thiết kế với đặc tả mà dịch vụ đang chạy thực sự trả về.

Realtime có phòng vệ

Server là bên duy nhất có quyền quyết định trạng thái ván đấu. Mỗi kết nối có giới hạn tần suất theo token bucket và giới hạn kích thước frame, có thể nối lại bằng một token riêng, và mọi sự kiện đều được ghi vào nhật ký kiểm tra. Đồng hồ Fischer do server quản lý và được tách khỏi trạng thái game.

Giải đấu và triển khai

Giải đấu giữa các bot chạy trên một service riêng, dùng Postgres với câu SQL viết tay. API key chỉ lưu dưới dạng mã băm và được so sánh trong thời gian không đổi, bảng xếp hạng lấy từ một SQL view, còn ván đấu được lưu thành nhật ký hành động có thể phát lại. Hai bot, một dùng minimax với cắt tỉa alpha-beta và một dùng MCTS, được viết để thử tải service. Cả hai service triển khai lên Cloud Run qua GitHub Actions mà không lưu khoá. Mỗi bản phát hành phải qua test hợp đồng, test Playwright và smoke test WebSocket chạy trên bản triển khai thật.