using System; using System.Threading; using System.Collections; using System.Collections.Generic; using Server; using Server.Items; using Server.Mobiles; using Server.Network; using Server.Factions; using Server.Accounting; using Server.Engines.ConPVP; namespace Server.Engines.Reports { public class Reports { public static bool Enabled = false; public static void Initialize() { if ( !Enabled ) return; m_StatsHistory = new SnapshotHistory(); m_StatsHistory.Load(); m_StaffHistory = new StaffHistory(); m_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 ), new TimerCallback( CheckRegenerate ) ); } private static DateTime m_GenerateTime; public static void CheckRegenerate() { if ( DateTime.UtcNow < m_GenerateTime ) return; Generate(); m_GenerateTime += TimeSpan.FromHours( 1.0 ); } private static SnapshotHistory m_StatsHistory; private static StaffHistory m_StaffHistory; public static StaffHistory StaffHistory{ get{ return m_StaffHistory; } } public static void Generate() { Snapshot ss = new Snapshot(); ss.TimeStamp = DateTime.UtcNow; FillSnapshot( ss ); m_StatsHistory.Snapshots.Add( ss ); m_StaffHistory.QueueStats.Add( new QueueStatus( Engines.Help.PageQueue.List.Count ) ); ThreadPool.QueueUserWorkItem( new WaitCallback( UpdateOutput ), ss ); } private static void UpdateOutput( object state ) { m_StatsHistory.Save(); m_StaffHistory.Save(); HtmlRenderer renderer = new HtmlRenderer( "stats", (Snapshot) state, m_StatsHistory ); renderer.Render(); renderer.Upload(); renderer = new HtmlRenderer( "staff", m_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 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 class SkillDistribution : IComparable { public SkillInfo m_Skill; public int m_NumberOfGMs; public SkillDistribution( SkillInfo skill ) { m_Skill = skill; } public int CompareTo( object obj ) { return ( ((SkillDistribution)obj).m_NumberOfGMs - m_NumberOfGMs ); } } 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 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 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 = String.Format( "{0} Finance Minister", pl.Finance.Definition.FriendlyName ); else if ( pl.Sheriff != null ) office = String.Format( "{0} Sheriff", pl.Sheriff.Definition.FriendlyName ); 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 factions = Faction.Factions; for ( int i = 0; i < factions.Count; ++i ) { Faction faction = factions[i]; List 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 sigils = Sigil.Sigils; for ( int i = 0; i < sigils.Count; ++i ) { Sigil sigil = sigils[i]; string controller = "Unknown"; Mobile mob = sigil.RootParent as Mobile; if ( mob != null ) { Faction faction = Faction.Find( mob ); if ( faction != null ) controller = faction.Definition.FriendlyName; } else if ( sigil.LastMonolith != null && 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 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.ToString() + "%"; else if ( town.Tax > 0 ) prices = "+" + town.Tax.ToString() + "%"; 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; } } }