Пример #1
0
    def get_card_embed(self, ctx, card: CardMaster, limit_break):
        l10n = self.l10n[ctx]

        if card.rarity_id <= 2:
            limit_break = 0

        color_code = card.character.color_code
        color = discord.Colour.from_rgb(*ImageColor.getcolor(color_code, 'RGB')) if color_code else discord.Embed.Empty

        embed = discord.Embed(title=self.format_card_name(card), color=color)

        thumb_url = ctx.bot.asset_url + get_asset_filename(card.icon_path(limit_break))
        art_url = ctx.bot.asset_url + get_asset_filename(card.art_path(limit_break))

        embed.set_thumbnail(url=thumb_url)
        embed.set_image(url=art_url)

        embed.add_field(name=l10n.format_value('info'),
                        value=l10n.format_value('info-desc', {
                            'rarity': f'{card.rarity_id}★',
                            'character': f'{card.character.full_name_english}',
                            'attribute': f'{ctx.bot.get_emoji(attribute_emoji_ids_by_attribute_id[card.attribute_id])} {card.attribute.en_name.capitalize()}',
                            'unit': f'{ctx.bot.get_emoji(unit_emoji_ids_by_unit_id[card.character.unit_id])} {card.character.unit.name}',
                            'release-date': fluent_date(ctx.convert_tz(card.start_datetime),
                                                        dateStyle='medium', timeStyle='medium'),
                            'event': f'{card.event.name if card.event else "None"}',
                            'gacha': f'{card.gacha.name if card.gacha else "None"}',
                            'availability': card.availability.name,
                        }),
                        inline=False)
        embed.add_field(name=l10n.format_value('parameters'),
                        value=l10n.format_value('parameters-desc', {
                            'total': card.max_power_with_limit_break,
                            'heart': card.max_parameters_with_limit_break[0],
                            'technique': card.max_parameters_with_limit_break[1],
                            'physical': card.max_parameters_with_limit_break[2],
                            'heart-emoji': str(ctx.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[1])),
                            'technique-emoji': str(ctx.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[2])),
                            'physical-emoji': str(ctx.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[3])),
                        }),
                        inline=True)
        skill: SkillMaster = card.skill
        embed.add_field(name=l10n.format_value('skill'),
                        value=l10n.format_value('skill-desc', {
                            'name': card.skill_name,
                            'duration': f'{skill.min_seconds}-{skill.max_seconds}s',
                            'score-up': f'{skill.score_up_rate}%' if not skill.perfect_score_up_rate else f'{skill.score_up_rate}% + {skill.perfect_score_up_rate}% perfect',
                            'heal': (f'{skill.min_recovery_value}-{skill.max_recovery_value}'
                                     if skill.min_recovery_value != skill.max_recovery_value
                                     else str(skill.min_recovery_value))
                        }),
                        inline=True)
        embed.set_footer(text=l10n.format_value('card-id', {'card-id': f'{card.id:0>8}'}))

        return embed
Пример #2
0
    def get_song_embed(self, ctx, song: MusicMaster):
        l10n = self.l10n[ctx]

        color_code = song.unit.main_color_code
        color = discord.Colour.from_rgb(*ImageColor.getcolor(
            color_code, 'RGB')) if color_code else discord.Embed.Empty

        embed = discord.Embed(title=song.name, color=color)
        embed.set_thumbnail(url=self.bot.asset_url +
                            get_asset_filename(song.jacket_path))

        embed.add_field(
            name=l10n.format_value('artist'),
            value=l10n.format_value(
                'artist-desc', {
                    'lyricist': song.lyricist,
                    'composer': song.composer,
                    'arranger': song.arranger,
                    'unit-name': song.unit.name,
                    'special-unit-name': song.special_unit_name or 'None',
                }),
            inline=False)
        embed.add_field(
            name=l10n.format_value('info'),
            value=l10n.format_value(
                'song-info-desc', {
                    'song-category':
                    song.category.name,
                    'duration':
                    self.format_duration(song.duration),
                    'bpm':
                    song.bpm,
                    'section-trend':
                    song.section_trend.name,
                    'sort-order':
                    song.default_order,
                    'levels':
                    ', '.join(c.display_level for c in song.charts.values()),
                    'chart-designers':
                    ', '.join({
                        f'{c.designer.name} ({c.designer.id})': None
                        for c in song.charts.values()
                    }.keys()),
                    'release-date':
                    fluent_date(ctx.convert_tz(song.start_datetime),
                                dateStyle='medium',
                                timeStyle='medium'),
                    'hidden':
                    song.is_hidden,
                    'fair-use':
                    song.can_fair_use,
                }),
            inline=False)

        embed.set_footer(
            text=l10n.format_value('song-id', {'song-id': f'{song.id:>07}'}))

        return embed
