---
# System prepended metadata

title: メイドハッカソン大概念

---

# メイドハッカソン大概念

## 大概念

- 無駄に捻くれた恋愛ゲーム
- 真夏の夜の〇〇でデート with メイド
    - 海辺
    - 花火
    - 2つを選ぶ（シナリオ）
    - 夜景の綺麗な福岡の街並（同時接続数が20になったらサジェストされる隠し要素）
        - 上にポップアップで表示される
- やること
    - メイドとデート（シナリオに沿う）
    - メイドとのコミュニケーション（シナリオ関係無しにメイドにメッセージを常時爆撃出来る）
- ユーザーの心を揺さぶる演出
    - メイドの好感度が上がるとテクスチャの解像度が落ちる
        - セリフは優しくなる
    - メイドとの好感度が下がると解像度が上がる
        - セリフは辛辣になる

## maid hackathon APIの仕様

### ホストURL
https://stego-chan.yukinissie.com

### 1. シナリオリストの取得

#### URI

```
/api/scenario-info
```

#### クエリ

key|value|example
---|---|---
scenarioId|string|scenario_1

#### example

```
/api/scenario-info?scenarioId=scenario_1
```

#### Response

```json=
// GET /api/scenario-info?scenarioId=scenario_1
{
    "data": [
        {
            "id": "scene_1_1",
            "name": "hoge",
            "next_scene": "selection",
            "first": true
        },
        {
            "id": "scene_1_2",
            "name": "hoge",
            "next_scene": "準備中",
            "first": false
        },
    .
    .
    .
        {
            "id": "scene_1_11",
            "name": "hoge",
            "next_scene": "準備中",
            "first": false
        }
    ],
    "message": "ok"
}
```

### 2. シーンオブジェクトの取得

#### URI

```
/api/scene
```

#### クエリ

key|value|example
---|---|---
sceneId|string|scene_1_1
value|number|-2121212

#### example

```
/api/scene?sceneId=scene_3_11&value=-211132
```

#### Response

##### example1

```json=
// GET /api/scene?sceneId=scene_1_1&value=832028
{
    "data": {
        "id": "dialogue_1_1",
        "serifs": [
            {
                "type": "normal",
                "id": "1_1_1",
                "serif": [
                    "example",
                    "example"
                ]
            },
            {
                "type": "normal",
                "id": "1_1_2",
                "serif": [
                    "example2",
                    "example2"
                ]
            },
            {
                "type": "select",
                "id": "1_1_3",
                "serif": [
                    "どちらにする？" // selectの場合でも配列で管理
                ],
                "selects": [
                    {
                        "message": "example3",
                        "id": "scene_1_2",
                        "value": 10
                    },
                    {
                        "message": "example3",
                        "id": "scene_1_3",
                        "value": -114514
                    }
                ]
            }
        ]
    },
    "message": "ok"
}
```

##### example2

```json=
// GET /api/scene?sceneId=scene_3_11&value=-2112
{
    "data": {
        "id": "dialogue_3_11",
        "serifs": [
            {
                "type": "normal",
                "id": "3_11_1",
                "serif": [
                    "example",
                    "example"
                ]
            },
            {
                "type": "normal",
                "id": "3_11_2",
                "serif": [
                    "example2",
                    "example2"
                ]
            }
        ]
    },
    "message": "ok"
}
```

## 仕様

- シーンオブジェクト
- シナリオオブジェクト

### 基本の流れ

シナリオ（花火、海辺などを選択） -> 対応するシナリオオブジェクトを一括取得 -> 各シナリオオブジェクトにあるIDからセリフDBにアクセスしてシーンに対応したセリフデータを取得する。好感度はサーバー内部で計算を行うのでフロントは関係ない。好感度=constantでとりあえず実装して、その後動的に変える！

注意：この下は全てREST APIで提供します。

```json
//シナリオオブジェクト
//花火、海辺、福岡の夜の街並みを選ぶ時に必要な概念
{
    "id":"一意のシナリオID",
    "name":"シナリオの名前。最初シナリオを選択するときに表示すると良き",
}

//シーンオブジェクト
//博多駅のシーン(scenario_id=hoge,scene_num=0)・・・今日どこ行こう？そうだ、天神に行こう
//天神に到着(scenario_id=hoge,scene_num=1)・・・天神に到着！
{
    "id":"シーンに割り当てる一意のID。シナリオに関するデータは大体こいつをロードすれば良い",
    "scenario_id":"親のシナリオID",
    "scene_num":"自身のシーンの順番（0から始まる）。要らない気もする。"
}

```

