察象èªè : CHroS ã®å®è£ è ãèŠä»¶ãã®ãã®ã¯ requirements.md ãåç §ã
ãã®ããã¥ã¡ã³ãã¯ãæ¢åå®è£ ïŒNext.js + Express/socket.io + FastAPI ã®3ãµãŒãã¹æ§æïŒã ãŒãããŒã¹ã§åèšèšããçµæãå®ãããæ¢åã³ãŒããšã®å·®åã¯æ«å°Ÿã®ãçŸè¡æ§æããã®ç§»è¡ãã«èšãã
| é ç® | æ±ºå® | çç± |
|---|---|---|
| èšèª | 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ïŒ |
åœå㯠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 ã®ããŒãµãšããŠåããã±ãŒãžå
ã«çœ®ãã
æ¢åã¹ããŒããåå°ã«ãé²è¡ç¶æ ãäžçŽåžæ°ãšããŠæãããã
enum Side { COOL, HOT }
enum Half { FIRST, SECOND }
enum MatchState { PENDING, IN_PROGRESS, FINISHED }
model Tournament {
id Int @id @default(autoincrement())
name String
format Format // ROUND_ROBIN | SINGLE_ELIMINATION
scoreRuleId Int // ãã®å€§äŒã«é©çšããèšç®èŠåïŒÂ§5ïŒ
matches Match[]
entries Participant[]
}
/// ã¹ã³ã¢èšç®èŠåã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
// 察æŠã»ã¹ã³ã¢ãžã®éåç
§
}
model Match {
id Int @id @default(autoincrement())
tournamentId Int
order Int // 察æŠé ãé²è¡ã¯ãã®é ã«åŸã
state MatchState @default(PENDING)
agent1Id Int
agent2Id Int
scores Score[]
result MatchResult? // åæã¯èšç®çµæåŽãæã€ïŒäžèšïŒ
@@unique([tournamentId, order])
}
/// 察æŠã®çããŒã¿ãèšç®çµæã§ã¯ãªãã芳枬ãããäºå®ãã®ã¿ãæã€ã
/// ããã«äžŠã¶é
ç®ãããã®ãŸãŸåŸç¹ç®åºãããã¯ã®ãå
¥åã®ç®±ãã«ãªãïŒÂ§5.4ïŒã
model Score {
id Int @id @default(autoincrement())
matchId Int
half Half
coolId Int
hotId Int
coolScore Int
hotScore Int
coolItems Int // ååŸã¢ã€ãã æ°
hotItems Int
remainingTime Int // ããŒãçµäºæç¹ã®æ®ãæé
blocked Side? // é²è¡äžèœã«ãªã£ãåŽïŒå£åãŸãã»è¡åäžèœã»å¿çãªãïŒ
@@unique([matchId, half])
}
/// èšç®èŠåã Score ã«é©çšããçµæãã©ã®èŠåã§åºããããå¿
ãæ·»ããã
model MatchResult {
id Int @id @default(autoincrement())
matchId Int @unique
scoreRuleId Int // åçŸæ§ã®ãããé©çšããèŠåã® version ãåºå®ããŠèšé²
agent1Output Json // åºåã¹ãããå -> å€ãäŸ { score: 12, specialPoint: 1 }
agent2Output Json // äœãåºããã¯èŠåãæ±ºããããåºå®ã«ã©ã ã«ããªãïŒÂ§5.3ïŒ
winnerId Int?
winReason String? // å°éããçµç«¯ããŒããšæ±ºãæã®ã¹ãããåïŒÂ§5.3ïŒ
trace Json? // è©äŸ¡ã®äžéå€ãšééããå¶åŸ¡çµè·¯ïŒÂ§5.6 æ€èšŒã»èª¬æçšïŒ
computedAt DateTime @default(now())
}远å ã»å€æŽã®æå³:
Tournament: è€æ°å€§äŒã»è€æ°éšéãæ±ããããã«ãããæ¢åã¹ããŒãã«ã¯ç¡ããåŸä»ããæãé«ãã€ãç®æãMatch.order/Match.state: ãä»ã©ã®å¯ŸæŠããã£ãŠããããã DB ã®ç¶æ ãšããŠæã€ã Viewer ã®è¡šç€ºã¯ãã®ç¶æ ããå°åºãããç»é¢åæ¿ã®ããã ãã®ç¬ç«ããç¶æ ãæããªããScore.blockedãçŸè¡ã®put/lostConnectã眮ãæãã: ã©ã¡ãããé²è¡äžèœã«ãªã£ãåŽãã® äžçš®ã§ãããåºå¥ãèŠããã¯èŠåã§ã¯ãªãå€§äŒæ¬¡ç¬¬ãäºå®ã1ã€ã«ãŸãšããæå³ä»ãã¯èŠåã«å§ããïŒÂ§5.4ïŒã èšé²äžã®è©³çްãªçç±ãå¿ èŠã«ãªã£ãå Žåã¯ãblockedã«çç±ã®åæãæ·»ããåœ¢ã§æ¡åŒµãããMatchResult.winReason: ãã©ã®ãããªåã¡æ¹ãããããã®è¡šç€ºèŠä»¶ïŒåŸç¹è¡šç€ºïŒã«çŽæ¥å¯Ÿå¿ããã çŸè¡ã¯put/lostConnectãã衚瀺åŽãæšè«ããå¿ èŠããããããžãã¯ãæ£ãã å€ã¯ enum ã§ã¯ãªãæååãšãããåå ã¯èŠååŽã®çµç«¯ããŒãæ§æã§æ±ºãŸãããã ã·ã¹ãã åŽã§åæãåããªããMatchResult.agent*OutputãJsonã«ããçç±: äœãåŸç¹ãšããŠå€ã«åºããã¯èŠåãæ±ºããïŒÂ§5.3ïŒãscore1ã€ã®å€§äŒãããã°scoreãšspecialPointãåºã倧äŒããããããåºå®ã«ã©ã ã«ã§ããªãã 衚瀺åŽã¯åºåã¹ãããã®å®çŸ©ïŒååã»è¡šç€ºåã»åïŒãèŠåããåŒããŠæç»ãããScoreãšMatchResultã®åé¢: å ¥åãããäºå®ãšãèŠåãé©çšããçµæãæ··ããªãã èŠåãå€ãã£ããšããäºå®ã¯ãã®ãŸãŸã«çµæã ãåèšç®ã§ããã坿¬æ§ãæ²ãã以äžããã¯è²ããªãã
åæå€å®ã¯ DB ã«æžãåã« packages/scoring ã®è©äŸ¡åšã§æ±ºå®ããçµæã MatchResult ã«æ°žç¶åããã
衚瀺ã®ãã³ã«åèšç®ããªãã
æ¬ã·ã¹ãã ã®æ žã倧äŒããšã«ç°ãªãè€éãªèšç®èŠåãããšã³ãžãã¢ã®æ¹ä¿®ãªãã«å·®ãæ¿ããããããã«ãã ïŒåæ©ã¯ §1.2ïŒã
[Console: ããŒããšãã£ã¿] --(ScoreGraph JSON)--> [æ€èšŒåš] --> [ScoreRule ããŒãã«(jsonb)]
|
[Score(äºå®)] ------> [è©äŸ¡åš evaluate()] <---+
|
v
[MatchResult(çµæ + trace)]
ãã¹ãŠ packages/scoring ã«çœ®ããI/O ã DB ã React ãåç
§ããªãçŽç²ãª TS ãšãã
è©äŸ¡åšã»æ€èšŒåšã»åå®çŸ©ã1ãæã«ãŸãšãããããã«ããèšç®èŠåã®åäœãã¹ãã容æã«ãªãã
å°æ¥ CLI ãå¥ãµãŒãã¹ããåãèŠåãåå©çšã§ããã
ããããã¯ããæŒç®åããããŒãããæ··ãããšè°è«ãæ»ãããã以äžã«åºå®ããã
| çšèª | æããã® | äŸ |
|---|---|---|
| ããã㯠| ç·šéåäœããŠãŒã¶ãŒã远å ã»åé€ã§ããªãåºå®ã®åºç» | åŸç¹ç®åºãããã¯ãåæå€å®ããã㯠|
| ããŒã | ãããã¯å ã«çœ®ãåŠçã®1åäœããŠãŒã¶ãŒãèªç±ã«é 眮ãã | å ç®ããŒããåå€å€å®ããŒã |
| ããŒã | ããŒãã®å ¥åºåã®æ¥ç¶å£ãååãšåãæã€ | left / right / yes / no |
| å€ãšããž | æ°å€ã»çåœå€ãéã¶ç·ãåŸç¹ç®åºãããã¯ã®ã¿ | å ç®ããŒã â åºåã¹ããã |
| å¶åŸ¡ãšããž | ãæ¬¡ã«ã©ã®ããŒããžé²ããããéã¶ç·ãåæå€å®ãããã¯ã®ã¿ | åå€å€å®ã® no â çµç«¯ããŒã |
以éããŠãŒã¶ãŒããæŒç®åããšåŒãã§ãããã®ã¯ããŒããšåŒã¶ã
ã°ã©ãã¯å¹³åŠãª1æã§ã¯ãªãã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ïŒãåç §ã㊠ãããã¯å ã®åå²ãšããŠè¡šçŸããã
ãã®åå²ãæã€æå³:
- ãäœç¹ã«ãªããããšãã©ã¡ããåã¡ãããæ··ããªãã åŸç¹ç®åºãããã¯ã¯æ°å€ãåºãããšã ãã«è²¬ä»»ãæã¡ã åæã®æŠå¿µãç¥ããªããåæå€å®ãããã¯ã¯åŸç¹ã®äœãæ¹ãç¥ããªãã èŠå倿Žã®å€ãã¯çæ¹ã ãã®ä¿®æ£ã§æžãã
- åŸç¹ç®åºãããã¯ã¯çåŽã¶ãã®å ¥åããåãåããªããçžæã®åŸç¹ãåç §ã§ããªãããã ãçžæãã1ç¹å€ããã°ãã®ãããªæ¯èŒã¯æ§é äžããã«æžãããå¿ ãåæå€å®ãããã¯ã«å¯ãã ãã®å¶çŽããèŠåã®çœ®ãå Žæã®ææ§ããæ¶ãã
- åæå€å®ãããã¯ã®åºåã¯åè ãšåå ã®ã¿ãåŸç¹ãããã§æžãæããããšã¯ã§ããªãã
export type ScoreRuleGraph = {
formatVersion: 1; // ä¿å圢åŒã®çãç§»è¡å€å®ã«äœ¿ã
points: Block; // åŸç¹ç®åºãããã¯ïŒ1ã€ãäž¡åå è
ãžé©çšïŒ
decision: Block; // åæå€å®ãããã¯
};
/** åŸç¹ç®åºãããã¯: å€ãšããžã®ã¿ã®çŽç²ãªåŒãè€æ°ã®å€ãååä»ãã§å€ã«åºã */
export type PointsBlock = {
nodes: PointsNode[];
valueEdges: ValueEdge[];
outputs: OutputSlot[]; // 1ã€ä»¥äžãååã¯åæå€å®ãããã¯ããåç
§ããã
};
export type OutputSlot = {
name: string; // äŸ: 'score' / 'specialPoint' / 'items'
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ã€ä»¥äž | äžèš |
å
¥åå㯠cool / hot ã§ã¯ãªã asCool / asHotïŒèªåã COOL ã ã£ãåŽ / HOT ã ã£ãåŽïŒãšããã
åå è
ã¯ååãšåŸåã§åŽãå
¥ãæ¿ããããããèªåã COOL ãšããŠåã£ãç¹ããšããèŠç¹ã§ãªããšåŒãæžããªãã
åºåã¯1ã€ã®æ°å€ã«åºå®ããªããäœãããã€å€ã«åºãããèŠåã®äœæè ãæ±ºããã ããã¯å€§äŒããšã®å·®ãåžåããããã«å¿ èŠãªèªç±åºŠã§ããã
- ãååŸã¢ã€ãã æ° + æ®ãæéãã1ã€ã®åŸç¹ãšããŠåºãå€§äŒ â
scoreã1ã€åºã - ç¹æ®ãã€ã³ããåŸç¹ãšã¯å¥ã«å€å®ãžæž¡ãå€§äŒ â
scoreãšspecialPointã®2ã€ãåºãïŒÂ§5.5 倧äŒAïŒ - ã¢ã€ãã æ°ãšæéãå¥ã
ã«èŠãããå€§äŒ â
itemsãštimeBonusãåããŠåºã
åºåã¹ãããã¯ååãšåãæã¡ãåæå€å®ãããã¯ã®åããŒããååã§1ã€éžæããïŒäž¡åå è ã®ååã¹ãããã察象ïŒã åºåã¹ãããã®è¿œå ã»åé€ã»æ¹åã¯ããããåç §ããŠããåæå€å®ãããã¯ãå£ããããæ€èšŒã§æ€åºããïŒÂ§5.6ïŒã
åæå€å®ãããã¯
ãã®ãããã¯ã ãã¯åŒã§ã¯ãªããããŒãã£ãŒãã§ããã å¶åŸ¡ãšããžããã©ã£ãŠé²ã¿ãçµç«¯ããŒãã«å°éããæç¹ã§åæã確å®ããŠè©äŸ¡ãçµããã
åããŒãã¯ãã©ã®ã¹ã³ã¢ãèŠããããéžæãšããŠæã¡ãå€ã¯ç·ã§éã°ãªãã åŸç¹ç®åºãããã¯ã®åºåã¹ããããéžæè¢ãšããŠäžŠã³ããã®äžãã1ã€éžã¶ã
| çš®å¥ | ããŒã | èŠããã® | å¶åŸ¡åºå | æå³ |
|---|---|---|---|---|
| åå² | åå€å€å® | æ°å€ã¹ããã1〠| yes / no |
äž¡è ã®ãã®ã¹ã³ã¢ãçãããã§é²ãå ãåãã |
| åå² | ãã©ã°å€å® | çåœã¹ããã1〠| yes / no |
çåœã®èŠå ã§é²ãå ãåãã |
| çµç«¯ | é«ãæ¹ã®åå© | æ°å€ã¹ããã1〠| ãªã | ãã®ã¹ã³ã¢ã倧ããåŽãåè ãšããŠç¢ºå®ãã |
| çµç«¯ | ä»åãçŽã | ãªã | ãªã | åæãä»ãããåäžã«ãŒãã®åæŠãšãã |
| çµç«¯ | åŒãåã | ãªã | ãªã | åŒãåããšããŠç¢ºå®ãã |
ãä»åãçŽããã¯åŒãåããšã¯å¥ç©ã§ãããäž¡è ãåºå¥ããŠæã€ã æ¢ç¥ã®å€§äŒïŒÂ§5.5ïŒã¯ããããåç¹æã«åæŠãè¡ã£ãŠãããåŒãåãã§ç¢ºå®ãããªãã åŒãåãçµç«¯ã¯ãé äœèšç®äžã§åŒãåããèªãã倧äŒã®ããã«æ®ãããåçã®å®äŸã§ã¯äœ¿ãããªãã
- çµç«¯ããŒãã¯å¶åŸ¡åºåãæããªãã ãããã確å®ããŠçµãããããšã®è¡šçŸã§ããã åºåãç¡ãããšèªäœãæå³ãæ ããçµç«¯ã«å°éããã以éã®ããŒãã¯è©äŸ¡ããªãã
- åå²ããŒãã¯å€ãåºåããªãã çåœå€ãåŸæ®µã«é ã£ãŠäœ¿ãåãã®ã§ã¯ãªãã å¶åŸ¡ã®è¡ãå ãã®ãã®ãåãããçåœå€ãç·ãšããŠæŒããªãã®ã§ã ããã® true ã¯ã©ãã§äœ¿ãããã®ãããèªã¿è§£ãå¿ èŠããªãã
- ãã®ãããã¯ã«å€ãšããžã¯ååšããªããç·ã¯å¶åŸ¡ãšããž1çš®é¡ã ãã§ããã
ã¹ãããã®éžæããã®åœ¹å²ãæãããããã«ããåŸããããã®ã3ã€ããã
- ç·šéããç·ã2çš®é¡åŒãåããããããããããããŠã³ã§éžã¶ãã«èœã¡ãã éãšã³ãžãã¢ã«è§Šããããšããç®çã«å¯ŸããŠãUI ã®é£æã1ã€æ¶ããã
- ç¡æå³ãªæ¥ç¶ãåççã«äœããªãã å€ãšããžããããš
ãA ã®
scoreãš B ã®specialPointãæ¯ã¹ãããšããé察称ã§ç¡æå³ãªç¹ãæ¹ãæžããŠããŸãã ã¹ãããã1ã€éžã¶åœ¢ãªããæ¯èŒã¯åžžã«äž¡åå è ã®ååã¹ãããå士ã«ãªãã §5.3 åé ã§è¿°ã¹ãèŠåã®å¯Ÿç§°æ§ããå€å®ãããã¯åŽã§ãæ§é ãšããŠä¿èšŒãããã - åæ€èšŒããç·ã®åæŽåãã§ã¯ãªããéžãã ã¹ãããã®åãããŒãã®èŠæ±ãšåãããã«åçŽåãããã ããããããŠã³ã«åãåã®ã¹ãããã ãã䞊ã¹ãã°ã誀ãã¯éžæè¢ãšããŠååšããªããªãã
å€ãšããžãæã€ã®ã¯åŸç¹ç®åºãããã¯ã ãã«ãªãã§5.2 ã®çšèªè¡šã§ã¯2çš®é¡ã®ç·ãå®çŸ©ããŠãããã 1ã€ã®ãããã¯ãäž¡æ¹ã®ç·ãæã€ããšã¯ãªãã
ãã¹ã³ã¢ããç¹æ®ãã€ã³ãã®å€å®ãå ã«æ¥ãã倧äŒïŒÂ§5.5 ã®å€§äŒAïŒã¯ã åªå 床ãšãã奿Šå¿µãå°å ¥ãããå¶åŸ¡ãšããžãç¹ãé åºã§è¡šçŸããã å ã«çœ®ããåå²ãå ã«è©äŸ¡ãããã
[éå§]
â
v
ââââââââââââââââââââââââââ
â åå€å€å® â
â èŠãã¹ã³ã¢: specialPoint â
ââââââ¬âââââââââââââââ¬âââââ
no â â yes ïŒç¹æ®ãã€ã³ããåç¹ïŒ
v v
ââââââââââââââââââââââââââ ââââââââââââââââââââ
â é«ãæ¹ã®åå© â â åå€å€å® â
â èŠãã¹ã³ã¢: specialPoint â â èŠãã¹ã³ã¢: score â
ââââââââââââââââââââââââââ ââââ¬âââââââââââââ¬âââ
(çµç«¯) no â â yes
v v
ââââââââââââââââââââ ââââââââââââââ
â é«ãæ¹ã®åå© â â ä»åãçŽã â
â èŠãã¹ã³ã¢: score â ââââââââââââââ
ââââââââââââââââââââ (çµç«¯)
(çµç«¯)
ç·ã¯å¶åŸ¡ãšããž1çš®é¡ã ãã§ãããåããŒãã®äžã«ãèŠãã¹ã³ã¢ãã®éžæãå
¥ã£ãŠããã
倧äŒBïŒåŸç¹ã®ã¿ã§å€å®ïŒã¯ããã®å³ããå
é ã® specialPoint ã®åå²ãš
ãã® no åŽã®çµç«¯ãåãé€ãã圢ã«ãªããèªåœã¯åãã§ãé
眮ã ããéãã
åãèªåœã®ãŸãŸãåå²ã眮ãé ãå ¥ãæ¿ããã ãã§ãåŸç¹ãå ãèŠå ãåŸãã®å€§äŒã«ã察å¿ã§ããã åªå é äœãæ°å€ããã£ãŒã«ãã§æããªããããé åºãå³ãšããŠäžç®ã§èªãããšããå©ç¹ãããã
åå ïŒWinReasonïŒã¯ãã©ã®çµç«¯ããŒãã«å°éããããã®ãã®ã§ããã
å¥éãã£ãŒã«ããšããŠçµã¿ç«ãŠãå¿
èŠã¯ãªããçµç«¯ããŒãã®çš®å¥ãšã
ããã«ç¹ãããŠããåºåã¹ãããåïŒäŸ: specialPoint ã§æ±ºçïŒãèšé²ããã°è¶³ããã
ãã㯠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 ã«æå©ãªåŒãçŽã蟌ãã§ããªããããæ€èšŒããå¿ èŠãç¡ãã é察称æ§ã¯åæå€å®ãããã¯ã«æžãããå Žåã«ã®ã¿çºçãããã®ã§ãã¬ãã¥ãŒç¯å²ãããã«éå®ãããã
åŸç¹ç®åºãããã¯ãåç §ã§ããå ¥åããç®±ããšããŠå®çŸ©ããã ç®±ã¯åå è 1人ã¶ãã®ã1詊åã¶ãã®äºå®ã衚ãã
åçã§çšæããç®±ïŒasCool. / asHot. ã®2çµãæã€ã以äžã¯çåŽã¶ãã®äžèЧïŒ:
| ç®± | å | å 容 |
|---|---|---|
score |
number | ãã®ããŒãã§èªåãååŸããç¹ |
items |
number | ãã®ããŒãã§èªåãååŸããã¢ã€ãã æ° |
remainingTime |
number | ãã®ããŒãçµäºæç¹ã®æ®ãæé |
selfBlocked |
boolean | ãã®ããŒãã§èªåãé²è¡äžèœã«ãªã£ãã |
opponentBlocked |
boolean | ãã®ããŒãã§çžæãé²è¡äžèœã«ãªã£ãã |
ãé²è¡äžèœãã¯ãå£ã«åãŸãã»åæ¹ãå¡ãã£ãŠè¡åã§ããªãã»ãšãŒãžã§ã³ããèŠå®æéå ã«å¿çããªãã ãšãã£ã察æŠç¶è¡äžèœã®ç¶æ ããŸãšãããã®ã§ããã ãããåæãåŸç¹ã«ã©ãå¹ããã¯ã·ã¹ãã ãæ±ºããªãã äºå®ãšããŠèšé²ããã ãã§ã æ±ãã¯èŠååŽã«å§ããïŒå€§äŒAã¯çžæã®é²è¡äžèœãç¹æ®ãã€ã³ãã«æç®ãã倧äŒBã¯åŸç¹ã®ç¬Šå·ã«äœ¿ãã§5.5ïŒã
§5.3 ã§ãåŸç¹ç®åºãããã¯ã¯èªåã®å€ã®ã¿ãåç §ã§ããããšè¿°ã¹ãããæ£ç¢ºã«ã¯æ¬¡ã®ãšããã
- åç §ã§ããªã: çžæã®åºåã¹ãããïŒçžæã®ç®åºæžã¿åŸç¹ïŒã ãããèš±ããšåŸç¹ç®åºãçžäºåç §ã«ãªãã察称æ§ã®ä¿èšŒãšãããã¯åå²ã®æå³ã倱ãããã
- åç
§ããŠãã: çžæã«ã€ããŠã®çã®äºå®ïŒ
opponentBlockedãªã©ïŒã ãçžæãé²è¡äžèœã«ãªã£ãã®ã§èªåã«å ç¹ããšããèŠåãçŸã«ååšããããããããçŠãããšæžããªãã
å¢çã¯ãäºå®ããç®åºçµæããã§ãã£ãŠãèªåããçžæããã§ã¯ãªãã
ç®±ãå¢ããå Žå㯠Score ã¢ãã«ãžã®ãã£ãŒã«ã远å ãš formatVersion ã®æŽæ°ã䌎ãã
ç®±ã¯åŸããè¶³ããããäžåºŠå
¬éããç®±ã¯æžãããªãã
ãªããã¢ã€ãã æ°Ã3 + æ®ãæéãã®ãããªåæã¯ç®±ãšããŠã¯æããªãã ããã¯åŸç¹ç®åºãããã¯ã§çµã¿ç«ãŠããã®ã§ããïŒÂ§5.5 ã®å€§äŒBïŒã ç®±ã®åŽã§åæããŠããŸããšèŠåãå·®ãæ¿ãããããšããåæã厩ããã
æ¢ç¥ã®2倧äŒããäžèšã®èªåœã ãã§è¡šçŸã§ãããæ€èšŒããçµæãèšãã ã©ã¡ãã衚çŸã§ããã 以äžã¯å®è£ æã®åãå ¥ãåºæºãšããŠäœ¿ãã
èŠå: 察æŠäžã«é²è¡äžèœã«ãªããšçžæã«ç¹æ®ãã€ã³ããå ¥ããååŸåãéèšãã ãŸãç¹æ®ãã€ã³ããé«ãæ¹ãåã¡ãåç¹ãªãã¹ã³ã¢ã§æ¯èŒããããåç¹ãªãä»åãçŽãã
åŸç¹ç®åºãããã¯ïŒåºåã¹ããã2ã€ïŒ:
| ã¹ããã | å | çµã¿ç«ãŠ |
|---|---|---|
specialPoint |
number | (asCool.opponentBlocked ? 1 : 0) + (asHot.opponentBlocked ? 1 : 0) |
score |
number | asCool.score + asHot.score |
åæå€å®ãããã¯:
[éå§] â åå€å€å®(specialPoint)
â no â é«ãæ¹ã®åå©(specialPoint) (çµç«¯)
â yes â åå€å€å®(score)
â no â é«ãæ¹ã®åå©(score) (çµç«¯)
â yes â ä»åãçŽã (çµç«¯)
ãç¹æ®ãã€ã³ããã¯çåœå€ã§ã¯ãªãæ°å€ã§ããã ååŸåã§æå€§2ç¹å
¥ãããããã
以åã®èšèšã«ãã£ã specialWin: boolean ã§ã¯è¡šçŸã§ããªãã£ãã
ããã §5.4 ã§ç®±ãçåœå€ã® opponentBlocked ã«å€ãã
ç¹æ°ãžã®æç®ãèŠååŽïŒåŸç¹ç®åºãããã¯ïŒã«ç§»ããçç±ã§ããã
èŠå: é²è¡äžèœã§æ±ºçããå Žåãåã£ãåŽã®åŸç¹ã¯ ã¢ã€ãã æ°Ã3 + æ®ãæéã
è² ããåŽã¯ ã¢ã€ãã æ°Ã3 - æ®ãæéãç¹æ®æ¡ä»¶ã¯èããåŸç¹ã ãã§æ¯èŒãåç¹ãªãä»åãçŽãã
åŸç¹ç®åºãããã¯ïŒåºåã¹ããã1ã€ïŒ:
| ã¹ããã | å | çµã¿ç«ãŠ |
|---|---|---|
score |
number | åããŒãã§ itemsÃ3 + (selfBlocked ? -remainingTime : +remainingTime) ãæ±ããååŸåãå ç® |
åæå€å®ãããã¯:
[éå§] â åå€å€å®(score)
â no â é«ãæ¹ã®åå©(score) (çµç«¯)
â yes â ä»åãçŽã (çµç«¯)
- åŸç¹ç®åºãããã¯ã«
ifã¯å¿ èŠã§5.8 ã§ãäžèŠãªãåããããšããŠãããã 倧äŒBã®æ®ãæéã®ç¬Šå·å転ã倧äŒAã®çåœå€ããç¹æ°ãžã®æç®ã®åæ¹ã§äœ¿ããåããªãã - ãä»åãçŽããçµç«¯ãå¿ é ã䞡倧äŒãšãåç¹ãåŒãåãã§ç¢ºå®ãããåæŠããã åŒãåãçµç«¯ã ãã§ã¯è¡šçŸã§ããªãã
- å€å®ã®åªå é äœããããŒã®é åºã§è¡šçŸã§ããŠããã 倧äŒAã¯ç¹æ®ãã€ã³ãã®åå²ãå ã«çœ®ãã倧äŒBã¯çœ®ããªããããã ãã®å·®ã«ãªãã
- ç®±ã«çžæã®äºå®ïŒ
opponentBlockedïŒãèŠãã倧äŒAã®ç¹æ®ãã€ã³ãã¯ çžæãé²è¡äžèœã«ãªã£ãããšã§èªåã«å ¥ãããããããç¡ããšæžããªãïŒÂ§5.4ïŒã - 倧äŒAãšå€§äŒBã§èªåœã¯åäžã§ãããéãã¯ããŒãã®é 眮ã ãã 坿¬æ§ã®ç®æšã«å¯Ÿããå ·äœçãªè£ä»ãã«ãªã£ãŠããã
ãä»åãçŽããã«å°éãã察æŠã¯ãåæãæªç¢ºå®ã®ãŸãŸåæŠãè¡ãã
æ¢åã® 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ã«ãä»åãçŽããã®çµæãæ®ãããŸãŸç¢ºå®ãããwinnerIdã¯nullã«ãªãã - é äœèšç®ã¯æçµçã«åæãä»ãã
Matchã®ã¿ãæ°ãã ä»åãçŽãã«çµãã£ã察æŠã¯éèšããé€å€ããã - é
ä¿¡ç»é¢ã«ã¯ãä»åãçŽãããæç€ºã§ããããã«ããïŒÂ§8 ã®
resultç»é¢ïŒã
ãææ§ãªç¶æ ãé²ããããšãæç€ºçãªä»çµã¿ãšããŠæã€ãèŠåã¯æ€èšŒãééãããŸã§å€§äŒã«é©çšã§ããªãã
æ€èšŒã¯5段éã§è¡ãã
-
æ§é æ€èšŒ: Zod ã¹ããŒãé©åãåŸç¹ç®åºãããã¯ã®å€ãšããžãš åæå€å®ãããã¯ã®å¶åŸ¡ãšããžããããã DAG ã§ããããšã æªæ¥ç¶ã®å ¥åããŒããç¡ãããšãå°éäžèœãªããŒããç¡ãããšã ãããã¯ãè·šã蟺ãç¡ãããšããã®ãããã¯ã§èš±å¯ãããçš®å¥ã®ããŒãã®ã¿ã䜿ã£ãŠããããšã åŸç¹ç®åºãããã¯ã¯åºåã¹ãããã1ã€ä»¥äžãããååãéè€ããŠããªãããšã
-
å¶åŸ¡ãããŒæ€èšŒïŒåæå€å®ãããã¯ã®ã¿ïŒ:
entryãã¡ããã©1ã€ããããšã- ãã¹ãŠã®å¶åŸ¡çµè·¯ãçµç«¯ããŒãã«å°éããããšã åå²ããŒãã®
yes/noã®ãã¡ çæ¹ã§ãç¹ãã£ãŠããªããã°æ€èšŒãšã©ãŒãšããã - çµç«¯ããŒãããåºãå¶åŸ¡ãšããžãç¡ãããšã
- å°éãããçµç«¯ã1ã€ãç¡ãããŸãã¯å°éã§ããªãçµç«¯ãããå Žåã¯ãšã©ãŒãšããã
ãã®æ®µããææ§ãªç¶æ ãé²ããã®å®äœã§ãããå€å®æŒãïŒåæã決ãŸããªãç¶æ ãã å®è¡æã®äŸå€ã§ã¯ãªãèŠåã®ä¿åæã«æ§é ãšããŠåŒŸãã ã«ãŒããç¡ããããå šçµè·¯ã®åæã¯æéã§ç¶²çŸ çã«è¡ããã
-
ã¹ãããåç §æ€èšŒ: åæå€å®ãããã¯ã®åããŒããéžãã§ãã
slotãã åŸç¹ç®åºãããã¯ã«å®åšãããã€ããŒãã®èŠæ±ããåãšäžèŽããããš ïŒåå€å€å®ã»é«ãæ¹ã®åå©ã¯æ°å€ããã©ã°å€å®ã¯çåœå€ïŒã ã¹ãããã®æ¹åã»åé€ã§å€å®åŽãå£ããã®ãä¿åæã«æ€åºããã ãŸããã©ã®ããŒããããéžã°ããŠããªãåºåã¹ãããã¯èŠåãšããŠæç€ºãã ïŒè¡šç€ºå°çšãšããŠæå³çã«åºãå Žåãããããããšã©ãŒã«ã¯ããªãïŒãã¹ããããéžæã«ããããšã§ããã®æ€èšŒã¯ãšãã£ã¿ã®ããããããŠã³ã« é©åããåã®ã¹ãããã ãã䞊ã¹ãããšãšç䟡ã«ãªãã 誀ããæ€åºããã®ã§ã¯ãªããéžæè¢ãšããŠååšãããªã圢ã«ã§ããã
-
åæ€èšŒïŒåŸç¹ç®åºãããã¯ã®ã¿ïŒ: å€ãšããžã®ããŒãéã®åïŒæ°å€ / çåœå€ïŒã®æŽåã ã«ãŒããç¡ãããããã®æ€èšŒã¯è©äŸ¡ããã«å®äºããã åæå€å®ãããã¯ã«ã¯å€ãšããžãç¡ãããããã®æ®µã®å¯Ÿè±¡å€ãšãªãã
-
æ¯ãèãæ€èšŒ: èŠåããšã«ãã¹ãã±ãŒã¹ïŒå ¥åã®
ScoreãšæåŸ ããçµæã®çµïŒãç»é²ã§ããã éå»å€§äŒã®å®ããŒã¿ãæµããçµæãå€ãããªãããšã確èªããååž°ãã¹ããšããŠäœ¿ãã
è©äŸ¡åšã¯ trace ãè¿ããMatchResult.trace ã«ä¿åãããtrace ã¯2éšæ§æã«ãªãã
- åŸç¹ç®åºãããã¯: åããŒãã®äžéå€ïŒãªããã®ç¹æ°ã«ãªã£ããïŒ
- åæå€å®ãããã¯: ééããå¶åŸ¡çµè·¯ãšãå°éããçµç«¯ããŒãïŒãªããã®åæã«ãªã£ããïŒ
åŸè ã¯å¶åŸ¡ãšããžãå°å ¥ããããšã§èªç¶ã«åŸãããããåå€å€å®(score) â no â é«ãæ¹ã®åå©(score)ããšãã çµè·¯ãã®ãã®ã説æã«ãªã£ãŠãããéãšã³ãžãã¢ãèŠåãä¿¡é Œããæ¡ä»¶ãæºããã
- äžåºŠå€§äŒã§äœ¿çšãã
ScoreRuleã¯æžãæããªããç·šéã¯æ°ããversionã®äœæãšããŠæ±ãã MatchResultã¯é©çšããscoreRuleIdãä¿æãããããéå»ã®çµæã¯åžžã«åçŸã§ããã- 倧äŒäžã«èŠåã®èª€ããèŠã€ãã£ãå Žåã¯ãæ°çãäœãã圱é¿ãã
Matchãæç€ºçã«åèšç®ããã åèšç®ã¯éå¶ã®æäœãšããŠè¡ããæé»ã«èµ°ãããªãã
- ããŒãèªåœã®ç¢ºå®: å倧äŒã®ã«ãŒã«äžèЧãçªãåãããå®éã«å¿ èŠãªè¡šçŸåãæŽãåºããŠããæ±ºããã §5.5 ã®2倧äŒã¯çŸè¡ã®èªåœã§è¡šçŸã§ããŠããããããã以äžåºããªãããšãåçã®æ¹éãšããã ãããæ³åã§åºãããšãéãšã³ãžãã¢åããšããç®çããå€ããã
- 3倧äŒç®ä»¥éã§ã®åæ€èšŒ: æ¢ç¥ã®å€§äŒã2ã€ã§ã¯èªåœã®ååæ§ã䞻匵ããããªãã å¥ã®å€§äŒèŠåãæã«å ¥ã次第ãåã圢åŒïŒÂ§5.5ïŒã§æžãäžãããã確èªããã æžããªãèŠåãåºãå Žåã«äœãè¶³ããã¯ããã®ãšãã®å®äŸã«åŸãã
min/maxããŒãã®èŠåŠ: §5.5 ã®2倧äŒã§ã¯äœ¿ã£ãŠããªãã å®éã«äœ¿ãèŠåãçŸãããŸã§å®è£ ãä¿çããŠããã- åå²ããŒãã®è¿œå : åçã¯ãåå€å€å®ãããã©ã°å€å®ãã®2ã€ã
ãæå®å€ä»¥äžãããªã©ã®æ¯èŒãå¿
èŠã«ãªãããå®äŸã§ç¢ºèªããã
ãªã §5.5 ã®2倧äŒã¯ãããã
ãã©ã°å€å®ã䜿ã£ãŠããªã ïŒçåœã®ç®±ã¯åŸç¹ç®åºãããã¯å ã®ifã§æ¶è²»ãããïŒãåçããå€ã倿ãããããã - åºåã¹ããããšè¡šç€ºã®çµã³ã€ã: é ä¿¡ç»é¢ïŒÂ§8ïŒãåºåã¹ããããã©ãæç»ãããã èŠåããšã«ã¹ãããæ§æãå€ããããã衚瀺åŽãã¹ãããå®çŸ©ããé§åãããã 衚瀺ã«äœ¿ãã¹ããããèŠååŽã§æå®ãããããæ±ºããå¿ èŠãããã
- ä»åãçŽãã®åæ°äžé: åæŠãç¹°ãè¿ããŠãåç¹ãç¶ããå Žåã®æ±ãã èŠååŽã§ã¯è¡šçŸã§ããªããããéå¶ã®å€æã§æã¡åãéçšãšãããã 倧äŒèšå®ãšããŠäžéåæ°ãæã€ããæ±ºããïŒÂ§5.5ïŒã
- åŒãåãã®æ±ã: ãåŒãåããçµç«¯ã«å°éãã察æŠãã ç·åœããæŠã®é äœèšç®ãã©ãè§£éãããïŒÂ§11 ã®é äœæ±ºå®èŠåãšæ¥ç¶ããïŒã æ¢ç¥ã®2倧äŒã¯åŒãåãã䜿ããªããããåªå 床ã¯äœãã
- 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, half, ... } |
ããŒãã®ã¹ã³ã¢ç¢ºå® |
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; format: Format };
slots: OutputSlot[]; // 衚瀺ã«äœ¿ãåºåã¹ãããã®å®çŸ©ïŒÂ§8.2ïŒ
participants: ParticipantView[];
matches: MatchView[]; // 察æŠè¡šãæãã®ã«è¶³ããå
šå¯ŸæŠïŒç¶æ
ã€ãïŒ
currentMatchId: number | null;
standings: Standings | null;
};Snapshot ã« slots ãå«ããã®ã¯ §8.2 ã®ããã§ããã
Viewer ã¯ã¹ã³ã¢ã®æå³ãç¥ãããã¹ãããå®çŸ©ã«åŸã£ãŠæç»ããã
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 |
ããŒãã®ã¹ã³ã¢ç»é² |
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 } }ã®åœ¢ã«çµ±äžããã
é ä¿¡ã«èŒã衚瀺å°çšã®ç»é¢ãæäœã¯åãä»ããããµãŒããŒã®ç¶æ ã«è¿œåŸããŠè¡šç€ºã ããå€ããã
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 ãšå€ã䞊ã¹ãã
- 倧äŒAãªããç¹æ®ãã€ã³ã 2 / ã¹ã³ã¢ 15ãã®2è¡
- 倧äŒBãªããã¹ã³ã¢ 41ãã®1è¡
ããã«ããã倧äŒãå€ãã£ãŠã衚瀺ã³ã³ããŒãã³ããæ¹ä¿®ããªããŠããã
OutputSlot.label ãæãããŠããã®ã¯ãã®ããã§ããã
ãªããã©ã®ã¹ãããã倧ããèŠãããããªã©æŒåºäžã®åªå£ã¯ããã®ä»çµã¿ã§ã¯æ±ºãŸããªãã åçã¯å®£èšé ã®å é ã䞻衚瀺ãšãã现ããå¶åŸ¡ãå¿ èŠã«ãªã£ãæç¹ã§ §5.8 ã®æªæ±ºäºé ãšããŠæ±ãã
ããŒãã¡ã³ããšç·åœããã®äž¡æ¹ãæ±ããã©ã¡ããã察æŠäžèЧ + å察æŠã®ç¶æ
ãããæç»ã§ãã
Tournament.format ã§æãåããã
- ããŒãã¡ã³ã:
MatchãåæŠããšã«é 眮ããåè ãæ¬¡ã®å¯ŸæŠãžç¹ãã§æãã - ç·åœãã: åå è à åå è ã®è¡šãšããåã»ã«ã«å¯ŸæŠã®ç¶æ ãšçµæãå ¥ããã
ãããã Match.stateïŒPENDING / IN_PROGRESS / 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 ã¹ããŒã | Tournament / ScoreRule / MatchResult / MatchState ã远å |
§4 |
| åæãã³ãŒãã«çŽæžã | ScoreRule ã®ã°ã©ããšããŠå€éšå |
§5 |
ã¹ã³ã¢èšç®ãŸããïŒÂ§5ïŒã¯èšèšãç¶ç¶äžã®ãããããã«äŸåããªãéšåãå ã«é²ããã 以äžã®2ãã©ãã¯ã¯ç¬ç«ããŠåãããã
ãã©ãã¯A â åå°ãšç»é¢ïŒå è¡ïŒ
- pnpm workspace åãš
packages/sharedã®åãåºã - ã€ãã³ãå®çŸ©ãš
Snapshotåã®ç¢ºå®ïŒÂ§6.2ïŒãã¹ã³ã¢ã®äžèº«ã¯slotsçµç±ã§æ±ãããã èšç®èŠåãæªç¢ºå®ã§ããã®åã¯æ±ºãããã - é²è¡ãŸããã® Prisma ã¹ããŒãïŒ
Tournament/Participant/MatchïŒãšãã€ã°ã¬ãŒã·ã§ã³ãScoreRule/MatchResultã¯å«ããªã - API Route Handlers + SSE ã®å®è£
ã
chros-websockã®åé€ - Viewer ã® SSE åãšåç»é¢ã®å®è£
ïŒÂ§8ïŒã
socket.io-clientã®åé€ - Console ã® Server Actions åïŒé²è¡æäœã»ç»é¢åãæ¿ãïŒ
chros-scoreã®åé€ãš docker-compose ã®æŽç
ãã©ãã¯B â ã¹ã³ã¢èšç®ïŒäžŠè¡ããŠèšèšãç¶ç¶ïŒ
- ããŒãèªåœãš
ScoreRuleGraphä¿å圢åŒã®ç¢ºå®ïŒÂ§5.8 ã®æªæ±ºãè§£æ¶ïŒ Score/ScoreRule/MatchResultã®ã¹ããŒã確å®ãšãã€ã°ã¬ãŒã·ã§ã³packages/scoringã®è©äŸ¡åšã»æ€èšŒåšã®å®è£ ãšãã¹ãïŒçŽç²é¢æ°ãªã®ã§åç¬ã§åºããããïŒ- ããŒããšãã£ã¿ UI
ãã©ãã¯Aãé²ããããã ãã¹ã³ã¢ã¯åºå®ã®ãããŒå®è£
ã§ä»£æ¿ããŠããã
§8.2 ã®ãšãã Viewer ã¯ã¹ãããå®çŸ©ã«åŸã£ãŠæç»ããããã
ã¹ãããã { name: 'score' } 1ã€ã ãã®ãããŒãè¿ããŠããã°ç»é¢ã¯å®æãããããã
è©äŸ¡åšãä¹ã£ãæç¹ã§å·®ãæ¿ãããViewer åŽã®æ¹ä¿®ã¯äžèŠã«ãªãã
ããŒããšãã£ã¿ UIïŒæé 11ïŒã¯å·¥æ°ã倧ãããå ã«æé 10ãŸã§ãæžãŸãã JSON ãçŽæ¥æå ¥ããŠè©äŸ¡ã§ããç¶æ ãäœããããããã°ãšãã£ã¿ãæªå®æã§ã倧äŒéçšã¯æç«ããã
æªæ±ºã®ãã¡çæåã«æ±ºããå¿ èŠããããã®ãšãåŸåãã§ãããã®ãåããŠèšãã
- ããŒãèªåœã®ç¢ºå®ã
min/maxãšãã©ã°å€å®ã®èŠåŠïŒÂ§5.8ïŒ Score/ScoreRule/MatchResultã®ã¹ããŒã確å®- 3倧äŒç®ã®èŠåã§ã®èªåœã®åæ€èšŒïŒÂ§5.8ïŒ
§5 ãšåçã®æ€èšãå¿ èŠã ãããŸã äœã決ãŸã£ãŠããªãã ã¹ã³ã¢èšç®ãèŠåã§å·®ãæ¿ãå¯èœã«ãã以äžãé äœèŠåã倧äŒããšã«å€ããã¯ãã§ããã ãããã³ãŒãã«çŽæžããã㚠§5 ã§åŸã坿¬æ§ãããã§éåããã
- é äœã®æ±ºãæ¹ïŒåã¡ç¹å¶ / åç / åŸå€±ç¹å·® / çŽæ¥å¯Ÿæ±ºïŒ
- åé äœã®æ±ããšãä»åãçŽãã«çµãã£ã察æŠã®éèšäžã®æ±ãïŒÂ§5.5ïŒ
- äºéžç·åœãã â æ±ºåããŒãã¡ã³ãã®æ¥ç¶æ¹æ³ãã·ãŒãæ±ã
- é äœèŠåã
ScoreRuleãšåããããŒã¿ãšããŠæã€ããåçã¯ã³ãŒãã«çœ®ãã
ãã©ãã¯AïŒÂ§10.1ïŒã¯é äœèšç®ã«äŸåããªãããããããä¿çãããŸãŸé²ããããã
ãã ã standings ç»é¢ïŒÂ§8.1ïŒã ãã¯äžèº«ã決ãŸããªãã
- CHaser æ¬äœãšã®é£æºæç¡ïŒçŸç¶ã¯æå ¥ååæãå°æ¥ãã°åã蟌ã¿ãè¡ããïŒ
- 倧äŒåŸã®èšé²å ¬éã®åœ¢åŒïŒéçæžãåºãããã·ã¹ãã ã皌åããç¶ãããïŒã 皌åããç¶ããå Žåã¯èªèšŒã®èŠåŠã忀èšããïŒÂ§1.3ïŒ
- ç»é¢é·ç§»ã®æŒåºãåºåã¹ãããã®è¡šç€ºäžã®åªå£ïŒÂ§8.2ïŒ