コード例 #1
0
    def get_summary(index, card, show_gem=False, ext_col=[]):
        res = {
            'index': int(index),
            'CID': '<span>{0}</span>'.format(card.card_id)
        }
        # Generate HTML code for card view and skill
        res[col_name['view']] = '<img src="{0}" width=50 />'.format(
            icon_path(card.card_id, card.idolized))
        if show_gem:
            gems = [gem.name for gem in card.equipped_gems]
            res[col_name['view']] += gem_slot_pic(card, gem_size=gem_size)

        if card.skill is not None:
            temp = repr(card.skill).split(': ')
            fmt = '<p> <img style="float: left" src="{0}" width=15 /> {1} <br style="clear: both;"/> {2} <br/> {3} </p>'
            res[col_name['skill']] = fmt.format(
                misc_path(card.skill.effect_type), temp[0],
                *temp[1].split('. '))
        else:
            res[col_name['skill']] = '<p>{0}</p>'.format('NA')
        if card.cskill is not None:
            temp = repr(card.cskill).split('. ')
            func = lambda x: x.split(': ')[-1].replace(
                'raise', 'Raise').replace('contribution ', '')
            if temp[1] == '':
                res[col_name['skill']] += '<p>{0}</p>'.format(func(temp[0]))
            else:
                res[col_name['skill']] += '<p>{0}<br/>{1}</p>'.format(
                    func(temp[0]), func(temp[1]))

        fmt = '<p style="color:{0};">{1}<br/>{2}</p>'
        res[col_name['level']] = fmt.format('black', card.level,
                                            card.max_level)
        res[col_name['bond']] = fmt.format('black', card.bond, card.max_bond)
        res[col_name['hp']] = '<p style="color:orange;"><b>{0}</b></p>'.format(
            card.hp)

        fmt = '<p style="color:{0};">{1}</p>'
        res[col_name['smile']] = fmt.format('red', card.smile)
        res[col_name['pure']] = fmt.format('green', card.pure)
        res[col_name['cool']] = fmt.format('blue', card.cool)

        if card.skill is None:
            res['Skill Gain'] = '<p>NA</p>'
        else:
            gain = card.skill.skill_gain()[0]
            if card.skill.effect_type in ['Strong Judge', 'Weak Judge']:
                res['Skill Gain'] = '<p>Lv:{1}<br/>{0:.2f}%<br/>covered</p>'.format(
                    100 * gain, card.skill.level)
            elif card.skill.effect_type == 'Stamina Restore':
                res['Skill Gain'] = '<p>Lv:{1}<br/>{0:.4f}<br/>hp/note</p>'.format(
                    gain, card.skill.level)
            elif card.skill.effect_type == 'Score Up':
                res['Skill Gain'] = '<p>Lv:{1}<br/>{0:.4f}<br/>pt/note</p>'.format(
                    gain, card.skill.level)

        # If there are other columns to show
        for attr in ext_col:
            res[attr] = getattr(card, attr)
        return res
コード例 #2
0
		def get_summary(card, ext_col=[]):
			res = {'index':int(card.index)}
			match_cskill = self.guest_cskill is not None and self.guest_cskill.bonus_range in card.tags
			match_color, match_group = card.main_attr == self.live.attr, self.live.group in card.tags
			font_color, font_weight = attr_color[self.live.attr] if match_color else 'black', 900 if match_cskill else 'normal'
			border_style = '3px double' if (match_color and match_group) else ('1px solid' if (match_color or match_group) else '1px none')
			res['CID'] = '<span style="color:{1}; border:{1} {2};font-weight:{3}; padding: 0 3px">{0}</span>'.format(card.card_id, font_color, border_style, font_weight)
			# Generate HTML code for card view and skill
			res[col_name['view']] =  '<img src="{0}" width=50 title="{1}"/>'.format(icon_path(card.card_id, card.idolized), card.tooltip())

			if card.skill is not None:
				temp = repr(card.skill).split(': ')
				fmt = '<p> <img style="float: left" src="{0}" width=15 /> {1} <br style="clear: both;"/> {2} <br/> {3} </p>'
				res[col_name['skill']] = fmt.format(misc_path(card.skill.effect_type) ,temp[0], *temp[1].split('. '))
			else:
				res[col_name['skill']] = '<p>{0}</p>'.format('NA')
			if card.cskill is not None:
				temp = repr(card.cskill).split('. ')
				func = lambda x: x.split(': ')[-1].replace('raise', 'Raise').replace('contribution ','')
				if temp[1] == '':
					res[col_name['skill']] += '<p>{0}</p>'.format(func(temp[0]))
				else:
					res[col_name['skill']] += '<p>{0}<br/>{1}</p>'.format(func(temp[0]), func(temp[1]))

			fmt = '<p style="color:{0};">{1}<br/>{2}</p>'
			res[col_name['level']] = fmt.format('black', card.level, card.max_level)
			res[col_name['bond']] = fmt.format('black', card.bond, card.max_bond)
			res[col_name['hp']] = '<p style="color:orange;"><b>{0}</b></p>'.format(card.hp)
			res['Slot'] = card.slot_num

			fmt = '<p style="color:{0};">{1}<br>{2}</p>'
			card.compute_rough_strength(cskill=None, guest_cskill=self.guest_cskill, live=self.live, setting=self.setting)
			roungh_str_fmt = lambda attr: ('<b style="border:1px solid; padding:0px 1px">{0}</b>' if card.rough_strength[attr]['use_skill_gem'] else '{0}').format(card.rough_strength[attr]['strength'])
			for attr in attr_list:
				res[col_name[attr.lower()]] = fmt.format(attr_color[attr], getattr(card, attr.lower()), roungh_str_fmt(attr))
			res['sort_STR'] = card.rough_strength[self.live.attr]['strength']

			if card.skill is None:
				res['skill_effect_type'] = 'NA'
				res['skill_gain'] = 0
				res['Skill Gain'] = '<p>NA</p>'
			else:
				gain = card.skill.skill_gain(self.setting)[0]
				res['skill_effect_type'] = card.skill.effect_type
				res['skill_gain'] = gain
				if card.skill.effect_type in ['Strong Judge', 'Weak Judge']:
					res['Skill Gain'] = '<p><img style="float: left" src="{2}" width=15 />Lv:{1}<br clear="both"/>{0:.2f}%<br/>covered</p>'.format(100*gain, card.skill.level, misc_path(card.skill.effect_type))
				elif card.skill.effect_type == 'Stamina Restore':
					res['Skill Gain'] = '<p><img style="float: left" src="{2}" width=15 />Lv:{1}<br clear="both"/>{0:.4f}<br/>hp/note</p>'.format(gain, card.skill.level, misc_path(card.skill.effect_type))
				elif card.skill.effect_type == 'Score Up':
					res['Skill Gain'] = '<p><img style="float: left" src="{2}" width=15 />Lv:{1}<br clear="both"/>{0:.4f}<br/>pt/note</p>'.format(gain, card.skill.level, misc_path(card.skill.effect_type))

			# If there are other columns to show
			for attr in ext_col: res[attr] = getattr(card, attr)
			return res
