bauiv1lib.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, override 8 9from bauiv1lib.popup import PopupWindow 10import bauiv1 as bui 11 12if TYPE_CHECKING: 13 from typing import Any, Sequence, Callable 14 15 import bascenev1 as bs 16 17 18class TournamentScoresWindow(PopupWindow): 19 """Window for viewing tournament scores.""" 20 21 def __init__( 22 self, 23 tournament_id: str, 24 *, 25 position: tuple[float, float] = (0.0, 0.0), 26 ): 27 plus = bui.app.plus 28 assert plus is not None 29 30 self._tournament_id = tournament_id 31 self._subcontainer: bui.Widget | None = None 32 assert bui.app.classic is not None 33 uiscale = bui.app.ui_v1.uiscale 34 scale = ( 35 2.3 36 if uiscale is bui.UIScale.SMALL 37 else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 38 ) 39 self._transitioning_out = False 40 41 self._width = 400 42 self._height = ( 43 300 44 if uiscale is bui.UIScale.SMALL 45 else 370 if uiscale is bui.UIScale.MEDIUM else 450 46 ) 47 48 bg_color = (0.5, 0.4, 0.6) 49 50 # Creates our _root_widget. 51 super().__init__( 52 position=position, 53 size=(self._width, self._height), 54 scale=scale, 55 bg_color=bg_color, 56 ) 57 58 self._cancel_button = bui.buttonwidget( 59 parent=self.root_widget, 60 position=(50, self._height - 30), 61 size=(50, 50), 62 scale=0.5, 63 label='', 64 color=bg_color, 65 on_activate_call=self._on_cancel_press, 66 autoselect=True, 67 icon=bui.gettexture('crossOut'), 68 iconscale=1.2, 69 ) 70 71 self._title_text = bui.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=bui.Lstr(resource='tournamentStandingsText'), 79 maxwidth=200, 80 color=bui.app.ui_v1.title_color, 81 ) 82 83 self._scrollwidget = bui.scrollwidget( 84 parent=self.root_widget, 85 size=(self._width - 60, self._height - 70), 86 position=(30, 30), 87 highlight=False, 88 simple_culling_v=10, 89 border_opacity=0.4, 90 ) 91 bui.widget(edit=self._scrollwidget, autoselect=True) 92 93 self._loading_spinner = bui.spinnerwidget( 94 parent=self.root_widget, 95 position=(self._width * 0.5, self._height * 0.5), 96 ) 97 self._loading_text = bui.textwidget( 98 parent=self._scrollwidget, 99 scale=0.5, 100 text='', 101 size=(self._width - 60, 100), 102 h_align='center', 103 v_align='center', 104 ) 105 106 bui.containerwidget( 107 edit=self.root_widget, cancel_button=self._cancel_button 108 ) 109 110 plus.tournament_query( 111 args={ 112 'tournamentIDs': [tournament_id], 113 'numScores': 50, 114 'source': 'scores window', 115 }, 116 callback=bui.WeakCall(self._on_tournament_query_response), 117 ) 118 119 def _on_tournament_query_response( 120 self, data: dict[str, Any] | None 121 ) -> None: 122 if data is not None: 123 # This used to be the whole payload. 124 data_t: list[dict[str, Any]] = data['t'] 125 126 # Kill our loading text if we've got scores; otherwise just 127 # replace it with 'no scores yet'. 128 bui.spinnerwidget(edit=self._loading_spinner, visible=False) 129 if data_t[0]['scores']: 130 self._loading_text.delete() 131 else: 132 bui.textwidget( 133 edit=self._loading_text, 134 text=bui.Lstr(resource='noScoresYetText'), 135 ) 136 incr = 30 137 sub_width = self._width - 90 138 sub_height = 30 + len(data_t[0]['scores']) * incr 139 self._subcontainer = bui.containerwidget( 140 parent=self._scrollwidget, 141 size=(sub_width, sub_height), 142 background=False, 143 ) 144 for i, entry in enumerate(data_t[0]['scores']): 145 bui.textwidget( 146 parent=self._subcontainer, 147 position=(sub_width * 0.1 - 5, sub_height - 20 - incr * i), 148 maxwidth=20, 149 scale=0.5, 150 color=(0.6, 0.6, 0.7), 151 flatness=1.0, 152 shadow=0.0, 153 text=str(i + 1), 154 size=(0, 0), 155 h_align='right', 156 v_align='center', 157 ) 158 159 bui.textwidget( 160 parent=self._subcontainer, 161 position=(sub_width * 0.25 - 2, sub_height - 20 - incr * i), 162 maxwidth=sub_width * 0.24, 163 color=(0.9, 1.0, 0.9), 164 flatness=1.0, 165 shadow=0.0, 166 scale=0.6, 167 text=( 168 bui.timestring( 169 (entry[0] * 10) / 1000.0, 170 centi=True, 171 ) 172 if data_t[0]['scoreType'] == 'time' 173 else str(entry[0]) 174 ), 175 size=(0, 0), 176 h_align='center', 177 v_align='center', 178 ) 179 180 txt = bui.textwidget( 181 parent=self._subcontainer, 182 position=( 183 sub_width * 0.25, 184 sub_height - 20 - incr * i - (0.5 / 0.7) * incr, 185 ), 186 maxwidth=sub_width * 0.6, 187 scale=0.7, 188 flatness=1.0, 189 shadow=0.0, 190 text=bui.Lstr(value=entry[1]), 191 selectable=True, 192 click_activate=True, 193 autoselect=True, 194 extra_touch_border_scale=0.0, 195 size=((sub_width * 0.6) / 0.7, incr / 0.7), 196 h_align='left', 197 v_align='center', 198 ) 199 200 bui.textwidget( 201 edit=txt, 202 on_activate_call=bui.Call( 203 self._show_player_info, entry, txt 204 ), 205 ) 206 if i == 0: 207 bui.widget(edit=txt, up_widget=self._cancel_button) 208 209 def _show_player_info(self, entry: Any, textwidget: bui.Widget) -> None: 210 from bauiv1lib.account.viewer import AccountViewerWindow 211 212 # For the moment we only work if a single player-info is 213 # present. 214 if len(entry[2]) != 1: 215 bui.getsound('error').play() 216 return 217 bui.getsound('swish').play() 218 AccountViewerWindow( 219 account_id=entry[2][0].get('a', None), 220 profile_id=entry[2][0].get('p', None), 221 position=textwidget.get_screen_space_center(), 222 ) 223 self._transition_out() 224 225 def _on_cancel_press(self) -> None: 226 self._transition_out() 227 228 def _transition_out(self) -> None: 229 if not self._transitioning_out: 230 self._transitioning_out = True 231 bui.containerwidget(edit=self.root_widget, transition='out_scale') 232 233 @override 234 def on_popup_cancel(self) -> None: 235 bui.getsound('swish').play() 236 self._transition_out()
19class TournamentScoresWindow(PopupWindow): 20 """Window for viewing tournament scores.""" 21 22 def __init__( 23 self, 24 tournament_id: str, 25 *, 26 position: tuple[float, float] = (0.0, 0.0), 27 ): 28 plus = bui.app.plus 29 assert plus is not None 30 31 self._tournament_id = tournament_id 32 self._subcontainer: bui.Widget | None = None 33 assert bui.app.classic is not None 34 uiscale = bui.app.ui_v1.uiscale 35 scale = ( 36 2.3 37 if uiscale is bui.UIScale.SMALL 38 else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 39 ) 40 self._transitioning_out = False 41 42 self._width = 400 43 self._height = ( 44 300 45 if uiscale is bui.UIScale.SMALL 46 else 370 if uiscale is bui.UIScale.MEDIUM else 450 47 ) 48 49 bg_color = (0.5, 0.4, 0.6) 50 51 # Creates our _root_widget. 52 super().__init__( 53 position=position, 54 size=(self._width, self._height), 55 scale=scale, 56 bg_color=bg_color, 57 ) 58 59 self._cancel_button = bui.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=bui.gettexture('crossOut'), 69 iconscale=1.2, 70 ) 71 72 self._title_text = bui.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=bui.Lstr(resource='tournamentStandingsText'), 80 maxwidth=200, 81 color=bui.app.ui_v1.title_color, 82 ) 83 84 self._scrollwidget = bui.scrollwidget( 85 parent=self.root_widget, 86 size=(self._width - 60, self._height - 70), 87 position=(30, 30), 88 highlight=False, 89 simple_culling_v=10, 90 border_opacity=0.4, 91 ) 92 bui.widget(edit=self._scrollwidget, autoselect=True) 93 94 self._loading_spinner = bui.spinnerwidget( 95 parent=self.root_widget, 96 position=(self._width * 0.5, self._height * 0.5), 97 ) 98 self._loading_text = bui.textwidget( 99 parent=self._scrollwidget, 100 scale=0.5, 101 text='', 102 size=(self._width - 60, 100), 103 h_align='center', 104 v_align='center', 105 ) 106 107 bui.containerwidget( 108 edit=self.root_widget, cancel_button=self._cancel_button 109 ) 110 111 plus.tournament_query( 112 args={ 113 'tournamentIDs': [tournament_id], 114 'numScores': 50, 115 'source': 'scores window', 116 }, 117 callback=bui.WeakCall(self._on_tournament_query_response), 118 ) 119 120 def _on_tournament_query_response( 121 self, data: dict[str, Any] | None 122 ) -> None: 123 if data is not None: 124 # This used to be the whole payload. 125 data_t: list[dict[str, Any]] = data['t'] 126 127 # Kill our loading text if we've got scores; otherwise just 128 # replace it with 'no scores yet'. 129 bui.spinnerwidget(edit=self._loading_spinner, visible=False) 130 if data_t[0]['scores']: 131 self._loading_text.delete() 132 else: 133 bui.textwidget( 134 edit=self._loading_text, 135 text=bui.Lstr(resource='noScoresYetText'), 136 ) 137 incr = 30 138 sub_width = self._width - 90 139 sub_height = 30 + len(data_t[0]['scores']) * incr 140 self._subcontainer = bui.containerwidget( 141 parent=self._scrollwidget, 142 size=(sub_width, sub_height), 143 background=False, 144 ) 145 for i, entry in enumerate(data_t[0]['scores']): 146 bui.textwidget( 147 parent=self._subcontainer, 148 position=(sub_width * 0.1 - 5, sub_height - 20 - incr * i), 149 maxwidth=20, 150 scale=0.5, 151 color=(0.6, 0.6, 0.7), 152 flatness=1.0, 153 shadow=0.0, 154 text=str(i + 1), 155 size=(0, 0), 156 h_align='right', 157 v_align='center', 158 ) 159 160 bui.textwidget( 161 parent=self._subcontainer, 162 position=(sub_width * 0.25 - 2, sub_height - 20 - incr * i), 163 maxwidth=sub_width * 0.24, 164 color=(0.9, 1.0, 0.9), 165 flatness=1.0, 166 shadow=0.0, 167 scale=0.6, 168 text=( 169 bui.timestring( 170 (entry[0] * 10) / 1000.0, 171 centi=True, 172 ) 173 if data_t[0]['scoreType'] == 'time' 174 else str(entry[0]) 175 ), 176 size=(0, 0), 177 h_align='center', 178 v_align='center', 179 ) 180 181 txt = bui.textwidget( 182 parent=self._subcontainer, 183 position=( 184 sub_width * 0.25, 185 sub_height - 20 - incr * i - (0.5 / 0.7) * incr, 186 ), 187 maxwidth=sub_width * 0.6, 188 scale=0.7, 189 flatness=1.0, 190 shadow=0.0, 191 text=bui.Lstr(value=entry[1]), 192 selectable=True, 193 click_activate=True, 194 autoselect=True, 195 extra_touch_border_scale=0.0, 196 size=((sub_width * 0.6) / 0.7, incr / 0.7), 197 h_align='left', 198 v_align='center', 199 ) 200 201 bui.textwidget( 202 edit=txt, 203 on_activate_call=bui.Call( 204 self._show_player_info, entry, txt 205 ), 206 ) 207 if i == 0: 208 bui.widget(edit=txt, up_widget=self._cancel_button) 209 210 def _show_player_info(self, entry: Any, textwidget: bui.Widget) -> None: 211 from bauiv1lib.account.viewer import AccountViewerWindow 212 213 # For the moment we only work if a single player-info is 214 # present. 215 if len(entry[2]) != 1: 216 bui.getsound('error').play() 217 return 218 bui.getsound('swish').play() 219 AccountViewerWindow( 220 account_id=entry[2][0].get('a', None), 221 profile_id=entry[2][0].get('p', None), 222 position=textwidget.get_screen_space_center(), 223 ) 224 self._transition_out() 225 226 def _on_cancel_press(self) -> None: 227 self._transition_out() 228 229 def _transition_out(self) -> None: 230 if not self._transitioning_out: 231 self._transitioning_out = True 232 bui.containerwidget(edit=self.root_widget, transition='out_scale') 233 234 @override 235 def on_popup_cancel(self) -> None: 236 bui.getsound('swish').play() 237 self._transition_out()
Window for viewing tournament scores.
TournamentScoresWindow(tournament_id: str, *, position: tuple[float, float] = (0.0, 0.0))
22 def __init__( 23 self, 24 tournament_id: str, 25 *, 26 position: tuple[float, float] = (0.0, 0.0), 27 ): 28 plus = bui.app.plus 29 assert plus is not None 30 31 self._tournament_id = tournament_id 32 self._subcontainer: bui.Widget | None = None 33 assert bui.app.classic is not None 34 uiscale = bui.app.ui_v1.uiscale 35 scale = ( 36 2.3 37 if uiscale is bui.UIScale.SMALL 38 else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 39 ) 40 self._transitioning_out = False 41 42 self._width = 400 43 self._height = ( 44 300 45 if uiscale is bui.UIScale.SMALL 46 else 370 if uiscale is bui.UIScale.MEDIUM else 450 47 ) 48 49 bg_color = (0.5, 0.4, 0.6) 50 51 # Creates our _root_widget. 52 super().__init__( 53 position=position, 54 size=(self._width, self._height), 55 scale=scale, 56 bg_color=bg_color, 57 ) 58 59 self._cancel_button = bui.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=bui.gettexture('crossOut'), 69 iconscale=1.2, 70 ) 71 72 self._title_text = bui.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=bui.Lstr(resource='tournamentStandingsText'), 80 maxwidth=200, 81 color=bui.app.ui_v1.title_color, 82 ) 83 84 self._scrollwidget = bui.scrollwidget( 85 parent=self.root_widget, 86 size=(self._width - 60, self._height - 70), 87 position=(30, 30), 88 highlight=False, 89 simple_culling_v=10, 90 border_opacity=0.4, 91 ) 92 bui.widget(edit=self._scrollwidget, autoselect=True) 93 94 self._loading_spinner = bui.spinnerwidget( 95 parent=self.root_widget, 96 position=(self._width * 0.5, self._height * 0.5), 97 ) 98 self._loading_text = bui.textwidget( 99 parent=self._scrollwidget, 100 scale=0.5, 101 text='', 102 size=(self._width - 60, 100), 103 h_align='center', 104 v_align='center', 105 ) 106 107 bui.containerwidget( 108 edit=self.root_widget, cancel_button=self._cancel_button 109 ) 110 111 plus.tournament_query( 112 args={ 113 'tournamentIDs': [tournament_id], 114 'numScores': 50, 115 'source': 'scores window', 116 }, 117 callback=bui.WeakCall(self._on_tournament_query_response), 118 )
@override
def
on_popup_cancel(self) -> None:
234 @override 235 def on_popup_cancel(self) -> None: 236 bui.getsound('swish').play() 237 self._transition_out()
Called when the popup is canceled.
Cancels can occur due to clicking outside the window, hitting escape, etc.