Exemplo n.º 1
0
def _get_answers(session_id, data, session={}):
    """
    if not is_current_question and not scored:
        return failure

    get map player_id -> [answer_ids]
    compose map
        player_id:
            answer: x
            wager: n
    """
    question_index = data[QUESTION_ID]
    round_index = data[ROUND_ID]
    answers = get_question_by_index(session_id, round_index, question_index)
    if not answers[SUCCESS]:
        return answers

    answers = answers[OBJECT][ANSWERS]

    composed = {}
    for player_id in answers:
        composed[player_id] = []
        answer_ids = answers[player_id]
        for answer_id in answer_ids:
            answer = get_answer(answer_id)
            if not answer[SUCCESS]:
                return answer
            answer = answer[OBJECT]
            composed[player_id].append({ANSWER: answer[ANSWER], ID: answer[ID],
                                        WAGER: answer[WAGER]})

    return succeed(composed)
Exemplo n.º 2
0
def score_question(session_id, data, session={}):
    """
    data = {
        question_id: x
        round_id: y
        players:
            team1: {correct: true}
            team2: {correct: false}
            ...
    }

    """
    question_id = data[QUESTION_ID]
    round_id = data[ROUND_ID]

    question = session.get(ROUNDS)[round_id][QUESTIONS][question_id]
    rescore = question.get(SCORED, False)

    answers = question.get(ANSWERS, None)
    if answers is None:
        return fail(f"{QUESTION}_id {question_id} is not open")

    session_players = session.get(PLAYERS, [])
    given_players = data[PLAYERS]

    for player_id in session_players:
        if player_id not in given_players:
            return fail(f"{PLAYER_ID} {player_id} was not scored.")
        is_correct = given_players[player_id].get(CORRECT, None)
        if is_correct is None:
            return fail(f"Did not set correct True/False for {PLAYER_ID} {player_id}")

    players = get_players2(session)
    answers = get_answers_as_mod(players, answers)[OBJECT]
    for answer in answers:
        print(answer)
        if answer['answered'] is False:
            return fail(f"{PLAYER_ID} {answer[PLAYER_ID]} has not answered question {question_id}")

        last_answer = answer[ANSWERS][-1]

        player_id = answer[PLAYER_ID]
        score_override = given_players[player_id].get(SCORE_OVERRIDE, None)
        wager = last_answer[WAGER] if score_override is None else score_override  # hack here to override

        is_correct = given_players[player_id].get(CORRECT, None)
        points_awarded = wager if is_correct else 0

        mongo.update("answer", last_answer['answer_id'], {CORRECT: is_correct, POINTS_AWARDED: points_awarded})

        award_points(session_id, player_id, points_awarded, rescore)

    score_flag = f"{ROUNDS}.{round_id}.{QUESTIONS}.{question_id}.{SCORED}"
    answ = f"{ROUNDS}.{round_id}.{QUESTIONS}.{question_id}.{ANSWER}"
    real_answer = get_real_question(session, round_id, question_id)[ANSWER]

    mongo.update("session", session_id, {score_flag: True, answ: real_answer})

    mongo.incr_state(session_id)
    return succeed(data)
Exemplo n.º 3
0
def create_game(data):

    round_names = data[ROUND_NAMES]
    rounds = data[ROUNDS]

    if len(round_names) != len(rounds):
        return fail(
            f"{ROUND_NAMES} is different length ({len(round_names)}) than {ROUNDS} ({len(rounds)})"
        )

    for round_id in rounds:
        if round_names.get(round_id, None) is None:
            return fail(f"missing round name for round with id {round_id})")

    created = mongo.create("game", data)
    if not created:
        return fail("Failed to create game")

    # add game_id to all rounds, and return error if this fails
    game_id = created[ID]
    rupdate = rounds_have_game_id(rounds, game_id)
    if not rupdate:
        return rupdate

    return succeed(created)
