private static void PrintStatisticsTable(IList <double> data, IList <double> withoutOutliers)
        {
            var table = new ConsoleTable("title", "original", "no outliers");

            table.AddRow("Count", data.Count(), withoutOutliers.Count());
            table.AddRow("Maximum", Stats.Maximum(data).Round(), Stats.Maximum(withoutOutliers).Round());
            table.AddRow("Minimum", Stats.Minimum(data).Round(), Stats.Minimum(withoutOutliers).Round());
            table.AddRow("Mean", Stats.Mean(data).Round(), Stats.Mean(withoutOutliers).Round());
            table.AddRow("Median", Stats.Median(data).Round(), Stats.Median(withoutOutliers).Round());
            table.AddRow("Variance", Stats.Variance(data).Round(), Stats.Variance(withoutOutliers).Round());
            table.AddRow("StandardDeviation", Stats.StandardDeviation(data).Round(),
                         Stats.StandardDeviation(withoutOutliers).Round());
            table.AddRow("Percentile 90", Stats.Percentile(data, 90).Round(), Stats.Percentile(withoutOutliers, 90).Round());
            table.AddRow("Percentile 95", Stats.Percentile(data, 95).Round(), Stats.Percentile(withoutOutliers, 95).Round());
            table.AddRow("Percentile 99", Stats.Percentile(data, 99).Round(), Stats.Percentile(withoutOutliers, 99).Round());
            table.Write(Format.MarkDown);
        }
        private static void PrintSimulationSnapshots(List <SimulationSnapshot> snapshots, List <RequestRecording> requests)
        {
            EnrichSnapshotsWithRequests(snapshots, requests);

            var buckets        = Constants.DEFAULT_REPORT_BUCKET_SIZE;
            var snapshotsCount = snapshots.Count;
            var bucketSize     = (int)Math.Floor((double)snapshotsCount / buckets);
            var duration       = snapshots.Max(x => x.TimeStamp).Subtract(snapshots.Min(x => x.TimeStamp)).TotalSeconds;


            var table = new ConsoleTable("bucket", "requests", "avg ms", "95 percentile ms", "avg simulated speed (X)", "progress %", "duration s", "duration %");

            for (var i = 0; i < buckets; i++)
            {
                var bucket  = snapshots.Skip(bucketSize * i).Take(bucketSize).ToList();
                var timings = new List <double>();

                foreach (var snapshot in bucket)
                {
                    var elapsed = snapshot.Requests.Select(x => (double)x.Elapsed).ToArray();
                    if (elapsed.Any())
                    {
                        timings.AddRange(elapsed);
                    }
                }

                var bucketDuration = bucket.Max(x => x.TimeStamp).Subtract(bucket.Min(x => x.TimeStamp)).TotalSeconds.Round();

                table.AddRow(i + 1,
                             bucket.Sum(x => x.Requests.Count),
                             Stats.Mean(timings).Round(),
                             Stats.Percentile(timings, 95).Round(),
                             Stats.Mean(bucket.Select(x => x.SimulatedSpeedMultiplier)).Round(),
                             Stats.Mean(bucket.Select(x => x.Progress)).ToString("P"),
                             bucketDuration,
                             (bucketDuration / duration).Round().ToString("P"));
            }
            table.Write(Format.MarkDown);
        }