bauiv1lib.league.rankbutton
Provides a button showing league rank.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides a button showing league rank.""" 4 5from __future__ import annotations 6 7import logging 8from typing import TYPE_CHECKING 9 10import bauiv1 as bui 11 12if TYPE_CHECKING: 13 from typing import Any, Callable 14 15 16class LeagueRankButton: 17 """Button showing league rank.""" 18 19 def __init__( 20 self, 21 parent: bui.Widget, 22 position: tuple[float, float], 23 size: tuple[float, float], 24 scale: float, 25 on_activate_call: Callable[[], Any] | None = None, 26 transition_delay: float | None = None, 27 color: tuple[float, float, float] | None = None, 28 textcolor: tuple[float, float, float] | None = None, 29 smooth_update_delay: float | None = None, 30 ): 31 if on_activate_call is None: 32 on_activate_call = bui.WeakCall(self._default_on_activate_call) 33 self._on_activate_call = on_activate_call 34 if smooth_update_delay is None: 35 smooth_update_delay = 1.0 36 self._smooth_update_delay = smooth_update_delay 37 self._size = size 38 self._scale = scale 39 if color is None: 40 color = (0.5, 0.6, 0.5) 41 if textcolor is None: 42 textcolor = (1, 1, 1) 43 self._color = color 44 self._textcolor = textcolor 45 self._header_color = (0.8, 0.8, 2.0) 46 self._parent = parent 47 self._position: tuple[float, float] = (0.0, 0.0) 48 49 self._button = bui.buttonwidget( 50 parent=parent, 51 size=size, 52 label='', 53 button_type='square', 54 scale=scale, 55 autoselect=True, 56 on_activate_call=self._on_activate, 57 transition_delay=transition_delay, 58 color=color, 59 ) 60 61 self._title_text = bui.textwidget( 62 parent=parent, 63 size=(0, 0), 64 draw_controller=self._button, 65 h_align='center', 66 v_align='center', 67 maxwidth=size[0] * scale * 0.85, 68 text=bui.Lstr( 69 resource='league.leagueRankText', 70 fallback_resource='coopSelectWindow.powerRankingText', 71 ), 72 color=self._header_color, 73 flatness=1.0, 74 shadow=1.0, 75 scale=scale * 0.5, 76 transition_delay=transition_delay, 77 ) 78 79 self._value_text = bui.textwidget( 80 parent=parent, 81 size=(0, 0), 82 h_align='center', 83 v_align='center', 84 maxwidth=size[0] * scale * 0.85, 85 text='-', 86 draw_controller=self._button, 87 big=True, 88 scale=scale, 89 transition_delay=transition_delay, 90 color=textcolor, 91 ) 92 93 plus = bui.app.plus 94 assert plus is not None 95 96 self._smooth_percent: float | None = None 97 self._percent: int | None = None 98 self._smooth_rank: float | None = None 99 self._rank: int | None = None 100 self._ticking_sound: bui.Sound | None = None 101 self._smooth_increase_speed = 1.0 102 self._league: str | None = None 103 self._improvement_text: str | None = None 104 105 self._smooth_update_timer: bui.AppTimer | None = None 106 107 # Take note of our account state; we'll refresh later if this changes. 108 self._account_state_num = plus.get_v1_account_state_num() 109 self._last_power_ranking_query_time: float | None = None 110 self._doing_power_ranking_query = False 111 self.set_position(position) 112 self._bg_flash = False 113 self._update_timer = bui.AppTimer( 114 1.0, bui.WeakCall(self._update), repeat=True 115 ) 116 self._update() 117 118 # If we've got cached power-ranking data already, apply it. 119 assert bui.app.classic is not None 120 data = bui.app.classic.accounts.get_cached_league_rank_data() 121 if data is not None: 122 self._update_for_league_rank_data(data) 123 124 def _on_activate(self) -> None: 125 bui.increment_analytics_count('League rank button press') 126 self._on_activate_call() 127 128 def __del__(self) -> None: 129 if self._ticking_sound is not None: 130 self._ticking_sound.stop() 131 self._ticking_sound = None 132 133 def _start_smooth_update(self) -> None: 134 self._smooth_update_timer = bui.AppTimer( 135 0.05, bui.WeakCall(self._smooth_update), repeat=True 136 ) 137 138 def _smooth_update(self) -> None: 139 # pylint: disable=too-many-branches 140 # pylint: disable=too-many-statements 141 try: 142 if not self._button: 143 return 144 if self._ticking_sound is None: 145 self._ticking_sound = bui.getsound('scoreIncrease') 146 self._ticking_sound.play() 147 self._bg_flash = not self._bg_flash 148 color_used = ( 149 (self._color[0] * 2, self._color[1] * 2, self._color[2] * 2) 150 if self._bg_flash 151 else self._color 152 ) 153 textcolor_used = (1, 1, 1) if self._bg_flash else self._textcolor 154 header_color_used = ( 155 (1, 1, 1) if self._bg_flash else self._header_color 156 ) 157 158 if self._rank is not None: 159 assert self._smooth_rank is not None 160 self._smooth_rank -= 1.0 * self._smooth_increase_speed 161 finished = int(self._smooth_rank) <= self._rank 162 elif self._smooth_percent is not None: 163 self._smooth_percent += 1.0 * self._smooth_increase_speed 164 assert self._percent is not None 165 finished = int(self._smooth_percent) >= self._percent 166 else: 167 finished = True 168 if finished: 169 if self._rank is not None: 170 self._smooth_rank = float(self._rank) 171 elif self._percent is not None: 172 self._smooth_percent = float(self._percent) 173 color_used = self._color 174 textcolor_used = self._textcolor 175 self._smooth_update_timer = None 176 if self._ticking_sound is not None: 177 self._ticking_sound.stop() 178 self._ticking_sound = None 179 bui.getsound('cashRegister2').play() 180 assert self._improvement_text is not None 181 diff_text = bui.textwidget( 182 parent=self._parent, 183 size=(0, 0), 184 h_align='center', 185 v_align='center', 186 text='+' + self._improvement_text + '!', 187 position=( 188 self._position[0] + self._size[0] * 0.5 * self._scale, 189 self._position[1] + self._size[1] * -0.2 * self._scale, 190 ), 191 color=(0, 1, 0), 192 flatness=1.0, 193 shadow=0.0, 194 scale=self._scale * 0.7, 195 ) 196 197 def safe_delete(widget: bui.Widget) -> None: 198 if widget: 199 widget.delete() 200 201 bui.apptimer(2.0, bui.Call(safe_delete, diff_text)) 202 status_text: str | bui.Lstr 203 if self._rank is not None: 204 assert self._smooth_rank is not None 205 status_text = bui.Lstr( 206 resource='numberText', 207 subs=[('${NUMBER}', str(int(self._smooth_rank)))], 208 ) 209 elif self._smooth_percent is not None: 210 status_text = str(int(self._smooth_percent)) + '%' 211 else: 212 status_text = '-' 213 bui.textwidget( 214 edit=self._value_text, text=status_text, color=textcolor_used 215 ) 216 bui.textwidget(edit=self._title_text, color=header_color_used) 217 bui.buttonwidget(edit=self._button, color=color_used) 218 219 except Exception: 220 logging.exception('Error doing smooth update.') 221 self._smooth_update_timer = None 222 223 def _update_for_league_rank_data(self, data: dict[str, Any] | None) -> None: 224 # pylint: disable=too-many-branches 225 # pylint: disable=too-many-statements 226 227 plus = bui.app.plus 228 assert plus is not None 229 230 # If our button has died, ignore. 231 if not self._button: 232 return 233 234 status_text: str | bui.Lstr 235 236 in_top = data is not None and data['rank'] is not None 237 do_percent = False 238 if data is None or plus.get_v1_account_state() != 'signed_in': 239 self._percent = self._rank = None 240 status_text = '-' 241 elif in_top: 242 self._percent = None 243 self._rank = data['rank'] 244 prev_league = self._league 245 self._league = data['l'] 246 247 # If this is the first set, league has changed, or rank has gotten 248 # worse, snap the smooth value immediately. 249 assert self._rank is not None 250 if ( 251 self._smooth_rank is None 252 or prev_league != self._league 253 or self._rank > int(self._smooth_rank) 254 ): 255 self._smooth_rank = float(self._rank) 256 status_text = bui.Lstr( 257 resource='numberText', 258 subs=[('${NUMBER}', str(int(self._smooth_rank)))], 259 ) 260 else: 261 try: 262 if not data['scores'] or data['scores'][-1][1] <= 0: 263 self._percent = self._rank = None 264 status_text = '-' 265 else: 266 assert bui.app.classic is not None 267 our_points = ( 268 bui.app.classic.accounts.get_league_rank_points(data) 269 ) 270 progress = float(our_points) / data['scores'][-1][1] 271 self._percent = int(progress * 100.0) 272 self._rank = None 273 do_percent = True 274 prev_league = self._league 275 self._league = data['l'] 276 277 # If this is the first set, league has changed, or percent 278 # has decreased, snap the smooth value immediately. 279 if ( 280 self._smooth_percent is None 281 or prev_league != self._league 282 or self._percent < int(self._smooth_percent) 283 ): 284 self._smooth_percent = float(self._percent) 285 status_text = str(int(self._smooth_percent)) + '%' 286 287 except Exception: 288 logging.exception('Error updating power ranking.') 289 self._percent = self._rank = None 290 status_text = '-' 291 292 # If we're doing a smooth update, set a timer. 293 if ( 294 self._rank is not None 295 and self._smooth_rank is not None 296 and int(self._smooth_rank) != self._rank 297 ): 298 self._improvement_text = str( 299 -(int(self._rank) - int(self._smooth_rank)) 300 ) 301 diff = abs(self._rank - self._smooth_rank) 302 if diff > 100: 303 self._smooth_increase_speed = diff / 80.0 304 elif diff > 50: 305 self._smooth_increase_speed = diff / 70.0 306 elif diff > 25: 307 self._smooth_increase_speed = diff / 55.0 308 else: 309 self._smooth_increase_speed = diff / 40.0 310 self._smooth_increase_speed = max(0.4, self._smooth_increase_speed) 311 bui.apptimer( 312 self._smooth_update_delay, 313 bui.WeakCall(self._start_smooth_update), 314 ) 315 316 if ( 317 self._percent is not None 318 and self._smooth_percent is not None 319 and int(self._smooth_percent) != self._percent 320 ): 321 self._improvement_text = str( 322 (int(self._percent) - int(self._smooth_percent)) 323 ) 324 self._smooth_increase_speed = 0.3 325 bui.apptimer( 326 self._smooth_update_delay, 327 bui.WeakCall(self._start_smooth_update), 328 ) 329 330 if do_percent: 331 bui.textwidget( 332 edit=self._title_text, 333 text=bui.Lstr(resource='coopSelectWindow.toRankedText'), 334 ) 335 else: 336 try: 337 assert data is not None 338 txt = bui.Lstr( 339 resource='league.leagueFullText', 340 subs=[ 341 ( 342 '${NAME}', 343 bui.Lstr(translate=('leagueNames', data['l']['n'])), 344 ), 345 ], 346 ) 347 t_color = data['l']['c'] 348 except Exception: 349 txt = bui.Lstr( 350 resource='league.leagueRankText', 351 fallback_resource='coopSelectWindow.powerRankingText', 352 ) 353 assert bui.app.classic is not None 354 t_color = bui.app.ui_v1.title_color 355 bui.textwidget(edit=self._title_text, text=txt, color=t_color) 356 bui.textwidget(edit=self._value_text, text=status_text) 357 358 def _on_power_ranking_query_response( 359 self, data: dict[str, Any] | None 360 ) -> None: 361 self._doing_power_ranking_query = False 362 assert bui.app.classic is not None 363 bui.app.classic.accounts.cache_league_rank_data(data) 364 self._update_for_league_rank_data(data) 365 366 def _update(self) -> None: 367 cur_time = bui.apptime() 368 369 plus = bui.app.plus 370 assert plus is not None 371 372 # If our account state has changed, refresh our UI. 373 account_state_num = plus.get_v1_account_state_num() 374 if account_state_num != self._account_state_num: 375 self._account_state_num = account_state_num 376 377 # And power ranking too... 378 if not self._doing_power_ranking_query: 379 self._last_power_ranking_query_time = None 380 381 # Send off a new power-ranking query if its been 382 # long enough or whatnot. 383 if not self._doing_power_ranking_query and ( 384 self._last_power_ranking_query_time is None 385 or cur_time - self._last_power_ranking_query_time > 30.0 386 ): 387 self._last_power_ranking_query_time = cur_time 388 self._doing_power_ranking_query = True 389 plus.power_ranking_query( 390 callback=bui.WeakCall(self._on_power_ranking_query_response) 391 ) 392 393 def _default_on_activate_call(self) -> None: 394 # pylint: disable=cyclic-import 395 from bauiv1lib.league.rankwindow import LeagueRankWindow 396 397 LeagueRankWindow(modal=True, origin_widget=self._button) 398 399 def set_position(self, position: tuple[float, float]) -> None: 400 """Set the button's position.""" 401 self._position = position 402 if not self._button: 403 return 404 bui.buttonwidget(edit=self._button, position=self._position) 405 bui.textwidget( 406 edit=self._title_text, 407 position=( 408 self._position[0] + self._size[0] * 0.5 * self._scale, 409 self._position[1] + self._size[1] * 0.82 * self._scale, 410 ), 411 ) 412 bui.textwidget( 413 edit=self._value_text, 414 position=( 415 self._position[0] + self._size[0] * 0.5 * self._scale, 416 self._position[1] + self._size[1] * 0.36 * self._scale, 417 ), 418 ) 419 420 def get_button(self) -> bui.Widget: 421 """Return the underlying button bui.Widget>""" 422 return self._button
class
LeagueRankButton:
17class LeagueRankButton: 18 """Button showing league rank.""" 19 20 def __init__( 21 self, 22 parent: bui.Widget, 23 position: tuple[float, float], 24 size: tuple[float, float], 25 scale: float, 26 on_activate_call: Callable[[], Any] | None = None, 27 transition_delay: float | None = None, 28 color: tuple[float, float, float] | None = None, 29 textcolor: tuple[float, float, float] | None = None, 30 smooth_update_delay: float | None = None, 31 ): 32 if on_activate_call is None: 33 on_activate_call = bui.WeakCall(self._default_on_activate_call) 34 self._on_activate_call = on_activate_call 35 if smooth_update_delay is None: 36 smooth_update_delay = 1.0 37 self._smooth_update_delay = smooth_update_delay 38 self._size = size 39 self._scale = scale 40 if color is None: 41 color = (0.5, 0.6, 0.5) 42 if textcolor is None: 43 textcolor = (1, 1, 1) 44 self._color = color 45 self._textcolor = textcolor 46 self._header_color = (0.8, 0.8, 2.0) 47 self._parent = parent 48 self._position: tuple[float, float] = (0.0, 0.0) 49 50 self._button = bui.buttonwidget( 51 parent=parent, 52 size=size, 53 label='', 54 button_type='square', 55 scale=scale, 56 autoselect=True, 57 on_activate_call=self._on_activate, 58 transition_delay=transition_delay, 59 color=color, 60 ) 61 62 self._title_text = bui.textwidget( 63 parent=parent, 64 size=(0, 0), 65 draw_controller=self._button, 66 h_align='center', 67 v_align='center', 68 maxwidth=size[0] * scale * 0.85, 69 text=bui.Lstr( 70 resource='league.leagueRankText', 71 fallback_resource='coopSelectWindow.powerRankingText', 72 ), 73 color=self._header_color, 74 flatness=1.0, 75 shadow=1.0, 76 scale=scale * 0.5, 77 transition_delay=transition_delay, 78 ) 79 80 self._value_text = bui.textwidget( 81 parent=parent, 82 size=(0, 0), 83 h_align='center', 84 v_align='center', 85 maxwidth=size[0] * scale * 0.85, 86 text='-', 87 draw_controller=self._button, 88 big=True, 89 scale=scale, 90 transition_delay=transition_delay, 91 color=textcolor, 92 ) 93 94 plus = bui.app.plus 95 assert plus is not None 96 97 self._smooth_percent: float | None = None 98 self._percent: int | None = None 99 self._smooth_rank: float | None = None 100 self._rank: int | None = None 101 self._ticking_sound: bui.Sound | None = None 102 self._smooth_increase_speed = 1.0 103 self._league: str | None = None 104 self._improvement_text: str | None = None 105 106 self._smooth_update_timer: bui.AppTimer | None = None 107 108 # Take note of our account state; we'll refresh later if this changes. 109 self._account_state_num = plus.get_v1_account_state_num() 110 self._last_power_ranking_query_time: float | None = None 111 self._doing_power_ranking_query = False 112 self.set_position(position) 113 self._bg_flash = False 114 self._update_timer = bui.AppTimer( 115 1.0, bui.WeakCall(self._update), repeat=True 116 ) 117 self._update() 118 119 # If we've got cached power-ranking data already, apply it. 120 assert bui.app.classic is not None 121 data = bui.app.classic.accounts.get_cached_league_rank_data() 122 if data is not None: 123 self._update_for_league_rank_data(data) 124 125 def _on_activate(self) -> None: 126 bui.increment_analytics_count('League rank button press') 127 self._on_activate_call() 128 129 def __del__(self) -> None: 130 if self._ticking_sound is not None: 131 self._ticking_sound.stop() 132 self._ticking_sound = None 133 134 def _start_smooth_update(self) -> None: 135 self._smooth_update_timer = bui.AppTimer( 136 0.05, bui.WeakCall(self._smooth_update), repeat=True 137 ) 138 139 def _smooth_update(self) -> None: 140 # pylint: disable=too-many-branches 141 # pylint: disable=too-many-statements 142 try: 143 if not self._button: 144 return 145 if self._ticking_sound is None: 146 self._ticking_sound = bui.getsound('scoreIncrease') 147 self._ticking_sound.play() 148 self._bg_flash = not self._bg_flash 149 color_used = ( 150 (self._color[0] * 2, self._color[1] * 2, self._color[2] * 2) 151 if self._bg_flash 152 else self._color 153 ) 154 textcolor_used = (1, 1, 1) if self._bg_flash else self._textcolor 155 header_color_used = ( 156 (1, 1, 1) if self._bg_flash else self._header_color 157 ) 158 159 if self._rank is not None: 160 assert self._smooth_rank is not None 161 self._smooth_rank -= 1.0 * self._smooth_increase_speed 162 finished = int(self._smooth_rank) <= self._rank 163 elif self._smooth_percent is not None: 164 self._smooth_percent += 1.0 * self._smooth_increase_speed 165 assert self._percent is not None 166 finished = int(self._smooth_percent) >= self._percent 167 else: 168 finished = True 169 if finished: 170 if self._rank is not None: 171 self._smooth_rank = float(self._rank) 172 elif self._percent is not None: 173 self._smooth_percent = float(self._percent) 174 color_used = self._color 175 textcolor_used = self._textcolor 176 self._smooth_update_timer = None 177 if self._ticking_sound is not None: 178 self._ticking_sound.stop() 179 self._ticking_sound = None 180 bui.getsound('cashRegister2').play() 181 assert self._improvement_text is not None 182 diff_text = bui.textwidget( 183 parent=self._parent, 184 size=(0, 0), 185 h_align='center', 186 v_align='center', 187 text='+' + self._improvement_text + '!', 188 position=( 189 self._position[0] + self._size[0] * 0.5 * self._scale, 190 self._position[1] + self._size[1] * -0.2 * self._scale, 191 ), 192 color=(0, 1, 0), 193 flatness=1.0, 194 shadow=0.0, 195 scale=self._scale * 0.7, 196 ) 197 198 def safe_delete(widget: bui.Widget) -> None: 199 if widget: 200 widget.delete() 201 202 bui.apptimer(2.0, bui.Call(safe_delete, diff_text)) 203 status_text: str | bui.Lstr 204 if self._rank is not None: 205 assert self._smooth_rank is not None 206 status_text = bui.Lstr( 207 resource='numberText', 208 subs=[('${NUMBER}', str(int(self._smooth_rank)))], 209 ) 210 elif self._smooth_percent is not None: 211 status_text = str(int(self._smooth_percent)) + '%' 212 else: 213 status_text = '-' 214 bui.textwidget( 215 edit=self._value_text, text=status_text, color=textcolor_used 216 ) 217 bui.textwidget(edit=self._title_text, color=header_color_used) 218 bui.buttonwidget(edit=self._button, color=color_used) 219 220 except Exception: 221 logging.exception('Error doing smooth update.') 222 self._smooth_update_timer = None 223 224 def _update_for_league_rank_data(self, data: dict[str, Any] | None) -> None: 225 # pylint: disable=too-many-branches 226 # pylint: disable=too-many-statements 227 228 plus = bui.app.plus 229 assert plus is not None 230 231 # If our button has died, ignore. 232 if not self._button: 233 return 234 235 status_text: str | bui.Lstr 236 237 in_top = data is not None and data['rank'] is not None 238 do_percent = False 239 if data is None or plus.get_v1_account_state() != 'signed_in': 240 self._percent = self._rank = None 241 status_text = '-' 242 elif in_top: 243 self._percent = None 244 self._rank = data['rank'] 245 prev_league = self._league 246 self._league = data['l'] 247 248 # If this is the first set, league has changed, or rank has gotten 249 # worse, snap the smooth value immediately. 250 assert self._rank is not None 251 if ( 252 self._smooth_rank is None 253 or prev_league != self._league 254 or self._rank > int(self._smooth_rank) 255 ): 256 self._smooth_rank = float(self._rank) 257 status_text = bui.Lstr( 258 resource='numberText', 259 subs=[('${NUMBER}', str(int(self._smooth_rank)))], 260 ) 261 else: 262 try: 263 if not data['scores'] or data['scores'][-1][1] <= 0: 264 self._percent = self._rank = None 265 status_text = '-' 266 else: 267 assert bui.app.classic is not None 268 our_points = ( 269 bui.app.classic.accounts.get_league_rank_points(data) 270 ) 271 progress = float(our_points) / data['scores'][-1][1] 272 self._percent = int(progress * 100.0) 273 self._rank = None 274 do_percent = True 275 prev_league = self._league 276 self._league = data['l'] 277 278 # If this is the first set, league has changed, or percent 279 # has decreased, snap the smooth value immediately. 280 if ( 281 self._smooth_percent is None 282 or prev_league != self._league 283 or self._percent < int(self._smooth_percent) 284 ): 285 self._smooth_percent = float(self._percent) 286 status_text = str(int(self._smooth_percent)) + '%' 287 288 except Exception: 289 logging.exception('Error updating power ranking.') 290 self._percent = self._rank = None 291 status_text = '-' 292 293 # If we're doing a smooth update, set a timer. 294 if ( 295 self._rank is not None 296 and self._smooth_rank is not None 297 and int(self._smooth_rank) != self._rank 298 ): 299 self._improvement_text = str( 300 -(int(self._rank) - int(self._smooth_rank)) 301 ) 302 diff = abs(self._rank - self._smooth_rank) 303 if diff > 100: 304 self._smooth_increase_speed = diff / 80.0 305 elif diff > 50: 306 self._smooth_increase_speed = diff / 70.0 307 elif diff > 25: 308 self._smooth_increase_speed = diff / 55.0 309 else: 310 self._smooth_increase_speed = diff / 40.0 311 self._smooth_increase_speed = max(0.4, self._smooth_increase_speed) 312 bui.apptimer( 313 self._smooth_update_delay, 314 bui.WeakCall(self._start_smooth_update), 315 ) 316 317 if ( 318 self._percent is not None 319 and self._smooth_percent is not None 320 and int(self._smooth_percent) != self._percent 321 ): 322 self._improvement_text = str( 323 (int(self._percent) - int(self._smooth_percent)) 324 ) 325 self._smooth_increase_speed = 0.3 326 bui.apptimer( 327 self._smooth_update_delay, 328 bui.WeakCall(self._start_smooth_update), 329 ) 330 331 if do_percent: 332 bui.textwidget( 333 edit=self._title_text, 334 text=bui.Lstr(resource='coopSelectWindow.toRankedText'), 335 ) 336 else: 337 try: 338 assert data is not None 339 txt = bui.Lstr( 340 resource='league.leagueFullText', 341 subs=[ 342 ( 343 '${NAME}', 344 bui.Lstr(translate=('leagueNames', data['l']['n'])), 345 ), 346 ], 347 ) 348 t_color = data['l']['c'] 349 except Exception: 350 txt = bui.Lstr( 351 resource='league.leagueRankText', 352 fallback_resource='coopSelectWindow.powerRankingText', 353 ) 354 assert bui.app.classic is not None 355 t_color = bui.app.ui_v1.title_color 356 bui.textwidget(edit=self._title_text, text=txt, color=t_color) 357 bui.textwidget(edit=self._value_text, text=status_text) 358 359 def _on_power_ranking_query_response( 360 self, data: dict[str, Any] | None 361 ) -> None: 362 self._doing_power_ranking_query = False 363 assert bui.app.classic is not None 364 bui.app.classic.accounts.cache_league_rank_data(data) 365 self._update_for_league_rank_data(data) 366 367 def _update(self) -> None: 368 cur_time = bui.apptime() 369 370 plus = bui.app.plus 371 assert plus is not None 372 373 # If our account state has changed, refresh our UI. 374 account_state_num = plus.get_v1_account_state_num() 375 if account_state_num != self._account_state_num: 376 self._account_state_num = account_state_num 377 378 # And power ranking too... 379 if not self._doing_power_ranking_query: 380 self._last_power_ranking_query_time = None 381 382 # Send off a new power-ranking query if its been 383 # long enough or whatnot. 384 if not self._doing_power_ranking_query and ( 385 self._last_power_ranking_query_time is None 386 or cur_time - self._last_power_ranking_query_time > 30.0 387 ): 388 self._last_power_ranking_query_time = cur_time 389 self._doing_power_ranking_query = True 390 plus.power_ranking_query( 391 callback=bui.WeakCall(self._on_power_ranking_query_response) 392 ) 393 394 def _default_on_activate_call(self) -> None: 395 # pylint: disable=cyclic-import 396 from bauiv1lib.league.rankwindow import LeagueRankWindow 397 398 LeagueRankWindow(modal=True, origin_widget=self._button) 399 400 def set_position(self, position: tuple[float, float]) -> None: 401 """Set the button's position.""" 402 self._position = position 403 if not self._button: 404 return 405 bui.buttonwidget(edit=self._button, position=self._position) 406 bui.textwidget( 407 edit=self._title_text, 408 position=( 409 self._position[0] + self._size[0] * 0.5 * self._scale, 410 self._position[1] + self._size[1] * 0.82 * self._scale, 411 ), 412 ) 413 bui.textwidget( 414 edit=self._value_text, 415 position=( 416 self._position[0] + self._size[0] * 0.5 * self._scale, 417 self._position[1] + self._size[1] * 0.36 * self._scale, 418 ), 419 ) 420 421 def get_button(self) -> bui.Widget: 422 """Return the underlying button bui.Widget>""" 423 return self._button
Button showing league rank.
LeagueRankButton( parent: _bauiv1.Widget, position: tuple[float, float], size: tuple[float, float], scale: float, on_activate_call: Optional[Callable[[], Any]] = None, transition_delay: float | None = None, color: tuple[float, float, float] | None = None, textcolor: tuple[float, float, float] | None = None, smooth_update_delay: float | None = None)
20 def __init__( 21 self, 22 parent: bui.Widget, 23 position: tuple[float, float], 24 size: tuple[float, float], 25 scale: float, 26 on_activate_call: Callable[[], Any] | None = None, 27 transition_delay: float | None = None, 28 color: tuple[float, float, float] | None = None, 29 textcolor: tuple[float, float, float] | None = None, 30 smooth_update_delay: float | None = None, 31 ): 32 if on_activate_call is None: 33 on_activate_call = bui.WeakCall(self._default_on_activate_call) 34 self._on_activate_call = on_activate_call 35 if smooth_update_delay is None: 36 smooth_update_delay = 1.0 37 self._smooth_update_delay = smooth_update_delay 38 self._size = size 39 self._scale = scale 40 if color is None: 41 color = (0.5, 0.6, 0.5) 42 if textcolor is None: 43 textcolor = (1, 1, 1) 44 self._color = color 45 self._textcolor = textcolor 46 self._header_color = (0.8, 0.8, 2.0) 47 self._parent = parent 48 self._position: tuple[float, float] = (0.0, 0.0) 49 50 self._button = bui.buttonwidget( 51 parent=parent, 52 size=size, 53 label='', 54 button_type='square', 55 scale=scale, 56 autoselect=True, 57 on_activate_call=self._on_activate, 58 transition_delay=transition_delay, 59 color=color, 60 ) 61 62 self._title_text = bui.textwidget( 63 parent=parent, 64 size=(0, 0), 65 draw_controller=self._button, 66 h_align='center', 67 v_align='center', 68 maxwidth=size[0] * scale * 0.85, 69 text=bui.Lstr( 70 resource='league.leagueRankText', 71 fallback_resource='coopSelectWindow.powerRankingText', 72 ), 73 color=self._header_color, 74 flatness=1.0, 75 shadow=1.0, 76 scale=scale * 0.5, 77 transition_delay=transition_delay, 78 ) 79 80 self._value_text = bui.textwidget( 81 parent=parent, 82 size=(0, 0), 83 h_align='center', 84 v_align='center', 85 maxwidth=size[0] * scale * 0.85, 86 text='-', 87 draw_controller=self._button, 88 big=True, 89 scale=scale, 90 transition_delay=transition_delay, 91 color=textcolor, 92 ) 93 94 plus = bui.app.plus 95 assert plus is not None 96 97 self._smooth_percent: float | None = None 98 self._percent: int | None = None 99 self._smooth_rank: float | None = None 100 self._rank: int | None = None 101 self._ticking_sound: bui.Sound | None = None 102 self._smooth_increase_speed = 1.0 103 self._league: str | None = None 104 self._improvement_text: str | None = None 105 106 self._smooth_update_timer: bui.AppTimer | None = None 107 108 # Take note of our account state; we'll refresh later if this changes. 109 self._account_state_num = plus.get_v1_account_state_num() 110 self._last_power_ranking_query_time: float | None = None 111 self._doing_power_ranking_query = False 112 self.set_position(position) 113 self._bg_flash = False 114 self._update_timer = bui.AppTimer( 115 1.0, bui.WeakCall(self._update), repeat=True 116 ) 117 self._update() 118 119 # If we've got cached power-ranking data already, apply it. 120 assert bui.app.classic is not None 121 data = bui.app.classic.accounts.get_cached_league_rank_data() 122 if data is not None: 123 self._update_for_league_rank_data(data)
def
set_position(self, position: tuple[float, float]) -> None:
400 def set_position(self, position: tuple[float, float]) -> None: 401 """Set the button's position.""" 402 self._position = position 403 if not self._button: 404 return 405 bui.buttonwidget(edit=self._button, position=self._position) 406 bui.textwidget( 407 edit=self._title_text, 408 position=( 409 self._position[0] + self._size[0] * 0.5 * self._scale, 410 self._position[1] + self._size[1] * 0.82 * self._scale, 411 ), 412 ) 413 bui.textwidget( 414 edit=self._value_text, 415 position=( 416 self._position[0] + self._size[0] * 0.5 * self._scale, 417 self._position[1] + self._size[1] * 0.36 * self._scale, 418 ), 419 )
Set the button's position.