Archived
Added document generation
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator.Abstract;
|
||||
|
||||
public abstract class DocumentGeneratorBase : FileSerializableBase, IDocumentGenerator
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public abstract IDocumentGenerator AppendHeading(int level, string text);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IDocumentGenerator Append(string? text = default)
|
||||
{
|
||||
StringBuilder.Append(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IDocumentGenerator AppendLine(string? text = default)
|
||||
{
|
||||
StringBuilder.AppendLine(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract IDocumentGenerator AppendParagraph(string? text = default);
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDocumentGenerator AppendTable(int columns, Action<ITableGenerator> table)
|
||||
{
|
||||
var builder = AppendTable(columns);
|
||||
table(builder);
|
||||
return AppendLine(builder.ToString());
|
||||
}
|
||||
|
||||
protected abstract ITableGenerator AppendTable(int columns);
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string FormatImage(string path, IBounds? bounds = default);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Text;
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator.Abstract;
|
||||
|
||||
public abstract class FileSerializableBase : StringSerializableBase, IFileSerializable
|
||||
{
|
||||
public abstract string FileExtension { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ToFile(string path, Encoding? encoding = default) =>
|
||||
File.WriteAllText($"{path}.{FileExtension}", ToString(), encoding ?? Encoding.UTF8);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ReportGenerator.Generator.Interface;
|
||||
using System.Text;
|
||||
|
||||
namespace ReportGenerator.Generator.Abstract;
|
||||
|
||||
public abstract class StringSerializableBase : IStringSerializable
|
||||
{
|
||||
protected StringBuilder StringBuilder { get; } = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() => StringBuilder.ToString();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator.Abstract;
|
||||
|
||||
public abstract class TableGeneratorBase : StringSerializableBase, ITableGenerator
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int Columns { get; }
|
||||
|
||||
protected TableGeneratorBase(int columns)
|
||||
{
|
||||
Columns = columns;
|
||||
}
|
||||
|
||||
#region Header
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ITableGenerator AppendHeader(string content) =>
|
||||
AppendHeader(Enumerable.Range(0, Columns).Select(_ => content));
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract ITableGenerator AppendHeader(IEnumerable<string> row);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ITableGenerator AppendHeader(IEnumerable<IEnumerable<string>> rows)
|
||||
{
|
||||
foreach (var row in rows)
|
||||
{
|
||||
AppendHeader(row);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Row
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ITableGenerator AppendRow(string content) =>
|
||||
AppendRow(Enumerable.Range(0, Columns).Select(_ => content));
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract ITableGenerator AppendRow(IEnumerable<string> row);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ITableGenerator AppendRows(IEnumerable<IEnumerable<string>> rows)
|
||||
{
|
||||
foreach (var row in rows)
|
||||
{
|
||||
AppendRow(row);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using ReportGenerator.Generator.Abstract;
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator.Generator;
|
||||
|
||||
public class HtmlDocumentGenerator : DocumentGeneratorBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string FileExtension => "html";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IDocumentGenerator AppendParagraph(string? text = default) =>
|
||||
AppendLine($"<p>{text}</p>");
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ITableGenerator AppendTable(int columns) =>
|
||||
new HtmlTableGenerator(columns);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IDocumentGenerator AppendHeading(int level, string text) =>
|
||||
AppendLine($"<h{level}>{text}</h{level}>");
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string FormatImage(string path, IBounds? bounds = default) =>
|
||||
HtmlTools.FormatImage(path, bounds);
|
||||
|
||||
#region Overrides of StringSerializableBase
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() =>
|
||||
HtmlTools.Wrap("html", GetHead() + HtmlTools.Wrap("body", base.ToString()));
|
||||
|
||||
#endregion
|
||||
|
||||
private static string GetHead() =>
|
||||
HtmlTools.Wrap(
|
||||
"head",
|
||||
$"<meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">{GetStyle()}"
|
||||
);
|
||||
|
||||
private static string GetStyle() =>
|
||||
HtmlTools.Wrap("style",
|
||||
"html,body{width:100%;height:100%;overflow:scroll;} td,th{border:1px solid #777;padding:.5rem;text-align:center}table{border-collapse:collapse}tbody tr:nth-child(odd){background:#eee}caption{font-size:.8rem}"
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using ReportGenerator.Generator.Abstract;
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator.Generator;
|
||||
|
||||
internal class HtmlTableGenerator : TableGeneratorBase
|
||||
{
|
||||
public (string start, string end) RowFormat { get; init; } = ("<tr>", "</tr>");
|
||||
public (string start, string end) HeaderFormat { get; init; } = ("<th>", "</th>");
|
||||
public (string start, string end) ColumnFormat { get; init; } = ("<td>", "</td>");
|
||||
|
||||
/// <inheritdoc />
|
||||
public HtmlTableGenerator(int columns) : base(columns) { }
|
||||
|
||||
#region Overrides of TableGeneratorBase
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ITableGenerator AppendHeader(IEnumerable<string> row) => AppendRow(row, RowFormat, HeaderFormat);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ITableGenerator AppendRow(IEnumerable<string> row) => AppendRow(row, RowFormat, ColumnFormat);
|
||||
|
||||
private ITableGenerator AppendRow(
|
||||
IEnumerable<string> row,
|
||||
(string, string) rowFormat,
|
||||
(string, string) columnFormat
|
||||
)
|
||||
{
|
||||
var (rowStart, rowEnd) = rowFormat;
|
||||
var (colStart, colEnd) = columnFormat;
|
||||
|
||||
StringBuilder
|
||||
.Append(rowStart)
|
||||
.Append(colStart)
|
||||
.AppendLine(string.Join(colEnd + colStart, row))
|
||||
.Append(colEnd)
|
||||
.Append(rowEnd);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() => "<table>" + base.ToString() + "</table>";
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using ReportGenerator.Generator.Abstract;
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator.Generator;
|
||||
|
||||
public class MarkdownDocumentGenerator : DocumentGeneratorBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string FileExtension => "md";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IDocumentGenerator AppendHeading(int level, string text) =>
|
||||
AppendParagraph(new string('#', level) + ' ' + text);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ITableGenerator AppendTable(int columns) =>
|
||||
new MarkdownTableGenerator(columns);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IDocumentGenerator AppendParagraph(string? text = default)
|
||||
{
|
||||
AppendLine(text);
|
||||
AppendLine();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string FormatImage(string path, IBounds? bounds = default) =>
|
||||
HtmlTools.FormatImage(path, bounds);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using ReportGenerator.Generator.Abstract;
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator.Generator;
|
||||
|
||||
internal class MarkdownTableGenerator : TableGeneratorBase
|
||||
{
|
||||
public string ColumnSeparator { get; init; } = " | ";
|
||||
|
||||
/// <inheritdoc />
|
||||
internal MarkdownTableGenerator(int columns) : base(columns) { }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ITableGenerator AppendHeader(IEnumerable<string> row) => AppendRow(row).AppendRow("---");
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ITableGenerator AppendRow(IEnumerable<string> row)
|
||||
{
|
||||
StringBuilder.AppendLine(ColumnSeparator + string.Join(" | ", row) + ColumnSeparator);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator;
|
||||
|
||||
internal static class HtmlTools
|
||||
{
|
||||
public static string Wrap(string tag, string content) => $"<{tag}>{content}</{tag}>";
|
||||
|
||||
public static string FormatImage(string path, IBounds? bounds = default)
|
||||
{
|
||||
var style = bounds is null
|
||||
? string.Empty
|
||||
: GetCssStyle(bounds);
|
||||
|
||||
path += path.EndsWith(".png") ? string.Empty : ".png";
|
||||
|
||||
return $"<img src=\"{path}\" style=\"{style}\" />";
|
||||
}
|
||||
|
||||
private static string GetCssStyle(IBounds bounds)
|
||||
{
|
||||
var style = string.Empty;
|
||||
|
||||
// Width
|
||||
if (bounds.Width.HasValue)
|
||||
{
|
||||
style += $"width:{bounds.Width}{bounds.Unit};";
|
||||
}
|
||||
|
||||
if (bounds.MinWidth.HasValue)
|
||||
{
|
||||
style += $"min-width:{bounds.MinWidth}{bounds.Unit};";
|
||||
}
|
||||
|
||||
if (bounds.MaxWidth.HasValue)
|
||||
{
|
||||
style += $"max-width:{bounds.MaxWidth}{bounds.Unit};";
|
||||
}
|
||||
|
||||
// Height
|
||||
if (bounds.Height.HasValue)
|
||||
{
|
||||
style += $"height:{bounds.Height}{bounds.Unit};";
|
||||
}
|
||||
|
||||
if (bounds.MinHeight.HasValue)
|
||||
{
|
||||
style += $"min-height:{bounds.MinHeight}{bounds.Unit};";
|
||||
}
|
||||
|
||||
if (bounds.MaxHeight.HasValue)
|
||||
{
|
||||
style += $"max-height:{bounds.MaxHeight}{bounds.Unit};";
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace ReportGenerator.Generator.Interface;
|
||||
|
||||
public interface IBounds
|
||||
{
|
||||
public string Unit { get; }
|
||||
public int? MinWidth { get; }
|
||||
public int? MinHeight { get; }
|
||||
public int? MaxWidth { get; }
|
||||
public int? MaxHeight { get; }
|
||||
public int? Width { get; }
|
||||
public int? Height { get; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace ReportGenerator.Generator.Interface;
|
||||
|
||||
public interface IDocumentGenerator : IFileSerializable
|
||||
{
|
||||
IDocumentGenerator Append(string? text = default);
|
||||
IDocumentGenerator AppendLine(string? text = default);
|
||||
IDocumentGenerator AppendParagraph(string? text = default);
|
||||
|
||||
IDocumentGenerator AppendHeading(int level, string text);
|
||||
|
||||
IDocumentGenerator AppendTable(int columns, Action<ITableGenerator> table);
|
||||
|
||||
string FormatImage(string path, IBounds? bounds = default);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text;
|
||||
|
||||
namespace ReportGenerator.Generator.Interface;
|
||||
|
||||
public interface IFileSerializable : IStringSerializable
|
||||
{
|
||||
public string FileExtension { get; }
|
||||
|
||||
void ToFile(string path, Encoding? encoding = default);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ReportGenerator.Generator.Interface;
|
||||
|
||||
public interface IStringSerializable
|
||||
{
|
||||
string ToString();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace ReportGenerator.Generator.Interface;
|
||||
|
||||
public interface ITableGenerator : IStringSerializable
|
||||
{
|
||||
int Columns { get; }
|
||||
|
||||
ITableGenerator AppendHeader(string content);
|
||||
ITableGenerator AppendHeader(IEnumerable<string> row);
|
||||
ITableGenerator AppendHeader(IEnumerable<IEnumerable<string>> rows);
|
||||
|
||||
ITableGenerator AppendRow(string content);
|
||||
ITableGenerator AppendRow(IEnumerable<string> row);
|
||||
ITableGenerator AppendRows(IEnumerable<IEnumerable<string>> rows);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using ReportGenerator.Generator.Interface;
|
||||
|
||||
namespace ReportGenerator.Generator.Model;
|
||||
|
||||
public struct Bounds : IBounds
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string Unit => "px";
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? MinWidth { get; set; } = null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? MinHeight { get; set; } = null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? MaxWidth { get; set; } = null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? MaxHeight { get; set; } = null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? Width { get; set; } = null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? Height { get; set; } = null;
|
||||
|
||||
public Bounds() { }
|
||||
|
||||
public Bounds(int? size)
|
||||
{
|
||||
Width = size;
|
||||
Height = size;
|
||||
}
|
||||
|
||||
public Bounds(int? min, int? max, int? size = null) : this(size)
|
||||
{
|
||||
MinWidth = min;
|
||||
MinHeight = min;
|
||||
|
||||
MaxWidth = max;
|
||||
MaxHeight = max;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using ReportGenerator.Models;
|
||||
using ReportGenerator.Generator.Generator;
|
||||
using ReportGenerator.Models;
|
||||
|
||||
namespace ReportGenerator;
|
||||
|
||||
@@ -16,13 +17,12 @@ internal static class Program
|
||||
|
||||
Console.WriteLine("Generating report");
|
||||
var scans = Scan(tagFileInfos, scanFileInfos);
|
||||
var report = ReportGenerator
|
||||
.FromData(scans)
|
||||
|
||||
new ReportGenerator(scans, new HtmlDocumentGenerator())
|
||||
.WithTitle("OCR Report")
|
||||
.WithBestOf("Best of")
|
||||
.WithFullStatistic("Statistic");
|
||||
|
||||
report.ToFile("Report.md");
|
||||
.WithFullStatistic("Statistic")
|
||||
.ToFile("report");
|
||||
|
||||
Console.WriteLine("Completed");
|
||||
}
|
||||
|
||||
@@ -1,74 +1,77 @@
|
||||
using Common.Extensions;
|
||||
using ReportGenerator.Generator.Abstract;
|
||||
using ReportGenerator.Generator.Interface;
|
||||
using ReportGenerator.Generator.Model;
|
||||
using ReportGenerator.Models;
|
||||
using System.Text;
|
||||
|
||||
namespace ReportGenerator;
|
||||
|
||||
public class ReportGenerator
|
||||
public class ReportGenerator : FileSerializableBase
|
||||
{
|
||||
private IDocumentGenerator Document { get; }
|
||||
private ICollection<ImageStats> Images { get; }
|
||||
|
||||
private readonly StringBuilder _sb = new();
|
||||
|
||||
private ReportGenerator(IEnumerable<ImageStats> stats) => Images = stats.ToArray();
|
||||
|
||||
public void ToFile(string path) =>
|
||||
File.WriteAllText(path, ToString(), Encoding.UTF8);
|
||||
public ReportGenerator(IEnumerable<ImageStats> stats, IDocumentGenerator document)
|
||||
{
|
||||
Images = stats.ToArray();
|
||||
Document = document;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() =>
|
||||
_sb.ToString();
|
||||
public override string ToString() => Document.ToString();
|
||||
|
||||
#region Fluent definition
|
||||
|
||||
public ReportGenerator WithTitle(string text)
|
||||
{
|
||||
_sb.AppendHeading(1, text);
|
||||
Document.AppendHeading(1, text);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReportGenerator WithFullStatistic(string title)
|
||||
{
|
||||
_sb.AppendHeading(2, title);
|
||||
Document.AppendHeading(2, title);
|
||||
|
||||
foreach (var stat in Images)
|
||||
{
|
||||
_sb.AppendHeading(3, stat.ImageName);
|
||||
_sb.AppendParagraph(HtmlImage(Path.Combine("img", stat.ImageName), 350, 350));
|
||||
Document
|
||||
.AppendHeading(3, stat.ImageName)
|
||||
.AppendParagraph(
|
||||
Document.FormatImage(Path.Combine("img", stat.ImageName), new Bounds(0, 350))
|
||||
)
|
||||
.AppendTable(
|
||||
stat.Reference.Count + 5,
|
||||
table =>
|
||||
{
|
||||
table.AppendHeader(stat
|
||||
.Reference
|
||||
.Prepend("Image")
|
||||
.Prepend("CER (avg)")
|
||||
.Prepend("WER")
|
||||
.Prepend("Elapsed")
|
||||
.Prepend("Processor")
|
||||
);
|
||||
|
||||
AppendRow(stat
|
||||
.Reference
|
||||
.Prepend("Image")
|
||||
.Prepend("CER (avg)")
|
||||
.Prepend("WER")
|
||||
.Prepend("Elapsed")
|
||||
.Prepend("Processor")
|
||||
);
|
||||
var processors = stat.Processors
|
||||
.OrderBy(s => s.Distance)
|
||||
.ThenBy(s => s.ProcessingTime);
|
||||
|
||||
AppendRowSeparator(stat.Reference.Count + 5);
|
||||
foreach (var processor in processors)
|
||||
{
|
||||
var imgPath = Path.Combine("results", $"{processor.Name}.00.{stat.ImageName}.png");
|
||||
|
||||
var processors = stat.Processors
|
||||
.OrderBy(s => s.Distance)
|
||||
.ThenBy(s => s.ProcessingTime);
|
||||
|
||||
foreach (var processor in processors)
|
||||
{
|
||||
var imgPath = Path.Combine("results", $"{processor.Name}.00.{stat.ImageName}.png");
|
||||
|
||||
AppendRow(processor.Words
|
||||
.Select(s => s.ToString() ?? string.Empty)
|
||||
.Prepend(HtmlImage(imgPath, 150, 150))
|
||||
.Prepend(processor.Words.Average(s => s.Distance).ToString("F2"))
|
||||
.Prepend($"{processor.Distance * 100:F1}%")
|
||||
.Prepend($"{processor.ProcessingTime * 1000:F1}ms")
|
||||
.Prepend(processor.Name)
|
||||
table.AppendRow(processor.Words
|
||||
.Select(s => s.ToString() ?? string.Empty)
|
||||
.Prepend(Document.FormatImage(imgPath, new Bounds(0, 150)))
|
||||
.Prepend(processor.Words.Average(s => s.Distance).ToString("F2"))
|
||||
.Prepend($"{processor.Distance * 100:F1}%")
|
||||
.Prepend($"{processor.ProcessingTime * 1000:F1}ms")
|
||||
.Prepend(processor.Name)
|
||||
);
|
||||
}
|
||||
})
|
||||
.AppendParagraph(
|
||||
$"*Comparison data generated based on {stat.Reference.Count} tagged words.*"
|
||||
);
|
||||
}
|
||||
|
||||
_sb.AppendLine();
|
||||
_sb.AppendParagraph(
|
||||
$"*Comparison data generated based on {stat.Reference.Count} tagged words.*"
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -77,7 +80,7 @@ public class ReportGenerator
|
||||
|
||||
public ReportGenerator WithBestOf(string title, int context = 5)
|
||||
{
|
||||
_sb.AppendHeading(2, title);
|
||||
Document.AppendHeading(2, title);
|
||||
|
||||
var lookup = Images
|
||||
.SelectMany(s => s.Processors)
|
||||
@@ -107,7 +110,7 @@ public class ReportGenerator
|
||||
|
||||
void AppendComparison(
|
||||
int level,
|
||||
string tableTitle,
|
||||
string title,
|
||||
IEnumerable<(string, double)> values,
|
||||
string valueUnit = ""
|
||||
)
|
||||
@@ -115,60 +118,32 @@ public class ReportGenerator
|
||||
var tValues = values.ToArray();
|
||||
var tContext = Math.Min(tValues.Length / 2, context);
|
||||
|
||||
_sb.AppendHeading(level, tableTitle);
|
||||
|
||||
AppendRow(new[] { "Processor", "Average" });
|
||||
AppendRowSeparator(2);
|
||||
AppendRows(tValues.Take(tContext).Select(v => new[]
|
||||
{
|
||||
v.Item1,
|
||||
v.Item2.ToString("F2") + valueUnit
|
||||
}));
|
||||
AppendRowSeparator(2, "...");
|
||||
AppendRows(tValues.TakeLast(tContext).Select(v => new[]
|
||||
{
|
||||
v.Item1,
|
||||
v.Item2.ToString("F2") + valueUnit
|
||||
}));
|
||||
Document
|
||||
.AppendHeading(level, title)
|
||||
.AppendTable(2, table => table
|
||||
.AppendHeader(new[] { "Processor", "Average" })
|
||||
.AppendRows(tValues
|
||||
.Take(tContext).Select(v => new[]
|
||||
{
|
||||
v.Item1,
|
||||
v.Item2.ToString("F2") + valueUnit
|
||||
}))
|
||||
.AppendRow("...")
|
||||
.AppendRows(tValues.TakeLast(tContext).Select(v => new[]
|
||||
{
|
||||
v.Item1,
|
||||
v.Item2.ToString("F2") + valueUnit
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
#region Overrides of FileSerializableBase
|
||||
|
||||
private void AppendRow(IEnumerable<string> row)
|
||||
{
|
||||
const string separator = " | ";
|
||||
_sb.AppendLine(separator + string.Join(" | ", row) + separator);
|
||||
}
|
||||
|
||||
private void AppendRows(IEnumerable<IEnumerable<string>> rows)
|
||||
{
|
||||
foreach (var row in rows)
|
||||
{
|
||||
AppendRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
private static string HtmlImage(string path, int maxWidth, int maxHeight)
|
||||
{
|
||||
if (!path.EndsWith(".png"))
|
||||
{
|
||||
path += ".png";
|
||||
}
|
||||
|
||||
return $"<img src=\"{path}\" style=\"max-width:{maxWidth}px;max-height:{maxHeight}px;\" />";
|
||||
}
|
||||
|
||||
private void AppendRowSeparator(int columns, string content = "---") =>
|
||||
AppendRow(Enumerable.Range(0, columns).Select(_ => content));
|
||||
/// <inheritdoc />
|
||||
public override string FileExtension => Document.FileExtension;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Factory Methods
|
||||
|
||||
public static ReportGenerator FromData(IEnumerable<ImageStats> stats) => new(stats);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
|
||||
Reference in New Issue
Block a user