Archived
Added report generation
This commit is contained in:
@@ -18,17 +18,6 @@ public static class Calculator
|
|||||||
var refArr = reference.Cast<object>().ToArray();
|
var refArr = reference.Cast<object>().ToArray();
|
||||||
var hypArr = hypothesis?.Cast<object>().ToArray() ?? Array.Empty<object>();
|
var hypArr = hypothesis?.Cast<object>().ToArray() ?? Array.Empty<object>();
|
||||||
|
|
||||||
if (!hypArr.Any())
|
|
||||||
{
|
|
||||||
return refArr.Length;
|
|
||||||
// return double.PositiveInfinity; // Adjust penalty for empty scans
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Equals(refArr, hypArr))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var distance = new int[refArr.Length + 1, hypArr.Length + 1];
|
var distance = new int[refArr.Length + 1, hypArr.Length + 1];
|
||||||
|
|
||||||
// Fill matrix
|
// Fill matrix
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public readonly struct DistanceComparer<T> : IDistanceComparer<T>
|
|||||||
{
|
{
|
||||||
Reference = reference;
|
Reference = reference;
|
||||||
Hypothesis = hypothesis;
|
Hypothesis = hypothesis;
|
||||||
|
|
||||||
Distance = Calculator.GetDistance(Reference, Hypothesis);
|
Distance = Calculator.GetDistance(Reference, Hypothesis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Common.Distance;
|
|||||||
public interface IDistanceComparer
|
public interface IDistanceComparer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The calculated distance between
|
/// The calculated absolute distance between
|
||||||
/// <see cref="IDistanceComparer{T}.Reference"/> and
|
/// <see cref="IDistanceComparer{T}.Reference"/> and
|
||||||
/// <see cref="IDistanceComparer{T}.Hypothesis"/>
|
/// <see cref="IDistanceComparer{T}.Hypothesis"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,38 +1,56 @@
|
|||||||
using ReportGenerator.Generator.Interface;
|
using ReportGenerator.Generator.Interface;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace ReportGenerator.Generator.Abstract;
|
namespace ReportGenerator.Generator.Abstract;
|
||||||
|
|
||||||
public abstract class DocumentGeneratorBase : FileSerializableBase, IDocumentGenerator
|
public abstract class DocumentGeneratorBase : StreamWriterBase, IDocumentGenerator
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract IDocumentGenerator AppendHeading(int level, string text);
|
protected DocumentGeneratorBase() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected DocumentGeneratorBase(Stream stream) : base(stream) { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected DocumentGeneratorBase(string filePath) : base(File.Open(filePath, FileMode.Create,
|
||||||
|
FileAccess.Write))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected DocumentGeneratorBase(Stream stream, Encoding encoding) : base(stream, encoding) { }
|
||||||
|
|
||||||
|
#region Writing
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual IDocumentGenerator Append(string? text = default)
|
public virtual IDocumentGenerator Append(string? text = default)
|
||||||
{
|
{
|
||||||
StringBuilder.Append(text);
|
Write(text);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual IDocumentGenerator AppendLine(string? text = default)
|
public virtual IDocumentGenerator AppendLine(string? text = default)
|
||||||
{
|
{
|
||||||
StringBuilder.AppendLine(text);
|
WriteLine(text);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract IDocumentGenerator AppendHeading(int level, string text);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract IDocumentGenerator AppendParagraph(string? text = default);
|
public abstract IDocumentGenerator AppendParagraph(string? text = default);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IDocumentGenerator AppendTable(int columns, Action<ITableGenerator> table)
|
public IDocumentGenerator AppendTable(int columns, Action<ITableGenerator> table)
|
||||||
{
|
{
|
||||||
var builder = AppendTable(columns);
|
Write(() => MakeTable(columns, new MemoryStream()), table);
|
||||||
table(builder);
|
return this;
|
||||||
return AppendLine(builder.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ITableGenerator AppendTable(int columns);
|
protected abstract ITableGenerator MakeTable(int columns, Stream stream);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract string FormatImage(string path, IBounds? bounds = default);
|
public abstract string FormatImage(string path, IBounds? bounds = default);
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
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,198 @@
|
|||||||
|
using ReportGenerator.Generator.Interface;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ReportGenerator.Generator.Abstract;
|
||||||
|
|
||||||
|
public abstract class StreamWriterBase : IStreamWriter
|
||||||
|
{
|
||||||
|
private bool _isOpen;
|
||||||
|
private bool _isClosed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Underlying <see cref="Stream"/>
|
||||||
|
/// </summary>
|
||||||
|
private Stream Stream { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal <see cref="StreamWriter"/> for generating the output <see cref="string"/>
|
||||||
|
/// </summary>
|
||||||
|
protected TextWriter Writer { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor; Configures the
|
||||||
|
/// <see cref="StreamWriterBase"/> to write to the memory
|
||||||
|
/// </summary>
|
||||||
|
protected StreamWriterBase() : this(new MemoryStream()) { }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="StreamWriterBase(System.IO.Stream, Encoding)"/>
|
||||||
|
protected StreamWriterBase(Stream stream) : this(stream, Encoding.UTF8) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor; Configures the <see cref="StreamWriterBase"/>
|
||||||
|
/// to write to the specified <paramref name="stream"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The <see cref="Stream"/> to write to</param>
|
||||||
|
/// <param name="encoding">Text <see cref="Encoding"/> of the written data</param>
|
||||||
|
protected StreamWriterBase(Stream stream, Encoding encoding)
|
||||||
|
{
|
||||||
|
Stream = stream;
|
||||||
|
Writer = new StreamWriter(stream, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Control
|
||||||
|
|
||||||
|
public void Open()
|
||||||
|
{
|
||||||
|
if (_isOpen)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{GetType()} has already been opened");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isClosed)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Cannot call open on a closed {GetType()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
_isOpen = true;
|
||||||
|
|
||||||
|
OnOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (_isClosed)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{GetType()} has already been closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_isOpen)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{GetType()} has never been opened");
|
||||||
|
}
|
||||||
|
|
||||||
|
_isClosed = true;
|
||||||
|
|
||||||
|
OnClose();
|
||||||
|
Writer.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called once the internal writer has been initialized
|
||||||
|
/// and the <see cref="Stream"/> is ready for writing
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnOpen() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called once the document is about to be closed
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnClose() { }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Reading
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public StreamReader Read()
|
||||||
|
{
|
||||||
|
Writer.Flush();
|
||||||
|
Stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
return new StreamReader(Stream, Writer.Encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Writing
|
||||||
|
|
||||||
|
public IStreamWriter Write(IStreamWriter writer)
|
||||||
|
{
|
||||||
|
using var reader = writer.Read();
|
||||||
|
return Write(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IStreamWriter Write(StreamReader reader)
|
||||||
|
{
|
||||||
|
int bytesRead;
|
||||||
|
char[] buffer = new char[4096];
|
||||||
|
|
||||||
|
while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0)
|
||||||
|
{
|
||||||
|
Writer.Write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IStreamWriter Write(string? text = default)
|
||||||
|
{
|
||||||
|
Writer.Write(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IStreamWriter WriteLine(string? text = default)
|
||||||
|
{
|
||||||
|
Writer.WriteLine(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates and configures the <typeparamref name="T"/> using the given functions
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the <see cref="IStreamWriter"/></typeparam>
|
||||||
|
/// <param name="makeFunc">Function used to generate the <typeparamref name="T"/></param>
|
||||||
|
/// <param name="configFunc">Function used to configure the <typeparamref name="T"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IStreamWriter Write<T>(Func<T> makeFunc, Action<T> configFunc)
|
||||||
|
where T : IStreamWriter
|
||||||
|
{
|
||||||
|
using var writer = makeFunc();
|
||||||
|
|
||||||
|
writer.Open();
|
||||||
|
configFunc(writer);
|
||||||
|
writer.Close();
|
||||||
|
|
||||||
|
Write(writer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Close document
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Dispose stream
|
||||||
|
Stream.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
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();
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,25 @@
|
|||||||
using ReportGenerator.Generator.Interface;
|
using ReportGenerator.Generator.Interface;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace ReportGenerator.Generator.Abstract;
|
namespace ReportGenerator.Generator.Abstract;
|
||||||
|
|
||||||
public abstract class TableGeneratorBase : StringSerializableBase, ITableGenerator
|
public abstract class TableGeneratorBase : StreamWriterBase, ITableGenerator
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int Columns { get; }
|
public int Columns { get; }
|
||||||
|
|
||||||
protected TableGeneratorBase(int columns)
|
/// <inheritdoc />
|
||||||
{
|
protected TableGeneratorBase(int columns) =>
|
||||||
Columns = columns;
|
Columns = columns;
|
||||||
}
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected TableGeneratorBase(int columns, Stream stream)
|
||||||
|
: base(stream) => Columns = columns;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected TableGeneratorBase(int columns, Stream stream, Encoding encoding)
|
||||||
|
: base(stream, encoding) => Columns = columns;
|
||||||
|
|
||||||
|
|
||||||
#region Header
|
#region Header
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +1,146 @@
|
|||||||
using ReportGenerator.Generator.Abstract;
|
using ReportGenerator.Generator.Abstract;
|
||||||
using ReportGenerator.Generator.Interface;
|
using ReportGenerator.Generator.Interface;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace ReportGenerator.Generator.Generator;
|
namespace ReportGenerator.Generator.Generator;
|
||||||
|
|
||||||
public class HtmlDocumentGenerator : DocumentGeneratorBase
|
public class HtmlDocumentGenerator : DocumentGeneratorBase
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
private int _sectionLevel = 0;
|
||||||
public override string FileExtension => "html";
|
|
||||||
|
public string Title { get; init; } = string.Empty;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override IDocumentGenerator AppendParagraph(string? text = default) =>
|
public HtmlDocumentGenerator() { }
|
||||||
AppendLine($"<p>{text}</p>");
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override ITableGenerator AppendTable(int columns) =>
|
public HtmlDocumentGenerator(string filePath) : base(filePath)
|
||||||
new HtmlTableGenerator(columns);
|
{
|
||||||
|
Title = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override IDocumentGenerator AppendHeading(int level, string text) =>
|
public HtmlDocumentGenerator(Stream stream) : base(stream) { }
|
||||||
AppendLine($"<h{level}>{text}</h{level}>");
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string FormatImage(string path, IBounds? bounds = default) =>
|
public HtmlDocumentGenerator(Stream stream, Encoding encoding) : base(stream, encoding) { }
|
||||||
HtmlTools.FormatImage(path, bounds);
|
|
||||||
|
|
||||||
#region Overrides of StringSerializableBase
|
#region State
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string ToString() =>
|
protected override void OnOpen()
|
||||||
HtmlTools.Wrap("html", GetHead() + HtmlTools.Wrap("body", base.ToString()));
|
{
|
||||||
|
base.OnOpen();
|
||||||
|
|
||||||
|
// Init html document
|
||||||
|
Write("<!DOCTYPE html>");
|
||||||
|
Write("<html>");
|
||||||
|
|
||||||
|
// Header
|
||||||
|
Write("<head>");
|
||||||
|
Write(HtmlTools.Wrap("title", Title));
|
||||||
|
Write("<meta charset=\"utf-8\">");
|
||||||
|
Write("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
|
||||||
|
Write("<style>");
|
||||||
|
|
||||||
|
using (var stream = Resources.Get("Style.css"))
|
||||||
|
{
|
||||||
|
using var streamReader = new StreamReader(stream);
|
||||||
|
Write(streamReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Write("</style>");
|
||||||
|
Write("</head>");
|
||||||
|
|
||||||
|
// Init body
|
||||||
|
Write("<body>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
base.OnClose();
|
||||||
|
|
||||||
|
// End document
|
||||||
|
Write("</body>");
|
||||||
|
Write("</html>");
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private static string GetHead() =>
|
#region Writing
|
||||||
HtmlTools.Wrap(
|
|
||||||
"head",
|
|
||||||
$"<meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">{GetStyle()}"
|
|
||||||
);
|
|
||||||
|
|
||||||
private static string GetStyle() =>
|
/// <inheritdoc cref="AppendParagraph(string)" />
|
||||||
HtmlTools.Wrap("style",
|
public IDocumentGenerator AppendParagraph(string? text, string? @class) =>
|
||||||
"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}"
|
Append(HtmlTools.Wrap("p", text, @class));
|
||||||
);
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IDocumentGenerator AppendParagraph(string? text = default) =>
|
||||||
|
AppendParagraph(text, default);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IDocumentGenerator AppendHeading(int level, string text)
|
||||||
|
{
|
||||||
|
if (_sectionLevel > 0)
|
||||||
|
{
|
||||||
|
// todo ??
|
||||||
|
}
|
||||||
|
|
||||||
|
var delta = level - _sectionLevel;
|
||||||
|
switch (delta)
|
||||||
|
{
|
||||||
|
case > 0:
|
||||||
|
for (int i = 0; i < delta; i++)
|
||||||
|
{
|
||||||
|
Append("<div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case < 0:
|
||||||
|
for (int i = delta; i < 0; i++)
|
||||||
|
{
|
||||||
|
Append("</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Append("</div>");
|
||||||
|
Append("<div>");
|
||||||
|
|
||||||
|
_sectionLevel = level;
|
||||||
|
|
||||||
|
return Append($"<h{level}>{text}</h{level}>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override ITableGenerator MakeTable(int columns, Stream stream) =>
|
||||||
|
new CollapsibleHtmlTableGenerator(columns, stream);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string FormatImage(string path, IBounds? bounds = default) =>
|
||||||
|
FormatImage(path, default, bounds);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="FormatImage(string,IBounds)" />
|
||||||
|
public string FormatImage(string path, string? @class, IBounds? bounds = default) =>
|
||||||
|
HtmlTools.FormatImage(path, @class, bounds);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Resource Management
|
||||||
|
|
||||||
|
private static class Resources
|
||||||
|
{
|
||||||
|
private static readonly Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
|
private static readonly string basePath =
|
||||||
|
typeof(HtmlDocumentGenerator).Namespace + ".Resources.";
|
||||||
|
|
||||||
|
public static Stream Get(string fileName) =>
|
||||||
|
assembly.GetManifestResourceStream(basePath + fileName) ??
|
||||||
|
throw new FileNotFoundException("Could not get resource", fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,92 @@
|
|||||||
using ReportGenerator.Generator.Abstract;
|
using ReportGenerator.Generator.Abstract;
|
||||||
using ReportGenerator.Generator.Interface;
|
using ReportGenerator.Generator.Interface;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace ReportGenerator.Generator.Generator;
|
namespace ReportGenerator.Generator.Generator;
|
||||||
|
|
||||||
|
internal class CollapsibleHtmlTableGenerator : HtmlTableGenerator
|
||||||
|
{
|
||||||
|
public string DetailsClass { get; init; }
|
||||||
|
public string Summary { get; init; } = "Show table";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public CollapsibleHtmlTableGenerator(int columns)
|
||||||
|
: base(columns) { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public CollapsibleHtmlTableGenerator(int columns, Stream stream)
|
||||||
|
: base(columns, stream) { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public CollapsibleHtmlTableGenerator(int columns, Stream stream, Encoding encoding)
|
||||||
|
: base(columns, stream, encoding) { }
|
||||||
|
|
||||||
|
#region Overrides of HtmlTableGenerator
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnOpen()
|
||||||
|
{
|
||||||
|
Writer.Write($"<details class={DetailsClass}>");
|
||||||
|
Writer.Write(HtmlTools.Wrap("summary", Summary));
|
||||||
|
base.OnOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
base.OnClose();
|
||||||
|
Writer.Write($"</details>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
internal class HtmlTableGenerator : TableGeneratorBase
|
internal class HtmlTableGenerator : TableGeneratorBase
|
||||||
{
|
{
|
||||||
public (string start, string end) RowFormat { get; init; } = ("<tr>", "</tr>");
|
public string Class { get; init; }
|
||||||
public (string start, string end) HeaderFormat { get; init; } = ("<th>", "</th>");
|
|
||||||
public (string start, string end) ColumnFormat { get; init; } = ("<td>", "</td>");
|
private static readonly (string start, string end) rowFormat = ("<tr>", "</tr>");
|
||||||
|
private static readonly (string start, string end) headerFormat = ("<th>", "</th>");
|
||||||
|
private static readonly (string start, string end) columnFormat = ("<td>", "</td>");
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public HtmlTableGenerator(int columns) : base(columns) { }
|
public HtmlTableGenerator(int columns) : base(columns) { }
|
||||||
|
|
||||||
#region Overrides of TableGeneratorBase
|
/// <inheritdoc />
|
||||||
|
public HtmlTableGenerator(int columns, Stream stream) : base(columns, stream) { }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ITableGenerator AppendHeader(IEnumerable<string> row) => AppendRow(row, RowFormat, HeaderFormat);
|
public HtmlTableGenerator(int columns, Stream stream, Encoding encoding) : base(columns, stream,
|
||||||
|
encoding)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#region State
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnOpen()
|
||||||
|
{
|
||||||
|
base.OnOpen();
|
||||||
|
Writer.Write($"<table class={Class}>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
base.OnClose();
|
||||||
|
Writer.Write("</table>");
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Writing
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ITableGenerator AppendRow(IEnumerable<string> row) => AppendRow(row, RowFormat, ColumnFormat);
|
public override ITableGenerator AppendHeader(IEnumerable<string> row) =>
|
||||||
|
AppendRow(row, rowFormat, headerFormat);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ITableGenerator AppendRow(IEnumerable<string> row) =>
|
||||||
|
AppendRow(row, rowFormat, columnFormat);
|
||||||
|
|
||||||
private ITableGenerator AppendRow(
|
private ITableGenerator AppendRow(
|
||||||
IEnumerable<string> row,
|
IEnumerable<string> row,
|
||||||
@@ -31,16 +97,15 @@ internal class HtmlTableGenerator : TableGeneratorBase
|
|||||||
var (rowStart, rowEnd) = rowFormat;
|
var (rowStart, rowEnd) = rowFormat;
|
||||||
var (colStart, colEnd) = columnFormat;
|
var (colStart, colEnd) = columnFormat;
|
||||||
|
|
||||||
StringBuilder
|
this
|
||||||
.Append(rowStart)
|
.Write(rowStart)
|
||||||
.Append(colStart)
|
.Write(colStart)
|
||||||
.AppendLine(string.Join(colEnd + colStart, row))
|
.Write(string.Join(colEnd + colStart, row))
|
||||||
.Append(colEnd)
|
.Write(colEnd)
|
||||||
.Append(rowEnd);
|
.Write(rowEnd);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
#endregion
|
||||||
public override string ToString() => "<table>" + base.ToString() + "</table>";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,32 @@
|
|||||||
using ReportGenerator.Generator.Abstract;
|
using ReportGenerator.Generator.Abstract;
|
||||||
using ReportGenerator.Generator.Interface;
|
using ReportGenerator.Generator.Interface;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace ReportGenerator.Generator.Generator;
|
namespace ReportGenerator.Generator.Generator;
|
||||||
|
|
||||||
public class MarkdownDocumentGenerator : DocumentGeneratorBase
|
public class MarkdownDocumentGenerator : DocumentGeneratorBase
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string FileExtension => "md";
|
public MarkdownDocumentGenerator() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public MarkdownDocumentGenerator(string filePath) : base(filePath) { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public MarkdownDocumentGenerator(Stream stream) : base(stream) { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public MarkdownDocumentGenerator(Stream stream, Encoding encoding) : base(stream, encoding) { }
|
||||||
|
|
||||||
|
#region Writing
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override IDocumentGenerator AppendHeading(int level, string text) =>
|
public override IDocumentGenerator AppendHeading(int level, string text) =>
|
||||||
AppendParagraph(new string('#', level) + ' ' + text);
|
AppendParagraph(new string('#', level) + ' ' + text);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override ITableGenerator AppendTable(int columns) =>
|
protected override ITableGenerator MakeTable(int columns, Stream stream) =>
|
||||||
new MarkdownTableGenerator(columns);
|
new MarkdownTableGenerator(columns, stream);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override IDocumentGenerator AppendParagraph(string? text = default)
|
public override IDocumentGenerator AppendParagraph(string? text = default)
|
||||||
@@ -24,7 +36,9 @@ public class MarkdownDocumentGenerator : DocumentGeneratorBase
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string FormatImage(string path, IBounds? bounds = default) =>
|
public override string FormatImage(string path, IBounds? bounds = default) =>
|
||||||
HtmlTools.FormatImage(path, bounds);
|
HtmlTools.FormatImage(path, default, bounds);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,35 @@
|
|||||||
using ReportGenerator.Generator.Abstract;
|
using ReportGenerator.Generator.Abstract;
|
||||||
using ReportGenerator.Generator.Interface;
|
using ReportGenerator.Generator.Interface;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace ReportGenerator.Generator.Generator;
|
namespace ReportGenerator.Generator.Generator;
|
||||||
|
|
||||||
internal class MarkdownTableGenerator : TableGeneratorBase
|
internal class MarkdownTableGenerator : TableGeneratorBase
|
||||||
{
|
{
|
||||||
public string ColumnSeparator { get; init; } = " | ";
|
private const string ColumnSeparator = " | ";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
internal MarkdownTableGenerator(int columns) : base(columns) { }
|
public MarkdownTableGenerator(int columns)
|
||||||
|
: base(columns) { }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ITableGenerator AppendHeader(IEnumerable<string> row) => AppendRow(row).AppendRow("---");
|
public MarkdownTableGenerator(int columns, Stream stream)
|
||||||
|
: base(columns, stream) { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public MarkdownTableGenerator(int columns, Stream stream, Encoding encoding)
|
||||||
|
: base(columns, stream, encoding) { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ITableGenerator AppendHeader(IEnumerable<string> row) =>
|
||||||
|
this
|
||||||
|
.AppendRow(row)
|
||||||
|
.AppendRow("---");
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ITableGenerator AppendRow(IEnumerable<string> row)
|
public override ITableGenerator AppendRow(IEnumerable<string> row)
|
||||||
{
|
{
|
||||||
StringBuilder.AppendLine(ColumnSeparator + string.Join(" | ", row) + ColumnSeparator);
|
Writer.WriteLine(ColumnSeparator + string.Join(" | ", row) + ColumnSeparator);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
@@ -4,9 +4,10 @@ namespace ReportGenerator.Generator;
|
|||||||
|
|
||||||
internal static class HtmlTools
|
internal static class HtmlTools
|
||||||
{
|
{
|
||||||
public static string Wrap(string tag, string content) => $"<{tag}>{content}</{tag}>";
|
public static string Wrap(string tag, string? content, string? @class = default) =>
|
||||||
|
$"<{tag} class={@class}>{content}</{tag}>";
|
||||||
|
|
||||||
public static string FormatImage(string path, IBounds? bounds = default)
|
public static string FormatImage(string path, string? @class = default, IBounds? bounds = default)
|
||||||
{
|
{
|
||||||
var style = bounds is null
|
var style = bounds is null
|
||||||
? string.Empty
|
? string.Empty
|
||||||
@@ -14,7 +15,7 @@ internal static class HtmlTools
|
|||||||
|
|
||||||
path += path.EndsWith(".png") ? string.Empty : ".png";
|
path += path.EndsWith(".png") ? string.Empty : ".png";
|
||||||
|
|
||||||
return $"<img src=\"{path}\" style=\"{style}\" />";
|
return $"<img src=\"{path}\" style=\"{style}\" class={@class} />";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetCssStyle(IBounds bounds)
|
private static string GetCssStyle(IBounds bounds)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
namespace ReportGenerator.Generator.Interface;
|
namespace ReportGenerator.Generator.Interface;
|
||||||
|
|
||||||
public interface IDocumentGenerator : IFileSerializable
|
public interface IDocumentGenerator : IStreamWriter
|
||||||
{
|
{
|
||||||
IDocumentGenerator Append(string? text = default);
|
IDocumentGenerator Append(string? text = default);
|
||||||
|
|
||||||
IDocumentGenerator AppendLine(string? text = default);
|
IDocumentGenerator AppendLine(string? text = default);
|
||||||
|
|
||||||
IDocumentGenerator AppendParagraph(string? text = default);
|
IDocumentGenerator AppendParagraph(string? text = default);
|
||||||
|
|
||||||
IDocumentGenerator AppendHeading(int level, string text);
|
IDocumentGenerator AppendHeading(int level, string text);
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
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,37 @@
|
|||||||
|
namespace ReportGenerator.Generator.Interface;
|
||||||
|
|
||||||
|
public interface IStreamWriter : IDisposable
|
||||||
|
{
|
||||||
|
/// <inheritdoc cref="TextWriter.WriteLine(string)"/>
|
||||||
|
IStreamWriter Write(string? text = default);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="TextWriter.WriteLine(string)"/>
|
||||||
|
IStreamWriter WriteLine(string? text = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Writes the contents of the given <paramref name="writer"/>
|
||||||
|
/// to the internal <see cref="Stream"/></para>
|
||||||
|
/// </summary>
|
||||||
|
IStreamWriter Write(IStreamWriter writer);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Writes the contents of the given <paramref name="reader"/>
|
||||||
|
/// to the internal <see cref="Stream"/></para>
|
||||||
|
/// </summary>
|
||||||
|
IStreamWriter Write(StreamReader reader);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes the content writer
|
||||||
|
/// </summary>
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the content writer
|
||||||
|
/// </summary>
|
||||||
|
void Open();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the content of the underlying stream
|
||||||
|
/// </summary>
|
||||||
|
StreamReader Read();
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace ReportGenerator.Generator.Interface;
|
|
||||||
|
|
||||||
public interface IStringSerializable
|
|
||||||
{
|
|
||||||
string ToString();
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace ReportGenerator.Generator.Interface;
|
namespace ReportGenerator.Generator.Interface;
|
||||||
|
|
||||||
public interface ITableGenerator : IStringSerializable
|
public interface ITableGenerator : IStreamWriter
|
||||||
{
|
{
|
||||||
int Columns { get; }
|
int Columns { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -49,12 +49,22 @@ public readonly struct ProcessorStat : IDistanceComparer<IEnumerable<string>>
|
|||||||
Words = reference.Select(r => GetDistanceInfo(r, hypothesis)).ToArray();
|
Words = reference.Select(r => GetDistanceInfo(r, hypothesis)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ICollection<IDistanceComparer<string>> GetDistanceInfos(
|
||||||
|
ICollection<string> reference,
|
||||||
|
ICollection<string> hypothesis
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// todo avoid matching the same reference with a value multiple times
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the <paramref name="reference"/> with all given <paramref name="values"/>
|
/// Compares the <paramref name="reference"/> with all given <paramref name="values"/>
|
||||||
/// and determines the <see cref="IDistanceComparer{T}"/> with the lowest error
|
/// and determines the <see cref="IDistanceComparer{T}"/> with the lowest error
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static IDistanceComparer<string> GetDistanceInfo(
|
private static IDistanceComparer<string> GetDistanceInfo(
|
||||||
string reference, IEnumerable<string> values
|
string reference,
|
||||||
|
IEnumerable<string> values
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var result = new DistanceComparer<string>(reference);
|
var result = new DistanceComparer<string>(reference);
|
||||||
@@ -62,15 +72,18 @@ public readonly struct ProcessorStat : IDistanceComparer<IEnumerable<string>>
|
|||||||
// Determine character stat with lowest error
|
// Determine character stat with lowest error
|
||||||
foreach (var value in values)
|
foreach (var value in values)
|
||||||
{
|
{
|
||||||
|
// todo avoid matching the same reference with a value multiple times
|
||||||
|
|
||||||
var stat = new DistanceComparer<string>(reference, value);
|
var stat = new DistanceComparer<string>(reference, value);
|
||||||
if (stat.Distance > result.Distance)
|
if (stat.Distance > result.Distance || (stat.Distance / reference.Length) > 0.6d)
|
||||||
{
|
{
|
||||||
|
// todo fine-tune threshold
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = stat;
|
result = stat;
|
||||||
|
|
||||||
if (stat.Distance == 0)
|
if (stat.Distance <= 0)
|
||||||
{
|
{
|
||||||
// We cannot go lower than zero, break
|
// We cannot go lower than zero, break
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -18,13 +18,16 @@ internal static class Program
|
|||||||
Console.WriteLine("Generating report");
|
Console.WriteLine("Generating report");
|
||||||
var scans = Scan(tagFileInfos, scanFileInfos);
|
var scans = Scan(tagFileInfos, scanFileInfos);
|
||||||
|
|
||||||
new ReportGenerator("OCR Report", new HtmlDocumentGenerator(), scans)
|
var path = Path.GetFullPath("report.html");
|
||||||
.AddComparison("Processing summary (Average)", v => v.Average())
|
|
||||||
// .AddComparison("Processing summary (Median)", v => v.Median())
|
|
||||||
.AddImageStatsFull("Scan Results")
|
|
||||||
.ToFile("report");
|
|
||||||
|
|
||||||
Console.WriteLine("Completed");
|
using var document = new HtmlDocumentGenerator(path);
|
||||||
|
using var report = new ReportGenerator("OCR Report", document, scans)
|
||||||
|
.AddComparison("Processing summary (Average)", v => v.Average())
|
||||||
|
// .AddComparison("Processing summary (Cumulative)", v => v.Sum())
|
||||||
|
// .AddComparison("Processing summary (Median)", v => v.Median())
|
||||||
|
.AddImageStatsFull("Scan Results");
|
||||||
|
|
||||||
|
Console.WriteLine($"Saved report to '{path}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ImageStats> Scan(
|
private static IEnumerable<ImageStats> Scan(
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
using ReportGenerator.Generator.Abstract;
|
using ReportGenerator.Generator.Interface;
|
||||||
using ReportGenerator.Generator.Interface;
|
|
||||||
using ReportGenerator.Generator.Model;
|
using ReportGenerator.Generator.Model;
|
||||||
using ReportGenerator.Models;
|
using ReportGenerator.Models;
|
||||||
|
|
||||||
namespace ReportGenerator;
|
namespace ReportGenerator;
|
||||||
|
|
||||||
public class ReportGenerator : FileSerializableBase
|
public class ReportGenerator : IDisposable
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override string FileExtension => Document.FileExtension;
|
|
||||||
|
|
||||||
private IDocumentGenerator Document { get; }
|
private IDocumentGenerator Document { get; }
|
||||||
|
|
||||||
private ICollection<ImageStats> Images { get; }
|
private ICollection<ImageStats> Images { get; }
|
||||||
@@ -19,30 +15,34 @@ public class ReportGenerator : FileSerializableBase
|
|||||||
IEnumerable<ImageStats> data
|
IEnumerable<ImageStats> data
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Document = document;
|
|
||||||
Images = data.ToArray();
|
Images = data.ToArray();
|
||||||
|
|
||||||
|
Document = document;
|
||||||
|
document.Open();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReportGenerator(
|
public ReportGenerator(
|
||||||
string title,
|
string title,
|
||||||
IDocumentGenerator document,
|
IDocumentGenerator document,
|
||||||
IEnumerable<ImageStats> data
|
IEnumerable<ImageStats> data
|
||||||
) : this(document, data)
|
) : this(document, data) => AddTitle(title);
|
||||||
{
|
|
||||||
WithTitle(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
#region Writing
|
||||||
public override string ToString() => Document.ToString();
|
|
||||||
|
|
||||||
#region Report content generation
|
public ReportGenerator AddTitle(string text)
|
||||||
|
|
||||||
public ReportGenerator WithTitle(string text)
|
|
||||||
{
|
{
|
||||||
Document.AppendHeading(1, text);
|
Document.AppendHeading(1, text);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReportGenerator AddProcessorStats(string title)
|
||||||
|
{
|
||||||
|
Document.AppendHeading(2, title);
|
||||||
|
|
||||||
|
// todo show best/worst images per processor
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ReportGenerator AddImageStatsFull(string title)
|
public ReportGenerator AddImageStatsFull(string title)
|
||||||
{
|
{
|
||||||
Document.AppendHeading(2, title);
|
Document.AppendHeading(2, title);
|
||||||
@@ -86,7 +86,7 @@ public class ReportGenerator : FileSerializableBase
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.AppendParagraph(
|
.AppendParagraph(
|
||||||
$"*Comparison data generated based on {stat.Reference.Count} tagged words.*"
|
$"Comparison data generated based on {stat.Reference.Count} tagged words."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,4 +167,23 @@ public class ReportGenerator : FileSerializableBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
Document.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,14 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Properties\htmldocument-style.css" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Generator\Generator\Resources\Style.css" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"float",
|
"float",
|
||||||
"treibervariable",
|
"treibervariable",
|
||||||
"bit",
|
"bit",
|
||||||
"byt",
|
"byte",
|
||||||
"wort",
|
"wort",
|
||||||
"doppelwort",
|
"doppelwort",
|
||||||
"float",
|
"float",
|
||||||
|
|||||||
Vendored
+17
-1943
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user