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 style='bomb', 97 size=48, 98 ) 99 self._loading_text = bui.textwidget( 100 parent=self._scrollwidget, 101 scale=0.5, 102 text='', 103 size=(self._width - 60, 100), 104 h_align='center', 105 v_align='center', 106 ) 107 108 bui.containerwidget( 109 edit=self.root_widget, cancel_button=self._cancel_button 110 ) 111 112 plus.tournament_query( 113 args={ 114 'tournamentIDs': [tournament_id], 115 'numScores': 50, 116 'source': 'scores window', 117 }, 118 callback=bui.WeakCall(self._on_tournament_query_response), 119 ) 120 121 def _on_tournament_query_response( 122 self, data: dict[str, Any] | None 123 ) -> None: 124 if data is not None: 125 # This used to be the whole payload. 126 data_t: list[dict[str, Any]] = data['t'] 127 128 # Kill our loading text if we've got scores; otherwise just 129 # replace it with 'no scores yet'. 130 bui.spinnerwidget(edit=self._loading_spinner, visible=False) 131 if data_t[0]['scores']: 132 self._loading_text.delete() 133 else: 134 bui.textwidget( 135 edit=self._loading_text, 136 text=bui.Lstr(resource='noScoresYetText'), 137 ) 138 incr = 30 139 sub_width = self._width - 90 140 sub_height = 30 + len(data_t[0]['scores']) * incr 141 self._subcontainer = bui.containerwidget( 142 parent=self._scrollwidget, 143 size=(sub_width, sub_height), 144 background=False, 145 ) 146 for i, entry in enumerate(data_t[0]['scores']): 147 bui.textwidget( 148 parent=self._subcontainer, 149 position=(sub_width * 0.1 - 5, sub_height - 20 - incr * i), 150 maxwidth=20, 151 scale=0.5, 152 color=(0.6, 0.6, 0.7), 153 flatness=1.0, 154 shadow=0.0, 155 text=str(i + 1), 156 size=(0, 0), 157 h_align='right', 158 v_align='center', 159 ) 160 161 bui.textwidget( 162 parent=self._subcontainer, 163 position=(sub_width * 0.25 - 2, sub_height - 20 - incr * i), 164 maxwidth=sub_width * 0.24, 165 color=(0.9, 1.0, 0.9), 166 flatness=1.0, 167 shadow=0.0, 168 scale=0.6, 169 text=( 170 bui.timestring( 171 (entry[0] * 10) / 1000.0, 172 centi=True, 173 ) 174 if data_t[0]['scoreType'] == 'time' 175 else str(entry[0]) 176 ), 177 size=(0, 0), 178 h_align='center', 179 v_align='center', 180 ) 181 182 txt = bui.textwidget( 183 parent=self._subcontainer, 184 position=( 185 sub_width * 0.25, 186 sub_height - 20 - incr * i - (0.5 / 0.7) * incr, 187 ), 188 maxwidth=sub_width * 0.6, 189 scale=0.7, 190 flatness=1.0, 191 shadow=0.0, 192 text=bui.Lstr(value=entry[1]), 193 selectable=True, 194 click_activate=True, 195 autoselect=True, 196 extra_touch_border_scale=0.0, 197 size=((sub_width * 0.6) / 0.7, incr / 0.7), 198 h_align='left', 199 v_align='center', 200 ) 201 202 bui.textwidget( 203 edit=txt, 204 on_activate_call=bui.Call( 205 self._show_player_info, entry, txt 206 ), 207 ) 208 if i == 0: 209 bui.widget(edit=txt, up_widget=self._cancel_button) 210 211 def _show_player_info(self, entry: Any, textwidget: bui.Widget) -> None: 212 from bauiv1lib.account.viewer import AccountViewerWindow 213 214 # For the moment we only work if a single player-info is 215 # present. 216 if len(entry[2]) != 1: 217 bui.getsound('error').play() 218 return 219 bui.getsound('swish').play() 220 AccountViewerWindow( 221 account_id=entry[2][0].get('a', None), 222 profile_id=entry[2][0].get('p', None), 223 position=textwidget.get_screen_space_center(), 224 ) 225 self._transition_out() 226 227 def _on_cancel_press(self) -> None: 228 self._transition_out() 229 230 def _transition_out(self) -> None: 231 if not self._transitioning_out: 232 self._transitioning_out = True 233 bui.containerwidget(edit=self.root_widget, transition='out_scale') 234 235 @override 236 def on_popup_cancel(self) -> None: 237 bui.getsound('swish').play() 238 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 style='bomb', 98 size=48, 99 ) 100 self._loading_text = bui.textwidget( 101 parent=self._scrollwidget, 102 scale=0.5, 103 text='', 104 size=(self._width - 60, 100), 105 h_align='center', 106 v_align='center', 107 ) 108 109 bui.containerwidget( 110 edit=self.root_widget, cancel_button=self._cancel_button 111 ) 112 113 plus.tournament_query( 114 args={ 115 'tournamentIDs': [tournament_id], 116 'numScores': 50, 117 'source': 'scores window', 118 }, 119 callback=bui.WeakCall(self._on_tournament_query_response), 120 ) 121 122 def _on_tournament_query_response( 123 self, data: dict[str, Any] | None 124 ) -> None: 125 if data is not None: 126 # This used to be the whole payload. 127 data_t: list[dict[str, Any]] = data['t'] 128 129 # Kill our loading text if we've got scores; otherwise just 130 # replace it with 'no scores yet'. 131 bui.spinnerwidget(edit=self._loading_spinner, visible=False) 132 if data_t[0]['scores']: 133 self._loading_text.delete() 134 else: 135 bui.textwidget( 136 edit=self._loading_text, 137 text=bui.Lstr(resource='noScoresYetText'), 138 ) 139 incr = 30 140 sub_width = self._width - 90 141 sub_height = 30 + len(data_t[0]['scores']) * incr 142 self._subcontainer = bui.containerwidget( 143 parent=self._scrollwidget, 144 size=(sub_width, sub_height), 145 background=False, 146 ) 147 for i, entry in enumerate(data_t[0]['scores']): 148 bui.textwidget( 149 parent=self._subcontainer, 150 position=(sub_width * 0.1 - 5, sub_height - 20 - incr * i), 151 maxwidth=20, 152 scale=0.5, 153 color=(0.6, 0.6, 0.7), 154 flatness=1.0, 155 shadow=0.0, 156 text=str(i + 1), 157 size=(0, 0), 158 h_align='right', 159 v_align='center', 160 ) 161 162 bui.textwidget( 163 parent=self._subcontainer, 164 position=(sub_width * 0.25 - 2, sub_height - 20 - incr * i), 165 maxwidth=sub_width * 0.24, 166 color=(0.9, 1.0, 0.9), 167 flatness=1.0, 168 shadow=0.0, 169 scale=0.6, 170 text=( 171 bui.timestring( 172 (entry[0] * 10) / 1000.0, 173 centi=True, 174 ) 175 if data_t[0]['scoreType'] == 'time' 176 else str(entry[0]) 177 ), 178 size=(0, 0), 179 h_align='center', 180 v_align='center', 181 ) 182 183 txt = bui.textwidget( 184 parent=self._subcontainer, 185 position=( 186 sub_width * 0.25, 187 sub_height - 20 - incr * i - (0.5 / 0.7) * incr, 188 ), 189 maxwidth=sub_width * 0.6, 190 scale=0.7, 191 flatness=1.0, 192 shadow=0.0, 193 text=bui.Lstr(value=entry[1]), 194 selectable=True, 195 click_activate=True, 196 autoselect=True, 197 extra_touch_border_scale=0.0, 198 size=((sub_width * 0.6) / 0.7, incr / 0.7), 199 h_align='left', 200 v_align='center', 201 ) 202 203 bui.textwidget( 204 edit=txt, 205 on_activate_call=bui.Call( 206 self._show_player_info, entry, txt 207 ), 208 ) 209 if i == 0: 210 bui.widget(edit=txt, up_widget=self._cancel_button) 211 212 def _show_player_info(self, entry: Any, textwidget: bui.Widget) -> None: 213 from bauiv1lib.account.viewer import AccountViewerWindow 214 215 # For the moment we only work if a single player-info is 216 # present. 217 if len(entry[2]) != 1: 218 bui.getsound('error').play() 219 return 220 bui.getsound('swish').play() 221 AccountViewerWindow( 222 account_id=entry[2][0].get('a', None), 223 profile_id=entry[2][0].get('p', None), 224 position=textwidget.get_screen_space_center(), 225 ) 226 self._transition_out() 227 228 def _on_cancel_press(self) -> None: 229 self._transition_out() 230 231 def _transition_out(self) -> None: 232 if not self._transitioning_out: 233 self._transitioning_out = True 234 bui.containerwidget(edit=self.root_widget, transition='out_scale') 235 236 @override 237 def on_popup_cancel(self) -> None: 238 bui.getsound('swish').play() 239 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 style='bomb', 98 size=48, 99 ) 100 self._loading_text = bui.textwidget( 101 parent=self._scrollwidget, 102 scale=0.5, 103 text='', 104 size=(self._width - 60, 100), 105 h_align='center', 106 v_align='center', 107 ) 108 109 bui.containerwidget( 110 edit=self.root_widget, cancel_button=self._cancel_button 111 ) 112 113 plus.tournament_query( 114 args={ 115 'tournamentIDs': [tournament_id], 116 'numScores': 50, 117 'source': 'scores window', 118 }, 119 callback=bui.WeakCall(self._on_tournament_query_response), 120 )
@override
def
on_popup_cancel(self) -> None:
236 @override 237 def on_popup_cancel(self) -> None: 238 bui.getsound('swish').play() 239 self._transition_out()
Called when the popup is canceled.
Cancels can occur due to clicking outside the window, hitting escape, etc.