public CsvMetadata Clone()
        {
            CsvMetadata rv = new CsvMetadata();

            rv.Values = Values;
            return(rv);
        }
 public CsvStats(CsvStats sourceCsvStats, string [] statNamesToFilter = null)
 {
     Stats  = new Dictionary <string, StatSamples>();
     Events = new List <CsvEvent>();
     if (statNamesToFilter != null)
     {
         foreach (string statName in statNamesToFilter)
         {
             List <StatSamples> stats = sourceCsvStats.GetStatsMatchingString(statName);
             foreach (StatSamples sourceStat in stats)
             {
                 string key = sourceStat.Name.ToLower();
                 if (!Stats.ContainsKey(key))
                 {
                     Stats.Add(key, new StatSamples(sourceStat));
                 }
             }
         }
     }
     else
     {
         foreach (StatSamples sourceStat in sourceCsvStats.Stats.Values)
         {
             AddStat(new StatSamples(sourceStat));
         }
     }
     foreach (CsvEvent ev in sourceCsvStats.Events)
     {
         Events.Add(new CsvEvent(ev));
     }
     if (sourceCsvStats.metaData != null)
     {
         metaData = new CsvMetadata(sourceCsvStats.metaData);
     }
 }
        public void CombineAndValidate(CsvMetadata comparisonMetadata)
        {
            List <string> valuesDontMatchKeys = new List <string>();

            foreach (KeyValuePair <string, string> pair in Values)
            {
                bool bMatch = false;
                if (comparisonMetadata.Values.ContainsKey(pair.Key))
                {
                    if (comparisonMetadata.Values[pair.Key] == pair.Value)
                    {
                        bMatch = true;
                    }
                }
                if (!bMatch)
                {
                    valuesDontMatchKeys.Add(pair.Key);
                    break;
                }
            }

            foreach (string key in valuesDontMatchKeys)
            {
                Values[key] = "[" + key + " doesn't match!]";
            }
        }
        public CsvMetadata(CsvMetadata source)
        {
            Values = new Dictionary <string, string>();
            List <KeyValuePair <string, string> > pairList = source.Values.ToList();

            foreach (KeyValuePair <string, string> pair in pairList)
            {
                Values.Add(pair.Key, pair.Value);
            }
        }
        public static bool Matches(CsvMetadata a, CsvMetadata b)
        {
            if (a == null && b == null)
            {
                return(true);
            }
            if (a == null)
            {
                return(false);
            }
            if (b == null)
            {
                return(false);
            }
            if (a.Values.Count != b.Values.Count)
            {
                return(false);
            }

            foreach (KeyValuePair <string, string> pair in a.Values)
            {
                bool bMatch = false;
                // if (pair.Key != "deviceprofile")
                {
                    if (b.Values.ContainsKey(pair.Key))
                    {
                        if (b.Values[pair.Key] == pair.Value)
                        {
                            bMatch = true;
                        }
                    }
                    if (!bMatch)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
 public static bool DoesMetadataMatchFilter(CsvMetadata metadata, string metadataFilterString)
 {
     string[] keyValuePairStrs = metadataFilterString.Split(',');
     foreach (string keyValuePairStr in keyValuePairStrs)
     {
         string[] keyValue = keyValuePairStr.Split('=');
         if (keyValue.Length != 2)
         {
             return(false);
         }
         string key = keyValue[0].ToLower();
         if (!metadata.Values.ContainsKey(key))
         {
             return(false);
         }
         if (metadata.Values[key].ToLower() != keyValue[1].ToLower())
         {
             return(false);
         }
     }
     return(true);
 }
        public static CsvStats ReadCSVFromLines(string[] linesArray, string[] statNames, int numRowsToSkip = 0, bool skipReadingData = false)
        {
            List <string> lines = linesArray.ToList();

            // Check if we have any metadata
            bool bHasMetaData = LineIsMetadata(lines.Last());

            CsvMetadata metaData = null;

            // Add the metadata to the stats collection
            if (bHasMetaData)
            {
                string[] lastLine = lines.Last().Split(',');
                metaData = new CsvMetadata(lastLine);

                // New CSVs from the csv profiler have a header row at the end of the file,
                // since the profiler writes out the file incrementally.
                if ("1" == metaData.GetValue("hasheaderrowatend", null))
                {
                    // Swap the header row for the one at the end of the file,
                    // then remove the end one.
                    lines[0] = lines[lines.Count - 2];
                    lines.RemoveAt(lines.Count - 2);
                }
            }

            if (numRowsToSkip > 0)
            {
                lines.RemoveRange(0, numRowsToSkip);
            }
            string[] headings = lines[0].Split(',');

            if (lines.Count > 2 && lines[lines.Count - 1] == "\"")
            {
                lines[lines.Count - 2] += lines[lines.Count - 1];
                lines.RemoveAt(lines.Count - 1);
            }

            if (skipReadingData)
            {
                int dataLineCount = bHasMetaData ? lines.Count - 2 : lines.Count - 1;
                lines.RemoveRange(1, dataLineCount);
            }

            // Get the list of lower case stat names, expanding wildcards
            string[] statNamesLowercase = null;
            if (statNames != null)
            {
                statNamesLowercase = statNames.Select(s => s.ToLowerInvariant()).ToArray();
                {
                    // Expand the list of stat names based on the wildcards and the headers. We do this here to make sorting simpler
                    HashSet <string> newStatNamesLowercase = new HashSet <string>();
                    foreach (string statname in statNamesLowercase)
                    {
                        if (statname.EndsWith("*"))
                        {
                            int    index  = statname.LastIndexOf('*');
                            string prefix = statname.Substring(0, index);
                            // Expand all the stat names
                            foreach (string headingStat in headings)
                            {
                                if (headingStat.ToLower().StartsWith(prefix))
                                {
                                    newStatNamesLowercase.Add(headingStat.ToLower());
                                }
                            }
                        }
                        else
                        {
                            newStatNamesLowercase.Add(statname);
                        }
                    }

                    statNamesLowercase = newStatNamesLowercase.ToArray();
                }
            }

            // First line is headings, last line contains build info
            int numSamples = lines.Count - (bHasMetaData ? 2 : 1);

            // Create the stats
            int eventHeadingIndex = -1;

            StatSamples[] stats = new StatSamples[headings.Length];
            for (int i = 0; i < headings.Length; i++)
            {
                string heading = headings[i].Trim();
                if (heading == "")
                {
                    continue;
                }
                // find the events column (if there is one)
                else if (heading.ToLower() == "events")
                {
                    eventHeadingIndex = i;
                }
                else if (statNamesLowercase == null || statNamesLowercase.Contains(heading.ToLower()))
                {
                    stats[i] = new StatSamples(heading, numSamples);
                }
            }


            List <CsvEvent> FilteredEvents = new List <CsvEvent>();

            if (!skipReadingData)
            {
                string[] eventStrings = new string[numSamples];

//                for (int i = 1; i < numSamples + 1; i++)
                Parallel.For(1, numSamples + 1,
                             i =>
                {
                    int sampleIndex = i - 1;
                    int statIndex   = 0;
                    string line     = lines[i] + "\n";
                    for (int j = 0; j < line.Length; j++)
                    {
                        // Note: we check statIndex<stats.length here in case of truncated CSVs
                        if (statIndex < stats.Length && stats[statIndex] != null)
                        {
                            // Read the stat
                            float value = 0.0f;

                            // Skip whitespace
                            while (line[j] == ' ')
                            {
                                j++;
                            }

                            bool negative = false;
                            if (line[j] == '-')
                            {
                                negative = true;
                                j++;
                            }

                            // Read the nonfractional part of the number
                            int num = 0;
                            while (line[j] >= '0' && line[j] <= '9')
                            {
                                num *= 10;
                                num += line[j] - '0';
                                j++;
                            }
                            value = (float)num;

                            if (line[j] == '.')
                            {
                                // read fractional part
                                num = 0;
                                j++;
                                float multiplier = 0.1f;
                                while (line[j] >= '0' && line[j] <= '9')
                                {
                                    value += (float)(line[j] - '0') * multiplier;
                                    j++;
                                    multiplier *= 0.1f;
                                }
                            }

                            if (negative)
                            {
                                value = -value;
                            }

                            stats[statIndex].samples[sampleIndex] = value;

                            // Skip everything else until the next newline or comma
                            while (line[j] != ',' && line[j] != '\n')
                            {
                                j++;
                            }
                        }
                        else
                        {
                            // Skip parsing
                            int startJ = j;
                            while (line[j] != ',' && line[j] != '\n')
                            {
                                j++;
                            }
                            if (statIndex == eventHeadingIndex)
                            {
                                eventStrings[sampleIndex] = line.Substring(startJ, j - startJ);
                            }
                        }
                        statIndex++;
                    }
                }
                             ); // Needed by parallel for

                // Read events
                for (int i = 0; i < eventStrings.Length; i++)
                {
                    string eventString = eventStrings[i];
                    if (!string.IsNullOrEmpty(eventString))
                    {
                        string[] Events = eventString.Split(';');
                        foreach (string EventString in Events)
                        {
                            if (EventString.Length > 0)
                            {
                                CsvEvent ev = new CsvEvent();
                                ev.Frame = i;
                                ev.Name  = EventString;
                                FilteredEvents.Add(ev);
                            }
                        }
                    }
                }
            }

            // Make sure the stat ordering matches the order they're passed in
            CsvStats csvStats = new CsvStats();

            if (statNamesLowercase != null)
            {
                CsvStats unorderedCsvStats = new CsvStats();
                foreach (StatSamples statSamples in stats)
                {
                    if (statSamples != null)
                    {
                        // Combine stats if we find a duplicate
                        if (unorderedCsvStats.Stats.ContainsKey(statSamples.Name.ToLower()))
                        {
                            StatSamples existingStat = unorderedCsvStats.GetStat(statSamples.Name);
                            for (int i = 0; i < statSamples.samples.Count; i++)
                            {
                                existingStat.samples[i] += statSamples.samples[i];
                            }
                        }
                        else
                        {
                            unorderedCsvStats.AddStat(statSamples);
                        }
                    }
                }

                foreach (string statName in statNamesLowercase)
                {
                    StatSamples stat = unorderedCsvStats.GetStat(statName);
                    if (stat != null)
                    {
                        csvStats.AddStat(stat);
                    }
                }
            }
            else
            {
                int c = 0;
                foreach (StatSamples statSamples in stats)
                {
                    c++;
                    if (statSamples != null)
                    {
                        if (csvStats.Stats.ContainsKey(statSamples.Name.ToLower()))
                        {
                            // Combine stats if we find a duplicate
                            StatSamples existingStat = csvStats.GetStat(statSamples.Name);
                            for (int i = 0; i < statSamples.samples.Count; i++)
                            {
                                existingStat.samples[i] += statSamples.samples[i];
                            }
                        }
                        else
                        {
                            csvStats.AddStat(statSamples);
                        }
                    }
                }
            }

            // Compute averages
            foreach (StatSamples stat in csvStats.Stats.Values.ToArray())
            {
                stat.ComputeAverageAndTotal();
            }

            csvStats.metaData = metaData;

            csvStats.Events = FilteredEvents;
            return(csvStats);
        }