def generate_fake_comp_results(): """ Generates a bunch of fake results for the current competition with realistic-ish results. """ test_users = [ update_or_create_user_for_reddit(name, '') for name in __TEST_USER_NAMES ] for comp_event in get_all_comp_events_for_comp( get_active_competition().id): event_name = comp_event.Event.name if event_name in ('FMC', 'MBLD'): continue thresholds = __AUTO_BLACKLIST_THRESHOLDS.get(event_name) if not thresholds: continue wr_average = thresholds[1] for i, user in enumerate(test_users): results = UserEventResults(comp_event_id=comp_event.id, user_id=user.id, comment='') for solve in [ __build_solve(i, wr_average, event_name, s.id) for s in comp_event.scrambles ]: results.solves.append(solve) process_event_results(results, comp_event, user) save_event_results(results)
def apply_comment(): """ Applies the supplied comment to the desired competition event for this user. """ # Extract JSON solve data, deserialize to dict, and verify that all expected fields are present solve_data = json.loads(request.data) if not all(key in solve_data for key in (COMP_EVENT_ID, COMMENT)): return (ERR_MSG_MISSING_INFO, HTTPStatus.BAD_REQUEST) # Extract all the specific fields out of the solve data dictionary comp_event_id = solve_data[COMP_EVENT_ID] comment = solve_data[COMMENT] # Retrieve the specified competition event comp_event = get_comp_event_by_id(comp_event_id) if not comp_event: return (ERR_MSG_NO_SUCH_EVENT.format(comp_event_id), HTTPStatus.NOT_FOUND) # Verify that the competition event belongs to the active competition. comp = comp_event.Competition if not comp.active: return (ERR_MSG_INACTIVE_COMP, HTTPStatus.BAD_REQUEST) # Retrieve the user's results record for this event user_event_results = get_event_results_for_user(comp_event_id, current_user) if (not user_event_results) or (not user_event_results.solves): return (ERR_MSG_NO_RESULTS.format(comp_event_id), HTTPStatus.NOT_FOUND) # Apply the new comment and save the results user_event_results.comment = comment save_event_results(user_event_results) return timer_page(comp_event_id, gather_info_for_live_refresh=True)
def delete_solve(): """ Deletes the specified solve. """ target_solve_data, err_msg, http_status_code = __retrieve_target_solve( request.data, current_user) if not target_solve_data: return err_msg, http_status_code # Extract the target solve, user's event results, and the associated comp event target_solve, user_event_results, comp_event = target_solve_data # If the results only have one solve (which we're about to delete), # we need to delete the results entirely do_delete_user_results_after_solve = len(user_event_results.solves) == 1 # Delete the target solve delete_user_solve(target_solve) # If no more solves left, just delete the whole results record if do_delete_user_results_after_solve: delete_event_results(user_event_results) # Otherwise process through the user's event results, ensuring PB flags, best single, average, # overall event result, etc are all up-to-date. else: process_event_results(user_event_results, comp_event, current_user) save_event_results(user_event_results) return timer_page(comp_event.id, gather_info_for_live_refresh=True)
def toggle_prev_penalty(): """ Toggles the either the DNF or +2 status of the last solve for the specified user and competition event. """ # Extract JSON solve data, deserialize to dict, and verify that all expected fields are present solve_data = json.loads(request.data) if not all(key in solve_data for key in (COMP_EVENT_ID, )): return (ERR_MSG_MISSING_INFO, HTTPStatus.BAD_REQUEST) # Extract all the specific fields out of the solve data dictionary comp_event_id = solve_data[COMP_EVENT_ID] penalty_to_toggle = solve_data[PENALTY_TO_TOGGLE] # Retrieve the specified competition event comp_event = get_comp_event_by_id(comp_event_id) if not comp_event: return (ERR_MSG_NO_SUCH_EVENT.format(comp_event_id), HTTPStatus.NOT_FOUND) # If this is FMC, this isn't valid if comp_event.Event.name == 'FMC': return (ERR_MSG_NOT_VALID_FOR_FMC, HTTPStatus.BAD_REQUEST) # Verify that the competition event belongs to the active competition. comp = comp_event.Competition if not comp.active: return (ERR_MSG_INACTIVE_COMP, HTTPStatus.BAD_REQUEST) # Retrieve the user's results record for this event user_event_results = get_event_results_for_user(comp_event_id, current_user) if (not user_event_results) or (not user_event_results.solves): return (ERR_MSG_NO_RESULTS.format(comp_event_id), HTTPStatus.NOT_FOUND) # Grab the last completed solve previous_solve = user_event_results.solves[-1] if penalty_to_toggle == PENALTY_DNF: # Toggle DNF # If the solve now has DNF, ensure it doesn't also have +2 previous_solve.is_dnf = not previous_solve.is_dnf if previous_solve.is_dnf: previous_solve.is_plus_two = False else: # Toggle +2 # If the solve now has +2, ensure it doesn't also have DNF previous_solve.is_plus_two = not previous_solve.is_plus_two if previous_solve.is_plus_two: previous_solve.is_dnf = False # Process through the user's event results, ensuring PB flags, best single, average, overall # event result, etc are all up-to-date. process_event_results(user_event_results, comp_event, current_user) save_event_results(user_event_results) return timer_page(comp_event_id, gather_info_for_live_refresh=True)
def reprocess_results_for_user_and_comp_event(username, comp_event_id): """ Reprocesses the event results for the specified user and competition event. """ user = get_user_by_username(username) if not user: print("Oops, that user doesn't exist.") comp_event = get_comp_event_by_id(comp_event_id) if not comp_event: print("Oops, that comp event doesn't exist.") results = get_event_results_for_user(comp_event_id, user) results = process_event_results(results, comp_event, user) save_event_results(results)
def delete_prev_solve(): """ Deletes the last completed solve of the specified competition event for this user. """ # Extract JSON solve data, deserialize to dict, and verify that all expected fields are present solve_data = json.loads(request.data) if not all(key in solve_data for key in (COMP_EVENT_ID, )): return (ERR_MSG_MISSING_INFO, HTTPStatus.BAD_REQUEST) # Extract all the specific fields out of the solve data dictionary comp_event_id = solve_data[COMP_EVENT_ID] # Retrieve the specified competition event comp_event = get_comp_event_by_id(comp_event_id) if not comp_event: return (ERR_MSG_NO_SUCH_EVENT.format(comp_event_id), HTTPStatus.NOT_FOUND) # Verify that the competition event belongs to the active competition. comp = comp_event.Competition if not comp.active: return (ERR_MSG_INACTIVE_COMP, HTTPStatus.BAD_REQUEST) # Retrieve the user's results record for this event user_event_results = get_event_results_for_user(comp_event_id, current_user) if (not user_event_results) or (not user_event_results.solves): return (ERR_MSG_NO_RESULTS.format(comp_event_id), HTTPStatus.NOT_FOUND) # If the results only have one solve (which we're about to delete), we need to delete the # results entirely do_delete_user_results_after_solve = len(user_event_results.solves) == 1 # Grab the last completed solve and delete it previous_solve = user_event_results.solves[-1] delete_user_solve(previous_solve) # If no more solves left, just delete the whole results record if do_delete_user_results_after_solve: delete_event_results(user_event_results) # Otherwise process through the user's event results, ensuring PB flags, best single, average, # overall event result, etc are all up-to-date. else: process_event_results(user_event_results, comp_event, current_user) save_event_results(user_event_results) return timer_page(comp_event_id, gather_info_for_live_refresh=True)
def set_penalty(): """ Applies the specified penalty to the solve """ if not valid_token(request.headers.get('X_CSRF_TOKEN')): return ('', 400) solve_data = json.loads(request.data) target_solve_data, err_msg, http_status_code = __retrieve_target_solve( solve_data, current_user) if not target_solve_data: return err_msg, http_status_code # Extract the target solve, user's event results, and the associated competition event target_solve, user_event_results, comp_event = target_solve_data penalty = solve_data['penalty_to_toggle'] # If this is FMC, this isn't valid if comp_event.Event.name == 'FMC': return (ERR_MSG_NOT_VALID_FOR_FMC, HTTPStatus.BAD_REQUEST) if penalty == PENALTY_CLEAR: # Remove penalties target_solve.is_dnf = False target_solve.is_plus_two = False elif penalty == PENALTY_PLUS_TWO: # Toggle target solve +2, and ensure it's not DNF target_solve.is_plus_two = not target_solve.is_plus_two target_solve.is_dnf = False elif penalty == PENALTY_DNF: # Toggle target solve DNF, and ensure it's not +2 target_solve.is_plus_two = False target_solve.is_dnf = not target_solve.is_dnf process_event_results(user_event_results, comp_event, current_user) save_event_results(user_event_results) return get_event( comp_event.id ) #timer_page(comp_event.id, gather_info_for_live_refresh=True)
def set_time(): """ Applies the specified time to the specified solve. """ if not valid_token(request.headers.get('X_CSRF_TOKEN')): return ('', 400) solve_data = json.loads(request.data) target_solve_data, err_msg, http_status_code = __retrieve_target_solve( solve_data, current_user) if not target_solve_data: return err_msg, http_status_code # Extract the target solve, user's event results, and the associated competition event target_solve, user_event_results, comp_event = target_solve_data # If this is FMC, this isn't valid if comp_event.Event.name == 'FMC': return (ERR_MSG_NOT_VALID_FOR_FMC, HTTPStatus.BAD_REQUEST) # Extract JSON solve data, deserialize to dict, and verify that all expected fields are present # This is slightly redundant given the call to __retrieve_target_solve, but we also need to pull # the centiseconds value which that doesn't do. solve_data = json.loads(request.data) if not all(key in solve_data for key in (SOLVE_ID, COMP_EVENT_ID, CENTISECONDS)): return (ERR_MSG_MISSING_INFO, HTTPStatus.BAD_REQUEST) # Extract all the specific fields out of the solve data dictionary target_solve.time = solve_data[CENTISECONDS] # No penalties on the solve after adjusting time target_solve.is_plus_two = False target_solve.is_dnf = False process_event_results(user_event_results, comp_event, current_user) save_event_results(user_event_results) return get_event( comp_event.id ) #timer_page(comp_event.id, gather_info_for_live_refresh=True)
def clear_penalty(): """ Clears penalties from the specified solve. """ target_solve_data, err_msg, http_status_code = __retrieve_target_solve( request.data, current_user) if not target_solve_data: return err_msg, http_status_code # Extract the target solve, user's event results, and the associated competition event target_solve, user_event_results, comp_event = target_solve_data # If this is FMC, this isn't valid if comp_event.Event.name == 'FMC': return (ERR_MSG_NOT_VALID_FOR_FMC, HTTPStatus.BAD_REQUEST) # Clear penalties target_solve.is_plus_two = False target_solve.is_dnf = False process_event_results(user_event_results, comp_event, current_user) save_event_results(user_event_results) return timer_page(comp_event.id, gather_info_for_live_refresh=True)
def post_solve(): """ Saves a solve. Ensures the user has UserEventResults for this event, associated this solve with those results, and processes the results to make sure all relevant data is up-to-date. """ # Extract JSON solve data, deserialize to dict, and verify that all expected fields are present solve_data = json.loads(request.data) if not all(key in solve_data for key in EXPECTED_FIELDS): return (ERR_MSG_MISSING_INFO, HTTPStatus.BAD_REQUEST) # Extract all the specific fields out of the solve data dictionary is_dnf = solve_data[IS_DNF] is_plus_two = solve_data[IS_PLUS_TWO] scramble_id = solve_data[SCRAMBLE_ID] comp_event_id = solve_data[COMP_EVENT_ID] centiseconds = solve_data[CENTISECONDS] is_inspection_dnf = solve_data.get(IS_INSPECTION_DNF, False) fmc_comment = solve_data.get(FMC_COMMENT, '') # If the solve time isn't positive, don't save the solve. Let the user know that a negative # time isn't allowed. if centiseconds <= 0: return (ERR_MSG_NON_POSITIVE_TIME, HTTPStatus.BAD_REQUEST) # If the submitted solve is for a scramble the user already has a solve for, # don't take any further action to persist a solve, just return. User probably # is user manual time entry and pressed enter twice accidentally in quick succession if get_user_solve_for_scramble_id(current_user.id, scramble_id): return timer_page(comp_event_id, gather_info_for_live_refresh=True) # Retrieve the specified competition event comp_event = get_comp_event_by_id(comp_event_id) if not comp_event: return (ERR_MSG_NO_SUCH_EVENT.format(comp_event_id), HTTPStatus.NOT_FOUND) # Verify that the competition event belongs to the active competition. comp = comp_event.Competition if not comp.active: return (ERR_MSG_INACTIVE_COMP, HTTPStatus.BAD_REQUEST) # Double-check that if the solve is MBLD, the number of attempted cubes is > 1 if comp_event.Event.name == "MBLD": _, num_attempted = get_mbld_successful_and_attempted(centiseconds) if num_attempted < 2: return (ERR_MSG_MBLD_TOO_FEW_ATTEMPTED, HTTPStatus.BAD_REQUEST) # Retrieve the user's results record for this event if they exist, or else create a new record user_event_results = get_event_results_for_user(comp_event_id, current_user) if not user_event_results: user_event_results = UserEventResults(comp_event_id=comp_event_id, user_id=current_user.id, comment='') # Create the record for this solve and associate it with the user's event results solve = UserSolve(time=centiseconds, is_dnf=is_dnf, is_plus_two=is_plus_two, scramble_id=scramble_id, is_inspection_dnf=is_inspection_dnf, fmc_explanation=fmc_comment) user_event_results.solves.append(solve) # Process through the user's event results, ensuring PB flags, best single, average, overall # event result, etc are all up-to-date. process_event_results(user_event_results, comp_event, current_user) save_event_results(user_event_results) return timer_page(comp_event_id, gather_info_for_live_refresh=True)