From 5c8070114d4d0b10a7710ae1f11dbda07f0356a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BF=E3=81=9E=40CrazyBeatCoder?= Date: Thu, 16 Aug 2018 16:28:10 +0900 Subject: [PATCH] feat(*.py): add limit count of words that Google Home will response. fix #419 @2.5h --- domain.py | 70 ++++++++++++++++++++++++++++++++++---------- infra.py | 87 +++++++++++++++++++++++++++++++++++++++++++------------ main.py | 3 ++ 3 files changed, 127 insertions(+), 33 deletions(-) diff --git a/domain.py b/domain.py index 5e68154..b4c33dc 100644 --- a/domain.py +++ b/domain.py @@ -25,6 +25,7 @@ ASK_CONTINUE_EVENT = u'ASK_CONTINUE_EVENT' ASK_WORD_EVENT = u'ASK_WORD_EVENT' DECLARE_USER_LOSE_EVENT = u'DECLARE_USER_LOSE_EVENT' +DECLARE_GOOGLE_HOME_LOSE_EVENT = u'DECLARE_GOOGLE_HOME_LOSE_EVENT' def ask_continue(obj): @@ -52,7 +53,12 @@ def response_word(obj): queryResult = obj[u'queryResult'] userId = originalDetectIntentRequest[u'payload'][u'user'][u'userId'] queryText = queryResult[u'queryText'] + + user = infra.load_user(userId) + if queryText == ASK_WORD_EVENT: + infra.reset_datastore(user) + infra.save_word_datastore(user, u'シリトリ') return { u'fulfillmentText': u'しりとり、の、リ', } @@ -62,36 +68,70 @@ def response_word(obj): if reading: logging.info(reading) reading_end = reading[-1] - if infra.check_last_word_datastore(userId, reading): + if infra.check_last_word_datastore(user, reading): if reading_end == u'ン': - infra.reset_datastore(userId) + infra.reset_datastore(user) return { u'followupEventInput': { u'name': DECLARE_USER_LOSE_EVENT, u'languageCode': queryResult[u'languageCode'], } } - elif infra.check_word_datastore(userId, reading): - infra.save_word_datastore(userId, reading) - word_record = infra.search_word_record_from_dic( - userId, reading_end) - logging.info(word_record) - word = word_record[u'org'][0] - infra.save_word_datastore(userId, word_record[u'key']) - fulfillmentText = word + u'、の、' + word_record[u'end'] - logging.info(fulfillmentText) - return { - u'fulfillmentText': fulfillmentText, - } + elif infra.check_word_datastore(user, reading): + infra.save_word_datastore(user, reading) + if infra.is_need_google_home_lose(user): + return { + u'followupEventInput': { + u'name': DECLARE_GOOGLE_HOME_LOSE_EVENT, + u'languageCode': queryResult[u'languageCode'], + } + } + else: + word_record = infra.search_word_record_from_dic( + user, reading_end) + logging.info(word_record) + word = word_record[u'org'][0] + infra.save_word_datastore(user, word_record[u'key']) + fulfillmentText = word + u'、の、' + word_record[u'end'] + logging.info(fulfillmentText) + return { + u'fulfillmentText': fulfillmentText, + } else: return { u'fulfillmentText': u'それは使用済みの言葉です', } else: return { - u'fulfillmentText': infra.get_last_word_datastore(userId) + u'で始まる言葉を使ってください', + u'fulfillmentText': infra.get_last_word_datastore(user) + u'で始まる言葉を使ってください', } else: return { u'fulfillmentText': u'それは知らない言葉です', } + + +def response_lose_word(obj): + originalDetectIntentRequest = obj['originalDetectIntentRequest'] + userId = originalDetectIntentRequest[u'payload'][u'user'][u'userId'] + + user = infra.load_user(userId) + reading_end = user.last_word[-1] + + word_record = infra.search_lose_word_record_from_dic( + user, reading_end) + logging.info(word_record) + fulfillmentText = u'' + if word_record: + word = word_record[u'org'][0] + infra.save_word_datastore(user, word_record[u'key']) + fulfillmentText += word + u'。' + fulfillmentText += u'あら、「ん」で終わってしまいました。' + else: + fulfillmentText += u'うーん、「' + reading_end + u'」で始まる言葉が思いつきません。' + fulfillmentText += u'私の負けです。' + logging.info(fulfillmentText) + infra.reset_datastore(user) + return { + u'fulfillmentText': fulfillmentText, + } diff --git a/infra.py b/infra.py index 421568c..50030b1 100644 --- a/infra.py +++ b/infra.py @@ -23,6 +23,10 @@ import json import random +# しりとりが WORDS_COUNT_LIMIT 以上続いたら AI が降参する +WORDS_COUNT_LIMIT = 10 + + with open('data/dict.json') as json_file: json_dic = json.load(json_file) @@ -34,36 +38,51 @@ class User(ndb.Model): date = ndb.DateTimeProperty(auto_now_add=True) -def reset_datastore(user_id): +def load_user(user_id): try: user = User.get_by_id(user_id) + if user: + return user + except Exception: + pass + + user = User(id=user_id) + user.words = None + user.last_word = None + user.count = 0 + user.date = None + return user + + +def reset_datastore(user): + try: user.key.delete() + user.words = None + user.last_word = None + user.count = 0 + user.date = None except Exception: pass -def get_last_word_datastore(user_id): +def get_last_word_datastore(user): try: - user = User.get_by_id(user_id) - if user.last_word == u'': - return u'リ' return user.last_word[-1] except Exception: - return u'リ' + pass -def check_last_word_datastore(user_id, check_word): +def check_last_word_datastore(user, check_word): try: - if check_word[0] == get_last_word_datastore(user_id): + if check_word[0] == get_last_word_datastore(user): return True return False except Exception: return True -def check_word_datastore(user_id, check_word): +def check_word_datastore(user, check_word): try: - user = User.get_by_id(user_id) words = user.words.split(u',') if check_word in words: return False @@ -72,15 +91,15 @@ def check_word_datastore(user_id, check_word): return True -def save_word_datastore(user_id, save_word): +def save_word_datastore(user, save_word): try: - user = User.get_by_id(user_id) - user.words += u',' + save_word + if user.words: + user.words += u',' + save_word + else: + user.words = save_word user.count += 1 except Exception: - user = User(id=user_id) - user.words = save_word - user.count = 1 + pass user.last_word = save_word user.put() @@ -99,7 +118,7 @@ def search_reading_from_dic(search_word): return u'' -def search_word_record_from_dic(user_id, search_first): +def search_word_record_from_dic(user, search_first): """json形式の辞書ファイルを全探索し、読みが search_first で始まる適当な単語レコードを返す。 無効な単語(既出の単語・存在しない単語・「ん」で終わる単語)のレコードは返さない。 @@ -116,10 +135,42 @@ def search_word_record_from_dic(user_id, search_first): if dict_record[u'end'] == u'ン': continue # Google Home は既出の単語を言わない - if not check_word_datastore(user_id, dict_record[u'key']): + if not check_word_datastore(user, dict_record[u'key']): continue dict_record_list.append(dict_record) if dict_record_list: return dict_record_list[random.randint(0, len(dict_record_list) - 1)] else: return {} + + +def search_lose_word_record_from_dic(user, search_first): + """json形式の辞書ファイルを全探索し、読みが search_first で始まり + かつ、「ん」で終わる単語レコードを返す。 + + :param unicode search_first: カタカナ 1 文字 + :rtype: dict + :return: 検索した単語レコード(辞書にない場合は空の辞書) + """ + dict_record_list = [] + for dict_record in json_dic: + # search_first で始まる単語レコードを検索する + if dict_record[u'first'] != search_first: + continue + # 「ん」で終わる単語を検索する + if dict_record[u'end'] == u'ン': + dict_record_list.append(dict_record) + if dict_record_list: + return dict_record_list[random.randint(0, len(dict_record_list) - 1)] + else: + return {} + + +def is_need_google_home_lose(user): + """Google Home の負け処理が必要であるかを返す。 + + :param infra.User user: ユーザ + :rtype: bool + :return: Google Home の負け処理が必要であるか + """ + return user.count >= WORDS_COUNT_LIMIT diff --git a/main.py b/main.py index 9474ec9..100e496 100644 --- a/main.py +++ b/main.py @@ -27,6 +27,7 @@ GOOGLE_ASSISTANT_WELCOME_INTENT = u'Google Assistant Welcome Intent' ASK_CONTINUE_INTENT = u'Ask Continue Intent' ASK_WORD_INTENT = u'Ask Word Intent' +DECLARE_GOOGLE_HOME_LOSE_INTENT = u'Declare Google Home Lose Intent' class MainPage(webapp2.RequestHandler): @@ -51,6 +52,8 @@ def post(self): obj = domain.set_continue(obj) elif intentDisplayName == ASK_WORD_INTENT: obj = domain.response_word(obj) + elif intentDisplayName == DECLARE_GOOGLE_HOME_LOSE_INTENT: + obj = domain.response_lose_word(obj) else: obj = { u'fulfillmentText': queryResult[u'queryText'],