問題リプレイ機能プロポーザル[WIP]

ページ名:問題リプレイ機能プロポーザル


メモ (2019-06-01 カニチャット Cindychat で) クリックでオープン


はやて◆
 現在Cindyにアクセスできないので、ここでメモ:
 ラテシン本家問題を使用します:http://sui-hei.net/mondai/show/1 2019/06/01 19:57
はやて◆
  kuromoji.js で問題文を形態素解析した結果です 2019/06/01 19:58
はやて◆
 1 *    1 レストラン 1 一   1 勘定
 1 口    1 呼ぶ    1 帰宅  1 彼
 1 後    1 止める   1 注文  1 海
 1 済ませる 1 自殺    1 見える 1 間違い
 1 飲む   2 男     4 する  4 ウミガメ
 6 スープ  2019/06/01 20:00
はやて◆
 (名詞と動詞のみ摘出) 2019/06/01 20:01
はやて◆
 以下は質問の結果 2019/06/01 20:03
はやて◆
 1 海 見える レストラン 選ぶ こと 男 自殺 する こと 関係 ある
 2 男 自殺 する 理由 ウミガメ スープ 飲む こと 原因
 3 男 借金 抱える いる
 4 男 自殺 する の スープ 飲む こと 原因
 5 話 現実 的 要素 含む れる
 6 死因 関係 ある 2019/06/01 20:07
はやて◆
 7 男 過去 何 ある
 8 過去 ウミガメ スープ 食べる 事 ある
 9 過去 食べる もの ウミガメ スープ 勘違い する いる
 10 男 職業 船乗り
はやて◆
 11 男 過去 遭難
 12 物語 死人 でる くる
 13 男 過去 遭難 飢える ため 人 食べる
 14 他 乗組 員 ウミガメ スープ 言う れる 食べる
 15 男 遭難 中 ウミガメ スープ 言う れる 食べる スープ 味 レストラン ウミガメ スープ 味 違う 事 遭難 中 食べる モノ 人 こと 気づく 絶望 する 2019/06/01 20:11
はやて◆
 で、すべての問題と質問に出る単語を数えた結果です: 2019/06/01 20:13
はやて◆
 ('男', 9), ('スープ', 9), ('ウミガメ', 7), ('する', 6), ('食べる', 6), ('こと', 5), ('自殺', 4),
 ('ある', 4), ('過去', 4), ('飲む', 3), ('れる', 3), ('遭難', 3), ('海', 2), ('見える', 2),
 ('レストラン', 2), ('関係', 2), ('原因', 2), ('いる', 2), ('事', 2), ('人', 2), ('言う', 2),
 ('中', 2), ('味', 2), ('一', 1), ('勘定', 1), ('口', 1), ('呼ぶ', 1), ('帰宅', 1), ('彼', 1),
 ('後', 1), ('止める', 1), ('注文', 1), ('済ませる', 1), ('間違い', 1) 2019/06/01 20:15
はやて◆
 ('選ぶ', 1), ('理由', 1), ('借金', 1), ('抱える', 1), ('の', 1), ('話', 1), ('現実', 1), ('的', 1),
 ('要素', 1), ('含む', 1), ('死因', 1), ('何', 1), ('もの', 1), ('勘違い', 1), ('職業', 1),
 ('船乗り', 1), ('飢える', 1), ('ため', 1), ('他', 1), ('乗組', 1), ('員', 1),
 ('違う', 1), ('モノ', 1), ('気づく', 1), ('絶望', 1) 2019/06/01 20:16
はやて◆
 問題リプレイ機能を作るなら、出現数が1以上の名詞・動詞を選んだほうがいいかな? 2019/06/01 20:19
はやて◆
 で、最初に出現されたキーワードリストはこうなる:
 男 過去 他 海 話 死因
 男を選んだ場合、二番目のキーワード:
 自殺 借金 職業 過去 遭難 2019/06/01 20:21
はやて◆
 遭難という単語が唐突だから、質問10出る前に隠したほうが良いかな(質問10依存キーワード) 2019/06/01 20:23
