Goで実装されたojichatのJS版、ojichat.jsを作りました

[表参道.rb#48](https://omotesandorb.connpass.com/event/136761)の発表資料です。

---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21799/67d1c54c-9ce2-c888-b826-1ff8006b2c00.png)

[@kaiba](https://twitter.com/kaiba)です…。
最近ボーズにしました…。どうしてくれるんだ…。

----

# なにこれ?

Goで実装された[ojichat](https://github.com/greymd/ojichat)のJS版です。
一部、本家の機能に劣りますが、ブラウザで動くので以下のような利用を想定しています。

----

- Hubotにすまわせて「疲れた」とチャットしたら、おじさんbotに励ましてもらう、とかできます。嬉しい(嬉しくない)。
- チャットのクレーマーの相手をojichatにしてもらう。

などなど可能性は無限大！

----

## ここで遊べます
https://pokosho.com/a/ojichat_sample/dist/

----

## CLIでも遊べるよ!

初のnpmモジュール公開がojichat.js。

```
npm i -g ojichat.js
ojichatjs かいば
かいばチャン、ヤッホー💕😄(^_^)🎵😘何してるのかい😜⁉️かいばチャンと今度イチャイチャ、したいなぁ😃♥ 😆今日も大変だったんだね(^▽^;)(・_・;(
◎ ＿◎;)💦(^_^;
```

----

## ソースコードとか

- https://www.npmjs.com/package/ojichat.js
- https://github.com/kaibadash/ojichat.js
- https://bitbucket.org/kaiba/ojichat_sample

----

# ojichatのコードリーディング

みなさんも好きな言語にポーティングしたくなってきたことでしょう。
ojichatの仕組みを簡単に説明します。

----

## はじまり
[GeneratorのselectMessage](https://github.com/greymd/ojichat/blob/master/generator/generator.go#L66)から主な処理が始まります。

```go
func selectMessage() string {
	rand.Seed(time.Now().UnixNano())
	selectedMessage := ""
	// アルゴリズム (ONARA) を無作為に選定
	selectedOnara := pattern.Onara[rand.Intn(len(pattern.Onara))]

```

----

## [Onara](https://github.com/greymd/ojichat/blob/master/pattern/onara.go)
見慣れない単語がでてきました。

```go
// アルゴリズム (ONARA) を無作為に選定
selectedOnara := pattern.Onara[rand.Intn(len(pattern.Onara))]
```

---

## Ojisan NArikiri Randomized Algorithm

Onaraとは、近年のおじさん研究により明らかになってきたおじさんの会話パターンを乱択する
`Ojisan NArikiri Randomized Algorithm: おじさんなりきり乱択アルゴリズム` です。

すごい有意義な研究テーマですね。すごい。

---

```go
var Onara = [][]OjisanEmotion{
	// GQS パターン
	[]OjisanEmotion{GREETING, QUESTION, SYMPATHY},
	// GR パターン
	[]OjisanEmotion{GREETING, REPORTING},
	// GC パターン
	[]OjisanEmotion{GREETING, CHEERING},
	// GQI パターン
	[]OjisanEmotion{GREETING, QUESTION, INVITATION},
	// PA パターン
	[]OjisanEmotion{PRAISING, ADMIRATION},
	// S パターン (短いので SS にする)
	[]OjisanEmotion{SYMPATHY, SYMPATHY},
}
```

----

## 例:GQSパターン

GQS パターンは、GREETING(挨拶)、QUESTION(質問), SYMPATHY(気遣い/慰め/同情)から成ります。

GQSパターンを例に読み進めましょう。

---

## Greeting

```go
GREETING: []string{
  "{TARGET_NAME}{EMOJI_POS}",
  "{TARGET_NAME}、お疲れ様〜{EMOJI_POS}",
  "{TARGET_NAME}、オハヨウ〜{EMOJI_POS}",
  // 中略
```

```
さやかちゃん、お疲れ様〜＼(^o^)／
```

ojichatでは `{〜}` は Tag と呼んでおり、人名、おじさんの一人称、曜日、地名、食べ物、などがあります。

---

## Question


```go
QUESTION: []string{
    "今日はどんな一日だった{EMOJI_ASK}",
    "今日は{WEATHER}だけどなにするのかな{EMOJI_ASK}",
    "{RESTAURANT}好きかな{EMOJI_ASK}",
```

```
今日はどんな一日だった(・・?
```

---

## Sympathy

```go
SYMPATHY: []string{
    "{TARGET_NAME}{EMOJI_POS}元気、ないのかなぁ{EMOJI_NEG}大丈夫{EMOJI_ASK}",
    "僕は、すごく心配だよ{EMOJI_NEG}そんなときは、美味しいもの食べて、元気出さなきゃだね{EMOJI_POS}",
    "今日も大変だったんだね{EMOJI_NEG}",
```

```
さやかちゃん(^o^)元気、ないのかなぁ^^;(;o;)大丈夫(・・?
```

---

# さやかちゃん、お疲れ様〜＼(^o^)／今日はどんな一日だった(・・?さやかちゃん(^o^)元気、ないのかなぁ^^;(;o;)大丈夫(・・?

という具合です。

----

## 人名

パラメータで指定された場合はそれを使います。
[gimei](https://github.com/mattn/go-gimei)を使用していますね。

JS実装では、gimeiのJS実装を使おうかと思ったのですが、ファイルサイズがそこそこ大きかったため、ランダムに100個お借りしました…。

----

## 句読点を挟む

近年の研究により、句読点を多めに使うおじさんもいることがわかってきました。
形態素解析器を使用して、句読点がきてもおかしくない位置に句読点を入れます。

----

JS実装では以下の理由で実装を諦めました。

- [kuromoji.js](https://github.com/takuyaa/kuromoji.js/blob/master/README.md)を使えばできそうだけどリソース食いそう…
- [TinySegmenter](http://chasen.org/~taku/software/TinySegmenter/)は品詞が取れない…
- 句読点のタグをテンプレートに用意する?
  - 本家のテンプレート実装に追従するのが面倒になり、メンテ性がよくない

----

```go
// おじさんの文句の形態素解析に使われるなんて可哀そうなライブラリだな
t := tokenizer.NewWithDic(tokenizer.SysDicIPASimple()
```

私も可哀そうなライブラリを作りたい。

----

どうでしょう? 
みなさんも好きな言語にポーティングしたくなってきたことでしょう!
ojichat、ポーティングしていくぞ！ :muscle: 

----

# ojichat.rb 開発開始!

- https://github.com/kaibadash/ojichat.rb
- まだ .ts をコピーしてきて .rb にしただけ… 
- ~~若干飽きた~~ やるきに満ち溢れている!

---

# ojichat in Hubot

```typescript
import * as hubot from "hubot";
import * as ojichat from "ojichat.js";

module.exports = async (robot: hubot.Robot<any>) => {
  robot.hear(/おじさん/i, async (msg: hubot.Response<any>) => {
    const name = msg.message.user.name
    msg.reply(new ojichat.Generator(name).getMessage());
  });
};
```

---

# 終わりに(真面目に)

悪ふざけはこの辺にして、最後だけはまじめに。

----

- Go言語はじめてちゃんと読んだ
  - 泥臭い…! もっと短く書きたい…!
- 思ったより真面目に文章を作って勉強になった
- 面白いし、わかりやすいし、プログラミングの練習課題として良いかも
- 自分もおじさんなので気をつけたい

----

# おしまい。
ありがとうございました！