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

Window for viewing tournament scores.

TournamentScoresWindow( tournament_id: str, tournament_activity: ba._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)
 21    def __init__(self,
 22                 tournament_id: str,
 23                 tournament_activity: ba.GameActivity | None = None,
 24                 position: tuple[float, float] = (0.0, 0.0),
 25                 scale: float | None = None,
 26                 offset: tuple[float, float] = (0.0, 0.0),
 27                 tint_color: Sequence[float] = (1.0, 1.0, 1.0),
 28                 tint2_color: Sequence[float] = (1.0, 1.0, 1.0),
 29                 selected_character: str | None = None,
 30                 on_close_call: Callable[[], Any] | None = None):
 31
 32        del tournament_activity  # unused arg
 33        del tint_color  # unused arg
 34        del tint2_color  # unused arg
 35        del selected_character  # unused arg
 36        self._tournament_id = tournament_id
 37        self._subcontainer: ba.Widget | None = None
 38        self._on_close_call = on_close_call
 39        uiscale = ba.app.ui.uiscale
 40        if scale is None:
 41            scale = (2.3 if uiscale is ba.UIScale.SMALL else
 42                     1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
 43        self._transitioning_out = False
 44
 45        self._width = 400
 46        self._height = (300 if uiscale is ba.UIScale.SMALL else
 47                        370 if uiscale is ba.UIScale.MEDIUM else 450)
 48
 49        bg_color = (0.5, 0.4, 0.6)
 50
 51        # creates our _root_widget
 52        super().__init__(position=position,
 53                         size=(self._width, self._height),
 54                         scale=scale,
 55                         bg_color=bg_color,
 56                         offset=offset)
 57
 58        # app = ba.app
 59
 60        self._cancel_button = ba.buttonwidget(
 61            parent=self.root_widget,
 62            position=(50, self._height - 30),
 63            size=(50, 50),
 64            scale=0.5,
 65            label='',
 66            color=bg_color,
 67            on_activate_call=self._on_cancel_press,
 68            autoselect=True,
 69            icon=ba.gettexture('crossOut'),
 70            iconscale=1.2)
 71
 72        self._title_text = ba.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=ba.Lstr(resource='tournamentStandingsText'),
 80            maxwidth=200,
 81            color=(1, 1, 1, 0.4))
 82
 83        self._scrollwidget = ba.scrollwidget(parent=self.root_widget,
 84                                             size=(self._width - 60,
 85                                                   self._height - 70),
 86                                             position=(30, 30),
 87                                             highlight=False,
 88                                             simple_culling_v=10)
 89        ba.widget(edit=self._scrollwidget, autoselect=True)
 90
 91        self._loading_text = ba.textwidget(
 92            parent=self._scrollwidget,
 93            scale=0.5,
 94            text=ba.Lstr(value='${A}...',
 95                         subs=[('${A}', ba.Lstr(resource='loadingText'))]),
 96            size=(self._width - 60, 100),
 97            h_align='center',
 98            v_align='center')
 99
100        ba.containerwidget(edit=self.root_widget,
101                           cancel_button=self._cancel_button)
102
103        _ba.tournament_query(args={
104            'tournamentIDs': [tournament_id],
105            'numScores': 50,
106            'source': 'scores window'
107        },
108                             callback=ba.WeakCall(
109                                 self._on_tournament_query_response))
def on_popup_cancel(self) -> None:
208    def on_popup_cancel(self) -> None:
209        ba.playsound(ba.getsound('swish'))
210        self._transition_out()

Called when the popup is canceled.

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