Exemplo n.º 1
0
def __render_versus_page_for_users(user1, user2, errors):
    """ Renders and returns a user versus page for the specified two users. """

    # Get a map of event ID to event name, to facilitate rendering the template.
    # Sort it by the global sort order so the event records table has the same ordering as everywhere else.
    all_sorted_events = sort_events_by_global_sort_order(get_all_events())
    event_id_name_map = {e.id: e.name for e in all_sorted_events}

    # Get site rankings info for both users.
    # Get users' medal counts, number of total solves, number of competitions participated in
    rankings1, user1_stats = __get_versus_page_info_for_user(user1)
    rankings2, user2_stats = __get_versus_page_info_for_user(user2)

    # Remove any events which neither user has participated in.
    __remove_events_not_participated_in(event_id_name_map, rankings1,
                                        rankings2)

    return render_template("user/versus.html",
                           username1=user1.username,
                           username2=user2.username,
                           rankings1=rankings1,
                           rankings2=rankings2,
                           event_id_name_map=event_id_name_map,
                           user1_stats=user1_stats,
                           user2_stats=user2_stats,
                           errors=errors)
Exemplo n.º 2
0
def update_pbs():

    all_users = get_all_users()
    user_count = len(all_users)

    all_events = get_all_events()

    for i, user in enumerate(all_users):
        print("Calculating latest PBs for {} ({}/{})".format(user.username, i + 1, user_count))
        for event in all_events:
            calculate_latest_user_pbs_for_event(user.id, event.id)
Exemplo n.º 3
0
def recalculate_pbs():
    """ Works through every user, every event type, and re-calculates PB averages and singles
    and sets appropriate flags on UserEventResults. """

    all_users = get_all_users()
    user_count = len(all_users)

    all_events = get_all_events()

    for i, user in enumerate(all_users):
        print("Recalculating PBs for {} ({}/{})".format(user.username, i + 1, user_count))
        for event in all_events:
            recalculate_user_pbs_for_event(user.id, event.id)
Exemplo n.º 4
0
def check_scramble_pool() -> None:
    """ A periodic task to check the pre-generated pool of scrambles for all events. If the pool is too low for any
    event, queue up a task to generate more scrambles for those events. """

    for event in get_all_events():

        # Don't pre-generate COLL scrambles. The fact we need a specific COLL each week, and that rotates weekly,
        # makes this more difficult than it needs to be. We'll just generate them on the fly during competition
        # generation, since it's fast anyway.
        if event.name == EVENT_COLL.name:
            continue

        # Determine if the scramble pool is too low for this event. If so, queue up a task to generate enough scrambles
        # for this event to bring the pool up to (2 * number of solves) for that event.
        num_missing = (2 * event.totalSolves) - len(event.scramble_pool)
        if num_missing > 0:
            top_off_scramble_pool(
                ScramblePoolTopOffInfo(event.id, event.name, num_missing))
Exemplo n.º 5
0
def events_settings():
    """ A route for editing a user's preferred events. """

    if not current_user.is_authenticated:
        return redirect(url_for('index'))

    # Load hidden event IDs out of comma-delimited string and into a list of ints
    hidden_event_setting = get_setting_for_user(current_user.id,
                                                SettingCode.HIDDEN_EVENTS)
    if hidden_event_setting:
        hidden_event_ids = [int(s) for s in hidden_event_setting.split(',')]
    else:
        hidden_event_ids = list()

    return render_template("user/settings/events_settings.html",
                           is_mobile=request.MOBILE,
                           hidden_event_ids=hidden_event_ids,
                           events=sort_events_by_global_sort_order(
                               get_all_events()))
