WorldSimulation / CharacterStatistics.py
yingqianjiang-lingoace
update
0a0d866
import numpy as np
import matplotlib.pyplot as plt
class CharacterStatistics:
def __init__(self, characters):
self.characters = characters
self.characters_array = np.array([c.to_list() for c in characters])
# 前n名排行榜
def find_highest_cultivation(self, n=1):
sorted_characters = sorted(self.characters, key=lambda c: (c.cultivation_rank, c.cultivation_level), reverse=True)
return sorted_characters[:n]
# 宗族人数排行榜
def rank_top_clans(self, top_n=4):
clan_size = {}
for c in self.characters:
clan_size[c.clan] = clan_size.get(c.clan, 0) + 1
sorted_clans = sorted(clan_size.items(), key=lambda x: x[1], reverse=True)[:top_n]
return sorted_clans
# real_age、apparent_age、cultivation_level、cultivation_rank 分布图
def plot_attribute_distribution(self):
attributes = ['Real Age', 'Apparent Age', 'Cultivation Level', 'Cultivation Rank']
attribute_indices = [0, 1, 2, 3]
fig, axs = plt.subplots(2, 2, figsize=(10, 8))
axs = axs.flatten()
for i, ax in enumerate(axs):
ax.hist(self.characters_array[:, attribute_indices[i]], bins=20, edgecolor='black')
ax.set_xlabel(attributes[i])
ax.set_ylabel('Frequency')
plt.tight_layout()
return fig
# real_age、apparent_age、cultivation_level、cultivation_rank、孩子数量 统计平均数
def calculate_average_attributes(self):
real_age_mean = np.mean(self.characters_array[:, 0])
apparent_age_mean = np.mean(self.characters_array[:, 1])
cultivation_level_mean = np.mean(self.characters_array[:, 2])
cultivation_rank_mean = np.mean(self.characters_array[:, 3])
child_count_mean = np.mean(self.characters_array[:, 19])
return real_age_mean, apparent_age_mean, cultivation_level_mean, cultivation_rank_mean, child_count_mean
# 画出 cultivation_rank (x轴) 和 4项combat_power的关系(y轴)
def plot_combat_power_vs_cultivation_rank(self):
fig, axs = plt.subplots(2, 2, figsize=(10, 8))
axs = axs.flatten()
for i, combat_power in enumerate(['Attack Power', 'Defense Power', 'Attack Speed', 'Health Points']):
combat_power_data = []
for rank in range(6):
rank_data = self.characters_array[self.characters_array[:,3]==rank, i+5]
combat_power_data.append(rank_data)
axs[i].boxplot(combat_power_data)
axs[i].set_title(combat_power)
axs[i].set_xlabel('Cultivation Rank')
axs[i].set_ylabel('Value')
plt.tight_layout()
return fig
def calculate_average_special_constitution(self):
special_constitution_mean = np.mean(self.characters_array[:, 9:13], axis=0)
return special_constitution_mean
def calculate_average_spiritual_roots(self):
spiritual_roots_mean = np.mean(self.characters_array[:, 13:18], axis=0)
return spiritual_roots_mean
# 统计无灵根者的数量
def count_zero_spiritual_roots(self):
zero_spiritual_roots_count = np.sum(np.all(self.characters_array[:, 13:18] == 0, axis=1))
return zero_spiritual_roots_count
# 灵根数量分布图
def plot_sum_spiritual_root_distribution(self):
spiritual_roots_sum = np.sum(self.characters_array[:, 13:18], axis=1)
fig = plt.figure()
plt.hist(spiritual_roots_sum, bins=5, range=(0,5))
plt.xlabel('Number of Spiritual Roots')
plt.ylabel('Number of Characters')
plt.title('Distribution of Spiritual Roots')
return fig
# 各灵根人口分布(x轴:5种灵根,y轴:人数)
def plot_spiritual_roots_distribution(self):
spiritual_roots = self.characters_array[:, 13:18]
means = np.mean(spiritual_roots, axis=0)
roots = ['Metal', 'Wood', 'Water', 'Fire', 'Earth']
fig = plt.figure()
plt.bar(roots, means)
plt.xlabel('Spiritual Roots')
plt.ylabel('Percentage of Characters')
plt.title('Distribution of Spiritual Roots in Population')
return fig
# 宗族人数分布图
def plot_clan_size_distribution(self):
clan_size = {}
for c in self.characters:
clan_size[c.clan] = clan_size.get(c.clan, 0) + 1
sizes = list(clan_size.values())
fig = plt.figure()
plt.hist(sizes, bins=20)
plt.xlabel('Clan Size')
plt.ylabel('Number of Clans')
return fig
def summarize(self):
print("===== Character Statistics Summary =====")
# 打印平均属性
print("Average Attributes:")
real_age, apparent_age, cultivation_level, cultivation_rank, child_count = self.calculate_average_attributes()
print(f"Real Age: {real_age:.2f}")
print(f"Apparent Age: {apparent_age:.2f}")
print(f"Cultivation Level: {cultivation_level:.2f}")
print(f"Cultivation Rank: {cultivation_rank:.2f}")
print(f"Child Count: {child_count:.2f}")
# 打印平均特质
print("\nAverage Special Constitutions:")
special_names = ['战斗', '合欢', '灵龟', '蜉蝣']
for i, v in enumerate(self.calculate_average_special_constitution()):
print(f"{special_names[i]}: {v:.2%}")
# 打印平均灵根
print("\nAverage Spiritual Roots:")
root_names = ['金', '木', '水', '火', '土']
for i, v in enumerate(self.calculate_average_spiritual_roots()):
print(f"{root_names[i]}: {v:.2%}")
# 打印统计图
print("\nPlotting graphs...")
self.plot_attribute_distribution()
# self.plot_combat_power_vs_cultivation_rank()
self.plot_spiritual_roots_distribution()
self.plot_sum_spiritual_root_distribution()
self.plot_clan_size_distribution()
self.print_top_cultivators()
# 攻击力排行榜
self.print_rank('attack_power', name='Attack Power')
# 防御力排行榜
self.print_rank('defense_power', name='Defense Power')
self.print_top_clans()
print("\n===== End Summary =====\n")
# 返回Markdown字符串的总结输出
def summarize_markdown(self):
md = "## Character Statistics Summary\n\n"
md += "### Average Attributes:\n\n"
real_age, apparent_age, cultivation_level, cultivation_rank, child_count = self.calculate_average_attributes()
md += f"Real Age: {real_age:.2f}\n\n"
md += f"Apparent Age: {apparent_age:.2f}\n\n"
md += f"Cultivation Level: {cultivation_level:.2f}\n\n"
md += f"Cultivation Rank: {cultivation_rank:.2f}\n\n"
md += f"Child Count: {child_count:.2f}\n\n"
md += "### Average Special Constitutions:\n\n"
special_names = ['战斗', '合欢', '灵龟', '蜉蝣']
for i, v in enumerate(self.calculate_average_special_constitution()):
md += f"{special_names[i]}: {v:.2%}\n\n"
md += "### Average Spiritual Roots:\n\n"
root_names = ['金', '木', '水', '火', '土']
for i, v in enumerate(self.calculate_average_spiritual_roots()):
md += f"{root_names[i]}: {v:.2%}\n\n"
# md += "### Plotting graphs...\n\n"
# 画图并保存
fig1 = self.plot_attribute_distribution()
# fig1.savefig('./attribute_distribution.png')
# md += "#### Attribute Distribution\n\n"
# md += "![Attribute Distribution](./attribute_distribution.png)\n\n"
fig2 = self.plot_spiritual_roots_distribution()
# fig2.savefig('./spiritual_roots_distribution.png')
# md += "#### Spiritual Roots Distribution\n\n"
# md += "![Spiritual Roots Distribution](./spiritual_roots_distribution.png)\n\n"
fig3 = self.plot_sum_spiritual_root_distribution()
# fig3.savefig('./sum_spiritual_roots_distribution.png')
# md += "#### Sum Spiritual Roots Distribution\n\n"
# md += "![Sum Spiritual Roots Distribution](./sum_spiritual_roots_distribution.png)\n\n"
fig4 = self.plot_clan_size_distribution()
# fig4.savefig('clan_size_distribution.png')
# md += "#### Clan Size Distribution\n\n"
# md += "![Clan Size Distribution](clan_size_distribution.png)\n\n"
md += "#### Top Cultivators\n\n"
md += self.print_top_cultivators_markdown()
md += "#### Attack Power Ranking\n\n"
md += self.print_rank_markdown('attack_power', name='Attack Power')
md += "#### Defense Power Ranking\n\n"
md += self.print_rank_markdown('defense_power', name='Defense Power')
md += "#### Top Clans\n\n"
md += self.print_top_clans_markdown()
return md, fig1, fig2, fig3, fig4
def print_top_cultivators(self, top_n=10):
print("\n== Top Cultivators ==")
print("{:<10} {:>10} {:>10} {:>10} {:>10}".format('Name', 'Clan', 'Rank', 'Level', '境界'))
for c in self.find_highest_cultivation(top_n):
print("{:<10} {:>10} {:>10} {:>10} {:>10}".format(c.name, c.clan, c.cultivation_rank, c.cultivation_level, c.view_rank()))
def print_top_cultivators_markdown(self, n=10):
md = f"| Name | Clan | Cultivation Rank | Cultivation Level | 境界\n"
md += "| ---- | ---- | ---------------- | ---------------- | ----\n"
for c in self.find_highest_cultivation(n):
md += f"| {c.name} | {c.clan} | {c.cultivation_rank:.2f} | {c.cultivation_level:.2f} | {c.view_rank()}\n"
return md
def print_rank(self, rank_key, top_n=10, name=None):
print(f"\n== {'Name' if name is None else name} Rank ==")
sorted_characters = sorted(self.characters, key=lambda c: c.combat_power[rank_key], reverse=True)
print("{:<10} {:>10} {:>10} {:>10} {:>10}".format('Name', rank_key if name is None else name, 'Rank', 'Level', '境界'))
for c in sorted_characters[:top_n]:
print("{:<10} {:>10}{:>10} {:>10} {:>10}".format(c.name, c.combat_power[rank_key], c.cultivation_rank, c.cultivation_level, c.view_rank()))
def print_rank_markdown(self, attr, name=None, n=10):
md = f"| Name | {attr if name is None else name} | Cultivation Rank | Cultivation Level | 境界\n"
md += "| ---- | ---- | ---------------- | ---------------- | ----\n"
sorted_characters = sorted(self.characters, key=lambda c: c.combat_power[attr], reverse=True)
for c in sorted_characters[:n]:
md += f"| {c.name} | {c.combat_power[attr]:.2f} | {c.cultivation_rank:.2f} | {c.cultivation_level:.2f} | {c.view_rank()}\n"
return md
def print_top_clans(self, top_n=4):
print("\n== Top Clans ==")
print("{:<10} {:>10}".format('Clan', 'Members'))
for clan, size in self.rank_top_clans(top_n):
print("{:<10} {:>10}".format(clan, size))
def print_top_clans_markdown(self, n=10):
md = "| Clan | Clan Size |\n"
md += "| -------- | --------- |\n"
for clan, size in self.rank_top_clans(n):
md += f"| {clan} | {size} |\n"
return md