bastd.ui.tournamentscores
Provides a popup for viewing tournament scores.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides a popup for viewing tournament scores.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9import _ba 10import ba 11from bastd.ui import popup as popup_ui 12 13if TYPE_CHECKING: 14 from typing import Any, Sequence, Callable 15 16 17class TournamentScoresWindow(popup_ui.PopupWindow): 18 """Window for viewing tournament scores.""" 19 20 def __init__(self, 21 tournament_id: str, 22 tournament_activity: ba.GameActivity | None = None, 23 position: tuple[float, float] = (0.0, 0.0), 24 scale: float | None = None, 25 offset: tuple[float, float] = (0.0, 0.0), 26 tint_color: Sequence[float] = (1.0, 1.0, 1.0), 27 tint2_color: Sequence[float] = (1.0, 1.0, 1.0), 28 selected_character: str | None = None, 29 on_close_call: Callable[[], Any] | None = None): 30 31 del tournament_activity # unused arg 32 del tint_color # unused arg 33 del tint2_color # unused arg 34 del selected_character # unused arg 35 self._tournament_id = tournament_id 36 self._subcontainer: ba.Widget | None = None 37 self._on_close_call = on_close_call 38 uiscale = ba.app.ui.uiscale 39 if scale is None: 40 scale = (2.3 if uiscale is ba.UIScale.SMALL else 41 1.65 if uiscale is ba.UIScale.MEDIUM else 1.23) 42 self._transitioning_out = False 43 44 self._width = 400 45 self._height = (300 if uiscale is ba.UIScale.SMALL else 46 370 if uiscale is ba.UIScale.MEDIUM else 450) 47 48 bg_color = (0.5, 0.4, 0.6) 49 50 # creates our _root_widget 51 super().__init__(position=position, 52 size=(self._width, self._height), 53 scale=scale, 54 bg_color=bg_color, 55 offset=offset) 56 57 # app = ba.app 58 59 self._cancel_button = ba.buttonwidget( 60 parent=self.root_widget, 61 position=(50, self._height - 30), 62 size=(50, 50), 63 scale=0.5, 64 label='', 65 color=bg_color, 66 on_activate_call=self._on_cancel_press, 67 autoselect=True, 68 icon=ba.gettexture('crossOut'), 69 iconscale=1.2) 70 71 self._title_text = ba.textwidget( 72 parent=self.root_widget, 73 position=(self._width * 0.5, self._height - 20), 74 size=(0, 0), 75 h_align='center', 76 v_align='center', 77 scale=0.6, 78 text=ba.Lstr(resource='tournamentStandingsText'), 79 maxwidth=200, 80 color=(1, 1, 1, 0.4)) 81 82 self._scrollwidget = ba.scrollwidget(parent=self.root_widget, 83 size=(self._width - 60, 84 self._height - 70), 85 position=(30, 30), 86 highlight=False, 87 simple_culling_v=10) 88 ba.widget(edit=self._scrollwidget, autoselect=True) 89 90 self._loading_text = ba.textwidget( 91 parent=self._scrollwidget, 92 scale=0.5, 93 text=ba.Lstr(value='${A}...', 94 subs=[('${A}', ba.Lstr(resource='loadingText'))]), 95 size=(self._width - 60, 100), 96 h_align='center', 97 v_align='center') 98 99 ba.containerwidget(edit=self.root_widget, 100 cancel_button=self._cancel_button) 101 102 _ba.tournament_query(args={ 103 'tournamentIDs': [tournament_id], 104 'numScores': 50, 105 'source': 'scores window' 106 }, 107 callback=ba.WeakCall( 108 self._on_tournament_query_response)) 109 110 def _on_tournament_query_response(self, 111 data: dict[str, Any] | None) -> None: 112 if data is not None: 113 # this used to be the whole payload 114 data_t: list[dict[str, Any]] = data['t'] 115 # kill our loading text if we've got scores.. otherwise just 116 # replace it with 'no scores yet' 117 if data_t[0]['scores']: 118 self._loading_text.delete() 119 else: 120 ba.textwidget(edit=self._loading_text, 121 text=ba.Lstr(resource='noScoresYetText')) 122 incr = 30 123 sub_width = self._width - 90 124 sub_height = 30 + len(data_t[0]['scores']) * incr 125 self._subcontainer = ba.containerwidget(parent=self._scrollwidget, 126 size=(sub_width, 127 sub_height), 128 background=False) 129 for i, entry in enumerate(data_t[0]['scores']): 130 131 ba.textwidget(parent=self._subcontainer, 132 position=(sub_width * 0.1 - 5, 133 sub_height - 20 - incr * i), 134 maxwidth=20, 135 scale=0.5, 136 color=(0.6, 0.6, 0.7), 137 flatness=1.0, 138 shadow=0.0, 139 text=str(i + 1), 140 size=(0, 0), 141 h_align='right', 142 v_align='center') 143 144 ba.textwidget( 145 parent=self._subcontainer, 146 position=(sub_width * 0.25 - 2, 147 sub_height - 20 - incr * i), 148 maxwidth=sub_width * 0.24, 149 color=(0.9, 1.0, 0.9), 150 flatness=1.0, 151 shadow=0.0, 152 scale=0.6, 153 text=(ba.timestring(entry[0] * 10, 154 centi=True, 155 timeformat=ba.TimeFormat.MILLISECONDS) 156 if data_t[0]['scoreType'] == 'time' else str( 157 entry[0])), 158 size=(0, 0), 159 h_align='center', 160 v_align='center') 161 162 txt = ba.textwidget( 163 parent=self._subcontainer, 164 position=(sub_width * 0.25, 165 sub_height - 20 - incr * i - (0.5 / 0.7) * incr), 166 maxwidth=sub_width * 0.6, 167 scale=0.7, 168 flatness=1.0, 169 shadow=0.0, 170 text=ba.Lstr(value=entry[1]), 171 selectable=True, 172 click_activate=True, 173 autoselect=True, 174 extra_touch_border_scale=0.0, 175 size=((sub_width * 0.6) / 0.7, incr / 0.7), 176 h_align='left', 177 v_align='center') 178 179 ba.textwidget(edit=txt, 180 on_activate_call=ba.Call(self._show_player_info, 181 entry, txt)) 182 if i == 0: 183 ba.widget(edit=txt, up_widget=self._cancel_button) 184 185 def _show_player_info(self, entry: Any, textwidget: ba.Widget) -> None: 186 from bastd.ui.account.viewer import AccountViewerWindow 187 # for the moment we only work if a single player-info is present.. 188 if len(entry[2]) != 1: 189 ba.playsound(ba.getsound('error')) 190 return 191 ba.playsound(ba.getsound('swish')) 192 AccountViewerWindow(account_id=entry[2][0].get('a', None), 193 profile_id=entry[2][0].get('p', None), 194 position=textwidget.get_screen_space_center()) 195 self._transition_out() 196 197 def _on_cancel_press(self) -> None: 198 self._transition_out() 199 200 def _transition_out(self) -> None: 201 if not self._transitioning_out: 202 self._transitioning_out = True 203 ba.containerwidget(edit=self.root_widget, transition='out_scale') 204 if self._on_close_call is not None: 205 self._on_close_call() 206 207 def on_popup_cancel(self) -> None: 208 ba.playsound(ba.getsound('swish')) 209 self._transition_out()
18class TournamentScoresWindow(popup_ui.PopupWindow): 19 """Window for viewing tournament scores.""" 20 21 def __init__(self, 22 tournament_id: str, 23 tournament_activity: ba.GameActivity | None = None, 24 position: tuple[float, float] = (0.0, 0.0), 25 scale: float | None = None, 26 offset: tuple[float, float] = (0.0, 0.0), 27 tint_color: Sequence[float] = (1.0, 1.0, 1.0), 28 tint2_color: Sequence[float] = (1.0, 1.0, 1.0), 29 selected_character: str | None = None, 30 on_close_call: Callable[[], Any] | None = None): 31 32 del tournament_activity # unused arg 33 del tint_color # unused arg 34 del tint2_color # unused arg 35 del selected_character # unused arg 36 self._tournament_id = tournament_id 37 self._subcontainer: ba.Widget | None = None 38 self._on_close_call = on_close_call 39 uiscale = ba.app.ui.uiscale 40 if scale is None: 41 scale = (2.3 if uiscale is ba.UIScale.SMALL else 42 1.65 if uiscale is ba.UIScale.MEDIUM else 1.23) 43 self._transitioning_out = False 44 45 self._width = 400 46 self._height = (300 if uiscale is ba.UIScale.SMALL else 47 370 if uiscale is ba.UIScale.MEDIUM else 450) 48 49 bg_color = (0.5, 0.4, 0.6) 50 51 # creates our _root_widget 52 super().__init__(position=position, 53 size=(self._width, self._height), 54 scale=scale, 55 bg_color=bg_color, 56 offset=offset) 57 58 # app = ba.app 59 60 self._cancel_button = ba.buttonwidget( 61 parent=self.root_widget, 62 position=(50, self._height - 30), 63 size=(50, 50), 64 scale=0.5, 65 label='', 66 color=bg_color, 67 on_activate_call=self._on_cancel_press, 68 autoselect=True, 69 icon=ba.gettexture('crossOut'), 70 iconscale=1.2) 71 72 self._title_text = ba.textwidget( 73 parent=self.root_widget, 74 position=(self._width * 0.5, self._height - 20), 75 size=(0, 0), 76 h_align='center', 77 v_align='center', 78 scale=0.6, 79 text=ba.Lstr(resource='tournamentStandingsText'), 80 maxwidth=200, 81 color=(1, 1, 1, 0.4)) 82 83 self._scrollwidget = ba.scrollwidget(parent=self.root_widget, 84 size=(self._width - 60, 85 self._height - 70), 86 position=(30, 30), 87 highlight=False, 88 simple_culling_v=10) 89 ba.widget(edit=self._scrollwidget, autoselect=True) 90 91 self._loading_text = ba.textwidget( 92 parent=self._scrollwidget, 93 scale=0.5, 94 text=ba.Lstr(value='${A}...', 95 subs=[('${A}', ba.Lstr(resource='loadingText'))]), 96 size=(self._width - 60, 100), 97 h_align='center', 98 v_align='center') 99 100 ba.containerwidget(edit=self.root_widget, 101 cancel_button=self._cancel_button) 102 103 _ba.tournament_query(args={ 104 'tournamentIDs': [tournament_id], 105 'numScores': 50, 106 'source': 'scores window' 107 }, 108 callback=ba.WeakCall( 109 self._on_tournament_query_response)) 110 111 def _on_tournament_query_response(self, 112 data: dict[str, Any] | None) -> None: 113 if data is not None: 114 # this used to be the whole payload 115 data_t: list[dict[str, Any]] = data['t'] 116 # kill our loading text if we've got scores.. otherwise just 117 # replace it with 'no scores yet' 118 if data_t[0]['scores']: 119 self._loading_text.delete() 120 else: 121 ba.textwidget(edit=self._loading_text, 122 text=ba.Lstr(resource='noScoresYetText')) 123 incr = 30 124 sub_width = self._width - 90 125 sub_height = 30 + len(data_t[0]['scores']) * incr 126 self._subcontainer = ba.containerwidget(parent=self._scrollwidget, 127 size=(sub_width, 128 sub_height), 129 background=False) 130 for i, entry in enumerate(data_t[0]['scores']): 131 132 ba.textwidget(parent=self._subcontainer, 133 position=(sub_width * 0.1 - 5, 134 sub_height - 20 - incr * i), 135 maxwidth=20, 136 scale=0.5, 137 color=(0.6, 0.6, 0.7), 138 flatness=1.0, 139 shadow=0.0, 140 text=str(i + 1), 141 size=(0, 0), 142 h_align='right', 143 v_align='center') 144 145 ba.textwidget( 146 parent=self._subcontainer, 147 position=(sub_width * 0.25 - 2, 148 sub_height - 20 - incr * i), 149 maxwidth=sub_width * 0.24, 150 color=(0.9, 1.0, 0.9), 151 flatness=1.0, 152 shadow=0.0, 153 scale=0.6, 154 text=(ba.timestring(entry[0] * 10, 155 centi=True, 156 timeformat=ba.TimeFormat.MILLISECONDS) 157 if data_t[0]['scoreType'] == 'time' else str( 158 entry[0])), 159 size=(0, 0), 160 h_align='center', 161 v_align='center') 162 163 txt = ba.textwidget( 164 parent=self._subcontainer, 165 position=(sub_width * 0.25, 166 sub_height - 20 - incr * i - (0.5 / 0.7) * incr), 167 maxwidth=sub_width * 0.6, 168 scale=0.7, 169 flatness=1.0, 170 shadow=0.0, 171 text=ba.Lstr(value=entry[1]), 172 selectable=True, 173 click_activate=True, 174 autoselect=True, 175 extra_touch_border_scale=0.0, 176 size=((sub_width * 0.6) / 0.7, incr / 0.7), 177 h_align='left', 178 v_align='center') 179 180 ba.textwidget(edit=txt, 181 on_activate_call=ba.Call(self._show_player_info, 182 entry, txt)) 183 if i == 0: 184 ba.widget(edit=txt, up_widget=self._cancel_button) 185 186 def _show_player_info(self, entry: Any, textwidget: ba.Widget) -> None: 187 from bastd.ui.account.viewer import AccountViewerWindow 188 # for the moment we only work if a single player-info is present.. 189 if len(entry[2]) != 1: 190 ba.playsound(ba.getsound('error')) 191 return 192 ba.playsound(ba.getsound('swish')) 193 AccountViewerWindow(account_id=entry[2][0].get('a', None), 194 profile_id=entry[2][0].get('p', None), 195 position=textwidget.get_screen_space_center()) 196 self._transition_out() 197 198 def _on_cancel_press(self) -> None: 199 self._transition_out() 200 201 def _transition_out(self) -> None: 202 if not self._transitioning_out: 203 self._transitioning_out = True 204 ba.containerwidget(edit=self.root_widget, transition='out_scale') 205 if self._on_close_call is not None: 206 self._on_close_call() 207 208 def on_popup_cancel(self) -> None: 209 ba.playsound(ba.getsound('swish')) 210 self._transition_out()
Window for viewing tournament scores.
TournamentScoresWindow( tournament_id: str, tournament_activity: ba._gameactivity.GameActivity | None = None, position: tuple[float, float] = (0.0, 0.0), scale: float | None = None, offset: tuple[float, float] = (0.0, 0.0), tint_color: Sequence[float] = (1.0, 1.0, 1.0), tint2_color: Sequence[float] = (1.0, 1.0, 1.0), selected_character: str | None = None, on_close_call: Optional[Callable[[], Any]] = None)
21 def __init__(self, 22 tournament_id: str, 23 tournament_activity: ba.GameActivity | None = None, 24 position: tuple[float, float] = (0.0, 0.0), 25 scale: float | None = None, 26 offset: tuple[float, float] = (0.0, 0.0), 27 tint_color: Sequence[float] = (1.0, 1.0, 1.0), 28 tint2_color: Sequence[float] = (1.0, 1.0, 1.0), 29 selected_character: str | None = None, 30 on_close_call: Callable[[], Any] | None = None): 31 32 del tournament_activity # unused arg 33 del tint_color # unused arg 34 del tint2_color # unused arg 35 del selected_character # unused arg 36 self._tournament_id = tournament_id 37 self._subcontainer: ba.Widget | None = None 38 self._on_close_call = on_close_call 39 uiscale = ba.app.ui.uiscale 40 if scale is None: 41 scale = (2.3 if uiscale is ba.UIScale.SMALL else 42 1.65 if uiscale is ba.UIScale.MEDIUM else 1.23) 43 self._transitioning_out = False 44 45 self._width = 400 46 self._height = (300 if uiscale is ba.UIScale.SMALL else 47 370 if uiscale is ba.UIScale.MEDIUM else 450) 48 49 bg_color = (0.5, 0.4, 0.6) 50 51 # creates our _root_widget 52 super().__init__(position=position, 53 size=(self._width, self._height), 54 scale=scale, 55 bg_color=bg_color, 56 offset=offset) 57 58 # app = ba.app 59 60 self._cancel_button = ba.buttonwidget( 61 parent=self.root_widget, 62 position=(50, self._height - 30), 63 size=(50, 50), 64 scale=0.5, 65 label='', 66 color=bg_color, 67 on_activate_call=self._on_cancel_press, 68 autoselect=True, 69 icon=ba.gettexture('crossOut'), 70 iconscale=1.2) 71 72 self._title_text = ba.textwidget( 73 parent=self.root_widget, 74 position=(self._width * 0.5, self._height - 20), 75 size=(0, 0), 76 h_align='center', 77 v_align='center', 78 scale=0.6, 79 text=ba.Lstr(resource='tournamentStandingsText'), 80 maxwidth=200, 81 color=(1, 1, 1, 0.4)) 82 83 self._scrollwidget = ba.scrollwidget(parent=self.root_widget, 84 size=(self._width - 60, 85 self._height - 70), 86 position=(30, 30), 87 highlight=False, 88 simple_culling_v=10) 89 ba.widget(edit=self._scrollwidget, autoselect=True) 90 91 self._loading_text = ba.textwidget( 92 parent=self._scrollwidget, 93 scale=0.5, 94 text=ba.Lstr(value='${A}...', 95 subs=[('${A}', ba.Lstr(resource='loadingText'))]), 96 size=(self._width - 60, 100), 97 h_align='center', 98 v_align='center') 99 100 ba.containerwidget(edit=self.root_widget, 101 cancel_button=self._cancel_button) 102 103 _ba.tournament_query(args={ 104 'tournamentIDs': [tournament_id], 105 'numScores': 50, 106 'source': 'scores window' 107 }, 108 callback=ba.WeakCall( 109 self._on_tournament_query_response))