Exemplo n.º 6
0
def __get_user_site_rankings(user_id):
    """ Retrieves a user site rankings record by user id. """

    # Get a map of event ID to event name, to facilitate rendering the template.
    # Sort it by the global sort order so the event records table has the same ordering as everywhere else.
    all_sorted_events = sort_events_by_global_sort_order(get_all_events())
    event_id_name_map = {e.id: e.name for e in all_sorted_events}

    site_rankings = dict()

    # See if the user has any recorded site rankings. If they do, extract the data as a dict so we
    # can build their site ranking table
    site_rankings_record = get_site_rankings_for_user(user_id)
    if site_rankings_record:
        # TODO -- get the raw site rankings record back, sort those, then convert to dict for front-end
        site_rankings = site_rankings_record.get_site_rankings_and_pbs()

    # Iterate over all events, making sure there's an entry in the user site rankings for everything,
    # even events they haven't participated in, in case the other user has done that event.
    for event_id in event_id_name_map.keys():
        if event_id not in site_rankings.keys():
            site_rankings[event_id] = EVENT_NOT_PARTICIPATED

    return site_rankings
Exemplo n.º 7
0
def profile(username):
    """ A route for showing a user's profile. """

    user = get_user_by_username_case_insensitive(username)
    if not user:
        no_user_msg = MSG_NO_SUCH_USER.format(username)
        return render_template('error.html', error_message=no_user_msg), HTTPStatus.NOT_FOUND

    # Pull username from the user itself, so we know it's cased correctly for comparisons and
    # queries later
    username = user.username

    # Determine whether we're showing blacklisted results
    include_blacklisted = __should_show_blacklisted_results(username, current_user.is_admin)

    # Get the user's competition history
    history = get_user_competition_history(user, include_blacklisted=include_blacklisted)

    # Accumulate a count of medals this user has for podiuming
    gold_count, silver_count, bronze_count = get_user_medals_count(user.id)

    # Get some other interesting stats
    solve_count = get_user_completed_solves_count(user.id)
    comps_count = get_user_participated_competitions_count(user.id)

    # Get a dictionary of event ID to names, to facilitate rendering some stuff in the template
    event_id_name_map = {e.id: e.name for e in get_all_events()}

    # See if the user has any recorded site rankings. If they do, extract the data as a dict so we
    # can build their site ranking table
    site_rankings_record = get_site_rankings_for_user(user.id)
    if site_rankings_record:
        # TODO -- get the raw site rankings record back, sort those, then convert to dict for front-end
        site_rankings = site_rankings_record.get_site_rankings_and_pbs()

        # Get sum of ranks
        sor_all     = site_rankings_record.get_combined_sum_of_ranks()
        sor_wca     = site_rankings_record.get_WCA_sum_of_ranks()
        sor_non_wca = site_rankings_record.get_non_WCA_sum_of_ranks()

        # Get Kinchranks
        kinch_all     = site_rankings_record.get_combined_kinchrank()
        kinch_wca     = site_rankings_record.get_WCA_kinchrank()
        kinch_non_wca = site_rankings_record.get_non_WCA_kinchrank()

        # Timestamp of the last time site rankings were run, formatted like "2019 Jan 11"
        rankings_ts = site_rankings_record.timestamp.strftime(TIMESTAMP_FORMAT)

    else:
        rankings_ts   = None
        site_rankings = None
        sor_all       = None
        sor_wca       = None
        sor_non_wca   = None
        kinch_all     = None
        kinch_wca     = None
        kinch_non_wca = None

    # Set a flag indicating if this page view is for a user viewing another user's page
    viewing_self = user.username == current_user.username

    # Check if user has set WCA ID to be public
    show_wca_id = get_boolean_setting_for_user(user.id, SettingCode.SHOW_WCA_ID)

    # Set flags to indicate if user is missing a Reddit/WCA profile association
    missing_wca_association = viewing_self and username == user.reddit_id and not user.wca_id
    missing_reddit_association = viewing_self and username == user.wca_id and not user.reddit_id

    return render_template("user/profile.html", user=user, solve_count=solve_count,
                           comp_count=comps_count, history=history, rankings=site_rankings,
                           event_id_name_map=event_id_name_map, rankings_ts=rankings_ts,
                           is_admin_viewing=current_user.is_admin, sor_all=sor_all,
                           sor_wca=sor_wca, sor_non_wca=sor_non_wca, gold_count=gold_count,
                           silver_count=silver_count, bronze_count=bronze_count,
                           viewing_self=viewing_self, kinch_all=kinch_all, kinch_wca=kinch_wca,
                           kinch_non_wca=kinch_non_wca, show_wca_id=show_wca_id,
                           missing_wca_association=missing_wca_association,
                           missing_reddit_association=missing_reddit_association)
