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

Window for viewing tournament scores.

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

Called when the popup is canceled.

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