はやて◆
 となると、プロポーザルに書かれている「問題文に出現したキーワードだけ最初のキーワードにする」というのは無意味になるね。「死因」は問題文に出ないけど、「自殺」を見て自然に思いつく言葉だし。 2019/06/01 20:26



メモ (2019-06-02 カニチャット Cindychat で) クリックでオープン


はやて◆
 「ウミガメ」と「スープ」を合併し、「ウミガメのスープ」キーワードを生成して、
 それからキーワード「男」「ウミガメのスープ」「人」「食べる」
 「自殺」「過去」「借金」「遭難」
 「海」「レストラン」「関係」「原因」
 「味」「注文」「現実」「重要」「職業」「死」
 を選択した結果 2019/06/02 15:26
はやて◆
 1 レストラン 男 自殺 関係
 2 男 自殺 ウミガメのスープ 原因
 3 男 借金
 4 男 自殺 原因
 5 現実
 6 死因 関係
 7 男 過去
 8 過去 ウミガメのスープ 食べる 2019/06/02 15:28
はやて◆
 9 過去 食べる ウミガメのスープ
 10 男 職業
 11 男 過去 遭難
 12 
 13 男 過去 遭難 人 食べる
 14 ウミガメのスープ 食べる
 15 男 遭難 ウミガメのスープ 食べる レストラン ウミガメのスープ 遭難 食べる 人 2019/06/02 15:32
はやて◆
 少し編集が必要になるね 2019/06/02 15:34
はやて◆
 1OK レストラン 男 自殺 関係 → 「海の見えるレストラン」を選んだことは、男が自殺したことと関係がありますか?
 2OK 男 自殺 ウミガメのスープ 原因 → 男が自殺した理由は、ウミガメのスープを飲んだことが原因ですか?
 3OK 男 借金 → 男は借金を抱えていますか?
 4OK 男 自殺 ウミガメのスープ 原因 → 男が自殺したのはスープを飲んだことが原因ですか?
 5OK 現実 → この話に非現実的要素は含まれますか?
 6EDIT男 死因 重要 → 男の死因は重要ですか? (元:死因は関係ありますか?)
 7OK 男 過去 → 男は過去に何かありましたか?
 8+  (+男) 過去 ウミガメのスープ 食べる → 過去にウミガメのスープを食べた事はある? 2019/06/02 15:39
はやて◆
 9OK? 過去 食べる ウミガメのスープ → 過去に食べたものをウミガメのスープと勘違いしていた?
 10OK 男 職業 → 男の職業は船乗り?
 11OK 男 過去 遭難 → 男は過去に遭難した?
 12+  (+人) (+死)  → この物語で、男以外の死人がでますか?
 13OK 男 過去 遭難 人 食べる → 男は、過去に遭難で飢えたために人を食べた?
 14+  (+男) ウミガメのスープ (+人) 食べる → 他の乗組員にウミガメのスープと言われ(+人を)食べた?
 15DEL 男 遭難 ウミガメのスープ 食べる レストラン ウミガメのスープ 遭難 食べる 人 2019/06/02 15:44



作成必要なコンポーネント(開発用メモ 難しいことばかり書いてる) クリックでオープン


### 出題画面
#### ワークベンチ
1. キーワード編集ワークベンチ。キーワードの合併、リネーム、選出など。


1. リスト型問題編集ワークベンチ。実装は易いけど、特に問題が多い時は少し不便です。実験中に実装できます。フィルタリング機能とソート機能は工夫する必要がありそうだ。

  • フィルタリング(質問内容、回答内容、キーワード、キーワードの位置)
  • 質問のキーワード編集。キーワード追加、削除、位置の移動など。
  • 質問(および回答)の編集、追加(基礎質のヒントあり)、削除など。

1. グラフ型問題編集ワークベンチ。(実装は遅くなる)

  • キーワードツリー(画像を参照)
  • 質問依存ツリー(2つのモード。ひとつは質問に依存する質問を編集するモード。もうひとつは質問が依存する質問を編集するモード)


