362 lines
9.7 KiB
C#
362 lines
9.7 KiB
C#
|
|
///
|
|||
|
|
/// Copyright (c) 2013-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.Basic
|
|||
|
|
{
|
|||
|
|
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.Basic({0})", Cfg.ToString(1)); }
|
|||
|
|
|
|||
|
|
readonly WriterCfg writerCfg;
|
|||
|
|
readonly string separatorStr;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Result items to print
|
|||
|
|
/// </summary>
|
|||
|
|
IList<Results.ItemSpec> rsltItems;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Results to print
|
|||
|
|
/// </summary>
|
|||
|
|
Results.Entities.Batch batch;
|
|||
|
|
|
|||
|
|
StreamWriter writer;
|
|||
|
|
|
|||
|
|
|
|||
|
|
public Writer() {}
|
|||
|
|
|
|||
|
|
public Writer(WriterCfg cfg)
|
|||
|
|
: base(cfg)
|
|||
|
|
{
|
|||
|
|
writerCfg = cfg;
|
|||
|
|
|
|||
|
|
switch (cfg.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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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(DateTime time)
|
|||
|
|
{
|
|||
|
|
string directory = writerCfg.DestinationPath; /// Ends with "\\";
|
|||
|
|
Directory.CreateDirectory(directory);
|
|||
|
|
|
|||
|
|
if (writerCfg.YearFolders)
|
|||
|
|
{
|
|||
|
|
directory = string.Format("{0}{1}\\", directory, time.Year.ToString());
|
|||
|
|
Directory.CreateDirectory(directory);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (writerCfg.MonthFolders)
|
|||
|
|
{
|
|||
|
|
string monthStr /* = now.Month.ToString("D2")*/;
|
|||
|
|
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);
|
|||
|
|
Directory.CreateDirectory(directory);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (writerCfg.DayFolders)
|
|||
|
|
{
|
|||
|
|
directory = string.Format("{0}{1}\\", directory, time.Day.ToString("D2"));
|
|||
|
|
Directory.CreateDirectory(directory);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return string.Format("{0}{1}{2}{3}-{4}{5}.txt", directory, (time.Year % 100).ToString("D2"),
|
|||
|
|
time.Month.ToString("D2"), time.Day.ToString("D2"), time.Hour.ToString("D2"), time.Minute.ToString("D2"));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <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;
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rsltItems = Results.ItemSpec.FromStrArray(writerCfg.SelectedItems);
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
writer = new StreamWriter(System.IO.File.Create(GetFilename(batch.EndTime)));
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
writer = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>Start this operation</summary>
|
|||
|
|
public void Start()
|
|||
|
|
{
|
|||
|
|
if (writer == null) return;
|
|||
|
|
|
|||
|
|
///----------
|
|||
|
|
/// Header
|
|||
|
|
///----------
|
|||
|
|
writer.WriteLine(batch.ProtocolTitle);
|
|||
|
|
writer.WriteLine(string.Empty);
|
|||
|
|
|
|||
|
|
string[] leftColumn = new string[]
|
|||
|
|
{
|
|||
|
|
"Batch number: ",
|
|||
|
|
"Date and time: ",
|
|||
|
|
"Procedure:",
|
|||
|
|
Strings.User_,
|
|||
|
|
"Ambient temperature: ",
|
|||
|
|
"Ambient pressure: ",
|
|||
|
|
"Ambient humidity: ",
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
string[] rightColumn = new string[]
|
|||
|
|
{
|
|||
|
|
batch.BatchNr.ToString(),
|
|||
|
|
//batch.EndTime.ToShortDateString() + " " + batch.EndTime.ToShortTimeString(),
|
|||
|
|
string.Format("{0}.{1}.{2} {3}:{4}", batch.EndTime.Year.ToString("D4"),
|
|||
|
|
batch.EndTime.Month.ToString("D2"),
|
|||
|
|
batch.EndTime.Day.ToString("D2"),
|
|||
|
|
batch.EndTime.Hour.ToString("D2"),
|
|||
|
|
batch.EndTime.Minute.ToString("D2")),
|
|||
|
|
batch.ProcedureName,
|
|||
|
|
batch.UserName,
|
|||
|
|
batch.AmbientTempAve().ToString("F1") + " °C",
|
|||
|
|
batch.AmbientPressAve().ToString("F0") + " mbar",
|
|||
|
|
batch.AmbientHumiAve().ToString("F0") + " %",
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/// 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++)
|
|||
|
|
{
|
|||
|
|
writer.Write(leftColumn[i]);
|
|||
|
|
writer.Write(new string(' ', maxLen - leftColumn[i].Length + 3));
|
|||
|
|
writer.WriteLine(rightColumn[i]);
|
|||
|
|
}
|
|||
|
|
writer.WriteLine(string.Empty);
|
|||
|
|
|
|||
|
|
|
|||
|
|
///--------
|
|||
|
|
/// Body
|
|||
|
|
///--------
|
|||
|
|
foreach (var wm in batch.WaterMeters) WriteWM(wm);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Write one water meter results
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="wmNr">Water meter number (0-based)</param>
|
|||
|
|
void WriteWM(Results.Entities.WaterMeter wm)
|
|||
|
|
{
|
|||
|
|
/// Determine column widths
|
|||
|
|
int[] columnWidths = new int[rsltItems.Count];
|
|||
|
|
int totalWidth = 0;
|
|||
|
|
for (int i = 0; i < rsltItems.Count; i++)
|
|||
|
|
{
|
|||
|
|
columnWidths[i] = ElSpaces(rsltItems[i].ClmnHeaderText).Length;
|
|||
|
|
foreach (var mtr in wm.MeterTestRslts)
|
|||
|
|
{
|
|||
|
|
if ((mtr != null) && (mtr.Publish() == Config.Entities.Publish.Always))
|
|||
|
|
{
|
|||
|
|
string itemText;
|
|||
|
|
|
|||
|
|
if (!wm.Compound())
|
|||
|
|
{
|
|||
|
|
/// Single water meter
|
|||
|
|
itemText = rsltItems[i].Print(mtr);
|
|||
|
|
}
|
|||
|
|
else if (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 = rsltItems[i].PrintCombined(mainMtr, auxMtr, mtr);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 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 * (rsltItems.Count - 1);
|
|||
|
|
if (totalWidth < 0) totalWidth = 0;
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// Write water meter number and s/n
|
|||
|
|
writer.Write(string.Format("Water meter {0}", wm.WMPosition));
|
|||
|
|
if (!string.IsNullOrEmpty(wm.SerialNr)) writer.Write(string.Format(" s/n: {0}", wm.SerialNr));
|
|||
|
|
writer.WriteLine(string.Empty);
|
|||
|
|
|
|||
|
|
|
|||
|
|
writer.WriteLine(new String('-', totalWidth)); /// Horizontal line above the header
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// Write column headers
|
|||
|
|
for (int i = 0; i < rsltItems.Count; i++)
|
|||
|
|
{
|
|||
|
|
writer.Write(ElSpaces(rsltItems[i].ClmnHeaderText));
|
|||
|
|
|
|||
|
|
if (i < rsltItems.Count - 1)
|
|||
|
|
{
|
|||
|
|
if (!writerCfg.EliminateSpaces)
|
|||
|
|
{
|
|||
|
|
writer.Write(new string(' ', columnWidths[i] - rsltItems[i].ClmnHeaderText.Length + 3));
|
|||
|
|
}
|
|||
|
|
writer.Write(separatorStr);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
writer.WriteLine(string.Empty);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
writer.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 < rsltItems.Count; i++)
|
|||
|
|
{
|
|||
|
|
string itemText;
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Fetch an item
|
|||
|
|
///
|
|||
|
|
if (!wm.Compound())
|
|||
|
|
{
|
|||
|
|
/// Single water meter
|
|||
|
|
itemText = rsltItems[i].Print(mtr);
|
|||
|
|
}
|
|||
|
|
else if (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 = rsltItems[i].PrintCombined(mainMtr, auxMtr, mtr);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Print the item
|
|||
|
|
///
|
|||
|
|
string[] texts = itemText.Split(new char[] { '|' });
|
|||
|
|
if (texts.Length == 2) { itemText = texts[0]; } /// Strip color information
|
|||
|
|
|
|||
|
|
writer.Write(ElSpaces(itemText));
|
|||
|
|
|
|||
|
|
if (i < rsltItems.Count - 1)
|
|||
|
|
{
|
|||
|
|
if (!writerCfg.EliminateSpaces)
|
|||
|
|
{
|
|||
|
|
writer.Write(new string(' ', columnWidths[i] - itemText.Length + 3));
|
|||
|
|
}
|
|||
|
|
writer.Write(separatorStr);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
writer.WriteLine(string.Empty);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
writer.WriteLine(new String('-', totalWidth)); /// Horizontal line below the body
|
|||
|
|
|
|||
|
|
writer.WriteLine(string.Empty);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <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();
|
|||
|
|
writer = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|