コード例 #3
0
	def get_summary(index, card, show_gem=False, ext_col=[]):
		res = {'index':index, 'CID': '<span> &nbsp {0} &nbsp </span>'.format(card.card_id)}
		# Generate HTML code for card view and skill
		res[col_name['view']] =  '<img src="{0}" width=60 />'.format(icon_path(card.card_id, card.idolized))
		if show_gem:
			res[col_name['view']] += gem_slot_pic1(card, show_cost=False, gem_size=gem_size)

		if card.skill is not None:
			temp = repr(card.skill).split(': ')
			fmt = '<p> <img style="float: left" src="{0}" width=15 /> {1} <br style="clear: both;"/> {2} <br/> {3} </p>'
			res[col_name['skill']] = fmt.format(misc_path(card.skill.effect_type) ,temp[0], *temp[1].split('. '))
		else:
			res[col_name['skill']] = '<p>{0}</p>'.format('NA')
		if card.cskill is not None:
			temp = repr(card.cskill).split('. ')
			func = lambda x: x.split(': ')[-1].replace('raise', 'Raise').replace('contribution ','')
			if temp[1] == '':
				res[col_name['skill']] += '<p>{0}</p>'.format(func(temp[0]))
			else:
				res[col_name['skill']] += '<p> {0} <br/> {1} </p>'.format(func(temp[0]), func(temp[1]))

		fmt = '<p style="color:{0};"> {1:<4d} <br/> {2:<4d} </p>'
		res[col_name['level']] = fmt.format('black', card.level, card.max_level)
		res[col_name['bond']] = fmt.format('black', card.bond, card.max_bond)
		res[col_name['hp']] = '<p style="color:orange;"> <b> &nbsp &nbsp {0} &nbsp </b> </p>'.format(card.hp)

		fmt = '<p style="color:{0};"> {1:<4d} <br/> {2:<4d} </p>'
		temp = card.card_strength(include_gem=True)
		res[col_name['smile']] = fmt.format('red', card.smile, temp['smile*'])
		res[col_name['pure']]  = fmt.format('green', card.pure, temp['pure*'])
		res[col_name['cool']]  = fmt.format('blue', card.cool, temp['cool*'])

		if card.skill is None:
			res['Skill Gain'] = '<p>NA</p>'
		else:
			gain = card.skill.skill_gain()[0]
			if card.skill.effect_type in ['Strong Judge', 'Weak Judge']:
				res['Skill Gain'] = '<p>{0:.4f}% <br/> covered </p>'.format(100*gain)
			elif card.skill.effect_type == 'Stamina Restore':
				res['Skill Gain'] = '<p>{0:.4f} <br/> hp/note</p>'.format(gain)
			elif card.skill.effect_type == 'Score Up':
				res['Skill Gain'] = '<p>{0:.4f} <br/> pt/note</p>'.format(gain)
		temp = card.general_strength()
		fmt = '<p> <span style="color:red">{0}</span> <br/> <span style="color:green">{1}</span> <br/> <span style="color:blue">{2}</span> </p> '
		func = lambda x: str(x['strength']) + ' (gem)'*int(x['use_skill_gem'])
		res['general_strength'] = fmt.format(func(temp['Smile']), func(temp['Pure']), func(temp['Cool']))
		res['skill_strength'] = fmt.format(temp['Smile']['skill_strength'], temp['Pure']['skill_strength'], temp['Cool']['skill_strength'])

		# If there are other columns to show
		for attr in ext_col: res[attr] = getattr(card, attr)
		return res
