using System; using System.IO; using System.Web; using System.Web.UI; using System.Net; using System.Drawing; using System.Drawing.Imaging; using System.Collections; using System.Diagnostics; using HtmlTag = System.Web.UI.HtmlTextWriterTag; using HtmlAttr = System.Web.UI.HtmlTextWriterAttribute; namespace Server.Engines.Reports { public class HtmlRenderer { private string m_Type; private string m_Title; private string m_OutputDirectory; private DateTime m_TimeStamp; private ObjectCollection m_Objects; private HtmlRenderer( string outputDirectory ) { m_Type = outputDirectory; m_Title = ( m_Type == "staff" ? "Staff" : "Stats" ); m_OutputDirectory = Path.Combine( Core.BaseDirectory, "output" ); if ( !Directory.Exists( m_OutputDirectory ) ) Directory.CreateDirectory( m_OutputDirectory ); m_OutputDirectory = Path.Combine( m_OutputDirectory, outputDirectory ); if ( !Directory.Exists( m_OutputDirectory ) ) Directory.CreateDirectory( m_OutputDirectory ); } public HtmlRenderer( string outputDirectory, Snapshot ss, SnapshotHistory history ) : this( outputDirectory ) { m_TimeStamp = ss.TimeStamp; m_Objects = new ObjectCollection(); for ( int i = 0; i < ss.Children.Count; ++i ) m_Objects.Add( ss.Children[i] ); m_Objects.Add( BarGraph.OverTime( history, "General Stats", "Clients", 1, 100, 6 ) ); m_Objects.Add( BarGraph.OverTime( history, "General Stats", "Items", 24, 9, 1 ) ); m_Objects.Add( BarGraph.OverTime( history, "General Stats", "Players", 24, 9, 1 ) ); m_Objects.Add( BarGraph.OverTime( history, "General Stats", "NPCs", 24, 9, 1 ) ); m_Objects.Add( BarGraph.DailyAverage( history, "General Stats", "Clients" ) ); m_Objects.Add( BarGraph.Growth( history, "General Stats", "Clients" ) ); } public HtmlRenderer( string outputDirectory, StaffHistory history ) : this( outputDirectory ) { m_TimeStamp = DateTime.Now; m_Objects = new ObjectCollection(); history.Render( m_Objects ); } public void Render() { Console.WriteLine( "Reports: {0}: Render started", m_Title ); RenderFull(); for ( int i = 0; i < m_Objects.Count; ++i ) RenderSingle( m_Objects[i] ); Console.WriteLine( "Reports: {0}: Render complete", m_Title ); } private static readonly string FtpHost = null; private static readonly string FtpUsername = null; private static readonly string FtpPassword = null; private static readonly string FtpStatsDirectory = null; private static readonly string FtpStaffDirectory = null; public void Upload() { if ( FtpHost == null ) return; Console.WriteLine( "Reports: {0}: Upload started", m_Title ); string filePath = Path.Combine( m_OutputDirectory, "upload.ftp" ); using ( StreamWriter op = new StreamWriter( filePath ) ) { op.WriteLine( "open \"{0}\"", FtpHost ); op.WriteLine( FtpUsername ); op.WriteLine( FtpPassword ); op.WriteLine( "cd \"{0}\"", ( m_Type == "staff" ? FtpStaffDirectory : FtpStatsDirectory ) ); op.WriteLine( "mput \"{0}\"", Path.Combine( m_OutputDirectory, "*.html" ) ); op.WriteLine( "mput \"{0}\"", Path.Combine( m_OutputDirectory, "*.css" ) ); op.WriteLine( "binary" ); op.WriteLine( "mput \"{0}\"", Path.Combine( m_OutputDirectory, "*.png" ) ); op.WriteLine( "disconnect" ); op.Write( "quit" ); } ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "ftp"; psi.Arguments = String.Format( "-i -s:\"{0}\"", filePath ); psi.CreateNoWindow = true; psi.WindowStyle = ProcessWindowStyle.Hidden; //psi.UseShellExecute = true; try { Process p = Process.Start( psi ); p.WaitForExit(); } catch { } Console.WriteLine( "Reports: {0}: Upload complete", m_Title ); try{ File.Delete( filePath ); } catch{} } public void RenderFull() { string filePath = Path.Combine( m_OutputDirectory, "reports.html" ); using ( StreamWriter op = new StreamWriter( filePath ) ) { using ( HtmlTextWriter html = new HtmlTextWriter( op, "\t" ) ) RenderFull( html ); } string cssPath = Path.Combine( m_OutputDirectory, "styles.css" ); if ( File.Exists( cssPath ) ) return; using ( StreamWriter css = new StreamWriter( cssPath ) ) { css.WriteLine( "body { background-color: #FFFFFF; font-family: verdana, arial; font-size: 11px; }" ); css.WriteLine( "a { color: #28435E; }" ); css.WriteLine( "a:hover { color: #4878A9; }" ); css.WriteLine( "td.header { background-color: #9696AA; font-weight: bold; font-size: 12px; }" ); css.WriteLine( "td.lentry { background-color: #D7D7EB; width: 10%; }" ); css.WriteLine( "td.rentry { background-color: #FFFFFF; width: 90%; }" ); css.WriteLine( "td.entry { background-color: #FFFFFF; }" ); css.WriteLine( "td { font-size: 11px; }" ); css.Write ( ".tbl-border { background-color: #46465A; }" ); } } private const string ShardTitle = "Shard"; public void RenderFull( HtmlTextWriter html ) { html.RenderBeginTag( HtmlTag.Html ); html.RenderBeginTag( HtmlTag.Head ); html.RenderBeginTag( HtmlTag.Title ); html.Write( "{0} Statistics", ShardTitle ); html.RenderEndTag(); html.AddAttribute( "rel", "stylesheet" ); html.AddAttribute( HtmlAttr.Type, "text/css" ); html.AddAttribute( HtmlAttr.Href, "styles.css" ); html.RenderBeginTag( HtmlTag.Link ); html.RenderEndTag(); html.RenderEndTag(); html.RenderBeginTag( HtmlTag.Body ); for ( int i = 0; i < m_Objects.Count; ++i ) { RenderDirect( m_Objects[i], html ); html.Write( "

" ); } html.RenderBeginTag( HtmlTag.Center ); TimeZone tz = TimeZone.CurrentTimeZone; bool isDaylight = tz.IsDaylightSavingTime( m_TimeStamp ); TimeSpan utcOffset = tz.GetUtcOffset( m_TimeStamp ); html.Write( "Snapshot taken at {0:d} {0:t}. All times are {1}.", m_TimeStamp, tz.StandardName ); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); } public static string SafeFileName( string name ) { return name.ToLower().Replace( ' ', '_' ); } public void RenderSingle( PersistableObject obj ) { string filePath = Path.Combine( m_OutputDirectory, SafeFileName( FindNameFrom( obj ) ) + ".html" ); using ( StreamWriter op = new StreamWriter( filePath ) ) { using ( HtmlTextWriter html = new HtmlTextWriter( op, "\t" ) ) RenderSingle( obj, html ); } } private string FindNameFrom( PersistableObject obj ) { if ( obj is Report ) return (obj as Report).Name; else if ( obj is Chart ) return (obj as Chart).Name; return "Invalid"; } public void RenderSingle( PersistableObject obj, HtmlTextWriter html ) { html.RenderBeginTag( HtmlTag.Html ); html.RenderBeginTag( HtmlTag.Head ); html.RenderBeginTag( HtmlTag.Title ); html.Write( "{0} Statistics - {1}", ShardTitle, FindNameFrom( obj ) ); html.RenderEndTag(); html.AddAttribute( "rel", "stylesheet" ); html.AddAttribute( HtmlAttr.Type, "text/css" ); html.AddAttribute( HtmlAttr.Href, "styles.css" ); html.RenderBeginTag( HtmlTag.Link ); html.RenderEndTag(); html.RenderEndTag(); html.RenderBeginTag( HtmlTag.Body ); html.RenderBeginTag( HtmlTag.Center ); RenderDirect( obj, html ); html.Write( "
" ); TimeZone tz = TimeZone.CurrentTimeZone; bool isDaylight = tz.IsDaylightSavingTime( m_TimeStamp ); TimeSpan utcOffset = tz.GetUtcOffset( m_TimeStamp ); html.Write( "Snapshot taken at {0:d} {0:t}. All times are {1}.", m_TimeStamp, tz.StandardName ); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); } public void RenderDirect( PersistableObject obj, HtmlTextWriter html ) { if ( obj is Report ) RenderReport( obj as Report, html ); else if ( obj is BarGraph ) RenderBarGraph( obj as BarGraph, html ); else if ( obj is PieChart ) RenderPieChart( obj as PieChart, html ); } private void RenderPieChart( PieChart chart, HtmlTextWriter html ) { PieChartRenderer pieChart = new PieChartRenderer( Color.White ); pieChart.ShowPercents = chart.ShowPercents; string[] labels = new string[chart.Items.Count]; string[] values = new string[chart.Items.Count]; for ( int i = 0; i < chart.Items.Count; ++i ) { ChartItem item = chart.Items[i]; labels[i] = item.Name; values[i] = item.Value.ToString(); } pieChart.CollectDataPoints( labels, values ); Bitmap bmp = pieChart.Draw(); string fileName = chart.FileName + ".png"; bmp.Save( Path.Combine( m_OutputDirectory, fileName ), ImageFormat.Png ); html.Write( "" ); html.AddAttribute( HtmlAttr.Cellpadding, "0" ); html.AddAttribute( HtmlAttr.Cellspacing, "0" ); html.AddAttribute( HtmlAttr.Border, "0" ); html.RenderBeginTag( HtmlTag.Table ); html.RenderBeginTag( HtmlTag.Tr ); html.AddAttribute( HtmlAttr.Class, "tbl-border" ); html.RenderBeginTag( HtmlTag.Td ); html.AddAttribute( HtmlAttr.Width, "100%" ); html.AddAttribute( HtmlAttr.Cellpadding, "4" ); html.AddAttribute( HtmlAttr.Cellspacing, "1" ); html.RenderBeginTag( HtmlTag.Table ); html.RenderBeginTag( HtmlTag.Tr ); html.AddAttribute( HtmlAttr.Colspan, "10" ); html.AddAttribute( HtmlAttr.Width, "100%" ); html.AddAttribute( HtmlAttr.Align, "center" ); html.AddAttribute( HtmlAttr.Class, "header" ); html.RenderBeginTag( HtmlTag.Td ); html.Write( chart.Name ); html.RenderEndTag(); html.RenderEndTag(); html.RenderBeginTag( HtmlTag.Tr ); html.AddAttribute( HtmlAttr.Colspan, "10" ); html.AddAttribute( HtmlAttr.Width, "100%" ); html.AddAttribute( HtmlAttr.Align, "center" ); html.AddAttribute( HtmlAttr.Class, "entry" ); html.RenderBeginTag( HtmlTag.Td ); html.AddAttribute( HtmlAttr.Width, bmp.Width.ToString() ); html.AddAttribute( HtmlAttr.Height, bmp.Height.ToString() ); html.AddAttribute( HtmlAttr.Src, fileName ); html.RenderBeginTag( HtmlTag.Img ); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); bmp.Dispose(); } private void RenderBarGraph( BarGraph graph, HtmlTextWriter html ) { BarGraphRenderer barGraph = new BarGraphRenderer( Color.White ); barGraph.RenderMode = graph.RenderMode; barGraph._regions = graph.Regions; barGraph.SetTitles( graph.xTitle, null ); if ( graph.yTitle != null ) barGraph.VerticalLabel = graph.yTitle; barGraph.FontColor = Color.Black; barGraph.ShowData = ( graph.Interval == 1 ); barGraph.VerticalTickCount = graph.Ticks; string[] labels = new string[graph.Items.Count]; string[] values = new string[graph.Items.Count]; for ( int i = 0; i < graph.Items.Count; ++i ) { ChartItem item = graph.Items[i]; labels[i] = item.Name; values[i] = item.Value.ToString(); } barGraph._interval = graph.Interval; barGraph.CollectDataPoints( labels, values ); Bitmap bmp = barGraph.Draw(); string fileName = graph.FileName + ".png"; bmp.Save( Path.Combine( m_OutputDirectory, fileName ), ImageFormat.Png ); html.Write( "" ); html.AddAttribute( HtmlAttr.Cellpadding, "0" ); html.AddAttribute( HtmlAttr.Cellspacing, "0" ); html.AddAttribute( HtmlAttr.Border, "0" ); html.RenderBeginTag( HtmlTag.Table ); html.RenderBeginTag( HtmlTag.Tr ); html.AddAttribute( HtmlAttr.Class, "tbl-border" ); html.RenderBeginTag( HtmlTag.Td ); html.AddAttribute( HtmlAttr.Width, "100%" ); html.AddAttribute( HtmlAttr.Cellpadding, "4" ); html.AddAttribute( HtmlAttr.Cellspacing, "1" ); html.RenderBeginTag( HtmlTag.Table ); html.RenderBeginTag( HtmlTag.Tr ); html.AddAttribute( HtmlAttr.Colspan, "10" ); html.AddAttribute( HtmlAttr.Width, "100%" ); html.AddAttribute( HtmlAttr.Align, "center" ); html.AddAttribute( HtmlAttr.Class, "header" ); html.RenderBeginTag( HtmlTag.Td ); html.Write( graph.Name ); html.RenderEndTag(); html.RenderEndTag(); html.RenderBeginTag( HtmlTag.Tr ); html.AddAttribute( HtmlAttr.Colspan, "10" ); html.AddAttribute( HtmlAttr.Width, "100%" ); html.AddAttribute( HtmlAttr.Align, "center" ); html.AddAttribute( HtmlAttr.Class, "entry" ); html.RenderBeginTag( HtmlTag.Td ); html.AddAttribute( HtmlAttr.Width, bmp.Width.ToString() ); html.AddAttribute( HtmlAttr.Height, bmp.Height.ToString() ); html.AddAttribute( HtmlAttr.Src, fileName ); html.RenderBeginTag( HtmlTag.Img ); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); bmp.Dispose(); } private void RenderReport( Report report, HtmlTextWriter html ) { html.AddAttribute( HtmlAttr.Width, report.Width ); html.AddAttribute( HtmlAttr.Cellpadding, "0" ); html.AddAttribute( HtmlAttr.Cellspacing, "0" ); html.AddAttribute( HtmlAttr.Border, "0" ); html.RenderBeginTag( HtmlTag.Table ); html.RenderBeginTag( HtmlTag.Tr ); html.AddAttribute( HtmlAttr.Class, "tbl-border" ); html.RenderBeginTag( HtmlTag.Td ); html.AddAttribute( HtmlAttr.Width, "100%" ); html.AddAttribute( HtmlAttr.Cellpadding, "4" ); html.AddAttribute( HtmlAttr.Cellspacing, "1" ); html.RenderBeginTag( HtmlTag.Table ); html.RenderBeginTag( HtmlTag.Tr ); html.AddAttribute( HtmlAttr.Colspan, "10" ); html.AddAttribute( HtmlAttr.Width, "100%" ); html.AddAttribute( HtmlAttr.Align, "center" ); html.AddAttribute( HtmlAttr.Class, "header" ); html.RenderBeginTag( HtmlTag.Td ); html.Write( report.Name ); html.RenderEndTag(); html.RenderEndTag(); bool isNamed = false; for ( int i = 0; i < report.Columns.Count && !isNamed; ++i ) isNamed = ( report.Columns[i].Name != null ); if ( isNamed ) { html.RenderBeginTag( HtmlTag.Tr ); for ( int i = 0; i < report.Columns.Count; ++i ) { ReportColumn column = report.Columns[i]; html.AddAttribute( HtmlAttr.Class, "header" ); html.AddAttribute( HtmlAttr.Width, column.Width ); html.AddAttribute( HtmlAttr.Align, column.Align ); html.RenderBeginTag( HtmlTag.Td ); html.Write( column.Name ); html.RenderEndTag(); } html.RenderEndTag(); } for ( int i = 0; i < report.Items.Count; ++i ) { ReportItem item = report.Items[i]; html.RenderBeginTag( HtmlTag.Tr ); for ( int j = 0; j < item.Values.Count; ++j ) { if ( !isNamed && j == 0 ) html.AddAttribute( HtmlAttr.Width, report.Columns[j].Width ); html.AddAttribute( HtmlAttr.Align, report.Columns[j].Align ); html.AddAttribute( HtmlAttr.Class, "entry" ); html.RenderBeginTag( HtmlTag.Td ); if ( item.Values[j].Format == null ) html.Write( item.Values[j].Value ); else html.Write( int.Parse( item.Values[j].Value ).ToString( item.Values[j].Format ) ); html.RenderEndTag(); } html.RenderEndTag(); } html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); html.RenderEndTag(); } } }