def minimum_quiz(file_num=-1, category=None, image=True): """最小正解数の問題を取得する Args: file_num (int, optional): ファイル番号. Defaults to -1. category (str, optional): カテゴリ. Defaults to None. image (bool, optional): イメージフラグ. Defaults to True. Returns: results [JSON]: 取得した問題 """ # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号の時はランダムに選ぶ) table_list = get_table_list() if (file_num < 0 or len(table_list) <= file_num): file_num = random.randint(0, len(table_list) - 1) table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] # TODO イメージフラグの操作 # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } # テーブル名からSQLを作成して投げる try: with conn.cursor() as cursor: # 指定したテーブルの正解数が最も低い問題を調べる # カテゴリが指定されている場合は条件文を追加する where_statement = "WHERE" if (category is not None): where_statement += " category LIKE '%" + category + "%' " if (where_statement == "WHERE"): where_statement = "" sql = "SELECT quiz_num, quiz_sentense, answer, clear_count, fail_count, category, img_file FROM {0} ".format( table) + where_statement + " ORDER BY clear_count LIMIT 1" cursor.execute(sql) # MySQLから帰ってきた結果を受け取る # Select結果を取り出す results = cursor.fetchall() # 結果をJSONに変形して返す return {"statusCode": 200, "result": results} except Exception as e: return { "statusCode": 500, "message": 'Error: DB操作時にエラーが発生しました', "traceback": traceback.format_exc() }
def get_accuracy_rate_by_category(file_ind): """ファイル番号からカテゴリ毎の正解率を取得する関数 Args: file_ind (int): ファイル番号 Returns: result [JSON]: 取得した結果のリスト """ # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号ならエラー終了) try: table_list = get_table_list() table = table_list[file_ind]['name'] nickname = table_list[file_ind]['nickname'] except IndexError: return {"statusCode": 500, "message": 'Error: ファイル番号が正しくありません'} # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } # # SQLを作成して投げる try: with conn.cursor() as cursor: # 検索語句がカテゴリに含まれる # SQLを実行する sql_statement = "SELECT c_category,accuracy_rate FROM {0} ORDER BY accuracy_rate ".format( table + '_category_view') cursor.execute(sql_statement) # MySQLから帰ってきた結果を受け取る # Select結果を取り出す results = cursor.fetchall() # TODO Decimal -> strに直す効率良い方法、もしくは数値のままでもエラー出ずに返せる方法(DecimalのままだとAPIで取得時にエラーになる) for i in range(len(results)): ri = results[i] ri['accuracy_rate'] = str(ri['accuracy_rate']) results[i] = ri # 結果をJSONに変形して返す return {"statusCode": 200, "result": results} except Exception as e: return { "statusCode": 500, "message": 'Error: DB操作時にエラーが発生しました', "traceback": traceback.format_exc() }
def random_quiz(file_num=-1, image=True, rate=100.0, category=""): """問題を1問、ランダムに取得するAPI Args: file_num (int, optional): ファイル番号. Defaults to -1. image (bool, optional): 画像取得フラグ. Defaults to True. rate (float, optional): 取得する問題の正解率の最大値. Defaults to 100.0. category (str, optional): 取得する問題のカテゴリ Defaults to '' Returns: result (JSON): ランダムに取得した問題 """ # TODO image_flagの処理 # TODO rateの処理 # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号の時はランダムに選ぶ) table_list = get_table_list() if (file_num < 0 or len(table_list) <= file_num): file_num = random.randint(0, len(table_list) - 1) table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } # WHERE文作成 where_statement = 'WHERE' if (len(category) > 0): where_statement += (" category LIKE '%" + category + "%' ") if (where_statement == 'WHERE'): where_statement = '' # テーブル名からSQLを作成して投げる with conn.cursor() as cursor: # SQL作成して問題を取得する。結果のうちランダムに1つ取得する sql = "SELECT quiz_num, quiz_sentense, answer, clear_count, fail_count, category, img_file FROM {0} {1} ORDER BY RAND() LIMIT 1".format( table, where_statement) cursor.execute(sql) # MySQLから帰ってきた結果を受け取る # Select結果を取り出す results = cursor.fetchall() # 結果をJSONに変形して返す return {"statusCode": 200, "result": results}
def get_category(file_num): """ファイル番号からカテゴリを取得する関数 Args: file_num (int): ファイル番号 Returns: result [JSON]: 取得したカテゴリのリスト """ # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号ならエラー終了) try: table_list = get_table_list() table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] except IndexError: return {"statusCode": 500, "message": 'Error: ファイル番号が正しくありません'} # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } # # SQLを作成して投げる with conn.cursor() as cursor: # 検索語句がカテゴリに含まれる # SQLを実行する sql_statement = "SELECT DISTINCT category FROM {0} ".format(table) cursor.execute(sql_statement) # MySQLから帰ってきた結果を受け取る # Select結果を取り出す results = cursor.fetchall() categories = set([]) for ri in results: categories = categories | set(list(ri['category'].split(':'))) # 結果をJSONに変形して返す return {"statusCode": 200, "result": list(categories)}
def edit_category_of_question(data): """問題にカテゴリを追加・削除する関数 Args: data ([JSON]): JSONの配列 要素は { "file_num" : ファイル番号(int) "quiz_num" : 問題番号(int) "category" : 追加・削除するカテゴリ } """ # テーブルリスト取得 table_list = get_table_list() # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } try: # data内のクエリを1個1個見ていく for data_i in data: # ファイル番号を取得 file_num = data_i['file_num'] # 問題番号を取得 quiz_num = data_i['quiz_num'] # 追加・削除するカテゴリを取得 query_category = data_i['category'] # テーブル名取得 table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] with conn.cursor() as cursor: # まずは問題を取得 sql = "SELECT quiz_num, quiz_sentense, answer, clear_count, fail_count, category, img_file FROM {0} WHERE quiz_num = {1}".format( table, quiz_num) cursor.execute(sql) # MySQLから帰ってきた結果を受け取る # Select結果を取り出す results = cursor.fetchall() # カテゴリを取得 category = results[0]['category'] # カテゴリを修正する if (category is not None and query_category in category): # クエリで出したカテゴリがすでにある場合はそれを削除する category = category.replace(query_category, "") category = category.replace("::", ":") if (category == ":"): category = "" elif (len(category) > 1 and category[0] == ":"): category = category[1:] elif (len(category) > 1 and category[-1] == ":"): category = category[:-1] else: # クエリで出したカテゴリが含まれてない場合は追加する if (category is None or category == ''): category = query_category else: category = category + ":" + query_category # アップデート sql = "UPDATE {0} SET category = '{1}' WHERE quiz_num = {2} ".format( table, category, quiz_num) cursor.execute(sql) #全て成功したらコミット conn.commit() conn.close() return {"statusCode": 200, "message": "All OK."} # DB操作失敗時はロールバック except Exception as e: message = 'Error: DB接続時にエラーが発生しました ' try: conn.rollback() except: message += '( ロールバックにも失敗しました )' finally: return { "statusCode": 500, "message": message, "traceback": traceback.format_exc() }
def edit_quiz(file_num, quiz_num, question, answer, category, img_file): """入力データで問題を編集する関数 Args: file_num (int): ファイル番号 quiz_num (int): 問題番号 question (str): 問題文 answer (str): 答えの文 category (str): カテゴリ img_file (str): 画像ファイル名 Returns: [type]: [description] """ # 入力内容確認 if (question is None or len(question.strip()) == 0) and (answer is None or len(answer.strip()) == 0) and ( category is None or len(category.strip()) == 0) and (img_file is None or len(img_file.strip()) == 0): return {"statusCode": 500, "message": 'Error: 入力内容がありません'} # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号ならエラー終了) try: table_list = get_table_list() table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] except IndexError: return {"statusCode": 500, "message": 'Error: ファイル番号が正しくありません'} # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } try: # 入力内容からSQLを作成して投げる # SQLを実行する with conn.cursor() as cursor: # テーブルに入力内容を更新する update_question = "" if question is None or len(question.strip( )) == 0 else " quiz_sentense = '{0}', ".format(question) update_answer = "" if answer is None or len( answer.strip()) == 0 else " answer = '{0}', ".format(answer) update_category = "" if category is None or len(category.strip( )) == 0 else " category = '{0}', ".format(category) update_img_file = " img_file = '' " if img_file is None else " img_file = '{0}' ".format( img_file) sql = "UPDATE {0} SET {1} {2} {3} {4} WHERE quiz_num = {5} ".format( table, update_question, update_answer, update_category, update_img_file, quiz_num) print(sql) cursor.execute(sql) result = "Success!! [{0}-{1}]:{2},{3},{4},{5}".format( nickname, str(quiz_num), question, answer, category, img_file) #全て成功したらコミット conn.commit() conn.close() # DB操作失敗時はロールバック except Exception as e: message = 'Error: DB接続時にエラーが発生しました ' try: conn.rollback() except: message += '( ロールバックにも失敗しました )' finally: return { "statusCode": 500, "message": message, "traceback": traceback.format_exc() } # 結果(文字列)を返す return {"statusCode": 200, "result": result}
def add_quiz(file_num, input_data): """ファイル番号、問題番号、イメージ取得フラグから問題を取得する関数 Args: file_num (int): ファイル番号 input_data (str): 入力されたデータ(テスト問題,正解,カテゴリ,画像ファイル名)*x行 Returns: result (JSON): 取得した問題 """ # 入力データを1行ずつに分割 input_data = list(input_data.split('\n')) # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号ならエラー終了) try: table_list = get_table_list() table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] except IndexError: return {"statusCode": 500, "message": 'Error: ファイル番号が正しくありません'} # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } try: # データ全件数を確認 count = 0 with conn.cursor() as cursor: # 指定したテーブルの件数を調べる sql = "SELECT count(*) FROM {0}".format(table) cursor.execute(sql) results = cursor.fetchall() count = results[0]['count(*)'] # 返るデータ result = [] # 1行ずつ処理し、全て正常に行えた場合のみコミット、途中でエラーが発生した場合はロールバック for di in input_data: # 入力データ作成 data_i = di.split(',') question = data_i[0] answer = data_i[1] category = data_i[2] img_file = data_i[3] # データのidを作成 count += 1 # テーブル名と問題番号からSQLを作成して投げる # (問題番号が範囲外なら終了) # SQLを実行する with conn.cursor() as cursor: # データを挿入する sql = "INSERT INTO {0} VALUES({1},'{2}','{3}',0,0,'{4}','{5}')".format( table, count, question, answer, category, img_file) print(sql) cursor.execute(sql) result.append("Added!! [{0}-{1}]:{2},{3}".format( nickname, str(count), question, answer)) else: #全て成功したらコミット conn.commit() conn.close() # DB操作失敗時はロールバック except Exception as e: message = 'Error: DB接続時にエラーが発生しました ' try: conn.rollback() except: message += '( ロールバックにも失敗しました )' finally: return { "statusCode": 500, "message": message, "traceback": traceback.format_exc() } # 結果(文字列)を返す return {"statusCode": 200, "result": result}
def update_category_master(): """ファイル番号からカテゴリを取得する関数 Args: なし Returns: なし """ # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号ならエラー終了) try: table_list = get_table_list() table = [table_list[i]['name'] for i in range(len(table_list))] nickname = [table_list[i]['nickname'] for i in range(len(table_list))] except IndexError: return {"statusCode": 500, "message": 'Error: ファイル読み取りに失敗しました'} # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } # # SQLを作成して投げる try: # 追加するカテゴリ数 insert_categories = 0 with conn.cursor() as cursor: # テーブル毎にカテゴリのリストを取得してマスタに更新 for i in range(len(table)): # 問題テーブルからカテゴリのリストを取得 sql_statement = "SELECT DISTINCT category FROM {0} ".format( table[i]) cursor.execute(sql_statement) results = cursor.fetchall() categories = set([]) for ri in results: categories = categories | set( list(ri['category'].split(':'))) # カテゴリマスタから既にあるカテゴリを取得 sql_statement = "SELECT DISTINCT category FROM category WHERE file_name = '{0}' ".format( table[i]) cursor.execute(sql_statement) results = cursor.fetchall() already_exists_category = set( [ri['category'] for ri in results]) # マスタに入れるカテゴリリストを作る categories = list(categories - already_exists_category) insert_categories += len(categories) # カテゴリマスタにデータを入れる for ci in categories: sql_statement = "INSERT INTO category VALUES('{0}','{1}') ".format( table[i], ci) cursor.execute(sql_statement) #全て成功したらコミット conn.commit() conn.close() # DB操作失敗時はロールバック except Exception as e: message = 'Error: DB接続時にエラーが発生しました ' try: conn.rollback() except: message += '( ロールバックにも失敗しました )' finally: return { "statusCode": 500, "message": message, "traceback": traceback.format_exc() } # 結果をJSONに変形して返す return { "statusCode": 200, "message": "カテゴリマスタの更新が完了しました(新規カテゴリ数:{0})".format(insert_categories), }
def search_quiz(query, file_num, cond, category): """検索語句から問題を取得する関数 Args: query (str): 検索語句 file_num (int): ファイル番号 cond(JSON): 検索条件のオプション category (str): カテゴリ Returns: result [JSON]: 取得した問題のリスト """ # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号ならエラー終了) try: table_list = get_table_list() table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] cond_question = cond.get('question', False) cond_answer = cond.get('answer', False) except IndexError: return {"statusCode": 500, "message": 'Error: ファイル番号が正しくありません'} # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } # テーブル名と問題番号からSQLを作成して投げる with conn.cursor() as cursor: # 検索語句が問題文または解答文に含まれる # SQLを実行する sql_statement = "SELECT quiz_num, quiz_sentense, answer, clear_count, fail_count, category, img_file FROM {0} ".format( table, query) sql_statement += " WHERE " where_statement = [] if (not cond_question and not cond_answer): where_statement.append( " (quiz_sentense LIKE '%{0}%' OR answer LIKE '%{0}%') ".format( query)) if (cond_question): # 問題にチェックあったときは語句が含まれている問題文を検索 where_statement.append( " quiz_sentense LIKE '%{0}%' ".format(query)) if (cond_answer): # 答えにチェックあったときは語句が含まれている解答文を検索 where_statement.append(" answer LIKE '%{0}%' ".format(query)) if (category != ""): # カテゴリを指定して検索 where_statement.append(" category LIKE '%{0}%' ".format(category)) sql_statement += ' AND '.join(where_statement) cursor.execute(sql_statement) # MySQLから帰ってきた結果を受け取る # Select結果を取り出す results = cursor.fetchall() # 結果をJSONに変形して返す return {"statusCode": 200, "result": results}
def select_quiz(file_num, quiz_num, image_flag): """ファイル番号、問題番号、イメージ取得フラグから問題を取得する関数 Args: file_num (int): ファイル番号 quiz_num (int): 問題番号 image_flag (bool): イメージ取得フラグ Returns: result (JSON): 取得した問題 """ # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号ならエラー終了) try: table_list = get_table_list() table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] except IndexError: return {"statusCode": 500, "message": 'Error: ファイル番号が正しくありません'} # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } # テーブル名と問題番号からSQLを作成して投げる # (問題番号が範囲外なら終了) # SQLを実行する with conn.cursor() as cursor: # 指定したテーブルの件数を調べる sql = "SELECT count(*) FROM {0}".format(table) cursor.execute(sql) results = cursor.fetchall() for r in results: count = r['count(*)'] # 問題番号が範囲外なら終了 if (quiz_num < 1 or count < quiz_num): return { "statusCode": 500, "message": 'Error: {0}の問題番号は1~{1}の間で入力してください'.format(nickname, count) } sql = "SELECT quiz_num, quiz_sentense, answer, clear_count, fail_count, category, img_file FROM {0} WHERE quiz_num = {1}".format( table, quiz_num) cursor.execute(sql) # MySQLから帰ってきた結果を受け取る # Select結果を取り出す results = cursor.fetchall() # 結果をJSONに変形して返す return {"statusCode": 200, "result": results}
def answer_input(file_num,quiz_num,clear): """正解不正解データを受け取ってデータを登録する Args: answer_data (JSON): 解答データのJSON 解答データは { "file_num": ファイル番号 "quiz_num": 問題番号 "clear": 正解ならTrue、不正解ならFalse } Returns: str: レコードのSQL、実行結果 """ # 結果 result = "" # 設定ファイルを呼び出す table_list = get_table_list() # MySQL への接続を確立する try: conn = get_connection() except Exception as e: return { "statusCode": 500, "message": 'Error: DB接続時にエラーが発生しました', "traceback": traceback.format_exc() } try: # 設定ファイルを呼び出してファイル番号からテーブル名を取得 # (変なファイル番号ならエラー終了) file_num = int(file_num) quiz_num = int(quiz_num) isclear = bool(clear) table = table_list[file_num]['name'] nickname = table_list[file_num]['nickname'] # テーブル名からSQLを作成して投げる with conn.cursor() as cursor: # 指定した問題の正解(不正解)数を取得する get_column_name = "clear_count" if isclear else "fail_count" sql = "SELECT " + get_column_name + " FROM {0} where quiz_num = {1}".format(table,quiz_num) cursor.execute(sql) results = cursor.fetchall() num = int(results[0][get_column_name]) # 正解(不正解)数+1 num += 1 # SQL作成して更新する sql = "UPDATE {0} SET {1} = {2} WHERE quiz_num = {3}".format(table,get_column_name,num,quiz_num) cursor.execute(sql) # 結果を格納する result = "[" + nickname + "-" + str(quiz_num) + "]:" + ("正解" if isclear else "不正解") + " 登録OK" #全て成功したらコミット conn.commit() conn.close() # DB操作失敗時はロールバック except Exception as e: message = 'Error: DB接続時にエラーが発生しました ' try: conn.rollback() except: message += '( ロールバックにも失敗しました )' finally: return { "statusCode": 500, "message": message, "traceback": traceback.format_exc() } # 結果を返す return { "statusCode": 200, "result": result }