コード例 #4
0
 def _gen_summary(self, col_width=50):
     pd.set_option('display.max_colwidth', -1)
     song_name = '<p style="color:{0};">{1}</p>'.format(
         attr_color[self.live.attr], self.live.name)
     df_head = pd.DataFrame({'Song Name': [song_name]})
     df_head['Difficulty'] = self.live.difficulty
     df_head['Score'] = int(self.global_status['cum_score'])
     df_head['Cover Rate'] = '{0:.2f}%'.format(
         100 * (self.simul_result['timing_sec'] <=
                self.simul_result['judge_end_time']).mean())
     df_head['Max Combo'] = self.simul_result['combo'].max()
     for accr in accuracy_list:
         df_head[accr] = self.global_status['note_stat'][accr]
     card = [
         '<img src="{0}" width={1} />'.format(
             icon_path(card.card_id, card.idolized), col_width)
         for card in self.card_list
     ]
     summary, keys = [], [
         'base_score', 'score', 'hp', 'judge', 'weak_judge'
     ]
     for i in range(len(card)):
         temp = {
             k: getattr(self.skill_tracker[i], 'cum_' + k)
             for k in keys
         }
         temp['card'] = card[i]
         summary.append(temp)
     df = pd.DataFrame(summary, columns=['card'] + keys)
     df = df.append(pd.DataFrame(df.sum()).transpose())
     df['base_score'] = df['base_score'].apply(
         lambda x: '<p>{0}</p>'.format(int(x)))
     df['score'] = df['score'].apply(lambda x: '<p>{0}</p>'.format(int(x)))
     df['hp'] = df['hp'].apply(lambda x: '<p>{0}</p>'.format(int(x)))
     df['judge'] = df['judge'].apply(
         lambda x: '<p>{0}</p>'.format(round(x, 1)))
     df['weak_judge'] = df['weak_judge'].apply(
         lambda x: '<p>{0}</p>'.format(round(x, 1)))
     df.index = [
         '<p>{0}</p>'.format(x) for x in
         ['L1', 'L2', 'L3', 'L4', 'C', 'R4', 'R3', 'R2', 'R1', 'Total']
     ]
     df.loc['<p>Total</p>', 'card'] = ''
     html_code = df_head.to_html(
         escape=False, index=False) + df.transpose().to_html(escape=False)
     return HTML(html_code)
コード例 #5
0
        def format_row(row, max_hp, card_list):
            fmt = '<p style="color:{0};"> {1} </p>'
            res = dict()
            color = 'cyan' if row.swing else ('red' if row.star else (
                'blue' if row.long else 'black'))
            res['index'] = fmt.format(color, row['index'])
            color_fun = lambda n: 'rgb({0},{1},0)'.format(
                int((255 * n / 4) * 0.8), int((255 - 255 * n / 4) * 0.8))

            color = {
                'Perfect': color_fun(0),
                'Great': color_fun(1),
                'Good': color_fun(2),
                'Bad': color_fun(3),
                'Miss': color_fun(4)
            }
            res['accuracy'] = fmt.format(color[row.accuracy], row.accuracy)
            res['accuracy*'] = fmt.format(color[row['accuracy*']],
                                          row['accuracy*'])

            color_fun = lambda hp: 'rgb({0},{1},{0})'.format(
                int((255 - 255 * hp / max_hp) * 0.8),
                int((255 * hp / max_hp) * 0.8))
            res['hp'] = fmt.format(color_fun(row.hp), row.hp)

            res['cum_score'], res['score'] = row.cum_score, row.score
            res['time'] = row.timing_sec
            res['note'], res['combo'], res[
                'perfect'] = row.note, row.combo, row.perfect

            res.update({x: row[x] for x in ext_cols})

            for i, card in enumerate(card_list, 1):
                note_type, content = row['note type ' + str(i)], ''
                if 'long' in note_type:
                    content += '<img style="position: relative;" src="{0}" width={1} />'.format(
                        misc_path(note_type), col_width)
                if 'Note' in note_type:
                    content += '<img style="position: relative;" src="{0}" width={1} />'.format(
                        misc_path(note_type), col_width)
                elif 'Star' in note_type:
                    content += '<img style="position: relative;" src="{0}" width={1} />'.format(
                        misc_path(note_type.replace('Star', 'Note')),
                        col_width)
                    content += '<img style="position: absolute; top: 0px; left: 0px;" src="{0}" width={1} />'.format(
                        misc_path('star'), col_width)
                elif 'Swing' in note_type:
                    if 'left' in note_type:
                        content += '<img style="position: relative;transform: rotateZ(180deg)" src="{0}" width={1} />'.format(
                            misc_path(note_type.replace(' left', '')),
                            col_width)
                    elif 'right' in note_type:
                        content += '<img style="position: relative;" src="{0}" width={1} />'.format(
                            misc_path(note_type.replace(' right', '')),
                            col_width)
                if row['card ' + str(i)] > 0:
                    top, left = -0.3 * col_width if content == '' else 0.15 * col_width, 0.15 * col_width
                    content += '<img style="position: absolute; top: {0}px; left: {1}px;opacity:{4}" src="{2}" width={3} /></div>' ''.format(
                        top, left, misc_path(card.skill.effect_type),
                        0.7 * col_width, row['card ' + str(i)] * 0.7 + 0.3)
                col = '<img src="{0}" width={1} class="{2}" />'.format(
                    icon_path(card.card_id, card.idolized), col_width, i)
                res[col] = '<div style="position: relative;">{0}</div>'.format(
                    content)
            return res