セリフオブジェクトはJSON配列で返ってくる。DBにシナリオIDを条件に検索する。これはシーケンシャルなデータで配列の順に表示されれば良い。遅延取得などには対応しない予定。なお、分岐が発生する場合は以後は別シーンになるので注意。
セリフオブジェクトにはいくつかのtypeがある。これらのタイプをJSON形式で示し解説する。

scene_idからセリフデータを取ってくるとき

```json
{
    "id":"hogehoge",
    "scene_id":"piyopiyo",
    //入ってる順番に先頭から呼んでいけばおｋ！
    "serifs":[
        {
            "type":"基本のセリフか選択肢オブジェクトかを示すtypeが書かれている。"
            "id":"一意に割り当てるID",
            "scene_id":"シーンID",
            "serif":[
                "今日は何処に行こう？",
                "そうだ、天神駅に行こう（唐突）",
                ....
            ],
        },
        {
            "type":"基本のセリフか選択肢オブジェクトかを示すtypeが書かれている。"
            "id":"一意に割り当てるID",
            "scene_id":"シーンID",
            "serif":[
                "今日は何処に行こう？",
                "そうだ、天神駅に行こう（唐突）",
                ....
            ],
        },
        {
            "type": "select",
            "serif":"今日どこ行く？",
            "selects":[
                {
                    "message":"海",
                    "id":"ジャンプ先のシーンID"
                },        
                {
                    "message":"山",
                    "id":"ジャンプ先のシーンID"
                },
            ],
        },....
    ]
}
```

```json

//各タイプ共通要素
//normal,selectが文字列で格納されています
{
    "id":"一意に割り当てるID",
    "scene_id":"シーンID",
}

//基本のセリフオブジェクト
{
    "type":"基本のセリフか選択肢オブジェクトかを示すtypeが書かれている。"
    "id":"一意に割り当てるID",
    "scene_id":"シーンID",
    "serif":[
    "今日は何処に行こう？",
    "そうだ、天神駅に行こう（唐突）",
    ....
    ],
}

//画像付きセリフ
//画像付きメッセージの表示は画像を中央に表示すれば良い。相手が隠れても問題ない。画像の表示期限は次のセリフに移るまでである。
{
    "image_serif":[
        {
            "serif":"hogehoge：こちらは配列ではなくただのstringであることが保証されている",
            "url":"画像の保存リンク"
        },..
    ]
}

//選択肢オブジェクト
//選択肢はボタンなどを利用することを想定している。
//ボタンにメッセージを表示して押すと新しいシーンが決定するのでそのシーンのオブジェクトを取得していく。
{
    "type": "select",
    "serif":"今日どこ行く？",
    "selects":[
        {
            "message":"海",
            "id":"ジャンプ先のシーンID"
        },        
        {
            "message":"山",
            "id":"ジャンプ先のシーンID"
        },
    ],
}

```

### WebSocket通信で双方向通信で行われるやりとり

**随時アクションオブジェクトの仕様を示します。**

- こちらからのメッセージ送信（常時）
    - メイドに常時メッセージを送るとセリフ枠とは別に吹き出しか何かで簡単なレスを行う（インタラクティブなアプリになる）

```json
//メッセージを投げる時
{
    "action":"SEND_MESSAGE",
    "message":"message",
    "user_id":"user_id",　//nullでも良い（バックエンドだけで対応出来る）
}

//メイドからメッセージがやってくる時
{
    "action":"MAID_MESSAGE",
    "message":"message", //ダイアログとかポップアップでよしなに表示
}

```

- メイドのグラフィックレベル（グラフィックレベルを元に画像をスケールダウン）

```json
{
    "action":"NOTIFY_MAID_LEVEL",
    "level":1 //0~10で、数字が大きいほどグラフィックの品質が向上する
}
```


- 現在のユーザーの接続数

```json
{
    "action":"CONNECTION_COUNT",
    "num":100,
}
```


## フロントエンド

- フロントエンド
    - スタート画面
    - シナリオ選択画面
    - シーン画面
        - 選択パターン
        - セリフが出てくるパターン
        - メイドとテキストフォームとメイドのメッセージが流れる 