#### キーワード自動的に選ぶフェイズ
1. 形態素解析して、キーワードを摘出する関数
1. どんな形態の単語を使用するパネル(デフォルト:名詞と動詞。変更は非推奨ですが、一応作る必要はあると思う)
1. キーワード出現数フィルター(または Tf-Idf に基づいたフィルター?)
1. キーワード依存ツリーを、回答文のキーワードに基づいて、自動的に生成する関数
1. 問題に使うキーワードを選定する。


このフェイズでキーワードを変更した場合、すべての質問に適用することになる。
キーワード操作フェイスになると、一つの質問に適用することになる。誤操作で変更点を上書きすることを防ぐため、このフェイズに戻ることはできない。


#### キーワード操作フェイズ
1. キーワード調整パネル(基本的はグローバルでキーワードを調整し、全ての質問に適用する機能)

  • キーワードを合併される機能:男+カメオ→カメオ
  • キーワードを合併される機能(上と同じ?):ウミガメ+スープ→ウミガメのスープ
  • キーワードを編集する機能(編集したキーワードはすべての質問に適用する):男→カメオ
  • キーワードを削除する機能

1. 質問調整パネル

  • 質問のフィルタリング
  • 質問の追加、編集または削除
  • 質問のキーワードを変更する(追加または削除)機能
  • キーワードが重複の質問をハイライト表示

1. ヒント調整パネル

  • ヒントの追加、編集または削除

1. キーワード依存ツリーを調整するパネル

  • キーワードを指定された質問に依存するように調整できる

### 質問画面
1. 質問キーワード選択のパネル
1. 質問状況をサーバーにアップロードし、コンティニューできるようにする機能
1. ヒントを見るボタン ヒント見るにはひらめきコインが必要とか?
1. 諦めてそのまま解説を見るボタン?ヒントのX番目をほぼ解説にする?


### その他
#### データベースデザインについて


graphql schema


One option is to use pure sql database:

```graphql
type Replay {
  id: Int!
  puzzle: Puzzle
  user: User!
  created_at: Timestamp!
  updated_at: Timestamp!
  #dialogues: [ReplayDialogue]
}

type ReplayKeyword {
  id: Int!
  keyword: String!
}

type ReplayDialogue {
  id: Int!
  replay_id: Int!
  #replay: Replay!
  question: String!
  answer: String!
  #depends_on: [ReplayQuestion]
  #keywords: [ReplayKeyword]!
}

type ReplayDialogueDependency {
  id: Int!
  dialogue_id: Int!
  #dialogue: ReplayDialogue!
  depends_on_id: Int!
  #depends_on: ReplayDialogue!
}

type ReplayDialogueKeyword {
  id: Int!
  dialogue_id: Int!
  #dialogue: ReplayDialogue!
  keyword_id: Int!
  #keyword: ReplayKeyword!
}

type ReplayPlaygroundDialogue {
  id: Int!
  dialogue_id: Int!
  #dialogue: ReplayDialogue!
  playground_id: Int!
  #playground: ReplayPlayground!
  created_at: Timestamp!
}

type ReplayPlayground {
  id: Int!
  status: Int!  # Whether the replay is finished for the current user.
  created_at: Timestamp!
  updated_at: Timestamp!
  #dialogues: [ReplayPlaygroundDialogue]
  #replay: Replay!
  replay_id: Int!
  #user: User!
  user_id: Int!
}
```

Another option is to store keywords and questions in json fields.

```graphql
type Replay {
  id: Int!
  puzzle: Puzzle
  user: User!
  questions: Json!
  created_at: Timestamp!
  updated_at: Timestamp!
}

type ReplayPlayground {
  id: Int!
  replay: Replay!
  user: User!
  status: Int!  # Whether the replay is finished for the current user.
  data: Json!
}
```




画像のソースコード

@startuml
object Replay {
    id: Int!
    puzzle_id: Int
    user_id: Int!
    created_at: Timestamp!
    updated_at: Timestamp!
}

object ReplayDialogue {
    id: Int!
    replay_id: Int!
    question: String!
    answer: String!
}
Replay "1" -- "0..n" ReplayDialogue
ReplayDialogue "0..n" -- "0..n" ReplayDialogue : ReplayDialogueDependency

object ReplayKeyword {
    id: Int!
    keyword: String!
}
ReplayDialogue "0..n" -- "0..n" ReplayKeyword : ReplayDialogueKeyword