コード例 #6
0
    def show_simul(self, col_width=30, ext_cols=[], filename=None):
        def determine_note_type(df):
            df = df.assign(direction=0)
            cal_dir = lambda x: np.concatenate((np.diff(x), [np.diff(x)[-1]]))
            for i in range(2, df['notes_level'].max() + 1):
                try:
                    df.loc[df.notes_level == i, 'direction'] = cal_dir(
                        df[df.notes_level == i]['position'].values)
                except:
                    df.loc[df.notes_level == i, 'direction'] = 1
            attr = self.live.attr
            notes = {
                'note type ' + str(l + 1): []
                for l in range(len(self.card_list))
            }
            swing_dir = df.direction.apply(lambda x: 'left'
                                           if x > 0 else 'right')
            long_on = [False] * 9
            for i, row in df.iterrows():
                pos = 9 - row.position
                for l in range(len(self.card_list)):
                    key = 'note type ' + str(l + 1)
                    if l == pos:
                        # If it is not the head and tail of a long note
                        if row['index'][-1] not in ['h', 't']:
                            # Normal note or Star note
                            if not row.swing:
                                notes[key].append(
                                    attr + (' Star' if row.star else ' Note'))
                            # Swing note
                            elif row.swing:
                                notes[key].append(attr + ' Swing ' +
                                                  swing_dir[i])
                        # If it is the head and tail of a long note
                        else:
                            long_on[l] = row['index'][-1] == 'h'
                            notes[key].append(attr + ' Note')
                    else:
                        # If a long note is present
                        notes[key].append('long' if long_on[l] else 'empty')
            return pd.DataFrame(notes)

        def format_row(row, max_hp, card_list):
            fmt = '<p style="color:{0};"> {1} </p>'
            res = dict()
            color = 'cyan' if row.swing else ('red' if row.star else (
                'blue' if row.long else 'black'))
            res['index'] = fmt.format(color, row['index'])
            color_fun = lambda n: 'rgb({0},{1},0)'.format(
                int((255 * n / 4) * 0.8), int((255 - 255 * n / 4) * 0.8))

            color = {
                'Perfect': color_fun(0),
                'Great': color_fun(1),
                'Good': color_fun(2),
                'Bad': color_fun(3),
                'Miss': color_fun(4)
            }
            res['accuracy'] = fmt.format(color[row.accuracy], row.accuracy)
            res['accuracy*'] = fmt.format(color[row['accuracy*']],
                                          row['accuracy*'])

            color_fun = lambda hp: 'rgb({0},{1},{0})'.format(
                int((255 - 255 * hp / max_hp) * 0.8),
                int((255 * hp / max_hp) * 0.8))
            res['hp'] = fmt.format(color_fun(row.hp), row.hp)

            res['cum_score'], res['score'] = row.cum_score, row.score
            res['time'] = row.timing_sec
            res['note'], res['combo'], res[
                'perfect'] = row.note, row.combo, row.perfect

            res.update({x: row[x] for x in ext_cols})

            for i, card in enumerate(card_list, 1):
                note_type, content = row['note type ' + str(i)], ''
                if 'long' in note_type:
                    content += '<img style="position: relative;" src="{0}" width={1} />'.format(
                        misc_path(note_type), col_width)
                if 'Note' in note_type:
                    content += '<img style="position: relative;" src="{0}" width={1} />'.format(
                        misc_path(note_type), col_width)
                elif 'Star' in note_type:
                    content += '<img style="position: relative;" src="{0}" width={1} />'.format(
                        misc_path(note_type.replace('Star', 'Note')),
                        col_width)
                    content += '<img style="position: absolute; top: 0px; left: 0px;" src="{0}" width={1} />'.format(
                        misc_path('star'), col_width)
                elif 'Swing' in note_type:
                    if 'left' in note_type:
                        content += '<img style="position: relative;transform: rotateZ(180deg)" src="{0}" width={1} />'.format(
                            misc_path(note_type.replace(' left', '')),
                            col_width)
                    elif 'right' in note_type:
                        content += '<img style="position: relative;" src="{0}" width={1} />'.format(
                            misc_path(note_type.replace(' right', '')),
                            col_width)
                if row['card ' + str(i)] > 0:
                    top, left = -0.3 * col_width if content == '' else 0.15 * col_width, 0.15 * col_width
                    content += '<img style="position: absolute; top: {0}px; left: {1}px;opacity:{4}" src="{2}" width={3} /></div>' ''.format(
                        top, left, misc_path(card.skill.effect_type),
                        0.7 * col_width, row['card ' + str(i)] * 0.7 + 0.3)
                col = '<img src="{0}" width={1} class="{2}" />'.format(
                    icon_path(card.card_id, card.idolized), col_width, i)
                res[col] = '<div style="position: relative;">{0}</div>'.format(
                    content)
            return res

        columns = [
            'index', 'time', 'accuracy', 'accuracy*', 'hp', 'note', 'combo',
            'perfect', 'cum_score', 'score'
        ]
        columns += [
            '<img src="{0}" width={1} class="{2}" />'.format(
                icon_path(card.card_id, card.idolized), col_width, i)
            for i, card in enumerate(self.card_list, 1)
        ]
        columns += ext_cols
        df = pd.concat(
            (self.simul_result, determine_note_type(self.simul_result)),
            axis=1)
        data = [
            format_row(row, self.team_hp, self.card_list)
            for _, row in df.iterrows()
        ]
        pd.set_option('display.max_colwidth', -1)
        df = pd.DataFrame(data, columns=columns).set_index('index')
        df.cum_score = df.cum_score.apply(lambda x: int(x))
        df.score = df.score.apply(lambda x: int(x))
        html_code = df.to_html(escape=False)

        if filename is not None:
            html_head = self._gen_summary().data
            with open(filename, 'w') as fp:
                fp.write(html_template.format(html_head + html_code))
            print('File saved to', filename)
