def view_card(card, show_gem=False, extra_col=[], gem_size=25): def get_summary(index, card, show_gem=False, ext_col=[]): res = {'index':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=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>     {0}   </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 col_name = {'view':'<p><b> Card View </b></p>', 'skill':'<p><b> Skill & Center Skill </b></p>'} col_name.update({ x:'<img src="{0}" width=25/>'.format(misc_path(x)) for x in ['level','bond','hp','smile','pure','cool'] }) columns = ['index', 'CID'] columns += [col_name[x] for x in ['view', 'skill', 'level', 'bond', 'hp', 'smile', 'pure', 'cool']] columns += ['Skill Gain', 'skill_strength', 'general_strength'] columns += extra_col df = pd.DataFrame([get_summary(0, card, show_gem=show_gem, ext_col=extra_col)], columns=columns) df = df.set_index('index') df.index.name = '' return HTML(html_template.format(df.to_html(escape=False, index=False)))
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
def view_cards(cards, show_gem=False, extra_col=[], gem_size=25, no_skill=True): 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 col_name = {'view':'<p><b> Card View </b></p>', 'skill':'<p><b> Skill & Center Skill </b></p>'} col_name.update({ x:'<img src="{0}" width=25/>'.format(misc_path(x)) for x in ['level','bond','hp','smile','pure','cool'] }) columns = ['index', 'CID'] columns += [col_name[x] for x in ['view', 'skill', 'level', 'bond', 'hp', 'smile', 'pure', 'cool']] columns += ['Skill Gain'] + extra_col if isinstance(cards, pd.core.frame.DataFrame): data = [get_summary(index, card, show_gem, ext_col=extra_col) for index, card in cards.iterrows()] elif type(cards) == list: data = [get_summary(index, card, show_gem, ext_col=extra_col) for index, card in enumerate(cards,1)] elif type(cards) == dict: data = [get_summary(index, card, show_gem, ext_col=extra_col) for index, card in cards.items()] data.sort(key=lambda x: x['index']) else: print('Input must be a list, a dict, or a pandas DataFrame!') raise df = pd.DataFrame(data, columns=columns) df = df.set_index('index') df.index.name = '' if no_skill: del df['<p><b> Skill & Center Skill </b></p>'] del df[col_name['hp']] return HTML(html_template.format(df.to_html(escape=False)))
def view_team(team, show_gem=False, extra_col=[], gem_size=25): def get_summary(index, card, show_gem=False, ext_col=[]): res = {'index':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=60 />'.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: gain = card.skill.skill_gain()[0] if card.skill is None: skill_gain_str = 'NA' elif card.skill.effect_type in ['Strong Judge', 'Weak Judge']: skill_gain_str = '{0:.4f}% covered '.format(100*gain) elif card.skill.effect_type == 'Stamina Restore': skill_gain_str = '{0:.4f} hp/note'.format(gain) elif card.skill.effect_type == 'Score Up': skill_gain_str = '{0:.4f} pt/note'.format(gain) temp = repr(card.skill).split(': ') fmt = '<p> <img style="float: left" src="{0}" width=15 /> {1} <br style="clear: both;"/> {2} <br/> {3} Gain: {4} </p>' res[col_name['skill']] = fmt.format(misc_path(card.skill.effect_type) ,temp[0], *temp[1].split('. '), skill_gain_str) 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>     {0}   </b> </p>'.format(card.hp) fmt = '<p style="color:{0};"> {1:<4d} <br/> {2:<4d} <br/> {3:<4d} </p>' res[col_name['smile']] = fmt.format('red', card.smile, disp_card_attr[index][0], final_card_attr[index][0]) res[col_name['pure']] = fmt.format('green', card.pure, disp_card_attr[index][1], final_card_attr[index][1]) res[col_name['cool']] = fmt.format('blue', card.cool, disp_card_attr[index][2], final_card_attr[index][2]) # If there are other columns to show for attr in ext_col: res[attr] = getattr(card, attr) return res team_strength_info = team.team_strength() disp_card_attr = team_strength_info['displayed_card_attr'] final_card_attr = team_strength_info['final_card_attr'] col_name = {'view':'<p><b> Card View </b></p>', 'skill':'<p><b> Skill & Center Skill </b></p>'} col_name.update({ x:'<img src="{0}" width=25/>'.format(misc_path(x)) for x in ['level','bond','hp','smile','pure','cool'] }) columns = ['index', 'CID'] columns += [col_name[x] for x in ['view', 'skill', 'level', 'bond', 'hp', 'smile', 'pure', 'cool']] columns += extra_col data = [get_summary(index, card, show_gem, ext_col=extra_col) for index, card in enumerate(team.card_list)] df = pd.DataFrame(data, columns=columns) pos_name = ['L1', 'L2', 'L3', 'L4', 'C', 'R4', 'R3', 'R2', 'R1'] df['index'] = pos_name df = df.set_index('index') df.index.name = '' # For Team input, add header for team stats col = ['team_total', 'team_center_skill_bonus', 'center_SIS_bonus', 'guest_center_skill_bonus'] df_header = pd.DataFrame({c:team_strength_info[c] for c in col}, columns=col, index=attr_list) df_header.columns = ['Team Total', 'Center Skill Bonus', 'Center SIS Bonus', 'Support Member Bonus'] header = '<div align="left"> {0} </div>'.format(df_header.to_html()) # Bold center skill of the center member temp =[str(x) for x in BeautifulSoup(df.loc['C', col_name['skill']], "html.parser").find_all('p')] center = team.center() if len(temp) == 2: start_str = '<p style="color:{0};"><b><u>'.format(attr_color[center.main_attr]) temp[-1] = temp[-1].replace('<p>',start_str).replace('</p>','</u></b></p>') df.loc['C', col_name['skill']] = ''.join(temp) # For all member satisfying center skill bonus range, if center.cskill.bonus_range is not None: bonus_range = groups[center.cskill.bonus_range] start_str = '<span style="background-color:{0};color:white">'.format(attr_color[center.main_attr]) for index, card in zip(pos_name, team.card_list): if card.main_attr == center.main_attr: df.loc[index, 'CID'] = df.loc[index, 'CID'].replace('<span>','<span><u>').replace('</u></span>','</span>') if card.member_name in bonus_range: df.loc[index, 'CID'] = df.loc[index, 'CID'].replace('<span>',start_str) # Place center card first df = df.loc[['C', 'L1', 'L2', 'L3', 'L4', 'R4', 'R3', 'R2', 'R1']] return HTML(html_template.format(header + df.to_html(escape=False)))
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 />'.format( icon_path(card.card_id, card.idolized)) 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
def show_rough_strength(self, extra_col=[], no_skill=True): 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 />'.format( icon_path(card.card_id, card.idolized)) 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 col_name = { 'view': '<p><b> Card View </b></p>', 'skill': '<p><b> Skill & Center Skill </b></p>' } col_name.update({ x: '<img src="{0}" width=25/>'.format(misc_path(x)) for x in ['level', 'bond', 'hp', 'smile', 'pure', 'cool'] }) columns = ['index', 'CID'] columns += [ col_name[x] for x in ['view', 'skill', 'level', 'bond', 'hp', 'smile', 'pure', 'cool'] ] columns += ['Slot', 'Skill Gain'] + [ 'sort_STR', 'skill_effect_type', 'skill_gain' ] + extra_col data = [ get_summary(card, ext_col=extra_col) for card in self.cards if card.rarity not in ['N', 'R'] ] df = pd.DataFrame(data, columns=columns) df = df.set_index('index') df.index.name = '' df_all = df.sort_values(by='sort_STR', ascending=False) del df_all['sort_STR'] del df_all['skill_effect_type'] del df_all['skill_gain'] if no_skill: del df_all['<p><b> Skill & Center Skill </b></p>'] del df_all[col_name['hp']] df_healer = df[df.skill_effect_type == 'Stamina Restore'].sort_values( by='skill_gain', ascending=False) del df_healer['sort_STR'] del df_healer['skill_effect_type'] del df_healer['skill_gain'] if no_skill: del df_healer['<p><b> Skill & Center Skill </b></p>'] del df_healer[col_name['hp']] df_plocker = df[df.apply(lambda x: 'Judge' in x.skill_effect_type, axis=1)].sort_values(by='skill_gain', ascending=False) del df_plocker['sort_STR'] del df_plocker['skill_effect_type'] del df_plocker['skill_gain'] if no_skill: del df_plocker['<p><b> Skill & Center Skill </b></p>'] del df_plocker[col_name['hp']] return { 'all': HTML(html_template.format(df_all.to_html(escape=False))), 'healer': HTML(html_template.format(df_healer.to_html(escape=False))), 'plocker': HTML(html_template.format(df_plocker.to_html(escape=False))) }
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
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))
def get_summary(index, card, show_gem=False, ext_col=[]): res = { 'index': 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=60 />'.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: gain = card.skill.skill_gain()[0] if card.skill is None: skill_gain_str = 'NA' elif card.skill.effect_type in ['Strong Judge', 'Weak Judge']: skill_gain_str = '{0:.4f}% covered '.format(100 * gain) elif card.skill.effect_type == 'Stamina Restore': skill_gain_str = '{0:.4f} hp/note'.format(gain) elif card.skill.effect_type == 'Score Up': skill_gain_str = '{0:.4f} pt/note'.format(gain) temp = repr(card.skill).split(': ') fmt = '<p> <img style="float: left" src="{0}" width=15 /> {1} <br style="clear: both;"/> {2} <br/> {3} Gain: {4} </p>' res[col_name['skill']] = fmt.format( misc_path(card.skill.effect_type), temp[0], *temp[1].split('. '), skill_gain_str) 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>     {0}   </b> </p>'.format( card.hp) fmt = '<p style="color:{0};"> {1:<4d} <br/> {2:<4d} <br/> {3:<4d} </p>' res[col_name['smile']] = fmt.format('red', card.smile, disp_card_attr[index][0], final_card_attr[index][0]) res[col_name['pure']] = fmt.format('green', card.pure, disp_card_attr[index][1], final_card_attr[index][1]) res[col_name['cool']] = fmt.format('blue', card.cool, disp_card_attr[index][2], final_card_attr[index][2]) # If there are other columns to show for attr in ext_col: res[attr] = getattr(card, attr) return res