bastd.ui.coop.tournamentbutton

Defines button for co-op games.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Defines button for co-op games."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING
  8import copy
  9
 10import ba
 11import _ba
 12
 13if TYPE_CHECKING:
 14    from typing import Any, Callable
 15
 16
 17class TournamentButton:
 18    """Button showing a tournament in coop window."""
 19
 20    def __init__(self, parent: ba.Widget, x: float, y: float, select: bool,
 21                 on_pressed: Callable[[TournamentButton], None]) -> None:
 22        self._r = 'coopSelectWindow'
 23        sclx = 300
 24        scly = 195.0
 25        self.on_pressed = on_pressed
 26        self.lsbt = ba.getmodel('level_select_button_transparent')
 27        self.lsbo = ba.getmodel('level_select_button_opaque')
 28        self.allow_ads = False
 29        self.tournament_id: str | None = None
 30        self.time_remaining: int = 0
 31        self.has_time_remaining: bool = False
 32        self.leader: Any = None
 33        self.required_league: str | None = None
 34        self.button = btn = ba.buttonwidget(
 35            parent=parent,
 36            position=(x + 23, y + 4),
 37            size=(sclx, scly),
 38            label='',
 39            button_type='square',
 40            autoselect=True,
 41            # on_activate_call=lambda: self.run(None, tournament_button=data)
 42            on_activate_call=ba.WeakCall(self._pressed))
 43        ba.widget(edit=btn,
 44                  show_buffer_bottom=50,
 45                  show_buffer_top=50,
 46                  show_buffer_left=400,
 47                  show_buffer_right=200)
 48        if select:
 49            ba.containerwidget(edit=parent,
 50                               selected_child=btn,
 51                               visible_child=btn)
 52        image_width = sclx * 0.85 * 0.75
 53
 54        self.image = ba.imagewidget(
 55            parent=parent,
 56            draw_controller=btn,
 57            position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 150),
 58            size=(image_width, image_width * 0.5),
 59            model_transparent=self.lsbt,
 60            model_opaque=self.lsbo,
 61            texture=ba.gettexture('black'),
 62            opacity=0.2,
 63            mask_texture=ba.gettexture('mapPreviewMask'))
 64
 65        self.lock_image = ba.imagewidget(
 66            parent=parent,
 67            draw_controller=btn,
 68            position=(x + 21 + sclx * 0.5 - image_width * 0.25,
 69                      y + scly - 150),
 70            size=(image_width * 0.5, image_width * 0.5),
 71            texture=ba.gettexture('lock'),
 72            opacity=0.0)
 73
 74        self.button_text = ba.textwidget(parent=parent,
 75                                         draw_controller=btn,
 76                                         position=(x + 20 + sclx * 0.5,
 77                                                   y + scly - 35),
 78                                         size=(0, 0),
 79                                         h_align='center',
 80                                         text='-',
 81                                         v_align='center',
 82                                         maxwidth=sclx * 0.76,
 83                                         scale=0.85,
 84                                         color=(0.8, 1.0, 0.8, 1.0))
 85
 86        header_color = (0.43, 0.4, 0.5, 1)
 87        value_color = (0.6, 0.6, 0.6, 1)
 88
 89        x_offs = 0
 90        ba.textwidget(parent=parent,
 91                      draw_controller=btn,
 92                      position=(x + 360, y + scly - 20),
 93                      size=(0, 0),
 94                      h_align='center',
 95                      text=ba.Lstr(resource=self._r + '.entryFeeText'),
 96                      v_align='center',
 97                      maxwidth=100,
 98                      scale=0.9,
 99                      color=header_color,
100                      flatness=1.0)
101
102        self.entry_fee_text_top = ba.textwidget(parent=parent,
103                                                draw_controller=btn,
104                                                position=(x + 360,
105                                                          y + scly - 60),
106                                                size=(0, 0),
107                                                h_align='center',
108                                                text='-',
109                                                v_align='center',
110                                                maxwidth=60,
111                                                scale=1.3,
112                                                color=value_color,
113                                                flatness=1.0)
114        self.entry_fee_text_or = ba.textwidget(parent=parent,
115                                               draw_controller=btn,
116                                               position=(x + 360,
117                                                         y + scly - 90),
118                                               size=(0, 0),
119                                               h_align='center',
120                                               text='',
121                                               v_align='center',
122                                               maxwidth=60,
123                                               scale=0.5,
124                                               color=value_color,
125                                               flatness=1.0)
126        self.entry_fee_text_remaining = ba.textwidget(parent=parent,
127                                                      draw_controller=btn,
128                                                      position=(x + 360,
129                                                                y + scly - 90),
130                                                      size=(0, 0),
131                                                      h_align='center',
132                                                      text='',
133                                                      v_align='center',
134                                                      maxwidth=60,
135                                                      scale=0.5,
136                                                      color=value_color,
137                                                      flatness=1.0)
138
139        self.entry_fee_ad_image = ba.imagewidget(parent=parent,
140                                                 size=(40, 40),
141                                                 draw_controller=btn,
142                                                 position=(x + 360 - 20,
143                                                           y + scly - 140),
144                                                 opacity=0.0,
145                                                 texture=ba.gettexture('tv'))
146
147        x_offs += 50
148
149        ba.textwidget(parent=parent,
150                      draw_controller=btn,
151                      position=(x + 447 + x_offs, y + scly - 20),
152                      size=(0, 0),
153                      h_align='center',
154                      text=ba.Lstr(resource=self._r + '.prizesText'),
155                      v_align='center',
156                      maxwidth=130,
157                      scale=0.9,
158                      color=header_color,
159                      flatness=1.0)
160
161        self.button_x = x
162        self.button_y = y
163        self.button_scale_y = scly
164
165        xo2 = 0
166        prize_value_scale = 1.5
167
168        self.prize_range_1_text = ba.textwidget(
169            parent=parent,
170            draw_controller=btn,
171            position=(x + 355 + xo2 + x_offs, y + scly - 93),
172            size=(0, 0),
173            h_align='right',
174            v_align='center',
175            maxwidth=50,
176            text='-',
177            scale=0.8,
178            color=header_color,
179            flatness=1.0)
180        self.prize_value_1_text = ba.textwidget(
181            parent=parent,
182            draw_controller=btn,
183            position=(x + 380 + xo2 + x_offs, y + scly - 93),
184            size=(0, 0),
185            h_align='left',
186            text='-',
187            v_align='center',
188            maxwidth=100,
189            scale=prize_value_scale,
190            color=value_color,
191            flatness=1.0)
192
193        self.prize_range_2_text = ba.textwidget(
194            parent=parent,
195            draw_controller=btn,
196            position=(x + 355 + xo2 + x_offs, y + scly - 93),
197            size=(0, 0),
198            h_align='right',
199            v_align='center',
200            maxwidth=50,
201            scale=0.8,
202            color=header_color,
203            flatness=1.0)
204        self.prize_value_2_text = ba.textwidget(
205            parent=parent,
206            draw_controller=btn,
207            position=(x + 380 + xo2 + x_offs, y + scly - 93),
208            size=(0, 0),
209            h_align='left',
210            text='',
211            v_align='center',
212            maxwidth=100,
213            scale=prize_value_scale,
214            color=value_color,
215            flatness=1.0)
216
217        self.prize_range_3_text = ba.textwidget(
218            parent=parent,
219            draw_controller=btn,
220            position=(x + 355 + xo2 + x_offs, y + scly - 93),
221            size=(0, 0),
222            h_align='right',
223            v_align='center',
224            maxwidth=50,
225            scale=0.8,
226            color=header_color,
227            flatness=1.0)
228        self.prize_value_3_text = ba.textwidget(
229            parent=parent,
230            draw_controller=btn,
231            position=(x + 380 + xo2 + x_offs, y + scly - 93),
232            size=(0, 0),
233            h_align='left',
234            text='',
235            v_align='center',
236            maxwidth=100,
237            scale=prize_value_scale,
238            color=value_color,
239            flatness=1.0)
240
241        ba.textwidget(parent=parent,
242                      draw_controller=btn,
243                      position=(x + 620 + x_offs, y + scly - 20),
244                      size=(0, 0),
245                      h_align='center',
246                      text=ba.Lstr(resource=self._r + '.currentBestText'),
247                      v_align='center',
248                      maxwidth=180,
249                      scale=0.9,
250                      color=header_color,
251                      flatness=1.0)
252        self.current_leader_name_text = ba.textwidget(
253            parent=parent,
254            draw_controller=btn,
255            position=(x + 620 + x_offs - (170 / 1.4) * 0.5,
256                      y + scly - 60 - 40 * 0.5),
257            selectable=True,
258            click_activate=True,
259            autoselect=True,
260            on_activate_call=ba.WeakCall(self._show_leader),
261            size=(170 / 1.4, 40),
262            h_align='center',
263            text='-',
264            v_align='center',
265            maxwidth=170,
266            scale=1.4,
267            color=value_color,
268            flatness=1.0)
269        self.current_leader_score_text = ba.textwidget(
270            parent=parent,
271            draw_controller=btn,
272            position=(x + 620 + x_offs, y + scly - 113 + 10),
273            size=(0, 0),
274            h_align='center',
275            text='-',
276            v_align='center',
277            maxwidth=170,
278            scale=1.8,
279            color=value_color,
280            flatness=1.0)
281
282        self.more_scores_button = ba.buttonwidget(
283            parent=parent,
284            position=(x + 620 + x_offs - 60, y + scly - 50 - 125),
285            color=(0.5, 0.5, 0.6),
286            textcolor=(0.7, 0.7, 0.8),
287            label='-',
288            size=(120, 40),
289            autoselect=True,
290            up_widget=self.current_leader_name_text,
291            text_scale=0.6,
292            on_activate_call=ba.WeakCall(self._show_scores))
293        ba.widget(edit=self.current_leader_name_text,
294                  down_widget=self.more_scores_button)
295
296        ba.textwidget(parent=parent,
297                      draw_controller=btn,
298                      position=(x + 820 + x_offs, y + scly - 20),
299                      size=(0, 0),
300                      h_align='center',
301                      text=ba.Lstr(resource=self._r + '.timeRemainingText'),
302                      v_align='center',
303                      maxwidth=180,
304                      scale=0.9,
305                      color=header_color,
306                      flatness=1.0)
307        self.time_remaining_value_text = ba.textwidget(
308            parent=parent,
309            draw_controller=btn,
310            position=(x + 820 + x_offs, y + scly - 68),
311            size=(0, 0),
312            h_align='center',
313            text='-',
314            v_align='center',
315            maxwidth=180,
316            scale=2.0,
317            color=value_color,
318            flatness=1.0)
319        self.time_remaining_out_of_text = ba.textwidget(
320            parent=parent,
321            draw_controller=btn,
322            position=(x + 820 + x_offs, y + scly - 110),
323            size=(0, 0),
324            h_align='center',
325            text='-',
326            v_align='center',
327            maxwidth=120,
328            scale=0.72,
329            color=(0.4, 0.4, 0.5),
330            flatness=1.0)
331
332    def _pressed(self) -> None:
333        self.on_pressed(self)
334
335    def _show_leader(self) -> None:
336        # pylint: disable=cyclic-import
337        from bastd.ui.account.viewer import AccountViewerWindow
338        tournament_id = self.tournament_id
339
340        # FIXME: This assumes a single player entry in leader; should expand
341        #  this to work with multiple.
342        if tournament_id is None or self.leader is None or len(
343                self.leader[2]) != 1:
344            ba.playsound(ba.getsound('error'))
345            return
346        ba.playsound(ba.getsound('swish'))
347        AccountViewerWindow(
348            account_id=self.leader[2][0].get('a', None),
349            profile_id=self.leader[2][0].get('p', None),
350            position=self.current_leader_name_text.get_screen_space_center())
351
352    def _show_scores(self) -> None:
353        # pylint: disable=cyclic-import
354        from bastd.ui.tournamentscores import TournamentScoresWindow
355        tournament_id = self.tournament_id
356        if tournament_id is None:
357            ba.playsound(ba.getsound('error'))
358            return
359
360        TournamentScoresWindow(
361            tournament_id=tournament_id,
362            position=self.more_scores_button.get_screen_space_center())
363
364    def update_for_data(self, entry: dict[str, Any]) -> None:
365        """Update for new incoming data."""
366        # pylint: disable=too-many-statements
367        # pylint: disable=too-many-locals
368        # pylint: disable=too-many-branches
369        from ba.internal import getcampaign, get_tournament_prize_strings
370        prize_y_offs = (34 if 'prizeRange3' in entry else
371                        20 if 'prizeRange2' in entry else 12)
372        x_offs = 90
373
374        # This seems to be a false alarm.
375        # pylint: disable=unbalanced-tuple-unpacking
376        pr1, pv1, pr2, pv2, pr3, pv3 = (get_tournament_prize_strings(entry))
377        # pylint: enable=unbalanced-tuple-unpacking
378        enabled = 'requiredLeague' not in entry
379        ba.buttonwidget(edit=self.button,
380                        color=(0.5, 0.7, 0.2) if enabled else (0.5, 0.5, 0.5))
381        ba.imagewidget(edit=self.lock_image, opacity=0.0 if enabled else 1.0)
382        ba.textwidget(edit=self.prize_range_1_text,
383                      text='-' if pr1 == '' else pr1,
384                      position=(self.button_x + 365 + x_offs, self.button_y +
385                                self.button_scale_y - 93 + prize_y_offs))
386
387        # We want to draw values containing tickets a bit smaller
388        # (scratch that; we now draw medals a bit bigger).
389        ticket_char = ba.charstr(ba.SpecialChar.TICKET_BACKING)
390        prize_value_scale_large = 1.0
391        prize_value_scale_small = 1.0
392
393        ba.textwidget(edit=self.prize_value_1_text,
394                      text='-' if pv1 == '' else pv1,
395                      scale=prize_value_scale_large
396                      if ticket_char not in pv1 else prize_value_scale_small,
397                      position=(self.button_x + 380 + x_offs, self.button_y +
398                                self.button_scale_y - 93 + prize_y_offs))
399
400        ba.textwidget(edit=self.prize_range_2_text,
401                      text=pr2,
402                      position=(self.button_x + 365 + x_offs, self.button_y +
403                                self.button_scale_y - 93 - 45 + prize_y_offs))
404        ba.textwidget(edit=self.prize_value_2_text,
405                      text=pv2,
406                      scale=prize_value_scale_large
407                      if ticket_char not in pv2 else prize_value_scale_small,
408                      position=(self.button_x + 380 + x_offs, self.button_y +
409                                self.button_scale_y - 93 - 45 + prize_y_offs))
410
411        ba.textwidget(edit=self.prize_range_3_text,
412                      text=pr3,
413                      position=(self.button_x + 365 + x_offs, self.button_y +
414                                self.button_scale_y - 93 - 90 + prize_y_offs))
415        ba.textwidget(edit=self.prize_value_3_text,
416                      text=pv3,
417                      scale=prize_value_scale_large
418                      if ticket_char not in pv3 else prize_value_scale_small,
419                      position=(self.button_x + 380 + x_offs, self.button_y +
420                                self.button_scale_y - 93 - 90 + prize_y_offs))
421
422        leader_name = '-'
423        leader_score: str | ba.Lstr = '-'
424        if entry['scores']:
425            score = self.leader = copy.deepcopy(entry['scores'][0])
426            leader_name = score[1]
427            leader_score = (ba.timestring(
428                score[0] * 10,
429                centi=True,
430                timeformat=ba.TimeFormat.MILLISECONDS,
431                suppress_format_warning=True)
432                            if entry['scoreType'] == 'time' else str(score[0]))
433        else:
434            self.leader = None
435
436        ba.textwidget(edit=self.current_leader_name_text,
437                      text=ba.Lstr(value=leader_name))
438        ba.textwidget(edit=self.current_leader_score_text, text=leader_score)
439        ba.buttonwidget(edit=self.more_scores_button,
440                        label=ba.Lstr(resource=self._r + '.seeMoreText'))
441        out_of_time_text: str | ba.Lstr = (
442            '-' if 'totalTime' not in entry else ba.Lstr(
443                resource=self._r + '.ofTotalTimeText',
444                subs=[('${TOTAL}',
445                       ba.timestring(entry['totalTime'],
446                                     centi=False,
447                                     suppress_format_warning=True))]))
448        ba.textwidget(edit=self.time_remaining_out_of_text,
449                      text=out_of_time_text)
450
451        self.time_remaining = entry['timeRemaining']
452        self.has_time_remaining = entry is not None
453        self.tournament_id = entry['tournamentID']
454        self.required_league = (None if 'requiredLeague' not in entry else
455                                entry['requiredLeague'])
456
457        game = ba.app.accounts_v1.tournament_info[self.tournament_id]['game']
458
459        if game is None:
460            ba.textwidget(edit=self.button_text, text='-')
461            ba.imagewidget(edit=self.image,
462                           texture=ba.gettexture('black'),
463                           opacity=0.2)
464        else:
465            campaignname, levelname = game.split(':')
466            campaign = getcampaign(campaignname)
467            max_players = ba.app.accounts_v1.tournament_info[
468                self.tournament_id]['maxPlayers']
469            txt = ba.Lstr(value='${A} ${B}',
470                          subs=[('${A}',
471                                 campaign.getlevel(levelname).displayname),
472                                ('${B}',
473                                 ba.Lstr(resource='playerCountAbbreviatedText',
474                                         subs=[('${COUNT}', str(max_players))
475                                               ]))])
476            ba.textwidget(edit=self.button_text, text=txt)
477            ba.imagewidget(
478                edit=self.image,
479                texture=campaign.getlevel(levelname).get_preview_texture(),
480                opacity=1.0 if enabled else 0.5)
481
482        fee = entry['fee']
483
484        if fee is None:
485            fee_var = None
486        elif fee == 4:
487            fee_var = 'price.tournament_entry_4'
488        elif fee == 3:
489            fee_var = 'price.tournament_entry_3'
490        elif fee == 2:
491            fee_var = 'price.tournament_entry_2'
492        elif fee == 1:
493            fee_var = 'price.tournament_entry_1'
494        else:
495            if fee != 0:
496                print('Unknown fee value:', fee)
497            fee_var = 'price.tournament_entry_0'
498
499        self.allow_ads = allow_ads = entry['allowAds']
500
501        final_fee: int | None = (None if fee_var is None else
502                                 _ba.get_v1_account_misc_read_val(
503                                     fee_var, '?'))
504
505        final_fee_str: str | ba.Lstr
506        if fee_var is None:
507            final_fee_str = ''
508        else:
509            if final_fee == 0:
510                final_fee_str = ba.Lstr(resource='getTicketsWindow.freeText')
511            else:
512                final_fee_str = (ba.charstr(ba.SpecialChar.TICKET_BACKING) +
513                                 str(final_fee))
514
515        ad_tries_remaining = ba.app.accounts_v1.tournament_info[
516            self.tournament_id]['adTriesRemaining']
517        free_tries_remaining = ba.app.accounts_v1.tournament_info[
518            self.tournament_id]['freeTriesRemaining']
519
520        # Now, if this fee allows ads and we support video ads, show
521        # the 'or ad' version.
522        if allow_ads and _ba.has_video_ads():
523            ads_enabled = _ba.have_incentivized_ad()
524            ba.imagewidget(edit=self.entry_fee_ad_image,
525                           opacity=1.0 if ads_enabled else 0.25)
526            or_text = ba.Lstr(resource='orText',
527                              subs=[('${A}', ''),
528                                    ('${B}', '')]).evaluate().strip()
529            ba.textwidget(edit=self.entry_fee_text_or, text=or_text)
530            ba.textwidget(edit=self.entry_fee_text_top,
531                          position=(self.button_x + 360,
532                                    self.button_y + self.button_scale_y - 60),
533                          scale=1.3,
534                          text=final_fee_str)
535
536            # Possibly show number of ad-plays remaining.
537            ba.textwidget(edit=self.entry_fee_text_remaining,
538                          position=(self.button_x + 360,
539                                    self.button_y + self.button_scale_y - 146),
540                          text='' if ad_tries_remaining in [None, 0] else
541                          ('' + str(ad_tries_remaining)),
542                          color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
543        else:
544            ba.imagewidget(edit=self.entry_fee_ad_image, opacity=0.0)
545            ba.textwidget(edit=self.entry_fee_text_or, text='')
546            ba.textwidget(edit=self.entry_fee_text_top,
547                          position=(self.button_x + 360,
548                                    self.button_y + self.button_scale_y - 80),
549                          scale=1.3,
550                          text=final_fee_str)
551
552            # Possibly show number of free-plays remaining.
553            ba.textwidget(
554                edit=self.entry_fee_text_remaining,
555                position=(self.button_x + 360,
556                          self.button_y + self.button_scale_y - 100),
557                text=('' if (free_tries_remaining in [None, 0]
558                             or final_fee != 0) else
559                      ('' + str(free_tries_remaining))),
560                color=(0.6, 0.6, 0.6, 1),
561            )
class TournamentButton:
 18class TournamentButton:
 19    """Button showing a tournament in coop window."""
 20
 21    def __init__(self, parent: ba.Widget, x: float, y: float, select: bool,
 22                 on_pressed: Callable[[TournamentButton], None]) -> None:
 23        self._r = 'coopSelectWindow'
 24        sclx = 300
 25        scly = 195.0
 26        self.on_pressed = on_pressed
 27        self.lsbt = ba.getmodel('level_select_button_transparent')
 28        self.lsbo = ba.getmodel('level_select_button_opaque')
 29        self.allow_ads = False
 30        self.tournament_id: str | None = None
 31        self.time_remaining: int = 0
 32        self.has_time_remaining: bool = False
 33        self.leader: Any = None
 34        self.required_league: str | None = None
 35        self.button = btn = ba.buttonwidget(
 36            parent=parent,
 37            position=(x + 23, y + 4),
 38            size=(sclx, scly),
 39            label='',
 40            button_type='square',
 41            autoselect=True,
 42            # on_activate_call=lambda: self.run(None, tournament_button=data)
 43            on_activate_call=ba.WeakCall(self._pressed))
 44        ba.widget(edit=btn,
 45                  show_buffer_bottom=50,
 46                  show_buffer_top=50,
 47                  show_buffer_left=400,
 48                  show_buffer_right=200)
 49        if select:
 50            ba.containerwidget(edit=parent,
 51                               selected_child=btn,
 52                               visible_child=btn)
 53        image_width = sclx * 0.85 * 0.75
 54
 55        self.image = ba.imagewidget(
 56            parent=parent,
 57            draw_controller=btn,
 58            position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 150),
 59            size=(image_width, image_width * 0.5),
 60            model_transparent=self.lsbt,
 61            model_opaque=self.lsbo,
 62            texture=ba.gettexture('black'),
 63            opacity=0.2,
 64            mask_texture=ba.gettexture('mapPreviewMask'))
 65
 66        self.lock_image = ba.imagewidget(
 67            parent=parent,
 68            draw_controller=btn,
 69            position=(x + 21 + sclx * 0.5 - image_width * 0.25,
 70                      y + scly - 150),
 71            size=(image_width * 0.5, image_width * 0.5),
 72            texture=ba.gettexture('lock'),
 73            opacity=0.0)
 74
 75        self.button_text = ba.textwidget(parent=parent,
 76                                         draw_controller=btn,
 77                                         position=(x + 20 + sclx * 0.5,
 78                                                   y + scly - 35),
 79                                         size=(0, 0),
 80                                         h_align='center',
 81                                         text='-',
 82                                         v_align='center',
 83                                         maxwidth=sclx * 0.76,
 84                                         scale=0.85,
 85                                         color=(0.8, 1.0, 0.8, 1.0))
 86
 87        header_color = (0.43, 0.4, 0.5, 1)
 88        value_color = (0.6, 0.6, 0.6, 1)
 89
 90        x_offs = 0
 91        ba.textwidget(parent=parent,
 92                      draw_controller=btn,
 93                      position=(x + 360, y + scly - 20),
 94                      size=(0, 0),
 95                      h_align='center',
 96                      text=ba.Lstr(resource=self._r + '.entryFeeText'),
 97                      v_align='center',
 98                      maxwidth=100,
 99                      scale=0.9,
100                      color=header_color,
101                      flatness=1.0)
102
103        self.entry_fee_text_top = ba.textwidget(parent=parent,
104                                                draw_controller=btn,
105                                                position=(x + 360,
106                                                          y + scly - 60),
107                                                size=(0, 0),
108                                                h_align='center',
109                                                text='-',
110                                                v_align='center',
111                                                maxwidth=60,
112                                                scale=1.3,
113                                                color=value_color,
114                                                flatness=1.0)
115        self.entry_fee_text_or = ba.textwidget(parent=parent,
116                                               draw_controller=btn,
117                                               position=(x + 360,
118                                                         y + scly - 90),
119                                               size=(0, 0),
120                                               h_align='center',
121                                               text='',
122                                               v_align='center',
123                                               maxwidth=60,
124                                               scale=0.5,
125                                               color=value_color,
126                                               flatness=1.0)
127        self.entry_fee_text_remaining = ba.textwidget(parent=parent,
128                                                      draw_controller=btn,
129                                                      position=(x + 360,
130                                                                y + scly - 90),
131                                                      size=(0, 0),
132                                                      h_align='center',
133                                                      text='',
134                                                      v_align='center',
135                                                      maxwidth=60,
136                                                      scale=0.5,
137                                                      color=value_color,
138                                                      flatness=1.0)
139
140        self.entry_fee_ad_image = ba.imagewidget(parent=parent,
141                                                 size=(40, 40),
142                                                 draw_controller=btn,
143                                                 position=(x + 360 - 20,
144                                                           y + scly - 140),
145                                                 opacity=0.0,
146                                                 texture=ba.gettexture('tv'))
147
148        x_offs += 50
149
150        ba.textwidget(parent=parent,
151                      draw_controller=btn,
152                      position=(x + 447 + x_offs, y + scly - 20),
153                      size=(0, 0),
154                      h_align='center',
155                      text=ba.Lstr(resource=self._r + '.prizesText'),
156                      v_align='center',
157                      maxwidth=130,
158                      scale=0.9,
159                      color=header_color,
160                      flatness=1.0)
161
162        self.button_x = x
163        self.button_y = y
164        self.button_scale_y = scly
165
166        xo2 = 0
167        prize_value_scale = 1.5
168
169        self.prize_range_1_text = ba.textwidget(
170            parent=parent,
171            draw_controller=btn,
172            position=(x + 355 + xo2 + x_offs, y + scly - 93),
173            size=(0, 0),
174            h_align='right',
175            v_align='center',
176            maxwidth=50,
177            text='-',
178            scale=0.8,
179            color=header_color,
180            flatness=1.0)
181        self.prize_value_1_text = ba.textwidget(
182            parent=parent,
183            draw_controller=btn,
184            position=(x + 380 + xo2 + x_offs, y + scly - 93),
185            size=(0, 0),
186            h_align='left',
187            text='-',
188            v_align='center',
189            maxwidth=100,
190            scale=prize_value_scale,
191            color=value_color,
192            flatness=1.0)
193
194        self.prize_range_2_text = ba.textwidget(
195            parent=parent,
196            draw_controller=btn,
197            position=(x + 355 + xo2 + x_offs, y + scly - 93),
198            size=(0, 0),
199            h_align='right',
200            v_align='center',
201            maxwidth=50,
202            scale=0.8,
203            color=header_color,
204            flatness=1.0)
205        self.prize_value_2_text = ba.textwidget(
206            parent=parent,
207            draw_controller=btn,
208            position=(x + 380 + xo2 + x_offs, y + scly - 93),
209            size=(0, 0),
210            h_align='left',
211            text='',
212            v_align='center',
213            maxwidth=100,
214            scale=prize_value_scale,
215            color=value_color,
216            flatness=1.0)
217
218        self.prize_range_3_text = ba.textwidget(
219            parent=parent,
220            draw_controller=btn,
221            position=(x + 355 + xo2 + x_offs, y + scly - 93),
222            size=(0, 0),
223            h_align='right',
224            v_align='center',
225            maxwidth=50,
226            scale=0.8,
227            color=header_color,
228            flatness=1.0)
229        self.prize_value_3_text = ba.textwidget(
230            parent=parent,
231            draw_controller=btn,
232            position=(x + 380 + xo2 + x_offs, y + scly - 93),
233            size=(0, 0),
234            h_align='left',
235            text='',
236            v_align='center',
237            maxwidth=100,
238            scale=prize_value_scale,
239            color=value_color,
240            flatness=1.0)
241
242        ba.textwidget(parent=parent,
243                      draw_controller=btn,
244                      position=(x + 620 + x_offs, y + scly - 20),
245                      size=(0, 0),
246                      h_align='center',
247                      text=ba.Lstr(resource=self._r + '.currentBestText'),
248                      v_align='center',
249                      maxwidth=180,
250                      scale=0.9,
251                      color=header_color,
252                      flatness=1.0)
253        self.current_leader_name_text = ba.textwidget(
254            parent=parent,
255            draw_controller=btn,
256            position=(x + 620 + x_offs - (170 / 1.4) * 0.5,
257                      y + scly - 60 - 40 * 0.5),
258            selectable=True,
259            click_activate=True,
260            autoselect=True,
261            on_activate_call=ba.WeakCall(self._show_leader),
262            size=(170 / 1.4, 40),
263            h_align='center',
264            text='-',
265            v_align='center',
266            maxwidth=170,
267            scale=1.4,
268            color=value_color,
269            flatness=1.0)
270        self.current_leader_score_text = ba.textwidget(
271            parent=parent,
272            draw_controller=btn,
273            position=(x + 620 + x_offs, y + scly - 113 + 10),
274            size=(0, 0),
275            h_align='center',
276            text='-',
277            v_align='center',
278            maxwidth=170,
279            scale=1.8,
280            color=value_color,
281            flatness=1.0)
282
283        self.more_scores_button = ba.buttonwidget(
284            parent=parent,
285            position=(x + 620 + x_offs - 60, y + scly - 50 - 125),
286            color=(0.5, 0.5, 0.6),
287            textcolor=(0.7, 0.7, 0.8),
288            label='-',
289            size=(120, 40),
290            autoselect=True,
291            up_widget=self.current_leader_name_text,
292            text_scale=0.6,
293            on_activate_call=ba.WeakCall(self._show_scores))
294        ba.widget(edit=self.current_leader_name_text,
295                  down_widget=self.more_scores_button)
296
297        ba.textwidget(parent=parent,
298                      draw_controller=btn,
299                      position=(x + 820 + x_offs, y + scly - 20),
300                      size=(0, 0),
301                      h_align='center',
302                      text=ba.Lstr(resource=self._r + '.timeRemainingText'),
303                      v_align='center',
304                      maxwidth=180,
305                      scale=0.9,
306                      color=header_color,
307                      flatness=1.0)
308        self.time_remaining_value_text = ba.textwidget(
309            parent=parent,
310            draw_controller=btn,
311            position=(x + 820 + x_offs, y + scly - 68),
312            size=(0, 0),
313            h_align='center',
314            text='-',
315            v_align='center',
316            maxwidth=180,
317            scale=2.0,
318            color=value_color,
319            flatness=1.0)
320        self.time_remaining_out_of_text = ba.textwidget(
321            parent=parent,
322            draw_controller=btn,
323            position=(x + 820 + x_offs, y + scly - 110),
324            size=(0, 0),
325            h_align='center',
326            text='-',
327            v_align='center',
328            maxwidth=120,
329            scale=0.72,
330            color=(0.4, 0.4, 0.5),
331            flatness=1.0)
332
333    def _pressed(self) -> None:
334        self.on_pressed(self)
335
336    def _show_leader(self) -> None:
337        # pylint: disable=cyclic-import
338        from bastd.ui.account.viewer import AccountViewerWindow
339        tournament_id = self.tournament_id
340
341        # FIXME: This assumes a single player entry in leader; should expand
342        #  this to work with multiple.
343        if tournament_id is None or self.leader is None or len(
344                self.leader[2]) != 1:
345            ba.playsound(ba.getsound('error'))
346            return
347        ba.playsound(ba.getsound('swish'))
348        AccountViewerWindow(
349            account_id=self.leader[2][0].get('a', None),
350            profile_id=self.leader[2][0].get('p', None),
351            position=self.current_leader_name_text.get_screen_space_center())
352
353    def _show_scores(self) -> None:
354        # pylint: disable=cyclic-import
355        from bastd.ui.tournamentscores import TournamentScoresWindow
356        tournament_id = self.tournament_id
357        if tournament_id is None:
358            ba.playsound(ba.getsound('error'))
359            return
360
361        TournamentScoresWindow(
362            tournament_id=tournament_id,
363            position=self.more_scores_button.get_screen_space_center())
364
365    def update_for_data(self, entry: dict[str, Any]) -> None:
366        """Update for new incoming data."""
367        # pylint: disable=too-many-statements
368        # pylint: disable=too-many-locals
369        # pylint: disable=too-many-branches
370        from ba.internal import getcampaign, get_tournament_prize_strings
371        prize_y_offs = (34 if 'prizeRange3' in entry else
372                        20 if 'prizeRange2' in entry else 12)
373        x_offs = 90
374
375        # This seems to be a false alarm.
376        # pylint: disable=unbalanced-tuple-unpacking
377        pr1, pv1, pr2, pv2, pr3, pv3 = (get_tournament_prize_strings(entry))
378        # pylint: enable=unbalanced-tuple-unpacking
379        enabled = 'requiredLeague' not in entry
380        ba.buttonwidget(edit=self.button,
381                        color=(0.5, 0.7, 0.2) if enabled else (0.5, 0.5, 0.5))
382        ba.imagewidget(edit=self.lock_image, opacity=0.0 if enabled else 1.0)
383        ba.textwidget(edit=self.prize_range_1_text,
384                      text='-' if pr1 == '' else pr1,
385                      position=(self.button_x + 365 + x_offs, self.button_y +
386                                self.button_scale_y - 93 + prize_y_offs))
387
388        # We want to draw values containing tickets a bit smaller
389        # (scratch that; we now draw medals a bit bigger).
390        ticket_char = ba.charstr(ba.SpecialChar.TICKET_BACKING)
391        prize_value_scale_large = 1.0
392        prize_value_scale_small = 1.0
393
394        ba.textwidget(edit=self.prize_value_1_text,
395                      text='-' if pv1 == '' else pv1,
396                      scale=prize_value_scale_large
397                      if ticket_char not in pv1 else prize_value_scale_small,
398                      position=(self.button_x + 380 + x_offs, self.button_y +
399                                self.button_scale_y - 93 + prize_y_offs))
400
401        ba.textwidget(edit=self.prize_range_2_text,
402                      text=pr2,
403                      position=(self.button_x + 365 + x_offs, self.button_y +
404                                self.button_scale_y - 93 - 45 + prize_y_offs))
405        ba.textwidget(edit=self.prize_value_2_text,
406                      text=pv2,
407                      scale=prize_value_scale_large
408                      if ticket_char not in pv2 else prize_value_scale_small,
409                      position=(self.button_x + 380 + x_offs, self.button_y +
410                                self.button_scale_y - 93 - 45 + prize_y_offs))
411
412        ba.textwidget(edit=self.prize_range_3_text,
413                      text=pr3,
414                      position=(self.button_x + 365 + x_offs, self.button_y +
415                                self.button_scale_y - 93 - 90 + prize_y_offs))
416        ba.textwidget(edit=self.prize_value_3_text,
417                      text=pv3,
418                      scale=prize_value_scale_large
419                      if ticket_char not in pv3 else prize_value_scale_small,
420                      position=(self.button_x + 380 + x_offs, self.button_y +
421                                self.button_scale_y - 93 - 90 + prize_y_offs))
422
423        leader_name = '-'
424        leader_score: str | ba.Lstr = '-'
425        if entry['scores']:
426            score = self.leader = copy.deepcopy(entry['scores'][0])
427            leader_name = score[1]
428            leader_score = (ba.timestring(
429                score[0] * 10,
430                centi=True,
431                timeformat=ba.TimeFormat.MILLISECONDS,
432                suppress_format_warning=True)
433                            if entry['scoreType'] == 'time' else str(score[0]))
434        else:
435            self.leader = None
436
437        ba.textwidget(edit=self.current_leader_name_text,
438                      text=ba.Lstr(value=leader_name))
439        ba.textwidget(edit=self.current_leader_score_text, text=leader_score)
440        ba.buttonwidget(edit=self.more_scores_button,
441                        label=ba.Lstr(resource=self._r + '.seeMoreText'))
442        out_of_time_text: str | ba.Lstr = (
443            '-' if 'totalTime' not in entry else ba.Lstr(
444                resource=self._r + '.ofTotalTimeText',
445                subs=[('${TOTAL}',
446                       ba.timestring(entry['totalTime'],
447                                     centi=False,
448                                     suppress_format_warning=True))]))
449        ba.textwidget(edit=self.time_remaining_out_of_text,
450                      text=out_of_time_text)
451
452        self.time_remaining = entry['timeRemaining']
453        self.has_time_remaining = entry is not None
454        self.tournament_id = entry['tournamentID']
455        self.required_league = (None if 'requiredLeague' not in entry else
456                                entry['requiredLeague'])
457
458        game = ba.app.accounts_v1.tournament_info[self.tournament_id]['game']
459
460        if game is None:
461            ba.textwidget(edit=self.button_text, text='-')
462            ba.imagewidget(edit=self.image,
463                           texture=ba.gettexture('black'),
464                           opacity=0.2)
465        else:
466            campaignname, levelname = game.split(':')
467            campaign = getcampaign(campaignname)
468            max_players = ba.app.accounts_v1.tournament_info[
469                self.tournament_id]['maxPlayers']
470            txt = ba.Lstr(value='${A} ${B}',
471                          subs=[('${A}',
472                                 campaign.getlevel(levelname).displayname),
473                                ('${B}',
474                                 ba.Lstr(resource='playerCountAbbreviatedText',
475                                         subs=[('${COUNT}', str(max_players))
476                                               ]))])
477            ba.textwidget(edit=self.button_text, text=txt)
478            ba.imagewidget(
479                edit=self.image,
480                texture=campaign.getlevel(levelname).get_preview_texture(),
481                opacity=1.0 if enabled else 0.5)
482
483        fee = entry['fee']
484
485        if fee is None:
486            fee_var = None
487        elif fee == 4:
488            fee_var = 'price.tournament_entry_4'
489        elif fee == 3:
490            fee_var = 'price.tournament_entry_3'
491        elif fee == 2:
492            fee_var = 'price.tournament_entry_2'
493        elif fee == 1:
494            fee_var = 'price.tournament_entry_1'
495        else:
496            if fee != 0:
497                print('Unknown fee value:', fee)
498            fee_var = 'price.tournament_entry_0'
499
500        self.allow_ads = allow_ads = entry['allowAds']
501
502        final_fee: int | None = (None if fee_var is None else
503                                 _ba.get_v1_account_misc_read_val(
504                                     fee_var, '?'))
505
506        final_fee_str: str | ba.Lstr
507        if fee_var is None:
508            final_fee_str = ''
509        else:
510            if final_fee == 0:
511                final_fee_str = ba.Lstr(resource='getTicketsWindow.freeText')
512            else:
513                final_fee_str = (ba.charstr(ba.SpecialChar.TICKET_BACKING) +
514                                 str(final_fee))
515
516        ad_tries_remaining = ba.app.accounts_v1.tournament_info[
517            self.tournament_id]['adTriesRemaining']
518        free_tries_remaining = ba.app.accounts_v1.tournament_info[
519            self.tournament_id]['freeTriesRemaining']
520
521        # Now, if this fee allows ads and we support video ads, show
522        # the 'or ad' version.
523        if allow_ads and _ba.has_video_ads():
524            ads_enabled = _ba.have_incentivized_ad()
525            ba.imagewidget(edit=self.entry_fee_ad_image,
526                           opacity=1.0 if ads_enabled else 0.25)
527            or_text = ba.Lstr(resource='orText',
528                              subs=[('${A}', ''),
529                                    ('${B}', '')]).evaluate().strip()
530            ba.textwidget(edit=self.entry_fee_text_or, text=or_text)
531            ba.textwidget(edit=self.entry_fee_text_top,
532                          position=(self.button_x + 360,
533                                    self.button_y + self.button_scale_y - 60),
534                          scale=1.3,
535                          text=final_fee_str)
536
537            # Possibly show number of ad-plays remaining.
538            ba.textwidget(edit=self.entry_fee_text_remaining,
539                          position=(self.button_x + 360,
540                                    self.button_y + self.button_scale_y - 146),
541                          text='' if ad_tries_remaining in [None, 0] else
542                          ('' + str(ad_tries_remaining)),
543                          color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
544        else:
545            ba.imagewidget(edit=self.entry_fee_ad_image, opacity=0.0)
546            ba.textwidget(edit=self.entry_fee_text_or, text='')
547            ba.textwidget(edit=self.entry_fee_text_top,
548                          position=(self.button_x + 360,
549                                    self.button_y + self.button_scale_y - 80),
550                          scale=1.3,
551                          text=final_fee_str)
552
553            # Possibly show number of free-plays remaining.
554            ba.textwidget(
555                edit=self.entry_fee_text_remaining,
556                position=(self.button_x + 360,
557                          self.button_y + self.button_scale_y - 100),
558                text=('' if (free_tries_remaining in [None, 0]
559                             or final_fee != 0) else
560                      ('' + str(free_tries_remaining))),
561                color=(0.6, 0.6, 0.6, 1),
562            )

Button showing a tournament in coop window.

TournamentButton( parent: _ba.Widget, x: float, y: float, select: bool, on_pressed: Callable[[bastd.ui.coop.tournamentbutton.TournamentButton], NoneType])
 21    def __init__(self, parent: ba.Widget, x: float, y: float, select: bool,
 22                 on_pressed: Callable[[TournamentButton], None]) -> None:
 23        self._r = 'coopSelectWindow'
 24        sclx = 300
 25        scly = 195.0
 26        self.on_pressed = on_pressed
 27        self.lsbt = ba.getmodel('level_select_button_transparent')
 28        self.lsbo = ba.getmodel('level_select_button_opaque')
 29        self.allow_ads = False
 30        self.tournament_id: str | None = None
 31        self.time_remaining: int = 0
 32        self.has_time_remaining: bool = False
 33        self.leader: Any = None
 34        self.required_league: str | None = None
 35        self.button = btn = ba.buttonwidget(
 36            parent=parent,
 37            position=(x + 23, y + 4),
 38            size=(sclx, scly),
 39            label='',
 40            button_type='square',
 41            autoselect=True,
 42            # on_activate_call=lambda: self.run(None, tournament_button=data)
 43            on_activate_call=ba.WeakCall(self._pressed))
 44        ba.widget(edit=btn,
 45                  show_buffer_bottom=50,
 46                  show_buffer_top=50,
 47                  show_buffer_left=400,
 48                  show_buffer_right=200)
 49        if select:
 50            ba.containerwidget(edit=parent,
 51                               selected_child=btn,
 52                               visible_child=btn)
 53        image_width = sclx * 0.85 * 0.75
 54
 55        self.image = ba.imagewidget(
 56            parent=parent,
 57            draw_controller=btn,
 58            position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 150),
 59            size=(image_width, image_width * 0.5),
 60            model_transparent=self.lsbt,
 61            model_opaque=self.lsbo,
 62            texture=ba.gettexture('black'),
 63            opacity=0.2,
 64            mask_texture=ba.gettexture('mapPreviewMask'))
 65
 66        self.lock_image = ba.imagewidget(
 67            parent=parent,
 68            draw_controller=btn,
 69            position=(x + 21 + sclx * 0.5 - image_width * 0.25,
 70                      y + scly - 150),
 71            size=(image_width * 0.5, image_width * 0.5),
 72            texture=ba.gettexture('lock'),
 73            opacity=0.0)
 74
 75        self.button_text = ba.textwidget(parent=parent,
 76                                         draw_controller=btn,
 77                                         position=(x + 20 + sclx * 0.5,
 78                                                   y + scly - 35),
 79                                         size=(0, 0),
 80                                         h_align='center',
 81                                         text='-',
 82                                         v_align='center',
 83                                         maxwidth=sclx * 0.76,
 84                                         scale=0.85,
 85                                         color=(0.8, 1.0, 0.8, 1.0))
 86
 87        header_color = (0.43, 0.4, 0.5, 1)
 88        value_color = (0.6, 0.6, 0.6, 1)
 89
 90        x_offs = 0
 91        ba.textwidget(parent=parent,
 92                      draw_controller=btn,
 93                      position=(x + 360, y + scly - 20),
 94                      size=(0, 0),
 95                      h_align='center',
 96                      text=ba.Lstr(resource=self._r + '.entryFeeText'),
 97                      v_align='center',
 98                      maxwidth=100,
 99                      scale=0.9,
100                      color=header_color,
101                      flatness=1.0)
102
103        self.entry_fee_text_top = ba.textwidget(parent=parent,
104                                                draw_controller=btn,
105                                                position=(x + 360,
106                                                          y + scly - 60),
107                                                size=(0, 0),
108                                                h_align='center',
109                                                text='-',
110                                                v_align='center',
111                                                maxwidth=60,
112                                                scale=1.3,
113                                                color=value_color,
114                                                flatness=1.0)
115        self.entry_fee_text_or = ba.textwidget(parent=parent,
116                                               draw_controller=btn,
117                                               position=(x + 360,
118                                                         y + scly - 90),
119                                               size=(0, 0),
120                                               h_align='center',
121                                               text='',
122                                               v_align='center',
123                                               maxwidth=60,
124                                               scale=0.5,
125                                               color=value_color,
126                                               flatness=1.0)
127        self.entry_fee_text_remaining = ba.textwidget(parent=parent,
128                                                      draw_controller=btn,
129                                                      position=(x + 360,
130                                                                y + scly - 90),
131                                                      size=(0, 0),
132                                                      h_align='center',
133                                                      text='',
134                                                      v_align='center',
135                                                      maxwidth=60,
136                                                      scale=0.5,
137                                                      color=value_color,
138                                                      flatness=1.0)
139
140        self.entry_fee_ad_image = ba.imagewidget(parent=parent,
141                                                 size=(40, 40),
142                                                 draw_controller=btn,
143                                                 position=(x + 360 - 20,
144                                                           y + scly - 140),
145                                                 opacity=0.0,
146                                                 texture=ba.gettexture('tv'))
147
148        x_offs += 50
149
150        ba.textwidget(parent=parent,
151                      draw_controller=btn,
152                      position=(x + 447 + x_offs, y + scly - 20),
153                      size=(0, 0),
154                      h_align='center',
155                      text=ba.Lstr(resource=self._r + '.prizesText'),
156                      v_align='center',
157                      maxwidth=130,
158                      scale=0.9,
159                      color=header_color,
160                      flatness=1.0)
161
162        self.button_x = x
163        self.button_y = y
164        self.button_scale_y = scly
165
166        xo2 = 0
167        prize_value_scale = 1.5
168
169        self.prize_range_1_text = ba.textwidget(
170            parent=parent,
171            draw_controller=btn,
172            position=(x + 355 + xo2 + x_offs, y + scly - 93),
173            size=(0, 0),
174            h_align='right',
175            v_align='center',
176            maxwidth=50,
177            text='-',
178            scale=0.8,
179            color=header_color,
180            flatness=1.0)
181        self.prize_value_1_text = ba.textwidget(
182            parent=parent,
183            draw_controller=btn,
184            position=(x + 380 + xo2 + x_offs, y + scly - 93),
185            size=(0, 0),
186            h_align='left',
187            text='-',
188            v_align='center',
189            maxwidth=100,
190            scale=prize_value_scale,
191            color=value_color,
192            flatness=1.0)
193
194        self.prize_range_2_text = ba.textwidget(
195            parent=parent,
196            draw_controller=btn,
197            position=(x + 355 + xo2 + x_offs, y + scly - 93),
198            size=(0, 0),
199            h_align='right',
200            v_align='center',
201            maxwidth=50,
202            scale=0.8,
203            color=header_color,
204            flatness=1.0)
205        self.prize_value_2_text = ba.textwidget(
206            parent=parent,
207            draw_controller=btn,
208            position=(x + 380 + xo2 + x_offs, y + scly - 93),
209            size=(0, 0),
210            h_align='left',
211            text='',
212            v_align='center',
213            maxwidth=100,
214            scale=prize_value_scale,
215            color=value_color,
216            flatness=1.0)
217
218        self.prize_range_3_text = ba.textwidget(
219            parent=parent,
220            draw_controller=btn,
221            position=(x + 355 + xo2 + x_offs, y + scly - 93),
222            size=(0, 0),
223            h_align='right',
224            v_align='center',
225            maxwidth=50,
226            scale=0.8,
227            color=header_color,
228            flatness=1.0)
229        self.prize_value_3_text = ba.textwidget(
230            parent=parent,
231            draw_controller=btn,
232            position=(x + 380 + xo2 + x_offs, y + scly - 93),
233            size=(0, 0),
234            h_align='left',
235            text='',
236            v_align='center',
237            maxwidth=100,
238            scale=prize_value_scale,
239            color=value_color,
240            flatness=1.0)
241
242        ba.textwidget(parent=parent,
243                      draw_controller=btn,
244                      position=(x + 620 + x_offs, y + scly - 20),
245                      size=(0, 0),
246                      h_align='center',
247                      text=ba.Lstr(resource=self._r + '.currentBestText'),
248                      v_align='center',
249                      maxwidth=180,
250                      scale=0.9,
251                      color=header_color,
252                      flatness=1.0)
253        self.current_leader_name_text = ba.textwidget(
254            parent=parent,
255            draw_controller=btn,
256            position=(x + 620 + x_offs - (170 / 1.4) * 0.5,
257                      y + scly - 60 - 40 * 0.5),
258            selectable=True,
259            click_activate=True,
260            autoselect=True,
261            on_activate_call=ba.WeakCall(self._show_leader),
262            size=(170 / 1.4, 40),
263            h_align='center',
264            text='-',
265            v_align='center',
266            maxwidth=170,
267            scale=1.4,
268            color=value_color,
269            flatness=1.0)
270        self.current_leader_score_text = ba.textwidget(
271            parent=parent,
272            draw_controller=btn,
273            position=(x + 620 + x_offs, y + scly - 113 + 10),
274            size=(0, 0),
275            h_align='center',
276            text='-',
277            v_align='center',
278            maxwidth=170,
279            scale=1.8,
280            color=value_color,
281            flatness=1.0)
282
283        self.more_scores_button = ba.buttonwidget(
284            parent=parent,
285            position=(x + 620 + x_offs - 60, y + scly - 50 - 125),
286            color=(0.5, 0.5, 0.6),
287            textcolor=(0.7, 0.7, 0.8),
288            label='-',
289            size=(120, 40),
290            autoselect=True,
291            up_widget=self.current_leader_name_text,
292            text_scale=0.6,
293            on_activate_call=ba.WeakCall(self._show_scores))
294        ba.widget(edit=self.current_leader_name_text,
295                  down_widget=self.more_scores_button)
296
297        ba.textwidget(parent=parent,
298                      draw_controller=btn,
299                      position=(x + 820 + x_offs, y + scly - 20),
300                      size=(0, 0),
301                      h_align='center',
302                      text=ba.Lstr(resource=self._r + '.timeRemainingText'),
303                      v_align='center',
304                      maxwidth=180,
305                      scale=0.9,
306                      color=header_color,
307                      flatness=1.0)
308        self.time_remaining_value_text = ba.textwidget(
309            parent=parent,
310            draw_controller=btn,
311            position=(x + 820 + x_offs, y + scly - 68),
312            size=(0, 0),
313            h_align='center',
314            text='-',
315            v_align='center',
316            maxwidth=180,
317            scale=2.0,
318            color=value_color,
319            flatness=1.0)
320        self.time_remaining_out_of_text = ba.textwidget(
321            parent=parent,
322            draw_controller=btn,
323            position=(x + 820 + x_offs, y + scly - 110),
324            size=(0, 0),
325            h_align='center',
326            text='-',
327            v_align='center',
328            maxwidth=120,
329            scale=0.72,
330            color=(0.4, 0.4, 0.5),
331            flatness=1.0)
def update_for_data(self, entry: dict[str, typing.Any]) -> None:
365    def update_for_data(self, entry: dict[str, Any]) -> None:
366        """Update for new incoming data."""
367        # pylint: disable=too-many-statements
368        # pylint: disable=too-many-locals
369        # pylint: disable=too-many-branches
370        from ba.internal import getcampaign, get_tournament_prize_strings
371        prize_y_offs = (34 if 'prizeRange3' in entry else
372                        20 if 'prizeRange2' in entry else 12)
373        x_offs = 90
374
375        # This seems to be a false alarm.
376        # pylint: disable=unbalanced-tuple-unpacking
377        pr1, pv1, pr2, pv2, pr3, pv3 = (get_tournament_prize_strings(entry))
378        # pylint: enable=unbalanced-tuple-unpacking
379        enabled = 'requiredLeague' not in entry
380        ba.buttonwidget(edit=self.button,
381                        color=(0.5, 0.7, 0.2) if enabled else (0.5, 0.5, 0.5))
382        ba.imagewidget(edit=self.lock_image, opacity=0.0 if enabled else 1.0)
383        ba.textwidget(edit=self.prize_range_1_text,
384                      text='-' if pr1 == '' else pr1,
385                      position=(self.button_x + 365 + x_offs, self.button_y +
386                                self.button_scale_y - 93 + prize_y_offs))
387
388        # We want to draw values containing tickets a bit smaller
389        # (scratch that; we now draw medals a bit bigger).
390        ticket_char = ba.charstr(ba.SpecialChar.TICKET_BACKING)
391        prize_value_scale_large = 1.0
392        prize_value_scale_small = 1.0
393
394        ba.textwidget(edit=self.prize_value_1_text,
395                      text='-' if pv1 == '' else pv1,
396                      scale=prize_value_scale_large
397                      if ticket_char not in pv1 else prize_value_scale_small,
398                      position=(self.button_x + 380 + x_offs, self.button_y +
399                                self.button_scale_y - 93 + prize_y_offs))
400
401        ba.textwidget(edit=self.prize_range_2_text,
402                      text=pr2,
403                      position=(self.button_x + 365 + x_offs, self.button_y +
404                                self.button_scale_y - 93 - 45 + prize_y_offs))
405        ba.textwidget(edit=self.prize_value_2_text,
406                      text=pv2,
407                      scale=prize_value_scale_large
408                      if ticket_char not in pv2 else prize_value_scale_small,
409                      position=(self.button_x + 380 + x_offs, self.button_y +
410                                self.button_scale_y - 93 - 45 + prize_y_offs))
411
412        ba.textwidget(edit=self.prize_range_3_text,
413                      text=pr3,
414                      position=(self.button_x + 365 + x_offs, self.button_y +
415                                self.button_scale_y - 93 - 90 + prize_y_offs))
416        ba.textwidget(edit=self.prize_value_3_text,
417                      text=pv3,
418                      scale=prize_value_scale_large
419                      if ticket_char not in pv3 else prize_value_scale_small,
420                      position=(self.button_x + 380 + x_offs, self.button_y +
421                                self.button_scale_y - 93 - 90 + prize_y_offs))
422
423        leader_name = '-'
424        leader_score: str | ba.Lstr = '-'
425        if entry['scores']:
426            score = self.leader = copy.deepcopy(entry['scores'][0])
427            leader_name = score[1]
428            leader_score = (ba.timestring(
429                score[0] * 10,
430                centi=True,
431                timeformat=ba.TimeFormat.MILLISECONDS,
432                suppress_format_warning=True)
433                            if entry['scoreType'] == 'time' else str(score[0]))
434        else:
435            self.leader = None
436
437        ba.textwidget(edit=self.current_leader_name_text,
438                      text=ba.Lstr(value=leader_name))
439        ba.textwidget(edit=self.current_leader_score_text, text=leader_score)
440        ba.buttonwidget(edit=self.more_scores_button,
441                        label=ba.Lstr(resource=self._r + '.seeMoreText'))
442        out_of_time_text: str | ba.Lstr = (
443            '-' if 'totalTime' not in entry else ba.Lstr(
444                resource=self._r + '.ofTotalTimeText',
445                subs=[('${TOTAL}',
446                       ba.timestring(entry['totalTime'],
447                                     centi=False,
448                                     suppress_format_warning=True))]))
449        ba.textwidget(edit=self.time_remaining_out_of_text,
450                      text=out_of_time_text)
451
452        self.time_remaining = entry['timeRemaining']
453        self.has_time_remaining = entry is not None
454        self.tournament_id = entry['tournamentID']
455        self.required_league = (None if 'requiredLeague' not in entry else
456                                entry['requiredLeague'])
457
458        game = ba.app.accounts_v1.tournament_info[self.tournament_id]['game']
459
460        if game is None:
461            ba.textwidget(edit=self.button_text, text='-')
462            ba.imagewidget(edit=self.image,
463                           texture=ba.gettexture('black'),
464                           opacity=0.2)
465        else:
466            campaignname, levelname = game.split(':')
467            campaign = getcampaign(campaignname)
468            max_players = ba.app.accounts_v1.tournament_info[
469                self.tournament_id]['maxPlayers']
470            txt = ba.Lstr(value='${A} ${B}',
471                          subs=[('${A}',
472                                 campaign.getlevel(levelname).displayname),
473                                ('${B}',
474                                 ba.Lstr(resource='playerCountAbbreviatedText',
475                                         subs=[('${COUNT}', str(max_players))
476                                               ]))])
477            ba.textwidget(edit=self.button_text, text=txt)
478            ba.imagewidget(
479                edit=self.image,
480                texture=campaign.getlevel(levelname).get_preview_texture(),
481                opacity=1.0 if enabled else 0.5)
482
483        fee = entry['fee']
484
485        if fee is None:
486            fee_var = None
487        elif fee == 4:
488            fee_var = 'price.tournament_entry_4'
489        elif fee == 3:
490            fee_var = 'price.tournament_entry_3'
491        elif fee == 2:
492            fee_var = 'price.tournament_entry_2'
493        elif fee == 1:
494            fee_var = 'price.tournament_entry_1'
495        else:
496            if fee != 0:
497                print('Unknown fee value:', fee)
498            fee_var = 'price.tournament_entry_0'
499
500        self.allow_ads = allow_ads = entry['allowAds']
501
502        final_fee: int | None = (None if fee_var is None else
503                                 _ba.get_v1_account_misc_read_val(
504                                     fee_var, '?'))
505
506        final_fee_str: str | ba.Lstr
507        if fee_var is None:
508            final_fee_str = ''
509        else:
510            if final_fee == 0:
511                final_fee_str = ba.Lstr(resource='getTicketsWindow.freeText')
512            else:
513                final_fee_str = (ba.charstr(ba.SpecialChar.TICKET_BACKING) +
514                                 str(final_fee))
515
516        ad_tries_remaining = ba.app.accounts_v1.tournament_info[
517            self.tournament_id]['adTriesRemaining']
518        free_tries_remaining = ba.app.accounts_v1.tournament_info[
519            self.tournament_id]['freeTriesRemaining']
520
521        # Now, if this fee allows ads and we support video ads, show
522        # the 'or ad' version.
523        if allow_ads and _ba.has_video_ads():
524            ads_enabled = _ba.have_incentivized_ad()
525            ba.imagewidget(edit=self.entry_fee_ad_image,
526                           opacity=1.0 if ads_enabled else 0.25)
527            or_text = ba.Lstr(resource='orText',
528                              subs=[('${A}', ''),
529                                    ('${B}', '')]).evaluate().strip()
530            ba.textwidget(edit=self.entry_fee_text_or, text=or_text)
531            ba.textwidget(edit=self.entry_fee_text_top,
532                          position=(self.button_x + 360,
533                                    self.button_y + self.button_scale_y - 60),
534                          scale=1.3,
535                          text=final_fee_str)
536
537            # Possibly show number of ad-plays remaining.
538            ba.textwidget(edit=self.entry_fee_text_remaining,
539                          position=(self.button_x + 360,
540                                    self.button_y + self.button_scale_y - 146),
541                          text='' if ad_tries_remaining in [None, 0] else
542                          ('' + str(ad_tries_remaining)),
543                          color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2))
544        else:
545            ba.imagewidget(edit=self.entry_fee_ad_image, opacity=0.0)
546            ba.textwidget(edit=self.entry_fee_text_or, text='')
547            ba.textwidget(edit=self.entry_fee_text_top,
548                          position=(self.button_x + 360,
549                                    self.button_y + self.button_scale_y - 80),
550                          scale=1.3,
551                          text=final_fee_str)
552
553            # Possibly show number of free-plays remaining.
554            ba.textwidget(
555                edit=self.entry_fee_text_remaining,
556                position=(self.button_x + 360,
557                          self.button_y + self.button_scale_y - 100),
558                text=('' if (free_tries_remaining in [None, 0]
559                             or final_fee != 0) else
560                      ('' + str(free_tries_remaining))),
561                color=(0.6, 0.6, 0.6, 1),
562            )

Update for new incoming data.