Exemplo n.º 4
0
def get_players(session_id, player_id=None):
    """
    args: session_id
    returns:
        [
            {player_name: name, player_id: uuid4},
            {player_name: name, player_id: uuid4},
            ...
        ]
    """
    session = get_session(session_id)
    if session[SUCCESS]:
        session = session[OBJECT]
        players = session.get(PLAYERS, [])

        ret = []
        for player_id in players:
            player = get_player(player_id)
            if player[SUCCESS]:
                player = player[OBJECT]
                ret.append(player)
            else:
                return fail(f"Failed to get player {player_id}")

        resp = succeed(ret)
        resp[MODERATOR] = session[MODERATOR]
        return resp

    return fail("Failed to get session")
Exemplo n.º 5
0
def get_questions(text_filter=None, unused_only=True):
    ret = []
    questions = get_all("question")
    for q in questions:
        if matches(q, text_filter, unused_only, ROUNDS_USED, QUESTION):
            ret.append(q)
    return succeed(ret)
Exemplo n.º 6
0
def update_game(game_id, data, game={}):

    round_names = data.get(ROUND_NAMES, {})
    rounds = data.get(ROUNDS, [])

    if len(round_names) != len(rounds):
        return fail(
            f"{ROUND_NAMES} is different length ({len(round_names)}) than {ROUNDS} ({len(rounds)})"
        )

    for round_id in rounds:
        if round_names.get(round_id, None) is None:
            return fail(f"missing round name for round with id {round_id})")

    prev_rounds = game.get(ROUNDS, [])
    target_rounds = data.get(ROUNDS, [])
    for round_id in prev_rounds:
        if round_id not in target_rounds:
            set_round_and_game_id(round_id, game_id,
                                  False)  # remove game_id from round

    for round_id in target_rounds:
        if round_id not in prev_rounds:
            set_round_and_game_id(round_id, game_id,
                                  True)  # add game_id to round

    if len(round_names) == 0 or len(rounds) == 0:
        data[ROUND_NAMES] = {}
        data[ROUNDS] = {}

    success = mongo.update("game", game_id, data)
    if success:
        game.update(data)
        return succeed(game)
    return fail(f"Failed to update game with data {data}")
Exemplo n.º 7
0
def _start_session(session_id, data, session={}):
    if session[STARTED]:
        return fail(f"Session {session_id} is already started.")

    start = data[STARTED]
    if start:
        startable = game_has_round_and_question(session)
        if not startable[SUCCESS]:
            return startable

        rounds = startable[OBJECT][ROUNDS]
        for i, round_id in enumerate(rounds):
            success = mongo.push("session", session_id, ROUNDS, {ROUND_ID: round_id})
            if not success:
                fail(f"Failed to add round with index {i} to session")

        success = mongo.update("session", session_id, {STARTED: True})
        if not success:
            return fail("Failed tto start session")
        # set current round to 0th round ID in game
        # this will also set first question to 0th question in round
        set_round = set_current_round(session_id, 0)
        if not set_round[SUCCESS]:
            return set_round

        mongo.incr_state(session_id)
        return succeed(session)

    else:
        fail("Cannot start session with data {data}")
Exemplo n.º 8
0
def create_session(data):
    """
    POST /session
    """
    mod = create_player({TEAM_NAME: "mod", REAL_NAME: "mod", ICON: ""})
    if not mod[SUCCESS]:
        return mod

    mod_id = str(mod[OBJECT][ID])

    # create session with this moderator ID
    data[STARTED] = False
    data[MODERATOR] = mod_id
    created = mongo.create("session", data)
    if not created:
        return fail("Failed to create session")

    success = mongo.create("answer", data)
    if not success:
        return fail("Failed to create session")
    # created = created

    # resp = update_player(mod_id, {SESSION_ID: created[ID]})
    # if not resp[SUCCESS]:
    #     return fail(errors=resp[ERRORS])
    mongo.incr_state(created[ID])

    return succeed(created)
Exemplo n.º 9
0
def get_rounds(text_filter=None, unused_only=True):
    ret = []
    rounds = get_all("round")
    for r in rounds:
        if matches(r, text_filter, unused_only, GAMES, ROUND):
            ret.append(r)
    return succeed(ret)