Пример #3
0
    async def time_left(self,
                        ctx: commands.Context,
                        *,
                        arg: commands.clean_content = ''):
        event, timezone = await self.parse_event_argument(ctx, arg)

        state = event.state()

        embed = discord.Embed(title=event.name)

        embed.set_thumbnail(url=self.bot.asset_url +
                            get_asset_filename(event.logo_path))

        progress = None

        now = dt.datetime.now(dt.timezone.utc)

        if state == EventState.Upcoming:
            time_delta_heading = 'Time Until Start'
            delta = event.start_datetime - now
            date_heading = 'Start Date'
            date_value = event.start_datetime
        elif state == EventState.Open:
            time_delta_heading = 'Time Until Close'
            delta = event.reception_close_datetime - now
            progress = 1 - (
                delta /
                (event.reception_close_datetime - event.start_datetime))
            date_heading = 'Close Date'
            date_value = event.reception_close_datetime
        elif state in (EventState.Closing, EventState.Ranks_Fixed):
            time_delta_heading = 'Time Until Results'
            delta = event.result_announcement_datetime - now
            date_heading = 'Results Date'
            date_value = event.result_announcement_datetime
        elif state == EventState.Results:
            time_delta_heading = 'Time Until End'
            delta = event.end_datetime - now
            date_heading = 'End Date'
            date_value = event.end_datetime
        else:
            time_delta_heading = 'Time Since End'
            delta = now - event.end_datetime
            date_heading = 'End Date'
            date_value = event.end_datetime

        date_value = date_value.astimezone(timezone)

        embed.add_field(name=time_delta_heading,
                        value=self.format_timedelta(delta),
                        inline=True)
        embed.add_field(name='Progress',
                        value=f'{round(progress * 100, 2)}%'
                        if progress is not None else 'N/A',
                        inline=True)
        embed.add_field(name=date_heading, value=str(date_value), inline=True)

        await ctx.send(embed=embed)
Пример #4
0
    def get_gacha_embed(self, ctx, gacha: GachaMaster):
        l10n = self.l10n[ctx]

        embed = discord.Embed(title=gacha.name)

        thumb_url = self.bot.asset_url + get_asset_filename(gacha.banner_path)

        embed.set_thumbnail(url=thumb_url)

        featured_text = '\n'.join(
            self.format_card_name_with_emoji(card)
            for card in gacha.pick_up_cards) or 'None'

        if len(featured_text) > 1024:
            featured_text = '\n'.join(
                self.format_card_name_short(card)
                for card in gacha.pick_up_cards) or 'None'
        if len(featured_text) > 1024:
            featured_text = l10n.format_value('too-many-results')

        def fmt_date(date):
            return fluent_date(date, dateStyle='medium', timeStyle='medium')

        embed.add_field(
            name=l10n.format_value('info'),
            value=l10n.format_value(
                'info-desc', {
                    'start-date': fmt_date(ctx.convert_tz(
                        gacha.start_datetime)),
                    'end-date': fmt_date(ctx.convert_tz(gacha.end_datetime)),
                    'event-name': gacha.event.name if gacha.event else 'None',
                    'pity-requirement': gacha.bonus_max_value or 'None',
                    'gacha-type': gacha.gacha_type.name,
                }),
            inline=False)
        embed.add_field(name=l10n.format_value('summary'),
                        value=gacha.summary,
                        inline=False)
        embed.add_field(name=l10n.format_value('featured'),
                        value=l10n.format_value(
                            'featured-text',
                            {'featured-text': featured_text or 'None'}),
                        inline=False)
        embed.add_field(name=l10n.format_value('costs'),
                        value='\n'.join(
                            self.format_draw_data(draw, l10n)
                            for draw in gacha.draw_data))

        embed.set_footer(text=l10n.format_value(
            'gacha-id', {'gacha-id': f'{gacha.id:>05}'}))

        return embed
