# 機能設計書 109-投票機能

## 概要

本ドキュメントは、QuickerSite CMSにおけるサイト上での投票・アンケート回答機能について記載する。サイト訪問者が設置された投票（Poll）に参加し、選択肢を選んで投票できる機能である。

### 本機能の処理概要

**業務上の目的・背景**：サイト訪問者の意見を収集し、インタラクティブなコンテンツを提供するために本機能が必要である。アンケート調査、意見調査、人気投票など、様々な用途で訪問者参加型のコンテンツを実現できる。

**機能の利用シーン**：サイトページに設置された投票フォームで、訪問者が選択肢を選んで投票ボタンをクリックした際に利用される。投票後は自動的に結果表示に切り替わる。

**主要な処理内容**：
1. 投票フォームの表示（AJAX対応）
2. 投票可否のチェック（期間、既投票、IP制限）
3. 投票の記録
4. 投票結果の集計・表示
5. Cookie/セッションによる重複投票防止

**関連システム・外部連携**：投票データベース（tblPoll, tblPollVote）との連携。AJAX通信によるリアルタイム更新。

**権限による制御**：投票期間（dVoteFrom〜dVoteUntill）による表示制御。投票締切（dVoteDeadline）による投票可否制御。IPアドレスによる重複投票制限。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 投票アクション | 主機能 | サイト上での投票・アンケート回答 |

## 機能種別

データ登録処理 / AJAX処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pageAction | String | Yes | アクション種別（"vote"） | 固定値チェック |
| iPollID | String | Yes | 投票ID（暗号化済み） | 復号化処理 |
| vote | Integer | Yes | 選択肢番号（1-15） | 数値チェック |

### 入力データソース

- QueryStringリクエスト: 投票パラメータ（AJAX経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| HTML | String | 投票結果HTML（AJAX応答） |

### 出力先

AJAX応答（div要素の内容を更新）

## 処理フロー

### 処理シーケンス

