// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using CSVStats; using PerfReportTool; using System.Reflection; using System.Drawing; using System.Text; namespace PerfSummaries { class SummaryFactory { public static void Init() { summaryNameLookup = new Dictionary(); Assembly assembly = typeof(SummaryFactory).GetTypeInfo().Assembly; foreach (Type type in assembly.GetTypes()) { if (type.IsSubclassOf(typeof(Summary))) { Summary instance = (Summary)Activator.CreateInstance(type); summaryNameLookup.Add(instance.GetName(), type); } } } public static Summary Create(string summaryTypeName, XElement summaryXmlElement, XmlVariableMappings vars, string baseXmlDirectory) { if ( summaryNameLookup.TryGetValue(summaryTypeName, out System.Type summaryType ) ) { object[] constructArgs = new object[3] { summaryXmlElement, vars, baseXmlDirectory }; return (Summary)Activator.CreateInstance(summaryType, constructArgs); } throw new Exception("Summary type " + summaryType + " not found!"); } static Dictionary summaryNameLookup = null; }; abstract class Summary { public class CaptureRange { public string name; public string startEvent; public string endEvent; public bool includeFirstFrame; public bool includeLastFrame; public CaptureRange(string inName, string start, string end) { name = inName; startEvent = start; endEvent = end; includeFirstFrame = false; includeLastFrame = false; } } public class CaptureData { public int startIndex; public int endIndex; public List Frames; public CaptureData(int start, int end, List inFrames) { startIndex = start; endIndex = end; Frames = inFrames; } } public Summary() { stats = new List(); captures = new List(); StatThresholds = new Dictionary(); } public virtual HtmlSection WriteSummaryData(bool bWriteHtml, CsvStats csvStats, CsvStats csvStatsUnstripped, bool bWriteSummaryCsv, SummaryTableRowData rowData, string htmlFileName) { return null; } public virtual void PostInit(ReportTypeInfo reportTypeInfo, CsvStats csvStats) { // Resolve wildcards and remove duplicates stats = csvStats.GetStatNamesMatchingStringList(stats.ToArray()); } public abstract string GetName(); public void ReadStatsFromXML(XElement element, XmlVariableMappings vars) { if (element == null) { return; } bHideInDetailedReport = element.GetSafeAttribute(vars, "hideInDetailedReport", false); useUnstrippedCsvStats = element.GetSafeAttribute(vars, "useUnstrippedCsvStats", false); bStartCollapsed = element.GetSafeAttribute(vars, "collapsed", false); XElement statsElement = element.Element("stats"); if (statsElement != null) { stats = statsElement.GetValue(vars).Split(',').ToList(); } foreach (XElement child in element.Elements()) { if (child.Name == "capture") { string captureName = child.GetRequiredAttribute(vars, "name"); string captureStart = child.GetRequiredAttribute(vars, "startEvent"); string captureEnd = child.GetRequiredAttribute(vars, "endEvent"); bool incFirstFrame = child.GetSafeAttribute(vars, "includeFirstFrame", true); bool incLastFrame = child.GetSafeAttribute(vars, "includeLastFrame", true); CaptureRange newRange = new CaptureRange(captureName, captureStart, captureEnd); newRange.includeFirstFrame = incFirstFrame; newRange.includeLastFrame = incLastFrame; captures.Add(newRange); } else if (child.Name == "colourThresholds") { if (child.Attribute("stat") == null) { continue; } string statName = child.GetRequiredAttribute(vars, "stat"); string hitchThresholdsStr = child.GetValue(vars); if (hitchThresholdsStr == "") { continue; } string[] hitchThresholdsStrList = hitchThresholdsStr.Split(','); ColourThresholdList HitchThresholds = new ColourThresholdList(); for (int i = 0; i < hitchThresholdsStrList.Length; i++) { string hitchThresholdStr = hitchThresholdsStrList[i]; string hitchThresholdNumStr = hitchThresholdStr; Colour thresholdColour = null; int openBracketIndex = hitchThresholdStr.IndexOf('('); if (openBracketIndex != -1 ) { hitchThresholdNumStr = hitchThresholdStr.Substring(0, openBracketIndex); int closeBracketIndex = hitchThresholdStr.IndexOf(')'); if (closeBracketIndex > openBracketIndex) { string colourString = hitchThresholdStr.Substring(openBracketIndex+1, closeBracketIndex - openBracketIndex-1); thresholdColour = new Colour(colourString); } } double thresholdValue = Convert.ToDouble(hitchThresholdNumStr, System.Globalization.CultureInfo.InvariantCulture); HitchThresholds.Add(new ThresholdInfo(thresholdValue, thresholdColour)); } if (HitchThresholds.Count == 4) { StatThresholds.Add(statName, HitchThresholds); } } } } public CaptureData GetFramesForCapture(CaptureRange inCapture, List FrameTimes, List EventsCaptured) { List ReturnFrames = new List(); int startFrame = -1; int endFrame = FrameTimes.Count; for (int i = 0; i < EventsCaptured.Count; i++) { if (startFrame < 0 && EventsCaptured[i].Name.ToLower().Contains(inCapture.startEvent.ToLower())) { startFrame = EventsCaptured[i].Frame; if (!inCapture.includeFirstFrame) { startFrame++; } } else if (endFrame >= FrameTimes.Count && EventsCaptured[i].Name.ToLower().Contains(inCapture.endEvent.ToLower())) { endFrame = EventsCaptured[i].Frame; if (!inCapture.includeLastFrame) { endFrame--; } } } if (startFrame == -1 || endFrame == FrameTimes.Count || endFrame < startFrame) { return null; } ReturnFrames = FrameTimes.GetRange(startFrame, (endFrame - startFrame)); CaptureData CaptureToUse = new CaptureData(startFrame, endFrame, ReturnFrames); return CaptureToUse; } public string[] GetUniqueStatNames() { HashSet uniqueStats = new HashSet(); foreach (string stat in stats) { if (!uniqueStats.Contains(stat)) { uniqueStats.Add(stat); } } return uniqueStats.ToArray(); } protected ColourThresholdList ReadColourThresholdListXML(XElement colourThresholdEl, XmlVariableMappings vars) { return ColourThresholdList.ReadColourThresholdListXML(colourThresholdEl, vars); } protected double [] ReadColourThresholdsXML(XElement colourThresholdEl, XmlVariableMappings vars) { return ColourThresholdList.ReadColourThresholdsXML(colourThresholdEl, vars); } public string GetStatThresholdColour(string StatToUse, double value) { ColourThresholdList Thresholds = GetStatColourThresholdList(StatToUse); if (Thresholds != null) { return Thresholds.GetColourForValue(value); } return "'#ffffff'"; } public ColourThresholdList GetStatColourThresholdList(string StatToUse) { if (StatThresholds.ContainsKey(StatToUse)) { return StatThresholds[StatToUse]; } return null; } public List captures; public List stats; public Dictionary StatThresholds; public bool useUnstrippedCsvStats; public bool bStartCollapsed; public bool bHideInDetailedReport = false; }; class HtmlSection { public HtmlSection(string titleIn, bool bStartCollapsedIn, string elementIdIn = null, int headingLevel=2) { title = titleIn; bStartCollapsed = bStartCollapsedIn; elementId = elementIdIn; headingType = "h" + headingLevel.ToString(); } public void WriteLine(string text) { FlushPendingLine(); lines.Add(text); } public void Write(string text) { pendingLine.Append(text); } public void WriteToFile( System.IO.StreamWriter htmlFile ) { FlushPendingLine(); BeginHtmlSection(htmlFile); foreach (string line in lines) { htmlFile.WriteLine(line); } EndHtmlSection(htmlFile); } private void FlushPendingLine() { if (pendingLine.Length > 0) { lines.Add(pendingLine.ToString()); pendingLine.Clear(); } } protected void BeginHtmlSection(System.IO.StreamWriter htmlFile) { if (htmlFile != null) { string headingClass = "collapsibleHeading"; string divClass = "collapsibleSection"; if (!bStartCollapsed) { headingClass += " expanded"; divClass += " expanded"; } string extraHeadingAttributes = ""; if (elementId != null) { htmlFile.WriteLine(""); extraHeadingAttributes = "id='" + elementId + "'"; } htmlFile.WriteLine("<"+ headingType + " class='" + headingClass + "' "+ extraHeadingAttributes + ">" + title + ""); htmlFile.WriteLine("
"); htmlFile.WriteLine("
"); } } protected void EndHtmlSection(System.IO.StreamWriter htmlFile) { if (htmlFile != null) { htmlFile.WriteLine("
"); htmlFile.WriteLine("
"); htmlFile.WriteLine("
"); } } string title; StringBuilder pendingLine = new StringBuilder(); List lines = new List(); bool bStartCollapsed; string elementId; string headingType; }; }