Пример #5
0
    async def get_tier_embed(self, tier: str, event: EventMaster):
        async with self.bot.session.get(
                'http://www.projectdivar.com/eventdata/t20?chart=true'
        ) as resp:
            leaderboard = await resp.json(encoding='utf-8')

        data = leaderboard['statistics'].get(tier)
        if not data:
            return None

        if event.state() == EventState.Open:
            delta = event.reception_close_datetime - dt.datetime.now(
                dt.timezone.utc)
            time_left = self.format_timedelta(delta)
            progress = f'{round(100 * (1 - (delta / (event.reception_close_datetime - event.start_datetime))), 2)}%'
        else:
            time_left = 'N/A'
            progress = 'N/A'

        embed = discord.Embed(title=f'{event.name} [t{tier}]',
                              timestamp=dt.datetime.now(dt.timezone.utc))
        embed.set_thumbnail(url=self.bot.asset_url +
                            get_asset_filename(event.logo_path))

        average_rate = "\n( +" + str(
            math.ceil((data['rate'] * self.EPRATE_RESOLUTION) / data['count'])
        ) + " avg )" if int(
            tier
        ) <= 20 else ""  # Only T20 is tracked in real-time, we can't guarantee <2hr intervals for other points so the rate returned is just overall rate.

        embed.add_field(name='Points',
                        value=str(data['points']) + average_rate,
                        inline=True)
        embed.add_field(name='Last Update',
                        value=data['lastUpdate'] or 'None',
                        inline=True)
        embed.add_field(name='Rate',
                        value=f'{data["rate"]} pts/hr',
                        inline=True)
        embed.add_field(name='Current Estimate',
                        value=data['estimate'],
                        inline=True)
        embed.add_field(name='Final Prediction',
                        value=data['prediction'],
                        inline=True)
        embed.add_field(name='\u200b', value='\u200b', inline=True)
        embed.add_field(name='Time Left', value=time_left, inline=True)
        embed.add_field(name='Progress', value=progress, inline=True)
        return embed
Пример #6
0
    def get_login_bonus_embed(self, ctx, login_bonus: LoginBonusMaster):
        l10n = self.l10n[ctx]

        embed = discord.Embed(title=login_bonus.title)

        def fmt_date(date):
            return fluent_date(date, dateStyle='medium', timeStyle='medium')

        embed.add_field(
            name=l10n.format_value('info'),
            value=l10n.format_value(
                'info-desc', {
                    'start-date':
                    fmt_date(ctx.convert_tz(login_bonus.start_datetime)),
                    'end-date':
                    fmt_date(ctx.convert_tz(login_bonus.end_datetime)),
                    'login-bonus-type':
                    login_bonus.login_bonus_type.name,
                    'loop':
                    login_bonus.loop,
                }),
            inline=False)

        def format_login_bonus(item):
            rewards = item.rewards
            if len(rewards) > 1:
                prefix = f'{item.sequence}. '
                return prefix + ('\n' + ' ' * len(prefix)).join(
                    reward.get_friendly_description() for reward in rewards)
            elif len(rewards) == 1:
                return f'{item.sequence}. {rewards[0].get_friendly_description()}'
            else:
                return l10n.format_value('none')

        reward_text = '```' + ('\n'.join(
            format_login_bonus(item)
            for item in login_bonus.items) or 'None') + '```'

        embed.add_field(name=l10n.format_value('rewards'),
                        value=reward_text,
                        inline=False)

        embed.set_image(url=self.bot.asset_url +
                        get_asset_filename(login_bonus.image_path))

        embed.set_footer(text=l10n.format_value(
            'login-bonus-id', {'login-bonus-id': f'{login_bonus.id:>04}'}))

        return embed
