Files
doucan/AGENTS.md
2026-02-20 23:39:49 +08:00

170 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 斗地主残局版 - AGENTS.md
## 1. 项目结构
```
doudizhu-server/
├── app/ # Go后端
│ ├── cmd/main.go # 程序入口
│ ├── internal/
│ │ ├── models/ # 数据模型Card, Room, Player等
│ │ ├── game/ # 游戏逻辑(牌型判断、对局管理)
│ │ ├── handlers/ # HTTP API处理器
│ │ └── ws/ # WebSocket处理
│ ├── Dockerfile
│ └── go.mod
├── nginx/nginx.conf # Nginx反向代理配置
├── nginx/html/ # 静态文件HTML/CSS/JS
├── compose.yaml
├── README.md
└── API.md
```
## 2. 构建与运行命令
```bash
# 本地开发需先启动Redis
docker run -d --name redis -p 6379:6379 redis:7-alpine
cd doudizhu-server/app && go mod tidy && go run ./cmd
# Docker部署
cd doudizhu-server && docker compose up -d --build
# 代码格式化自动格式化所有Go文件
gofmt -w ./app
# 静态检查
go vet ./app/...
# 测试(当前项目暂无测试文件,以下为参考命令)
# go test ./app/...
# go test ./app/internal/game/...
# go test ./app/internal/game/... -run TestCardType
# go test ./app/... -cover
```
## 3. Go代码风格规范
### 命名规范
- **导出**:大驼峰命名,如 `GameManager``NewCardLogic`
- **模块内**:小驼峰命名,如 `userId``cardKey`
- **模块名**:全小写,如 `game``handlers``ws`
- **常量**:全大写下划线命名
### Import规范
```go
import (
"encoding/json" // 标准库
"net/http"
"github.com/gorilla/websocket" // 第三方库
"doudizhu-server/internal/game" // 本地包
"doudizhu-server/internal/models"
)
```
### 错误处理
使用哨兵错误模式:
```go
// 定义 (internal/game/errors.go)
var (
ErrRoomNotFound = errors.New("room not found")
ErrNotYourTurn = errors.New("not your turn")
)
// 使用:早返回
func (h *Handler) CreateRoom(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
h.writeError(w, http.StatusBadRequest, "invalid request")
return
}
}
```
### 并发安全
```go
type GameManager struct {
rooms map[string]*models.Room
mu sync.RWMutex
}
// 读操作用RLock
func (gm *GameManager) GetRoom(id string) (*models.Room, error) {
gm.mu.RLock()
defer gm.mu.RUnlock()
// ...
}
// 写操作用Lock
func (gm *GameManager) CreateRoom(...) {
gm.mu.Lock()
defer gm.mu.Unlock()
// ...
}
```
### 函数长度
- **禁止超过150行**不宜超过50行
- 保持函数单一职责,提高可读性和可维护性
### 代码优雅性
1. **空行规范**:不同逻辑块之间空一行
2. **运算符空格**:双目运算符(`+`, `=`, `==` 等)两端必须加空格
3. **禁止多行合并**:禁止使用分号将多行代码合并到一行
### 介词命名规范(用于函数名)
| 介词 | 用法 |
| ------ | -------------------------------------------------------------------- |
| by | 表示动作的执行者或方式,如 `formatByLocale``calculateByDate` |
| from | 表示数据来源、起点或类型转换源,如 `parseFromJson` |
| to | 指明目标位置、接收方或变换终点,如 `sendToServer``uploadToCloud` |
| with | 说明附加参数或属性,如 `buildWithOptions``createWithDefaults` |
| in | 描述在某个上下文/环境中执行的动作,如 `runInBackground` |
| on | 与事件相关的处理器或触发点,如 `handleOnClick``listenOnChange` |
| for | 指定目标受众、用途或适用范围,如 `renderForAdmin``queryForUser` |
## 4. HTTP API响应格式
```go
type ApiResponse struct {
Status int `json:"status"` // HTTP状态码
Code int `json:"code"` // 0=成功, 1=失败
Message string `json:"message"`
Data interface{} `json:"data"`
}
```
## 5. 游戏规则要点
- **超人强**第55张牌最大单牌可管一切
- **简化牌型**:三张可成顺子/炸弹,两对可成连对
- **发牌**每人初始5张一轮后摸1张
- **无地主**:上一轮获胜者先出
## 6. 开发注意事项
1. **代码变动后同步更新文档**README.md 和 API.md
2. **后端API路由必须在 `/api` 下**
3. **WebSocket路径**`/api/ws?roomId=xxx&playerId=xxx`
4. **前端不使用npm/react**采用HTML+CSS+JS
5. **JSON字段用camelCase命名**,如 `roomId``playerId``cardCount`
6. **Go版本**Go 1.21
## 7. 调试
```bash
# 查看日志
docker compose logs -f app
# 前端不生效?强制刷新 (Ctrl+F5)
```