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