今回は観客動員予測システム部分の解説をしましょう。
(いちばんやさしいpython教本の改造)観客動員予測システム「ベルマーレ観客動員予測1号ちゃん」プログラム解説③
以下がコードとなります。
def douin_csv_open(command): """フォームから入力した動員 1のような言葉を引数として受け取った時にdouin, numberという変数に分割して受け取る""" douin, number = command.split() with open('観客動員整理.csv', encoding='utf-8') as open_file: read_douin = open_file.read() douin_split = read_douin.splitlines() douin_dict = {} for douin in douin_split: team_number, mobilization = douin.split(':') douin_dict[team_number] = mobilization mobilization_dict = {} for team_number in douin_dict: audience_mobilizations = douin_dict[team_number].split(',') key = audience_mobilizations[0] name = audience_mobilizations[1] year = audience_mobilizations[2] section = audience_mobilizations[3] '''audience_mobilization = audience_mobilization[4]はエラーになるのでsを付けた''' audience_mobilization = audience_mobilizations[4] the_day_of_the_week = audience_mobilizations[5] sunny = audience_mobilizations[6] sunny_mobilization = audience_mobilizations[7] if sunny_mobilization != "観客動員数予測1": sunny_mobilization = int(sunny_mobilization) cloudy = audience_mobilizations[8] cloudy_mobilization = audience_mobilizations[9] rain = audience_mobilizations[10] rain_mobilyzation = audience_mobilizations[11] heavy_rain = audience_mobilizations[12] heavy_rain_mobilyzation = audience_mobilizations[13] star = audience_mobilizations[14] opening_match = audience_mobilizations[15] sannno_univ_special_day = audience_mobilizations[16] mobilization_dict[team_number] = (name, year, section, audience_mobilization, the_day_of_the_week, sunny, sunny_mobilization, cloudy, cloudy_mobilization, rain, rain_mobilyzation, heavy_rain, heavy_rain_mobilyzation, star, opening_match, sannno_univ_special_day) mobilization_dict[team_number] = '{}戦の観客動員数は\n{}の場合{}人\n{}の場合{}人\n{}の場合{}人\n{}の場合{}人よ。'.format(name, sunny, sunny_mobilization, cloudy, cloudy_mobilization, rain, rain_mobilyzation, heavy_rain, heavy_rain_mobilyzation) basic_message = '{}戦の観客動員数は\n{}の場合{}人\n{}の場合{}人\n{}の場合{}人\n{}の場合{}人よ。'.format(name, sunny, sunny_mobilization, cloudy, cloudy_mobilization, rain, rain_mobilyzation, heavy_rain, heavy_rain_mobilyzation) if audience_mobilization != "0": mobilization_dict[team_number] = '{}戦の観客動員数は{}人だったわ。\nお天気は{}だったわ。\nこの時私はまだ生まれてないから動員数の予測はしていないの。'.format(name, audience_mobilization, cloudy) if star == "1": mobilization_dict[team_number] = basic_message + "\nこの試合はスター選手が来るから、たくさんお客さんが来そうね。" .format(name, sunny, sunny_mobilization, cloudy, cloudy_mobilization, rain, rain_mobilyzation, heavy_rain, heavy_rain_mobilyzation, star) if sannno_univ_special_day == "1": mobilization_dict[team_number] = basic_message + "\nこの日は産能大スペシャルデーだから、たくさんの学生さんが来てくれると思うわ。" if sunny_mobilization > 15380: mobilization_dict[team_number] = basic_message + "\nスタジアムの収容人数よりも人が多い?\nごめんなさい。そういうことはまだ教わっていないの。" response = mobilization_dict return response[number]
この部分は前回解説しましたが入力された文字の分割とcsvの呼び出しをしてsplitlines()で行ごとに出力しています。
def douin_csv_open(command): """フォームから入力した動員 1のような言葉を引数として受け取った時にdouin, numberという変数に分割して受け取る""" douin, number = command.split() with open('観客動員整理.csv', encoding='utf-8') as open_file: read_douin = open_file.read() douin_split = read_douin.splitlines()
team_number, mobilization = douin.split(':')でキーとその他にデータを分ける。
douin_dict = {} for douin in douin_split: team_number, mobilization = douin.split(':') douin_dict[team_number] = mobilization
douin_dict[team_number] = mobilization
でdouin_dict(辞書)に1:'北海道コンサドーレ札幌' '14000'
のようにデータを突っ込んでいきます。
mobilization_dict = {} for team_number in douin_dict: audience_mobilizations = douin_dict[team_number].split(',')
キー以下を,で分割していきます。分割の際のポイントを解説。
'''audience_mobilization = audience_mobilization[4]はエラーになるのでsを付けた''' audience_mobilization = audience_mobilizations[4]
これは多分なんですが代入するワードと代入されるワードが同じだとエラーがでるっぽい。個人的には不可解で今でも本当にそうなのか疑問なんですが、sをつけることで改善しました。
if sunny_mobilization != "観客動員数予測1": sunny_mobilization = int(sunny_mobilization)
晴れの場合の観客動員予測のデータだけは(別に全部修正してもいいんだけど)strからintに変換しなきゃいけないんですけれど、csvデータの先頭行には観客動員数予測1のように列見出しが書いてあるので列見出しの部分はintに変換できずにエラーが出てしまうんですよね。
なのでifで
if sunny_mobilization != "観客動員数予測1":
として"観客動員数予測1"の場合は変換しないことにしました。
ちなみにintに変換する理由は終盤に出てくるこのプログラムに必要だから。
if sunny_mobilization > 15380: mobilization_dict[team_number] = basic_message + "\nスタジアムの収容人数よりも人が多い?\nごめんなさい。そういうことはまだ教わっていないの。"
僕の知識が不足(bottleではなくjupyter notebookを使った重回帰分析等の知識の方)していてスタジアムの動員数よりも上の観客動員数を予測してしまうんですよね。
ですのでintの15380がスタジアムの収容人数のMAXなのでこれより多い数値が出た場合にbasic_messageに加えて特殊なワードを喋るように改造を施したのです。
response = mobilization_dict return response[number]
あとはこんな感じでフォームから入力された番号から辞書を引き出して出力すればOK!
そのほかの機能
他の機能は改造ってほどのことはしてませんね。
ramdam機能を使ってJリーグと入力するとランダムで言葉を発します。
import random about_j_league_dict = { '1':'Jリーグ。実力差が少ないリーグという評判よ', '2':'Jリーグが強くならなければ日本代表も強くならないわ。\n選手を海外に輸出だけすれば強くなるなんて幻想よ。', '3':'みんなはどのチームのサポーターなの?\n私はもちろんベルマーレよ。', '4':'Jリーグアプリ。あれ面白そうね。', '5':'チケット買った?', '6':'バージョンが上がれば他にも会話が増えるかもね。', '7':'Jリーグは女性や子どもでも楽しめる安全なスタジアムを目指しているわ。\n私のようなインターネット上の存在でもいつか観戦できるようになるかしら?', } def about_j_league(): key, j_league = random.choice(list(about_j_league_dict .items())) choiced = j_league response = choiced return response
テキストからワードを呼び出すというのも元々の機能から改造してませんね。発する言葉は増やしましたけど。
command_file = open('pybot.txt', encoding='utf-8') raw_data = command_file.read() command_file.close() lines = raw_data.splitlines() bot_dict = {} for line in lines: word_list = line.split(',') key = word_list[0] response = word_list[1] bot_dict[key] = response
出力元のpybot.txtには以下のように記されている。
こんにちは,こんにちは! こんばんわ,こんばんわ! ありがとう,どういたしまして! おやすみなさい,おやすみなさい! さようなら,さようなら! そうだよ,そうなんだ! 頑張って,ありがとう はい,えっ?本当?やるわね! いいえ,えっ!じゃあ頑張るしかないわね! 買,チケット買いましょう。あとローストビーフ丼。 人工知能,私人工知能ではないの。バージョンが上がればそうなるかもね! ロースト,ローストビーフ丼は絶対おいしいと思うの! げっ,げげっ!
実はローストビーフ丼を食べたがっていますw
デプロイについて
デプロイについて少し。
bottleとdjangoのディレクトリを分けてお互いをデプロイするというのは出来ないわけではなさそうでした。ただ同時にdjangoに書き換えて1つのディレクトリでデプロイするのはオーソドックスな考え方と言われました。
ですのでいずれdjangoに書き換えるかもしれません。
今回はとりあえずherokuにデプロイ。
requirements.txtの構成はこんな感じ。これで動作しました。
requirment
bottle==0.12.13
python-dateutil==2.8.0
pythonanywhere==0.6
requests==2.20.0
wikipedia==1.4.0
Jinja2==2.10
今後について
これからやろうと思っていることについてメモがあります。
投票アプリケーション
Questionの掲載期限を設けたい →完了 vote→投票 →完了 投票時のコメントを設けられるようにしたい →完了 CSSをもっとかっこよくしたい →完了
将来やること 1人1票、投票6時間に1回とか→クッキーとipを送信させればできそうだが難しそう 3人まで投票できるようにしたい 棒グラフで得票数が見られるようにしたい 二重submit禁止 google analytics google adsense
掲示板アプリケーション CSSの改造 →完了 投票アプリ。今こんなの投票してます。の表示。→完了 いいねボタンの作成 →完了 フォーム横の文字を消したい → 完了
Djangoに振り替えてさくらVPSに ローカル環境時とデプロイ時でcsvの読み込みの成功不成功が変わってしまう(おそらく文字コードによる違い)のでそこをなんとかする。 →解決。ただしcsv自体は文字化けしている
将来やること ユニットテスト JavaScriptで非リダイレクトいいね(Ajax通信の使用) 二重submit禁止 画像のアップロード容量制限→完了
新しく作りたいアプリケーションもあるのですが、それよりはまず今までの復習もかねて既存アプリケーションに改造を加えたいと思っております。
たくさん作って忘れてることもあるので復習。
ただ改造においてjava scriptを学ぶ必要があるのでjava scriptをやろうと思っています。
あとものすごーく簡単なmysqlの操作方法みたいな講座を今見ているのでそれは全部見ます。
ベルマーレ観客動員予測1号ちゃん
というわけで一号ちゃんを作成は終了。まだいろいろ勉強しよう。