コード例 #7
0
 def prepare_simulation(self,
                        opt={
                            'scoreup': 1,
                            'skillup': 1,
                            'guest_cskill': None
                        }):
     res = self.team_strength(opt.get('guest_cskill'))
     temp = np.array(res['displayed_card_attr'])
     single, total = np.concatenate(
         (temp[None, :, :], temp[None, :, :])), np.zeros((2, 3))
     for i, card in enumerate(self.card_list):
         total += temp[i, :]
         for gem in card.equipped_gems:
             if gem.effect == 'judge_boost':
                 attr_idx = attr_list.index(gem.attribute)
                 total[1, attr_idx] += np.ceil(gem.value / 100 *
                                               temp[i, attr_idx])
                 single[1, i, attr_idx] += np.ceil(gem.value / 100 *
                                                   temp[i, attr_idx])
     single += np.array(res['center_SIS_bonus_detail'])[None, :, :]
     single += np.array(res['team_center_skill_bonus_detail'])[None, :, :]
     single += np.array(res['guest_center_skill_bonus_detail'])[None, :, :]
     total += np.array(res['center_SIS_bonus']) + np.array(
         res['center_skill_bonus'])
     skill_info = []
     for card in self.card_list:
         skill = card.skill
         if skill is None:
             skill_info.append(None)
         else:
             temp = skill.__dict__
             temp.pop('odds_list', None)
             temp.pop('reward_list', None)
             temp.pop('max_level', None)
             for k, v in temp.items():
                 if type(v) != str: temp[k] = float(v)
             if skill.effect_type == 'Score Up':
                 temp['score'] = temp['reward']
                 if any(['Charm' in gem.name
                         for gem in card.equipped_gems]):
                     temp['score'] += math.floor(1.5 * temp['reward'])
             elif skill.effect_type == 'Stamina Restore':
                 temp['score'] = 0
                 if any(['Heal' in gem.name for gem in card.equipped_gems]):
                     temp['score'] += math.floor(480 * temp['reward'])
             else:
                 temp['score'] = 0
         skill_info.append(temp)
     res = {
         'icon_url': [
             icon_path(card.card_id, card.idolized)
             for card in self.card_list
         ],
         'tot_attr_strength':
         total.tolist(),
         'strength_fraction': (single / total[:, None, :]).tolist(),
         'group': [
             "μ's" if "μ's" in card.tags else
             'Aqours' if 'Aqours' in card.tags else None
             for card in self.card_list
         ],
         'attr': [card.main_attr for card in self.card_list],
         'skill_info':
         skill_info
     }
     return res
コード例 #8
0
		def get_summary(index, card):
			res = { 'CID':'<p>{0}</p>'.format(card.card_id), 
					'Icon': '<img src="{0}" style="width:100%;max-width:75px;" title="{1}"/>'.format(icon_path(card.card_id, card.idolized), card.tooltip()),
					'SIS': gem_slot_pic(card, show_cost=show_cost, gem_size=25)}
			# Skill gain information
			if card.skill is not None:
				gain = card.skill.skill_gain(setting=new_setting)[0]
				if card.skill.effect_type in ['Strong Judge', 'Weak Judge']:
					skill_gain_str = '{0:.2f}% covered '.format(100*card.CR)
				elif card.skill.effect_type == 'Stamina Restore':
					skill_gain_str = '{0:.3f} hp/note'.format(gain)
				elif card.skill.effect_type == 'Score Up':
					skill_gain_str = '{0:.2f} pt/note'.format(gain)
				fmt = '<p> <img style="float:left" src="{0}" width=15 /> Lv{1} <br clear="both"/> {2} </p>'
				res['Skill Gain'] = fmt.format(misc_path(card.skill.effect_type) ,card.skill.level, skill_gain_str)
			else:
				res['Skill Gain'] = '<p>{0}</p>'.format('NA')

			# Basic stats
			fmt = '<p style="color:{0};"> {1:<4d} </p>'
			res[col_name['level']] = fmt.format('black', card.level)
			res[col_name['bond']] = fmt.format(attr_color[card.main_attr], card.bond)
			for attr in attr_list:
				res[col_name[attr.lower()]] = fmt.format(attr_color[attr], getattr(card, attr.lower()))

			# Non-skill gem bonus
			base_value = { attr:getattr(card, attr.lower()) + card.bond*(attr==card.main_attr) for attr in attr_list }
			before_C_value = base_value.copy()
			single_plus, single_mult, team_mult = {k:0 for k in attr_list}, {k:0 for k in attr_list}, {k:0 for k in attr_list}
			for gem in card.equipped_gems:
				for attr in attr_list:
					if attr in gem.name:
						if gem.effect == 'attr_add': 
							single_plus[attr] += gem.value
						if gem.effect == 'attr_boost': 
							single_mult[attr] += math.ceil(base_value[attr] * gem.value/100)
			for gem in team_gems:
				for attr in attr_list:
					if attr in gem.name:
						team_mult[attr] += math.ceil(base_value[attr] * gem.value/100)
			for attr in attr_list:
				before_C_value[attr] += single_plus[attr] + single_mult[attr] + team_mult[attr]
			res['Single +'] = single_plus[self.live.attr]
			res['Single ×'] = single_mult[self.live.attr] 
			res['Team ×']   = team_mult[self.live.attr]
			res['Card STR'] = before_C_value[self.live.attr]

			# Center skill bonus and team strength
			res['Main-C'], res['Vice-C'], res['Main-C2'], res['Vice-C2'] = 0, 0, 0, 0
			if cskill is not None and cskill.main_attr == self.live.attr:
				res['Main-C'] += math.ceil(before_C_value[cskill.base_attr] * cskill.main_ratio/100)
				if cskill.bonus_ratio is not None and cskill.bonus_range in card.tags:
					res['Vice-C'] += math.ceil(res['Card STR'] * cskill.bonus_ratio/100)
			if self.guest_cskill is not None and self.guest_cskill.main_attr == self.live.attr:
				res['Main-C2'] += math.ceil(before_C_value[self.guest_cskill.base_attr] * self.guest_cskill.main_ratio/100)
				if self.guest_cskill.bonus_ratio is not None and self.guest_cskill.bonus_range in card.tags:
					res['Vice-C2'] += math.ceil(res['Card STR'] * self.guest_cskill.bonus_ratio/100)
			res['Team STR'] = res['Card STR'] + res['Main-C'] + res['Vice-C'] + res['Main-C2'] + res['Vice-C2']

			# Skill gem equivalent strength
			res['Charm'], res['Heal'], res['Trick'] = 0, 0, 0
			if card.skill is not None and card.skill.effect_type in ['Score Up', 'Stamina Restore']:
				skill_gain = card.skill.skill_gain(setting=new_setting)[0]
				if card.skill.effect_type == 'Score Up':
					res['Charm'] = math.ceil(skill_gain*self.live.strength_per_pt_tap)
					if any(['Charm' in gem.name for gem in card.equipped_gems]):
						res['Charm'] += math.ceil(1.5*skill_gain*self.live.strength_per_pt_tap)
				elif card.skill.effect_type == 'Stamina Restore' and any(['Heal' in gem.name for gem in card.equipped_gems]):
					res['Heal'] = math.ceil(480*skill_gain*self.live.strength_per_pt_tap)
			res['Judge STR'] = res['Team STR']
			if self.live.attr == card.main_attr and any(['Trick' in gem.name for gem in card.equipped_gems]):
				res['Trick'] = math.ceil((res['Card STR']-res['Team ×'])*0.33*self.team_CR)
				res['Judge STR'] += math.ceil((res['Card STR']-res['Team ×'])*0.33)
			res['Skill STR'], res['Amend STR'] = res['Charm']+res['Heal'], res['Team STR']+res['Trick']

			# Compute same group and same color bonus
			res['Live Bonus'] = '{0:.2f}'.format(bonus(card))
			res['Cmb WT%'] = '{0:.2f}%'.format(self.live.combo_weight_fraction[index]*100)
			return res