object ReplayPlayground {
    id: Int!
    replay_id: Int!
    user_id: Int!
    status: Int!
    created_at: Timestamp!
    updated_at: Timestamp!
}
ReplayPlayground "0..n" -- "1" Replay

object ReplayPlaygroundDialogue {
    id: Int!
    dialogue_id: Int!
    playground_id: Int!
    created_at: Timestamp!
}
ReplayPlaygroundDialogue "0..n" -- "1" ReplayPlayground
ReplayPlaygroundDialogue "0..n" -- "1" ReplayDialogue

@enduml


#### キーワードツリーのデザインについて
暫定 react-d3-tree のフォーク+react-dnd でツリー生成及びドラッグドロップ機能実現をします。






上記画像のコード(planetumlでコンパイルしてください)


@startmindmap

* Root

** レストラン
*** 男
**** 自殺
***** 関係
****** 「海の見えるレストラン」を選んだことは、男が自殺したことと関係がありますか?

** 男
*** 自殺
**** ウミガメのスープ
***** 原因
****** 男が自殺した理由は、ウミガメのスープを飲んだことが原因ですか?
****** 男が自殺したのはスープを飲んだことが原因ですか?
***** 人
****** 食べる
******* 他の乗組員にウミガメのスープと言われ人を食べた?

*** 借金
**** 男は借金を抱えていますか

*** 死因
**** 重要
***** 男の死因は重要ですか?

*** 過去
**** 男は過去に何かありましたか?
**** ウミガメのスープ
***** 食べる
****** 過去にウミガメのスープを食べた事はある?
**** 遭難
***** 人
****** 食べる
******* 男は、過去に遭難で飢えたために人を食べた?

*** 職業
**** 男の職業は船乗り?

** 現実
*** この話に非現実的要素は含まれますか?

** 過去
*** 食べる
**** ウミガメのスープ
***** 過去にウミガメのスープを食べた事はある?

** 人
*** 死
**** この物語で、男以外の死人がでますか?

@endmindmap



2019 年 6 月 16 日追記(クリックで開く)
380問の問題を元にテストしましたが、予想以上に重かったのです。
そこで出題する流れを変えたいと思います。


=========
キーワード選出パネル(選択前)
=========
|男|レストラン|・・・|



=========
キーワード選出パネル(選択後)
=========
|レストラン|・・・|


|  変更点  |
|1. 男は自殺しましたか?  自殺 「変更する」|
|2. 男の職業は船員ですか?  職業 船員 「変更する」|
|「すべて変更する」|




キーワード合併パネルとキーワード編集パネルが上と同様、キーワードボタンと変更点2つの部分を含みます。


=========
質問個別編集パネル
=========
1.男は自殺しましたか? 「男/」「自殺/」「+」「ー」
2.ウミガメのスープはまずかったですか? 「ウミガメ/」「スープ/」「+」「ー」



ー:ゴミ箱アイコン

/ :鉛筆アイコン

説明:キーワードを他のキーワードにドラッグすると位置移動、ゴミ箱にドラッグすると削除、+ボタン押すとキーワード追加、鉛筆アイコン押すとキーワード編集


=========
質問依存編集パネル(提案1)
=========
|依存される質問|依存する質問|
|ー|ー|
|[ ] 質問&回答|[ ] 質問|
|[x] 質問&回答|[ ] 質問|
|[ ] 質問&回答|[ ] 質問|
|[ ] 質問&回答|[ ] 質問|
|「すべて選択・解除」|「すべて選択・解除」|


|キーワードに基づいて依存する質問を追加するアドバイスを展示|依存される質問を追加するアドバイスを展示|



==========
質問依存一覧パネル(依存する質問リスト)(提案1)
==========

  • 男は自殺しましたか?
  • 男の職業は船員ですか?

 >男は海で遭難しましたか?
 >男は海でウミガメのスープを飲みましたか?



=========
質問依存編集パネル(タグ追加パネル)(提案2)
=========

  • 男は自殺しましたか? YES

タグ:自殺

  • 男の職業は船員ですか?

タグ:船員

  • 男は海で遭難しましたか?

