Update the Topology display and the AsciiArt
This commit is contained in:
parent
8631ada267
commit
cb5bd91e55
|
@ -69,39 +69,6 @@ public static class AsciiArt
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String CreateVerticalPad(String value, Int32 contentVerticalWidth, Boolean direction, String name)
|
|
||||||
{
|
|
||||||
var v = value.PadLeft(contentVerticalWidth);
|
|
||||||
var n = name.PadLeft(contentVerticalWidth);
|
|
||||||
|
|
||||||
if (direction) // up
|
|
||||||
{
|
|
||||||
var horizontal = "".PadLeft(contentVerticalWidth - 4, ' ').V();
|
|
||||||
|
|
||||||
return StringUtils.JoinLines(
|
|
||||||
n,
|
|
||||||
horizontal,
|
|
||||||
horizontal,
|
|
||||||
v,
|
|
||||||
horizontal,
|
|
||||||
horizontal
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else // down
|
|
||||||
{
|
|
||||||
var horizontal = "".PadLeft(contentVerticalWidth - 4, ' ').V();
|
|
||||||
|
|
||||||
return StringUtils.JoinLines(
|
|
||||||
horizontal,
|
|
||||||
horizontal,
|
|
||||||
v,
|
|
||||||
horizontal,
|
|
||||||
horizontal,
|
|
||||||
n
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String CreateVerticalArrow(Decimal power, Int32 width = 0)
|
public static String CreateVerticalArrow(Decimal power, Int32 width = 0)
|
||||||
{
|
{
|
||||||
var flow = "V".NewLine() + "V".NewLine() + power.W().NewLine() + "V".NewLine() + "V";
|
var flow = "V".NewLine() + "V".NewLine() + power.W().NewLine() + "V".NewLine() + "V";
|
||||||
|
|
|
@ -4,7 +4,6 @@ using System.Text.Json.Nodes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Flurl.Http;
|
using Flurl.Http;
|
||||||
using InnovEnergy.App.SaliMax.Controller;
|
using InnovEnergy.App.SaliMax.Controller;
|
||||||
using InnovEnergy.App.SaliMax.Log;
|
|
||||||
using InnovEnergy.App.SaliMax.SaliMaxRelays;
|
using InnovEnergy.App.SaliMax.SaliMaxRelays;
|
||||||
using InnovEnergy.App.SaliMax.SystemConfig;
|
using InnovEnergy.App.SaliMax.SystemConfig;
|
||||||
using InnovEnergy.Lib.Devices.AMPT;
|
using InnovEnergy.Lib.Devices.AMPT;
|
||||||
|
@ -109,7 +108,6 @@ internal static class Program
|
||||||
{
|
{
|
||||||
InverterStatus = inverterDevice.ReadStatus(),
|
InverterStatus = inverterDevice.ReadStatus(),
|
||||||
DcDcStatus = dcDcDevice.ReadStatus(),
|
DcDcStatus = dcDcDevice.ReadStatus(),
|
||||||
|
|
||||||
BatteriesStatus = combinedBatteryStatus,
|
BatteriesStatus = combinedBatteryStatus,
|
||||||
AcInToAcOutMeterStatus = acInToAcOutMeterDevice.ReadStatus(),
|
AcInToAcOutMeterStatus = acInToAcOutMeterDevice.ReadStatus(),
|
||||||
GridMeterStatus = gridMeterDevice.ReadStatus(),
|
GridMeterStatus = gridMeterDevice.ReadStatus(),
|
||||||
|
@ -123,10 +121,6 @@ internal static class Program
|
||||||
var startTime = UnixTime.Now;
|
var startTime = UnixTime.Now;
|
||||||
const Int32 delayTime = 10;
|
const Int32 delayTime = 10;
|
||||||
|
|
||||||
|
|
||||||
await UploadTopology(s3Config, Salimax.TopologyToLog(startTime), startTime);
|
|
||||||
DebugWriteTopology(startTime);
|
|
||||||
|
|
||||||
Console.WriteLine("press ctrl-C to stop");
|
Console.WriteLine("press ctrl-C to stop");
|
||||||
|
|
||||||
|
|
||||||
|
@ -167,21 +161,6 @@ internal static class Program
|
||||||
// WriteToFile(jsonLog, "/home/debian/DataSaliMax/" + timestamp); // this is was for beaglebone TODO
|
// WriteToFile(jsonLog, "/home/debian/DataSaliMax/" + timestamp); // this is was for beaglebone TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// [Conditional("RELEASE")]
|
|
||||||
private static JsonObject ReleaseWriteTopology(UnixTime timestamp)
|
|
||||||
{
|
|
||||||
var topologyJson = Salimax.TopologyToLog(timestamp);
|
|
||||||
|
|
||||||
// WriteToFile(topologyJson, "/home/debian/DataSaliMax/topology" + timestamp); // this is was for beaglebone
|
|
||||||
return topologyJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
|
||||||
private static void DebugWriteTopology(UnixTime timestamp)
|
|
||||||
{
|
|
||||||
var topologyJson = Salimax.TopologyToLog(timestamp);
|
|
||||||
WriteToFile(topologyJson, "/home/atef/JsonData/topology" + timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
[Conditional("DEBUG")]
|
||||||
private static void DebugWriteLog(JsonObject jsonLog, UnixTime timestamp)
|
private static void DebugWriteLog(JsonObject jsonLog, UnixTime timestamp)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#undef BatteriesAllowed
|
#define BatteriesAllowed
|
||||||
|
|
||||||
using InnovEnergy.App.SaliMax.Controller;
|
using InnovEnergy.App.SaliMax.Controller;
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
|
@ -9,32 +9,56 @@ namespace InnovEnergy.App.SaliMax;
|
||||||
|
|
||||||
public static class Topology
|
public static class Topology
|
||||||
{
|
{
|
||||||
public static void Print(StatusRecord s)
|
private static String Separator(Decimal power)
|
||||||
{
|
{
|
||||||
const String chargingSeparator = ">>>>>>>>>>";
|
const String chargingSeparator = ">>>>>>>>>>";
|
||||||
const String dischargingSeparator = "<<<<<<<<<";
|
const String dischargingSeparator = "<<<<<<<<<";
|
||||||
|
|
||||||
|
return power > 0 ? chargingSeparator : dischargingSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Decimal Round3(this Decimal d)
|
||||||
|
{
|
||||||
|
return d.RoundToSignificantDigits(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Print(StatusRecord s)
|
||||||
|
{
|
||||||
const Int32 height = 25;
|
const Int32 height = 25;
|
||||||
|
|
||||||
|
var calculatedActivePwr = - s.InverterStatus!.Ac.ActivePower;
|
||||||
var pwr = s.InverterStatus!.Ac.ActivePower;
|
var measuredActivePwr = (s.InverterStatus.SumActivePowerL1 + s.InverterStatus.SumActivePowerL2 +
|
||||||
var pvPower = (s.AmptStatus!.Strings[0].Voltage * s.AmptStatus.Strings[0].Current + s.AmptStatus!.Strings[1].Voltage * s.AmptStatus.Strings[1].Current); // TODO using one Ampt
|
s.InverterStatus.SumActivePowerL3) * -1;
|
||||||
var loadPower = Utils.Round3((s.GridMeterStatus!.Ac.ActivePower + pwr)); // it's a + because the pwr is inverted
|
|
||||||
|
measuredActivePwr.WriteLine(" : measured Sum of Active Pwr ");
|
||||||
var gridSeparator = s.GridMeterStatus!.Ac.ActivePower > 0 ? chargingSeparator : dischargingSeparator;
|
|
||||||
var inverterSeparator = -pwr > 0 ? chargingSeparator : dischargingSeparator;
|
var setValueCosPhi = s.InverterStatus.CosPhiSetValue;
|
||||||
var dcSeparator = -s.DcDcStatus!.Right.Power > 0 ? chargingSeparator : dischargingSeparator;
|
var setValueApparentPower = s.InverterStatus.ApparentPowerSetValue;
|
||||||
#if BatteriesAllowed
|
|
||||||
var battery1Separator = s.BatteriesStatus[0]!.Power > 0 ? chargingSeparator : dischargingSeparator;
|
|
||||||
var battery2Separator = s.BatteriesStatus[1]!.Power > 0 ? chargingSeparator : dischargingSeparator;
|
#if AmptAvailable
|
||||||
|
var pvPower = (s.AmptStatus!.Devices[0].Dc.Voltage * s.AmptStatus.Devices[0].Dc.Current + s.AmptStatus!.Devices[1].Dc.Voltage * s.AmptStatus.Devices[1].Dc.Current).Round0(); // TODO using one Ampt
|
||||||
|
#else
|
||||||
|
var pvPower = 0;
|
||||||
#endif
|
#endif
|
||||||
|
var criticalLoadPower = (s.AcInToAcOutMeterStatus!.Ac.ActivePower.Value).Round3();
|
||||||
|
|
||||||
|
var dcTotalPower = -s.DcDcStatus!.TotalDcPower;
|
||||||
|
var gridSeparator = Separator(s.GridMeterStatus!.Ac.ActivePower);
|
||||||
|
var inverterSeparator = Separator(measuredActivePwr);
|
||||||
|
var dcSeparator = Separator(dcTotalPower);
|
||||||
|
var something = measuredActivePwr + criticalLoadPower;
|
||||||
|
var gridLoadPower = (s.GridMeterStatus!.Ac.ActivePower - something).Value.Round3();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////// Grid //////////////////////
|
////////////////// Grid //////////////////////
|
||||||
var boxGrid = AsciiArt.CreateBox
|
var boxGrid = AsciiArt.CreateBox
|
||||||
(
|
(
|
||||||
"Grid",
|
"Grid",
|
||||||
s.GridMeterStatus.Ac.L1.Voltage.V(),
|
s.GridMeterStatus.Ac.L1.Voltage.Value.V(),
|
||||||
s.GridMeterStatus.Ac.L2.Voltage.V(),
|
s.GridMeterStatus.Ac.L2.Voltage.Value.V(),
|
||||||
s.GridMeterStatus.Ac.L3.Voltage.V()
|
s.GridMeterStatus.Ac.L3.Voltage.Value.V()
|
||||||
).AlignCenterVertical(height);
|
).AlignCenterVertical(height);
|
||||||
|
|
||||||
var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.Ac.ActivePower, gridSeparator)
|
var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.Ac.ActivePower, gridSeparator)
|
||||||
|
@ -45,9 +69,9 @@ public static class Topology
|
||||||
var boxAcBus = AsciiArt.CreateBox
|
var boxAcBus = AsciiArt.CreateBox
|
||||||
(
|
(
|
||||||
"AC Bus",
|
"AC Bus",
|
||||||
s.InverterStatus.Ac.L1.Voltage.V(),
|
s.InverterStatus.Ac.L1.Voltage.Value.V(),
|
||||||
s.InverterStatus.Ac.L2.Voltage.V(),
|
s.InverterStatus.Ac.L2.Voltage.Value.V(),
|
||||||
s.InverterStatus.Ac.L3.Voltage.V()
|
s.InverterStatus.Ac.L3.Voltage.Value.V()
|
||||||
);
|
);
|
||||||
|
|
||||||
var boxLoad = AsciiArt.CreateBox
|
var boxLoad = AsciiArt.CreateBox
|
||||||
|
@ -57,9 +81,9 @@ public static class Topology
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
var loadRect = StringUtils.AlignBottom(CreateRect(boxAcBus, boxLoad, loadPower), height);
|
var loadRect = StringUtils.AlignBottom(CreateRect(boxAcBus, boxLoad, gridLoadPower), height);
|
||||||
|
|
||||||
var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(-pwr, inverterSeparator)
|
var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(measuredActivePwr, inverterSeparator)
|
||||||
.AlignCenterVertical(height);
|
.AlignCenterVertical(height);
|
||||||
|
|
||||||
//////////////////// Inverter /////////////////////////
|
//////////////////// Inverter /////////////////////////
|
||||||
|
@ -70,7 +94,7 @@ public static class Topology
|
||||||
""
|
""
|
||||||
).AlignCenterVertical(height);
|
).AlignCenterVertical(height);
|
||||||
|
|
||||||
var inverterArrow = AsciiArt.CreateHorizontalArrow(-pwr, inverterSeparator)
|
var inverterArrow = AsciiArt.CreateHorizontalArrow(measuredActivePwr, inverterSeparator)
|
||||||
.AlignCenterVertical(height);
|
.AlignCenterVertical(height);
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,90 +102,113 @@ public static class Topology
|
||||||
var dcBusBox = AsciiArt.CreateBox
|
var dcBusBox = AsciiArt.CreateBox
|
||||||
(
|
(
|
||||||
"DC Bus",
|
"DC Bus",
|
||||||
(s.InverterStatus.ActualDcLinkVoltageLowerHalfExt + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt).V(),
|
(s.InverterStatus.ActualDcLinkVoltageLowerHalfExt.Value + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt.Value).V(),
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
var pvBox = AsciiArt.CreateBox
|
var pvBox = AsciiArt.CreateBox
|
||||||
(
|
(
|
||||||
"MPPT",
|
"MPPT",
|
||||||
((s.AmptStatus!.Strings[0].Voltage + s.AmptStatus!.Strings[1].Voltage) / 2).V(),
|
((s.AmptStatus!.Devices[0].Strings[0].Voltage.Value + s.AmptStatus!.Devices[0].Strings[1].Voltage.Value) / 2).V(),
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
var pvRect = StringUtils.AlignTop(CreateRect(pvBox, dcBusBox, pvPower), height);
|
var pvRect = StringUtils.AlignTop(CreateRect(pvBox, dcBusBox, pvPower), height);
|
||||||
|
|
||||||
var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Dc.Power, dcSeparator)
|
var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Left.Power, dcSeparator)
|
||||||
.AlignCenterVertical(height);
|
.AlignCenterVertical(height);
|
||||||
|
|
||||||
//////////////////// Dc/Dc /////////////////////////
|
//////////////////// Dc/Dc /////////////////////////
|
||||||
var dcBox = AsciiArt.CreateBox
|
|
||||||
(
|
|
||||||
"Dc/Dc",
|
|
||||||
s.DcDcStatus.BatteryVoltage.V(),
|
|
||||||
""
|
|
||||||
).AlignCenterVertical(height);
|
|
||||||
#if BatteriesAllowed
|
|
||||||
var dcArrow1 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[0]!.Power, battery1Separator);
|
|
||||||
var dcArrow2 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[1]!.Power, battery2Separator);
|
|
||||||
#else
|
|
||||||
var dcArrow1 ="";
|
|
||||||
var dcArrow2 = "";
|
|
||||||
var dcArrowRect = StringUtils.AlignCenterVertical(CreateRect(dcArrow1, dcArrow2), height);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if BatteriesAllowed
|
|
||||||
|
|
||||||
//////////////////// Batteries /////////////////////////
|
var dcBox = AsciiArt.CreateBox( "Dc/Dc", s.DcDcStatus.Right.Voltage.Value.V(), "").AlignCenterVertical(height);
|
||||||
var battery1Box = AsciiArt.CreateBox
|
|
||||||
(
|
|
||||||
"Battery 1",
|
|
||||||
s.BatteriesStatus[0].Voltage.V(),
|
|
||||||
s.BatteriesStatus[0].Soc.Percent(),
|
|
||||||
s.BatteriesStatus[0].Temperature.Celsius()
|
|
||||||
);
|
|
||||||
|
|
||||||
var battery2Box = AsciiArt.CreateBox
|
|
||||||
(
|
|
||||||
"Battery 2",
|
|
||||||
s.BatteriesStatus[1].Voltage.V(),
|
|
||||||
s.BatteriesStatus[1].Soc.Percent(),
|
|
||||||
s.BatteriesStatus[1].Temperature.Celsius()
|
|
||||||
);
|
|
||||||
|
|
||||||
var batteryRect = CreateRect(battery1Box, battery2Box).AlignCenterVertical(height);
|
var topology = "";
|
||||||
|
|
||||||
|
if (s.BatteriesStatus != null)
|
||||||
|
{
|
||||||
|
var numBatteries = s.BatteriesStatus.Children.Count;
|
||||||
|
|
||||||
var avgBatteryBox = AsciiArt.CreateBox
|
// Create an array of battery arrows using LINQ
|
||||||
(
|
var dcArrows = s
|
||||||
"Batteries",
|
.BatteriesStatus.Children
|
||||||
s.AvgBatteriesStatus!.Voltage.V(),
|
.Select(b => AsciiArt.CreateHorizontalArrow(b.Dc.Power, Separator(b.Dc.Power)))
|
||||||
s.AvgBatteriesStatus.Soc.Percent(),
|
.ToArray();
|
||||||
s.AvgBatteriesStatus.Temperature.Celsius()
|
|
||||||
).AlignCenterVertical(height);
|
|
||||||
|
|
||||||
|
// Create a rectangle from the array of arrows and align it vertically
|
||||||
|
var dcArrowRect = CreateRect(dcArrows).AlignCenterVertical(height);
|
||||||
|
|
||||||
|
//////////////////// Batteries /////////////////////////
|
||||||
|
|
||||||
|
var batteryBox = new String[numBatteries];
|
||||||
|
|
||||||
|
for (var i = 0; i < numBatteries; i++)
|
||||||
|
{
|
||||||
|
if (s.BatteriesStatus.Children[i] != null)
|
||||||
|
{
|
||||||
|
batteryBox[i] = AsciiArt.CreateBox
|
||||||
|
(
|
||||||
|
"Battery " + (i+1),
|
||||||
|
s.BatteriesStatus.Children[i].Dc.Voltage .Value.V(),
|
||||||
|
s.BatteriesStatus.Children[i].Soc .Value.Percent(),
|
||||||
|
s.BatteriesStatus.Children[i].Temperature .Value.Celsius(),
|
||||||
|
s.BatteriesStatus.Children[i].Dc.Current .Value.A(),
|
||||||
|
s.BatteriesStatus.Children[i].TotalCurrent.Value.A()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
batteryBox[i] = AsciiArt.CreateBox
|
||||||
|
(
|
||||||
|
"Battery " + (i+1),
|
||||||
|
"not detected"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var batteryRect = CreateRect(batteryBox).AlignCenterVertical(height);
|
||||||
|
|
||||||
|
|
||||||
|
var avgBatteryBox = "";
|
||||||
|
|
||||||
|
if (s.BatteriesStatus.Combined != null)
|
||||||
|
{
|
||||||
|
avgBatteryBox = AsciiArt.CreateBox
|
||||||
|
(
|
||||||
|
"Batteries",
|
||||||
|
s.BatteriesStatus.Combined.CellsVoltage,
|
||||||
|
s.BatteriesStatus.Combined.Soc,
|
||||||
|
s.BatteriesStatus.Combined.Temperature,
|
||||||
|
s.BatteriesStatus.Combined.Dc.Current,
|
||||||
|
s.BatteriesStatus.Combined.Alarms.Count > 0 ? String.Join(Environment.NewLine, s.BatteriesStatus.Combined.Alarms) : "No Alarm"
|
||||||
|
).AlignCenterVertical(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
topology = boxGrid.SideBySideWith(gridAcBusArrow, "")
|
||||||
|
.SideBySideWith(loadRect, "")
|
||||||
|
.SideBySideWith(acBusInvertArrow, "")
|
||||||
|
.SideBySideWith(inverterBox, "")
|
||||||
|
.SideBySideWith(inverterArrow, "")
|
||||||
|
.SideBySideWith(pvRect, "")
|
||||||
|
.SideBySideWith(dcBusArrow, "")
|
||||||
|
.SideBySideWith(dcBox, "")
|
||||||
|
.SideBySideWith(dcArrowRect, "")
|
||||||
|
.SideBySideWith(batteryRect, "")
|
||||||
|
.SideBySideWith(avgBatteryBox, "")+ "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
topology = boxGrid.SideBySideWith(gridAcBusArrow, "")
|
||||||
|
.SideBySideWith(loadRect, "")
|
||||||
|
.SideBySideWith(acBusInvertArrow, "")
|
||||||
|
.SideBySideWith(inverterBox, "")
|
||||||
|
.SideBySideWith(inverterArrow, "")
|
||||||
|
.SideBySideWith(pvRect, "")
|
||||||
|
.SideBySideWith(dcBusArrow, "")
|
||||||
|
.SideBySideWith(dcBox, "") + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
var topology = boxGrid.SideBySideWith(gridAcBusArrow, "")
|
|
||||||
.SideBySideWith(loadRect, "")
|
|
||||||
.SideBySideWith(acBusInvertArrow, "")
|
|
||||||
.SideBySideWith(inverterBox, "")
|
|
||||||
.SideBySideWith(inverterArrow, "")
|
|
||||||
.SideBySideWith(pvRect, "")
|
|
||||||
.SideBySideWith(dcBusArrow, "")
|
|
||||||
.SideBySideWith(dcBox, "")
|
|
||||||
.SideBySideWith(dcArrowRect, "")
|
|
||||||
.SideBySideWith(batteryRect, "")
|
|
||||||
.SideBySideWith(avgBatteryBox, "")+ "\n";
|
|
||||||
#else
|
|
||||||
var topology = boxGrid.SideBySideWith(gridAcBusArrow, "")
|
|
||||||
.SideBySideWith(loadRect, "")
|
|
||||||
.SideBySideWith(acBusInvertArrow, "")
|
|
||||||
.SideBySideWith(inverterBox, "")
|
|
||||||
.SideBySideWith(inverterArrow, "")
|
|
||||||
.SideBySideWith(pvRect, "")
|
|
||||||
.SideBySideWith(dcBusArrow, "")
|
|
||||||
.SideBySideWith(dcBox, "")+ "\n";
|
|
||||||
#endif
|
|
||||||
Console.WriteLine(topology);
|
Console.WriteLine(topology);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,5 +230,12 @@ public static class Topology
|
||||||
var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines();
|
var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines();
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String CreateRect(String[] boxes)
|
||||||
|
{
|
||||||
|
var maxWidth = boxes.Max(l => l.Width());
|
||||||
|
var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines();
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue