bauiv1lib.league.rankwindow
UI related to league rank.
1# Released under the MIT License. See LICENSE for details. 2# 3"""UI related to league rank.""" 4# pylint: disable=too-many-lines 5 6from __future__ import annotations 7 8import copy 9import logging 10from typing import TYPE_CHECKING 11 12from bauiv1lib.popup import PopupMenu 13import bauiv1 as bui 14 15if TYPE_CHECKING: 16 from typing import Any 17 18 19class LeagueRankWindow(bui.Window): 20 """Window for showing league rank.""" 21 22 def __init__( 23 self, 24 transition: str = 'in_right', 25 modal: bool = False, 26 origin_widget: bui.Widget | None = None, 27 ): 28 # pylint: disable=too-many-statements 29 plus = bui.app.plus 30 assert plus is not None 31 32 bui.set_analytics_screen('League Rank Window') 33 34 self._league_rank_data: dict[str, Any] | None = None 35 self._modal = modal 36 37 self._power_ranking_achievements_button: bui.Widget | None = None 38 self._pro_mult_button: bui.Widget | None = None 39 self._power_ranking_trophies_button: bui.Widget | None = None 40 self._league_title_text: bui.Widget | None = None 41 self._league_text: bui.Widget | None = None 42 self._league_number_text: bui.Widget | None = None 43 self._your_power_ranking_text: bui.Widget | None = None 44 self._season_ends_text: bui.Widget | None = None 45 self._power_ranking_rank_text: bui.Widget | None = None 46 self._to_ranked_text: bui.Widget | None = None 47 self._trophy_counts_reset_text: bui.Widget | None = None 48 49 # If they provided an origin-widget, scale up from that. 50 scale_origin: tuple[float, float] | None 51 if origin_widget is not None: 52 self._transition_out = 'out_scale' 53 scale_origin = origin_widget.get_screen_space_center() 54 transition = 'in_scale' 55 else: 56 self._transition_out = 'out_right' 57 scale_origin = None 58 59 assert bui.app.classic is not None 60 uiscale = bui.app.ui_v1.uiscale 61 self._width = 1320 if uiscale is bui.UIScale.SMALL else 1120 62 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 63 self._height = ( 64 657 65 if uiscale is bui.UIScale.SMALL 66 else 710 67 if uiscale is bui.UIScale.MEDIUM 68 else 800 69 ) 70 self._r = 'coopSelectWindow' 71 self._rdict = bui.app.lang.get_resource(self._r) 72 top_extra = 20 if uiscale is bui.UIScale.SMALL else 0 73 74 self._league_url_arg = '' 75 76 self._is_current_season = False 77 self._can_do_more_button = True 78 79 super().__init__( 80 root_widget=bui.containerwidget( 81 size=(self._width, self._height + top_extra), 82 stack_offset=(0, -15) 83 if uiscale is bui.UIScale.SMALL 84 else (0, 10) 85 if uiscale is bui.UIScale.MEDIUM 86 else (0, 0), 87 transition=transition, 88 scale_origin_stack_offset=scale_origin, 89 scale=( 90 1.2 91 if uiscale is bui.UIScale.SMALL 92 else 0.93 93 if uiscale is bui.UIScale.MEDIUM 94 else 0.8 95 ), 96 ) 97 ) 98 99 self._back_button = btn = bui.buttonwidget( 100 parent=self._root_widget, 101 position=( 102 75 + x_inset, 103 self._height - 87 - (4 if uiscale is bui.UIScale.SMALL else 0), 104 ), 105 size=(120, 60), 106 scale=1.2, 107 autoselect=True, 108 label=bui.Lstr(resource='doneText' if self._modal else 'backText'), 109 button_type=None if self._modal else 'back', 110 on_activate_call=self._back, 111 ) 112 113 self._title_text = bui.textwidget( 114 parent=self._root_widget, 115 position=(self._width * 0.5, self._height - 56), 116 size=(0, 0), 117 text=bui.Lstr( 118 resource='league.leagueRankText', 119 fallback_resource='coopSelectWindow.powerRankingText', 120 ), 121 h_align='center', 122 color=bui.app.ui_v1.title_color, 123 scale=1.4, 124 maxwidth=600, 125 v_align='center', 126 ) 127 128 bui.buttonwidget( 129 edit=btn, 130 button_type='backSmall', 131 position=( 132 75 + x_inset, 133 self._height - 87 - (2 if uiscale is bui.UIScale.SMALL else 0), 134 ), 135 size=(60, 55), 136 label=bui.charstr(bui.SpecialChar.BACK), 137 ) 138 139 self._scroll_width = self._width - (130 + 2 * x_inset) 140 self._scroll_height = self._height - 160 141 self._scrollwidget = bui.scrollwidget( 142 parent=self._root_widget, 143 highlight=False, 144 position=(65 + x_inset, 70), 145 size=(self._scroll_width, self._scroll_height), 146 center_small_content=True, 147 ) 148 bui.widget(edit=self._scrollwidget, autoselect=True) 149 bui.containerwidget(edit=self._scrollwidget, claims_left_right=True) 150 bui.containerwidget( 151 edit=self._root_widget, 152 cancel_button=self._back_button, 153 selected_child=self._back_button, 154 ) 155 156 self._last_power_ranking_query_time: float | None = None 157 self._doing_power_ranking_query = False 158 159 self._subcontainer: bui.Widget | None = None 160 self._subcontainerwidth = 800 161 self._subcontainerheight = 483 162 self._power_ranking_score_widgets: list[bui.Widget] = [] 163 164 self._season_popup_menu: PopupMenu | None = None 165 self._requested_season: str | None = None 166 self._season: str | None = None 167 168 # take note of our account state; we'll refresh later if this changes 169 self._account_state = plus.get_v1_account_state() 170 171 self._refresh() 172 self._restore_state() 173 174 # if we've got cached power-ranking data already, display it 175 assert bui.app.classic is not None 176 info = bui.app.classic.accounts.get_cached_league_rank_data() 177 if info is not None: 178 self._update_for_league_rank_data(info) 179 180 self._update_timer = bui.AppTimer( 181 1.0, bui.WeakCall(self._update), repeat=True 182 ) 183 self._update(show=info is None) 184 185 def _on_achievements_press(self) -> None: 186 from bauiv1lib import achievements 187 188 # only allow this for all-time or the current season 189 # (we currently don't keep specific achievement data for old seasons) 190 if self._season == 'a' or self._is_current_season: 191 prab = self._power_ranking_achievements_button 192 assert prab is not None 193 achievements.AchievementsWindow( 194 position=prab.get_screen_space_center() 195 ) 196 else: 197 bui.screenmessage( 198 bui.Lstr( 199 resource='achievementsUnavailableForOldSeasonsText', 200 fallback_resource='unavailableText', 201 ), 202 color=(1, 0, 0), 203 ) 204 bui.getsound('error').play() 205 206 def _on_activity_mult_press(self) -> None: 207 from bauiv1lib import confirm 208 209 plus = bui.app.plus 210 assert plus is not None 211 212 txt = bui.Lstr( 213 resource='coopSelectWindow.activenessAllTimeInfoText' 214 if self._season == 'a' 215 else 'coopSelectWindow.activenessInfoText', 216 subs=[ 217 ( 218 '${MAX}', 219 str( 220 plus.get_v1_account_misc_read_val('activenessMax', 1.0) 221 ), 222 ) 223 ], 224 ) 225 confirm.ConfirmWindow( 226 txt, 227 cancel_button=False, 228 width=460, 229 height=150, 230 origin_widget=self._activity_mult_button, 231 ) 232 233 def _on_pro_mult_press(self) -> None: 234 from bauiv1lib import confirm 235 236 plus = bui.app.plus 237 assert plus is not None 238 239 txt = bui.Lstr( 240 resource='coopSelectWindow.proMultInfoText', 241 subs=[ 242 ( 243 '${PERCENT}', 244 str( 245 plus.get_v1_account_misc_read_val( 246 'proPowerRankingBoost', 10 247 ) 248 ), 249 ), 250 ( 251 '${PRO}', 252 bui.Lstr( 253 resource='store.bombSquadProNameText', 254 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 255 ), 256 ), 257 ], 258 ) 259 confirm.ConfirmWindow( 260 txt, 261 cancel_button=False, 262 width=460, 263 height=130, 264 origin_widget=self._pro_mult_button, 265 ) 266 267 def _on_trophies_press(self) -> None: 268 from bauiv1lib.trophies import TrophiesWindow 269 270 info = self._league_rank_data 271 if info is not None: 272 prtb = self._power_ranking_trophies_button 273 assert prtb is not None 274 TrophiesWindow( 275 position=prtb.get_screen_space_center(), 276 data=info, 277 ) 278 else: 279 bui.getsound('error').play() 280 281 def _on_power_ranking_query_response( 282 self, data: dict[str, Any] | None 283 ) -> None: 284 self._doing_power_ranking_query = False 285 286 # Important: *only* cache this if we requested the current season. 287 if data is not None and data.get('s', None) is None: 288 assert bui.app.classic is not None 289 bui.app.classic.accounts.cache_league_rank_data(data) 290 291 # Always store a copy locally though (even for other seasons). 292 self._league_rank_data = copy.deepcopy(data) 293 self._update_for_league_rank_data(data) 294 295 def _restore_state(self) -> None: 296 pass 297 298 def _update(self, show: bool = False) -> None: 299 plus = bui.app.plus 300 assert plus is not None 301 302 cur_time = bui.apptime() 303 304 # If our account state has changed, refresh our UI. 305 account_state = plus.get_v1_account_state() 306 if account_state != self._account_state: 307 self._account_state = account_state 308 self._save_state() 309 self._refresh() 310 311 # And power ranking too. 312 if not self._doing_power_ranking_query: 313 self._last_power_ranking_query_time = None 314 315 # Send off a new power-ranking query if its been long enough or our 316 # requested season has changed or whatnot. 317 if not self._doing_power_ranking_query and ( 318 self._last_power_ranking_query_time is None 319 or cur_time - self._last_power_ranking_query_time > 30.0 320 ): 321 try: 322 if show: 323 bui.textwidget(edit=self._league_title_text, text='') 324 bui.textwidget(edit=self._league_text, text='') 325 bui.textwidget(edit=self._league_number_text, text='') 326 bui.textwidget( 327 edit=self._your_power_ranking_text, 328 text=bui.Lstr( 329 value='${A}...', 330 subs=[('${A}', bui.Lstr(resource='loadingText'))], 331 ), 332 ) 333 bui.textwidget(edit=self._to_ranked_text, text='') 334 bui.textwidget(edit=self._power_ranking_rank_text, text='') 335 bui.textwidget(edit=self._season_ends_text, text='') 336 bui.textwidget(edit=self._trophy_counts_reset_text, text='') 337 except Exception: 338 logging.exception('Error showing updated rank info.') 339 340 self._last_power_ranking_query_time = cur_time 341 self._doing_power_ranking_query = True 342 plus.power_ranking_query( 343 season=self._requested_season, 344 callback=bui.WeakCall(self._on_power_ranking_query_response), 345 ) 346 347 def _refresh(self) -> None: 348 # pylint: disable=too-many-statements 349 350 plus = bui.app.plus 351 assert plus is not None 352 353 # (re)create the sub-container if need be.. 354 if self._subcontainer is not None: 355 self._subcontainer.delete() 356 self._subcontainer = bui.containerwidget( 357 parent=self._scrollwidget, 358 size=(self._subcontainerwidth, self._subcontainerheight), 359 background=False, 360 ) 361 362 w_parent = self._subcontainer 363 v = self._subcontainerheight - 20 364 365 v -= 0 366 367 h2 = 80 368 v2 = v - 60 369 worth_color = (0.6, 0.6, 0.65) 370 tally_color = (0.5, 0.6, 0.8) 371 spc = 43 372 373 h_offs_tally = 150 374 tally_maxwidth = 120 375 v2 -= 70 376 377 bui.textwidget( 378 parent=w_parent, 379 position=(h2 - 60, v2 + 106), 380 size=(0, 0), 381 flatness=1.0, 382 shadow=0.0, 383 text=bui.Lstr(resource='coopSelectWindow.pointsText'), 384 h_align='left', 385 v_align='center', 386 scale=0.8, 387 color=(1, 1, 1, 0.3), 388 maxwidth=200, 389 ) 390 391 self._power_ranking_achievements_button = bui.buttonwidget( 392 parent=w_parent, 393 position=(h2 - 60, v2 + 10), 394 size=(200, 80), 395 icon=bui.gettexture('achievementsIcon'), 396 autoselect=True, 397 on_activate_call=bui.WeakCall(self._on_achievements_press), 398 up_widget=self._back_button, 399 left_widget=self._back_button, 400 color=(0.5, 0.5, 0.6), 401 textcolor=(0.7, 0.7, 0.8), 402 label='', 403 ) 404 405 self._power_ranking_achievement_total_text = bui.textwidget( 406 parent=w_parent, 407 position=(h2 + h_offs_tally, v2 + 45), 408 size=(0, 0), 409 flatness=1.0, 410 shadow=0.0, 411 text='-', 412 h_align='left', 413 v_align='center', 414 scale=0.8, 415 color=tally_color, 416 maxwidth=tally_maxwidth, 417 ) 418 419 v2 -= 80 420 421 self._power_ranking_trophies_button = bui.buttonwidget( 422 parent=w_parent, 423 position=(h2 - 60, v2 + 10), 424 size=(200, 80), 425 icon=bui.gettexture('medalSilver'), 426 autoselect=True, 427 on_activate_call=bui.WeakCall(self._on_trophies_press), 428 left_widget=self._back_button, 429 color=(0.5, 0.5, 0.6), 430 textcolor=(0.7, 0.7, 0.8), 431 label='', 432 ) 433 self._power_ranking_trophies_total_text = bui.textwidget( 434 parent=w_parent, 435 position=(h2 + h_offs_tally, v2 + 45), 436 size=(0, 0), 437 flatness=1.0, 438 shadow=0.0, 439 text='-', 440 h_align='left', 441 v_align='center', 442 scale=0.8, 443 color=tally_color, 444 maxwidth=tally_maxwidth, 445 ) 446 447 v2 -= 100 448 449 bui.textwidget( 450 parent=w_parent, 451 position=(h2 - 60, v2 + 86), 452 size=(0, 0), 453 flatness=1.0, 454 shadow=0.0, 455 text=bui.Lstr(resource='coopSelectWindow.multipliersText'), 456 h_align='left', 457 v_align='center', 458 scale=0.8, 459 color=(1, 1, 1, 0.3), 460 maxwidth=200, 461 ) 462 463 self._activity_mult_button: bui.Widget | None 464 if plus.get_v1_account_misc_read_val('act', False): 465 self._activity_mult_button = bui.buttonwidget( 466 parent=w_parent, 467 position=(h2 - 60, v2 + 10), 468 size=(200, 60), 469 icon=bui.gettexture('heart'), 470 icon_color=(0.5, 0, 0.5), 471 label=bui.Lstr(resource='coopSelectWindow.activityText'), 472 autoselect=True, 473 on_activate_call=bui.WeakCall(self._on_activity_mult_press), 474 left_widget=self._back_button, 475 color=(0.5, 0.5, 0.6), 476 textcolor=(0.7, 0.7, 0.8), 477 ) 478 479 self._activity_mult_text = bui.textwidget( 480 parent=w_parent, 481 position=(h2 + h_offs_tally, v2 + 40), 482 size=(0, 0), 483 flatness=1.0, 484 shadow=0.0, 485 text='-', 486 h_align='left', 487 v_align='center', 488 scale=0.8, 489 color=tally_color, 490 maxwidth=tally_maxwidth, 491 ) 492 v2 -= 65 493 else: 494 self._activity_mult_button = None 495 496 self._pro_mult_button = bui.buttonwidget( 497 parent=w_parent, 498 position=(h2 - 60, v2 + 10), 499 size=(200, 60), 500 icon=bui.gettexture('logo'), 501 icon_color=(0.3, 0, 0.3), 502 label=bui.Lstr( 503 resource='store.bombSquadProNameText', 504 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 505 ), 506 autoselect=True, 507 on_activate_call=bui.WeakCall(self._on_pro_mult_press), 508 left_widget=self._back_button, 509 color=(0.5, 0.5, 0.6), 510 textcolor=(0.7, 0.7, 0.8), 511 ) 512 513 self._pro_mult_text = bui.textwidget( 514 parent=w_parent, 515 position=(h2 + h_offs_tally, v2 + 40), 516 size=(0, 0), 517 flatness=1.0, 518 shadow=0.0, 519 text='-', 520 h_align='left', 521 v_align='center', 522 scale=0.8, 523 color=tally_color, 524 maxwidth=tally_maxwidth, 525 ) 526 v2 -= 30 527 528 v2 -= spc 529 bui.textwidget( 530 parent=w_parent, 531 position=(h2 + h_offs_tally - 10 - 40, v2 + 35), 532 size=(0, 0), 533 flatness=1.0, 534 shadow=0.0, 535 text=bui.Lstr(resource='finalScoreText'), 536 h_align='right', 537 v_align='center', 538 scale=0.9, 539 color=worth_color, 540 maxwidth=150, 541 ) 542 self._power_ranking_total_text = bui.textwidget( 543 parent=w_parent, 544 position=(h2 + h_offs_tally - 40, v2 + 35), 545 size=(0, 0), 546 flatness=1.0, 547 shadow=0.0, 548 text='-', 549 h_align='left', 550 v_align='center', 551 scale=0.9, 552 color=tally_color, 553 maxwidth=tally_maxwidth, 554 ) 555 556 self._season_show_text = bui.textwidget( 557 parent=w_parent, 558 position=(390 - 15, v - 20), 559 size=(0, 0), 560 color=(0.6, 0.6, 0.7), 561 maxwidth=200, 562 text=bui.Lstr(resource='showText'), 563 h_align='right', 564 v_align='center', 565 scale=0.8, 566 shadow=0, 567 flatness=1.0, 568 ) 569 570 self._league_title_text = bui.textwidget( 571 parent=w_parent, 572 position=(470, v - 97), 573 size=(0, 0), 574 color=(0.6, 0.6, 0.7), 575 maxwidth=230, 576 text='', 577 h_align='center', 578 v_align='center', 579 scale=0.9, 580 shadow=0, 581 flatness=1.0, 582 ) 583 584 self._league_text_scale = 1.8 585 self._league_text_maxwidth = 210 586 self._league_text = bui.textwidget( 587 parent=w_parent, 588 position=(470, v - 140), 589 size=(0, 0), 590 color=(1, 1, 1), 591 maxwidth=self._league_text_maxwidth, 592 text='-', 593 h_align='center', 594 v_align='center', 595 scale=self._league_text_scale, 596 shadow=1.0, 597 flatness=1.0, 598 ) 599 self._league_number_base_pos = (470, v - 140) 600 self._league_number_text = bui.textwidget( 601 parent=w_parent, 602 position=(470, v - 140), 603 size=(0, 0), 604 color=(1, 1, 1), 605 maxwidth=100, 606 text='', 607 h_align='left', 608 v_align='center', 609 scale=0.8, 610 shadow=1.0, 611 flatness=1.0, 612 ) 613 614 self._your_power_ranking_text = bui.textwidget( 615 parent=w_parent, 616 position=(470, v - 142 - 70), 617 size=(0, 0), 618 color=(0.6, 0.6, 0.7), 619 maxwidth=230, 620 text='', 621 h_align='center', 622 v_align='center', 623 scale=0.9, 624 shadow=0, 625 flatness=1.0, 626 ) 627 628 self._to_ranked_text = bui.textwidget( 629 parent=w_parent, 630 position=(470, v - 250 - 70), 631 size=(0, 0), 632 color=(0.6, 0.6, 0.7), 633 maxwidth=230, 634 text='', 635 h_align='center', 636 v_align='center', 637 scale=0.8, 638 shadow=0, 639 flatness=1.0, 640 ) 641 642 self._power_ranking_rank_text = bui.textwidget( 643 parent=w_parent, 644 position=(473, v - 210 - 70), 645 size=(0, 0), 646 big=False, 647 text='-', 648 h_align='center', 649 v_align='center', 650 scale=1.0, 651 ) 652 653 self._season_ends_text = bui.textwidget( 654 parent=w_parent, 655 position=(470, v - 380), 656 size=(0, 0), 657 color=(0.6, 0.6, 0.6), 658 maxwidth=230, 659 text='', 660 h_align='center', 661 v_align='center', 662 scale=0.9, 663 shadow=0, 664 flatness=1.0, 665 ) 666 self._trophy_counts_reset_text = bui.textwidget( 667 parent=w_parent, 668 position=(470, v - 410), 669 size=(0, 0), 670 color=(0.5, 0.5, 0.5), 671 maxwidth=230, 672 text='Trophy counts will reset next season.', 673 h_align='center', 674 v_align='center', 675 scale=0.8, 676 shadow=0, 677 flatness=1.0, 678 ) 679 680 self._power_ranking_score_widgets = [] 681 682 self._power_ranking_score_v = v - 56 683 684 h = 707 685 v -= 451 686 687 self._see_more_button = bui.buttonwidget( 688 parent=w_parent, 689 label=self._rdict.seeMoreText, 690 position=(h, v), 691 color=(0.5, 0.5, 0.6), 692 textcolor=(0.7, 0.7, 0.8), 693 size=(230, 60), 694 autoselect=True, 695 on_activate_call=bui.WeakCall(self._on_more_press), 696 ) 697 698 def _on_more_press(self) -> None: 699 plus = bui.app.plus 700 assert plus is not None 701 702 our_login_id = plus.get_v1_account_public_login_id() 703 # our_login_id = _bs.get_account_misc_read_val_2( 704 # 'resolvedAccountID', None) 705 if not self._can_do_more_button or our_login_id is None: 706 bui.getsound('error').play() 707 bui.screenmessage( 708 bui.Lstr(resource='unavailableText'), color=(1, 0, 0) 709 ) 710 return 711 if self._season is None: 712 season_str = '' 713 else: 714 season_str = '&season=' + ( 715 'all_time' if self._season == 'a' else self._season 716 ) 717 if self._league_url_arg != '': 718 league_str = '&league=' + self._league_url_arg 719 else: 720 league_str = '' 721 bui.open_url( 722 plus.get_master_server_address() 723 + '/highscores?list=powerRankings&v=2' 724 + league_str 725 + season_str 726 + '&player=' 727 + our_login_id 728 ) 729 730 def _update_for_league_rank_data(self, data: dict[str, Any] | None) -> None: 731 # pylint: disable=too-many-statements 732 # pylint: disable=too-many-branches 733 # pylint: disable=too-many-locals 734 if not self._root_widget: 735 return 736 plus = bui.app.plus 737 assert plus is not None 738 assert bui.app.classic is not None 739 accounts = bui.app.classic.accounts 740 in_top = data is not None and data['rank'] is not None 741 eq_text = self._rdict.powerRankingPointsEqualsText 742 pts_txt = self._rdict.powerRankingPointsText 743 num_text = bui.Lstr(resource='numberText').evaluate() 744 do_percent = False 745 finished_season_unranked = False 746 self._can_do_more_button = True 747 extra_text = '' 748 if plus.get_v1_account_state() != 'signed_in': 749 status_text = ( 750 '(' + bui.Lstr(resource='notSignedInText').evaluate() + ')' 751 ) 752 elif in_top: 753 assert data is not None 754 status_text = num_text.replace('${NUMBER}', str(data['rank'])) 755 elif data is not None: 756 try: 757 # handle old seasons where we didn't wind up ranked 758 # at the end.. 759 if not data['scores']: 760 status_text = ( 761 self._rdict.powerRankingFinishedSeasonUnrankedText 762 ) 763 extra_text = '' 764 finished_season_unranked = True 765 self._can_do_more_button = False 766 else: 767 our_points = accounts.get_league_rank_points(data) 768 progress = float(our_points) / max(1, data['scores'][-1][1]) 769 status_text = str(int(progress * 100.0)) + '%' 770 extra_text = ( 771 '\n' 772 + self._rdict.powerRankingPointsToRankedText.replace( 773 '${CURRENT}', str(our_points) 774 ).replace('${REMAINING}', str(data['scores'][-1][1])) 775 ) 776 do_percent = True 777 except Exception: 778 logging.exception('Error updating power ranking.') 779 status_text = self._rdict.powerRankingNotInTopText.replace( 780 '${NUMBER}', str(data['listSize']) 781 ) 782 extra_text = '' 783 else: 784 status_text = '-' 785 786 self._season = data['s'] if data is not None else None 787 788 v = self._subcontainerheight - 20 789 popup_was_selected = False 790 if self._season_popup_menu is not None: 791 btn = self._season_popup_menu.get_button() 792 assert self._subcontainer 793 if self._subcontainer.get_selected_child() == btn: 794 popup_was_selected = True 795 btn.delete() 796 season_choices = [] 797 season_choices_display = [] 798 did_first = False 799 self._is_current_season = False 800 if data is not None: 801 # build our list of seasons we have available 802 for ssn in data['sl']: 803 season_choices.append(ssn) 804 if ssn != 'a' and not did_first: 805 season_choices_display.append( 806 bui.Lstr( 807 resource='league.currentSeasonText', 808 subs=[('${NUMBER}', ssn)], 809 ) 810 ) 811 did_first = True 812 # if we either did not specify a season or specified the 813 # first, we're looking at the current.. 814 if self._season in [ssn, None]: 815 self._is_current_season = True 816 elif ssn == 'a': 817 season_choices_display.append( 818 bui.Lstr(resource='league.allTimeText') 819 ) 820 else: 821 season_choices_display.append( 822 bui.Lstr( 823 resource='league.seasonText', 824 subs=[('${NUMBER}', ssn)], 825 ) 826 ) 827 assert self._subcontainer 828 self._season_popup_menu = PopupMenu( 829 parent=self._subcontainer, 830 position=(390, v - 45), 831 width=150, 832 button_size=(200, 50), 833 choices=season_choices, 834 on_value_change_call=bui.WeakCall(self._on_season_change), 835 choices_display=season_choices_display, 836 current_choice=self._season, 837 ) 838 if popup_was_selected: 839 bui.containerwidget( 840 edit=self._subcontainer, 841 selected_child=self._season_popup_menu.get_button(), 842 ) 843 bui.widget(edit=self._see_more_button, show_buffer_bottom=100) 844 bui.widget( 845 edit=self._season_popup_menu.get_button(), 846 up_widget=self._back_button, 847 ) 848 bui.widget( 849 edit=self._back_button, 850 down_widget=self._power_ranking_achievements_button, 851 right_widget=self._season_popup_menu.get_button(), 852 ) 853 854 bui.textwidget( 855 edit=self._league_title_text, 856 text='' 857 if self._season == 'a' 858 else bui.Lstr(resource='league.leagueText'), 859 ) 860 861 if data is None: 862 lname = '' 863 lnum = '' 864 lcolor = (1, 1, 1) 865 self._league_url_arg = '' 866 elif self._season == 'a': 867 lname = bui.Lstr(resource='league.allTimeText').evaluate() 868 lnum = '' 869 lcolor = (1, 1, 1) 870 self._league_url_arg = '' 871 else: 872 lnum = ('[' + str(data['l']['i']) + ']') if data['l']['i2'] else '' 873 lname = bui.Lstr( 874 translate=('leagueNames', data['l']['n']) 875 ).evaluate() 876 lcolor = data['l']['c'] 877 self._league_url_arg = ( 878 data['l']['n'] + '_' + str(data['l']['i']) 879 ).lower() 880 881 to_end_string: bui.Lstr | str 882 if data is None or self._season == 'a' or data['se'] is None: 883 to_end_string = '' 884 show_season_end = False 885 else: 886 show_season_end = True 887 days_to_end = data['se'][0] 888 minutes_to_end = data['se'][1] 889 if days_to_end > 0: 890 to_end_string = bui.Lstr( 891 resource='league.seasonEndsDaysText', 892 subs=[('${NUMBER}', str(days_to_end))], 893 ) 894 elif days_to_end == 0 and minutes_to_end >= 60: 895 to_end_string = bui.Lstr( 896 resource='league.seasonEndsHoursText', 897 subs=[('${NUMBER}', str(minutes_to_end // 60))], 898 ) 899 elif days_to_end == 0 and minutes_to_end >= 0: 900 to_end_string = bui.Lstr( 901 resource='league.seasonEndsMinutesText', 902 subs=[('${NUMBER}', str(minutes_to_end))], 903 ) 904 else: 905 to_end_string = bui.Lstr( 906 resource='league.seasonEndedDaysAgoText', 907 subs=[('${NUMBER}', str(-(days_to_end + 1)))], 908 ) 909 910 bui.textwidget(edit=self._season_ends_text, text=to_end_string) 911 bui.textwidget( 912 edit=self._trophy_counts_reset_text, 913 text=bui.Lstr(resource='league.trophyCountsResetText') 914 if self._is_current_season and show_season_end 915 else '', 916 ) 917 918 bui.textwidget(edit=self._league_text, text=lname, color=lcolor) 919 l_text_width = min( 920 self._league_text_maxwidth, 921 bui.get_string_width(lname, suppress_warning=True) 922 * self._league_text_scale, 923 ) 924 bui.textwidget( 925 edit=self._league_number_text, 926 text=lnum, 927 color=lcolor, 928 position=( 929 self._league_number_base_pos[0] + l_text_width * 0.5 + 8, 930 self._league_number_base_pos[1] + 10, 931 ), 932 ) 933 bui.textwidget( 934 edit=self._to_ranked_text, 935 text=bui.Lstr(resource='coopSelectWindow.toRankedText').evaluate() 936 + '' 937 + extra_text 938 if do_percent 939 else '', 940 ) 941 942 bui.textwidget( 943 edit=self._your_power_ranking_text, 944 text=bui.Lstr( 945 resource='rankText', 946 fallback_resource='coopSelectWindow.yourPowerRankingText', 947 ) 948 if (not do_percent) 949 else '', 950 ) 951 952 bui.textwidget( 953 edit=self._power_ranking_rank_text, 954 position=(473, v - 70 - (170 if do_percent else 220)), 955 text=status_text, 956 big=(in_top or do_percent), 957 scale=3.0 958 if (in_top or do_percent) 959 else 0.7 960 if finished_season_unranked 961 else 1.0, 962 ) 963 964 if self._activity_mult_button is not None: 965 if data is None or data['act'] is None: 966 bui.buttonwidget( 967 edit=self._activity_mult_button, 968 textcolor=(0.7, 0.7, 0.8, 0.5), 969 icon_color=(0.5, 0, 0.5, 0.3), 970 ) 971 bui.textwidget(edit=self._activity_mult_text, text=' -') 972 else: 973 bui.buttonwidget( 974 edit=self._activity_mult_button, 975 textcolor=(0.7, 0.7, 0.8, 1.0), 976 icon_color=(0.5, 0, 0.5, 1.0), 977 ) 978 # pylint: disable=consider-using-f-string 979 bui.textwidget( 980 edit=self._activity_mult_text, 981 text='x ' + ('%.2f' % data['act']), 982 ) 983 984 have_pro = False if data is None else data['p'] 985 pro_mult = ( 986 1.0 987 + float( 988 plus.get_v1_account_misc_read_val('proPowerRankingBoost', 0.0) 989 ) 990 * 0.01 991 ) 992 # pylint: disable=consider-using-f-string 993 bui.textwidget( 994 edit=self._pro_mult_text, 995 text=' -' 996 if (data is None or not have_pro) 997 else 'x ' + ('%.2f' % pro_mult), 998 ) 999 bui.buttonwidget( 1000 edit=self._pro_mult_button, 1001 textcolor=(0.7, 0.7, 0.8, (1.0 if have_pro else 0.5)), 1002 icon_color=(0.5, 0, 0.5) if have_pro else (0.5, 0, 0.5, 0.2), 1003 ) 1004 bui.buttonwidget( 1005 edit=self._power_ranking_achievements_button, 1006 label=('' if data is None else str(data['a']) + ' ') 1007 + bui.Lstr(resource='achievementsText').evaluate(), 1008 ) 1009 1010 # for the achievement value, use the number they gave us for 1011 # non-current seasons; otherwise calc our own 1012 total_ach_value = 0 1013 for ach in bui.app.classic.ach.achievements: 1014 if ach.complete: 1015 total_ach_value += ach.power_ranking_value 1016 if self._season != 'a' and not self._is_current_season: 1017 if data is not None and 'at' in data: 1018 total_ach_value = data['at'] 1019 1020 bui.textwidget( 1021 edit=self._power_ranking_achievement_total_text, 1022 text='-' 1023 if data is None 1024 else ('+ ' + pts_txt.replace('${NUMBER}', str(total_ach_value))), 1025 ) 1026 1027 total_trophies_count = accounts.get_league_rank_points( 1028 data, 'trophyCount' 1029 ) 1030 total_trophies_value = accounts.get_league_rank_points(data, 'trophies') 1031 bui.buttonwidget( 1032 edit=self._power_ranking_trophies_button, 1033 label=('' if data is None else str(total_trophies_count) + ' ') 1034 + bui.Lstr(resource='trophiesText').evaluate(), 1035 ) 1036 bui.textwidget( 1037 edit=self._power_ranking_trophies_total_text, 1038 text='-' 1039 if data is None 1040 else ( 1041 '+ ' + pts_txt.replace('${NUMBER}', str(total_trophies_value)) 1042 ), 1043 ) 1044 1045 bui.textwidget( 1046 edit=self._power_ranking_total_text, 1047 text='-' 1048 if data is None 1049 else eq_text.replace( 1050 '${NUMBER}', str(accounts.get_league_rank_points(data)) 1051 ), 1052 ) 1053 for widget in self._power_ranking_score_widgets: 1054 widget.delete() 1055 self._power_ranking_score_widgets = [] 1056 1057 scores = data['scores'] if data is not None else [] 1058 tally_color = (0.5, 0.6, 0.8) 1059 w_parent = self._subcontainer 1060 v2 = self._power_ranking_score_v 1061 1062 for score in scores: 1063 h2 = 680 1064 is_us = score[3] 1065 self._power_ranking_score_widgets.append( 1066 bui.textwidget( 1067 parent=w_parent, 1068 position=(h2 - 20, v2), 1069 size=(0, 0), 1070 color=(1, 1, 1) if is_us else (0.6, 0.6, 0.7), 1071 maxwidth=40, 1072 flatness=1.0, 1073 shadow=0.0, 1074 text=num_text.replace('${NUMBER}', str(score[0])), 1075 h_align='right', 1076 v_align='center', 1077 scale=0.5, 1078 ) 1079 ) 1080 self._power_ranking_score_widgets.append( 1081 bui.textwidget( 1082 parent=w_parent, 1083 position=(h2 + 20, v2), 1084 size=(0, 0), 1085 color=(1, 1, 1) if is_us else tally_color, 1086 maxwidth=60, 1087 text=str(score[1]), 1088 flatness=1.0, 1089 shadow=0.0, 1090 h_align='center', 1091 v_align='center', 1092 scale=0.7, 1093 ) 1094 ) 1095 txt = bui.textwidget( 1096 parent=w_parent, 1097 position=(h2 + 60, v2 - (28 * 0.5) / 0.9), 1098 size=(210 / 0.9, 28), 1099 color=(1, 1, 1) if is_us else (0.6, 0.6, 0.6), 1100 maxwidth=210, 1101 flatness=1.0, 1102 shadow=0.0, 1103 autoselect=True, 1104 selectable=True, 1105 click_activate=True, 1106 text=score[2], 1107 h_align='left', 1108 v_align='center', 1109 scale=0.9, 1110 ) 1111 self._power_ranking_score_widgets.append(txt) 1112 bui.textwidget( 1113 edit=txt, 1114 on_activate_call=bui.Call( 1115 self._show_account_info, score[4], txt 1116 ), 1117 ) 1118 assert self._season_popup_menu is not None 1119 bui.widget( 1120 edit=txt, left_widget=self._season_popup_menu.get_button() 1121 ) 1122 v2 -= 28 1123 1124 def _show_account_info( 1125 self, account_id: str, textwidget: bui.Widget 1126 ) -> None: 1127 from bauiv1lib.account import viewer 1128 1129 bui.getsound('swish').play() 1130 viewer.AccountViewerWindow( 1131 account_id=account_id, position=textwidget.get_screen_space_center() 1132 ) 1133 1134 def _on_season_change(self, value: str) -> None: 1135 self._requested_season = value 1136 self._last_power_ranking_query_time = None # make sure we update asap 1137 self._update(show=True) 1138 1139 def _save_state(self) -> None: 1140 pass 1141 1142 def _back(self) -> None: 1143 from bauiv1lib.coop.browser import CoopBrowserWindow 1144 1145 self._save_state() 1146 bui.containerwidget( 1147 edit=self._root_widget, transition=self._transition_out 1148 ) 1149 if not self._modal: 1150 assert bui.app.classic is not None 1151 bui.app.ui_v1.set_main_menu_window( 1152 CoopBrowserWindow(transition='in_left').get_root_widget() 1153 )
class
LeagueRankWindow(bauiv1._uitypes.Window):
20class LeagueRankWindow(bui.Window): 21 """Window for showing league rank.""" 22 23 def __init__( 24 self, 25 transition: str = 'in_right', 26 modal: bool = False, 27 origin_widget: bui.Widget | None = None, 28 ): 29 # pylint: disable=too-many-statements 30 plus = bui.app.plus 31 assert plus is not None 32 33 bui.set_analytics_screen('League Rank Window') 34 35 self._league_rank_data: dict[str, Any] | None = None 36 self._modal = modal 37 38 self._power_ranking_achievements_button: bui.Widget | None = None 39 self._pro_mult_button: bui.Widget | None = None 40 self._power_ranking_trophies_button: bui.Widget | None = None 41 self._league_title_text: bui.Widget | None = None 42 self._league_text: bui.Widget | None = None 43 self._league_number_text: bui.Widget | None = None 44 self._your_power_ranking_text: bui.Widget | None = None 45 self._season_ends_text: bui.Widget | None = None 46 self._power_ranking_rank_text: bui.Widget | None = None 47 self._to_ranked_text: bui.Widget | None = None 48 self._trophy_counts_reset_text: bui.Widget | None = None 49 50 # If they provided an origin-widget, scale up from that. 51 scale_origin: tuple[float, float] | None 52 if origin_widget is not None: 53 self._transition_out = 'out_scale' 54 scale_origin = origin_widget.get_screen_space_center() 55 transition = 'in_scale' 56 else: 57 self._transition_out = 'out_right' 58 scale_origin = None 59 60 assert bui.app.classic is not None 61 uiscale = bui.app.ui_v1.uiscale 62 self._width = 1320 if uiscale is bui.UIScale.SMALL else 1120 63 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 64 self._height = ( 65 657 66 if uiscale is bui.UIScale.SMALL 67 else 710 68 if uiscale is bui.UIScale.MEDIUM 69 else 800 70 ) 71 self._r = 'coopSelectWindow' 72 self._rdict = bui.app.lang.get_resource(self._r) 73 top_extra = 20 if uiscale is bui.UIScale.SMALL else 0 74 75 self._league_url_arg = '' 76 77 self._is_current_season = False 78 self._can_do_more_button = True 79 80 super().__init__( 81 root_widget=bui.containerwidget( 82 size=(self._width, self._height + top_extra), 83 stack_offset=(0, -15) 84 if uiscale is bui.UIScale.SMALL 85 else (0, 10) 86 if uiscale is bui.UIScale.MEDIUM 87 else (0, 0), 88 transition=transition, 89 scale_origin_stack_offset=scale_origin, 90 scale=( 91 1.2 92 if uiscale is bui.UIScale.SMALL 93 else 0.93 94 if uiscale is bui.UIScale.MEDIUM 95 else 0.8 96 ), 97 ) 98 ) 99 100 self._back_button = btn = bui.buttonwidget( 101 parent=self._root_widget, 102 position=( 103 75 + x_inset, 104 self._height - 87 - (4 if uiscale is bui.UIScale.SMALL else 0), 105 ), 106 size=(120, 60), 107 scale=1.2, 108 autoselect=True, 109 label=bui.Lstr(resource='doneText' if self._modal else 'backText'), 110 button_type=None if self._modal else 'back', 111 on_activate_call=self._back, 112 ) 113 114 self._title_text = bui.textwidget( 115 parent=self._root_widget, 116 position=(self._width * 0.5, self._height - 56), 117 size=(0, 0), 118 text=bui.Lstr( 119 resource='league.leagueRankText', 120 fallback_resource='coopSelectWindow.powerRankingText', 121 ), 122 h_align='center', 123 color=bui.app.ui_v1.title_color, 124 scale=1.4, 125 maxwidth=600, 126 v_align='center', 127 ) 128 129 bui.buttonwidget( 130 edit=btn, 131 button_type='backSmall', 132 position=( 133 75 + x_inset, 134 self._height - 87 - (2 if uiscale is bui.UIScale.SMALL else 0), 135 ), 136 size=(60, 55), 137 label=bui.charstr(bui.SpecialChar.BACK), 138 ) 139 140 self._scroll_width = self._width - (130 + 2 * x_inset) 141 self._scroll_height = self._height - 160 142 self._scrollwidget = bui.scrollwidget( 143 parent=self._root_widget, 144 highlight=False, 145 position=(65 + x_inset, 70), 146 size=(self._scroll_width, self._scroll_height), 147 center_small_content=True, 148 ) 149 bui.widget(edit=self._scrollwidget, autoselect=True) 150 bui.containerwidget(edit=self._scrollwidget, claims_left_right=True) 151 bui.containerwidget( 152 edit=self._root_widget, 153 cancel_button=self._back_button, 154 selected_child=self._back_button, 155 ) 156 157 self._last_power_ranking_query_time: float | None = None 158 self._doing_power_ranking_query = False 159 160 self._subcontainer: bui.Widget | None = None 161 self._subcontainerwidth = 800 162 self._subcontainerheight = 483 163 self._power_ranking_score_widgets: list[bui.Widget] = [] 164 165 self._season_popup_menu: PopupMenu | None = None 166 self._requested_season: str | None = None 167 self._season: str | None = None 168 169 # take note of our account state; we'll refresh later if this changes 170 self._account_state = plus.get_v1_account_state() 171 172 self._refresh() 173 self._restore_state() 174 175 # if we've got cached power-ranking data already, display it 176 assert bui.app.classic is not None 177 info = bui.app.classic.accounts.get_cached_league_rank_data() 178 if info is not None: 179 self._update_for_league_rank_data(info) 180 181 self._update_timer = bui.AppTimer( 182 1.0, bui.WeakCall(self._update), repeat=True 183 ) 184 self._update(show=info is None) 185 186 def _on_achievements_press(self) -> None: 187 from bauiv1lib import achievements 188 189 # only allow this for all-time or the current season 190 # (we currently don't keep specific achievement data for old seasons) 191 if self._season == 'a' or self._is_current_season: 192 prab = self._power_ranking_achievements_button 193 assert prab is not None 194 achievements.AchievementsWindow( 195 position=prab.get_screen_space_center() 196 ) 197 else: 198 bui.screenmessage( 199 bui.Lstr( 200 resource='achievementsUnavailableForOldSeasonsText', 201 fallback_resource='unavailableText', 202 ), 203 color=(1, 0, 0), 204 ) 205 bui.getsound('error').play() 206 207 def _on_activity_mult_press(self) -> None: 208 from bauiv1lib import confirm 209 210 plus = bui.app.plus 211 assert plus is not None 212 213 txt = bui.Lstr( 214 resource='coopSelectWindow.activenessAllTimeInfoText' 215 if self._season == 'a' 216 else 'coopSelectWindow.activenessInfoText', 217 subs=[ 218 ( 219 '${MAX}', 220 str( 221 plus.get_v1_account_misc_read_val('activenessMax', 1.0) 222 ), 223 ) 224 ], 225 ) 226 confirm.ConfirmWindow( 227 txt, 228 cancel_button=False, 229 width=460, 230 height=150, 231 origin_widget=self._activity_mult_button, 232 ) 233 234 def _on_pro_mult_press(self) -> None: 235 from bauiv1lib import confirm 236 237 plus = bui.app.plus 238 assert plus is not None 239 240 txt = bui.Lstr( 241 resource='coopSelectWindow.proMultInfoText', 242 subs=[ 243 ( 244 '${PERCENT}', 245 str( 246 plus.get_v1_account_misc_read_val( 247 'proPowerRankingBoost', 10 248 ) 249 ), 250 ), 251 ( 252 '${PRO}', 253 bui.Lstr( 254 resource='store.bombSquadProNameText', 255 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 256 ), 257 ), 258 ], 259 ) 260 confirm.ConfirmWindow( 261 txt, 262 cancel_button=False, 263 width=460, 264 height=130, 265 origin_widget=self._pro_mult_button, 266 ) 267 268 def _on_trophies_press(self) -> None: 269 from bauiv1lib.trophies import TrophiesWindow 270 271 info = self._league_rank_data 272 if info is not None: 273 prtb = self._power_ranking_trophies_button 274 assert prtb is not None 275 TrophiesWindow( 276 position=prtb.get_screen_space_center(), 277 data=info, 278 ) 279 else: 280 bui.getsound('error').play() 281 282 def _on_power_ranking_query_response( 283 self, data: dict[str, Any] | None 284 ) -> None: 285 self._doing_power_ranking_query = False 286 287 # Important: *only* cache this if we requested the current season. 288 if data is not None and data.get('s', None) is None: 289 assert bui.app.classic is not None 290 bui.app.classic.accounts.cache_league_rank_data(data) 291 292 # Always store a copy locally though (even for other seasons). 293 self._league_rank_data = copy.deepcopy(data) 294 self._update_for_league_rank_data(data) 295 296 def _restore_state(self) -> None: 297 pass 298 299 def _update(self, show: bool = False) -> None: 300 plus = bui.app.plus 301 assert plus is not None 302 303 cur_time = bui.apptime() 304 305 # If our account state has changed, refresh our UI. 306 account_state = plus.get_v1_account_state() 307 if account_state != self._account_state: 308 self._account_state = account_state 309 self._save_state() 310 self._refresh() 311 312 # And power ranking too. 313 if not self._doing_power_ranking_query: 314 self._last_power_ranking_query_time = None 315 316 # Send off a new power-ranking query if its been long enough or our 317 # requested season has changed or whatnot. 318 if not self._doing_power_ranking_query and ( 319 self._last_power_ranking_query_time is None 320 or cur_time - self._last_power_ranking_query_time > 30.0 321 ): 322 try: 323 if show: 324 bui.textwidget(edit=self._league_title_text, text='') 325 bui.textwidget(edit=self._league_text, text='') 326 bui.textwidget(edit=self._league_number_text, text='') 327 bui.textwidget( 328 edit=self._your_power_ranking_text, 329 text=bui.Lstr( 330 value='${A}...', 331 subs=[('${A}', bui.Lstr(resource='loadingText'))], 332 ), 333 ) 334 bui.textwidget(edit=self._to_ranked_text, text='') 335 bui.textwidget(edit=self._power_ranking_rank_text, text='') 336 bui.textwidget(edit=self._season_ends_text, text='') 337 bui.textwidget(edit=self._trophy_counts_reset_text, text='') 338 except Exception: 339 logging.exception('Error showing updated rank info.') 340 341 self._last_power_ranking_query_time = cur_time 342 self._doing_power_ranking_query = True 343 plus.power_ranking_query( 344 season=self._requested_season, 345 callback=bui.WeakCall(self._on_power_ranking_query_response), 346 ) 347 348 def _refresh(self) -> None: 349 # pylint: disable=too-many-statements 350 351 plus = bui.app.plus 352 assert plus is not None 353 354 # (re)create the sub-container if need be.. 355 if self._subcontainer is not None: 356 self._subcontainer.delete() 357 self._subcontainer = bui.containerwidget( 358 parent=self._scrollwidget, 359 size=(self._subcontainerwidth, self._subcontainerheight), 360 background=False, 361 ) 362 363 w_parent = self._subcontainer 364 v = self._subcontainerheight - 20 365 366 v -= 0 367 368 h2 = 80 369 v2 = v - 60 370 worth_color = (0.6, 0.6, 0.65) 371 tally_color = (0.5, 0.6, 0.8) 372 spc = 43 373 374 h_offs_tally = 150 375 tally_maxwidth = 120 376 v2 -= 70 377 378 bui.textwidget( 379 parent=w_parent, 380 position=(h2 - 60, v2 + 106), 381 size=(0, 0), 382 flatness=1.0, 383 shadow=0.0, 384 text=bui.Lstr(resource='coopSelectWindow.pointsText'), 385 h_align='left', 386 v_align='center', 387 scale=0.8, 388 color=(1, 1, 1, 0.3), 389 maxwidth=200, 390 ) 391 392 self._power_ranking_achievements_button = bui.buttonwidget( 393 parent=w_parent, 394 position=(h2 - 60, v2 + 10), 395 size=(200, 80), 396 icon=bui.gettexture('achievementsIcon'), 397 autoselect=True, 398 on_activate_call=bui.WeakCall(self._on_achievements_press), 399 up_widget=self._back_button, 400 left_widget=self._back_button, 401 color=(0.5, 0.5, 0.6), 402 textcolor=(0.7, 0.7, 0.8), 403 label='', 404 ) 405 406 self._power_ranking_achievement_total_text = bui.textwidget( 407 parent=w_parent, 408 position=(h2 + h_offs_tally, v2 + 45), 409 size=(0, 0), 410 flatness=1.0, 411 shadow=0.0, 412 text='-', 413 h_align='left', 414 v_align='center', 415 scale=0.8, 416 color=tally_color, 417 maxwidth=tally_maxwidth, 418 ) 419 420 v2 -= 80 421 422 self._power_ranking_trophies_button = bui.buttonwidget( 423 parent=w_parent, 424 position=(h2 - 60, v2 + 10), 425 size=(200, 80), 426 icon=bui.gettexture('medalSilver'), 427 autoselect=True, 428 on_activate_call=bui.WeakCall(self._on_trophies_press), 429 left_widget=self._back_button, 430 color=(0.5, 0.5, 0.6), 431 textcolor=(0.7, 0.7, 0.8), 432 label='', 433 ) 434 self._power_ranking_trophies_total_text = bui.textwidget( 435 parent=w_parent, 436 position=(h2 + h_offs_tally, v2 + 45), 437 size=(0, 0), 438 flatness=1.0, 439 shadow=0.0, 440 text='-', 441 h_align='left', 442 v_align='center', 443 scale=0.8, 444 color=tally_color, 445 maxwidth=tally_maxwidth, 446 ) 447 448 v2 -= 100 449 450 bui.textwidget( 451 parent=w_parent, 452 position=(h2 - 60, v2 + 86), 453 size=(0, 0), 454 flatness=1.0, 455 shadow=0.0, 456 text=bui.Lstr(resource='coopSelectWindow.multipliersText'), 457 h_align='left', 458 v_align='center', 459 scale=0.8, 460 color=(1, 1, 1, 0.3), 461 maxwidth=200, 462 ) 463 464 self._activity_mult_button: bui.Widget | None 465 if plus.get_v1_account_misc_read_val('act', False): 466 self._activity_mult_button = bui.buttonwidget( 467 parent=w_parent, 468 position=(h2 - 60, v2 + 10), 469 size=(200, 60), 470 icon=bui.gettexture('heart'), 471 icon_color=(0.5, 0, 0.5), 472 label=bui.Lstr(resource='coopSelectWindow.activityText'), 473 autoselect=True, 474 on_activate_call=bui.WeakCall(self._on_activity_mult_press), 475 left_widget=self._back_button, 476 color=(0.5, 0.5, 0.6), 477 textcolor=(0.7, 0.7, 0.8), 478 ) 479 480 self._activity_mult_text = bui.textwidget( 481 parent=w_parent, 482 position=(h2 + h_offs_tally, v2 + 40), 483 size=(0, 0), 484 flatness=1.0, 485 shadow=0.0, 486 text='-', 487 h_align='left', 488 v_align='center', 489 scale=0.8, 490 color=tally_color, 491 maxwidth=tally_maxwidth, 492 ) 493 v2 -= 65 494 else: 495 self._activity_mult_button = None 496 497 self._pro_mult_button = bui.buttonwidget( 498 parent=w_parent, 499 position=(h2 - 60, v2 + 10), 500 size=(200, 60), 501 icon=bui.gettexture('logo'), 502 icon_color=(0.3, 0, 0.3), 503 label=bui.Lstr( 504 resource='store.bombSquadProNameText', 505 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 506 ), 507 autoselect=True, 508 on_activate_call=bui.WeakCall(self._on_pro_mult_press), 509 left_widget=self._back_button, 510 color=(0.5, 0.5, 0.6), 511 textcolor=(0.7, 0.7, 0.8), 512 ) 513 514 self._pro_mult_text = bui.textwidget( 515 parent=w_parent, 516 position=(h2 + h_offs_tally, v2 + 40), 517 size=(0, 0), 518 flatness=1.0, 519 shadow=0.0, 520 text='-', 521 h_align='left', 522 v_align='center', 523 scale=0.8, 524 color=tally_color, 525 maxwidth=tally_maxwidth, 526 ) 527 v2 -= 30 528 529 v2 -= spc 530 bui.textwidget( 531 parent=w_parent, 532 position=(h2 + h_offs_tally - 10 - 40, v2 + 35), 533 size=(0, 0), 534 flatness=1.0, 535 shadow=0.0, 536 text=bui.Lstr(resource='finalScoreText'), 537 h_align='right', 538 v_align='center', 539 scale=0.9, 540 color=worth_color, 541 maxwidth=150, 542 ) 543 self._power_ranking_total_text = bui.textwidget( 544 parent=w_parent, 545 position=(h2 + h_offs_tally - 40, v2 + 35), 546 size=(0, 0), 547 flatness=1.0, 548 shadow=0.0, 549 text='-', 550 h_align='left', 551 v_align='center', 552 scale=0.9, 553 color=tally_color, 554 maxwidth=tally_maxwidth, 555 ) 556 557 self._season_show_text = bui.textwidget( 558 parent=w_parent, 559 position=(390 - 15, v - 20), 560 size=(0, 0), 561 color=(0.6, 0.6, 0.7), 562 maxwidth=200, 563 text=bui.Lstr(resource='showText'), 564 h_align='right', 565 v_align='center', 566 scale=0.8, 567 shadow=0, 568 flatness=1.0, 569 ) 570 571 self._league_title_text = bui.textwidget( 572 parent=w_parent, 573 position=(470, v - 97), 574 size=(0, 0), 575 color=(0.6, 0.6, 0.7), 576 maxwidth=230, 577 text='', 578 h_align='center', 579 v_align='center', 580 scale=0.9, 581 shadow=0, 582 flatness=1.0, 583 ) 584 585 self._league_text_scale = 1.8 586 self._league_text_maxwidth = 210 587 self._league_text = bui.textwidget( 588 parent=w_parent, 589 position=(470, v - 140), 590 size=(0, 0), 591 color=(1, 1, 1), 592 maxwidth=self._league_text_maxwidth, 593 text='-', 594 h_align='center', 595 v_align='center', 596 scale=self._league_text_scale, 597 shadow=1.0, 598 flatness=1.0, 599 ) 600 self._league_number_base_pos = (470, v - 140) 601 self._league_number_text = bui.textwidget( 602 parent=w_parent, 603 position=(470, v - 140), 604 size=(0, 0), 605 color=(1, 1, 1), 606 maxwidth=100, 607 text='', 608 h_align='left', 609 v_align='center', 610 scale=0.8, 611 shadow=1.0, 612 flatness=1.0, 613 ) 614 615 self._your_power_ranking_text = bui.textwidget( 616 parent=w_parent, 617 position=(470, v - 142 - 70), 618 size=(0, 0), 619 color=(0.6, 0.6, 0.7), 620 maxwidth=230, 621 text='', 622 h_align='center', 623 v_align='center', 624 scale=0.9, 625 shadow=0, 626 flatness=1.0, 627 ) 628 629 self._to_ranked_text = bui.textwidget( 630 parent=w_parent, 631 position=(470, v - 250 - 70), 632 size=(0, 0), 633 color=(0.6, 0.6, 0.7), 634 maxwidth=230, 635 text='', 636 h_align='center', 637 v_align='center', 638 scale=0.8, 639 shadow=0, 640 flatness=1.0, 641 ) 642 643 self._power_ranking_rank_text = bui.textwidget( 644 parent=w_parent, 645 position=(473, v - 210 - 70), 646 size=(0, 0), 647 big=False, 648 text='-', 649 h_align='center', 650 v_align='center', 651 scale=1.0, 652 ) 653 654 self._season_ends_text = bui.textwidget( 655 parent=w_parent, 656 position=(470, v - 380), 657 size=(0, 0), 658 color=(0.6, 0.6, 0.6), 659 maxwidth=230, 660 text='', 661 h_align='center', 662 v_align='center', 663 scale=0.9, 664 shadow=0, 665 flatness=1.0, 666 ) 667 self._trophy_counts_reset_text = bui.textwidget( 668 parent=w_parent, 669 position=(470, v - 410), 670 size=(0, 0), 671 color=(0.5, 0.5, 0.5), 672 maxwidth=230, 673 text='Trophy counts will reset next season.', 674 h_align='center', 675 v_align='center', 676 scale=0.8, 677 shadow=0, 678 flatness=1.0, 679 ) 680 681 self._power_ranking_score_widgets = [] 682 683 self._power_ranking_score_v = v - 56 684 685 h = 707 686 v -= 451 687 688 self._see_more_button = bui.buttonwidget( 689 parent=w_parent, 690 label=self._rdict.seeMoreText, 691 position=(h, v), 692 color=(0.5, 0.5, 0.6), 693 textcolor=(0.7, 0.7, 0.8), 694 size=(230, 60), 695 autoselect=True, 696 on_activate_call=bui.WeakCall(self._on_more_press), 697 ) 698 699 def _on_more_press(self) -> None: 700 plus = bui.app.plus 701 assert plus is not None 702 703 our_login_id = plus.get_v1_account_public_login_id() 704 # our_login_id = _bs.get_account_misc_read_val_2( 705 # 'resolvedAccountID', None) 706 if not self._can_do_more_button or our_login_id is None: 707 bui.getsound('error').play() 708 bui.screenmessage( 709 bui.Lstr(resource='unavailableText'), color=(1, 0, 0) 710 ) 711 return 712 if self._season is None: 713 season_str = '' 714 else: 715 season_str = '&season=' + ( 716 'all_time' if self._season == 'a' else self._season 717 ) 718 if self._league_url_arg != '': 719 league_str = '&league=' + self._league_url_arg 720 else: 721 league_str = '' 722 bui.open_url( 723 plus.get_master_server_address() 724 + '/highscores?list=powerRankings&v=2' 725 + league_str 726 + season_str 727 + '&player=' 728 + our_login_id 729 ) 730 731 def _update_for_league_rank_data(self, data: dict[str, Any] | None) -> None: 732 # pylint: disable=too-many-statements 733 # pylint: disable=too-many-branches 734 # pylint: disable=too-many-locals 735 if not self._root_widget: 736 return 737 plus = bui.app.plus 738 assert plus is not None 739 assert bui.app.classic is not None 740 accounts = bui.app.classic.accounts 741 in_top = data is not None and data['rank'] is not None 742 eq_text = self._rdict.powerRankingPointsEqualsText 743 pts_txt = self._rdict.powerRankingPointsText 744 num_text = bui.Lstr(resource='numberText').evaluate() 745 do_percent = False 746 finished_season_unranked = False 747 self._can_do_more_button = True 748 extra_text = '' 749 if plus.get_v1_account_state() != 'signed_in': 750 status_text = ( 751 '(' + bui.Lstr(resource='notSignedInText').evaluate() + ')' 752 ) 753 elif in_top: 754 assert data is not None 755 status_text = num_text.replace('${NUMBER}', str(data['rank'])) 756 elif data is not None: 757 try: 758 # handle old seasons where we didn't wind up ranked 759 # at the end.. 760 if not data['scores']: 761 status_text = ( 762 self._rdict.powerRankingFinishedSeasonUnrankedText 763 ) 764 extra_text = '' 765 finished_season_unranked = True 766 self._can_do_more_button = False 767 else: 768 our_points = accounts.get_league_rank_points(data) 769 progress = float(our_points) / max(1, data['scores'][-1][1]) 770 status_text = str(int(progress * 100.0)) + '%' 771 extra_text = ( 772 '\n' 773 + self._rdict.powerRankingPointsToRankedText.replace( 774 '${CURRENT}', str(our_points) 775 ).replace('${REMAINING}', str(data['scores'][-1][1])) 776 ) 777 do_percent = True 778 except Exception: 779 logging.exception('Error updating power ranking.') 780 status_text = self._rdict.powerRankingNotInTopText.replace( 781 '${NUMBER}', str(data['listSize']) 782 ) 783 extra_text = '' 784 else: 785 status_text = '-' 786 787 self._season = data['s'] if data is not None else None 788 789 v = self._subcontainerheight - 20 790 popup_was_selected = False 791 if self._season_popup_menu is not None: 792 btn = self._season_popup_menu.get_button() 793 assert self._subcontainer 794 if self._subcontainer.get_selected_child() == btn: 795 popup_was_selected = True 796 btn.delete() 797 season_choices = [] 798 season_choices_display = [] 799 did_first = False 800 self._is_current_season = False 801 if data is not None: 802 # build our list of seasons we have available 803 for ssn in data['sl']: 804 season_choices.append(ssn) 805 if ssn != 'a' and not did_first: 806 season_choices_display.append( 807 bui.Lstr( 808 resource='league.currentSeasonText', 809 subs=[('${NUMBER}', ssn)], 810 ) 811 ) 812 did_first = True 813 # if we either did not specify a season or specified the 814 # first, we're looking at the current.. 815 if self._season in [ssn, None]: 816 self._is_current_season = True 817 elif ssn == 'a': 818 season_choices_display.append( 819 bui.Lstr(resource='league.allTimeText') 820 ) 821 else: 822 season_choices_display.append( 823 bui.Lstr( 824 resource='league.seasonText', 825 subs=[('${NUMBER}', ssn)], 826 ) 827 ) 828 assert self._subcontainer 829 self._season_popup_menu = PopupMenu( 830 parent=self._subcontainer, 831 position=(390, v - 45), 832 width=150, 833 button_size=(200, 50), 834 choices=season_choices, 835 on_value_change_call=bui.WeakCall(self._on_season_change), 836 choices_display=season_choices_display, 837 current_choice=self._season, 838 ) 839 if popup_was_selected: 840 bui.containerwidget( 841 edit=self._subcontainer, 842 selected_child=self._season_popup_menu.get_button(), 843 ) 844 bui.widget(edit=self._see_more_button, show_buffer_bottom=100) 845 bui.widget( 846 edit=self._season_popup_menu.get_button(), 847 up_widget=self._back_button, 848 ) 849 bui.widget( 850 edit=self._back_button, 851 down_widget=self._power_ranking_achievements_button, 852 right_widget=self._season_popup_menu.get_button(), 853 ) 854 855 bui.textwidget( 856 edit=self._league_title_text, 857 text='' 858 if self._season == 'a' 859 else bui.Lstr(resource='league.leagueText'), 860 ) 861 862 if data is None: 863 lname = '' 864 lnum = '' 865 lcolor = (1, 1, 1) 866 self._league_url_arg = '' 867 elif self._season == 'a': 868 lname = bui.Lstr(resource='league.allTimeText').evaluate() 869 lnum = '' 870 lcolor = (1, 1, 1) 871 self._league_url_arg = '' 872 else: 873 lnum = ('[' + str(data['l']['i']) + ']') if data['l']['i2'] else '' 874 lname = bui.Lstr( 875 translate=('leagueNames', data['l']['n']) 876 ).evaluate() 877 lcolor = data['l']['c'] 878 self._league_url_arg = ( 879 data['l']['n'] + '_' + str(data['l']['i']) 880 ).lower() 881 882 to_end_string: bui.Lstr | str 883 if data is None or self._season == 'a' or data['se'] is None: 884 to_end_string = '' 885 show_season_end = False 886 else: 887 show_season_end = True 888 days_to_end = data['se'][0] 889 minutes_to_end = data['se'][1] 890 if days_to_end > 0: 891 to_end_string = bui.Lstr( 892 resource='league.seasonEndsDaysText', 893 subs=[('${NUMBER}', str(days_to_end))], 894 ) 895 elif days_to_end == 0 and minutes_to_end >= 60: 896 to_end_string = bui.Lstr( 897 resource='league.seasonEndsHoursText', 898 subs=[('${NUMBER}', str(minutes_to_end // 60))], 899 ) 900 elif days_to_end == 0 and minutes_to_end >= 0: 901 to_end_string = bui.Lstr( 902 resource='league.seasonEndsMinutesText', 903 subs=[('${NUMBER}', str(minutes_to_end))], 904 ) 905 else: 906 to_end_string = bui.Lstr( 907 resource='league.seasonEndedDaysAgoText', 908 subs=[('${NUMBER}', str(-(days_to_end + 1)))], 909 ) 910 911 bui.textwidget(edit=self._season_ends_text, text=to_end_string) 912 bui.textwidget( 913 edit=self._trophy_counts_reset_text, 914 text=bui.Lstr(resource='league.trophyCountsResetText') 915 if self._is_current_season and show_season_end 916 else '', 917 ) 918 919 bui.textwidget(edit=self._league_text, text=lname, color=lcolor) 920 l_text_width = min( 921 self._league_text_maxwidth, 922 bui.get_string_width(lname, suppress_warning=True) 923 * self._league_text_scale, 924 ) 925 bui.textwidget( 926 edit=self._league_number_text, 927 text=lnum, 928 color=lcolor, 929 position=( 930 self._league_number_base_pos[0] + l_text_width * 0.5 + 8, 931 self._league_number_base_pos[1] + 10, 932 ), 933 ) 934 bui.textwidget( 935 edit=self._to_ranked_text, 936 text=bui.Lstr(resource='coopSelectWindow.toRankedText').evaluate() 937 + '' 938 + extra_text 939 if do_percent 940 else '', 941 ) 942 943 bui.textwidget( 944 edit=self._your_power_ranking_text, 945 text=bui.Lstr( 946 resource='rankText', 947 fallback_resource='coopSelectWindow.yourPowerRankingText', 948 ) 949 if (not do_percent) 950 else '', 951 ) 952 953 bui.textwidget( 954 edit=self._power_ranking_rank_text, 955 position=(473, v - 70 - (170 if do_percent else 220)), 956 text=status_text, 957 big=(in_top or do_percent), 958 scale=3.0 959 if (in_top or do_percent) 960 else 0.7 961 if finished_season_unranked 962 else 1.0, 963 ) 964 965 if self._activity_mult_button is not None: 966 if data is None or data['act'] is None: 967 bui.buttonwidget( 968 edit=self._activity_mult_button, 969 textcolor=(0.7, 0.7, 0.8, 0.5), 970 icon_color=(0.5, 0, 0.5, 0.3), 971 ) 972 bui.textwidget(edit=self._activity_mult_text, text=' -') 973 else: 974 bui.buttonwidget( 975 edit=self._activity_mult_button, 976 textcolor=(0.7, 0.7, 0.8, 1.0), 977 icon_color=(0.5, 0, 0.5, 1.0), 978 ) 979 # pylint: disable=consider-using-f-string 980 bui.textwidget( 981 edit=self._activity_mult_text, 982 text='x ' + ('%.2f' % data['act']), 983 ) 984 985 have_pro = False if data is None else data['p'] 986 pro_mult = ( 987 1.0 988 + float( 989 plus.get_v1_account_misc_read_val('proPowerRankingBoost', 0.0) 990 ) 991 * 0.01 992 ) 993 # pylint: disable=consider-using-f-string 994 bui.textwidget( 995 edit=self._pro_mult_text, 996 text=' -' 997 if (data is None or not have_pro) 998 else 'x ' + ('%.2f' % pro_mult), 999 ) 1000 bui.buttonwidget( 1001 edit=self._pro_mult_button, 1002 textcolor=(0.7, 0.7, 0.8, (1.0 if have_pro else 0.5)), 1003 icon_color=(0.5, 0, 0.5) if have_pro else (0.5, 0, 0.5, 0.2), 1004 ) 1005 bui.buttonwidget( 1006 edit=self._power_ranking_achievements_button, 1007 label=('' if data is None else str(data['a']) + ' ') 1008 + bui.Lstr(resource='achievementsText').evaluate(), 1009 ) 1010 1011 # for the achievement value, use the number they gave us for 1012 # non-current seasons; otherwise calc our own 1013 total_ach_value = 0 1014 for ach in bui.app.classic.ach.achievements: 1015 if ach.complete: 1016 total_ach_value += ach.power_ranking_value 1017 if self._season != 'a' and not self._is_current_season: 1018 if data is not None and 'at' in data: 1019 total_ach_value = data['at'] 1020 1021 bui.textwidget( 1022 edit=self._power_ranking_achievement_total_text, 1023 text='-' 1024 if data is None 1025 else ('+ ' + pts_txt.replace('${NUMBER}', str(total_ach_value))), 1026 ) 1027 1028 total_trophies_count = accounts.get_league_rank_points( 1029 data, 'trophyCount' 1030 ) 1031 total_trophies_value = accounts.get_league_rank_points(data, 'trophies') 1032 bui.buttonwidget( 1033 edit=self._power_ranking_trophies_button, 1034 label=('' if data is None else str(total_trophies_count) + ' ') 1035 + bui.Lstr(resource='trophiesText').evaluate(), 1036 ) 1037 bui.textwidget( 1038 edit=self._power_ranking_trophies_total_text, 1039 text='-' 1040 if data is None 1041 else ( 1042 '+ ' + pts_txt.replace('${NUMBER}', str(total_trophies_value)) 1043 ), 1044 ) 1045 1046 bui.textwidget( 1047 edit=self._power_ranking_total_text, 1048 text='-' 1049 if data is None 1050 else eq_text.replace( 1051 '${NUMBER}', str(accounts.get_league_rank_points(data)) 1052 ), 1053 ) 1054 for widget in self._power_ranking_score_widgets: 1055 widget.delete() 1056 self._power_ranking_score_widgets = [] 1057 1058 scores = data['scores'] if data is not None else [] 1059 tally_color = (0.5, 0.6, 0.8) 1060 w_parent = self._subcontainer 1061 v2 = self._power_ranking_score_v 1062 1063 for score in scores: 1064 h2 = 680 1065 is_us = score[3] 1066 self._power_ranking_score_widgets.append( 1067 bui.textwidget( 1068 parent=w_parent, 1069 position=(h2 - 20, v2), 1070 size=(0, 0), 1071 color=(1, 1, 1) if is_us else (0.6, 0.6, 0.7), 1072 maxwidth=40, 1073 flatness=1.0, 1074 shadow=0.0, 1075 text=num_text.replace('${NUMBER}', str(score[0])), 1076 h_align='right', 1077 v_align='center', 1078 scale=0.5, 1079 ) 1080 ) 1081 self._power_ranking_score_widgets.append( 1082 bui.textwidget( 1083 parent=w_parent, 1084 position=(h2 + 20, v2), 1085 size=(0, 0), 1086 color=(1, 1, 1) if is_us else tally_color, 1087 maxwidth=60, 1088 text=str(score[1]), 1089 flatness=1.0, 1090 shadow=0.0, 1091 h_align='center', 1092 v_align='center', 1093 scale=0.7, 1094 ) 1095 ) 1096 txt = bui.textwidget( 1097 parent=w_parent, 1098 position=(h2 + 60, v2 - (28 * 0.5) / 0.9), 1099 size=(210 / 0.9, 28), 1100 color=(1, 1, 1) if is_us else (0.6, 0.6, 0.6), 1101 maxwidth=210, 1102 flatness=1.0, 1103 shadow=0.0, 1104 autoselect=True, 1105 selectable=True, 1106 click_activate=True, 1107 text=score[2], 1108 h_align='left', 1109 v_align='center', 1110 scale=0.9, 1111 ) 1112 self._power_ranking_score_widgets.append(txt) 1113 bui.textwidget( 1114 edit=txt, 1115 on_activate_call=bui.Call( 1116 self._show_account_info, score[4], txt 1117 ), 1118 ) 1119 assert self._season_popup_menu is not None 1120 bui.widget( 1121 edit=txt, left_widget=self._season_popup_menu.get_button() 1122 ) 1123 v2 -= 28 1124 1125 def _show_account_info( 1126 self, account_id: str, textwidget: bui.Widget 1127 ) -> None: 1128 from bauiv1lib.account import viewer 1129 1130 bui.getsound('swish').play() 1131 viewer.AccountViewerWindow( 1132 account_id=account_id, position=textwidget.get_screen_space_center() 1133 ) 1134 1135 def _on_season_change(self, value: str) -> None: 1136 self._requested_season = value 1137 self._last_power_ranking_query_time = None # make sure we update asap 1138 self._update(show=True) 1139 1140 def _save_state(self) -> None: 1141 pass 1142 1143 def _back(self) -> None: 1144 from bauiv1lib.coop.browser import CoopBrowserWindow 1145 1146 self._save_state() 1147 bui.containerwidget( 1148 edit=self._root_widget, transition=self._transition_out 1149 ) 1150 if not self._modal: 1151 assert bui.app.classic is not None 1152 bui.app.ui_v1.set_main_menu_window( 1153 CoopBrowserWindow(transition='in_left').get_root_widget() 1154 )
Window for showing league rank.
LeagueRankWindow( transition: str = 'in_right', modal: bool = False, origin_widget: _bauiv1.Widget | None = None)
23 def __init__( 24 self, 25 transition: str = 'in_right', 26 modal: bool = False, 27 origin_widget: bui.Widget | None = None, 28 ): 29 # pylint: disable=too-many-statements 30 plus = bui.app.plus 31 assert plus is not None 32 33 bui.set_analytics_screen('League Rank Window') 34 35 self._league_rank_data: dict[str, Any] | None = None 36 self._modal = modal 37 38 self._power_ranking_achievements_button: bui.Widget | None = None 39 self._pro_mult_button: bui.Widget | None = None 40 self._power_ranking_trophies_button: bui.Widget | None = None 41 self._league_title_text: bui.Widget | None = None 42 self._league_text: bui.Widget | None = None 43 self._league_number_text: bui.Widget | None = None 44 self._your_power_ranking_text: bui.Widget | None = None 45 self._season_ends_text: bui.Widget | None = None 46 self._power_ranking_rank_text: bui.Widget | None = None 47 self._to_ranked_text: bui.Widget | None = None 48 self._trophy_counts_reset_text: bui.Widget | None = None 49 50 # If they provided an origin-widget, scale up from that. 51 scale_origin: tuple[float, float] | None 52 if origin_widget is not None: 53 self._transition_out = 'out_scale' 54 scale_origin = origin_widget.get_screen_space_center() 55 transition = 'in_scale' 56 else: 57 self._transition_out = 'out_right' 58 scale_origin = None 59 60 assert bui.app.classic is not None 61 uiscale = bui.app.ui_v1.uiscale 62 self._width = 1320 if uiscale is bui.UIScale.SMALL else 1120 63 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 64 self._height = ( 65 657 66 if uiscale is bui.UIScale.SMALL 67 else 710 68 if uiscale is bui.UIScale.MEDIUM 69 else 800 70 ) 71 self._r = 'coopSelectWindow' 72 self._rdict = bui.app.lang.get_resource(self._r) 73 top_extra = 20 if uiscale is bui.UIScale.SMALL else 0 74 75 self._league_url_arg = '' 76 77 self._is_current_season = False 78 self._can_do_more_button = True 79 80 super().__init__( 81 root_widget=bui.containerwidget( 82 size=(self._width, self._height + top_extra), 83 stack_offset=(0, -15) 84 if uiscale is bui.UIScale.SMALL 85 else (0, 10) 86 if uiscale is bui.UIScale.MEDIUM 87 else (0, 0), 88 transition=transition, 89 scale_origin_stack_offset=scale_origin, 90 scale=( 91 1.2 92 if uiscale is bui.UIScale.SMALL 93 else 0.93 94 if uiscale is bui.UIScale.MEDIUM 95 else 0.8 96 ), 97 ) 98 ) 99 100 self._back_button = btn = bui.buttonwidget( 101 parent=self._root_widget, 102 position=( 103 75 + x_inset, 104 self._height - 87 - (4 if uiscale is bui.UIScale.SMALL else 0), 105 ), 106 size=(120, 60), 107 scale=1.2, 108 autoselect=True, 109 label=bui.Lstr(resource='doneText' if self._modal else 'backText'), 110 button_type=None if self._modal else 'back', 111 on_activate_call=self._back, 112 ) 113 114 self._title_text = bui.textwidget( 115 parent=self._root_widget, 116 position=(self._width * 0.5, self._height - 56), 117 size=(0, 0), 118 text=bui.Lstr( 119 resource='league.leagueRankText', 120 fallback_resource='coopSelectWindow.powerRankingText', 121 ), 122 h_align='center', 123 color=bui.app.ui_v1.title_color, 124 scale=1.4, 125 maxwidth=600, 126 v_align='center', 127 ) 128 129 bui.buttonwidget( 130 edit=btn, 131 button_type='backSmall', 132 position=( 133 75 + x_inset, 134 self._height - 87 - (2 if uiscale is bui.UIScale.SMALL else 0), 135 ), 136 size=(60, 55), 137 label=bui.charstr(bui.SpecialChar.BACK), 138 ) 139 140 self._scroll_width = self._width - (130 + 2 * x_inset) 141 self._scroll_height = self._height - 160 142 self._scrollwidget = bui.scrollwidget( 143 parent=self._root_widget, 144 highlight=False, 145 position=(65 + x_inset, 70), 146 size=(self._scroll_width, self._scroll_height), 147 center_small_content=True, 148 ) 149 bui.widget(edit=self._scrollwidget, autoselect=True) 150 bui.containerwidget(edit=self._scrollwidget, claims_left_right=True) 151 bui.containerwidget( 152 edit=self._root_widget, 153 cancel_button=self._back_button, 154 selected_child=self._back_button, 155 ) 156 157 self._last_power_ranking_query_time: float | None = None 158 self._doing_power_ranking_query = False 159 160 self._subcontainer: bui.Widget | None = None 161 self._subcontainerwidth = 800 162 self._subcontainerheight = 483 163 self._power_ranking_score_widgets: list[bui.Widget] = [] 164 165 self._season_popup_menu: PopupMenu | None = None 166 self._requested_season: str | None = None 167 self._season: str | None = None 168 169 # take note of our account state; we'll refresh later if this changes 170 self._account_state = plus.get_v1_account_state() 171 172 self._refresh() 173 self._restore_state() 174 175 # if we've got cached power-ranking data already, display it 176 assert bui.app.classic is not None 177 info = bui.app.classic.accounts.get_cached_league_rank_data() 178 if info is not None: 179 self._update_for_league_rank_data(info) 180 181 self._update_timer = bui.AppTimer( 182 1.0, bui.WeakCall(self._update), repeat=True 183 ) 184 self._update(show=info is None)
Inherited Members
- bauiv1._uitypes.Window
- get_root_widget