ModernUO/Scripts/Engines/Reports/Reports.cs

548 lines
No EOL
15 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using Server.Accounting;
using Server.Engines.ConPVP;
using Server.Engines.Help;
using Server.Factions;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.Reports
{
public class Reports
{
public static bool Enabled = false;
private static DateTime m_GenerateTime;
private static SnapshotHistory m_StatsHistory;
public static StaffHistory StaffHistory{ get; private set; }
public static void Initialize()
{
if (!Enabled)
return;
m_StatsHistory = new SnapshotHistory();
m_StatsHistory.Load();
StaffHistory = new StaffHistory();
StaffHistory.Load();
DateTime now = DateTime.UtcNow;
DateTime date = now.Date;
TimeSpan timeOfDay = now.TimeOfDay;
m_GenerateTime = date + TimeSpan.FromHours(Math.Ceiling(timeOfDay.TotalHours));
Timer.DelayCall(TimeSpan.FromMinutes(0.5), TimeSpan.FromMinutes(0.5), CheckRegenerate);
}
public static void CheckRegenerate()
{
if (DateTime.UtcNow < m_GenerateTime)
return;
Generate();
m_GenerateTime += TimeSpan.FromHours(1.0);
}
public static void Generate()
{
Snapshot ss = new Snapshot();
ss.TimeStamp = DateTime.UtcNow;
FillSnapshot(ss);
m_StatsHistory.Snapshots.Add(ss);
StaffHistory.QueueStats.Add(new QueueStatus(PageQueue.List.Count));
ThreadPool.QueueUserWorkItem(UpdateOutput, ss);
}
private static void UpdateOutput(object state)
{
m_StatsHistory.Save();
StaffHistory.Save();
HtmlRenderer renderer = new HtmlRenderer("stats", (Snapshot)state, m_StatsHistory);
renderer.Render();
renderer.Upload();
renderer = new HtmlRenderer("staff", StaffHistory);
renderer.Render();
renderer.Upload();
}
public static void FillSnapshot(Snapshot ss)
{
ss.Children.Add(CompileGeneralStats());
ss.Children.Add(CompilePCByDL());
ss.Children.Add(CompileTop15());
ss.Children.Add(CompileDislikedArenas());
ss.Children.Add(CompileStatChart());
PersistableObject[] obs = CompileSkillReports();
for (int i = 0; i < obs.Length; ++i)
ss.Children.Add(obs[i]);
obs = CompileFactionReports();
for (int i = 0; i < obs.Length; ++i)
ss.Children.Add(obs[i]);
}
public static Report CompileGeneralStats()
{
Report report = new Report("General Stats", "200");
report.Columns.Add("50%", "left");
report.Columns.Add("50%", "left");
int npcs = 0, players = 0;
foreach (Mobile mob in World.Mobiles.Values)
if (mob.Player)
++players;
else
++npcs;
report.Items.Add("NPCs", npcs, "N0");
report.Items.Add("Players", players, "N0");
report.Items.Add("Clients", NetState.Instances.Count, "N0");
report.Items.Add("Accounts", Accounts.Count, "N0");
report.Items.Add("Items", World.Items.Count, "N0");
return report;
}
private static Chart CompilePCByDL()
{
BarGraph chart = new BarGraph("Player Count By Dueling Level", "graphs_pc_by_dl", 5, "Dueling Level", "Players",
BarGraphRenderMode.Bars);
int lastLevel = -1;
ChartItem lastItem = null;
Ladder ladder = Ladder.Instance;
if (ladder != null)
{
ArrayList entries = ladder.ToArrayList();
for (int i = entries.Count - 1; i >= 0; --i)
{
LadderEntry entry = (LadderEntry)entries[i];
int level = Ladder.GetLevel(entry.Experience);
if (lastItem == null || level != lastLevel)
{
chart.Items.Add(lastItem = new ChartItem(level.ToString(), 1));
lastLevel = level;
}
else
{
lastItem.Value++;
}
}
}
return chart;
}
private static Report CompileTop15()
{
Report report = new Report("Top 15 Duelists", "80%");
report.Columns.Add("6%", "center", "Rank");
report.Columns.Add("6%", "center", "Level");
report.Columns.Add("6%", "center", "Guild");
report.Columns.Add("70%", "left", "Name");
report.Columns.Add("6%", "center", "Wins");
report.Columns.Add("6%", "center", "Losses");
Ladder ladder = Ladder.Instance;
if (ladder != null)
{
ArrayList entries = ladder.ToArrayList();
for (int i = 0; i < entries.Count && i < 15; ++i)
{
LadderEntry entry = (LadderEntry)entries[i];
int level = Ladder.GetLevel(entry.Experience);
string guild = "";
if (entry.Mobile.Guild != null)
guild = entry.Mobile.Guild.Abbreviation;
ReportItem item = new ReportItem();
item.Values.Add(LadderGump.Rank(entry.Index + 1));
item.Values.Add(level.ToString(), "N0");
item.Values.Add(guild);
item.Values.Add(entry.Mobile.Name);
item.Values.Add(entry.Wins.ToString(), "N0");
item.Values.Add(entry.Losses.ToString(), "N0");
report.Items.Add(item);
}
}
return report;
}
private static Chart CompileDislikedArenas()
{
PieChart chart = new PieChart("Most Disliked Arenas", "graphs_arenas_disliked", false);
Preferences prefs = Preferences.Instance;
if (prefs != null)
{
List<Arena> arenas = Arena.Arenas;
for (int i = 0; i < arenas.Count; ++i)
{
Arena arena = arenas[i];
string name = arena.Name;
if (name != null)
chart.Items.Add(name, 0);
}
ArrayList entries = prefs.Entries;
for (int i = 0; i < entries.Count; ++i)
{
PreferencesEntry entry = (PreferencesEntry)entries[i];
ArrayList list = entry.Disliked;
for (int j = 0; j < list.Count; ++j)
{
string disliked = (string)list[j];
for (int k = 0; k < chart.Items.Count; ++k)
{
ChartItem item = chart.Items[k];
if (item.Name == disliked)
{
++item.Value;
break;
}
}
}
}
}
return chart;
}
public static Chart CompileStatChart()
{
PieChart chart = new PieChart("Stat Distribution", "graphs_strdexint_distrib", true);
ChartItem strItem = new ChartItem("Strength", 0);
ChartItem dexItem = new ChartItem("Dexterity", 0);
ChartItem intItem = new ChartItem("Intelligence", 0);
foreach (Mobile mob in World.Mobiles.Values)
if (mob.RawStatTotal == mob.StatCap && mob is PlayerMobile)
{
strItem.Value += mob.RawStr;
dexItem.Value += mob.RawDex;
intItem.Value += mob.RawInt;
}
chart.Items.Add(strItem);
chart.Items.Add(dexItem);
chart.Items.Add(intItem);
return chart;
}
public static SkillDistribution[] GetSkillDistribution()
{
int skip = Core.ML ? 0 : Core.SE ? 1 : Core.AOS ? 3 : 6;
SkillDistribution[] distribs = new SkillDistribution[SkillInfo.Table.Length - skip];
for (int i = 0; i < distribs.Length; ++i)
distribs[i] = new SkillDistribution(SkillInfo.Table[i]);
foreach (Mobile mob in World.Mobiles.Values)
if (mob.SkillsTotal >= 1500 && mob.SkillsTotal <= 7200 && mob is PlayerMobile)
{
Skills skills = mob.Skills;
for (int i = 0; i < skills.Length - skip; ++i)
{
Skill skill = skills[i];
if (skill.BaseFixedPoint >= 1000)
distribs[i].m_NumberOfGMs++;
}
}
return distribs;
}
public static PersistableObject[] CompileSkillReports()
{
SkillDistribution[] distribs = GetSkillDistribution();
Array.Sort(distribs);
return new PersistableObject[] { CompileSkillChart(distribs), CompileSkillReport(distribs) };
}
public static Report CompileSkillReport(SkillDistribution[] distribs)
{
Report report = new Report("Skill Report", "300");
report.Columns.Add("70%", "left", "Name");
report.Columns.Add("30%", "center", "GMs");
for (int i = 0; i < distribs.Length; ++i)
report.Items.Add(distribs[i].m_Skill.Name, distribs[i].m_NumberOfGMs, "N0");
return report;
}
public static Chart CompileSkillChart(SkillDistribution[] distribs)
{
PieChart chart = new PieChart("GM Skill Distribution", "graphs_skill_distrib", true);
for (int i = 0; i < 12; ++i)
chart.Items.Add(distribs[i].m_Skill.Name, distribs[i].m_NumberOfGMs);
int rem = 0;
for (int i = 12; i < distribs.Length; ++i)
rem += distribs[i].m_NumberOfGMs;
chart.Items.Add("Other", rem);
return chart;
}
public static PersistableObject[] CompileFactionReports()
{
return new PersistableObject[]
{
CompileFactionMembershipChart(), CompileFactionReport(), CompileFactionTownReport(), CompileSigilReport(),
CompileFactionLeaderboard()
};
}
public static Chart CompileFactionMembershipChart()
{
PieChart chart = new PieChart("Faction Membership", "graphs_faction_membership", true);
List<Faction> factions = Faction.Factions;
for (int i = 0; i < factions.Count; ++i)
chart.Items.Add(factions[i].Definition.FriendlyName, factions[i].Members.Count);
return chart;
}
public static Report CompileFactionLeaderboard()
{
Report report = new Report("Faction Leaderboard", "60%");
report.Columns.Add("28%", "center", "Name");
report.Columns.Add("28%", "center", "Faction");
report.Columns.Add("28%", "center", "Office");
report.Columns.Add("16%", "center", "Kill Points");
ArrayList list = new ArrayList();
List<Faction> factions = Faction.Factions;
for (int i = 0; i < factions.Count; ++i)
{
Faction faction = factions[i];
list.AddRange(faction.Members);
}
list.Sort();
list.Reverse();
for (int i = 0; i < list.Count && i < 15; ++i)
{
PlayerState pl = (PlayerState)list[i];
string office;
if (pl.Faction.Commander == pl.Mobile)
office = "Commanding Lord";
else if (pl.Finance != null)
office = $"{pl.Finance.Definition.FriendlyName} Finance Minister";
else if (pl.Sheriff != null)
office = $"{pl.Sheriff.Definition.FriendlyName} Sheriff";
else
office = "";
ReportItem item = new ReportItem();
item.Values.Add(pl.Mobile.Name);
item.Values.Add(pl.Faction.Definition.FriendlyName);
item.Values.Add(office);
item.Values.Add(pl.KillPoints.ToString(), "N0");
report.Items.Add(item);
}
return report;
}
public static Report CompileFactionReport()
{
Report report = new Report("Faction Statistics", "80%");
report.Columns.Add("20%", "center", "Name");
report.Columns.Add("20%", "center", "Commander");
report.Columns.Add("15%", "center", "Members");
report.Columns.Add("15%", "center", "Merchants");
report.Columns.Add("15%", "center", "Kill Points");
report.Columns.Add("15%", "center", "Silver");
List<Faction> factions = Faction.Factions;
for (int i = 0; i < factions.Count; ++i)
{
Faction faction = factions[i];
List<PlayerState> members = faction.Members;
int totalKillPoints = 0;
int totalMerchants = 0;
for (int j = 0; j < members.Count; ++j)
{
totalKillPoints += members[j].KillPoints;
if (members[j].MerchantTitle != MerchantTitle.None)
++totalMerchants;
}
ReportItem item = new ReportItem();
item.Values.Add(faction.Definition.FriendlyName);
item.Values.Add(faction.Commander == null ? "" : faction.Commander.Name);
item.Values.Add(faction.Members.Count.ToString(), "N0");
item.Values.Add(totalMerchants.ToString(), "N0");
item.Values.Add(totalKillPoints.ToString(), "N0");
item.Values.Add(faction.Silver.ToString(), "N0");
report.Items.Add(item);
}
return report;
}
public static Report CompileSigilReport()
{
Report report = new Report("Faction Town Sigils", "50%");
report.Columns.Add("35%", "center", "Town");
report.Columns.Add("35%", "center", "Controller");
report.Columns.Add("30%", "center", "Capturable");
List<Sigil> sigils = Sigil.Sigils;
for (int i = 0; i < sigils.Count; ++i)
{
Sigil sigil = sigils[i];
string controller = "Unknown";
if (sigil.RootParent is Mobile mob)
{
Faction faction = Faction.Find(mob);
if (faction != null)
controller = faction.Definition.FriendlyName;
}
else if (sigil.LastMonolith?.Faction != null)
{
controller = sigil.LastMonolith.Faction.Definition.FriendlyName;
}
ReportItem item = new ReportItem();
item.Values.Add(sigil.Town == null ? "" : sigil.Town.Definition.FriendlyName);
item.Values.Add(controller);
item.Values.Add(sigil.IsPurifying ? "No" : "Yes");
report.Items.Add(item);
}
return report;
}
public static Report CompileFactionTownReport()
{
Report report = new Report("Faction Towns", "80%");
report.Columns.Add("20%", "center", "Name");
report.Columns.Add("20%", "center", "Owner");
report.Columns.Add("17%", "center", "Sheriff");
report.Columns.Add("17%", "center", "Finance Minister");
report.Columns.Add("13%", "center", "Silver");
report.Columns.Add("13%", "center", "Prices");
List<Town> towns = Town.Towns;
for (int i = 0; i < towns.Count; ++i)
{
Town town = towns[i];
string prices = "Normal";
if (town.Tax < 0)
prices = town.Tax + "%";
else if (town.Tax > 0)
prices = "+" + town.Tax + "%";
ReportItem item = new ReportItem();
item.Values.Add(town.Definition.FriendlyName);
item.Values.Add(town.Owner == null ? "Neutral" : town.Owner.Definition.FriendlyName);
item.Values.Add(town.Sheriff == null ? "" : town.Sheriff.Name);
item.Values.Add(town.Finance == null ? "" : town.Finance.Name);
item.Values.Add(town.Silver.ToString(), "N0");
item.Values.Add(prices);
report.Items.Add(item);
}
return report;
}
public class SkillDistribution : IComparable
{
public int m_NumberOfGMs;
public SkillInfo m_Skill;
public SkillDistribution(SkillInfo skill)
{
m_Skill = skill;
}
public int CompareTo(object obj)
{
return ((SkillDistribution)obj).m_NumberOfGMs - m_NumberOfGMs;
}
}
}
}