Пример #7
0
def main():
    for p in ['assets', 'assets_en']:
        base_path = Path(p)
        target_path = Path('export')

        asset_paths = [
            'music_jacket/*.jpg',
            'ondemand/card_chara/*.jpg',
            'ondemand/card_icon/*.jpg',
            'ondemand/chart/*.png',
            'ondemand/event/*/*.jpg',
            'ondemand/event/*/*.png',
            'ondemand/gacha/top/banner/*.png',
            'ondemand/loginBonus/*.jpg',
        ]

        for asset_path in asset_paths:
            for path in base_path.glob(asset_path):
                target_file = target_path / get_asset_filename(path)
                if not target_file.exists():
                    shutil.copy(path, target_file)
Пример #8
0
    def get_sections_embed(self, ctx, song: MusicMaster, difficulty):
        l10n = self.l10n[ctx]

        difficulty = ChartDifficulty(difficulty + 1)

        if difficulty not in song.charts:
            embed = discord.Embed(
                title=f'Mix: {song.name} [{difficulty.name}]',
                description=l10n.format_value('no-data'))
            embed.set_thumbnail(url=self.bot.asset_url +
                                get_asset_filename(song.jacket_path))
            return embed

        color_code = song.unit.main_color_code
        color = discord.Colour.from_rgb(*ImageColor.getcolor(
            color_code, 'RGB')) if color_code else discord.Embed.Empty

        chart = song.charts[difficulty]
        embed = discord.Embed(
            title=f'Mix: {song.name} [{chart.difficulty.name}]', color=color)
        embed.set_thumbnail(url=self.bot.asset_url +
                            get_asset_filename(song.jacket_path))
        embed.set_image(url=self.bot.asset_url +
                        get_asset_filename(chart.mix_path))

        note_counts = chart.note_counts
        mix_info = chart.mix_info

        embed.add_field(name=l10n.format_value('info'),
                        value=l10n.format_value(
                            'sections-info-desc', {
                                'level': chart.display_level,
                                'unit-name': song.unit.name,
                                'bpm': song.bpm,
                                'section-trend': song.section_trend.name,
                            }),
                        inline=False)
        embed.add_field(
            name=l10n.format_value('section-begin'),
            value=l10n.format_value(
                'section-desc', {
                    'time':
                    f'{round(mix_info[ChartSectionType.Begin].duration, 2)}s',
                    'combo': note_counts[ChartSectionType.Begin].count,
                }),
            inline=True)
        embed.add_field(
            name=l10n.format_value('section-middle'),
            value=l10n.format_value(
                'section-desc', {
                    'time':
                    f'{round(mix_info[ChartSectionType.Middle].duration, 2)}s',
                    'combo': note_counts[ChartSectionType.Middle].count,
                }),
            inline=True)
        embed.add_field(
            name=l10n.format_value('section-end'),
            value=l10n.format_value(
                'section-desc', {
                    'time':
                    f'{round(mix_info[ChartSectionType.End].duration, 2)}s',
                    'combo': note_counts[ChartSectionType.End].count,
                }),
            inline=True)
        embed.set_footer(text=l10n.format_value(
            'chart-id', {'chart-id': f'{chart.id:>08}'}))

        return embed
