# `daq/sampler.py` 設計検討まとめ

## 実装した関数

- `class Sampler(device: Device, config: DeviceConfig)`
- `read_event() -> RawEvent`
- `count_based_iterator(num_events) -> int`
- `time_based_iterator(duration) -> None`
- `acquire_by_count(iterator) -> list[RawEvent]`
- `acquire_by_time(iterator) -> list[RawEvent]`
- `stream_events -> Iterator[RawEvent]`
- `collect_events -> list[RawEvent]`
- `save_events`
- `to_csv(events: list[RawEvent], path: Path) -> bool`

## ✅ 追加検討中の関数案

| 関数名 | 説明 |
|--------|------|
| `run_session(device, config, output_dir)` | DAQやSCAN設定に従ってイベントを収集・ファイル出力する |
| `sanitize(event)` | `RawEvent` の整形・補完・欠損チェックなどを行う |
| `tqdm_wrapper(iterator, total)` | 進捗表示つきイテレーターに変換 |
| `mock_sample(index)` | モックデータの `RawEvent` を生成（テスト用） |

---

## ✅ `run_session()` の引数方針について

### 検討された選択肢

| 案 | 内容 | 評価 |
|----|------|------|
| `RunConfig` を導入する | DAQ/SCAN共通の設定クラスを作成 | 将来的には有効だが、現段階では未導入なので採用見送り |
| `DaqConfig` / `ScanConfig` を直接使う | すでに定義されており、設定と一致している | ✅ 採用方針 |
| `Union[DaqConfig, ScanConfig]` を使う | 両方の型を受け取れるようにする | オプションとして検討可 |
| `Protocol` でインターフェース共通化 | 共通プロパティをもつ型を明示 | 後からの拡張として有効 |

---

#### RunConfigのサンプル

```python
from pydantic import BaseModel
from pathlib import Path

class RunConfig(BaseModel):
    output_dir: Path
    events_per_file: int = 1000
    events_per_run: int = 10000
    prefix: str = "osechi_data"
    use_progress: bool = True  # オプション
```

- `DaqConfig`と`ScanConfig`で代用できるので採用しない

#### Protocolのサンプル

```python
from typing import Protocol

class RunLikeConfig(Protocol):
    filename_prefix: str
    events_per_file: int
    events_per_run: int
```

```python
def run_session(device: serial.Serial, config: RunLikeConfig, output_dir: Path) -> None:
    ...
```

- `DaqConfig`, `ScanConfig` のどちらも `RunLikeConfig` とみなされる（構造的部分型）
- 明示的に共通項目を示すことで、後からの拡張やIDE補完がスムーズ
- テストやユーティリティ関数の引数型を簡潔に記述できる

## ✅ 採用する関数シグネチャ（暫定）

- `run_session(device: serial.Serial, config: Union[DaqConfig, ScanConfig], output_dir: Path) -> None`

```python
from typing import Union
from pathlib import Path
import serial

def run_session(
    device: serial.Serial,
    config: Union[DaqConfig, ScanConfig],
    output_dir: Path,
) -> None:
    """DAQまたはスキャン設定に従って、イベントを取得しファイルに保存する"""
```

---

## ✅ まとめ

- `run_session` は `DaqConfig` / `ScanConfig` をそのまま受け取る構成でOK。
- `output_dir` は TOML外部で決定するため、引数として分離。
- 今後共通化したくなったら `RunLikeConfig` のような `Protocol` で対応可能。
- 他にも `parse_line`, `sanitize`, `tqdm_wrapper` などのユーティリティが有用。