```
1. 投票リクエスト受信
   └─ pageAction="vote"でルーティング

2. 投票インスタンス生成
   └─ cls_pollでiPollIDから投票情報を取得

3. registerVote実行
   └─ canVoteで投票可否チェック
   └─ 投票レコード登録
   └─ セッション/Cookieに投票済みフラグ設定

4. 結果表示
   └─ showresults()で集計結果HTML生成
   └─ AJAX応答として返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[投票インスタンス生成]
    B --> C{canVote?}
    C -->|No| D[処理終了]
    C -->|Yes| E[投票レコード登録]
    E --> F[セッション更新]
    F --> G[Cookie更新]
    G --> H[結果集計]
    H --> I[結果HTML生成]
    I --> J[AJAX応答]
    J --> K[終了]
    D --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-901 | 公開期間制御 | dVoteFrom〜dVoteUntillの期間内のみ表示 | 常時 |
| BR-902 | 投票締切 | dVoteDeadline以降は投票不可（結果表示のみ） | 締切設定時 |
| BR-903 | セッション重複防止 | 同一セッションでの重複投票防止 | 投票時 |
| BR-904 | Cookie重複防止 | 同一Cookieでの重複投票防止（10日間） | 投票時 |
| BR-905 | IP制限 | 同一IPからの投票は6回まで | 投票時 |
| BR-906 | リセット対応 | dResetDate以降のCookieは無効 | リセット設定時 |

### 計算ロジック

- 投票率計算: `percent = formatnumber((arr(i) / totalquot) * 100, 0)`
- totalquot: 0の場合は1を使用（ゼロ除算防止）

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 投票登録 | tblPollVote | INSERT | 投票レコードを登録 |
| IP重複チェック | tblPollVote | SELECT | 同一IPの投票数をカウント |
| 結果集計 | tblPollVote | SELECT | 選択肢ごとの投票数を集計 |

### テーブル別操作詳細

#### tblPollVote

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | iPollID, iVote, IP, dVoteTS | 投票情報 | 新規投票登録 |
| SELECT | count(*) | iPollID, IPでフィルタ | IP重複チェック |
| SELECT | count(*) | iPollID, iVoteでグループ化 | 結果集計 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 投票スキップ | canVote=false | 何も返さない |

### リトライ仕様

リトライ不要（重複投票は防止される）。

## トランザクション仕様

単一INSERT文で実行。

## パフォーマンス要件

- 投票ごとにSELECT COUNT実行のため、大量投票時の負荷に注意
- AJAX応答のため、高速なレスポンスが必要

## セキュリティ考慮事項

- encrypt関数によるPollIDの暗号化
- cleanup関数によるSQLインジェクション対策
- IP制限による不正投票防止
- Cookie/セッションによる重複投票防止

## 備考

- JavaScript（AJAX）による非同期投票処理
- 投票フォームと結果表示はdiv要素内で動的に切り替え
- 最大15個の選択肢をサポート

---

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

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

### 推奨読解順序

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

まず、投票を管理するクラス構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | poll.asp | `asp/includes/poll.asp` | cls_pollクラス、投票・結果表示ロジック |

**読解のコツ**: canVoteプロパティが投票可否を判定。registerVoteメソッドが投票登録処理。showresultsメソッドが結果集計・表示。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | process.asp | `asp/process.asp` | pageAction="vote"時の処理（61-67行目） |

**主要処理フロー**:
1. **61行目**: `case "vote"` - 投票アクションの分岐
2. **62行目**: `set poll=new cls_poll` - 投票インスタンス生成
3. **63行目**: `poll.registerVote()` - 投票登録実行
4. **65-67行目**: レスポンス終了処理

#### Step 3: 投票処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | poll.asp | `asp/includes/poll.asp` | registerVote、canVote、showresults |

**主要処理フロー**:
- **299-320行目**: registerVoteメソッド
  - canVoteチェック
  - tblPollVoteにINSERT
  - セッション・Cookie更新
  - showresults()を呼び出し
- **242-298行目**: canVoteプロパティ
  - 各種チェック（オンライン、締切、セッション、Cookie、IP）
- **336-380行目**: showresultsメソッド
  - 選択肢ごとの集計
  - パーセンテージ計算
  - 結果HTML生成

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

```
process.asp (エントリーポイント)
    │
    ├─ cls_poll (投票クラス)
    │      │
    │      ├─ pick() (投票情報取得)
    │      │
    │      ├─ registerVote() (投票登録)
    │      │      ├─ canVote (投票可否判定)
    │      │      │    ├─ bIsOnline
    │      │      │    ├─ dVoteDeadline
    │      │      │    ├─ session check
    │      │      │    ├─ cookie check
    │      │      │    └─ IP check
    │      │      ├─ INSERT tblPollVote
    │      │      └─ showresults()
    │      │
    │      └─ showresults() (結果表示)
    │             ├─ SELECT COUNT
    │             └─ HTML生成
    │
    └─ Response.write (AJAX応答)
```

### データフロー図

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

iPollID ────────▶ cls_poll.pick() ───▶ 投票情報
vote ───────────▶       │
       │                ▼
       │          canVote判定
       │                │
       ▼                ▼
request ────────▶ registerVote() ──▶ INSERT
                        │
                        ▼
                 showresults() ────▶ AJAX応答
                        │
                        ▼
                 SELECT COUNT
                        │
                        ▼
                 HTML生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| poll.asp | `asp/includes/poll.asp` | ソース | 投票クラス定義 |
| process.asp | `asp/process.asp` | ソース | ページアクションルーター |
| database.asp | `asp/includes/database.asp` | ソース | データベース接続クラス |
| encryption.asp | `asp/includes/encryption.asp` | ソース | 暗号化関数 |
| javascript.asp | `asp/includes/javascript.asp` | ソース | AJAX関連JavaScript |
