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

Called when the popup is canceled.

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