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

Called when the popup is canceled.

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