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()
class TournamentScoresWindow(bauiv1lib.popup.PopupWindow):
 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.