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()
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            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.