Пример #9
0
    def get_chart_embed(self, ctx, song: MusicMaster, difficulty):
        l10n = self.l10n[ctx]

        difficulty = ChartDifficulty(difficulty + 1)

        if difficulty not in song.charts:
            embed = discord.Embed(title=f'{song.name} [{difficulty.name}]',
                                  description='No Data')
            embed.set_thumbnail(url=self.bot.asset_url +
                                get_asset_filename(song.jacket_path))
            return embed

        color_code = song.unit.main_color_code
        color = discord.Colour.from_rgb(*ImageColor.getcolor(
            color_code, 'RGB')) if color_code else discord.Embed.Empty

        chart = song.charts[difficulty]
        embed = discord.Embed(title=f'{song.name} [{chart.difficulty.name}]',
                              color=color)
        embed.set_thumbnail(url=self.bot.asset_url +
                            get_asset_filename(song.jacket_path))
        embed.set_image(url=self.bot.asset_url +
                        get_asset_filename(chart.image_path))
        chart_data = chart.load_chart_data()
        note_counts = chart_data.get_note_counts()

        embed.add_field(
            name=l10n.format_value('info'),
            value=l10n.format_value(
                'chart-info-desc', {
                    'level':
                    chart.display_level,
                    'duration':
                    self.format_duration(song.duration),
                    'unit-name':
                    song.special_unit_name or song.unit.name,
                    'song-category':
                    song.category.name,
                    'bpm':
                    song.bpm,
                    'designer':
                    f'{chart.designer.name} ({chart.designer.id})',
                    'skills':
                    ', '.join('{:.2f}s'.format(t) if t not in chart_data.info.
                              base_skill_times else '[{:.2f}s]'.format(t)
                              for t in chart_data.info.skill_times),
                    'fever':
                    f'{chart_data.info.fever_start:.2f}s - {chart_data.info.fever_end:.2f}s'
                }),
            inline=False)
        embed.add_field(name=l10n.format_value('combo'),
                        value=l10n.format_value(
                            'combo-desc', {
                                'max-combo':
                                chart.note_counts[ChartSectionType.Full].count,
                                **note_counts,
                            }),
                        inline=True)
        embed.add_field(name=l10n.format_value('ratings'),
                        value=f'NTS: {round(chart.trends[0] * 100, 2)}%\n'
                        f'DNG: {round(chart.trends[1] * 100, 2)}%\n'
                        f'SCR: {round(chart.trends[2] * 100, 2)}%\n'
                        f'EFT: {round(chart.trends[3] * 100, 2)}%\n'
                        f'TEC: {round(chart.trends[4] * 100, 2)}%\n',
                        inline=True)
        embed.set_footer(text=l10n.format_value(
            'chart-id', {'chart-id': f'{chart.id:>08}'}))

        return embed