## バックエンド班向けもう少し細かい仕様

**ゴールは上のフロントと合わせた仕様のデータを作成すること。そのデータを生成するロジックを複雑にしていくことでゲーム感を出していく。**

### 内部で持つパラメーター

- 好感度（Userと1対1で紐付いたもの）、以後ユーザー好感度とする
- 好感度累積値（重み付けされたやつ、好感度が低い方が重みが高くなる）、以後は単に好感度と表現する。

シーンについて補足：

シナリオ：花火、シーン：1,2,3が存在すると仮定。

シーン1について、内部的にはnつのシナリオデータを用意する。これはユーザー好感度に影響される。

ユーザーからシーンの取得が来たときには

- 外部シーンID（上の仕様で書いたシーンID）と好感度からnつのラベルにマッピングしたキーを合わせて検索を行う
- 該当オブジェクトを返却する。

つまり、外から見えるシーン1について内部的にはnつのシーンデータが存在することになる。これをどれだけ作るかはシナリオライターのキャパシティーにかかっている。

## バックエンドの実装

- WebSocket通信機構の実装
    - 各種ステータス観測・送信
    - リアルタイムチャット
- REST API（シナリオデータの取得周り）
    - テストデータを返す
    - DB繋ぎ込み
    - 好感度に応じたシナリオ選択ロジック



## バックエンドの開発スケジュール

来週の水曜日程度を目標に上にあるシナリオを返すなどのAPIを一通り作成してテストオブジェクトを仕込む部分まで実装する。
その後、内部ロジックとリアルタイムコミュニケーション機構の準備を行う。


---

**ここより下は前回の覚書。気にしない**

- 干渉される要素
    - 好感度
        - 0~100の値にする
        - セリフの質が変わる（10刻みでクオリティが変わっていく）
        - メイドの画像が粗くなる
            - メイドをコンポーネント化して上塗り
    - セリフ
        - API化します
                - ツリー構造的に定義
                - 各要素毎にキーを決めて
            - 自然言語処理でよしなに出来ないか？
                - 難しい
                - 出来るか分からない
                - けど、出来れば楽
        - セリフはデータ仕様を決める
            - 目的：フロントとセリフ職人の依存関係を無くす
            - 大概念
                - 基本はJSON配列
                    - 各オブジェクトにはtypeとテキストとその他必要に応じてオブジェクトが設定されている
                        - text:テキストデータだけ
                        - select：テキスト+selectオブジェクト配列がある
                            - selectオブジェクトは{選択肢、テキスト、ID（API叩く時に渡すやつ）}
                        - 画像付きテキスト
        - 好感度の計算
            - 一端保留にしましょう
- フロント・バックエンド版・設計・セリフ職人
- バックエンド(WebSocket)
    - セリフ
    - ユーザーとのコネクション



### 仕様

- 干渉される要素
    - 好感度
        - 0~100の値にする
        - セリフの質が変わる（10刻みでクオリティが変わっていく）
        - 
        - メイドの画像が粗くなる
            - メイドをコンポーネント化して上塗り
    - セリフ
        - 5つのストーリー毎にシナリオを作成
            - フローチャート的にインタラクティブ要素を取り入れながらやる
                - ツリー構造的に定義
                - 各要素毎にキーを決めて
            - 自然言語処理でよしなに出来ないか？
                - 難しい
                - 出来るか分からない
                - けど、出来れば楽
        - セリフはデータ仕様を決める
            - 目的：フロントとセリフ職人の依存関係を無くす
            - 大概念
                - 基本はJSON配列
                    - 各オブジェクトにはtypeとテキストとその他必要に応じてオブジェクトが設定されている
                        - text:テキストデータだけ
                        - select：テキスト+selectオブジェクト配列がある
                            - selectオブジェクトは{選択肢、テキスト、ID（API叩く時に渡すやつ）}
                        - 画像付きテキスト
        - 好感度の計算
            - 一端保留にしましょう
- フロント・バックエンド版・設計・セリフ職人
- バックエンド(WebSocket)
    - セリフ
    - ユーザーとのコネクション
- フロントエンド
    - スタート画面
    - チャット画面
        - メイドとテキストフォームとメイドのメッセージが流れる
    - 選択画面
    - 背景描画
    - 現在のユーザーの接続数