Source code for bauiv1lib.league.rankwindow

# Released under the MIT License. See LICENSE for details.
#
"""UI related to league rank."""
# pylint: disable=too-many-lines

from __future__ import annotations

import copy
import logging
from typing import TYPE_CHECKING, override

from bauiv1lib.popup import PopupMenu
import bauiv1 as bui

if TYPE_CHECKING:
    from typing import Any


[docs] class LeagueRankWindow(bui.MainWindow): """Window for showing league rank.""" def __init__( self, transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, ): # pylint: disable=too-many-statements plus = bui.app.plus assert plus is not None bui.set_analytics_screen('League Rank Window') self._league_rank_data: dict[str, Any] | None = None self._power_ranking_achievements_button: bui.Widget | None = None self._up_to_date_bonus_button: bui.Widget | None = None self._power_ranking_trophies_button: bui.Widget | None = None self._league_title_text: bui.Widget | None = None self._league_text: bui.Widget | None = None self._league_number_text: bui.Widget | None = None self._your_power_ranking_text: bui.Widget | None = None self._loading_spinner: bui.Widget | None = None self._season_ends_text: bui.Widget | None = None self._power_ranking_rank_text: bui.Widget | None = None self._to_ranked_text: bui.Widget | None = None self._trophy_counts_reset_text: bui.Widget | None = None assert bui.app.classic is not None uiscale = bui.app.ui_v1.uiscale self._width = 1500 if uiscale is bui.UIScale.SMALL else 1120 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 self._height = ( 1000 if uiscale is bui.UIScale.SMALL else 710 if uiscale is bui.UIScale.MEDIUM else 800 ) self._r = 'coopSelectWindow' self._rdict = bui.app.lang.get_resource(self._r) # top_extra = 20 if uiscale is bui.UIScale.SMALL else 0 # self._xoffs = 80.0 if uiscale is bui.UIScale.SMALL else 0 self._xoffs = 40 self._league_url_arg = '' self._is_current_season = False self._can_do_more_button = True # Do some fancy math to fill all available screen area up to the # size of our backing container. This lets us fit to the exact # screen shape at small ui scale. screensize = bui.get_virtual_screen_size() scale = ( 1.3 if uiscale is bui.UIScale.SMALL else 0.93 if uiscale is bui.UIScale.MEDIUM else 0.8 ) # Calc screen size in our local container space and clamp to a # bit smaller than our container size. target_width = min(self._width - 130, screensize[0] / scale) target_height = min(self._height - 130, screensize[1] / scale) # To get top/left coords, go to the center of our window and # offset by half the width/height of our target area. yoffs = 0.5 * self._height + 0.5 * target_height + 30.0 self._scroll_width = target_width self._scroll_height = target_height - 35 scroll_bottom = yoffs - 80 - self._scroll_height super().__init__( root_widget=bui.containerwidget( size=(self._width, self._height), stack_offset=( (0, 0) if uiscale is bui.UIScale.SMALL else (0, 10) if uiscale is bui.UIScale.MEDIUM else (0, 0) ), scale=scale, toolbar_visibility=( 'menu_minimal' if uiscale is bui.UIScale.SMALL else 'menu_full' ), ), transition=transition, origin_widget=origin_widget, # We're affected by screen size only at small ui-scale. refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL, ) if uiscale is bui.UIScale.SMALL: self._back_button = bui.get_special_widget('back_button') bui.containerwidget( edit=self._root_widget, on_cancel_call=self.main_window_back ) else: self._back_button = bui.buttonwidget( parent=self._root_widget, position=(75 + x_inset, yoffs - 60), size=(60, 55), scale=1.2, autoselect=True, label=bui.charstr(bui.SpecialChar.BACK), button_type='backSmall', on_activate_call=self.main_window_back, ) bui.containerwidget( edit=self._root_widget, cancel_button=self._back_button, selected_child=self._back_button, ) self._title_text = bui.textwidget( parent=self._root_widget, position=( self._width * 0.5, yoffs - (55 if uiscale is bui.UIScale.SMALL else 30), ), size=(0, 0), text=bui.Lstr( resource='league.leagueRankText', fallback_resource='coopSelectWindow.powerRankingText', ), h_align='center', color=bui.app.ui_v1.title_color, scale=1.2 if uiscale is bui.UIScale.SMALL else 1.3, maxwidth=600, v_align='center', ) self._scrollwidget = bui.scrollwidget( parent=self._root_widget, highlight=False, size=(self._scroll_width, self._scroll_height), position=( self._width * 0.5 - self._scroll_width * 0.5, scroll_bottom, ), center_small_content=True, center_small_content_horizontally=True, border_opacity=0.4, ) bui.widget(edit=self._scrollwidget, autoselect=True) bui.containerwidget(edit=self._scrollwidget, claims_left_right=True) self._last_power_ranking_query_time: float | None = None self._doing_power_ranking_query = False self._subcontainer: bui.Widget | None = None self._subcontainerwidth = 1024 self._subcontainerheight = 483 self._power_ranking_score_widgets: list[bui.Widget] = [] self._season_popup_menu: PopupMenu | None = None self._requested_season: str | None = None self._season: str | None = None # Take note of our account state; we'll refresh later if this # changes. self._account_state = plus.get_v1_account_state() self._refresh() self._restore_state() # If we've got cached power-ranking data already, display it. assert bui.app.classic is not None info = bui.app.classic.accounts.get_cached_league_rank_data() if info is not None: self._update_for_league_rank_data(info) self._update_timer = bui.AppTimer( 1.0, bui.WeakCall(self._update), repeat=True ) self._update(show=info is None)
[docs] @override def get_main_window_state(self) -> bui.MainWindowState: # Support recreating our window for back/refresh purposes. cls = type(self) return bui.BasicMainWindowState( create_call=lambda transition, origin_widget: cls( transition=transition, origin_widget=origin_widget ) )
[docs] @override def on_main_window_close(self) -> None: self._save_state()
def _on_achievements_press(self) -> None: from bauiv1lib.achievements import AchievementsWindow # Only allow this for all-time or the current season (we # currently don't keep specific achievement data for old # seasons). if self._season == 'a' or self._is_current_season: prab = self._power_ranking_achievements_button assert prab is not None self.main_window_replace(AchievementsWindow(origin_widget=prab)) else: bui.screenmessage( bui.Lstr( resource='achievementsUnavailableForOldSeasonsText', fallback_resource='unavailableText', ), color=(1, 0, 0), ) bui.getsound('error').play() def _on_activity_mult_press(self) -> None: from bauiv1lib import confirm plus = bui.app.plus assert plus is not None txt = bui.Lstr( resource=( 'coopSelectWindow.activenessAllTimeInfoText' if self._season == 'a' else 'coopSelectWindow.activenessInfoText' ), subs=[ ( '${MAX}', str( plus.get_v1_account_misc_read_val('activenessMax', 1.0) ), ) ], ) confirm.ConfirmWindow( txt, cancel_button=False, width=460, height=150, origin_widget=self._activity_mult_button, ) def _on_up_to_date_bonus_press(self) -> None: from bauiv1lib import confirm plus = bui.app.plus assert plus is not None txt = bui.Lstr( resource='league.upToDateBonusDescriptionText', subs=[ ( '${PERCENT}', str( plus.get_v1_account_misc_read_val( 'proPowerRankingBoost', 10 ) ), ), ], ) confirm.ConfirmWindow( txt, cancel_button=False, width=460, height=130, origin_widget=self._up_to_date_bonus_button, ) def _on_trophies_press(self) -> None: from bauiv1lib.trophies import TrophiesWindow info = self._league_rank_data if info is not None: prtb = self._power_ranking_trophies_button assert prtb is not None TrophiesWindow( position=prtb.get_screen_space_center(), data=info, ) else: bui.getsound('error').play() def _on_power_ranking_query_response( self, data: dict[str, Any] | None ) -> None: self._doing_power_ranking_query = False # Important: *only* cache this if we requested the current # season. if data is not None and data.get('s', None) is None: assert bui.app.classic is not None bui.app.classic.accounts.cache_league_rank_data(data) # Always store a copy locally though (even for other seasons). self._league_rank_data = copy.deepcopy(data) self._update_for_league_rank_data(data) def _restore_state(self) -> None: pass def _update(self, show: bool = False) -> None: plus = bui.app.plus assert plus is not None cur_time = bui.apptime() # If our account state has changed, refresh our UI. account_state = plus.get_v1_account_state() if account_state != self._account_state: self._account_state = account_state self._save_state() self._refresh() # And power ranking too. if not self._doing_power_ranking_query: self._last_power_ranking_query_time = None # Send off a new power-ranking query if its been long enough or # our requested season has changed or whatnot. if not self._doing_power_ranking_query and ( self._last_power_ranking_query_time is None or cur_time - self._last_power_ranking_query_time > 30.0 ): try: if show: bui.textwidget(edit=self._league_title_text, text='') bui.textwidget(edit=self._league_text, text='') bui.textwidget(edit=self._league_number_text, text='') bui.textwidget(edit=self._your_power_ranking_text, text='') bui.spinnerwidget(edit=self._loading_spinner, visible=True) bui.textwidget(edit=self._to_ranked_text, text='') bui.textwidget(edit=self._power_ranking_rank_text, text='') bui.textwidget(edit=self._season_ends_text, text='') bui.textwidget(edit=self._trophy_counts_reset_text, text='') except Exception: logging.exception('Error showing updated rank info.') self._last_power_ranking_query_time = cur_time self._doing_power_ranking_query = True plus.power_ranking_query( season=self._requested_season, callback=bui.WeakCall(self._on_power_ranking_query_response), ) def _refresh(self) -> None: # pylint: disable=too-many-statements plus = bui.app.plus assert plus is not None # (Re)create the sub-container if need be. if self._subcontainer is not None: self._subcontainer.delete() self._subcontainer = bui.containerwidget( parent=self._scrollwidget, size=(self._subcontainerwidth, self._subcontainerheight), background=False, ) w_parent = self._subcontainer v = self._subcontainerheight - 20 v -= 0 h2 = 80 v2 = v - 60 worth_color = (0.6, 0.6, 0.65) tally_color = (0.5, 0.6, 0.8) spc = 43 h_offs_tally = 150 tally_maxwidth = 120 v2 -= 70 bui.textwidget( parent=w_parent, position=(self._xoffs + h2 - 60, v2 + 106), size=(0, 0), flatness=1.0, shadow=0.0, text=bui.Lstr(resource='coopSelectWindow.pointsText'), h_align='left', v_align='center', scale=0.8, color=(1, 1, 1, 0.3), maxwidth=200, ) self._power_ranking_achievements_button = bui.buttonwidget( parent=w_parent, position=(self._xoffs + h2 - 60, v2 + 10), size=(200, 80), icon=bui.gettexture('achievementsIcon'), autoselect=True, on_activate_call=bui.WeakCall(self._on_achievements_press), up_widget=self._back_button, left_widget=self._back_button, color=(0.5, 0.5, 0.6), textcolor=(0.7, 0.7, 0.8), label='', ) self._power_ranking_achievement_total_text = bui.textwidget( parent=w_parent, position=(self._xoffs + h2 + h_offs_tally, v2 + 45), size=(0, 0), flatness=1.0, shadow=0.0, text='-', h_align='left', v_align='center', scale=0.8, color=tally_color, maxwidth=tally_maxwidth, ) v2 -= 80 self._power_ranking_trophies_button = bui.buttonwidget( parent=w_parent, position=(self._xoffs + h2 - 60, v2 + 10), size=(200, 80), icon=bui.gettexture('medalSilver'), autoselect=True, on_activate_call=bui.WeakCall(self._on_trophies_press), left_widget=self._back_button, color=(0.5, 0.5, 0.6), textcolor=(0.7, 0.7, 0.8), label='', ) self._power_ranking_trophies_total_text = bui.textwidget( parent=w_parent, position=(self._xoffs + h2 + h_offs_tally, v2 + 45), size=(0, 0), flatness=1.0, shadow=0.0, text='-', h_align='left', v_align='center', scale=0.8, color=tally_color, maxwidth=tally_maxwidth, ) v2 -= 100 bui.textwidget( parent=w_parent, position=(self._xoffs + h2 - 60, v2 + 86), size=(0, 0), flatness=1.0, shadow=0.0, text=bui.Lstr(resource='coopSelectWindow.multipliersText'), h_align='left', v_align='center', scale=0.8, color=(1, 1, 1, 0.3), maxwidth=200, ) self._activity_mult_button: bui.Widget | None if plus.get_v1_account_misc_read_val('act', False): self._activity_mult_button = bui.buttonwidget( parent=w_parent, position=(self._xoffs + h2 - 60, v2 + 10), size=(200, 60), icon=bui.gettexture('heart'), icon_color=(0.5, 0, 0.5), label=bui.Lstr(resource='coopSelectWindow.activityText'), autoselect=True, on_activate_call=bui.WeakCall(self._on_activity_mult_press), left_widget=self._back_button, color=(0.5, 0.5, 0.6), textcolor=(0.7, 0.7, 0.8), ) self._activity_mult_text = bui.textwidget( parent=w_parent, position=(self._xoffs + h2 + h_offs_tally, v2 + 40), size=(0, 0), flatness=1.0, shadow=0.0, text='-', h_align='left', v_align='center', scale=0.8, color=tally_color, maxwidth=tally_maxwidth, ) v2 -= 65 else: self._activity_mult_button = None self._up_to_date_bonus_button = bui.buttonwidget( parent=w_parent, position=(self._xoffs + h2 - 60, v2 + 10), size=(200, 60), icon=bui.gettexture('logo'), icon_color=(0.3, 0, 0.3), label=bui.Lstr(resource='league.upToDateBonusText'), autoselect=True, on_activate_call=bui.WeakCall(self._on_up_to_date_bonus_press), left_widget=self._back_button, color=(0.5, 0.5, 0.6), textcolor=(0.7, 0.7, 0.8), ) self._up_to_date_bonus_text = bui.textwidget( parent=w_parent, position=(self._xoffs + h2 + h_offs_tally, v2 + 40), size=(0, 0), flatness=1.0, shadow=0.0, text='-', h_align='left', v_align='center', scale=0.8, color=tally_color, maxwidth=tally_maxwidth, ) v2 -= 30 v2 -= spc bui.textwidget( parent=w_parent, position=(self._xoffs + h2 + h_offs_tally - 10 - 40, v2 + 35), size=(0, 0), flatness=1.0, shadow=0.0, text=bui.Lstr(resource='finalScoreText'), h_align='right', v_align='center', scale=0.9, color=worth_color, maxwidth=150, ) self._power_ranking_total_text = bui.textwidget( parent=w_parent, position=(self._xoffs + h2 + h_offs_tally - 40, v2 + 35), size=(0, 0), flatness=1.0, shadow=0.0, text='-', h_align='left', v_align='center', scale=0.9, color=tally_color, maxwidth=tally_maxwidth, ) self._season_show_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 390 - 15, v - 20), size=(0, 0), color=(0.6, 0.6, 0.7), maxwidth=200, text=bui.Lstr(resource='showText'), h_align='right', v_align='center', scale=0.8, shadow=0, flatness=1.0, ) self._league_title_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 470, v - 97), size=(0, 0), color=(0.6, 0.6, 0.7), maxwidth=230, text='', h_align='center', v_align='center', scale=0.9, shadow=0, flatness=1.0, ) self._league_text_scale = 1.8 self._league_text_maxwidth = 210 self._league_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 470, v - 140), size=(0, 0), color=(1, 1, 1), maxwidth=self._league_text_maxwidth, text='-', h_align='center', v_align='center', scale=self._league_text_scale, shadow=1.0, flatness=1.0, ) self._league_number_base_pos = (470, v - 140) self._league_number_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 470, v - 140), size=(0, 0), color=(1, 1, 1), maxwidth=100, text='', h_align='left', v_align='center', scale=0.8, shadow=1.0, flatness=1.0, ) self._loading_spinner = bui.spinnerwidget( parent=w_parent, position=( self._subcontainerwidth * 0.5, self._subcontainerheight * 0.5, ), style='bomb', size=64, ) self._your_power_ranking_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 470, v - 142 - 70), size=(0, 0), color=(0.6, 0.6, 0.7), maxwidth=230, text='', h_align='center', v_align='center', scale=0.9, shadow=0, flatness=1.0, ) self._to_ranked_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 470, v - 250 - 70), size=(0, 0), color=(0.6, 0.6, 0.7), maxwidth=230, text='', h_align='center', v_align='center', scale=0.8, shadow=0, flatness=1.0, ) self._power_ranking_rank_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 473, v - 210 - 70), size=(0, 0), big=False, text='-', h_align='center', v_align='center', scale=1.0, ) self._season_ends_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 470, v - 380), size=(0, 0), color=(0.6, 0.6, 0.6), maxwidth=230, text='', h_align='center', v_align='center', scale=0.9, shadow=0, flatness=1.0, ) self._trophy_counts_reset_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 470, v - 410), size=(0, 0), color=(0.5, 0.5, 0.5), maxwidth=230, text='Trophy counts will reset next season.', h_align='center', v_align='center', scale=0.8, shadow=0, flatness=1.0, ) self._power_ranking_score_widgets = [] self._power_ranking_score_v = v - 56 h = 707 v -= 451 self._see_more_button = bui.buttonwidget( parent=w_parent, label=self._rdict.seeMoreText, position=(self._xoffs + h, v), color=(0.5, 0.5, 0.6), textcolor=(0.7, 0.7, 0.8), size=(230, 60), autoselect=True, on_activate_call=bui.WeakCall(self._on_more_press), ) def _on_more_press(self) -> None: plus = bui.app.plus assert plus is not None our_login_id = plus.get_v1_account_public_login_id() if not self._can_do_more_button or our_login_id is None: bui.getsound('error').play() bui.screenmessage( bui.Lstr(resource='unavailableText'), color=(1, 0, 0) ) return if self._season is None: season_str = '' else: season_str = '&season=' + ( 'all_time' if self._season == 'a' else self._season ) if self._league_url_arg != '': league_str = '&league=' + self._league_url_arg else: league_str = '' bui.open_url( plus.get_master_server_address() + '/highscores?list=powerRankings&v=2' + league_str + season_str + '&player=' + our_login_id ) def _update_for_league_rank_data(self, data: dict[str, Any] | None) -> None: # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals if not self._root_widget: return plus = bui.app.plus uiscale = bui.app.ui_v1.uiscale assert plus is not None assert bui.app.classic is not None accounts = bui.app.classic.accounts in_top = data is not None and data['rank'] is not None eq_text = self._rdict.powerRankingPointsEqualsText pts_txt = self._rdict.powerRankingPointsText num_text = bui.Lstr(resource='numberText').evaluate() do_percent = False finished_season_unranked = False self._can_do_more_button = True extra_text = '' if plus.get_v1_account_state() != 'signed_in': status_text = ( '(' + bui.Lstr(resource='notSignedInText').evaluate() + ')' ) elif in_top: assert data is not None status_text = num_text.replace('${NUMBER}', str(data['rank'])) elif data is not None: try: # Handle old seasons where we didn't wind up ranked at # the end. if not data['scores']: status_text = ( self._rdict.powerRankingFinishedSeasonUnrankedText ) extra_text = '' finished_season_unranked = True self._can_do_more_button = False else: our_points = accounts.get_league_rank_points(data) progress = float(our_points) / max(1, data['scores'][-1][1]) status_text = str(int(progress * 100.0)) + '%' extra_text = ( '\n' + self._rdict.powerRankingPointsToRankedText.replace( '${CURRENT}', str(our_points) ).replace('${REMAINING}', str(data['scores'][-1][1])) ) do_percent = True except Exception: logging.exception('Error updating power ranking.') status_text = self._rdict.powerRankingNotInTopText.replace( '${NUMBER}', str(data['listSize']) ) extra_text = '' else: status_text = '-' self._season = data['s'] if data is not None else None v = self._subcontainerheight - 20 popup_was_selected = False if self._season_popup_menu is not None: btn = self._season_popup_menu.get_button() assert self._subcontainer if self._subcontainer.get_selected_child() == btn: popup_was_selected = True btn.delete() season_choices = [] season_choices_display = [] did_first = False self._is_current_season = False if data is not None: # Build our list of seasons we have available. for ssn in data['sl']: season_choices.append(ssn) if ssn != 'a' and not did_first: season_choices_display.append( bui.Lstr( resource='league.currentSeasonText', subs=[('${NUMBER}', ssn)], ) ) did_first = True # If we either did not specify a season or specified # the first, we're looking at the current. if self._season in [ssn, None]: self._is_current_season = True elif ssn == 'a': season_choices_display.append( bui.Lstr(resource='league.allTimeText') ) else: season_choices_display.append( bui.Lstr( resource='league.seasonText', subs=[('${NUMBER}', ssn)], ) ) assert self._subcontainer self._season_popup_menu = PopupMenu( parent=self._subcontainer, position=(self._xoffs + 390, v - 45), width=150, button_size=(200, 50), choices=season_choices, on_value_change_call=bui.WeakCall(self._on_season_change), choices_display=season_choices_display, current_choice=self._season, ) if popup_was_selected: bui.containerwidget( edit=self._subcontainer, selected_child=self._season_popup_menu.get_button(), ) bui.widget(edit=self._see_more_button, show_buffer_bottom=100) bui.widget( edit=self._season_popup_menu.get_button(), up_widget=self._back_button, ) if uiscale is not bui.UIScale.SMALL: bui.widget( edit=self._back_button, down_widget=self._power_ranking_achievements_button, right_widget=self._season_popup_menu.get_button(), ) bui.textwidget( edit=self._league_title_text, text=( '' if self._season == 'a' else bui.Lstr(resource='league.leagueText') ), ) if data is None: lname = '' lnum = '' lcolor = (1, 1, 1) self._league_url_arg = '' elif self._season == 'a': lname = bui.Lstr(resource='league.allTimeText').evaluate() lnum = '' lcolor = (1, 1, 1) self._league_url_arg = '' else: lnum = ('[' + str(data['l']['i']) + ']') if data['l']['i2'] else '' lname = bui.Lstr( translate=('leagueNames', data['l']['n']) ).evaluate() lcolor = data['l']['c'] self._league_url_arg = ( data['l']['n'] + '_' + str(data['l']['i']) ).lower() to_end_string: bui.Lstr | str if data is None or self._season == 'a' or data['se'] is None: to_end_string = '' show_season_end = False else: show_season_end = True days_to_end = data['se'][0] minutes_to_end = data['se'][1] if days_to_end > 0: to_end_string = bui.Lstr( resource='league.seasonEndsDaysText', subs=[('${NUMBER}', str(days_to_end))], ) elif days_to_end == 0 and minutes_to_end >= 60: to_end_string = bui.Lstr( resource='league.seasonEndsHoursText', subs=[('${NUMBER}', str(minutes_to_end // 60))], ) elif days_to_end == 0 and minutes_to_end >= 0: to_end_string = bui.Lstr( resource='league.seasonEndsMinutesText', subs=[('${NUMBER}', str(minutes_to_end))], ) else: to_end_string = bui.Lstr( resource='league.seasonEndedDaysAgoText', subs=[('${NUMBER}', str(-(days_to_end + 1)))], ) bui.textwidget(edit=self._season_ends_text, text=to_end_string) bui.textwidget( edit=self._trophy_counts_reset_text, text=( bui.Lstr(resource='league.trophyCountsResetText') if self._is_current_season and show_season_end else '' ), ) bui.textwidget(edit=self._league_text, text=lname, color=lcolor) l_text_width = min( self._league_text_maxwidth, bui.get_string_width(lname, suppress_warning=True) * self._league_text_scale, ) bui.textwidget( edit=self._league_number_text, text=lnum, color=lcolor, position=( self._xoffs + self._league_number_base_pos[0] + l_text_width * 0.5 + 8, self._league_number_base_pos[1] + 10, ), ) bui.textwidget( edit=self._to_ranked_text, text=( bui.Lstr(resource='coopSelectWindow.toRankedText').evaluate() + '' + extra_text if do_percent else '' ), ) bui.textwidget( edit=self._your_power_ranking_text, text=( bui.Lstr( resource='rankText', fallback_resource='coopSelectWindow.yourPowerRankingText', ) if (not do_percent) else '' ), ) bui.spinnerwidget(edit=self._loading_spinner, visible=False) bui.textwidget( edit=self._power_ranking_rank_text, position=(self._xoffs + 473, v - 70 - (170 if do_percent else 220)), text=status_text, big=(in_top or do_percent), scale=( 3.0 if (in_top or do_percent) else 0.7 if finished_season_unranked else 1.0 ), ) if self._activity_mult_button is not None: if data is None or data['act'] is None: bui.buttonwidget( edit=self._activity_mult_button, textcolor=(0.7, 0.7, 0.8, 0.5), icon_color=(0.5, 0, 0.5, 0.3), ) bui.textwidget(edit=self._activity_mult_text, text=' -') else: bui.buttonwidget( edit=self._activity_mult_button, textcolor=(0.7, 0.7, 0.8, 1.0), icon_color=(0.5, 0, 0.5, 1.0), ) bui.textwidget( edit=self._activity_mult_text, text=f'x {data['act']:.2f}', ) # This used to be a bonus for 'BombSquad Pro' holders, but since # we're transitioning away from that it is now a bonus for # everyone running a recent-ish version of the game. have_up_to_date_bonus = data is not None pro_mult = ( 1.0 + float( plus.get_v1_account_misc_read_val('proPowerRankingBoost', 0.0) ) * 0.01 ) bui.textwidget( edit=self._up_to_date_bonus_text, text=( ' -' if (data is None or not have_up_to_date_bonus) else f'x {pro_mult:.2f}' ), ) bui.buttonwidget( edit=self._up_to_date_bonus_button, textcolor=(0.7, 0.7, 0.8, (1.0 if have_up_to_date_bonus else 0.5)), icon_color=( (0.5, 0, 0.5) if have_up_to_date_bonus else (0.5, 0, 0.5, 0.2) ), ) bui.buttonwidget( edit=self._power_ranking_achievements_button, label=('' if data is None else str(data['a']) + ' ') + bui.Lstr(resource='achievementsText').evaluate(), ) # For the achievement value, use the number they gave us for # non-current seasons; otherwise calc our own. total_ach_value = 0 for ach in bui.app.classic.ach.achievements: if ach.complete: total_ach_value += ach.power_ranking_value if self._season != 'a' and not self._is_current_season: if data is not None and 'at' in data: total_ach_value = data['at'] bui.textwidget( edit=self._power_ranking_achievement_total_text, text=( '-' if data is None else ('+ ' + pts_txt.replace('${NUMBER}', str(total_ach_value))) ), ) total_trophies_count = accounts.get_league_rank_points( data, 'trophyCount' ) total_trophies_value = accounts.get_league_rank_points(data, 'trophies') bui.buttonwidget( edit=self._power_ranking_trophies_button, label=('' if data is None else str(total_trophies_count) + ' ') + bui.Lstr(resource='trophiesText').evaluate(), ) bui.textwidget( edit=self._power_ranking_trophies_total_text, text=( '-' if data is None else ( '+ ' + pts_txt.replace('${NUMBER}', str(total_trophies_value)) ) ), ) bui.textwidget( edit=self._power_ranking_total_text, text=( '-' if data is None else eq_text.replace( '${NUMBER}', str(accounts.get_league_rank_points(data)) ) ), ) for widget in self._power_ranking_score_widgets: widget.delete() self._power_ranking_score_widgets = [] scores = data['scores'] if data is not None else [] tally_color = (0.5, 0.6, 0.8) w_parent = self._subcontainer v2 = self._power_ranking_score_v for score in scores: h2 = 680 is_us = score[3] self._power_ranking_score_widgets.append( bui.textwidget( parent=w_parent, position=(self._xoffs + h2 - 20, v2), size=(0, 0), color=(1, 1, 1) if is_us else (0.6, 0.6, 0.7), maxwidth=40, flatness=1.0, shadow=0.0, text=num_text.replace('${NUMBER}', str(score[0])), h_align='right', v_align='center', scale=0.5, ) ) self._power_ranking_score_widgets.append( bui.textwidget( parent=w_parent, position=(self._xoffs + h2 + 20, v2), size=(0, 0), color=(1, 1, 1) if is_us else tally_color, maxwidth=60, text=str(score[1]), flatness=1.0, shadow=0.0, h_align='center', v_align='center', scale=0.7, ) ) txt = bui.textwidget( parent=w_parent, position=(self._xoffs + h2 + 60, v2 - (28 * 0.5) / 0.9), size=(210 / 0.9, 28), color=(1, 1, 1) if is_us else (0.6, 0.6, 0.6), maxwidth=210, flatness=1.0, shadow=0.0, autoselect=True, selectable=True, click_activate=True, text=score[2], h_align='left', v_align='center', scale=0.9, ) self._power_ranking_score_widgets.append(txt) bui.textwidget( edit=txt, on_activate_call=bui.Call( self._show_account_info, score[4], txt ), ) assert self._season_popup_menu is not None bui.widget( edit=txt, left_widget=self._season_popup_menu.get_button() ) v2 -= 28 def _show_account_info( self, account_id: str, textwidget: bui.Widget ) -> None: from bauiv1lib.account.viewer import AccountViewerWindow bui.getsound('swish').play() AccountViewerWindow( account_id=account_id, position=textwidget.get_screen_space_center() ) def _on_season_change(self, value: str) -> None: self._requested_season = value self._last_power_ranking_query_time = None # Update asap. self._update(show=True) def _save_state(self) -> None: pass
# Docs-generation hack; import some stuff that we likely only forward-declared # in our actual source code so that docs tools can find it. from typing import (Coroutine, Any, Literal, Callable, Generator, Awaitable, Sequence, Self) import asyncio from concurrent.futures import Future from pathlib import Path from enum import Enum