Пример #10
0
    def get_event_embed(self, ctx, event: EventMaster):
        l10n = self.l10n[ctx]

        timezone = ctx.preferences.timezone

        embed = discord.Embed(title=event.name)

        embed.set_thumbnail(url=self.bot.asset_url + get_asset_filename(event.logo_path))

        duration_hour_part = round((event.duration.seconds / 3600), 2)
        duration_hour_part = duration_hour_part if not duration_hour_part.is_integer() else int(duration_hour_part)
        duration_hours = round((event.duration.days * 24 + event.duration.seconds / 3600), 2)
        duration_hours = duration_hours if not duration_hours.is_integer() else int(duration_hours)

        def fmt_date(date):
            return fluent_date(date, dateStyle='medium', timeStyle='medium')

        embed.add_field(name=l10n.format_value('info'),
                        value=l10n.format_value('info-desc', {
                            'duration-days': event.duration.days,
                            'duration-hours': duration_hour_part,
                            'duration-total-hours': duration_hours,
                            'start-date': fmt_date(event.start_datetime.astimezone(timezone)),
                            'close-date': fmt_date(event.reception_close_datetime.astimezone(timezone)),
                            'rank-fix-date': fmt_date(event.rank_fix_start_datetime.astimezone(timezone)),
                            'results-date': fmt_date(event.result_announcement_datetime.astimezone(timezone)),
                            'end-date': fmt_date(event.end_datetime.astimezone(timezone)),
                            'story-unlock-date': fmt_date(event.story_unlock_datetime.astimezone(timezone)),
                            'status': event.state().name,
                        }),
                        inline=False)
        embed.add_field(name=l10n.format_value('event-type'),
                        value=l10n.format_value('event-type-name', {'event-type': event.event_type.name}),
                        inline=True)
        embed.add_field(name=l10n.format_value('bonus-characters'),
                        value='\n'.join(
                            f'{self.bot.get_emoji(unit_emoji_ids_by_unit_id[char.unit_id])} {char.full_name_english}'
                            for char in event.bonus.characters
                        ),
                        inline=True)
        embed.add_field(name=l10n.format_value('bonus-attribute'),
                        value=f'{self.bot.get_emoji(attribute_emoji_ids_by_attribute_id[event.bonus.attribute_id])} '
                              f'{event.bonus.attribute.en_name.capitalize()}' if event.bonus.attribute else 'None',
                        inline=True)
        embed.add_field(name=l10n.format_value('parameter-point-bonus'),
                        value=l10n.format_value('parameter-point-bonus-description', {
                            'parameter-emoji': f'{self.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[event.bonus.event_point_parameter_bonus_id + 1])}',
                            'parameter-bonus-rate': event.bonus.event_point_parameter_bonus_rate
                        }) if event.bonus.event_point_parameter_bonus_rate else
                        l10n.format_value('no-parameter-point-bonus'),
                        inline=False)
        embed.add_field(name=l10n.format_value('point-bonus'),
                        value=l10n.format_value('bonus-description', {
                            'attribute': f'{self.bot.get_emoji(event_point_emoji_id)} +{event.bonus.attribute_match_point_bonus_value}%' if event.bonus.attribute_match_point_bonus_value else 'None',
                            'character': f'{self.bot.get_emoji(event_point_emoji_id)} +{event.bonus.character_match_point_bonus_value}%' if event.bonus.character_match_point_bonus_value else 'None',
                            'both': f'{self.bot.get_emoji(event_point_emoji_id)} +{event.bonus.all_match_point_bonus_value}%' if event.bonus.all_match_point_bonus_value else 'None',
                        }),
                        inline=True)
        embed.add_field(name=l10n.format_value('parameter-bonus'),
                        value=l10n.format_value('bonus-description', {
                            'attribute': f'{self.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[event.bonus.attribute_match_parameter_bonus_id])} +{event.bonus.attribute_match_parameter_bonus_value}%' if event.bonus.attribute_match_parameter_bonus_value else 'None',
                            'character': f'{self.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[event.bonus.character_match_parameter_bonus_id])} +{event.bonus.attribute_match_parameter_bonus_value}%' if event.bonus.attribute_match_parameter_bonus_value else 'None',
                            'both': f'{self.bot.get_emoji(parameter_bonus_emoji_ids_by_parameter_id[event.bonus.all_match_parameter_bonus_id])} +{event.bonus.all_match_parameter_bonus_value}%' if event.bonus.all_match_parameter_bonus_value else 'None',
                        }),
                        inline=True)
        embed.set_footer(text=l10n.format_value('event-id', {'event-id': event.id}))

        return embed
