tbf/TestBenchFramework/BenchControl/Output/FileWriters/Enhanced/Writer.cs
2016-10-11 14:27:28 +02:00

410 lines
13 KiB
C#

///
/// Copyright (c) 2016 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using System.IO;
using log4net;
using Config.Entities;
using TBF.BenchControl;
using TBF.Resources;
namespace TBF.BenchControl.Output.FileWriters.Enhanced
{
public class Writer : ComponentBase, IOperation, GenericDevices.IResultsWriter
{
private static readonly ILog log = LogManager.GetLogger(typeof(Writer));
public override string ToString() { return string.Format("Output.FileWriters.Enhanced({0})", Cfg.ToString(1)); }
readonly WriterCfg writerCfg;
readonly string separatorStr;
readonly string header;
readonly string footer;
///
/// Items to print
///
readonly IList<Results.WMeterRsltItemSpec> commonItems;
readonly IList<Results.ItemSpec> testItems;
///
/// Results to print
///
Results.Entities.Batch batch;
StreamWriter writer;
StreamWriter writer2;
public Writer() {}
public Writer(Generic.IComponentCfg cfg)
: base(cfg)
{
writerCfg = cfg as WriterCfg;
switch (writerCfg.Separator)
{
default:
case Separator.None: separatorStr = string.Empty; break;
case Separator.Space: separatorStr = " "; break;
case Separator.Tabulator: separatorStr = "\t"; break;
case Separator.Comma: separatorStr = ","; break;
case Separator.Semicolon: separatorStr = ";"; break;
}
header = writerCfg.Header.Replace("~", "\r\n");
commonItems = Results.WMeterRsltItemSpec.FromStrArray(writerCfg.CommonItems);
testItems = Results.ItemSpec.FromStrArray(writerCfg.SelectedItems);
footer = writerCfg.Footer.Replace("~", "\r\n");
log.Debug(this.ToString());
}
/// <summary>
/// Eliminate spaces conditionally, depesing on bool WriterCfg.EliminateSpaces
/// </summary>
/// <param name="item">Input string</param>
/// <returns>Output string</returns>
string ElSpaces(string item)
{
if (writerCfg.EliminateSpaces)
return item.Replace(" ", string.Empty);
else
return item;
}
/// <summary>
/// Returns a file name derived from a DateTime structure.
/// Creates directories on this path as a side effect.
/// </summary>
/// <param name="time">Date and time</param>
/// <returns>File name</returns>
string GetFilename(string destinationPath, DateTime time)
{
string directory = destinationPath; /// Ends with "\\";
switch (writerCfg.YearFolders)
{
case YearFolders.FourDigit:
directory = string.Format("{0}{1:yyyy}\\", directory, time);
break;
case YearFolders.TwoDigit:
directory = string.Format("{0}{1:yy}\\", directory, time);
break;
}
switch (writerCfg.MonthFolders)
{
case MonthFolders.Name:
{
string monthStr;
switch (time.Month)
{
default:
case 1: monthStr = "January"; break;
case 2: monthStr = "February"; break;
case 3: monthStr = "March"; break;
case 4: monthStr = "April"; break;
case 5: monthStr = "May"; break;
case 6: monthStr = "June"; break;
case 7: monthStr = "July"; break;
case 8: monthStr = "August"; break;
case 9: monthStr = "September"; break;
case 10: monthStr = "October"; break;
case 11: monthStr = "November"; break;
case 12: monthStr = "December"; break;
}
directory = string.Format("{0}{1}\\", directory, monthStr);
break;
}
case MonthFolders.Digit:
directory = string.Format("{0}{1}\\", directory, time.Month.ToString());
break;
case MonthFolders.TwoDigit:
directory = string.Format("{0}{1:MM}\\", directory, time);
break;
}
switch (writerCfg.DayFolders)
{
case DayFolders.Digit:
directory = string.Format("{0}{1}\\", directory, time.Day.ToString());
break;
case DayFolders.TwoDigit:
directory = string.Format("{0}{1:dd}\\", directory, time);
break;
}
Directory.CreateDirectory(directory);
try
{
if (string.IsNullOrEmpty(writerCfg.FileNameFormat)) throw new Exception();
return directory + string.Format(writerCfg.FileNameFormat, time);
}
catch
{
return string.Format("{0}{1:yyMMdd-HHmm}.txt", directory, time);
}
}
/// <summary>
/// Writes the test cycle results into a file, Events: Event.ResultsWritten
/// </summary>
/// <param name="procedure">Procedure to print the results of</param>
/// <param name="unsortedResults">Results to write into the file</param>
/// <returns>Reference to the operation</returns>
public IOperation WriteResultsOp(Results.Entities.Batch batchResults)
{
this.batch = batchResults;
if (batch.WaterMeters.Count <= 0)
{
writer = null;
writer2 = null;
return this;
}
writer = null;
if (!string.IsNullOrEmpty(writerCfg.DestinationPath))
{
try { writer = File.AppendText(GetFilename(writerCfg.DestinationPath, batch.EndTime)); }
catch { };
}
writer2 = null;
if (!string.IsNullOrEmpty(writerCfg.DestinationPath2))
{
try { writer2 = File.AppendText(GetFilename(writerCfg.DestinationPath2, batch.EndTime)); }
catch { };
}
return this;
}
/// <summary>Start this operation</summary>
public void Start()
{
if (writer != null) WriteRslts(writer);
if (writer2 != null) WriteRslts(writer2);
}
void WriteRslts(StreamWriter wr)
{
///----------
/// Header
///----------
if (!string.IsNullOrEmpty(writerCfg.Header)) wr.Write(header);
wr.WriteLine(batch.ProtocolTitle);
wr.WriteLine(string.Empty);
///----------------
/// Common items
///----------------
string[] leftColumn = new string[commonItems.Count];
string[] rightColumn = new string[commonItems.Count];
int cnt = 0;
foreach (var v in commonItems)
{
leftColumn[cnt] = v.Caption;
rightColumn[cnt] = v.Print(batch.WaterMeters[0]);
cnt++;
}
/// Determine max. left column width in characters
int maxLen = 0;
foreach (var s in leftColumn) if (s.Length > maxLen) maxLen = s.Length;
/// Write aligned columns
for (int i = 0; i < Math.Min(leftColumn.Length, rightColumn.Length); i++)
{
wr.Write(leftColumn[i]);
wr.Write(new string(' ', maxLen - leftColumn[i].Length + 3));
wr.WriteLine(rightColumn[i]);
}
///--------
/// Body
///--------
foreach (var wm in batch.WaterMeters) WriteWM(wr, wm);
///----------
/// Footer
///----------
if (!string.IsNullOrEmpty(writerCfg.Footer)) wr.Write(footer);
}
/// <summary>
/// Write one water meter results
/// </summary>
/// <param name="wmNr">Water meter number (0-based)</param>
void WriteWM(StreamWriter wr, Results.Entities.WaterMeter wm)
{
wr.WriteLine(string.Empty);
/// Write water meter number and s/n
wr.Write(string.Format(Strings.Water_Meter_nr, wm.WMPosition));
if (!wm.Compound())
{
if (!string.IsNullOrEmpty(wm.SerialNr)) wr.Write(string.Format(", {0} {1}", Strings.SerialNr, wm.SerialNr));
}
else
{
if (!string.IsNullOrEmpty(wm.SerialNr)) wr.Write(string.Format(", {0} {1}", Strings.Main_WM_SerialNr, wm.SerialNr));
if (!string.IsNullOrEmpty(wm.SerialNrAux)) wr.Write(string.Format(", {0} {1}", Strings.Aux_WM_SerialNr, wm.SerialNrAux));
}
wr.WriteLine(string.Empty);
/// Determine column widths
int[] columnWidths = new int[testItems.Count];
int totalWidth = 0;
for (int i = 0; i < testItems.Count; i++)
{
columnWidths[i] = ElSpaces(testItems[i].ClmnHeaderText).Length;
foreach (var mtr in wm.MeterTestRslts)
{
if ((mtr != null) && (mtr.Publish() == Config.Entities.Publish.Always))
{
string itemText;
if (wm.Compound())
{
if (mtr.CompoundMeterId != (byte)CompoundMeterId.Compound) continue;
Results.Entities.MeterTestRslt mainMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.CompoundMain);
Results.Entities.MeterTestRslt auxMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.CompoundAux);
itemText = testItems[i].PrintCombined(mainMtr, auxMtr, mtr);
}
else if (wm.HeatMeter())
{
if (mtr.CompoundMeterId != (byte)CompoundMeterId.HeatMeterEnergy) continue;
Results.Entities.MeterTestRslt volumeMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.HeatMeterVolume);
itemText = testItems[i].PrintHeatMeter(volumeMtr, mtr);
}
else /// Single water meter
{
itemText = testItems[i].Print(mtr);
}
/// Strip color information
string[] texts = itemText.Split(new char[] { '|' });
if (texts.Length == 2) { itemText = texts[0]; }
int len = ElSpaces(itemText).Length;
if (len > columnWidths[i]) columnWidths[i] = len;
}
}
totalWidth += columnWidths[i];
}
totalWidth += 3 * (testItems.Count - 1);
if (totalWidth < 0) totalWidth = 0;
wr.WriteLine(new String('-', totalWidth)); /// Horizontal line above the header
/// Write column headers
for (int i = 0; i < testItems.Count; i++)
{
wr.Write(ElSpaces(testItems[i].ClmnHeaderText));
if (i < testItems.Count - 1)
{
if (!writerCfg.EliminateSpaces)
{
wr.Write(new string(' ', columnWidths[i] - testItems[i].ClmnHeaderText.Length + 3));
}
wr.Write(separatorStr);
}
else
{
wr.WriteLine(string.Empty);
}
}
wr.WriteLine(new String('-', totalWidth)); /// Horizontal line between the header and the body
/// Write table data
foreach (var mtr in wm.MeterTestRslts)
{
if ((mtr != null) && (mtr.Publish() == Config.Entities.Publish.Always))
{
for (int i = 0; i < testItems.Count; i++)
{
string itemText;
///
/// Fetch an item
///
if (wm.Compound() && mtr.CompoundMeterId == (byte)CompoundMeterId.Compound)
{
Results.Entities.MeterTestRslt mainMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.CompoundMain);
Results.Entities.MeterTestRslt auxMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.CompoundAux);
itemText = testItems[i].PrintCombined(mainMtr, auxMtr, mtr);
}
else if (wm.HeatMeter() && mtr.CompoundMeterId == (byte)CompoundMeterId.HeatMeterEnergy)
{
Results.Entities.MeterTestRslt volumeMtr = wm.GetMeterTestRslt(mtr.Name(), CompoundMeterId.HeatMeterVolume);
itemText = testItems[i].PrintHeatMeter(volumeMtr, mtr);
}
else if (!wm.Compound() && !wm.HeatMeter() && mtr.CompoundMeterId == (byte)CompoundMeterId.Single) /// Single water meter
{
itemText = testItems[i].Print(mtr);
}
else
{
continue;
}
///
/// Print the item
///
string[] texts = itemText.Split(new char[] { '|' });
if (texts.Length == 2) { itemText = texts[0]; } /// Strip color information
wr.Write(ElSpaces(itemText));
if (i < testItems.Count - 1)
{
if (!writerCfg.EliminateSpaces)
{
wr.Write(new string(' ', columnWidths[i] - itemText.Length + 3));
}
wr.Write(separatorStr);
}
else
{
wr.WriteLine(string.Empty);
}
}
}
}
wr.WriteLine(new String('-', totalWidth)); /// Horizontal line below the body
}
/// <summary>Run this operation</summary>
/// <returns>Event.ResultsWritten</returns>
public Event Run()
{
return Event.ResultsWritten;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
if (writer != null) writer.Close();
if (writer2 != null) writer2.Close();
}
}
}