コード例 #9
0
	def view_optimal_details(self, show_cost=False, lang='EN', fixed_team=None):
		team = self.construct_team() if fixed_team is None else fixed_team

		col_name = { x:'<img src="{0}" width=25/>'.format(misc_path(x)) for x in ['level','bond','smile','pure','cool'] }

		columns  = ['CID', 'Icon', 'SIS', 'Skill Gain']
		columns += [col_name[x] for x in ['level', 'bond', 'smile', 'pure', 'cool']]
		columns += ['Single +', 'Single ×', 'Team ×', 'Card STR', 
					'Main-C', 'Vice-C', 'Main-C2', 'Vice-C2', 'Team STR', 'Judge STR',
					'Charm', 'Heal', 'Trick', 'Amend STR', 'Skill STR', 'Live Bonus', 'Cmb WT%']

		# Extract all team gems
		team_gems = [gem for card in team.card_list for gem in card.equipped_gems if self.live.attr in gem.name and gem.effect == 'team_boost']
		# Find team center skill and cover rate
		cskill = team.center().cskill
		temp = np.ones(9)
		for i, card in enumerate(team.card_list):
			if card.skill is not None and card.skill.effect_type in ['Weak Judge', 'Strong Judge']:
				temp[i] -= card.skill.skill_gain(setting=self.setting)[0]
		CR = 1 - temp.prod()
		new_setting = self.setting.copy()
		new_setting['attr_group_factor'] = self.mu_bar
		new_setting['perfect_rate'] = 1 - (1-self.live.perfect_rate) * (1-self.team_CR)

		# Update live settings on new CR
		if hasattr(self.live, 'update_live_stat'):
			self.live.update_live_stat(new_setting['perfect_rate'])
		self.mu_bar = self.compute_optimal_placement()[0]

		# Compute same group&attr bonus
		bonus = lambda card: attr_match_factor**(self.live.attr==card.main_attr) * group_match_factor**(self.live.group in card.tags)

		def get_summary(index, card):
			res = { 'CID':'<p>{0}</p>'.format(card.card_id), 
					'Icon': '<img src="{0}" style="width:100%;max-width:75px;" title="{1}"/>'.format(icon_path(card.card_id, card.idolized), card.tooltip()),
					'SIS': gem_slot_pic(card, show_cost=show_cost, gem_size=25)}
			# Skill gain information
			if card.skill is not None:
				gain = card.skill.skill_gain(setting=new_setting)[0]
				if card.skill.effect_type in ['Strong Judge', 'Weak Judge']:
					skill_gain_str = '{0:.2f}% covered '.format(100*card.CR)
				elif card.skill.effect_type == 'Stamina Restore':
					skill_gain_str = '{0:.3f} hp/note'.format(gain)
				elif card.skill.effect_type == 'Score Up':
					skill_gain_str = '{0:.2f} pt/note'.format(gain)
				fmt = '<p> <img style="float:left" src="{0}" width=15 /> Lv{1} <br clear="both"/> {2} </p>'
				res['Skill Gain'] = fmt.format(misc_path(card.skill.effect_type) ,card.skill.level, skill_gain_str)
			else:
				res['Skill Gain'] = '<p>{0}</p>'.format('NA')

			# Basic stats
			fmt = '<p style="color:{0};"> {1:<4d} </p>'
			res[col_name['level']] = fmt.format('black', card.level)
			res[col_name['bond']] = fmt.format(attr_color[card.main_attr], card.bond)
			for attr in attr_list:
				res[col_name[attr.lower()]] = fmt.format(attr_color[attr], getattr(card, attr.lower()))

			# Non-skill gem bonus
			base_value = { attr:getattr(card, attr.lower()) + card.bond*(attr==card.main_attr) for attr in attr_list }
			before_C_value = base_value.copy()
			single_plus, single_mult, team_mult = {k:0 for k in attr_list}, {k:0 for k in attr_list}, {k:0 for k in attr_list}
			for gem in card.equipped_gems:
				for attr in attr_list:
					if attr in gem.name:
						if gem.effect == 'attr_add': 
							single_plus[attr] += gem.value
						if gem.effect == 'attr_boost': 
							single_mult[attr] += math.ceil(base_value[attr] * gem.value/100)
			for gem in team_gems:
				for attr in attr_list:
					if attr in gem.name:
						team_mult[attr] += math.ceil(base_value[attr] * gem.value/100)
			for attr in attr_list:
				before_C_value[attr] += single_plus[attr] + single_mult[attr] + team_mult[attr]
			res['Single +'] = single_plus[self.live.attr]
			res['Single ×'] = single_mult[self.live.attr] 
			res['Team ×']   = team_mult[self.live.attr]
			res['Card STR'] = before_C_value[self.live.attr]

			# Center skill bonus and team strength
			res['Main-C'], res['Vice-C'], res['Main-C2'], res['Vice-C2'] = 0, 0, 0, 0
			if cskill is not None and cskill.main_attr == self.live.attr:
				res['Main-C'] += math.ceil(before_C_value[cskill.base_attr] * cskill.main_ratio/100)
				if cskill.bonus_ratio is not None and cskill.bonus_range in card.tags:
					res['Vice-C'] += math.ceil(res['Card STR'] * cskill.bonus_ratio/100)
			if self.guest_cskill is not None and self.guest_cskill.main_attr == self.live.attr:
				res['Main-C2'] += math.ceil(before_C_value[self.guest_cskill.base_attr] * self.guest_cskill.main_ratio/100)
				if self.guest_cskill.bonus_ratio is not None and self.guest_cskill.bonus_range in card.tags:
					res['Vice-C2'] += math.ceil(res['Card STR'] * self.guest_cskill.bonus_ratio/100)
			res['Team STR'] = res['Card STR'] + res['Main-C'] + res['Vice-C'] + res['Main-C2'] + res['Vice-C2']

			# Skill gem equivalent strength
			res['Charm'], res['Heal'], res['Trick'] = 0, 0, 0
			if card.skill is not None and card.skill.effect_type in ['Score Up', 'Stamina Restore']:
				skill_gain = card.skill.skill_gain(setting=new_setting)[0]
				if card.skill.effect_type == 'Score Up':
					res['Charm'] = math.ceil(skill_gain*self.live.strength_per_pt_tap)
					if any(['Charm' in gem.name for gem in card.equipped_gems]):
						res['Charm'] += math.ceil(1.5*skill_gain*self.live.strength_per_pt_tap)
				elif card.skill.effect_type == 'Stamina Restore' and any(['Heal' in gem.name for gem in card.equipped_gems]):
					res['Heal'] = math.ceil(480*skill_gain*self.live.strength_per_pt_tap)
			res['Judge STR'] = res['Team STR']
			if self.live.attr == card.main_attr and any(['Trick' in gem.name for gem in card.equipped_gems]):
				res['Trick'] = math.ceil((res['Card STR']-res['Team ×'])*0.33*self.team_CR)
				res['Judge STR'] += math.ceil((res['Card STR']-res['Team ×'])*0.33)
			res['Skill STR'], res['Amend STR'] = res['Charm']+res['Heal'], res['Team STR']+res['Trick']

			# Compute same group and same color bonus
			res['Live Bonus'] = '{0:.2f}'.format(bonus(card))
			res['Cmb WT%'] = '{0:.2f}%'.format(self.live.combo_weight_fraction[index]*100)
			return res

		# Data frame for detailed stats
		data = [get_summary(i, card) for i, card in enumerate(team.card_list)]
		df = pd.DataFrame(data, columns=columns)

		# Data frame for live song
		def format_song_name(name):
			s = name.split(': ')
			return [s[0] + ':'] + s[1].split(', ') if len(s) > 1 else s[0].split(', ')
		song_name = '<p style="color:{0};">{1}</p>'.format(attr_color[self.live.attr], '<br/>'.join(format_song_name(self.live.name)))
		df_live = pd.DataFrame({'Song Name': [song_name]})
		df_live['Difficulty'] = self.live.difficulty
		df_live['Total Note'] = self.live.note_number
		df_live['Duration'] = self.live.duration
		df_live['Pt per STR'] = self.live.pts_per_strength
		df_live['Presume PR'] = '{0:.2f}%'.format(self.live.perfect_rate*100)
		df_live['Score Up Rate'] = self.setting['score_up_rate']
		df_live['Skill Up Rate'] = self.setting['skill_up_rate']
		df_live['Avg Pos Bonus'] = self.mu_bar
		df_live.index = ['Live Stats']
		df_live.columns = ['<p>{0}</p>'.format(x) for x in list(df_live.columns)]
		df_live = df_live.applymap(lambda x: x if type(x)==str and x[0]=='<' else '<p>{0}</p>'.format(round(x,3) if type(x)==float else ('-' if str(x)=='0' else x)))
		if lang=='CN':
			df_live.columns = ['<p>{0}</p>'.format(x) for x in ['曲名', '难度', 'Note个数' ,'时长', '每点强度对应得分', '预设P率', '应援得分加成', '应援技能加成', '平均位置加成']]
		html_live = df_live.to_html(escape=False)

		# Data frame for brief team total stats
		def format_cskill(cskill):
			if cskill is None: return '<p>{0}</p>'.format('NA')
			fmt ='<img src="{0}" height=25 style="display:inline;vertical-align: middle;">'
			cskill_str  = '<div style="padding:5px">' + fmt.format(misc_path(cskill.main_attr.lower())) + '<span> + </span>'
			cskill_str += fmt.format(misc_path(cskill.base_attr.lower())) + '<span> x {0}% </span>'.format(cskill.main_ratio) + '</div>'
			if cskill.bonus_range is not None:
				cskill_str += '<div style="padding:5px">' + fmt.format(misc_path(cskill.bonus_range))
				cskill_str += fmt.format(misc_path(cskill.main_attr.lower())) + '<span> x {0}% </span>'.format(cskill.bonus_ratio) + '</div>'
			return cskill_str

		df_team = pd.DataFrame({'Center Skill':[format_cskill(team[4].cskill)], 'Guest Center Skill': [format_cskill(self.guest_cskill)]})
		df_team['Mics/OP'] = '{0} / {1}'.format(*team.compute_mics())
		df_team['Cover Rate'] = '{0:.2f}%'.format(self.team_CR*100)
		df_team['Team STR'] = df['Team STR'].sum()
		df_team['Amend Team STR'] = df['Amend STR'].sum()
		df_team['Total Skill STR'] = df['Skill STR'].sum()
		df_team['Expected Score']  = math.floor(df_team['Amend Team STR'] * self.live.pts_per_strength * self.mu_bar * self.setting['score_up_rate']) 
		df_team['Expected Score'] += math.floor(df_team['Total Skill STR'] * self.live.pts_per_strength)
		df_team.index = ['Total Stats']
		df_team.columns = ['<p>{0}</p>'.format(x) for x in list(df_team.columns)]
		df_team = df_team.applymap(lambda x: x if type(x)==str and x[0]=='<' else '<p>{0}</p>'.format(round(x,3) if type(x)==float else ('-' if str(x)=='0' else x)))
		if lang=='CN':
			df_team.columns = ['<p>{0}</p>'.format(x) for x in ['Center技', '好友Center技', 'Mic数/援力', '判定覆盖率' ,'队伍强度', '判定修正队伍强度', '总技能强度', '期望得分']]
		html_team = df_team.to_html(escape=False)


		df.columns = ['<p>{0}</p>'.format(x) if '<p>' not in x else x for x in columns]		
		df = df.applymap(lambda x: x if type(x)==str and x[0]=='<' else '<p>{0}</p>'.format('-' if type(x)==int and x==0 else x))
		df.index = ['<p>{0}</p>'.format(x) for x in ['L1', 'L2', 'L3', 'L4', 'C', 'R4', 'R3', 'R2', 'R1']]
		if lang=='CN':
			columns  = ['<p>{0}</p>'.format(x) for x in ['卡牌编号', '卡牌图标', '装配宝石' ,'技能收益']] + list(df.columns)[4:9]
			columns += ['<p>{0}</p>'.format(x) for x in ['单体增加宝石', '单体加成宝石', '团队加成宝石' ,'单卡界面强度', '队伍主C', '队伍副C', '好友主C', '好友副C', '单卡队中强度', 
						'单卡队中强度(判)', '得分技能强度', '回复技能强度', '判定技能强度', '单卡修正强度', '单卡技能强度', '同色同团加成', '连击权重占比']] 
			df.columns = columns
		html_main = df.transpose().to_html(escape=False)

		html_recommend_guest = ''
		if self.guest_cskill is None:
			# find all UR center skill with same color as the live
			raw_card_dict = {int(k):Card.fromJSON(v) for k,v in json.loads(open(card_archive_dir).read()).items()}
			guest_candidate, cskill_list = defaultdict(lambda:[]), []
			is_new = lambda cskill: all([not x.is_equal(cskill) for x in cskill_list])
			for index, card in raw_card_dict.items():
				if card.main_attr == self.live.attr and card.rarity == 'UR' and not card.promo:
					guest_candidate[(card.cskill.base_attr, card.cskill.bonus_range)].append(card)
					if is_new(card.cskill):
						cskill_list.append(card.cskill)
			# find the center skill that increases the team strength most
			best_guest_cskill, max_strength = None, 0
			for cskill in cskill_list:
				strength = team.team_strength(guest_cskill=cskill)['team_total'][attr_list.index(self.live.attr)]
				if strength > max_strength:
					best_guest_cskill, max_strength = cskill, strength
			recommend_guest = guest_candidate[(best_guest_cskill.base_attr, best_guest_cskill.bonus_range)]
			# construct data frame to demonstrate best guest center skill information
			df_guest = pd.DataFrame()
			df_guest['Recommend Guest Center Skill'] = [format_cskill(best_guest_cskill)]
			# list the cards that has the best guest center skill
			guest_size, fmt = 50, '<div style="float:left;*padding-left:0;"><img src="{0}" width={1} title="{2}"></div>'
			# divs = [fmt.format(icon_path(card_id,idolized), guest_size) for card_id in recommend_guest for idolized in [False,True] ]
			divs1 = [fmt.format(icon_path(card.card_id,False), guest_size, card.tooltip()) for card in recommend_guest]
			divs2 = [fmt.format(icon_path(card.card_id,True), guest_size, card.tooltip()) for card in recommend_guest]
			df_guest['Recommend Guest Icon'] = '<div style="width:{0}px;">{1}<div>'.format(len(divs1)*guest_size, ''.join(divs1)+''.join(divs2))
			# compute the expected score if the best guest center skill is present
			setting = self.setting.copy()
			setting.update({'score_up_bonus':setting['score_up_rate']-1, 'skill_up_bonus':setting['skill_up_rate']-1, 'guest_cskill':best_guest_cskill})
			df_guest['Expected Score'] = team.compute_expected_total_score(copy.deepcopy(self.live), setting)
			df_guest.columns = ['<p>{0}</p>'.format(x) for x in list(df_guest.columns)]
			df_guest = df_guest.applymap(lambda x: x if type(x)==str and x[0]=='<' else '<p>{0}</p>'.format(round(x,3) if type(x)==float else ('-' if str(x)=='0' else x)))
			if lang=='CN':
				df_guest.columns = ['<p>{0}</p>'.format(x) for x in ['推荐好友Center技', '拥有该技能的卡牌图标' ,'应援后期望得分']]
			html_recommend_guest = df_guest.to_html(escape=False, index=False)

		return HTML(html_template.format(html_live+html_team+html_recommend_guest+html_main))