---
name: darts-domain
description: Provides comprehensive darts scoring rules and board structure knowledge. Use when implementing or testing darts scoring logic, validation, simulation, or any feature related to dart scores.
allowed-tools: Read
---

# Darts Domain Knowledge

ダーツボードの点数ルールとビジネスドメインの知識を定義します。

## ダーツボードの構造

### セグメント配置

真上（12時の位置）から時計回りに：
```
[20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, 16, 8, 11, 14, 9, 12, 5]
```
合計20セグメント

### リング構造（中心から外側へ）

1. **インナーブル（INNER_BULL）**: 半径 0-6.35mm（直径 12.7mm） → **50点**
2. **アウターブル（OUTER_BULL）**: 半径 6.35-16mm（直径 32mm） → **25点**
3. **インナーシングル（INNER_SINGLE）**: 半径 16-99mm → セグメント番号そのまま（1-20点）
4. **トリプルリング（TRIPLE）**: 半径 99-107mm → セグメント番号×3（3-60点）
5. **アウターシングル（OUTER_SINGLE）**: 半径 107-162mm → セグメント番号そのまま（1-20点）
6. **ダブルリング（DOUBLE）**: 半径 162-170mm → セグメント番号×2（2-40点）
7. **アウト（OUT）**: 半径 170mm以上 → **0点**

## 1投で取りうる全ての得点

### 0点
- ボード外（半径170mm以上）

### 1-20点（シングル）
- 各セグメント番号そのまま
- 有効値: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20

### 2-40点（ダブル）
- 各セグメント番号×2
- **重要**: 2から40までの**全ての偶数**が有効
- 有効値:
  ```
  2(D1), 4(D2), 6(D3), 8(D4), 10(D5),
  12(D6), 14(D7), 16(D8), 18(D9), 20(D10),
  22(D11), 24(D12), 26(D13), 28(D14), 30(D15),
  32(D16), 34(D17), 36(D18), 38(D19), 40(D20)
  ```

### 3-60点（トリプル）
- 各セグメント番号×3
- **重要**: 3から60までの**3の倍数のうち特定の値**が有効（セグメント番号は1-20のみ）
- 有効値:
  ```
  3(T1), 6(T2), 9(T3), 12(T4), 15(T5),
  18(T6), 21(T7), 24(T8), 27(T9), 30(T10),
  33(T11), 36(T12), 39(T13), 42(T14), 45(T15),
  48(T16), 51(T17), 54(T18), 57(T19), 60(T20)
  ```

### 25点・50点（ブル）
- 25点: アウターブル
- 50点: インナーブル

## 有効な得点の完全リスト（集合）

```
{
  0,
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  21, 22, 24, 25, 26, 27, 28, 30,
  32, 33, 34, 36, 38, 39, 40,
  42, 45, 48, 50, 51, 54, 57, 60
}
```

合計: **44個**の異なる得点値

注: 23, 29, 31, 35, 37, 41, 43, 44, 46, 47, 49, 52, 53, 55, 56, 58, 59 は取りえない値です（17個の無効値）。

## 無効な得点の例

- **負の数**: -1, -10, -100など
- **61以上**: 61, 62, 100, 180など
- **取りえない奇数**: 23, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59
- **浮動小数点数**: 1.5, 20.1など
- **特殊な数値**: NaN, Infinity, -Infinity

## よくある誤解

### ❌ 間違い: 22, 26, 28は取りえない値

**正しくは**: これらは全て偶数なので、ダブルスコアとして有効
- 22 = D11（ダブル11）
- 26 = D13（ダブル13）
- 28 = D14（ダブル14）

**原則**: **2から40までの全ての偶数は有効**（ダブル）

### ❌ 間違い: 21, 27は取りえない値

**正しくは**: これらはトリプルスコアとして有効
- 21 = T7（トリプル7）
- 27 = T9（トリプル9）
- 33 = T11（トリプル11）
- 39 = T13（トリプル13）

### ✅ 正しい理解

- **2-40の全ての偶数は有効**（ダブル）
- **セグメント番号1-20の3倍（3, 6, 9, ..., 60）は有効**（トリプル）
- **シングル、ダブル、トリプルの重複**: 一部のスコア（例: 6, 12, 18など）は複数の方法で達成可能
  - 6点: S6（シングル6）, D3（ダブル3）, T2（トリプル2）
  - 12点: S12（シングル12）, D6（ダブル6）, T4（トリプル4）

## 3投の合計得点

- **最小値**: 0点（3投全てボード外）
- **最大値**: 180点（T20 + T20 + T20）
- **有効範囲**: 0-180点

ただし、3投の組み合わせによって取りえない値も存在します（例: 179点、178点など）。

## 01ゲームの特殊ルール

### バスト条件

1. 残り点数を超えてしまった（オーバー）
2. 残り点数がちょうど1点になった（フィニッシュ不可能）
3. ダブルアウト時、最終投がダブルでない

### ダブルアウトルール

- 残り点数を0にする最終投は**ダブルである必要がある**
- 残り点数が奇数の場合、ダブルでフィニッシュできないため先にシングルやトリプルで調整が必要

## テスト・実装時の注意事項

### バリデーション実装時

1. **有効な得点の集合を事前生成**: Set構造を使って O(1) で判定
2. **整数チェック**: 浮動小数点数は無効
3. **特殊値チェック**: NaN, Infinity は無効
4. **範囲チェック**: 0-60の範囲が基本（ただし範囲内でも無効な値あり）

### テストケース作成時

1. **境界値テスト**: 0, 60, 61
2. **全ての偶数（2-40）をカバー**: ダブルスコア
3. **全てのトリプル（3, 6, 9, ..., 60）をカバー**: T1-T20
4. **ブル**: 25, 50
5. **無効な奇数**: 23, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59
6. **エッジケース**: NaN, Infinity, 浮動小数点数

## 有効な得点を生成するアルゴリズム

```typescript
function getValidSingleScores(): Set<number> {
  const valid = new Set<number>();

  // 0点（ボード外）
  valid.add(0);

  // 1-20点（シングル）
  for (let i = 1; i <= 20; i++) {
    valid.add(i);
  }

  // 2-40点（ダブル：全ての偶数）
  for (let i = 2; i <= 40; i += 2) {
    valid.add(i);
  }

  // 3-60点（トリプル：セグメント番号1-20の3倍）
  for (let i = 1; i <= 20; i++) {
    valid.add(i * 3);
  }

  // ブル
  valid.add(25);
  valid.add(50);

  return valid;
}
```

## 使用方法

このskillは以下のコンテキストで参照してください：

1. **テスト作成時**: test-writerサブエージェントで有効/無効な得点を判定
2. **実装時**: implementサブエージェントでバリデーションロジックを実装
3. **レビュー時**: review-fileサブエージェントでドメインロジックの正しさを検証
4. **フィードバック時**: SubagentStopフックでドメイン知識の適用を確認

**このドメイン知識を常に参照し、ダーツの点数ルールに関わる実装やテストを作成してください。**