Exemplo n.º 10
0
def game_has_round_and_question(session):
    """
    verify that this session has at least one round and question
    """
    game_id = session.get(GAME_ID, None)
    if not game_id:
        return fail(f"Session {session[ID]} does not have a {GAME}_id")

    game = get_game(game_id)  # probably don't need to test validity because setting game_id illegal is prevented
    if not game[SUCCESS]:
        return game

    game = game[OBJECT]

    rounds = game.get(ROUNDS, [])
    if len(rounds) == 0:
        return fail(f"{GAME}_id {game_id} does not have any {ROUNDS}")

    first_round_id = rounds[0]
    round_obj = get_round(first_round_id)
    if not round_obj[SUCCESS]:
        return round_obj
    round_obj = round_obj[OBJECT]

    questions = round_obj.get(QUESTIONS, [])
    if len(questions) == 0:
        return fail(f"{ROUND}_id {first_round_id} does not have any {QUESTIONS}")

    first_question_id = questions[0]

    return succeed({ROUND_ID: first_round_id, QUESTION_ID: first_question_id, ROUNDS: rounds})
Exemplo n.º 11
0
def set_round_and_game_id(round_id, game_id, present=True):
    """
    set round so that it has or does not have game_id in its games list

    args:
        round_id: ID of target round
        game_id: ID of target game
        present: true if round X is marked as in game Y, false if not
    """
    round = get_round(round_id)
    if not round:
        return fail(
            f"Can't set game_id {game_id} in nonexistent round_id {round_id}")
    round = round[OBJECT]

    games = round.get(GAMES, [])
    if present and game_id not in games:
        if not mongo.push("round", round_id, GAMES, game_id):
            return fail(
                f"Failed to add game_id {game_id} to round_id {round_id}")

    if not present and game_id in games:
        if not mongo.pull("round", round_id, GAMES, game_id):
            return fail(
                f"Failed to remove game_id {game_id} to round_id {round_id}")

    return succeed(round)
Exemplo n.º 12
0
def update_session(session_id, data, session={}):
    success = mongo.update("session", session_id, data)
    if success:
        session.update(data)
        return succeed(session)

    mongo.incr_state(session_id)
    return fail(f"Failed to update session with data {data}")
Exemplo n.º 13
0
def get_session_state(session_id):
    req_state = request.args.get("current", None)
    if req_state is None:
        time.sleep(10)

    sleep_time = .5
    timeout_s = 90

    attempts = 0
    while attempts < (timeout_s / sleep_time):
        state = mongo.get_state(session_id)
        if str(state) != str(req_state):
            return _resp(succeed({"state": state}))
        time.sleep(sleep_time)
        attempts += 1

    return _resp(succeed({"state": req_state}))
Exemplo n.º 14
0
def delete_game(game_id, game={}):
    mongo.delete("game", game_id)

    rounds = game.get(ROUNDS, [])
    rupdate = rounds_do_not_have_game_id(rounds, game_id)
    if not rupdate:
        return rupdate

    return succeed(game)
Exemplo n.º 15
0
def rounds_do_not_have_game_id(rounds, game_id):
    """
    set state of round so that all rounds in list
    do not have game_id in their games list
    """
    for round_id in rounds:
        added = set_round_and_game_id(round_id, game_id, False)
        if not added: return added
    return succeed(rounds)
Exemplo n.º 16
0
def delete_round_from_all_games(round_id):
    """
    don't need to validate round_id because this is called
    inside delete_round where round_id is already validated
    """
    games = get_games()[OBJECT]
    for game in games:
        game_id = game[ID]
        mongo.pull("game", game_id, ROUNDS, round_id)
    return succeed({})
Exemplo n.º 17
0
def update_question(question_id, data, question={}):
    """
    returns
         True/false if update successful
    """
    success = mongo.update("question", question_id, data)
    if success:
        question.update(data)
        return succeed(question)
    return fail(f"Failed to update {QUESTION} with data {data}")
Exemplo n.º 18
0
def remove_question_from_all_rounds(question):
    rounds_used = question.get(ROUNDS_USED, [])
    question_id = question.get(ID)
    for round_id in rounds_used:
        modified_count = mongo.pull("round", round_id, QUESTIONS, question_id)
        if modified_count == 0:
            return fail(
                f"Failed to remove {QUESTION} {question_id} from {ROUND} {round_id}"
            )

    return succeed(question)
