/// <summary> /// Calculate and generate statistics for factions. /// </summary> /// <param name="bgWkr"></param> /// <param name="log"></param> public void GenerateFactionActivity(BackgroundWorker bgWkr, LogRecorderInterface log) { DateTime endDate = DateTime.Today; DateTime startDate = endDate.Subtract(new TimeSpan(30, 0, 0, 0)); // If statistics are disabled, do nothing. if (AppSettings.Default.setStatisticsDir.Length == 0) { return; } // Produce activity statistics if they don't exist. string filePath = String.Format("{0}\\activity_summary_{1:yyyyMMdd}.html", AppSettings.Default.setStatisticsDir, endDate); if (File.Exists(filePath)) { return; } try { // Keep a summary table of all factions. UIDataSet summaryFactions = new UIDataSet(); // Crunch the data. bgWkr.ReportProgress(80, "Creating activity statistics..."); UIDataSet results = CalcActivity(startDate, endDate, bgWkr, log); // General overall activity report. string title = String.Format("Activity - {0} days to {1}", (endDate - startDate).Days, endDate); GenerateActivityReport(results, "", title, summaryFactions, endDate, true); // Save statistics for factions. bgWkr.ReportProgress(90, "Generating activity reports..."); string[] factionsFilter = AppSettings.Default.setStatsFactions.Split(' '); foreach (string factionFilter in factionsFilter) { string faction = factionFilter.Trim(); if (faction.Length > 0) { title = String.Format("Activity {0} - {1}", faction, endDate); GenerateActivityReport(results, faction, title, summaryFactions, DateTime.MinValue, false); } } // Write the index.html DataRow[] rows = summaryFactions.StatPlayer.Select("", "OnLineTime DESC"); SaveAsHTML(filePath, String.Format("Activity Summary - {0} days to {1}", (endDate - startDate).Days, endDate), rows, new string[] { "Name", "On Line Time" }, new string[] { "Name", "OnLineTime" }, 0, rows.Length); File.Copy(filePath, AppSettings.Default.setStatisticsDir + "\\activity_summary.html", true); } catch (Exception ex) { log.AddLog(String.Format("Error '{0}' when generating HTML", ex.Message)); try { File.Delete(filePath); } catch { }; } }
public override global::System.Data.DataSet Clone() { UIDataSet cln = ((UIDataSet)(base.Clone())); cln.InitVars(); cln.SchemaSerializationMode = this.SchemaSerializationMode; return(cln); }
public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedDataSetSchema(global::System.Xml.Schema.XmlSchemaSet xs) { UIDataSet ds = new UIDataSet(); global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); global::System.Xml.Schema.XmlSchemaAny any = new global::System.Xml.Schema.XmlSchemaAny(); any.Namespace = ds.Namespace; sequence.Items.Add(any); type.Particle = sequence; global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); if (xs.Contains(dsSchema.TargetNamespace)) { global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); try { global::System.Xml.Schema.XmlSchema schema = null; dsSchema.Write(s1); for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext();) { schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); s2.SetLength(0); schema.Write(s2); if ((s1.Length == s2.Length)) { s1.Position = 0; s2.Position = 0; for (; ((s1.Position != s1.Length) && (s1.ReadByte() == s2.ReadByte()));) { ; } if ((s1.Position == s1.Length)) { return(type); } } } } finally { if ((s1 != null)) { s1.Close(); } if ((s2 != null)) { s2.Close(); } } } xs.Add(dsSchema); return(type); }
/// <summary> /// Generate player stats in a format similar to FLStat. /// </summary> /// <param name="bgWkr"></param> /// <param name="log"></param> public void GeneratePlayerStats(BackgroundWorker bgWkr, LogRecorderInterface log) { DateTime date = DateTime.Now; try { string filePath = String.Format("{0}\\players_{1:yyyyMMdd}.html", AppSettings.Default.setStatisticsDir, date); if (File.Exists(filePath)) { return; } using (DamDataSet ds = new DamDataSet()) { dataAccess.GetCharacterList(ds.CharacterList); bgWkr.ReportProgress(75, "Generating player reports..."); //DataRow[] rows = ds.CharacterList.Select("IsDeleted = 'false'"); using (UIDataSet uds = new UIDataSet()) { foreach (DamDataSet.CharacterListRow cr in ds.CharacterList) { if (!cr.IsDeleted) { uds.StatPlayer.AddStatPlayerRow(cr.CharName, new TimeSpan(0, 0, cr.OnLineSecs), cr.Money, cr.Rank, cr.LastOnLine, cr.OnLineSecs); } } string[] colTitles = new string[] { "Name", "Rank", "Money", "Last On Line", "On Line Time" }; string[] colNames = new string[] { "Name", "Rank", "Money", "LastOnLine", "OnLineTime" }; string title = String.Format("Players - {0}", date); SaveAsHTML(filePath, title, uds.StatPlayer.Select("", "Rank DESC"), colTitles, colNames, 0, 2500); File.Copy(filePath, AppSettings.Default.setStatisticsDir + "\\players.html", true); } } } catch (Exception ex) { log.AddLog(String.Format("Error '{0}' when calculating player statistics", ex.Message)); } }
/// <summary> /// Generate from the results dataset for the specified charNameFilter /// </summary> void GenerateActivityReport(UIDataSet results, string charNameFilter, string title, UIDataSet summaryFactions, DateTime date, bool showChangedOnlineTimeOnly) { string[] colTitles = new string[] { "Name", "Last On Line", "On Line Time" }; string[] colNames = new string[] { "Name", "LastOnLine", "OnLineTime" }; // Prepare the filepath to save the HTML. string escapedFactionName = Regex.Replace(charNameFilter, @"[?:\\/*""<>|]", ""); string filePath = String.Format("{0}\\activity_{1}.html", AppSettings.Default.setStatisticsDir, escapedFactionName); if (date > DateTime.MinValue) { filePath = String.Format("{0}\\activity_{1:yyyyMMdd}.html", AppSettings.Default.setStatisticsDir, date); } // Filter and sort the results table. string query = "(Name LIKE '" + FLUtility.EscapeLikeExpressionString(charNameFilter) + "%'" + " OR Name LIKE '%" + FLUtility.EscapeLikeExpressionString(charNameFilter) + "')"; if (showChangedOnlineTimeOnly) { query += " AND OnLineSecs > 0"; } DataRow[] rows = results.StatPlayer.Select(query, "OnLineTime DESC"); // Save it. SaveAsHTML(filePath, title, rows, colTitles, colNames, 0, rows.Length); // Update faction activity summary table to generate the index table later. string linkName = HtmlEncode(filePath.Substring(AppSettings.Default.setStatisticsDir.Length + 1)); linkName = String.Format("<a href=\"{0}\">{1}</a>", HtmlEncode(linkName), HtmlEncode(linkName)); TimeSpan totalOnLineTime = TimeSpan.Zero; foreach (UIDataSet.StatPlayerRow row in (UIDataSet.StatPlayerRow[])rows) { totalOnLineTime += row.OnLineTime; } summaryFactions.StatPlayer.AddStatPlayerRow(linkName, totalOnLineTime, 0, 0, DateTime.Now, (int)totalOnLineTime.TotalSeconds); }
public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(global::System.Xml.Schema.XmlSchemaSet xs) { global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); UIDataSet ds = new UIDataSet(); global::System.Xml.Schema.XmlSchemaAny any1 = new global::System.Xml.Schema.XmlSchemaAny(); any1.Namespace = "http://www.w3.org/2001/XMLSchema"; any1.MinOccurs = new decimal(0); any1.MaxOccurs = decimal.MaxValue; any1.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; sequence.Items.Add(any1); global::System.Xml.Schema.XmlSchemaAny any2 = new global::System.Xml.Schema.XmlSchemaAny(); any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; any2.MinOccurs = new decimal(1); any2.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; sequence.Items.Add(any2); global::System.Xml.Schema.XmlSchemaAttribute attribute1 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute1.Name = "namespace"; attribute1.FixedValue = ds.Namespace; type.Attributes.Add(attribute1); global::System.Xml.Schema.XmlSchemaAttribute attribute2 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute2.Name = "tableTypeName"; attribute2.FixedValue = "运行日志DataTable"; type.Attributes.Add(attribute2); type.Particle = sequence; global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); if (xs.Contains(dsSchema.TargetNamespace)) { global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); try { global::System.Xml.Schema.XmlSchema schema = null; dsSchema.Write(s1); for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext();) { schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); s2.SetLength(0); schema.Write(s2); if ((s1.Length == s2.Length)) { s1.Position = 0; s2.Position = 0; for (; ((s1.Position != s1.Length) && (s1.ReadByte() == s2.ReadByte()));) { ; } if ((s1.Position == s1.Length)) { return(type); } } } } finally { if ((s1 != null)) { s1.Close(); } if ((s2 != null)) { s2.Close(); } } } xs.Add(dsSchema); return(type); }
public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(global::System.Xml.Schema.XmlSchemaSet xs) { global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); UIDataSet ds = new UIDataSet(); global::System.Xml.Schema.XmlSchemaAny any1 = new global::System.Xml.Schema.XmlSchemaAny(); any1.Namespace = "http://www.w3.org/2001/XMLSchema"; any1.MinOccurs = new decimal(0); any1.MaxOccurs = decimal.MaxValue; any1.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; sequence.Items.Add(any1); global::System.Xml.Schema.XmlSchemaAny any2 = new global::System.Xml.Schema.XmlSchemaAny(); any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; any2.MinOccurs = new decimal(1); any2.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; sequence.Items.Add(any2); global::System.Xml.Schema.XmlSchemaAttribute attribute1 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute1.Name = "namespace"; attribute1.FixedValue = ds.Namespace; type.Attributes.Add(attribute1); global::System.Xml.Schema.XmlSchemaAttribute attribute2 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute2.Name = "tableTypeName"; attribute2.FixedValue = "ShipPimperBaseListDataTable"; type.Attributes.Add(attribute2); type.Particle = sequence; global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); if (xs.Contains(dsSchema.TargetNamespace)) { global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); try { global::System.Xml.Schema.XmlSchema schema = null; dsSchema.Write(s1); for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext(); ) { schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); s2.SetLength(0); schema.Write(s2); if ((s1.Length == s2.Length)) { s1.Position = 0; s2.Position = 0; for (; ((s1.Position != s1.Length) && (s1.ReadByte() == s2.ReadByte())); ) { ; } if ((s1.Position == s1.Length)) { return type; } } } } finally { if ((s1 != null)) { s1.Close(); } if ((s2 != null)) { s2.Close(); } } } xs.Add(dsSchema); return type; }
public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedDataSetSchema(global::System.Xml.Schema.XmlSchemaSet xs) { UIDataSet ds = new UIDataSet(); global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); global::System.Xml.Schema.XmlSchemaAny any = new global::System.Xml.Schema.XmlSchemaAny(); any.Namespace = ds.Namespace; sequence.Items.Add(any); type.Particle = sequence; global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); if (xs.Contains(dsSchema.TargetNamespace)) { global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); try { global::System.Xml.Schema.XmlSchema schema = null; dsSchema.Write(s1); for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext(); ) { schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); s2.SetLength(0); schema.Write(s2); if ((s1.Length == s2.Length)) { s1.Position = 0; s2.Position = 0; for (; ((s1.Position != s1.Length) && (s1.ReadByte() == s2.ReadByte())); ) { ; } if ((s1.Position == s1.Length)) { return type; } } } } finally { if ((s1 != null)) { s1.Close(); } if ((s2 != null)) { s2.Close(); } } } xs.Add(dsSchema); return type; }
/// <summary> /// Scan the historical character lists and build a list containing the time each players /// was online within the specified time period. /// </summary> /// <returns>Returns the path to an HTML file cot </returns> private UIDataSet CalcActivity(DateTime startDate, DateTime endDate, BackgroundWorker bgWkr, LogRecorderInterface log) { UIDataSet results = new UIDataSet(); try { // Keep two tables; one containing the records when they are first detected and // the other with the most recent data. DamDataSet oldestData = new DamDataSet(); DamDataSet newestData = new DamDataSet(); Dictionary <string, int> onLineTimes = new Dictionary <string, int>(); // Scan from oldest date to newest reading character lists from the database // and building the online time list. for (DateTime date = startDate.Subtract(new TimeSpan(90, 0, 0, 0)); date <= endDate; date = date.AddDays(1)) { if (bgWkr.CancellationPending) { return(null); } using (DamDataSet tds = new DamDataSet()) { if (dataAccess.GetCharacterHistory(date, tds.CharacterList)) { foreach (DamDataSet.CharacterListRow tempCharRecord in tds.CharacterList) { if (bgWkr.CancellationPending) { return(null); } // Record the oldest data. Don't update if data is already present. DamDataSet.CharacterListRow oldCharRecord = oldestData.CharacterList.FindByCharPath(tempCharRecord.CharPath); if (oldCharRecord == null) { oldestData.CharacterList.AddCharacterListRow(tempCharRecord.CharName, tempCharRecord.CharPath, tempCharRecord.Created, tempCharRecord.Updated, tempCharRecord.AccID, tempCharRecord.IsDeleted, tempCharRecord.Location, tempCharRecord.Rank, tempCharRecord.Money, tempCharRecord.Ship, tempCharRecord.AccDir, tempCharRecord.OnLineSecs, tempCharRecord.LastOnLine); } // Keep updating to find the newest record from before the startDate else if (tempCharRecord.LastOnLine < startDate) { oldCharRecord.Created = tempCharRecord.Created; oldCharRecord.Updated = tempCharRecord.Updated; oldCharRecord.IsDeleted = tempCharRecord.IsDeleted; oldCharRecord.Location = tempCharRecord.Location; oldCharRecord.Rank = tempCharRecord.Rank; oldCharRecord.Money = tempCharRecord.Money; oldCharRecord.Ship = tempCharRecord.Ship; oldCharRecord.OnLineSecs = tempCharRecord.OnLineSecs; oldCharRecord.LastOnLine = tempCharRecord.LastOnLine; } } } } } newestData = oldestData.Copy() as DamDataSet; for (DateTime date = startDate; date <= endDate; date = date.AddDays(1)) { if (bgWkr.CancellationPending) { return(null); } using (DamDataSet tds = new DamDataSet()) { if (dataAccess.GetCharacterHistory(date, tds.CharacterList)) { foreach (DamDataSet.CharacterListRow tempCharRecord in tds.CharacterList) { if (bgWkr.CancellationPending) { return(null); } // Record the newest data. Keep updating with the most recent records. // Calculate the online seconds here to deal with the situation where // a character has been deleted then re-created. DamDataSet.CharacterListRow charRecord = newestData.CharacterList.FindByCharPath(tempCharRecord.CharPath); if (charRecord == null) { charRecord = newestData.CharacterList.AddCharacterListRow(tempCharRecord.CharName, tempCharRecord.CharPath, tempCharRecord.Created, tempCharRecord.Updated, tempCharRecord.AccID, tempCharRecord.IsDeleted, tempCharRecord.Location, tempCharRecord.Rank, tempCharRecord.Money, tempCharRecord.Ship, tempCharRecord.AccDir, tempCharRecord.OnLineSecs, tempCharRecord.LastOnLine); } else { int onLineTime = tempCharRecord.OnLineSecs - charRecord.OnLineSecs; if (onLineTime < 0) { onLineTime = 0; } if (onLineTimes.ContainsKey(charRecord.CharPath)) { onLineTimes[charRecord.CharPath] += onLineTime; } else { onLineTimes[charRecord.CharPath] = onLineTime; } charRecord.Created = tempCharRecord.Created; charRecord.Updated = tempCharRecord.Updated; charRecord.IsDeleted = tempCharRecord.IsDeleted; charRecord.Location = tempCharRecord.Location; charRecord.Rank = tempCharRecord.Rank; charRecord.Money = tempCharRecord.Money; charRecord.Ship = tempCharRecord.Ship; charRecord.OnLineSecs = tempCharRecord.OnLineSecs; charRecord.LastOnLine = tempCharRecord.LastOnLine; } } } } } // Build the results data set. This data set will be used to generate individual activity reports. foreach (DamDataSet.CharacterListRow newestCharRecord in newestData.CharacterList) { if (bgWkr.CancellationPending) { return(null); } DamDataSet.CharacterListRow oldestCharRecord = oldestData.CharacterList.FindByCharPath(newestCharRecord.CharPath); if (oldestCharRecord != null) { int rankDelta = newestCharRecord.Rank - oldestCharRecord.Rank; int moneyDelta = newestCharRecord.Money - oldestCharRecord.Money; int onLineSecsDelta = 0; if (onLineTimes.ContainsKey(oldestCharRecord.CharPath)) { onLineSecsDelta = onLineTimes[oldestCharRecord.CharPath]; } results.StatPlayer.AddStatPlayerRow(newestCharRecord.CharName, new TimeSpan(0, 0, onLineSecsDelta), moneyDelta, rankDelta, newestCharRecord.LastOnLine, onLineSecsDelta); } } } catch (Exception ex) { log.AddLog(String.Format("Error '{0}' when calculating activity statistics", ex.Message)); return(null); } return(results); }