Пример #11
0
    async def pull(self, ctx: PrefContext, *, arg: Optional[ParsedArguments]):
        if not arg:
            await ctx.send(
                'A gacha id must be given (can be found using the !banner command and checking the footer).'
            )
            return
        name = arg.text()
        arg.require_all_arguments_used()
        if not name.isnumeric():
            await ctx.send(
                'A gacha id must be given (can be found using the !banner command and checking the footer).'
            )
            return
        gacha: GachaMaster = self.bot.master_filters.gacha.get_by_id(
            int(name), ctx)
        if not gacha:
            await ctx.send('Unknown banner.')
            return
        draw_data = [
            d for d in gacha.draw_data if (d.stock_id == 902) or (
                d.stock_id in (1, 2) and d.stock_amount == 3000)
        ]
        if len(draw_data) != 1:
            await ctx.send('Unsupported banner.')
            return
        draw_data = draw_data[0]
        tables = gacha.tables
        tables_rates = [
            list(itertools.accumulate(t.rate for t in table))
            for table in tables
        ]

        cards = []
        for draw_amount, table_rate in zip(draw_data.draw_amounts,
                                           gacha.table_rates):
            rates = list(itertools.accumulate(table_rate.rates))
            for _i in range(draw_amount):
                rng = random.randint(1, rates[-1])
                table_index = next(i for i, s in enumerate(rates) if rng <= s)
                table_rates = tables_rates[table_index]
                rng = random.randint(1, table_rates[-1])
                result_index = next(i for i, s in enumerate(table_rates)
                                    if rng <= s)
                cards.append(ctx.assets.card_master[tables[table_index]
                                                    [result_index].card_id])

        bonus = None
        current_pity = None

        if gacha.bonus_max_value:
            pity_data, _ = await PityCount.get_or_create(user_id=ctx.author.id,
                                                         gacha_id=gacha.id)
            pity_data.counter += 10
            current_pity = pity_data.counter
            if pity_data.counter >= gacha.bonus_max_value:
                bonus_tables = gacha.bonus_tables
                pity_data.counter -= gacha.bonus_max_value
                current_pity = pity_data.counter
                rates = list(itertools.accumulate(
                    gacha.bonus_table_rate.rates))
                rng = random.randint(1, rates[-1])
                table_index = next(i for i, s in enumerate(rates) if rng <= s)
                table_rates = list(
                    itertools.accumulate(t.rate
                                         for t in bonus_tables[table_index]))
                rng = random.randint(1, table_rates[-1])
                result_index = next(i for i, s in enumerate(table_rates)
                                    if rng <= s)
                bonus = ctx.assets.card_master[bonus_tables[table_index]
                                               [result_index].card_id]
            await pity_data.save()

        img = await self.bot.loop.run_in_executor(
            self.bot.thread_pool,
            functools.partial(self.create_pull_image, cards, bonus))

        buffer = BytesIO()
        img.save(buffer, 'png')
        buffer.seek(0)

        embed = discord.Embed(title=gacha.name)
        thumb_url = self.bot.asset_url + get_asset_filename(gacha.banner_path)
        embed.set_thumbnail(url=thumb_url)
        embed.set_image(url='attachment://pull.png')

        if current_pity is not None:
            embed.description = f'Pity: {current_pity}/{gacha.bonus_max_value}'

        await ctx.send(embed=embed,
                       file=discord.File(fp=buffer, filename='pull.png'))
Пример #12
0
    def get_gacha_table_embed(self, ctx, gacha: GachaMaster):
        l10n = self.l10n[ctx]

        embed = discord.Embed(title=gacha.name)

        thumb_url = self.bot.asset_url + get_asset_filename(gacha.banner_path)

        embed.set_thumbnail(url=thumb_url)

        def add_table_field(table_rate: GachaTableRateMaster,
                            tables: Sequence[Sequence[GachaTableMaster]]):
            body = ''
            body_short = ''

            for table_normalized_rate, table in zip(
                    table_rate.normalized_rates, tables):
                if table_normalized_rate == 0:
                    continue
                rates = [t.rate for t in table]
                total_rate = sum(rates)
                rate_up_rate = max(rates)

                # Exclude tables with no rate up, except those with very few rate ups (mainly for pity pull)
                if rate_up_rate == min(
                        rates) and rate_up_rate / total_rate < 0.05:
                    continue

                rate_up_card_entries = [
                    t for t in table if t.rate == rate_up_rate
                ]

                for entry in rate_up_card_entries:
                    body += f'`{table_normalized_rate * entry.rate / total_rate * 100: >6.3f}% {self.format_card_name_for_list(entry.card)}`\n'
                    body_short += f'`{table_normalized_rate * entry.rate / total_rate * 100: >6.3f}% {self.format_card_name_short(entry.card)}`\n'

            if len(body) == 0:
                embed.add_field(
                    name=table_rate.tab_name,
                    value=f'`{l10n.format_value("none-or-too-many")}`',
                    inline=False)
            elif len(body) <= 1000:
                embed.add_field(name=table_rate.tab_name,
                                value=body,
                                inline=False)
            elif len(body_short) <= 1000:
                embed.add_field(name=table_rate.tab_name,
                                value=body_short,
                                inline=False)
            else:
                embed.add_field(name=table_rate.tab_name,
                                value=f'`{l10n.format_value("too-many")}`',
                                inline=False)

        for table_rate in gacha.table_rates:
            add_table_field(table_rate, gacha.tables)

        if gacha.bonus_tables:
            add_table_field(gacha.bonus_table_rate, gacha.bonus_tables)

        if not embed.fields:
            embed.description = l10n.format_value("none-or-too-many")

        return embed