タグ:遭難



=========
質問依存編集パネル(タグ依存パネル)(提案2)
=========

  • 男は自殺しましたか? YES

タグ依存:

  • 男の職業は船員ですか?

タグ依存:

  • 男は海で遭難しましたか?

タグ:船員



説明:
提案1を簡単に説明すると、複数の質問を複数の質問を依存させる時、「依存する質問」と「依存される質問」2つの視点で編集することです。
提案2を簡単に説明すると、質問で得た情報を「タグ」という形式で表現し、「タグ」の情報でどんな質問を出せるかを編集することです。


個人的に提案2がよりわかりやすいと思います。


ただ、提案2の問題点は複数タグがあった場合です。
例(2タグ):


  • 男は海で遭難しましたか?

タグ:船員 海


この場合、2つの分岐があります

  • OR:「海」と「船員」どれか一方のタグが出現したらこの質問は展示されます
  • AND:「海」と「船員」両方のタグが出現したらこの質問は展示されます

このANDとORをどう組み合わせするか、どうやってUI内で編集するかが一番の問題です。


=========
ツリー展示パネル
=========
下記のツリー図を展示する





プレビュー画像(2019-06-05)

コメント

返信元返信をやめる

※ 悪質なユーザーの書き込みは制限します。

最新を表示する
名無し編集者
>> 返信元

なるほど、わかりやすいし説明も不要な感じで良いですね。

返信
2019-06-17 18:46:23

はやて

⇩ 海and船員 or 遭難

返信
2019-06-17 06:50:13

はやて

そうですね、では

海 船員
遭難

= (海 or 船員) and 遭難

こんな表記にしますね

返信
2019-06-17 06:45:02

名無し編集者

確かにタグ方式の方がイメージ湧きやすいです。

ANDとORのUIについてですが、解放条件の設定という枠を複数作り、枠内にタグを放り込む形はどうでしょう?

例えば海と船員がORの場合、解放条件は[海][船員]という2枠になります。
ANDの場合[海・船員]という1枠になります。
いずれか1つの枠内がすべてONになれば解放される仕組みです。

2枠を[A][B・C]と設定すれば、「Aが出れば無条件に解放、BとCは両方揃わないと解放しない」というような複雑な判定にも使えそうです。


さらにNOTも加えれば、さらに複雑に……そこまではいらないかな。

返信
2019-06-17 00:55:49

はやて

2019 年 6 月 16 日追記を書きました。コメントお願いしますー

返信
2019-06-16 20:43:15

はやて

上記画像のページを配置しました: https://next.cindythink.com/add/replay/24

返信
2019-06-16 19:34:11

名無し編集者

>(でも詳しい正解文ならキーワードがすごく多くなるようです)

確かにそうですね。
正解の質問からキーワードを採用する代わりに、解説のオプションとして「(リプレイ用)要約」の入力欄を作って、そこからキーワードを拾う方式が良いかもしれません。

返信
2019-06-07 11:30:18

はやて

考えてみたら、環上配置はキーワードが少なければ、質問フェイズに使うといい感じになりますね。

>良質と正解をデフォルトで全採用
良い捉えです!了解しました
(でも詳しい正解文ならキーワードがすごく多くなるようです)

返信
2019-06-06 22:13:09

名無し編集者
>> 返信元

あー、なるほど、これだとツリーの方がわかりやすいかな。
(環上配置には失敗したので、多分図の公開はしないです。)


1つ気になったのですが、例えば「正解」のついた質問に入っている重要キーワードは、質問数に関わらず、全体を通して1回しか出てこないというケースが普通だと思うのです。
「良質」や「正解」に出現したキーワードはデフォルトで全部採用するくらいでないと抽出し損ねそうな気がするんですが、その点はいかがですか?

返信
2019-06-06 06:13:29

はやて

少しですが、サンプル画像を作りました。(ほとんどの機能が作っていないので、公開していません)

アップデート
- キーワード摘出と選択画面を作りました。
- デフォルトでキーワード出現数が log10(問題数) 以上のキーワードを選択します。(つまり、質問10以下の問題=すべてのキーワードを選択;質問10以上100以下の問題=最低2回出現したキーワードを選択;1000以下=3回)