Exemplo n.º 19
0
def verify_mod(session_id, player_id):
    # get session to make sure you are the mod
    # TODO: refactor this somehow into helper method to avoid double get
    session = get_session(session_id)
    if not session[SUCCESS]:
        return session

    mod = session[OBJECT][MODERATOR]
    if player_id != mod:
        return fail(f"only mod can start session")
    return succeed({})
Exemplo n.º 20
0
def validate_wagers(data):
    qlen = len(data.get(QUESTIONS, []))
    wlen = len(data.get(WAGERS, []))
    if qlen != wlen:
        error = f"{WAGERS} length ({wlen}) does not equal {QUESTIONS} length ({qlen}) (data: {data}))"
        return fail(error)

    for wager in data.get(WAGERS, []):
        if wager <= 0:
            return fail(f"Wager '{wager}' is not positive int")
    return succeed(data)
Exemplo n.º 21
0
def create_round(data):
    validate = validate_wagers(data)
    if not validate[SUCCESS]:
        return validate

    created = mongo.create("round", data)
    if not created:
        return fail("Failed to create round")

    set_round_in_questions(created, [])  # no original questions, new round
    return succeed(created)
Exemplo n.º 22
0
def legal_wagers_for_player(session_id):
    player_id = request.args.get(PLAYER_ID, None)
    round_id = request.args.get(ROUND_ID, None)
    session = get_session(session_id)[OBJECT]

    try:
        round_id = int(round_id)
    except:
        return _resp(fail("Bad round ID"))

    return _resp(succeed(get_legal_wagers(session, round_id, player_id)))
Exemplo n.º 23
0
def get_answers_unscored(players, answers, caller_player_id):
    ret = []
    for player in players:
        player_id = player[ID]
        p = {TEAM_NAME: player[TEAM_NAME], ICON: player.get(ICON, None)}
        panswers = answers.get(player_id, None)
        p['answered'] = panswers is not None
        if caller_player_id == player_id:
            p[PLAYER_ID] = player_id

        ret.append(p)
    return succeed({SCORED: False, ANSWERS: ret})
Exemplo n.º 24
0
def _set_current_round(session_id, data, session={}):
    round_index = data[ROUND_ID]

    # round must be in game.rounds
    game = get_game(session[GAME_ID])
    if game[SUCCESS]:
        game = game[OBJECT]
        round_ids = game.get(ROUNDS)
        if round_index > len(round_ids):
            return fail(f"{ROUND} with index '{round_index}' is not in {GAME} '{game}'")

        round_id = round_ids[round_index]

        # get round from DB and set in session obj
        r = get_round(round_id)
        if r[SUCCESS]:
            r = r[OBJECT]

            data_to_update = {
                f"{ROUNDS}.{round_index}.{WAGERS}":  r[WAGERS],
                ROUND_ID: round_id,
                CURRENT_ROUND: round_index,
            }

            success = mongo.update("session", session_id, data_to_update)
            if not success:
                fail(f"Failed to add update round with index {i} in session")
            if session[ROUNDS][round_index].get(QUESTIONS, None) is None:
                spot = f"{ROUNDS}.{round_index}.{QUESTIONS}"
                questions = r[QUESTIONS]
                for i, question_id in enumerate(questions):
                    question = get_question(question_id)
                    if not question[SUCCESS]:
                        return question
                    category = question[OBJECT][CATEGORY]

                    success = mongo.push("session", session_id, spot, {CATEGORY: category})
                    if not success:
                        fail(f"Failed to add question with index {i} to round")

            set_first_q = set_current_question(session_id, round_index, 0)
            if not set_first_q[SUCCESS]:
                return set_first_q

            mongo.incr_state(session_id)

            return succeed(r)

            fail(f"Failed to update {SESSION}")

        return fail(f"Failed to get {ROUND} with id {round_id}")

    return fail(f"Failed to get game with id '{session[GAME_ID]}'")
