# 画面設計書 11-Stopwatch

## 概要

本ドキュメントは、.NET WebAssemblyブラウザテンプレートに含まれるストップウォッチ機能画面の設計書です。この画面は、WebAssemblyランタイム上で動作する時間計測機能を提供するサンプルアプリケーションです。

### 本画面の処理概要

この画面では、.NET WebAssemblyを使用してブラウザ上でストップウォッチ機能を実行できます。経過時間をリアルタイムで表示し、一時停止・リセット操作が可能です。

**業務上の目的・背景**：本画面は、.NET WebAssemblyプロジェクトテンプレートのサンプルとして提供されています。開発者がWebAssemblyアプリケーションの基本的な実装パターンを学習するための教材として、またC#とJavaScript間の相互運用（JSImport/JSExport）の実例として機能します。System.Diagnostics.Stopwatchクラスを使用した時間計測とDOM操作の連携を示すことで、WebAssemblyでのリアルタイム更新処理の実装方法を理解できます。

**画面へのアクセス方法**：ブラウザでアプリケーションのルートURL（index.html）に直接アクセスすることで画面が表示されます。dotnet new browserテンプレートで生成されたプロジェクトをビルド・実行後、開発サーバー経由でアクセスします。

**主要な操作・処理内容**：
1. ストップウォッチの自動開始：アプリケーション起動時に"start"引数が渡されると自動的に計測を開始
2. 経過時間の表示：1秒ごとに現在の経過時間（mm:ss形式）をDOM要素に更新
3. 一時停止/再開操作：Pauseボタンでストップウォッチを一時停止、再度クリックで再開
4. リセット操作：Resetボタンで経過時間を00:00にリセット

**画面遷移**：この画面は単一画面アプリケーションのため、他画面への遷移はありません。

**権限による表示制御**：認証・権限機能は実装されていません。すべてのユーザーが全機能を使用可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Mono | 主機能 | WebAssemblyランタイム上でストップウォッチ機能を実行 |
| 59 | WebAssembly Workload | 主機能 | WebAssemblyブラウザテンプレートのビルドと実行 |
| 40 | WasmAppBuilder | 補助機能 | WebAssemblyアプリケーションのビルドサポート |

## 画面種別

単一機能画面（サンプルアプリケーション）

## URL/ルーティング

- パス: `/index.html` または `/`
- テンプレートファイル: `src/mono/wasm/templates/templates/browser/wwwroot/index.html`

## 入出力項目

| 項目名 | 入力/出力 | 型 | 説明 |
|--------|----------|-----|------|
| time | 出力 | string | 経過時間（mm:ss形式）を表示するspan要素 |

## 表示項目

| 項目名 | 説明 | 初期値 |
|--------|------|--------|
| タイトル | 画面タイトル「Stopwatch」 | Stopwatch |
| 経過時間 | 現在の計測時間を表示 | loading... |
| Pauseボタン | 計測を一時停止/再開するボタン | Pause |
| Resetボタン | 計測をリセットするボタン | Reset |

## イベント仕様

### 1-Pauseボタンクリック

**トリガー**: Pauseボタン（id="pause"）をクリック

**処理フロー**:
1. JavaScriptのイベントハンドラがクリックイベントを検知
2. C#のStopwatchSample.Toggle()メソッドをJSExport経由で呼び出し
3. Stopwatchが実行中の場合はStop()を呼び出して停止、停止中の場合はStart()を呼び出して再開
4. 戻り値（bool型、実行中かどうか）に基づいてボタンテキストを更新
5. デフォルトイベントをpreventDefault()でキャンセル

**結果**: ストップウォッチの状態が切り替わり、ボタンのラベルが「Pause」または「Start」に変更

### 2-Resetボタンクリック

**トリガー**: Resetボタン（id="reset"）をクリック

**処理フロー**:
1. JavaScriptのイベントハンドラがクリックイベントを検知
2. C#のStopwatchSample.Reset()メソッドをJSExport経由で呼び出し
3. Stopwatchが実行中の場合はRestart()で時間をリセットして継続、停止中の場合はReset()でリセット
4. Render()メソッドを呼び出して表示を即座に更新
5. デフォルトイベントをpreventDefault()でキャンセル

**結果**: 経過時間が00:00にリセットされる

### 3-定期更新（1秒間隔）

**トリガー**: アプリケーション起動後、無限ループ内でTask.Delay(1000)ごとに実行

**処理フロー**:
1. MainメソッドのwhileループがTask.Delay(1000)で1秒待機
2. StopwatchSample.Render()メソッドを呼び出し
3. 現在のElapsed時間をmm:ss形式にフォーマット
4. JSImportされたdom.setInnerText関数でDOM要素（#time）を更新

**結果**: 画面上の経過時間表示が1秒ごとに更新される

## データベース更新仕様

本画面ではデータベース操作は行いません。すべてのデータはメモリ上のStopwatchインスタンスで管理されます。

## メッセージ仕様

| メッセージ種別 | 表示条件 | メッセージ内容 |
|---------------|---------|---------------|
| コンソール出力 | アプリケーション起動時 | "Hello, Browser!" |
| 表示更新 | 初期ロード中 | "loading..." |

## 例外処理

| 例外条件 | 動作 |
|---------|------|
| WebAssemblyランタイム読み込み失敗 | ブラウザのデフォルトエラー表示。time要素は"loading..."のまま |
| JavaScript例外 | コンソールにエラー出力 |

## 備考