画像にはアシカさんの問題ID=24使用しています。
質問数 18;キーワードカウント1 65;カウント2 14;カウント3 3

返信
2019-06-05 21:40:17

名無し編集者
>> 返信元

ごめんなさい、冷静に考えたら、手動かどうかは後回しで良いです。

提案の要旨は「ツリー図じゃなくてネットワーク図の方がいいのではないか」ということです。
上のツリーだと、単語にダブリがあるんですよね。
ネットワークなら縦横無尽に線で結べるので、ダブらずに済むかな、と思ったのです。

また、環の上に単語を配置する形式も考えています。
うまくいきそうだったら図を書いてアップするので、ちょっと考えさせてください。

返信
2019-06-04 10:24:16

はやて
>> 返信元

単語を手動で関連付け> どんな感じなんでしょう?
疑問詞は、質問を見れば分かると思いますから追加してないですけど。それとも質問を展示する前に(ですか?)(ますか?)などのキーワードを追加したほうがいいかな?
リプレイ問題の質に関わるので、質問の数が少ないと警告メッセージを追加するのもOKです。闇問題はこういう問題がないのですね。

返信
2019-06-04 06:41:20

はやて
>> 返信元

それは多分kuromojiのファイルがまだ全部完成していないのです

返信
2019-06-04 06:28:49

名無し編集者

デボノを見ていると、良質のつかない質問を多く準備しているケースが多いです。
目くらましという意味もあるでしょうが、したい質問がないことを避ける目的もあるようです。

Cindyの問題を見ていると、質問数が少ないのが多いです。驚異的なスナイパーが何人もいるのでハシゴの段を飛ばすように質問進行してしまうのです。
慣れない人のために、ちょっと過剰なくらい段が補充された方が良いように思います。

他の方の御意見も聞いてみたいところですが。

返信
2019-06-04 00:30:32

名無し編集者

とりあえずkuromoji.jsの説明とデモは見てきました。
名詞と動詞の抽出が容易ならば、それを利用するのはとても良い手段だと思います。

基本的には、基礎質問に、問題文中の名詞と動詞と疑問詞(5W1H ●●が何かを特定すべきですか?という形式の質問を生成)を組み合わせれば、初動の質問としてはかなり網羅できると思います。
スナイパーの質問まで再現する必要はないと思うので、それで充分だと思います。

質問に出てきた単語については、まずは手動で関連付けてみることにしたらどうでしょう?
(私の中では、線を引いてつなげるイメージです。

返信
2019-06-04 00:26:12

名無し編集者
>> 返信元

はやてさん、コードありがとうございます。
ですが、コンソール使えるほどの知識はないのでうまくいかなかったです。申し訳ない。

試しにやってみたら、
Uncaught ReferenceError: tokenizer is not defined
at getData (<anonymous>:1:36)
at <anonymous>:1:1
とエラーが出ました。

返信
2019-06-04 00:11:47

アシカ

>はやてさん、名無し編集者さん
了解です。たしかに、自然な形で報告をする程度でいいと思いますし、まだまだ先でも大丈夫ですね〜

返信
2019-06-03 19:53:48

はやて
>> 返信元

連絡なら、見ていたかはわからないけれど、http://chat.kanichat.com/chat?roomid=suiheinet で報告しました。それ以外上杉さんと連絡を取る手段はないのですよね。DEBONOのチャットでメッセージ送信したほうが良いのかな?

今はまだ大丈夫ですね。いつ完成するかどうかわからないし。(もしグラフで編集するようにしたら、モジュール2つ分くらいのコードが必要かも)

返信
2019-06-03 17:01:22

はやて

訂正:

そして以下のコードで文章を処理します

getData(`ある男が....`);

返信
2019-06-03 16:55:20

はやて

kuromoji.js のページで、F12でコンソールを開いてこのコードをペーストします

let getData = text => Array.filter(tokenizer.tokenize(text), o => o.pos === '名詞' || o.pos === '動詞').map(o => o.basic_form);

そして以下のコードで文章を処理します

tokenizer.tokenize(`ある男が....`);

返信
2019-06-03 16:53:15