Exemplo n.º 8
0
def calculate_user_site_rankings() -> None:
    """ Calculate user event site rankings based on PBs. """

    all_events = [e for e in get_all_events() if e.name != "COLL"]
    wca_event_ids = set(e.id for e in get_all_WCA_events())

    # These are of the form dict[Event, [ordered list of PersonalBestRecords]]
    events_pb_singles = dict()
    events_pb_averages = dict()

    # These are of the form dict[Event, dict[user ID, index in ordered PB records list]]
    events_pb_singles_ix = dict()
    events_pb_averages_ix = dict()

    # These are of the form dict[Event, int]
    events_singles_len = dict()
    events_averages_len = dict()

    # All user IDs seen, so we only iterate over users that have participated in something
    all_user_ids = set()

    t0 = default_timer()

    for event in all_events:

        # Retrieve the the ordered list of PersonalBestRecords for singles for this event
        ordered_pb_singles = get_ordered_pb_singles_for_event(event.id)

        # If nobody at all has competed in this event, just move on to the next
        if not ordered_pb_singles:
            continue

        events_pb_singles[event] = ordered_pb_singles
        events_singles_len[event] = len(ordered_pb_singles)

        # Iterate the ordered PB singles, recording which users we've seen, and also building a map of the user ID to
        # their index in the ordered PB singles list, so we can retrieve the specific PersonalBestRecord for a user
        # directly by their index in this list rather than having to iterate it again.
        user_single_ix_map = dict()
        for i, pb_record in enumerate(ordered_pb_singles):
            user_single_ix_map[pb_record.user_id] = i
            all_user_ids.add(pb_record.user_id)

        events_pb_singles_ix[event] = user_single_ix_map

        # Retrieve the the ordered list of PersonalBestRecords for averages for this event
        ordered_pb_averages = get_ordered_pb_averages_for_event(event.id)
        events_pb_averages[event] = ordered_pb_averages
        events_averages_len[event] = len(ordered_pb_averages)

        # Iterate the ordered PB averages, recording which users we've seen, and also building a map of the user ID to
        # their index in the ordered PB averages list, so we can retrieve the specific PersonalBestRecord for a user
        # directly by their index in this list rather than having to iterate it again.
        user_average_ix_map = dict()
        for i, pb_record in enumerate(ordered_pb_averages):
            user_average_ix_map[pb_record.user_id] = i
            all_user_ids.add(pb_record.user_id)

        events_pb_averages_ix[event] = user_average_ix_map

    # We'll update the users' site rankings in bulk.
    site_rankings = list()
    bulk_update_count = 0
    bulk_update_limit = 250

    # Iterate through all users to determine their site rankings and PBs
    for user_id in all_user_ids:
        rankings = _calculate_site_rankings_for_user(
            user_id, events_pb_singles, events_pb_singles_ix,
            events_singles_len, events_pb_averages, events_pb_averages_ix,
            events_averages_len, wca_event_ids, all_events)

        site_rankings.append(rankings)
        bulk_update_count += 1

        # Save/update site rankings in bulk
        if bulk_update_count == bulk_update_limit:
            bulk_update_site_rankings(site_rankings)
            site_rankings = list()
            bulk_update_count = 0

    # If there's any left that didn't get updated in bulk, do that now.
    if site_rankings:
        bulk_update_site_rankings(site_rankings)

    t1 = default_timer()
    print(
        f"[RANKINGS] {t1 - t0}s elapsed to calculate site rankings for {len(all_user_ids)} users."
    )