Exemplo n.º 25
0
def update_player(player_id, data, player={}):
    success = mongo.update("player", player_id, data)
    if success:
        player.update(data)

        # dirty the session state, so other clients will see this update
        session_id = player.get(SESSION_ID, None)
        if session_id:
            mongo.incr_state(session_id)

        return succeed(player)
    return fail(f"Failed to update player with data {data}")
Exemplo n.º 26
0
def get_scoreboard(session_id, session={}):
    scoreboard = session.get(SCOREBOARD, None)
    if scoreboard is None:
        scoreboard = {}
        players = get_players(session_id)
        if not players[SUCCESS]:
            return players
        players = players[OBJECT]
        for player in players:
            player_id = player[ID]
            scoreboard[player_id] = 0

    return succeed(scoreboard)
Exemplo n.º 27
0
def update_round(round_id, data, round_obj={}, set_questions=True):
    validate = validate_wagers(data)
    if not validate[SUCCESS]:
        return validate

    orig_questions = round_obj.get(QUESTIONS, [])
    success = mongo.update("round", round_id, data)
    if success:
        if set_questions:
            round_obj[QUESTIONS] = data.get(QUESTIONS, orig_questions)
            set_round_in_questions(round_obj, orig_questions)
        return succeed(round_obj)
    return fail(f"Failed to update round")
Exemplo n.º 28
0
def _set_current_question(session_id, data, session={}):
    """
    validate that question ID in round
    set question.open = True
    set session.current_question = question_id
    return new question_id
    """
    qindex = data[QUESTION_ID]
    rindex = data[ROUND_ID]

    prev = get_question_in_round(session, rindex, qindex)
    if prev[SUCCESS]:
        prev = prev[OBJECT].get(ANSWERS, {})
    else:
        prev = {}

    r = get_current_round(session_id)
    if r[SUCCESS]:
        r = r[OBJECT]
        round_id = r[ROUND_ID]
        round_obj = get_round(round_id)
        if round_obj[SUCCESS]:
            round_obj = round_obj[OBJECT]

        question_ids = round_obj.get(QUESTIONS, [])

        if qindex > len(question_ids):
            return fail(f"{QUESTION} with index {qindex} is not in current round {r}.")

        question_id = question_ids[qindex]

        question = get_question(question_id)
        if not question[SUCCESS]:
            return question
        question = question[OBJECT]

        spot = f"{ROUNDS}.{rindex}.{QUESTIONS}.{qindex}"
        data_to_update = {
            CURRENT_QUESTION: qindex,
            f"{spot}.{QUESTION}": question[QUESTION],
            f"{spot}.{ANSWERS}": prev
        }
        mongo.update("session", session_id, data_to_update)
        # if not success:
        #     return fail(f"Failed to set question for question_id {question_id}")

        mongo.incr_state(session_id)

        return succeed({CURRENT_QUESTION: qindex})

    return fail(f"Failed to get round with ID {session.get(ROUND_ID)}")
Exemplo n.º 29
0
def add_round_to_question(question_id, data, question={}):
    round_id = data[ROUND_ID]
    rounds_used = question.get(ROUNDS_USED, [])
    if round_id in rounds_used:
        raise RuntimeError(
            f"Round {round_id} is already added to question {question_id}")

    success = mongo.push("question", question_id, ROUNDS_USED, round_id)
    if not success:
        return fail(f"Failed to add {ROUND} to {QUESTION}")

    rounds_used.append(round_id)
    question[ROUNDS_USED] = rounds_used
    return succeed(question)
Exemplo n.º 30
0
def remove_round_from_question(question_id, data, question={}):
    round_id = data[ROUND_ID]
    rounds_used = question.get(ROUNDS_USED, [])
    if round_id not in rounds_used:
        raise RuntimeError(
            f"Round {round_id} is not added to question {question_id}")

    success = mongo.pull("question", question_id, ROUNDS_USED, round_id)
    if not success:
        return fail(f"Failed to remove {ROUND} from {QUESTION}")

    rounds_used.remove(round_id)
    question[ROUNDS_USED] = rounds_used
    return succeed(question)