å°æ¥æ€èšçšã®æ§èšèšã2026-09-18ã®äŸé Œè ã®è£è¶³ã«ãããçŸåšã®å¯Ÿè±¡ã¯å¯ŸäººæŠã®èšé²ã»éèšã»æ²ç€ºãã€ãªã詊äœã«çµã£ãã BotæŠãããŒãåŒãšãã£ã¿ãŒãPostgreSQLãªã©æ¬æžã®å šé ç®ãå®è£ ããããã§ã¯ãªãã çŸåšã®å®è£ 仿§ã¯ technical-requirements.mdãèªäž»å€æã¯ prototype-proposal.md ãåªå ããã
察象èªè : CHroS ã®å®è£ è ãèŠä»¶ãã®ãã®ã¯ requirements.md ãåç §ã
ãã®ããã¥ã¡ã³ãã¯ãæ¢åå®è£ ïŒNext.js + Express/socket.io + FastAPI ã®3ãµãŒãã¹æ§æïŒã ãŒãããŒã¹ã§åèšèšããçµæãå®ãããæ¢åã³ãŒããšã®å·®åã¯æ«å°Ÿã®ãçŸè¡æ§æããã®ç§»è¡ãã«èšãã
2026-09-18远èš: é§è·¯ã䞻察象ãšããæå·ã»åæµ·éç³»ãšå šåœäº€æµå€§äŒãžã®æ¡åŒµãæŽçããã åºå žã»ç¢ºèªçã»æªç¢ºèªäºé 㯠倧äŒã«ãŒã«èª¿æ» ãåç §ã 以äžã¯èšèšã§ãããæ¢åã³ãŒãã®å®è£ å®äºã瀺ããã®ã§ã¯ãªãã
| é ç® | æ±ºå® | çç± |
|---|---|---|
| èšèª | TypeScript ã«çµ±äž | ããã³ããååšããä»¥äž TS ã¯å¿ é ãåãå ±æããã±ãŒãžã§æãŠã°å¢çã®ãºã¬ãæ¶ãã |
| æ§æ | pnpm workspace ã«ãã monorepoãã¢ããªã¯ Next.js åäœ | ãµãŒãã¹åå²ã®ã³ã¹ãã«èŠåãç¬ç«æ§ãçŸæç¹ã§ç¡ããçµ±åã®éã¯å®¹æã ãåå²ã®å·»ãæ»ãã¯é«ãã€ã |
| ãµãŒã㌠â Viewer éä¿¡ | SSEïŒWebSocket ã¯æ¡çšããªãïŒ | Viewer ã¯åä¿¡å°çšã忹忧ãèŠããªããªã SSE ã®æ¹ãåçŽã§ãHTTP ã®ãŸãŸæ±ãã |
| DB | PostgreSQL | 倿Žãªã |
| ORM | Prisma | 倿Žãªã |
| ã¹ã³ã¢èšç® | ããŒãã°ã©ãã§å®çŸ©ã JSON ãšããŠæ°žç¶åãè©äŸ¡åšã¯ TS | èšç®åŒãéãšã³ãžãã¢ãç·šéã§ããããšãæ¬ã·ã¹ãã ã®æ žïŒÂ§5ïŒ |
| èšç®åŒã®ä¿åå | PostgreSQL ã® jsonb |
圢ãå€ããããããŒã¿ãæ§é åã®ãŸãŸæãŠãæ€çŽ¢ãå¹ã |
| èªèšŒã»æš©é | èšããªã | äŒå Ž LAN å ã§ã®ã¿åããåæãæå³çãªæ±ºå®ã§ãããæªæ€èšã§ã¯ãªãïŒÂ§1.3ïŒ |
| å¯Ÿè±¡å€§äŒ | é§è·¯ãåªå ããæå·ã»åæµ·éç³»ãå šåœäº€æµå€§äŒãžæ¡åŒµ | éå¬å¹ŽåºŠã»ã¹ããŒãžå¥ã®èŠåãããã¡ã€ã«ã§å·®åãæã€ïŒÂ§4.1ïŒ |
| å€å®ã®å ¥å | çµäºåå ã»æ®ãã¿ãŒã³ã»å¯©å€è£å®ãåºå¥ | Putè² ããèªæ»
ãã¿ã€ã ã¢ãŠããäžåŸã® blocked ã«ãããšå®èŠåãåçŸã§ããªã |
åœå㯠WebSocket ãåæã«ããŠããããéä¿¡èŠä»¶ãæŽããšä»¥äžã ã£ãã
- Console â ãµãŒããŒ: éåžžã® HTTP ãªã¯ãšã¹ãïŒã¹ã³ã¢å ¥åãç»é¢åæ¿ïŒã§è¶³ãã
- ãµãŒã㌠â Viewer: äžæ¹åã®ããã·ã¥ã®ã¿ãViewer ããã®éä¿¡ã¯ç¡ã
åæ¹åã®ãã¬ãŒã ãå¿ èŠãªç®æãç¡ããããSSE ã§èŠä»¶ãæºãããSSE ãéžã¶å©ç¹ã¯å ·äœçã«ã
- 忥ç¶ãšã€ãã³ã ID ã«ããåãããŒã埩垰ããããã³ã«æšæºïŒ
Last-Event-IDïŒã§æäŸããã - çŽ ã® HTTP ãªã®ã§ããªããŒã¹ãããã·ã»Next.js ã® Route Handler ã«ãã®ãŸãŸèŒã
- socket.io / å¥ããã»ã¹ã® WS ãµãŒããŒãäžèŠã«ãªãããµãŒãã¹ã1ã€æžã
å°æ¥ Viewer åŽããå ¥åãåããèŠä»¶ïŒèг客æç¥šãªã©ïŒãåºãå Žåã®ã¿ WebSocket ã忀èšããã
é§è·¯å€§äŒã¯ä»å€§äŒãšæ¯ã¹ãŠã¹ã³ã¢èšç®ãè€éã§ããã倧äŒããšã«èŠåãå€ããã ãããã¢ããªã®ã³ãŒãã«åã蟌ããšãèŠåãå€ãããã³ã«ãšã³ãžãã¢ã®æ¹ä¿®ãå¿ èŠã«ãªãã ããã§èšç®åŒãããŒã¿ãšããŠå€éšããäžããããæ§é ããæ¬ã·ã¹ãã ã®äžæ žã«æ®ããã
åœåæ¡ã¯ Lua ãŸã㯠Python ã®åŒãå€éšå ¥åãšããŠåã蟌ã¿è©äŸ¡ããæ¹åŒã ã£ããããã¯æ€åããã
- è§Šã£ãŠã»ããçžæã¯éãšã³ãžãã¢ã§ãããã©ããªèšèªã§ãã£ãŠãã³ãŒããæžãããã®ã¯è² æ ã倧ãã
- ä»»æã³ãŒãè©äŸ¡ã¯ãµã³ãããã¯ã¹ã»å®è¡æéã»äŸå€ã®æ±ããèªåã§æ±ããããšã«ãªã
- å¥èšèªã©ã³ã¿ã€ã ãæã¡èŸŒããš TS çµ±äžã®å©ç¹ïŒåå ±æïŒãèšç®åŒã®å¢çã§åãã
代ããã«ãããŒããç¹ãã§èšç®ãçµã¿ç«ãŠãæ¹åŒïŒScratch çãªç·šé UIïŒãæ¡ãã
å®äœã¯ JSON ã®ã°ã©ãã§ãããjsonb ã«æ ŒçŽã㊠TS ã®è©äŸ¡åšã§è§£éããã
ããã«ãããç·šé UIã»ä¿å圢åŒã»è©äŸ¡åšã®ãã¹ãŠãåãå
±æãã1ã€ã® TS äžçã«åãŸãã
äžæ¹ã§ Rume ã®ææã©ãããããŒãæ¹åŒã§ãã£ãŠããä»»æã®åŒãçµãããããšãç®æããšçµå±è€éã«ãªãã çšæããããŒãã®èªåœã¯å€§äŒèŠåã®å®äŸããæ±ºããïŒÂ§5.8 æªæ±ºäºé ïŒã 衚çŸåã¯åŸããè¶³ããããäžåºŠå ¬éããä¿å圢åŒã¯æžãããªããããåçã¯çãå§ããã
Console ã«ãã°ã€ã³ãèšããªããéå¶ãè§Šãã端æ«ã¯äŒå Ž LAN å ã«ããã å€éšããå°éã§ããªããããã¯ãŒã¯ã§éçšããããšãåæãšããã
ãã®å€æãæç«ããæ¡ä»¶ãæèšããŠãããæºãããªããªã£ãæç¹ã§åæ€èšãå¿ èŠã§ããã
- ã¢ããªãäŒå Ž LAN ã®å€ã«å ¬éããªãïŒã€ã³ã¿ãŒãããçµç±ã§ã®éå¶æäœãè¡ããªãïŒ
- é ä¿¡çšã® Viewer ãåã LAN å ã®ãã©ãŠã¶ããéã
- 倧äŒåŸã«ã·ã¹ãã ã皌åããããŸãŸèšé²å ¬éã«äœ¿ãå Žåã¯ã Console ãžã®å°éãå¡ãããããã§åããŠèªèšŒãå°å ¥ããïŒÂ§11ïŒ
ãããã£ãŠãConsole ãš Viewer ããããã¯ãŒã¯çã«åé¢ããå¿ èŠã¯ãªããã Viewer åŽã®ç»é¢ãã Console ãžé·ç§»ã§ããå°ç·ã¯çœ®ããªãïŒé ä¿¡äºæ ãé¿ããããïŒã
CHaserProgressionControlSystem/
âââ chros/ # Next.js (App Router) â Console / Viewer / API ãå
å
â âââ app/
â â âââ console/ # éå¶åãæäœç»é¢
â â âââ display/ # é
ä¿¡çš Viewer ç»é¢
â â âââ api/ # Route Handlers (REST + SSE)
â âââ prisma/
â âââ schema.prisma
â âââ migrations/
âââ packages/
â âââ shared/ # ãã¡ã€ã³åã»ã€ãã³ãå®çŸ©ã»Zod ã¹ããŒãïŒDB éäŸåïŒ
â âââ scoring/ # ã¹ã³ã¢èšç®ã»é äœèšç®ã®çŽç²ããžãã¯
âââ docs/
âââ docker-compose.yaml
âââ pnpm-workspace.yaml
æ¹é:
packages/sharedãšpackages/scoringã¯å¯äœçšãš I/O ãæããªããDBã»HTTPã»React ã«äŸåããªãã ããããŠãããšãåŸã§ API ãå¥ããã»ã¹ã«åãåºã倿ããããšãã«ããã®ãŸãŸæã¡åºããã- Next.js ã¢ããªã®äžã§ã¯ Console / Viewer / API ããã£ã¬ã¯ããªã§åãããŠããã ãã§ããã
äŸåã®åãã¯
chros/** â packages/**ã®äžæ¹åã«éãã
åœå㯠apps/chros/ ãšã㊠monorepo ã®æ
£äŸã©ãã app éå±€ãèšããæ¡ã ã£ãããããã¯æ¡ããªãã
ãã®éå±€ãèŠãã®ã¯å¥ã
ã«ãããã€ãããææç©ãè€æ°ããå Žåã§ãããCHroS ã§ã¯è©²åœããªãããã
æ³å®ããŠããåå± å ã¯ããããå¥ãªããžããªã§ç®¡çããã
| æ³å® | æ±ã |
|---|---|
| 倧äŒåŸã®èšé²å ¬éïŒÂ§11.3ïŒ | å¥ãªããžã㪠|
| CHaServer ã®é£ã«åžžé§ãããã°åã蟌ã¿ïŒÂ§11.3ïŒ | å¥ãªããžã㪠|
ããŒããšãã£ã¿ UIïŒÂ§5.8ïŒãèªåæœéžã¯å·¥æ°ãã倧ããããããããéå¶ã Console ã§è§Šãç»é¢ã§ããã
chros/app/console/** ã®äžéšã«ãããªããæ©èœã®ç¬ç«æ§ãå·¥æ°ã¯ãããã€åäœãåããçç±ã«ãªããªãã
äžæ¹ packages/ 㯠app ã1ã€ã§ãæ®ããå¥ãªããžããªãžæã¡åºãéã«ãã®ãŸãŸåãããšã«å ãã
package.json ã« next / react / prisma ãæãããªãããšã§ã
äžèšã®ãå¯äœçšãš I/O ãæããªããå¶çŽãã¬ãã¥ãŒã§ã¯ãªããã«ãã§å®ãããããã
| é ç® | æ¡çš |
|---|---|
| ããã±ãŒãžãããŒãžã£ | pnpm (workspace) |
| Node.js | 22 LTS |
| TypeScript | 5.x, strict: true, noUncheckedIndexedAccess: true |
| ããªããŒã·ã§ã³ | ZodïŒAPI å ¥åºåã»SSE ãã€ããŒãã®åäžã®çå®ïŒ |
| Lint / Format | ESLint (flat config) + Prettier |
| ãã¹ã | VitestïŒpackages/scoring ã¯å¿
é ãAPI ã¯äž»èŠçµè·¯ïŒ |
| é ç® | æ¡çš |
|---|---|
| ãã¬ãŒã ã¯ãŒã¯ | Next.js 15 (App Router) |
| React | 19 |
| ã¹ã¿ã€ã« | Tailwind CSS v4 |
| Console ã®ããŒã¿ååŸ | Server Components + Server Actions ãåºæ¬ãšãã |
| Viewer ã®ããŒã¿ååŸ | SSE (EventSource) ã«ãã push ã®ã¿ |
Console ã¯ãæäœããŠçµæãè¿ããç»é¢ãªã®ã§ Server Actions ãšåæ€èšŒã§è¶³ããã Viewer ã¯ãç¶æ ã«è¿œåŸãããç»é¢ãªã®ã§ SSEããã®2ã€ãæ··ããªãã
| é ç® | æ¡çš |
|---|---|
| API | Next.js Route Handlers (app/api/**) |
| DB | PostgreSQL 17 |
| ORM | Prisma 6 |
| ãªã¢ã«ã¿ã€ã | SSE (text/event-stream) |
Python (FastAPI, lupa) ã¯å»æ¢ããã¹ã³ã¢èšç®ã¯ packages/scoring ã« TS ã§å®è£
ããã
CHaser ã®ãã°è§£æãå¿
èŠã«ãªã£ãå Žåã TS ã®ããŒãµãšããŠåããã±ãŒãžå
ã«çœ®ãã
æ¢åã¹ããŒããåå°ã«ãé²è¡ç¶æ
ãšå€§äŒã®ã¹ããŒãžãæãããã
Match ã¯è©ŠåãScore ã¯ãã®äžã®1察æŠã®äºå®ãæãã
以äžã¯äž»èŠãã£ãŒã«ãã®èšèšã¹ã±ããã§ãããéåç
§ãäžéšã®åã»å¶çŽãçç¥ããŠããã
ãã®ãŸãŸå®è¡ããPrismaã¹ããŒãã§ã¯ãªãã
enum Side { COOL, HOT }
enum MatchState { PENDING, IN_PROGRESS, REVIEW_REQUIRED, FINISHED }
model Tournament {
id Int @id @default(autoincrement())
name String
edition String // éå¬å¹ŽåºŠã»éå¬å
stages Stage[]
entries Participant[]
}
model Stage {
id Int @id @default(autoincrement())
tournamentId Int
order Int
name String // äºéžã決åãªã©
format Format // BOT_QUALIFYING | ROUND_ROBIN | SINGLE_ELIMINATION
ruleProfileId Int // å¯ŸæŠæ§æã»è£å®ã»èšç®ã»é äœã»ãããèšå®ã®ç¢ºå®ç
matches Match[]
@@unique([tournamentId, order])
}
model RuleProfile {
id Int @id @default(autoincrement())
name String
version Int
sourceReferences Json // URLãæ¹èšæ¥ïŒçïŒcommitïŒhashãæ¡é
ãç¢ºèªæ¥
gamePlan Json // 察æŠåæ°ãCOOL/HOTå²ãåœãŠãåäžãããæ¡ä»¶
gameOutcomePolicy Json // çµäºäºè±¡ãã察æŠåæã決ããæ¡ä»¶ã»åªå
é
replayPolicy Json // èªåå詊åïŒè£å®åŸ
ã¡ãç¡å¹ç¯å²ãæ°ãããç
rankingPolicy Json? // é äœã»çµããšã®ééè
ã»åç¹åŠçãæªç¢ºèªãªãnull
mapPolicy Json // 寞æ³ãã¿ãŒã³ç¯å²ãå
¬éæ¹éã䜿çšãµãŒããŒçç
scoreRuleId Int? // ãã©ãã¯Aã§ã¯æªèšå®å¯ãæ¬æ¡ç¹ã«ã¯æ€èšŒæžã¿çãå¿
èŠ
confirmedAt DateTime? // 察象倧äŒãžã®é©çšæ¡ä»¶ã確èªããæ¥æ
@@unique([name, version])
}
/// ã¹ã³ã¢èšç®èŠåãgraph ã«ããŒãã°ã©ãã® JSON ãæã€ã
/// äžåºŠå€§äŒã§äœ¿çšããèŠåã¯æžãæãããæ°ãã version ãäœãïŒÂ§5.7ïŒã
model ScoreRule {
id Int @id @default(autoincrement())
name String
version Int
graph Json // jsonbãScoreGraph åïŒpackages/sharedïŒ
publishedAt DateTime? // æ€èšŒãééã䜿çšå¯èœã«ãªã£ãæå»
createdAt DateTime @default(now())
@@unique([name, version])
}
model Participant {
id Int @id @default(autoincrement())
tournamentId Int
name String
kind ParticipantKind // COMPETITOR | BOTãBOTã¯éžæé äœã®å¯Ÿè±¡å€
// 察æŠã»ã¹ã³ã¢ãžã®éåç
§
}
model Match {
id Int @id @default(autoincrement())
stageId Int
groupId Int? // ã°ã«ãŒãäºéžãªãæå±ã°ã«ãŒã
order Int // ã¹ããŒãžå
ã®å¯ŸæŠæ ãå詊åã§ãåãå€
attempt Int @default(1)
rematchOfId Int?
ruleProfileId Int // ãã®è©Šè¡ã«é©çšããçãåºå®
state MatchState @default(PENDING)
agent1Id Int
agent2Id Int
firstCoolId Int? // ãããããçã§ç¢ºå®ããåæŠã®å
æ»
sideAssignmentMethod String? // JANKEN | FIXED_BY_RULE | MANUAL
scores Score[]
results MatchResult[] // åèšç®ã»è£å®ã®å±¥æŽãä¿æ
activeResultId Int? // æ¡çšäžã®çµæã倿Žãå±¥æŽã«æ®ã
@@unique([stageId, order, attempt])
}
/// 察æŠã®çããŒã¿ãèšç®çµæã§ã¯ãªãã芳枬ãããäºå®ãã®ã¿ãæã€ã
/// äºå®ãšè£å®ããåŸç¹ç®åºãããã¯ã®ãå
¥åã®ç®±ããæ§æããïŒÂ§5.4ïŒã
model Score {
id Int @id @default(autoincrement())
matchId Int
gameNumber Int // 1ããã1察æŠã®ã¿ã®BotæŠã«åŸåãäœããªã
coolId Int
hotId Int
mapVersionId Int // ãããã®èå¥åãšçãå
容ã®å
¬éãšã¯å¥
turnLimit Int
coolItems Int? // çã®ååŸåæ°ãäžæçã§æªç¢ºèªãªãnull
hotItems Int?
remainingTurns Int? // ç§ã§ã¯ãªããæªç¢ºèªãš0ãåºå¥ãã
endFacts Json // çµäºäºè±¡ã®çš®å¥ã»è¡çºè
ã»åœ±é¿ãåããåŽ
inputRevision Int // èšæ£åã®äºå®ã¯å¥å±¥æŽã«æ®ã
@@unique([matchId, gameNumber])
}
// 察æŠåäœïŒè©Šååäœã®è£å®ã¯å¥ã®è¿œèšåå±¥æŽãšããŠä¿æããã
// 察象IDãäºå®ã®çãé©çšãããã¡ã€ã«ãæ¡çšããçµäºåå ã察æŠåè
ã
// å詊åïŒæå¹ïŒè£å®åŸ
ã¡ãçç±ãè£å®è
ã®èšé²åãæ¥æãæã€ïŒÂ§4.2ïŒã
/// èšç®èŠåã Score ã«é©çšããçµæãã©ã®èŠåã§åºããããå¿
ãæ·»ããã
model MatchResult {
id Int @id @default(autoincrement())
matchId Int
revision Int
ruleProfileId Int // æ¡ç¹ä»¥å€ã®æ¡ä»¶ãå«ãé©çšç
scoreRuleId Int? // æ¡ç¹åã®ç¡å¹åã»è£å®ã ããªãnull
inputRefs Json // å
¥åã»è£å®ã®çãåºå®ããŠåç
§
outcome Outcome // WIN | DRAW | REPLAY | VOID
agent1Output Json? // åºåã¹ãããå -> å€ãæ¡ç¹ããªãçµæãªãnull
agent2Output Json?
winnerId Int?
winReason String? // 決ãæã®ã¹ãããïŒé©çšæ¡é
ãšè£å®çç±
trace Json? // è©äŸ¡ã®äžéå€ãšééããå¶åŸ¡çµè·¯ïŒÂ§5.6 æ€èšŒã»èª¬æçšïŒ
computedAt DateTime @default(now())
@@unique([matchId, revision])
}远å ã»å€æŽã®æå³:
Tournament/Stage: 倧äŒãšäºéžã»æ±ºåãåé¢ãããåäžå€§äŒå ã§Botäºéžãšå¯ŸäººæŠã®èŠåãå€ãããStageGroup/GroupEntryïŒäžã®ã¹ã±ããã§ã¯çç¥ïŒ: ã°ã«ãŒãã®æå±ã¹ããŒãžãšåå è ãæã€ã ã°ã«ãŒãäºéžã§ã¯åãçµã®éžæå士ã ãã察æŠãããé äœã»ééè ãçµåäœã§ç¢ºå®ããã éåžžã®ç·åœããäºéžã¯ã°ã«ãŒããªãã§ã衚ãããçµæ°ãã°ã«ãŒãåãã人æ°ã®éŸå€ã¯åºå®ããªããMatch.order/Match.state: ãä»ã©ã®å¯ŸæŠããã£ãŠããããã DB ã®ç¶æ ãšããŠæã€ã Viewer ã®è¡šç€ºã¯ãã®ç¶æ ããå°åºãããç»é¢åæ¿ã®ããã ãã®ç¬ç«ããç¶æ ãæããªããScore.endFacts: çµäºåå ãæœ°ããä¿åããæå³ä»ããèŠåã«å§ããã æå·ã®çžæPutè² ãã¯æ¯èŒå€0ãèªæ» è² ãã¯è² ã®æ®ãã¿ãŒã³ãšãªããé§è·¯ã®ã¿ã€ã ã¢ãŠãã¯å詊åã« ãªããããåŸæ¥æ¡ã®blocked: Side?ãžã®çµ±åã¯æ€åããïŒÂ§4.2ã§5.4ïŒãMatchResult.winReason: ãã©ã®ãããªåã¡æ¹ãããããã®è¡šç€ºèŠä»¶ïŒåŸç¹è¡šç€ºïŒã«çŽæ¥å¯Ÿå¿ããã çŸè¡ã¯put/lostConnectãã衚瀺åŽãæšè«ããå¿ èŠããããããžãã¯ãæ£ãã å€ã¯ enum ã§ã¯ãªãæååãšãããåå ã¯èŠååŽã®çµç«¯ããŒãæ§æã§æ±ºãŸãããã ã·ã¹ãã åŽã§åæãåããªããMatchResult.agent*OutputãJsonã«ããçç±: äœãåŸç¹ãšããŠå€ã«åºããã¯èŠåãæ±ºããïŒÂ§5.3ïŒã äºéžåŸç¹1ã€ã®èŠåãããã°å婿°ãšè£æ£ã¢ã€ãã æ°ãåºãèŠåããããããåºå®ã«ã©ã ã«ã§ããªãã 衚瀺åŽã¯åºåã¹ãããã®å®çŸ©ïŒååã»è¡šç€ºåã»åïŒãèŠåããåŒããŠæç»ãããScoreãšMatchResultã®åé¢: å ¥åãããäºå®ãšãèŠåãé©çšããçµæãæ··ããªãã èŠåãå€ãã£ããšããäºå®ã¯ãã®ãŸãŸã«çµæã ãåèšç®ã§ããã坿¬æ§ãæ²ãã以äžããã¯è²ããªãã
äºå®ã¯å
ã«ä¿åã§ãããè£å®ãšå¿
èŠãªå
¥åãæã£ãæç¹ã§ packages/scoring ãå®è¡ãã
çµæã MatchResult ã«æ°žç¶åããã衚瀺ã®ãã³ã«åèšç®ããªãã
å
¬åŒè³æã®æ¯èŒã¯ 倧äŒã«ãŒã«èª¿æ» §2â5 ã«ããã
RuleProfile ã¯å®è¡ã³ãŒãã§ã¯ãªãæ€èšŒå¯èœãªããŒã¿ãšããæ¬¡ãäžç·ã«åºå®ããã
- è³æã®åºå žãšçã察象ã®éå¬åã远å 现åãæªç¢ºèªé ç®ãšç¢ºèªèšé²ã
- å¯ŸæŠæ§æ: åçã¯1察æŠãŸãã¯å åŸäº€ä»£2察æŠã察æŠããšã®ããããBotã®åŽãæç€ºããã é§è·¯ã¯ãããããã§æ±ºãŸã£ãåæŠã®COOL/HOTãä¿åãã2æŠç®ã¯åãéžæã®åŽãå転ããã
- 察æŠåæã»å詊åã®æ¡ä»¶è¡šãšåªå é ã詊åã®æ¡ç¹ã°ã©ããé äœãšééè æ±ºå®ã®èšå®ã
- ãããã»éçšæ¡ä»¶: 寞æ³ãã¿ãŒã³äžéãšå¶æ°å¶çŽãå¿çå¶éæéãå ¬éæç¹ããµãŒããŒçã ãããèªåçæãã¯ã©ã€ã¢ã³ãå®è¡ã¯CHroSã®åçã«ã¯å«ããªãã
é§è·¯ãæåã®éçšå¯Ÿè±¡ãšããããæªç¢ºèªã®éèšæ¹æ³ãåæå€ã§åããªãã æå·ã§ã¯Botäºéžãšæ±ºåã§å¥ãããã¡ã€ã«ã䜿ããå šåœäº€æµå€§äŒã¯è©³çŽ°çŽ°åã確èªãããŸã§èæ¡ãšããã èŠåã®æè¡çæ€èšŒãšãéå¶ã«ããé©çšæ¡ä»¶ã®ç¢ºèªã¯å¥ã«èšé²ããèªåæ¡ç¹ã«å¿ èŠãªæªç¢ºèªäºé ã æ®ããããã¡ã€ã«ã¯å ¬éäžå¯ãšããããã©ãã¯Aã®å ¥åã»è¡šç€ºã»è£å®èšé²ã¯æªå ¬éã§ãå®è£ ã§ããã
é§è·¯ã®ã¹ããŒãžæ§æã¯ãäŸé Œè
ïŒå
å®è¡å§å¡é·ã2026-09-18ïŒã®çŸè¡éçšèª¬æãæ ¹æ ã«ã
ROUND_ROBIN ã®äºéžãš SINGLE_ELIMINATION ã®æ¬æŠãåºæ¬ãšããã
ã°ã«ãŒãäºéžãéžãã å Žåã¯çµããšã«ç·åœãããçµã¿ãåçµäžäœ2åãéé察象ãšããã
é äœèŠåãåé äœåŠçãéåžžäºéžã®éé人æ°ãæ¬æŠã®é
çœ®æ¹æ³ã¯å¥ã®èšå®ã»ç¢ºèªäºé
ã
å
¬åŒãµã€ãã®ãäºéžãªãããšã®çžé㯠調æ»è³æU1ã»Â§3.3 ã«èšé²ããã
åæŠã®å åŸãæªç¢ºå®ãªãéå§äžå¯ãšããããããããã®åè ããCOOLãæšå®ããã®ã§ãªãã 確å®ããCOOLã®åå è IDãå ¥åããçžæãHOTãšãããèšé²ããIDã¯ãã®è©Šåã®åå è ã«éãã BotæŠã¯ãããã¡ã€ã«ããå²ãåœãŠããããããå ¥åãèŠæ±ããªãã å詊åã¯å¥è©Šè¡ãªã®ã§ãå åŸãåŒãç¶ããæ±ºãçŽããã確å®ããŠããéå§ããã å察æŠã®COOL/HOTã¯è©Šåã®2åå è ãšäžèŽããå åŸäº€ä»£ã¢ãŒãã§ã¯å¿ ãå転ããããšãæ€èšŒããã ã°ã«ãŒããšè©Šåãåãã¹ããŒãžã«å±ããäž¡åå è ããã®ã°ã«ãŒãã«ç»é²æžã¿ã§ããããšãæ€èšŒããã
èšé²ãã¹ãäºè±¡ã¯ãèŠå®ã¿ãŒã³çµäºãçŽæ¥Putãçžæã«ããå°éãèªåã«ããå°éã ãããã¯ãžã®ç§»åãå Žå€ç§»åãã¯ã©ã€ã¢ã³ãç°åžžçµäºãå¿çã¿ã€ã ã¢ãŠããéä¿¡ãšã©ãŒã ãµãŒããŒé害ã審å€ãèªå®ãããã®ä»ã®ç°åžžãè¡çºè ã»åœ±é¿ãåããåŽã»å ã®èŠ³æž¬æ å ±ãæã€ã åææç«ãä¿åã§ããé åãšããåæã¯ãã®é åã«é©çšãããããã¡ã€ã«ãšè£å®ããæ±ããã
èªåã«ããå°éãšçžæã«ããå°éã¯ãæå·ã®æžç¹ã«å¿
èŠãªããå¥äºè±¡ã«ããã
åå äžæã®éä¿¡æãèªåã§éžæã®è²¬ä»»ãšãããREVIEW_REQUIRED ãžéãã
é§è·¯ã®çŽæ¥Putåªå
ãšãæå·ã®Putã«ããåææç«æã®åå©åªå
ãæ¡ä»¶è¡šã«æèšããã
è£å®å±¥æŽã¯åèšé²ãç·šéãã远èšããçç±ã»è£å®è ã®èšé²åã»æ¥æã»å¯Ÿè±¡ç¯å²ã»é©çšæ¡é ãæ®ãã èªèšŒæ©èœã¯è¿œå ããªãããèšé²åã¯æ¬äººèªèšŒãæå³ããªãã èšæ£ã»åèšç®ã»ç¡å¹åã§æ¡çšçµæãå€ãã£ãããé äœãšåã¡äžãããžã®åœ±é¿ã瀺ãã æ¢ã«éå§ããåŸç¶è©Šåãããå Žåã¯é²è¡ãä¿çããŠéå¶ãåŠçã確å®ããã
æ§ããŒã¿ã® put / lostConnect ã ãã§ã¯æ°ããçµäºåå ã埩å
ã§ããªãå Žåãããã
æšå®ã§èªæ»
ãå°éã«å€æãããæ§çã§ã®çµæãšå
ããŒã¿ãæ®ããåèšç®ã«ã¯åå ã®è£å®ãèŠããã
æ¬ã·ã¹ãã ã®æ žã倧äŒããšã«ç°ãªãè€éãªèšç®èŠåãããšã³ãžãã¢ã®æ¹ä¿®ãªãã«å·®ãæ¿ããããããã«ãã ïŒåæ©ã¯ §1.2ïŒã
[Console: ããŒããšãã£ã¿] --(ScoreGraph JSON)--> [æ€èšŒåš] --> [ScoreRule ããŒãã«(jsonb)]
|
[Score(äºå®)] ------> [è©äŸ¡åš evaluate()] <---+
|
v
[MatchResult(çµæ + trace)]
ãã¹ãŠ packages/scoring ã«çœ®ããI/O ã DB ã React ãåç
§ããªãçŽç²ãª TS ãšãã
è©äŸ¡åšã»æ€èšŒåšã»åå®çŸ©ã1ãæã«ãŸãšãããããã«ããèšç®èŠåã®åäœãã¹ãã容æã«ãªãã
å°æ¥ CLI ãå¥ãµãŒãã¹ããåãèŠåãåå©çšã§ããã
è©äŸ¡åšã®å段ã§ãRuleProfile ã®æ¡ä»¶è¡šãšè£å®å±¥æŽãã察æŠã®æå¹æ§ã»åè
ã»çµäºåé¡ã
確å®ãããåè©Šåæ¡ä»¶ã«è©²åœããã°æ¡ç¹ãã REPLAYã倿ãå
¥åãäžè¶³ããã°
REVIEW_REQUIRED ãšãããããã¯å€§äŒåã§åå²ããåŠçã§ã¯ãªããçãæã€æ¡ä»¶ããŒã¿ã®é©çšã§ããã
æ¡ä»¶è¡šãçŽç²é¢æ°ãšããŠæ€èšŒã»è©äŸ¡ããèŠåã«äžèŽããªãäºè±¡ãé»ã£ãŠæåãžå€æããªãã
ããããã¯ããæŒç®åããããŒãããæ··ãããšè°è«ãæ»ãããã以äžã«åºå®ããã
| çšèª | æããã® | äŸ |
|---|---|---|
| ããã㯠| ç·šéåäœããŠãŒã¶ãŒã远å ã»åé€ã§ããªãåºå®ã®åºç» | åŸç¹ç®åºãããã¯ãåæå€å®ããã㯠|
| ããŒã | ãããã¯å ã«çœ®ãåŠçã®1åäœããŠãŒã¶ãŒãèªç±ã«é 眮ãã | å ç®ããŒããåå€å€å®ããŒã |
| ããŒã | ããŒãã®å ¥åºåã®æ¥ç¶å£ãååãšåãæã€ | left / right / yes / no |
| å€ãšããž | æ°å€ã»çåœå€ãéã¶ç·ãåŸç¹ç®åºãããã¯ã®ã¿ | å ç®ããŒã â åºåã¹ããã |
| å¶åŸ¡ãšããž | ãæ¬¡ã«ã©ã®ããŒããžé²ããããéã¶ç·ãåæå€å®ãããã¯ã®ã¿ | åå€å€å®ã® no â çµç«¯ããŒã |
以éããŠãŒã¶ãŒããæŒç®åããšåŒãã§ãããã®ã¯ããŒããšåŒã¶ã
察人ã®è©Šååæãæ±ããã°ã©ãã¯ã2çš®é¡ã»3ãããã¯ã®æ§é ãæã€ã ãããã¯ã®åäœã¯åå è ã§ãããCOOL/HOT ã®åŽã§ã¯ãªãïŒçç±ã¯åŸè¿°ïŒã
ââ åŸç¹ç®åºããã㯠(åå è
A) ââ ââ åŸç¹ç®åºããã㯠(åå è
B) ââ
â å
¥å: A ã®å¯ŸæŠããŒã¿ â â å
¥å: B ã®å¯ŸæŠããŒã¿ â
â åå COOL ãšã㊠/ åŸå HOTâ â åå HOT ãšã㊠/ åŸå COOLâ
â æŒç®ããŒã矀 â â æŒç®ããŒã矀 â
â åºå: æ°å€ (A ã®åŸç¹) â â åºå: æ°å€ (B ã®åŸç¹) â
ââââââââââââââââ¬ââââââââââââââââ ââââââââââââââââ¬ââââââââââââââââ
â â
ââââââââââââââââââ¬âââââââââââââââââ
v
ââ åæå€å®ããã㯠(1ã€) âââââââââââââââ
â å
¥å: äž¡è
ã®åŸç¹ â
â if ããŒããäž»äœãšããæ¯èŒ â
â åºå: åè
(A / B / DRAW) + åå â
âââââââââââââââââââââââââââââââââââââââââ
åŸç¹ç®åºãããã¯ã®å®çŸ©ã¯1ã€ã ãæã¡ãè©äŸ¡æã«äž¡åå è ãžé©çšããã 2ãããã¯ã«èŠããã®ã¯è©äŸ¡æã®å§¿ã§ãããç·šé察象ã¯1ã€ã äž¡è ã«åãèŠåãåœããããšãæ§é ã§ä¿èšŒã§ãããçæ¹ã ãçŽãå¿ããŠäžå ¬å¹³ã«ãªãããã°ãèµ·ããªãã å æ»/åŸæ»ã«ããå·®ã¯ãããã¯ãåããã®ã§ã¯ãªããå ¥åïŒåå/åŸåãCOOL/HOTïŒãåç §ã㊠ãããã¯å ã®åå²ãšããŠè¡šçŸããã
äžå³ã¯å
åŸäº€ä»£2察æŠã®äŸãBotäºéžã¯1察æŠã®åŸç¹ç®åºãšé äœãžã®åºåã§è¶³ãã
çžæBotã®æç®åŸç¹ãšæ¯èŒããŠè©Šååæã決ãããããã¯ãä»ããªãã
察æŠåæã¯å段ã®è£å®çµæãçšãããpurpose ãš inputShape ã§äž¡è
ãåºå¥ããã
ãã®åå²ãæã€æå³:
- ãäœç¹ã«ãªããããšãã©ã¡ããåã¡ãããæ··ããªãã åŸç¹ç®åºãããã¯ã¯æ°å€ãåºãããšã ãã«è²¬ä»»ãæã¡ã åæã®æŠå¿µãç¥ããªããåæå€å®ãããã¯ã¯åŸç¹ã®äœãæ¹ãç¥ããªãã èŠå倿Žã®å€ãã¯çæ¹ã ãã®ä¿®æ£ã§æžãã
- åŸç¹ç®åºãããã¯ã¯çåŽã¶ãã®å ¥åããåãåããªããçžæã®åŸç¹ãåç §ã§ããªãããã ãçžæãã1ç¹å€ããã°ãã®ãããªæ¯èŒã¯æ§é äžããã«æžãããå¿ ãåæå€å®ãããã¯ã«å¯ãã ãã®å¶çŽããèŠåã®çœ®ãå Žæã®ææ§ããæ¶ãã
- åæå€å®ãããã¯ã®åºåã¯åè ãšåå ã®ã¿ãåŸç¹ãããã§æžãæããããšã¯ã§ããªãã
export type ScoreRuleGraph = {
formatVersion: 1; // ä¿å圢åŒã®çãç§»è¡å€å®ã«äœ¿ã
inputShape: 'single' | 'swap-pair';
points: PointsBlock; // åãå®çŸ©ãåå è
ããšã«é©çš
} & (
| { purpose: 'match-decision'; decision: DecisionBlock }
| { purpose: 'ranking-score'; rankingSlot: string }
);
/** åŸç¹ç®åºãããã¯: å€ãšããžã®ã¿ã®çŽç²ãªåŒãè€æ°ã®å€ãååä»ãã§å€ã«åºã */
export type PointsBlock = {
nodes: PointsNode[];
valueEdges: ValueEdge[];
outputs: OutputSlot[]; // 1ã€ä»¥äžãååã¯åæå€å®ãããã¯ããåç
§ããã
};
export type OutputSlot = {
name: string; // äŸ: 'qualifyingScore' / 'gameWins' / 'adjustedItems'
label: string; // 衚瀺åïŒConsoleã»é
ä¿¡ç»é¢ã§äœ¿ãïŒ
type: 'number' | 'boolean';
from: NodeId; // ãã®å€ãåºãããŒã
fromPort: string;
};
/**
* åæå€å®ãããã¯: å¶åŸ¡ãšããžã®ã¿ã®ãããŒãã£ãŒãã
* å€ã¯ç·ã§éã°ããåããŒãããã©ã®åºåã¹ããããèŠãããã屿§ãšããŠæã€ã
*/
export type DecisionBlock = {
nodes: DecisionNode[]; // åå²ããŒã | çµç«¯ããŒã
controlEdges: ControlEdge[]; // é²è¡å
ãéã¶ãå€ã¯æããªã
entry: NodeId; // å¶åŸ¡ã®éå§ç¹ãã¡ããã©1ã€
};
export type DecisionNode =
| { id: NodeId; kind: 'branch.equal'; slot: string } // æ°å€ã¹ããããåå€ã
| { id: NodeId; kind: 'branch.flag'; slot: string } // çåœã¹ãããã§åå²
| { id: NodeId; kind: 'terminal.higher'; slot: string } // é«ãæ¹ã®åå©
| { id: NodeId; kind: 'terminal.rematch' } // ä»åãçŽãïŒåæŠïŒ
| { id: NodeId; kind: 'terminal.draw' }; // åŒãåã
type ValueEdge = { from: NodeId; fromPort: string; to: NodeId; toPort: string };
type ControlEdge = { from: NodeId; branch: 'yes' | 'no'; to: NodeId };slot ã¯åŸç¹ç®åºãããã¯ã®åºåã¹ãããåã§ãããäž¡åå è
ã®ååã¹ãããã察象ãšããã
a.score ãš b.score ãåå¥ã«ç¹ãã®ã§ã¯ãªãããscore ãæ¯èŒããããš1ã€éžã¶ã
ãããã¯ããšã«äœ¿ããããŒãã®èªåœãå€ãããå šãããã¯å ±éã®èªåœã¯æããªãã
åŸç¹ç®åºãããã¯ïŒåçã®æ³å®ã確å®ã¯ §5.8ïŒ
| åé¡ | äŸ | åè |
|---|---|---|
| å ¥å | §5.4 ã®å ¥åã®ç®± | çžæã®åºåã¹ãããã¯åç §ã§ããªãïŒÂ§5.4ïŒ |
| æŒç® | å æžä¹é€ãmin / max |
|
| æ¡ä»¶ | ifïŒæ¡ä»¶ã»çã®å€ã»åœã®å€ã®3å
¥åïŒ |
å æ»/åŸæ»ã§å·®ãã€ãããå Žåã¯ããã§åå² |
| 宿° | æ°å€ã»çåœå€ | éãšã³ãžãã¢ã調æŽããäž»ãªå¯Ÿè±¡ |
| åºå | åºåã¹ããããæ°å€ãŸãã¯çåœå€ããååãä»ããŠ1ã€ä»¥äž | äžèš |
å
¥åã¯åå è
èŠç¹ã® games[0] / games[1] ãšããã
swap-pair ã§ã¯ asCool / asHot ã®å¥åã䜿ããããsingle ã«ã¯ååšããªãã
ååšããªãåŸåã0ã§è£ãããèŠåã® inputShape ã«åããªãåç
§ãæ§é æ€èšŒã§åŒŸãã
åºåã¯1ã€ã®æ°å€ã«åºå®ããªããäœãããã€å€ã«åºãããèŠåã®äœæè ãæ±ºããã ããã¯å€§äŒããšã®å·®ãåžåããããã«å¿ èŠãªèªç±åºŠã§ããã
- æå·Botäºéž â
qualifyingScoreãåºã - æå·ã®å¯ŸäººæŠ â
gameWinsãšadjustedItemsãåºãïŒÂ§5.5ïŒ - é§è·¯ â èªæ» çã»Putã»ã¢ã€ãã ã®åé¡ãåé¢ããåºåãçšæãããéèšåŒã¯éå¶ç¢ºèªåŸã«ç¢ºå®ãã
åºåã¹ãããã¯ååãšåãæã¡ãåæå€å®ãããã¯ã®åããŒããååã§1ã€éžæããïŒäž¡åå è ã®ååã¹ãããã察象ïŒã åºåã¹ãããã®è¿œå ã»åé€ã»æ¹åã¯ããããåç §ããŠããåæå€å®ãããã¯ãå£ããããæ€èšŒã§æ€åºããïŒÂ§5.6ïŒã
åæå€å®ãããã¯
ãã®ãããã¯ã ãã¯åŒã§ã¯ãªããããŒãã£ãŒãã§ããã å¶åŸ¡ãšããžããã©ã£ãŠé²ã¿ãçµç«¯ããŒãã«å°éããæç¹ã§åæã確å®ããŠè©äŸ¡ãçµããã
åããŒãã¯ãã©ã®ã¹ã³ã¢ãèŠããããéžæãšããŠæã¡ãå€ã¯ç·ã§éã°ãªãã åŸç¹ç®åºãããã¯ã®åºåã¹ããããéžæè¢ãšããŠäžŠã³ããã®äžãã1ã€éžã¶ã
| çš®å¥ | ããŒã | èŠããã® | å¶åŸ¡åºå | æå³ |
|---|---|---|---|---|
| åå² | åå€å€å® | æ°å€ã¹ããã1〠| yes / no |
äž¡è ã®ãã®ã¹ã³ã¢ãçãããã§é²ãå ãåãã |
| åå² | ãã©ã°å€å® | çåœã¹ããã1〠| yes / no |
çåœã®èŠå ã§é²ãå ãåãã |
| çµç«¯ | é«ãæ¹ã®åå© | æ°å€ã¹ããã1〠| ãªã | ãã®ã¹ã³ã¢ã倧ããåŽãåè ãšããŠç¢ºå®ãã |
| çµç«¯ | ä»åãçŽã | ãªã | ãªã | åæãä»ãããåäžã«ãŒãã®åæŠãšãã |
| çµç«¯ | åŒãåã | ãªã | ãªã | åŒãåããšããŠç¢ºå®ãã |
ãä»åãçŽããã¯åŒãåããšã¯å¥ç©ã§ãããäž¡è ãåºå¥ããŠæã€ã é§è·¯ã®è©Šåãšæå·ã®å¯ŸäººæŠïŒÂ§5.5ïŒã¯ãèŠå®ã®æ¯èŒã§ã決ãŸããªããã°å詊åãšãªãã ããã¯BotæŠã®åç¹æåŠçãå®ãããã®ã§ã¯ãªããåŒãåãçµç«¯ã¯å¯Ÿå¿ãæç€ºãããããã¡ã€ã«ã ã㧠䜿ããæªç¢ºèªã®åç¹ãåŒãåã確å®ã«çœ®ãæããªãã
- çµç«¯ããŒãã¯å¶åŸ¡åºåãæããªãã ãããã確å®ããŠçµãããããšã®è¡šçŸã§ããã åºåãç¡ãããšèªäœãæå³ãæ ããçµç«¯ã«å°éããã以éã®ããŒãã¯è©äŸ¡ããªãã
- åå²ããŒãã¯å€ãåºåããªãã çåœå€ãåŸæ®µã«é ã£ãŠäœ¿ãåãã®ã§ã¯ãªãã å¶åŸ¡ã®è¡ãå ãã®ãã®ãåãããçåœå€ãç·ãšããŠæŒããªãã®ã§ã ããã® true ã¯ã©ãã§äœ¿ãããã®ãããèªã¿è§£ãå¿ èŠããªãã
- ãã®ãããã¯ã«å€ãšããžã¯ååšããªããç·ã¯å¶åŸ¡ãšããž1çš®é¡ã ãã§ããã
ã¹ãããã®éžæããã®åœ¹å²ãæãããããã«ããåŸããããã®ã3ã€ããã
- ç·šéããç·ã2çš®é¡åŒãåããããããããããããŠã³ã§éžã¶ãã«èœã¡ãã éãšã³ãžãã¢ã«è§Šããããšããç®çã«å¯ŸããŠãUI ã®é£æã1ã€æ¶ããã
- ç¡æå³ãªæ¥ç¶ãåççã«äœããªãã å€ãšããžããããš
ãA ã®
gameWinsãš B ã®adjustedItemsãæ¯ã¹ãããšããé察称ã§ç¡æå³ãªç¹ãæ¹ãæžããŠããŸãã ã¹ãããã1ã€éžã¶åœ¢ãªããæ¯èŒã¯åžžã«äž¡åå è ã®ååã¹ãããå士ã«ãªãã §5.3 åé ã§è¿°ã¹ãèŠåã®å¯Ÿç§°æ§ããå€å®ãããã¯åŽã§ãæ§é ãšããŠä¿èšŒãããã - åæ€èšŒããç·ã®åæŽåãã§ã¯ãªããéžãã ã¹ãããã®åãããŒãã®èŠæ±ãšåãããã«åçŽåãããã ããããããŠã³ã«åãåã®ã¹ãããã ãã䞊ã¹ãã°ã誀ãã¯éžæè¢ãšããŠååšããªããªãã
å€ãšããžãæã€ã®ã¯åŸç¹ç®åºãããã¯ã ãã«ãªãã§5.2 ã®çšèªè¡šã§ã¯2çš®é¡ã®ç·ãå®çŸ©ããŠãããã 1ã€ã®ãããã¯ãäž¡æ¹ã®ç·ãæã€ããšã¯ãªãã
ãè£æ£ã¢ã€ãã æ°ãã察æŠå婿°ãå ã«æ¯èŒãããæå·ã®å¯ŸäººæŠïŒÂ§5.5ïŒã¯ã åªå 床ãšãã奿Šå¿µãå°å ¥ãããå¶åŸ¡ãšããžãç¹ãé åºã§è¡šçŸããã å ã«çœ®ããåå²ãå ã«è©äŸ¡ãããã
flowchart TD
start[éå§] --> wins{gameWins ãåãã}
wins -->|ããã| winByWins[gameWins ãé«ãæ¹ã®åå©]
wins -->|ã¯ã| items{adjustedItems ãåãã}
items -->|ããã| winByItems[adjustedItems ãé«ãæ¹ã®åå©]
items -->|ã¯ã| replay[ä»åãçŽã]
ç·ã¯å¶åŸ¡ãšããž1çš®é¡ã ãã§ãããåããŒãã®äžã«ãèŠãã¹ã³ã¢ãã®éžæãå
¥ã£ãŠããã
é§è·¯ã®æ¯èŒé ãåå€å€å®ãé£ãã圢ã§è¡šçŸã§ããããæ¯èŒããå€ã®ç®åºæ¹æ³ãå
ã«ç¢ºå®ããå¿
èŠãããã
Botäºéžã®é äœä»ãã¯ãã®å¯ŸäººåæãããŒã䜿ãããã¹ããŒãžã® rankingPolicy ãæ
åœããã
åãèªåœã®ãŸãŸãåå²ã眮ãé ãå ¥ãæ¿ããã ãã§ãåŸç¹ãå ãèŠå ãåŸãã®å€§äŒã«ã察å¿ã§ããã åªå é äœãæ°å€ããã£ãŒã«ãã§æããªããããé åºãå³ãšããŠäžç®ã§èªãããšããå©ç¹ãããã
åå ïŒWinReasonïŒã¯ãã©ã®çµç«¯ããŒãã«å°éããããã®ãã®ã§ããã
å¥éãã£ãŒã«ããšããŠçµã¿ç«ãŠãå¿
èŠã¯ãªããçµç«¯ããŒãã®çš®å¥ãšã
ããã«ç¹ãããŠããåºåã¹ãããåïŒäŸ: gameWins ã§æ±ºçïŒãèšé²ããã°è¶³ããã
ãã㯠traceïŒÂ§5.6ïŒãšãèªç¶ã«äžèŽããã
æ¡ç¹åã«å詊åã»å€±æ Œçã®è£å®ã§æ±ºããå Žåã¯ãçµç«¯ããŒãã®ä»£ããã«æ¡ä»¶è¡šã®æ¡é
ãšè£å®çç±ãèšé²ããã
ããã§ A / B 㯠Match.agent1 / agent2 ãæãã
è©äŸ¡åšã¯çµæãå®éã® Participant.id ã«è§£æ±ºããŠãã MatchResult ã«æžãã
å¶åŸ¡ãããŒãæã€ã®ã¯åæå€å®ãããã¯ã ãã§ãããåŸç¹ç®åºãããã¯ã«ã¯å¶åŸ¡ãšããžãå®çŸ©ããªãã åŸç¹ç®åºã¯åžžã«å šããŒããè©äŸ¡ããŠåºåã¹ããããåããçŽç²ãªåŒã®ãŸãŸãšããã
å¶çŽãšããŠã
- ã«ãŒãæ§é ãæããªããå€ãšããžã»å¶åŸ¡ãšããžã®ã©ã¡ãã«ã€ããŠããã§ããã
ããŒãã®ååž°åç
§ãšåŸæ¹ãžã®èŸºãæ€èšŒåšã§åŒŸããäž¡æ¹ã®ã°ã©ãã DAG ã«éãã
å¶åŸ¡ãšããžãå°å
¥ãããšãããŒãã£ãŒãã«ãªããæ»ãç·ããåŒããããªããããããèš±ããç¬éã«
äžèšã®ä¿èšŒããã¹ãŠå€±ããããããæç€ºçã«çŠæ¢ããã
ããã¯æå³çã«ãã¥ãŒãªã³ã°å®å
šæ§ãæšãŠãèšèšå€æã§ãããèŠè¿ããšããŠæ¬¡ãç¡æ¡ä»¶ã«åŸãã
- 忢æ§ãæ§é çã«ä¿èšŒãããã å®è¡æéã®ç£èŠãã¿ã€ã ã¢ãŠããç¡éã«ãŒãã®æ€åºãäžèŠã«ãªãã
- ç¶æ ãæããªãã è©äŸ¡ã¯å ¥åããåºåãžã®ååã§ãããéäžçµéã芳枬ã«åœ±é¿ããªãã ãã®ããä»»æã®é ã§è©äŸ¡ããŠããéäžã§æã¡åã£ãŠåéããŠãçµæãåãã«ãªãã
- éçã«å šããŒãã®å€åãšåã远ããã æ€èšŒïŒÂ§5.6ïŒãå®è¡ãªãã§å®çµãã ãšãã£ã¿äžã§ãç¹ãã ç¬éã«èª€ããåããã圢ã«ã§ããã
- trace ãåžžã«æéã§å šããŒãã¶ãåããã 説æå¯èœæ§ïŒÂ§5.6ïŒãããã«äŸåããã
- ãããã¯éã®æ¥ç¶ã¯åºå®ã§ããããŠãŒã¶ãŒãç·šéã§ããã®ã¯åãããã¯ã®å åŽã ãã ãããã¯ãè·šã蟺ããããã¯ã®è¿œå ã»åé€ã¯ã§ããªãã
- ããŒãã®çš®å¥ã¯åæåã§ãããä»»æã®é¢æ°åŒã³åºããã³ãŒãçã¯æãŠãªãã
- è©äŸ¡ã¯çŽç²ãä¹±æ°ã»çŸåšæå»ã»å€éšåç §ãæã€ããŒããå®çŸ©ããªã ïŒæœéžãªã©ä¹±æ°ãèŠãæ©èœã¯ã¹ã³ã¢èšç®ãšã¯å¥ç³»çµ±ã§æ±ãã§5.8ïŒã
察人詊åã®è©äŸ¡é åºã¯ points(åå è
A) â points(åå è
B) â decision ã«åºå®ããã
å2ã€ã¯åäžã®å®çŸ©ãç°ãªãå
¥åã§è©äŸ¡ããã ãã§çžäºã«äŸåããªãããã
é åºãå
¥ãæ¿ããŠãçµæã¯å€ãããªãïŒäžèšã®ç¡ç¶æ
æ§ã«ããïŒã
ããã«ããèŠåã®å¯Ÿç§°æ§ãæ§é çã«ä¿èšŒãããã
ãA ã«æå©ãªåŒãçŽã蟌ãã§ããªããããæ€èšŒããå¿
èŠãç¡ãã
é察称æ§ã¯åæå€å®ãããã¯ã«æžãããå Žåã«ã®ã¿çºçãããã®ã§ãã¬ãã¥ãŒç¯å²ãããã«éå®ãããã
Botäºéžã¯ points ã®æå®ã¹ããããé äœèšç®ãžæž¡ãã詊åã®æ¡ç¹çµæã«ã¯å段ã§ç¢ºå®ãã
察æŠåè
ãšåå è
ã®åŸç¹ãæ®ããBotãé äœå¯Ÿè±¡ããé€ãã®ã¯ã¹ããŒãžåŽã®è²¬åãšããã
åŸç¹ç®åºãããã¯ãåç §ã§ããå ¥åããç®±ããšããŠå®çŸ©ããã ç®±ã¯åå è 1人ã¶ãã®ã1詊åã¶ãã®äºå®ã衚ãã
åçã§çšæããç®±ïŒgames[n]. ã®äžã«çœ®ãã以äžã¯èªåã®1察æŠã¶ãã®äžèЧïŒ:
| ç®± | å | å 容 |
|---|---|---|
items |
number | çã®ååŸã¢ã€ãã æ°ãè£æ£å€ã§äžæžãããªã |
remainingTurns |
number | çµäºæã®æ®ãã¿ãŒã³æ°ãremainingTimeïŒç§ïŒãšã¯åãã |
selfWon / selfLost |
boolean | çµäºäºè±¡ãšé©çšèŠåã»è£å®ãã確å®ãã察æŠåæ |
lostByOpponentPut |
boolean | çžæã®çŽæ¥Putã«ããæåãšããŠç¢ºå® |
lostByOpponentEnclosure |
boolean | çžæããã®å°éã«ããæåãšããŠç¢ºå® |
lostBySelfBlockMove / lostBySelfEnclosure |
boolean | èªæ» ã®çš®é¡ãåºå¥ããæå |
lostByOutOfBounds |
boolean | èªãã®å Žå€ç§»åã«ããæåãšããŠç¢ºå® |
lostByClientCrash / lostByCommunicationError |
boolean | ç°åžžçµäºãšè²¬ä»»ã®ç¢ºå®ããéä¿¡ãšã©ãŒã«ããæå |
lostByAdjudicatedClientFault |
boolean | ãã®ä»ã®ç°åžžãè£å®ã§æåæ±ããšãããã® |
opponentLostBy⊠|
boolean | äžèšãšåãåé¡ãçžæåŽã«ã€ããŠåç § |
isCool |
boolean | ãã®å¯ŸæŠã§èªåãCOOLã ã£ãã |
ãããã¯åèšé²ãäžæžããããã£ãŒã«ãã§ã¯ãªãã§4.2ã®äºå®ãšçãåºå®ããè£å®ããäœã
è©äŸ¡çšã®å
¥åãã¥ãŒã§ãããå€±æ Œã»å詊åã»è£å®åŸ
ã¡ã¯åæ®µã§æ±ããselfLost ãžæŒã蟌ãŸãªãã
çŽæ¥Putãšèªåã®å°éã®åææç«ã§ã¯ã芳枬äºè±¡ã¯äž¡æ¹æ®ããæå ã®ç®±ã«ã¯åå©åªå
ãé©çšãã
æçµåé¡ãå
¥ãããæªç¢ºå®ã®åæãfalseïŒfalseãšããŠæ¡ç¹ã«é²ããªãã
remainingTurns ã¯æŽæ°ã〠0 <= remainingTurns <= turnLimitãã¢ã€ãã æ°ã¯éè² æŽæ°ãšããã
è£æ£åŸã®å€ã¯è² æ°ã蚱容ãããæªå®æœã®å¯ŸæŠãšæªå
¥åå€ã¯0ã«å€æããªãã
èŠå®ã¿ãŒã³çµäºæã®åæãªã©ãèŠåããæ±ºãŸãå€ãšå
¥åããè£å®ã«ççŸãããã°ç¢ºèªãæ±ããã
ã¿ã€ã ã¢ãŠããšéä¿¡ãšã©ãŒã¯å¥äºè±¡ã§ãããé§è·¯ã®ã¿ã€ã ã¢ãŠãããã®è¡šã®æåãžèªå倿ããªãã
§5.3 ã§ãåŸç¹ç®åºãããã¯ã¯èªåã®å€ã®ã¿ãåç §ã§ããããšè¿°ã¹ãããæ£ç¢ºã«ã¯æ¬¡ã®ãšããã
- åç §ã§ããªã: çžæã®åºåã¹ãããïŒçžæã®ç®åºæžã¿åŸç¹ïŒã ãããèš±ããšåŸç¹ç®åºãçžäºåç §ã«ãªãã察称æ§ã®ä¿èšŒãšãããã¯åå²ã®æå³ã倱ãããã
- åç
§ããŠãã: çžæã«ã€ããŠã®äºå®ãšç¢ºå®æžã¿ã®çµäºåé¡ïŒ
opponentLostByClientCrashãªã©ïŒã é§è·¯ã§ã¯çžæã®èªæ» çã«ããåå©ãšPutåã¡ãåºå¥ãããããçžæã®çµäºåå ãå¿ èŠã«ãªãã
å¢çã¯ã芳枬ã»è£å®ã«åºã¥ãå ¥åããçžæã®ç®åºæžã¿ã¹ã³ã¢ããã§ããããèªåããçžæããã§ã¯ãªãã
ç®±ãå¢ããå Žåã¯å
ã®äºå®ã»è£å®ã®ä¿åæ¹æ³ãšå
¥åã¹ããŒããæŽæ°ãã
äºææ§ã®ãªã倿Žã¯ formatVersion ãäžããã
ç®±ã¯åŸããè¶³ããããäžåºŠå
¬éããç®±ã¯æžãããªãã
ãªããã¢ã€ãã æ°Ã3 + æ®ãã¿ãŒã³æ°ãã®ãããªåæã¯ç®±ãšããŠã¯æããªãã ããã¯åŸç¹ç®åºãããã¯ã§çµã¿ç«ãŠããã®ã§ããïŒÂ§5.5 ã®BotäºéžïŒã ç®±ã®åŽã§åæããŠããŸããšèŠåãå·®ãæ¿ãããããšããåæã厩ããã
2026-09-18ã«å
¬éè³æãç
§åããåŸæ¥ã®å¿åã®ã倧äŒAïŒå€§äŒBãã®äŸã眮ãæããã
以åã®ãç¹æ®ãã€ã³ã1çš®é¡ããšãå
šå€§äŒã§ååŸåã® itemsÃ3 ± remainingTime ãåç®ããã
ãšãã説æã¯ã察象倧äŒã®å®èŠåã衚ããŠããªãã
åºå
žãšæ°å€ä»ãã®åãå
¥ãäŸã¯ 倧äŒã«ãŒã«èª¿æ» §3â6 ã«ãŸãšããã
å ¬é现å§1-3ã®æ¯èŒé ã¯ çžæã®èªæ» çã«ããåå© â Putåã¡ â ã¢ã€ãã æ°åªå¢ã ååé¡ãå¥ã¹ãããã«ããåå€ãªã次ã®ã¹ããããžé²ãæ§é ã¯æ¡çšã§ããã ãã ããååŸåãéèšããå ·äœåŒã¯éå¶ç¢ºèªåŸã«ç¢ºå®ããã åé¡ããšã®åå©åæ°ãåèšããæ¡ãéã¿ä»ãã®ä¿æ°ããå ¬åŒã«ç¢ºå®ãã仿§ãšããŠå®è£ ããªãã
å ¬é现å§1-4ã®åè©Šåæ¡ä»¶ã¯ããã®ã¹ãããæ¯èŒããå ã«å€å®ããã å¿çã¿ã€ã ã¢ãŠãããµãŒããŒé害ãªãå詊åã審å€å€æãå¿ èŠãªãè£å®åŸ ã¡ãšãªãã æ¡ç¹å¯Ÿè±¡ã«ãªã£ã詊åã ããã°ã©ãã«æž¡ãã
åæµ·é倧äŒã«ãŒã«ããã¯v3.1.0 p.4ã«ããã
inputShape: 'single'ãpurpose: 'ranking-score' ãšããBotãHOTã®1察æŠãæ¡ç¹ããã
qualifyingScore = games[0].items * 3
+ (games[0].selfWon ? games[0].remainingTurns : -games[0].remainingTurns)
äžåŒã®åæã¯å¯ŸæŠåæã®ç¢ºå®ã§ãããæªç¢ºå®ã»åç¹ãè² ãã®åå²ãžå
¥ããªãã
åå éžæã® qualifyingScore ãé äœèšç®ãžæž¡ããååšããªãåŸåã®å€ã¯èŠæ±ããªãã
åãã«ãŒã«ããã¯ã®åããŒãžã§ãBotæŠãšã¯å¥èŠåã
inputShape: 'swap-pair'ãpurpose: 'match-decision' ãšããåããããã§å
åŸäº€ä»£ã®2察æŠãæ±ãã
| ã¹ããã | ç®åºæ¹æ³ |
|---|---|
gameWins |
2察æŠã® selfWon ? 1 : 0 ã®åèš |
adjustedItems |
å察æŠã®äžèšè£æ£å€ã®åèš |
å察æŠã®è£æ£å€ã¯ãçžæPutïŒçžæããã®å°éã«ããæåãªã0ã
èªåã®ãããã¯ç§»åïŒèªå·±å°éïŒèªåã«èµ·å ããéä¿¡ãšã©ãŒçã«ããæåãªã
-remainingTurnsããã以å€ã¯çã® itemsã
倿ã§ããªãçµäºåå ãããã以å€ãã«èœãšãããå
ã«è£å®ã§åé¡ããã
åå€å€å®(gameWins)
no -> é«ãæ¹ã®åå©(gameWins)
yes -> åå€å€å®(adjustedItems)
no -> é«ãæ¹ã®åå©(adjustedItems)
yes -> ä»åãçŽã
- æ°å€ã»çåœå€ãå æžä¹ç®ã
ifãè€æ°ã®åºåã¹ããããåå€å€å®ã倧å°ã«ããåå©çµç«¯ã§ã æå·ã®ç¢ºèªæžã¿èšç®ã衚çŸã§ãããè€æ°æå ã®å€å®ã¯ifã®é£çµã§æžããã - 1ïŒ2察æŠã®å ¥åæ§æãšãæ¡ç¹åã®çµäºåå ã»å詊ååŠçãå¥éå¿ èŠã åŸç¹ã°ã©ãã ãã§å€§äŒã®å šéå¶èŠåã衚çŸã§ãããšã¯ããªãã
- é§è·¯ã®éèšåŒãšå šåœäº€æµå€§äŒã®è©³çŽ°çŽ°åã¯æªç¢ºå®ãå šå€§äŒãžã®ååæ§ã¯ãŸã 䞻匵ããªãã
ãä»åãçŽããã«å°éãã察æŠã¯ãåæãæªç¢ºå®ã®ãŸãŸåæŠãè¡ãã
æ¢åã® Score ãæžãæããŠäžæžããããšäºå®ã倱ããããããåæŠã¯æ°ãã Match ãšããŠäœãã
model Match {
// ...
attempt Int @default(1) // äœåç®ã®å¯ŸæŠã
rematchOfId Int? // ä»åãçŽãã®å
ã«ãªã£ã Match
rematchOf Match? @relation("Rematch", fields: [rematchOfId], references: [id])
rematches Match[] @relation("Rematch")
}- å
ã®
Matchã¯MatchResultã«ãä»åãçŽããã®çµæãæ®ãããŸãŸç¢ºå®ãããoutcome=REPLAYãwinnerId=nullãšããé äœã»åã¡äžãããžã®å¯äžãç¡å¹ã«ããã - é äœèšç®ã¯æçµçã«æå¹ãšç¢ºå®ãã詊è¡ã ããæ°ããä»åãçŽãã«çµãã£ã詊è¡ã¯é€å€ããã åŒãåã確å®ãèªããå¥ãããã¡ã€ã«ã§ã¯ããã®åŒãåããé äœèŠåã«åŸã£ãŠæ±ãã
- é
ä¿¡ç»é¢ã«ã¯ãä»åãçŽãããæç€ºã§ããããã«ããïŒÂ§8 ã®
resultç»é¢ïŒã - é§è·¯ã¯åå ãåŸåã ãã§ãæ°ãããã§ååŸåãšãããçŽããååã®åŸç¹ãæã¡è¶ããªãã
- æå·ã®å¯ŸäººæŠãåç¹æã¯æ°ãããã§å詊åãšãããBotæŠã®æªç¢ºèªã®åç¹åŠçã«ã¯æµçšããªãã
- å詊åã¯åã
stageId/orderãæã¡attemptãå¢ãããå 詊è¡ãæ®ããŠã äžæå¶çŽã«è¡çªãããåãå¯ŸæŠæ ããäºéã«åã¡äžãããªãããã«ããã
ãææ§ãªç¶æ ãé²ããããšãæç€ºçãªä»çµã¿ãšããŠæã€ãèŠåã¯æ€èšŒãééãããŸã§å€§äŒã«é©çšã§ããªãã
æ€èšŒã¯5段éã§è¡ãã
ãã®åæãšããŠããããã¡ã€ã«ã®å¿
é èšå®ã»ç¢ºèªç¶æ³ãinputShape ãšå¯ŸæŠæ§æã®æŽåãæ€èšŒããã
ranking-score ã§ã¯åŸç¹ç®åºãšé äœçšã¹ããããæ€èšŒãã以äžã®åæå€å®ãããã¯åºæã®æ€èšŒã¯
match-decision ã®ã¿ãžé©çšãããååšããªã察æŠãžã®åç
§ãäžæãªçµäºåå ãæªç¢ºå®ã®åæã
æªå
¥åå€ãæªèšå®ã®æ®ãã¿ãŒã³ãå«ãçµæã¯æ¬æ¡ç¹ãžæž¡ããªãã
-
æ§é æ€èšŒ: Zod ã¹ããŒãé©åãåŸç¹ç®åºãããã¯ã®å€ãšããžãš åæå€å®ãããã¯ã®å¶åŸ¡ãšããžããããã DAG ã§ããããšã æªæ¥ç¶ã®å ¥åããŒããç¡ãããšãå°éäžèœãªããŒããç¡ãããšã ãããã¯ãè·šã蟺ãç¡ãããšããã®ãããã¯ã§èš±å¯ãããçš®å¥ã®ããŒãã®ã¿ã䜿ã£ãŠããããšã åŸç¹ç®åºãããã¯ã¯åºåã¹ãããã1ã€ä»¥äžãããååãéè€ããŠããªãããšã
-
å¶åŸ¡ãããŒæ€èšŒïŒåæå€å®ãããã¯ã®ã¿ïŒ:
entryãã¡ããã©1ã€ããããšã- ãã¹ãŠã®å¶åŸ¡çµè·¯ãçµç«¯ããŒãã«å°éããããšã åå²ããŒãã®
yes/noã®ãã¡ çæ¹ã§ãç¹ãã£ãŠããªããã°æ€èšŒãšã©ãŒãšããã - çµç«¯ããŒãããåºãå¶åŸ¡ãšããžãç¡ãããšã
- å°éãããçµç«¯ã1ã€ãç¡ãããŸãã¯å°éã§ããªãçµç«¯ãããå Žåã¯ãšã©ãŒãšããã
ãã®æ®µããææ§ãªç¶æ ãé²ããã®å®äœã§ãããå€å®æŒãïŒåæã決ãŸããªãç¶æ ãã å®è¡æã®äŸå€ã§ã¯ãªãèŠåã®ä¿åæã«æ§é ãšããŠåŒŸãã ã«ãŒããç¡ããããå šçµè·¯ã®åæã¯æéã§ç¶²çŸ çã«è¡ããã
-
ã¹ãããåç §æ€èšŒ: åæå€å®ãããã¯ã®åããŒããéžãã§ãã
slotãã åŸç¹ç®åºãããã¯ã«å®åšãããã€ããŒãã®èŠæ±ããåãšäžèŽããããš ïŒåå€å€å®ã»é«ãæ¹ã®åå©ã¯æ°å€ããã©ã°å€å®ã¯çåœå€ïŒã ã¹ãããã®æ¹åã»åé€ã§å€å®åŽãå£ããã®ãä¿åæã«æ€åºããã ãŸããã©ã®ããŒããããéžã°ããŠããªãåºåã¹ãããã¯èŠåãšããŠæç€ºãã ïŒè¡šç€ºå°çšãšããŠæå³çã«åºãå Žåãããããããšã©ãŒã«ã¯ããªãïŒãã¹ããããéžæã«ããããšã§ããã®æ€èšŒã¯ãšãã£ã¿ã®ããããããŠã³ã« é©åããåã®ã¹ãããã ãã䞊ã¹ãããšãšç䟡ã«ãªãã 誀ããæ€åºããã®ã§ã¯ãªããéžæè¢ãšããŠååšãããªã圢ã«ã§ããã
-
åæ€èšŒïŒåŸç¹ç®åºãããã¯ã®ã¿ïŒ: å€ãšããžã®ããŒãéã®åïŒæ°å€ / çåœå€ïŒã®æŽåã ã«ãŒããç¡ãããããã®æ€èšŒã¯è©äŸ¡ããã«å®äºããã åæå€å®ãããã¯ã«ã¯å€ãšããžãç¡ãããããã®æ®µã®å¯Ÿè±¡å€ãšãªãã
-
æ¯ãèãæ€èšŒ: èŠåããšã«ãã¹ãã±ãŒã¹ïŒå ¥åã®
ScoreãšæåŸ ããçµæã®çµïŒãç»é²ã§ããã éå»å€§äŒã®å®ããŒã¿ãæµããçµæãå€ãããªãããšã確èªããååž°ãã¹ããšããŠäœ¿ãã
倧äŒã«ãŒã«èª¿æ» §6.1 ã®äŸãåãå ¥ãåºæºã«å«ããã ç¹ã«çžæPutãšèªæ» ã®è£æ£å·®ãBotæŠã®è² åŸç¹ãé§è·¯ã®åŸåé害ã«ããå šè©Šåç¡å¹åã åææç«ã®åªå é äœããããããåŸã®åŽäº€æãã°ã«ãŒãäºéžã®ééå¢çã確èªããã æåŸã®3ã€ãªã©ãæ¡ç¹é¢æ°ä»¥å€ã®æ¡ä»¶è¡šã»é²è¡åŠçã«ãæ€èšŒå¯Ÿè±¡ãããããšã«æ³šæããã
è©äŸ¡åšã¯ trace ãè¿ããMatchResult.trace ã«ä¿åããã察人詊åã®ã°ã©ãã®traceã¯2éšæ§æã«ãªãã
- åŸç¹ç®åºãããã¯: åããŒãã®äžéå€ïŒãªããã®ç¹æ°ã«ãªã£ããïŒ
- åæå€å®ãããã¯: ééããå¶åŸ¡çµè·¯ãšãå°éããçµç«¯ããŒãïŒãªããã®åæã«ãªã£ããïŒ
åŸè ã¯å¶åŸ¡ãšããžãå°å ¥ããããšã§èªç¶ã«åŸãããããåå€å€å®(score) â no â é«ãæ¹ã®åå©(score)ããšãã çµè·¯ãã®ãã®ã説æã«ãªã£ãŠãããéãšã³ãžãã¢ãèŠåãä¿¡é Œããæ¡ä»¶ãæºããã Botäºéžã«ã¯åŸç¹ç®åºã®traceã ãããããåæ®µã®åå åé¡ã»è£å®ã®åç §ã¯å¥éå ±éã§æ®ãã
- äžåºŠå€§äŒã§äœ¿çšãã
ScoreRuleã¯æžãæããªããç·šéã¯æ°ããversionã®äœæãšããŠæ±ãã RuleProfileãåæ§ã«çãåºå®ãããè³æã®æŽæ°ã§æ¡çšçãèªåçã«åãæ¿ããªããMatchResultã¯èŠåã»ãããã¡ã€ã«ã»å ¥åã»è£å®ã®åç §çãä¿æããéå»ã®çµæãåçŸããã- 倧äŒäžã«èŠåã®èª€ããèŠã€ãã£ãå Žåã¯ãæ°çãäœãã圱é¿ãã
Matchãæç€ºçã«åèšç®ããã åèšç®ã¯éå¶ã®æäœãšããŠè¡ããæé»ã«èµ°ãããªãã - æ°çµæã¯è¿œèšããŠæ¡çšçµæãåãæ¿ããæ§çµæãæ®ããé äœãééè ã«ãé©çšçãšå ¥åçµæã®çã æããã詊åçµæãèšæ£ããå Žåã¯å確å®ãå¿ èŠãªç®æãç¹å®ã§ããããã«ããã
- é§è·¯ã®ååŸåéèš: å€å®ã®åªå é ãš2察æŠãéèšããéçšã¯ç¢ºèªæžã¿ã ååé¡ã®æ°å€çãªéã¿ã»åç®ã»ã¢ã€ãã ã®æ¯èŒç¯å²ã確å®ããå®äŸã§æ€èšŒããã
- å šåœäº€æµå€§äŒã®çްå: éå¬åãç¹å®ããŠå ¥æããæ¢åã®å ¥åãšããŒãã§è¡šããã確èªããã æå·ã®èšç®äŸã衚ããã ãã§ã¯å šåœå¯Ÿå¿ãå®äºããããšã«ãªããªãã
- å ¥åãšæ¡ä»¶è¡šã®ä¿å圢åŒ: §4.2ã»Â§5.4ã®äºè±¡ã»è£å®ã»å ¥åãã¥ãŒã«ã€ããŠã Zodã¹ããŒããšçç§»è¡ã確å®ãããå¿ èŠãªåå åé¡ãçç¥ããŠç°¡çŽ åããªãã
min/maxããŒãã®èŠåŠ: §5.5ã®ç¢ºèªæžã¿èšç®ã§ã¯äœ¿ã£ãŠããªãã å®éã«äœ¿ãèŠåãçŸãããŸã§å®è£ ãä¿çããŠããã- åå²ããŒãã®è¿œå : åçã¯ãåå€å€å®ãããã©ã°å€å®ãã®2ã€ã
ãæå®å€ä»¥äžãããªã©ã®æ¯èŒãå¿
èŠã«ãªãããå®äŸã§ç¢ºèªããã
§5.5ã®æå·ã®èšç®äŸã§ã¯çåœå€ãåŸç¹ç®åºã®
ifã§æ¶è²»ã§ããã åæå€å®ã®ãã©ã°åå²ãå®è£ ããå Žåã¯ãäž¡è ã®å€ãéããšãã®æå³ãå ã«å®ããã - åºåã¹ããããšè¡šç€ºã®çµã³ã€ã: é ä¿¡ç»é¢ïŒÂ§8ïŒãåºåã¹ããããã©ãæç»ãããã ã¹ãããå®çŸ©ããé§åããæ¹éã¯Â§8.2ã§ç¢ºå®æžã¿ã衚瀺å°çšã¹ããããåŒ·èª¿æ¹æ³ã®è©³çްã¯åŸç¶ã§æ±ºããã
- ä»åãçŽãã®åæ°äžé: åæŠãç¹°ãè¿ããŠãåç¹ãç¶ããå Žåã®æ±ãã èŠååŽã§ã¯è¡šçŸã§ããªããããéå¶ã®å€æã§æã¡åãéçšãšãããã 倧äŒèšå®ãšããŠäžéåæ°ãæã€ããæ±ºããïŒÂ§5.5ïŒã
- åŒãåãã®æ±ã: ãåŒãåããçµç«¯ã«å°éãã察æŠãã ç·åœããæŠã®é äœèšç®ãã©ãè§£éãããïŒÂ§11 ã®é äœæ±ºå®èŠåãšæ¥ç¶ããïŒã BotæŠã®å¯ŸæŠèªäœãåç¹ãšãªã£ãå Žåãäºéžã®ååŸç¹é äœã¯ã察人詊åã®å詊åãšã¯å¥ã«ç¢ºèªããã
- 3ãããã¯ã§è¶³ããªãèŠåãåºãå Žåã®æ¡åŒµæ¹æ³: ãããã¯æ§æã¯åºå®ã§ããã
ãŠãŒã¶ãŒã¯è¿œå ã§ããªããæ§æèªäœã®å€æŽã¯
formatVersionãäžããç§»è¡ãšããŠæ±ãã - èªåæœéžã·ã¹ãã : 察æŠçµã¿åããã®èªåçæãä»åŸã®ç®æšãšããåçã®ã¹ã³ãŒãå€ã
ä¹±æ°ãå«ãããã¹ã³ã¢èšç®ã°ã©ããšã¯åé¢ããæœéžçµæã¯ç¢ºå®å€ãšããŠ
Matchã«æ°žç¶åããã
GET /api/stream â text/event-stream
- å
š Viewer ãåäžã¹ããªãŒã ã賌èªããã倧äŒåäœã§åãããå Žåã®ã¿
?tournamentId=ãåããã - æ¥ç¶æã«ãŸãçŸåšã®å®å šãªç¶æ ïŒã¹ãããã·ã§ããïŒã1ä»¶éããViewer ã¯åæååŸã®ããã® å¥ API ãå©ããªããŠããã
- 以éã¯å·®åã€ãã³ããéãã
- åã€ãã³ãã«å調å¢å ã®
id:ãä»äžããLast-Event-IDãããã«ããåéã«å¯Ÿå¿ããã åéäžèœãªã»ã©å€ãå Žåã¯ã¹ãããã·ã§ãããéãçŽãã - 15 ç§ããšã«ã³ã¡ã³ãè¡ (
: ping) ãéåºãããããã·ã«ããã¢ã€ãã«åæãé²ãã
å㯠packages/shared ã«çœ®ãããµãŒããŒãš Viewer ãåãå®çŸ©ã import ããã
| event | ãã€ããŒã | æå³ |
|---|---|---|
snapshot |
äžèš Snapshot |
æ¥ç¶çŽåŸã»åŸ©åž°æã®å šç¶æ |
screen.changed |
{ screen: ScreenId } |
é ä¿¡ç»é¢ã®åãæ¿ã |
match.started |
{ matchId } |
察æŠéå§ |
match.scored |
{ matchId, gameNumber, ... } |
1察æŠã®äºå®ã»è£å®ã»ç®åºå€ã®æŽæ° |
match.finished |
察æŠçµæ | 察æŠçµäºïŒä»åãçŽããå«ãïŒ |
standings.updated |
é äœè¡š | é äœã®åèšç®çµæ |
// packages/shared/src/events.ts
export type ChrosEvent =
| { type: 'snapshot'; payload: Snapshot }
| { type: 'screen.changed'; payload: { screen: ScreenId } }
| { type: 'match.started'; payload: { matchId: number } }
| { type: 'match.scored'; payload: ScorePayload }
| { type: 'match.finished'; payload: MatchResultPayload }
| { type: 'standings.updated'; payload: Standings };
/** æ¥ç¶çŽåŸã«1ä»¶éããViewer ãå
šç»é¢ãæãã®ã«å¿
èŠãªãã®ãæŒããªãå«ãïŒÂ§8.4ïŒ */
export type Snapshot = {
screen: ScreenId;
tournament: { id: number; name: string; edition: string };
stages: StageView[]; // æ¹åŒãã°ã«ãŒããèŠåçãå
¬éçšã®å¯ŸæŠæ§æ
currentStageId: number | null;
slots: OutputSlot[]; // 衚瀺ã«äœ¿ãåºåã¹ãããã®å®çŸ©ïŒÂ§8.2ïŒ
participants: ParticipantView[];
matches: MatchView[]; // 察æŠè¡šãæãã®ã«è¶³ããå
šå¯ŸæŠïŒç¶æ
ã€ãïŒ
currentMatchId: number | null;
standings: Standings | null;
};Snapshot ã« slots ãå«ããã®ã¯ §8.2 ã®ããã§ããã
Viewer ã¯ã¹ã³ã¢ã®æå³ãç¥ãããã¹ãããå®çŸ©ã«åŸã£ãŠæç»ããã
slots ã¯è¡šç€ºå¯Ÿè±¡ã¹ããŒãžã®èŠåããéžã³ãã¹ããŒãžåãæ¿ãæã«é¢é£ç¶æ
ãšäžç·ã«æŽæ°ããã
MatchView ã«ã¯å¯ŸæŠçªå·ã»å
åŸã»è©Šè¡çªå·ã»è£å®åŸ
ã¡ã»çµæã®æå¹æ§ããé äœã«ã¯ã°ã«ãŒããš
æ«å®ïŒç¢ºå®ã»ééè
ã®ç¶æ
ãå«ãããå詊åïŒç¡å¹åã§ã¯å¯ŸæŠè¡šãšé äœãåãçµæçã«æããã
half ã®ã¿ãæã€çŸè¡åããã®ç§»è¡ã§ã¯ãéä¿¡åŽãšViewerãåæã«æŽæ°ããã
å
¬éåã®ãããå
容ãéå¶å°çšã¡ã¢ãåèŠåJSONã®å
šäœã¯é
ä¿¡ããªãã
Next.js ãåäžããã»ã¹ã§åãéããã€ã³ã¡ã¢ãªã® EventEmitter ã§è³Œèªè
ã«é
ãã°è¶³ããã
è€æ°ã€ã³ã¹ã¿ã³ã¹ã§åããå¿
èŠãåºãå Žåã«éããPostgreSQL ã® LISTEN/NOTIFY ãçµç±ããã
ïŒRedis ãæ°èŠã«æã¡èŸŒãŸãªããDB ã¯æ¢ã«ããããïŒã
EventSourceã¯èªå忥ç¶ãè¡ããåæäžãçŽåã®æç»ãä¿æããç»é¢ãçœãããªãã- äŒå Žãããã¯ãŒã¯ãèœã¡ãŠãã埩垰æã«
Last-Event-IDãŸãã¯ã¹ãããã·ã§ããã§æŽåãåããããšã - Viewer ã¯é ä¿¡ã«èŒãããããšã©ãŒãã€ã¢ãã°ãããŒãã£ã³ã°ã¹ãããŒãç»é¢ã«åºããªãã ç°åžžæã¯çŽåã®æ£åžžãªè¡šç€ºãç¶æããç¶æ ã¯éå¶åŽã® Console ã«ã®ã¿éç¥ããã
Route Handlers ã§ REST ãæäŸãããConsole ããã®æäœã¯ Server Actions ãåªå ãã å€éšããŒã«é£æºãåªçæ§ãå¿ èŠãªæäœã®ã¿ REST ã«çœ®ãã
| Method | Path | çšé |
|---|---|---|
GET |
/api/stream |
SSE |
GET |
/api/tournaments/:id/matches |
察æŠè¡šååŸ |
POST |
/api/matches/:id/start |
察æŠéå§ |
POST |
/api/matches/:id/scores |
gameNumber ãæå®ããŠå¯ŸæŠã®äºå®ãç»é² |
POST |
/api/matches/:id/side-assignment |
åæŠã®COOL/HOTãšæ±ºå®æ¹æ³ãç»é² |
POST |
/api/matches/:id/adjudications |
çç±ãšå¯Ÿè±¡ç¯å²ãæã€è£å®ãè¿œèš |
POST |
/api/matches/:id/rematch |
å 詊è¡ã®ç¡å¹åãšæ¬¡ã®è©Šè¡ã®äœæ |
POST |
/api/stages/:id/advance |
äºéžã®ç¢ºå®é äœããæ¬æŠã®åºå Žè ãç¢ºå® |
POST |
/api/matches/:id/finish |
察æŠçµäºã»åæç¢ºå® |
POST |
/api/matches/:id/recompute |
èŠåã®æ°çã§åèšç®ïŒÂ§5.7ïŒ |
POST |
/api/screen |
é ä¿¡ç»é¢ã®åãæ¿ã |
GET |
/api/score-rules |
èšç®èŠåã®äžèЧïŒçã€ãïŒ |
POST |
/api/score-rules |
æ°ããçã®äœæ |
POST |
/api/score-rules/:id/validate |
æ€èšŒã®å®è¡ïŒÂ§5.6ïŒ |
POST |
/api/score-rules/:id/publish |
æ€èšŒééåŸã倧äŒã«é©çšå¯èœã«ãã |
èŠçŽ:
- ãªã¯ãšã¹ã / ã¬ã¹ãã³ã¹ã¯ Zod ã¹ããŒãã§æ€èšŒããã¹ããŒãã¯
packages/sharedã«çœ®ãã - ç¶æ ãå€ããæäœã¯ãã¹ãŠãDB æžã蟌ã¿ãš SSE ãããŒããã£ã¹ããåäžã®é¢æ°å ã§è¡ãã çæ¹ã ãå®è¡ãããçµè·¯ãäœããªãã
- ãšã©ãŒã¯ HTTP ã¹ããŒã¿ã¹ +
{ error: { code, message } }ã®åœ¢ã«çµ±äžããã - è£å®ã»å詊åã»éé確å®ã¯æäœIDãšå¯Ÿè±¡ã®çµæçãåããäºéç»é²ãšå€ãç»é¢ããã®ç¢ºå®ãé²ãã å詊åäœæãšå 詊è¡ã®éèšé€å€ã¯åäžãã©ã³ã¶ã¯ã·ã§ã³ã§è¡ãã 察æŠã®äžè¶³ã»å åŸæªç¢ºå®ã»è£å®åŸ ã¡ã»é²åºå¢çã®åé äœæªè§£æ±ºããšã©ãŒãšããŠèª¬æããã
é ä¿¡ã«èŒã衚瀺å°çšã®ç»é¢ãæäœã¯åãä»ããããµãŒããŒã®ç¶æ ã«è¿œåŸããŠè¡šç€ºã ããå€ããã
ScreenId 㯠packages/shared ã® union åã§å®çŸ©ããURL ãšã€ãã³ãã®äž¡æ¹ã§ããã䜿ãã
| ScreenId | çšé | 衚瀺ããå 容 |
|---|---|---|
interval |
ã€ãªã | 倧äŒåãããŽã次ã«å§ãŸãå 容ã®äºå |
next-match |
次ã®å¯ŸæŠã®çŽ¹ä» | 察æŠè 2åã®æ å ±ãã©ã®è©ŠåãïŒåæŠã»çµïŒ |
in-match |
察æŠç¶æ³ | 察æŠè 2åãå察æŠã®å åŸãšç¢ºå®æžã¿ã¹ã³ã¢ãåªå£ |
result |
察æŠçµæ | 察æŠè 2åãäž¡è ã®æçµã¹ã³ã¢ãåè ãæ±ºãæ |
bracket |
é²è¡äžã®å¯ŸæŠè¡š | ããŒãã¡ã³ã衚 / ç·åœãã衚ãšããã®äžã®çŸåšå° |
standings |
é äœè¡š | åå è ã®é äœïŒè©³çŽ°ã¯æªå®ã§11ïŒ |
åç»é¢ãå¿ èŠãšããããŒã¿ã¯ä»¥äžã®3ã€ã«éçŽãããããããæ¢åã®ã¢ãã«ããå°åºã§ããã
- 察æŠè
æ
å ±:
ParticipantïŒååãããã³å°æ¥çã«æå±ã»ã¢ã€ã³ã³çïŒ - ã¹ã³ã¢:
MatchResult.agent1Output/agent2OutputïŒåºåã¹ãããå â å€ïŒ - é²è¡ç¶æ³:
Match.order/Match.stateãšã倧äŒå šäœã®MatchäžèЧ
衚瀺åŽã«ã¹ãããåãããŒãã³ãŒãããªãã
äœãåŸç¹ãšããŠåºããã¯èŠåãæ±ºããããïŒÂ§5.3ïŒãç»é¢ã¯ ScoreRule ã®åºåã¹ãããå®çŸ©
ïŒname / label / typeïŒãåŒãã宣èšãããŠããé ã« label ãšå€ã䞊ã¹ãã
- æå·ã®å¯ŸäººæŠãªãã察æŠå婿° 1 / è£æ£ã¢ã€ãã æ° 8ãã®2è¡
- BotäºéžãªããäºéžåŸç¹ 44ãã®1è¡
- é§è·¯ã¯éå¶ç¢ºèªããéèšåŒã®åé¡å¥ã¹ãããã衚瀺ãã
ããã«ããã倧äŒãå€ãã£ãŠã衚瀺ã³ã³ããŒãã³ããæ¹ä¿®ããªããŠããã
OutputSlot.label ãæãããŠããã®ã¯ãã®ããã§ããã
ãªããã©ã®ã¹ãããã倧ããèŠãããããªã©æŒåºäžã®åªå£ã¯ããã®ä»çµã¿ã§ã¯æ±ºãŸããªãã åçã¯å®£èšé ã®å é ã䞻衚瀺ãšãã现ããå¶åŸ¡ãå¿ èŠã«ãªã£ãæç¹ã§ §5.8 ã®æªæ±ºäºé ãšããŠæ±ãã
ããŒãã¡ã³ããšç·åœããã®äž¡æ¹ãæ±ããã©ã¡ããã察æŠäžèЧ + å察æŠã®ç¶æ
ãããæç»ã§ãã
Stage.format ã§æãåãããBotäºéžã¯åå éžæãšBotã»åŸç¹ã®äžèЧãšããã
- ããŒãã¡ã³ã:
MatchãåæŠããšã«é 眮ããåè ãæ¬¡ã®å¯ŸæŠãžç¹ãã§æãã - ç·åœãã: åå è à åå è ã®è¡šãšããåã»ã«ã«å¯ŸæŠã®ç¶æ ãšçµæãå ¥ããã
- ã°ã«ãŒãäºéž: çµããšã®ç·åœãã衚ã»é äœã»ééæ ã衚瀺ãããé§è·¯ã¯åçµäžäœ2åã çµãè·šãå šäœé äœãåæã«äœãããåé äœãé²åºå¢çã«ãããå Žåã¯æªç¢ºå®ã瀺ãã
ãããã Match.stateïŒPENDING / IN_PROGRESS / REVIEW_REQUIRED / FINISHEDïŒã§èŠãç®ãå€ãã
é²è¡äžã®å¯ŸæŠãäžç®ã§åããããšãèŠä»¶ãšãããããã¯ã察æŠç¶æ³è¡šç€ºãã®èŠä»¶ã«çŽçµããã
ä»åãçŽãã«ãªã£ã察æŠïŒÂ§5.5ïŒã¯ãå ã®å¯ŸæŠãšåæŠã1ã€ã®æ ã«ãŸãšããŠè¡šç€ºããã å¥ã ã®å¯ŸæŠãšããŠ2ã€äžŠã¹ããšã察æŠè¡šã®æ§é ã厩ããŠèªããªããªãããã
- Viewer ã¯
/displayã®åäžã«ãŒãã§åããscreen.changedã«å¿ããŠæç»ãåãæ¿ããã çŸè¡ã®ããã«ããŒãžé·ç§»ïŒrouter.pushïŒã§åãæ¿ãããšãé·ç§»ã®ãã³ã«çœç»é¢ãšåæ¥ç¶ãæãŸã é ä¿¡ã«æ ããããã¯ã©ã€ã¢ã³ãåŽã®ç¶æ åãæ¿ããšããŠå®è£ ããããŒãžé·ç§»ã¯è¡ããªãã - ç»é¢é·ç§»ã«ã¯ã¢ãã¡ãŒã·ã§ã³ãå ¥ããããäœå°ãæ®ãïŒé ä¿¡ã®èŠæ ãã®ããïŒã ãã ãé·ç§»äžã« SSE ã®ç¶æ æŽæ°ãå±ããŠãç Žç¶»ããªãããšã
- 衚瀺ã«å¿
èŠãªããŒã¿ã¯ãã¹ãŠ
snapshotã€ãã³ãã«å«ããã ç»é¢ãåãæ¿ããç¬éã«è¿œå ã® API ãå©ãèšèšã«ããªããåãæ¿ãã衚瀺ã®é å»¶ãšããŠèŠããããã - ç»é¢ã¯åºå®è§£å床ïŒ1920Ã1080ïŒãåæã«çµãã é ä¿¡ã«èŒããçšéã§ããã ã¬ã¹ãã³ã·ã察å¿ã¯äžèŠãäžéå端ã«å¯Ÿå¿ãããšãå®éã«äœ¿ãè§£å床ã§ã®äœã蟌ã¿ãçããªãã
docker compose up -d ã§ä»¥äžãç«ã¡äžããããšã
| ãµãŒãã¹ | å 容 | ããŒã |
|---|---|---|
app |
Next.js (Console / Viewer / API) | 3000 |
db |
PostgreSQL 17 | 5432 |
- éçºæã¯
pnpm devã§ãåçã«åãããšïŒDB ã®ã¿ Docker ã§ç«ãŠãéçšã蚱容ïŒã - ç°å¢å€æ°ã¯
.env.exampleã«åæããèµ·åæã« Zod ã§æ€èšŒããŠæ¬ èœãå³åº§ã«èœãšãã
| 倿° | çšé |
|---|---|
DATABASE_URL |
PostgreSQL æ¥ç¶æåå |
NEXT_PUBLIC_APP_URL |
Viewer ã SSE ã匵ãå |
chros-websock / chros-score ã®ã³ã³ããã¯å»æ¢ããã
| çŸè¡ | ç§»è¡åŸ | åè |
|---|---|---|
chros/ (Next.js) |
chros/ïŒç§»åãªãïŒ |
App Router æ§é ã¯ããããæµçšã§2.1 |
chros-websock/ (Express + socket.io) |
廿¢ | SSE ã app/api/stream ã«å®è£
|
chros-score/ (FastAPI + lupa) |
廿¢ | packages/scoring ã« TS ã§åå®è£
|
chros/docs/overview.md |
docs/requirements.md |
éçŽæžã¿ |
socket.io-client äŸå |
åé€ | EventSource ãäœ¿çš |
display/layout.tsx ã® router.push åæ¿ |
ç¶æ ã«ããåæ¿ | çœç»é¢ãšåæ¥ç¶ãé¿ãããã |
| Prisma ã¹ããŒã | 倧äŒã»ã¹ããŒãžã»ã°ã«ãŒãã»èŠåçã»å¯ŸæŠäºå®ã»è£å®ã»çµæå±¥æŽã远å | §4ãçŸè¡ã®åå æ å ±ã ãã§ã¯åèšç®ã§ããªãå Žåããã |
| åæãã³ãŒãã«çŽæžã | ScoreRule ã®ã°ã©ããšããŠå€éšå |
§5 |
ã¹ã³ã¢èšç®ãŸããïŒÂ§5ïŒã¯èšèšãç¶ç¶äžã®ãããããã«äŸåããªãéšåãå ã«é²ããã 以äžã®2ãã©ãã¯ã¯ç¬ç«ããŠåãããã
ãã©ãã¯A â åå°ãšç»é¢ïŒå è¡ïŒ
- pnpm workspace åãš
packages/sharedã®åãåºã - ã€ãã³ãå®çŸ©ãš
Snapshotåã®ç¢ºå®ïŒÂ§6.2ïŒãã¹ã³ã¢ã®äžèº«ã¯slotsçµç±ã§æ±ãããã èšç®èŠåãæªç¢ºå®ã§ããã®åã¯æ±ºãããã - é²è¡ãŸããã® Prisma ã¹ããŒãïŒå€§äŒã»ã¹ããŒãžã»ã°ã«ãŒãã»åå è
ã»è©ŠåïŒãšãã€ã°ã¬ãŒã·ã§ã³ã
1ïŒ2察æŠãåæŠã®å
åŸæ±ºå®ãå詊è¡ãè£å®åŸ
ã¡ãæ±ããå¯ŸæŠæ§æãšåºå
žãæã€
RuleProfileã® éªšæ Œã¯å è¡ããŠããããScoreRuleãšèšç®çµæã®ç¢ºå®ä¿åã¯ãã©ãã¯Bãšãã - API Route Handlers + SSE ã®å®è£
ã
chros-websockã®åé€ - Viewer ã® SSE åãšåç»é¢ã®å®è£
ïŒÂ§8ïŒã
socket.io-clientã®åé€ - Console ã® Server Actions åïŒé²è¡æäœã»ç»é¢åãæ¿ãïŒãé§è·¯ã®ç·åœããïŒã°ã«ãŒãäºéžãã æ¬æŠãžã®æ¥ç¶ããããããçµæã®å ¥åãšåŽäº€æãæ±ããé äœèªåèšç®ãå ¥ãåã®ééè 㯠éå¶ç¢ºèªã®æåèšé²ãšããæªç¢ºèªã®é äœãèªåçæããªã
chros-scoreã®åé€ãš docker-compose ã®æŽç
ãã©ãã¯B â ã¹ã³ã¢èšç®ïŒäžŠè¡ããŠèšèšãç¶ç¶ïŒ
- é§è·¯ã®éèšåŒã確èªãã察æŠçµäºã»å詊åã®æ¡ä»¶è¡šãå
¥ååãš
ScoreRuleGraphã確å®ãã Score/ è£å®å±¥æŽ /ScoreRule/MatchResultãšèŠåãããã¡ã€ã«ã®èšç®éšåã確å®ã»ç§»è¡ããpackages/scoringã®è©äŸ¡åšã»æ€èšŒåšãšã¹ããŒãžã®é äœèšç®ãå®è£ ãã åãå ¥ãäŸ ãšéå¶ç¢ºèªããã±ãŒã¹ã§æ€èšŒãã- ããŒããšãã£ã¿ UI
ãã©ãã¯Aãé²ããããã ãã¹ã³ã¢ã¯åºå®ã®ãããŒå®è£
ã§ä»£æ¿ããŠããã
§8.2 ã®ãšãã Viewer ã¯ã¹ãããå®çŸ©ã«åŸã£ãŠæç»ããããã
ã¹ãããã { name: 'score' } 1ã€ã ãã®ãããŒãè¿ããŠããã°ç»é¢ã¯å®æãããããã
è©äŸ¡åšãä¹ã£ãæç¹ã§å·®ãæ¿ãããViewer åŽã®æ¹ä¿®ã¯äžèŠã«ãªãã
ããŒããšãã£ã¿ UIïŒæé 11ïŒã¯å·¥æ°ã倧ãããå ã«æé 10ãŸã§ãæžãŸãã JSON ãçŽæ¥æå ¥ããŠè©äŸ¡ã§ããç¶æ ãäœããããããã°ãšãã£ã¿ãæªå®æã§ã倧äŒéçšã¯æç«ããã
æªæ±ºã®ãã¡çæåã«æ±ºããå¿ èŠããããã®ãšãåŸåãã§ãããã®ãåããŠèšãã
- é§è·¯ã®ååŸåéèšã®å ·äœåŒãšãåœè©²å¹ŽåºŠã®è¿œå 现åïŒÂ§5.8ïŒ
- çµäºäºè±¡ã»è£å®ã»èŠåã»çµæå±¥æŽã®ã¹ããŒã確å®
- å šåœäº€æµå€§äŒã®éå¬åãšè©³çŽ°çŽ°åã®ç¢ºèªãèªåœã®åæ€èšŒ
min/maxãšãã©ã°å€å®ã®èŠåŠãç¢ºèªæžã¿ã®èšç®ã«äžèŠãªãåŸåãã«ãã
é§è·¯ã®ç·åœããäºéžâæ¬æŠããŒãã¡ã³ããã°ã«ãŒãäºéžæã®åçµäžäœ2åã
æå·ã®Botäºéžâ決åããŒãã¡ã³ãã¯ç¢ºèªã§ããã
äžæ¹ã詊åã®åè
ãåããã ãã§ã¯äºéžé äœãééè
ã¯ç¢ºå®ããªãã
é äœèŠåã¯ã¹ããŒãžã® rankingPolicy ã«çãæã€ããŒã¿ãšããŠçœ®ããæ¡ç¹ã°ã©ããšã¯åé¢ããã
- èŠç¢ºèª: é§è·¯ã®äºéžé äœã®éèšã»åé äœåŠçãéåžžäºéžã®éé人æ°ãã°ã«ãŒãã®çµæ°ã»å²ãåœãŠã æ¬æŠãžã®é 眮ãšã·ãŒããåæ°ãåçãçŽæ¥å¯Ÿæ±ºãªã©ã確èªåã«æ¡çšããªãã
- èŠç¢ºèª: æå·ã®BotæŠãåç¹ã®å ŽåãäºéžåŸç¹ãåãå Žåãéé人æ°ã»çµã¿åããã
- èšèšãšããŠç¢ºå®: å詊åã§ç¡å¹ã«ãªã£ã詊è¡ãéèšã«å«ãããBotãéžæé äœããé€ãã ã°ã«ãŒãäºéžã¯çµããšã«éèšããé²åºå¢çã®åé äœãæªè§£æ±ºãªãéé確å®ãæ¢ããã
- èšèšãšããŠç¢ºå®: ééè ãšæ¬æŠã®å²ãåœãŠã¯æ ¹æ ãšãªãé äœçãšãšãã«ä¿åããã å ã®è©Šåã®èšæ£ã§é äœãå€ããã°å確èªããæ¢åã®æ¬æŠãé»ã£ãŠæžãæããªãã
ãã©ãã¯AïŒÂ§10.1ïŒã®ä¿åã»å
¥åã»è¡šç€ºã®éªšæ Œã¯ããããã®ç¢ºèªãåŸ
ããé²ããããã
standings ã¯æ«å®ïŒç¢ºå®ãšã°ã«ãŒãã衚瀺ã§ããæ§é ãå
ã«çšæããæªç¢ºèªã®èŠåã§ã¯èªåé äœãåºããªãã
- CHaser æ¬äœãšã®é£æºæç¡ïŒçŸç¶ã¯æå ¥ååæãå°æ¥ãã°åã蟌ã¿ãè¡ããïŒ
- 倧äŒåŸã®èšé²å ¬éã®åœ¢åŒïŒéçæžãåºãããã·ã¹ãã ã皌åããç¶ãããïŒã 皌åããç¶ããå Žåã¯èªèšŒã®èŠåŠã忀èšããïŒÂ§1.3ïŒ
- ç»é¢é·ç§»ã®æŒåºãåºåã¹ãããã®è¡šç€ºäžã®åªå£ïŒÂ§8.2ïŒ