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