示例#1
0
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> &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

	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)))
示例#2
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
示例#3
0
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)))
示例#4
0
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> &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:
			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> &nbsp &nbsp {0} &nbsp </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))
示例#9
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:
            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> &nbsp &nbsp {0} &nbsp </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