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

Window for viewing tournament scores.

TournamentScoresWindow( tournament_id: str, tournament_activity: bascenev1.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)
 22    def __init__(
 23        self,
 24        tournament_id: str,
 25        tournament_activity: bs.GameActivity | None = None,
 26        position: tuple[float, float] = (0.0, 0.0),
 27        scale: float | None = None,
 28        offset: tuple[float, float] = (0.0, 0.0),
 29        tint_color: Sequence[float] = (1.0, 1.0, 1.0),
 30        tint2_color: Sequence[float] = (1.0, 1.0, 1.0),
 31        selected_character: str | None = None,
 32        on_close_call: Callable[[], Any] | None = None,
 33    ):
 34        plus = bui.app.plus
 35        assert plus is not None
 36
 37        del tournament_activity  # unused arg
 38        del tint_color  # unused arg
 39        del tint2_color  # unused arg
 40        del selected_character  # unused arg
 41        self._tournament_id = tournament_id
 42        self._subcontainer: bui.Widget | None = None
 43        self._on_close_call = on_close_call
 44        assert bui.app.classic is not None
 45        uiscale = bui.app.ui_v1.uiscale
 46        if scale is None:
 47            scale = (
 48                2.3
 49                if uiscale is bui.UIScale.SMALL
 50                else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23
 51            )
 52        self._transitioning_out = False
 53
 54        self._width = 400
 55        self._height = (
 56            300
 57            if uiscale is bui.UIScale.SMALL
 58            else 370 if uiscale is bui.UIScale.MEDIUM else 450
 59        )
 60
 61        bg_color = (0.5, 0.4, 0.6)
 62
 63        # creates our _root_widget
 64        super().__init__(
 65            position=position,
 66            size=(self._width, self._height),
 67            scale=scale,
 68            bg_color=bg_color,
 69            offset=offset,
 70        )
 71
 72        self._cancel_button = bui.buttonwidget(
 73            parent=self.root_widget,
 74            position=(50, self._height - 30),
 75            size=(50, 50),
 76            scale=0.5,
 77            label='',
 78            color=bg_color,
 79            on_activate_call=self._on_cancel_press,
 80            autoselect=True,
 81            icon=bui.gettexture('crossOut'),
 82            iconscale=1.2,
 83        )
 84
 85        self._title_text = bui.textwidget(
 86            parent=self.root_widget,
 87            position=(self._width * 0.5, self._height - 20),
 88            size=(0, 0),
 89            h_align='center',
 90            v_align='center',
 91            scale=0.6,
 92            text=bui.Lstr(resource='tournamentStandingsText'),
 93            maxwidth=200,
 94            color=(1, 1, 1, 0.4),
 95        )
 96
 97        self._scrollwidget = bui.scrollwidget(
 98            parent=self.root_widget,
 99            size=(self._width - 60, self._height - 70),
100            position=(30, 30),
101            highlight=False,
102            simple_culling_v=10,
103        )
104        bui.widget(edit=self._scrollwidget, autoselect=True)
105
106        self._loading_text = bui.textwidget(
107            parent=self._scrollwidget,
108            scale=0.5,
109            text=bui.Lstr(
110                value='${A}...',
111                subs=[('${A}', bui.Lstr(resource='loadingText'))],
112            ),
113            size=(self._width - 60, 100),
114            h_align='center',
115            v_align='center',
116        )
117
118        bui.containerwidget(
119            edit=self.root_widget, cancel_button=self._cancel_button
120        )
121
122        plus.tournament_query(
123            args={
124                'tournamentIDs': [tournament_id],
125                'numScores': 50,
126                'source': 'scores window',
127            },
128            callback=bui.WeakCall(self._on_tournament_query_response),
129        )
@override
def on_popup_cancel(self) -> None:
244    @override
245    def on_popup_cancel(self) -> None:
246        bui.getsound('swish').play()
247        self._transition_out()

Called when the popup is canceled.

Cancels can occur due to clicking outside the window, hitting escape, etc.