あかんわ

覚えたことをブログに書くようにすれば多少はやる気が出るかと思ったんです

恋するプログラムをSinatraでWebアプリにするPart.8[CHAPTER7 学習のススメ]①

記事の概要

『恋するプログラム』の[CHAPTER7 学習のススメ]を参考に、ユーザの入力した内容を覚えるチャットボットを作成します。

目次

開発環境

参考記事
Rubyの開発環境構築は、こちらの記事を参考にさせていただきました。

ノビィの辞書を増やす

入力した会話の内容をランダム辞書に追加し、応答時の語彙を動的に増やします。

アプリケーションディレクトリの構成
~/programinlove
    |- proto.rb                 // CUIチャットボットのメインファイル
    |- unmo.rb                  // チャットボットオブジェクトのモデル
    |- responder.rb             // 応答オブジェクトのモデル
    |- dictionary.rb            // 辞書を読み込み管理するクラス
    |- log.txt                  // ユーザの入力履歴を保存するログファイル
    |- /dics                    // 辞書ファイルを格納するディレクトリ
    |     |- random.txt         // ランダムな応答を返すための辞書
    |     |- pattern.txt        // パターンに合った応答を返すための辞書
    |- noby.rb                  // Webアプリのメインファイル
    |- /views                   // ビューのテンプレートを配置するディレクトリ
    |     |- index.erb          // チャットのインターフェースを表示するビュー
    |- /public                  // 静的ファイルを配置するディレクトリ
          |- nobycanvas.js      // キャラクターの画像をアニメーションさせるJavascript
          |- styles.css         // チャットのインターフェースをレイアウトするcss
          |- /img               // 画像ファイルを格納するディレクトリ
               |- /normal       // 平常時の画像を格納するディレクトリ
               |- /blink        // 瞬きの画像を格納するディレクトリ
               |- /lookaround   // 周囲を見回す画像を格納するディレクトリ
               |- /talk         // 喋る画像を格納するディレクトリ
               ~ 以下に表情ごとの画像を格納するディレクトリを配置
ソースコード

noby.rbにファイルへ書き込むためのヘルパーメソッドsave_logを追加し、ランダム辞書への語彙の追加とログファイルへの書き込みに使用します。

ファイルへの書き込みはサンプルプログラムと異なり、会話ごと実施しています。
サンプルプログラムではself_destroyの中でプログラムの終了時にまとめて保存していたので、ブラウザが閉じられた状態をプログラムの終了と捉えて、ブラウザを閉じた際のイベントの取得を試みましたが、少しばかり調べた程度では理想的な動作を実現できなかったため、それらしく動く楽な方法を選びました。

その他のRubyファイルは、サンプルプログラムと同様の記述で、特に変更はありません。

noby.rb
require 'sinatra'
require 'sinatra/reloader'

require_relative 'unmo'


# 会話ログを格納する配列
log_area = []

# 起動時にオプションを設定する
# 状態を保持するオブジェクトの生成に使う
configure do
  # ノビィ生成
  set :noby, Unmo.new('noby')
end

# ヘルパーメソッドを定義する
# ルーティングメソッドの中で使う
helpers do
  def noby
    # ノビィへアクセス
    noby = settings.noby
  end

  def prompt(resp_opt)
    # 応答を表示する際のプロンプトを作成
    resp_opt ? "#{noby.name}#{noby.responder_name}" : "#{noby.name}"
  end

  def change_looks
    # 感情値で表情を変化させる
    case noby.mood
    when -5..5 then 'talk'
    when -10..-5 then 'angry_talk'
    when -15..-10 then 'more_angry_talk'
    when 5..10 then 'happy_talk'
    when 10..15 then 'more_happy_talk'
    end
  end

  def save_log(log)
    # ファイルにログを書き込む
    noby.save

    open('log.txt', 'a') do |f|
      f.puts(log)
    end
  end
end

# URL'/'にアクセス
get '/' do
  # 日時情報をログに格納
  log = "\nUnmo System : #{noby.name} Log -- #{Time.now}"
  save_log(log)
  # 会話ログを初期化してnobyfomを表示
  log_area = []

  erb :index
end

# URL'/'にPOSTメソッドでアクセス
post '/' do
  # ユーザの入力を取得
  talk_text = params['inputarea']

  # Responderを表示するチェックボックスの状態を取得
  # チェックされてる場合は状態を維持
  resp_opt = params['respoption']
  @check = "checked" if resp_opt

  # ユーザの入力があれば応答して会話ログに表示
  unless talk_text.empty?
    @responder_resp = noby.dialogue(talk_text)
    log_area << "> #{talk_text}<br>"
    log_area << "#{prompt(resp_opt)}> #{@responder_resp}<br>"
    @noby_state = change_looks

    save_log(talk_text)
  end

  @talk_log = log_area.join

  erb :index
end

このコードのコミットには、[chapter7-1]のタグが付いてます。

実行結果

ターミナルでnoby.rbを動かし、ブラウザにhttp://localhost:4567を入力します。

~/programinlove
$ruby noby.rb

f:id:b0npu:20160107142020p:plain

会話の内容が、ランダム辞書とログファイルに保存されます。

f:id:b0npu:20160214210456p:plain

Unmo System : noby Log -- 2016-02-14 06:06:44 +0900
おはようございます
うふふ
あはは

参考書籍

参考記事

Sinatraについては、こちらの記事を参考にさせていただきました。

関連記事

- 恋するプログラムをSinatraでWebアプリにするPart.0[はじめに]
- 恋するプログラムをSinatraでWebアプリにするPart.1[CHAPTER3 ほんとに無能]
- 恋するプログラムをSinatraでWebアプリにするPart.2[CHAPTER4 あこがれのGUI]①
- 恋するプログラムをSinatraでWebアプリにするPart.3[CHAPTER4 あこがれのGUI]②
- 恋するプログラムをSinatraでWebアプリにするPart.4[CHAPTER4 あこがれのGUI]③
- 恋するプログラムをSinatraでWebアプリにするPart.5[CHAPTER5 辞書を片手に]
- 恋するプログラムをSinatraでWebアプリにするPart.6[CHAPTER6 感情コントロールの魔術師]①
- 恋するプログラムをSinatraでWebアプリにするPart.7[CHAPTER6 感情コントロールの魔術師]②
- 恋するプログラムをSinatraでWebアプリにするPart.9[CHAPTER7 学習のススメ]②
- 恋するプログラムをSinatraでWebアプリにするPart.10[CHAPTER7 学習のススメ]③
- 恋するプログラムをSinatraでWebアプリにするPart.11[CHAPTER8 文章を作り出す]
- 恋するプログラムをSinatraでWebアプリにするPart.12[CHAPTER9 ノビィ、ネットワークにつながる]
- 恋するプログラムをSinatraでWebアプリにするPart.13[おわりに]