- 本画面は`.NET WebAssemblyブラウザテンプレート`として提供されるサンプルアプリケーションです
- `dotnet new browser`コマンドで生成されるプロジェクトの基本構成を示しています
- JSImport/JSExport属性を使用したC#とJavaScript間の双方向通信の実装例として参照可能です
- フィンガープリント機能（`main#[.{fingerprint}].js`）によりブラウザキャッシュの制御が行われます

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

ストップウォッチの状態管理に使用されるSystem.Diagnostics.Stopwatchクラスの動作を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Program.cs | `src/mono/wasm/templates/templates/browser/Program.cs` | StopwatchSampleクラスの静的フィールドstopwatchがアプリケーション全体で共有される状態を保持 |

**読解のコツ**: C#のpartialクラス構文とトップレベルステートメントを使用しているため、Program.csファイル内にStopwatchSampleクラスが定義されています。

#### Step 2: エントリーポイントを理解する

処理の起点となるJavaScriptファイルを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | main.js | `src/mono/wasm/templates/templates/browser/wwwroot/main.js` | dotnet.create()でランタイムを初期化し、setModuleImportsでJS関数をC#に公開 |

**主要処理フロー**:
1. **4行目**: dotnetモジュールをインポート
2. **6-8行目**: dotnet.create()でWebAssemblyランタイムを初期化、withApplicationArgumentsで"start"引数を設定
3. **10-14行目**: setModuleImportsでdom.setInnerText関数をC#側から呼び出せるよう登録
4. **17行目**: getAssemblyExportsでC#のエクスポート関数を取得
5. **19-29行目**: ボタンのイベントハンドラを登録
6. **32行目**: dotnet.runMain()でC#のMainメソッドを実行

#### Step 3: C#側の処理を理解する

C#のメイン処理とJavaScript連携の実装を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Program.cs | `src/mono/wasm/templates/templates/browser/Program.cs` | トップレベルステートメントでMainメソッドを定義、partialクラスでJSExport属性付きメソッドを公開 |

**主要処理フロー**:
- **6行目**: "Hello, Browser!"をコンソール出力
- **8-9行目**: 引数に"start"が含まれる場合、ストップウォッチを開始
- **11-15行目**: 無限ループで1秒ごとにRender()を呼び出し
- **22行目**: SetInnerTextはJSImport属性でJavaScript関数と連携
- **24-40行目**: Toggle()メソッドで一時停止/再開を制御
- **42-51行目**: Reset()メソッドでリセット処理

#### Step 4: HTMLテンプレートを理解する

画面構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.html | `src/mono/wasm/templates/templates/browser/wwwroot/index.html` | シンプルなHTML構造。id属性でJavaScriptから要素を特定 |

**主要処理フロー**:
- **17行目**: h1要素でタイトル「Stopwatch」を表示
- **19行目**: span#timeで経過時間を表示、初期値は"loading..."
- **22-23行目**: Pause/Resetボタンを配置

### プログラム呼び出し階層図

```
main.js (エントリーポイント)
    │
    ├─ dotnet.create()
    │      └─ WebAssemblyランタイム初期化
    │
    ├─ setModuleImports('main.js', { dom: { setInnerText } })
    │      └─ JavaScript関数をC#から呼び出し可能に登録
    │
    ├─ getAssemblyExports(mainAssemblyName)
    │      └─ C#のJSExportメソッドを取得
    │
    ├─ addEventListener('click') [reset]
    │      └─ StopwatchSample.Reset() [C#]
    │              └─ Render()
    │                      └─ SetInnerText() → dom.setInnerText [JS]
    │
    ├─ addEventListener('click') [pause]
    │      └─ StopwatchSample.Toggle() [C#]
    │
    └─ dotnet.runMain()
           └─ Program.Main() [C#]
                  └─ while(true)
                         ├─ StopwatchSample.Render()
                         │      └─ SetInnerText() → dom.setInnerText [JS]
                         └─ Task.Delay(1000)
```

### データフロー図

```
[入力]                      [処理]                           [出力]

ユーザークリック          JavaScript                     DOM更新
(Pauseボタン)    ───▶    イベントハンドラ    ───▶    ボタンラベル変更
                              │
                              ▼
                    StopwatchSample.Toggle()
                        [C# JSExport]
                              │
                              ▼
                    Stopwatch.Start()/Stop()
                        [.NET BCL]

───────────────────────────────────────────────────────

タイマー(1秒)              C#処理                        DOM更新
Task.Delay(1000) ───▶ StopwatchSample.Render() ───▶ #time span
                              │
                              ▼
                      SetInnerText()
                      [JSImport]
                              │
                              ▼
                    dom.setInnerText()
                      [JavaScript]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.html | `src/mono/wasm/templates/templates/browser/wwwroot/index.html` | テンプレート | 画面構造を定義するHTMLファイル |
| main.js | `src/mono/wasm/templates/templates/browser/wwwroot/main.js` | ソース | JavaScriptエントリーポイント、ランタイム初期化とイベント処理 |
| Program.cs | `src/mono/wasm/templates/templates/browser/Program.cs` | ソース | C#メイン処理、Stopwatch制御ロジック |
| browser.0.csproj | `src/mono/wasm/templates/templates/browser/browser.0.csproj` | 設定 | プロジェクト設定、SDK・ターゲットフレームワーク定義 |
| AssemblyInfo.cs | `src/mono/wasm/templates/templates/browser/Properties/AssemblyInfo.cs` | ソース | アセンブリ属性定義 |
