Newer
Older
Skillsemi2023_WEB_Otaki_Nemoto / flask / testapp / views.py
from flask import render_template, request, jsonify
from testapp import app
from collections import Counter
import time

# ユーザーごとの点数を格納する辞書
user_score = {}

# playerの数
MAX_PLAYER = 70

WAIT_TIME = 40

WAIT_START = 6
CAPASITY_ERROR = 9


# 何位まで表示するか(nemoto)
max_order = MAX_PLAYER

# scoreを保存するデータ
data = [0] * MAX_PLAYER
#  user名を保存するデータ
user = [0] * MAX_PLAYER

# ゲーム中の選択肢を保存
choices = []

current_player = MAX_PLAYER
current_round = 0


# 各回のゲーム結果を保存
frequent_table = ""

# ユーザーを識別するための番号(実際の初期値は0にする)
user_number = 0

data_count = 0

order_table_array = []

most_common_option = 0
start_flag = False

start, end = 0, 0


@app.route("/", methods=["GET", "POST"])
def inputName():
    global user_number, current_player, start_flag, user

    if request.method == "GET":
        return render_template("testapp/inputName.html")
    if request.method == "POST":
        # ゲーム開始時にユーザー数を出しておき,それぞれに識別番号を振る
        if request.form.get("username") and request.form.get("language"):
            # ユーザー名を取得し,ユーザー情報を登録
            username = request.form.get("username")
            language = request.form.get("language")
            if user_number >= MAX_PLAYER or start_flag:
                return render_template(
                    "testapp/index.html", scene=CAPASITY_ERROR, language=language
                )

            user[user_number] = username
            user_number += 1
            current_player = user_number
            print("Received name:", username, "現在の参加人数:", user_number)

            return render_template(
                "testapp/index.html",
                username=username,
                user_number=user_number - 1,
                scene=WAIT_START,
                language=language,
            )


@app.route("/form", methods=["GET", "POST"])
def index():
    global frequent_table, user_number, data_count, order_table_array, most_common_option, max_order, current_player, start, end, start_flag, current_round

    if request.method == "GET":
        return render_template("testapp/index.html")

    if request.method == "POST":

        # 他のplayerが揃うのを待機(nemoto追記)
        if request.form.get("checkStart"):
            if user_number >= MAX_PLAYER or start_flag:
                start = time.time()
                return "START"
            # 全員のデータが集まった場合は,ゲーム開始
            else:
                return str(MAX_PLAYER) + " " + str(user_number)

        # 他のplayerが揃うのを待機(nemoto追記)
        if request.form.get("start"):
            start_flag = True

        # ゲーム中に選択肢を取得し,集計する
        if request.form.get("choice") and request.form.get("round"):
            if len(choices) >= current_player:
                current_round += 1
                choices.clear()
            if int(request.form.get("round")) == current_round:
                choices.append(request.form.get("choice"))
                print(f"Received choice:{choices}")
            else:
                return "FAILED"

        # 他の人が終わるまで待機
        if request.form.get("checkothers"):
            end = time.time()
            if len(choices) >= current_player or end - start > WAIT_TIME:
                start = time.time()
                current_player = len(choices)
                print(f"現在の参加人数:{current_player}")
                return calculate_majority(choices)
            else:  # 進捗を送信
                return str(len(choices)) + "\n" + str(current_player)

        # ゲーム終了時,識別番号とスコアを受け取る
        if request.form.get("number") and request.form.get("score"):
            # 識別番号を取得
            user_number = int(request.form.get("number"))
            # スコアを取得
            score = int(request.form.get("score"))  # nemoto変更
            data[user_number] = score
            print(
                "Received number:",
                user_number,
                "\nUserName:",
                user[user_number],
                "\nScore:",
                data[user_number],
            )
            data_count += 1

            # すべてのデータが集まった場合,順位表を作成 otaki
            if data_count >= current_player:
                print(data_count, current_player)
                scores_order, user_number_order = calculate_order(data)
                print(scores_order, user_number_order)
                order_table_array = create_order_table(
                    scores_order, user_number_order, max_order
                )

            return "WAIT"

        # 最終結果を集計
        if request.form.get("checkResult"):
            end = time.time()
            if end - start > WAIT_TIME:
                scores_order, user_number_order = calculate_order(data)
                order_table_array = create_order_table(
                    scores_order, user_number_order, max_order
                )

            #  順位表が作成した場合はそれを返す
            if order_table_array == []:
                return "WAIT"
            else:
                user_number = 0
                start_flag = False
                current_round = 0
                print(order_table_array)
                return "FINISH"

        return "WAIT"


# 多数派の計算
def calculate_majority(get_data):
    counter = Counter(get_data)
    get_frequent_table = ""
    # 選択肢の人数が多い順にリストを取得(選択肢、人数)
    common_order = counter.most_common()
    # 文字列として保存
    for i in range(5):
        get_frequent_table += (
            str(common_order[i][0]) if len(common_order) > i else str(4)
        )
        get_frequent_table += " "
        get_frequent_table += (
            str(common_order[i][1]) if len(common_order) > i else str(0)
        )
        get_frequent_table += "\n"

    if get_frequent_table.endswith("\n"):
        get_frequent_table = get_frequent_table[:-1]  # 最後の改行文字を削除

    return get_frequent_table


# ランキング上位の計算
def calculate_order(get_data):
    get_sorted_numbers_with_indices = sorted(
        enumerate(get_data), key=lambda x: x[1], reverse=True
    )
    get_scores = [item[1] for item in get_sorted_numbers_with_indices]
    get_labels = [item[0] for item in get_sorted_numbers_with_indices]

    return get_scores, get_labels


def create_order_table(scores, labels, max):
    get_order_table = []
    j = 0  # 同率順位の考慮

    # 最高"max位"までを表示する
    if max >= current_player:
        max = current_player

    for i in range(max):
        if i + j >= max:  # 参照する配列がこれ以上ない時
            break
        get_order_table.append(
            [str(i + 1 + j), user[int(labels[i + j])], str(scores[i + j])]
        )
        now_order = i + 1 + j  # 今の順位
        if i + j + 1 == max:  # 先ほどorder_tableに挿入した配列が,最後であった時
            break
        # 同じスコアのplayersの処理
        while str(scores[i + j]) == str(scores[i + 1 + j]):
            j += 1
            get_order_table.append(
                [str(now_order), user[int(labels[i + j])], str(scores[i + j])]
            )
            if i + j + 1 >= max:  # (i+j)と比較する配列(i+j+1)がない時
                break
    return get_order_table


@app.route("/resultJPN", methods=["GET", "POST"])
def showResultJPN():
    global order_table_array

    return render_template("testapp/showResultJPN.html", order_table=order_table_array)


@app.route("/resultENG", methods=["GET", "POST"])
def showResultENG():
    global order_table_array
    return render_template("testapp/showResultENG.html", order_table=order_table_array)