diff --git a/Elwig/Helpers/Billing/Graph.cs b/Elwig/Helpers/Billing/Graph.cs index b719013..66095cf 100644 --- a/Elwig/Helpers/Billing/Graph.cs +++ b/Elwig/Helpers/Billing/Graph.cs @@ -7,18 +7,18 @@ using System.Text.Json.Nodes; namespace Elwig.Helpers.Billing { public class Graph : ICloneable { - public string Type { get; set; } - public int Num { get; set; } + public BillingData.CurveMode Mode { get; set; } + public int Id { get; set; } private int MinX { get; set; } private int MaxX { get; set; } - public string Contracts { get; set; } + public List> Contracts { get; set; } public double[] DataX { get; set; } public double[] DataY { get; set; } - public Graph(int num, int minX, int maxX) { - Type = "oe"; - Num = num; - Contracts = ""; + public Graph(int id, BillingData.CurveMode mode, int minX, int maxX) { + Id = id; + Mode = mode; + Contracts = new List>(); MinX = minX; MaxX = maxX; @@ -26,21 +26,21 @@ namespace Elwig.Helpers.Billing { DataY = DataGen.Zeros(MaxX - MinX + 1); } - public Graph(string type, int num, JsonObject graphData, string contracts, int minX, int maxX) { - Type = type; - Num = num; - Contracts = contracts; + public Graph(int id, BillingData.CurveMode mode, Dictionary data, int minX, int maxX) { + Id = id; + Mode = mode; + Contracts = new List>(); MinX = minX; MaxX = maxX; DataX = DataGen.Range(MinX, MaxX + 1); DataY = DataGen.Zeros(MaxX - MinX + 1); - ParseGraphData(graphData); + ParseGraphData(data); } - public Graph(string type, int num, int minX, int maxX, string contracts, double[] dataX, double[] dataY) { - Type = type; - Num = num; + public Graph(int id, BillingData.CurveMode mode, int minX, int maxX, List> contracts, double[] dataX, double[] dataY) { + Id = id; + Mode = mode; MinX = minX; MaxX = maxX; Contracts = contracts; @@ -48,72 +48,78 @@ namespace Elwig.Helpers.Billing { DataY = dataY; } - private void ParseGraphData(JsonObject graphData) { - var GraphPoints = graphData.ToDictionary(p => int.Parse(p.Key[..^2]), p => (double)p.Value?.AsValue()); - - if (GraphPoints.Keys.Count < 1) { + private void ParseGraphData(Dictionary graphPoints) { + if (graphPoints.Keys.Count < 1) { return; } - var minKey = GraphPoints.Keys.Order().First(); - var maxKey = GraphPoints.Keys.OrderDescending().First(); + var minKey = graphPoints.Keys.Order().First(); + var maxKey = graphPoints.Keys.OrderDescending().First(); - if (!GraphPoints.ContainsKey(MinX)) { - GraphPoints.Add(MinX, GraphPoints.GetValueOrDefault(minKey)); + if (!graphPoints.ContainsKey(MinX)) { + graphPoints.Add(MinX, graphPoints.GetValueOrDefault(minKey)); } - if (!GraphPoints.ContainsKey(MaxX)) { - GraphPoints.Add(MaxX, GraphPoints.GetValueOrDefault(maxKey)); + if (!graphPoints.ContainsKey(MaxX)) { + graphPoints.Add(MaxX, graphPoints.GetValueOrDefault(maxKey)); } - var keys = GraphPoints.Keys.Order().ToArray(); + var keys = graphPoints.Keys.Order().ToArray(); for (int i = 0; i < keys.Length; i++) { - double point1Value = GraphPoints[keys[i]]; + decimal point1Value = graphPoints[keys[i]]; if (i + 1 < keys.Length) { - double point2Value = GraphPoints[keys[i + 1]]; + decimal point2Value = graphPoints[keys[i + 1]]; if (point1Value == point2Value) { - for (int j = keys[i] - MinX; j < keys[i + 1] - MinX; j++) { - DataY[j] = point1Value; + for (int j = (int)(keys[i] - MinX); j < keys[i + 1] - MinX; j++) { + DataY[j] = (double)point1Value; } } else { - int steps = Math.Abs(keys[i + 1] - keys[i]); - double step = (point2Value - point1Value) / steps; + int steps = (int)Math.Abs(keys[i + 1] - keys[i]); + decimal step = (point2Value - point1Value) / steps; - DataY[keys[i] - MinX] = point1Value; - DataY[keys[i + 1] - MinX] = point2Value; + DataY[(int)(keys[i] - MinX)] = (double)point1Value; + DataY[(int)(keys[i + 1] - MinX)] = (double)point2Value; - for (int j = keys[i] - MinX; j < keys[i + 1] - MinX - 1; j++) { - DataY[j + 1] = Math.Round(DataY[j] + step, 4); // TODO richtig runden + for (int j = (int)(keys[i] - MinX); j < keys[i + 1] - MinX - 1; j++) { + DataY[j + 1] = Math.Round(DataY[j] + (double)step, 4); // TODO richtig runden } } } else { - for (int j = keys[i] - MinX; j < DataX.Length; j++) { - DataY[j] = point1Value; + for (int j = (int)(keys[i] - MinX); j < DataX.Length; j++) { + DataY[j] = (double)point1Value; } } } } public JsonObject ToJson() { - JsonObject graph = new(); + var graph = new JsonObject { + ["id"] = Id, + ["mode"] = Mode.ToString().ToLower(), + }; + + var data = new JsonObject(); if (DataY[0] != DataY[1]) { - graph.Add(new KeyValuePair(DataX[0] + Type.ToLower(), Math.Round(DataY[0], 4))); + data.Add(new KeyValuePair(DataX[0] + Mode.ToString().ToLower(), Math.Round(DataY[0], 4))); } for (int i = 1; i < DataX.Length - 1; i++) { - if (Math.Round(DataY[i] - DataY[i - 1], 4) != Math.Round(DataY[i + 1] - DataY[i], 4)) { - graph.Add(new KeyValuePair(DataX[i] + Type.ToLower(), Math.Round(DataY[i], 4))); + if (Math.Round(DataY[i] - DataY[i - 1], 10) != Math.Round(DataY[i + 1] - DataY[i], 10)) { + data.Add(new KeyValuePair(DataX[i] + Mode.ToString().ToLower(), Math.Round(DataY[i], 4))); } } if (DataY[^1] != DataY[^2]) { - graph.Add(new KeyValuePair(DataX[^1] + Type.ToLower(), Math.Round(DataY[^1], 4))); + data.Add(new KeyValuePair(DataX[^1] + Mode.ToString().ToLower(), Math.Round(DataY[^1], 4))); } + + graph["data"] = data; + return graph; } public object Clone() { - return new Graph(Type, Num, MinX, MaxX, Contracts, (double[])DataX.Clone(), (double[])DataY.Clone()); + return new Graph(Id, Mode, MinX, MaxX, Contracts.ConvertAll(item => new Tuple(item.Item1, item.Item2)), (double[])DataX.Clone(), (double[])DataY.Clone()); } } } diff --git a/Elwig/Windows/ChartWindow.xaml b/Elwig/Windows/ChartWindow.xaml index f0be64b..707fa29 100644 --- a/Elwig/Windows/ChartWindow.xaml +++ b/Elwig/Windows/ChartWindow.xaml @@ -68,14 +68,14 @@ SelectionChanged="GraphList_SelectionChanged" Margin="5,15,5,0" Grid.Row="0" FontSize="14" Grid.ColumnSpan="3"> - + - + diff --git a/Elwig/Windows/ChartWindow.xaml.cs b/Elwig/Windows/ChartWindow.xaml.cs index 1466b99..913e021 100644 --- a/Elwig/Windows/ChartWindow.xaml.cs +++ b/Elwig/Windows/ChartWindow.xaml.cs @@ -75,27 +75,15 @@ namespace Elwig.Windows { var data = ParseData(paymentVar); if (data == null) return; - var auszahlungsSorten = data["AuszahlungSorten"]?.AsObject(); - if (auszahlungsSorten == null) { - return; + var curves = BillingData.GetCurves(data, BillingData.CalculationMode.Elwig); + List graphs = []; + + foreach (var (id, curve) in curves) { + graphs.Add(new Graph(id, curve.Mode, curve.Normal, MinOechsle, MaxOechsle)); } - var Graphs = auszahlungsSorten["Kurven"]?.AsArray(); - - if (Graphs == null) { - return; - } - - List GraphsList = []; - - int i = 1; - foreach (var graph in Graphs) { - GraphsList.Add(new Graph("Oe", i, graph?.AsObject(), ParseContracts(auszahlungsSorten, i - 1), 50, 140)); - i++; - } - - ControlUtils.RenewItemsSource(GraphList, GraphsList, g => (g as Graph)?.Num); - if (GraphsList.Count == 1) { + ControlUtils.RenewItemsSource(GraphList, graphs, g => (g as Graph)?.Id); + if (graphs.Count == 1) { GraphList.SelectedIndex = 0; } @@ -125,46 +113,63 @@ namespace Elwig.Windows { var data = ParseData(paymentVar); if (data == null) return false; - var auszahlungsSorten = data["AuszahlungSorten"]?.AsObject(); - if (auszahlungsSorten == null) { + MessageBox.Show("1"); + + + JsonArray? curves; + JsonObject? payment; + + if (data["mode"]?.GetValue() == "elwig") { + curves = data["curves"]?.AsArray(); + payment = data["payment"]?.AsObject(); + } else if (data["mode"]?.GetValue() == "wgmaster") { + curves = data["Kurven"]?.AsArray(); + payment = data["AuszahlungSorten"]?.AsObject(); + } else { return false; } - var Graphs = auszahlungsSorten["Kurven"]?.AsObject(); - if (Graphs == null) { + MessageBox.Show("2"); + + + if (curves == null || payment == null) { return false; } - int i = 1; - foreach (var graph in Graphs) { - if (i == num) { - Graphs.Remove(graph.Key); + MessageBox.Show("3"); + + foreach (var curve in curves) { + MessageBox.Show("LOOP"); + if (curve?.AsObject()?["id"]?.GetValue() == num) { + MessageBox.Show(curve.ToJsonString()); + curves.Remove(curve); break; } - i++; } - foreach (var sorte in auszahlungsSorten) { - if (sorte.Key == "Kurven") continue; - foreach (var attribut in sorte.Value.AsObject()) { - var bindungen = attribut.Value.AsObject(); - foreach (var bindung in bindungen) { - int v = (int)bindung.Value; - if (v == num - 1) { - bindungen.Remove(bindung.Key); - } else if (v > num - 1) { - bindungen[bindung.Key] = v - 1; - } - } + MessageBox.Show("4"); + + var keysToRemove = new List(); + foreach (var sorte in payment) { + MessageBox.Show(sorte.Value.GetType().ToString()); + if (sorte.Value.AsValue().TryGetValue(out string? curve) && curve.Equals($"curve:{num}")) { + keysToRemove.Add(sorte.Key); } } + foreach (var key in keysToRemove) { + payment.Remove(key); + } + + MessageBox.Show("5"); + EntityEntry? tr = null; try { paymentVar.Data = data.ToString(); tr = Context.Update(paymentVar); await Context.SaveChangesAsync(); + await App.HintContextChange(); } catch (Exception exc) { if (tr != null) await tr.ReloadAsync(); var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message; @@ -175,6 +180,62 @@ namespace Elwig.Windows { return true; } + private async Task UpdateGraph(Graph g) { + var paymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr); + if (paymentVar == null) return null; + + var data = ParseData(paymentVar); + if (data == null) return null; + + JsonArray? curves; + JsonObject? payment; + + if (data["mode"]?.GetValue() == "elwig") { + curves = data["curves"]?.AsArray(); + payment = data["payment"]?.AsObject(); + } else if (data["mode"]?.GetValue() == "wgmaster") { + curves = data["Kurven"]?.AsArray(); + payment = data["AuszahlungSorten"]?.AsObject(); + } else { + return null; + } + + if (curves == null || payment == null) { + return null; + } + + if (IsEditing) { + int i = 0; + foreach (var curve in curves) { + if (curve?.AsObject()?["id"]?.GetValue() == g.Id) { + curves[i] = g.ToJson(); + break; + } + i++; + } + } else if(IsCreating) { + curves.Add(g.ToJson()); + } else { + return null; + } + + EntityEntry? tr = null; + try { + paymentVar.Data = data.ToString(); + tr = Context.Update(paymentVar); + + await Context.SaveChangesAsync(); + await App.HintContextChange(); + } catch (Exception exc) { + if (tr != null) await tr.ReloadAsync(); + var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message; + if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; + MessageBox.Show(str, "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error); + } + + return g.Id; + } + private void RefreshInputs(bool validate = false) { ResetPlot(); ClearInputStates(); @@ -199,10 +260,10 @@ namespace Elwig.Windows { Graph = (Graph)g.Clone(); - GraphNumberInput.Text = Graph.Num.ToString(); - if (Graph.Type == "oe") { + GraphNumberInput.Text = Graph.Id.ToString(); + if (Graph.Mode == BillingData.CurveMode.Oe) { OechsleGraphType_Input.IsChecked = true; - } else if (Graph.Type == "kmw") { + } else if (Graph.Mode == BillingData.CurveMode.Kmw) { KmwGraphType_Input.IsChecked = true; } @@ -604,7 +665,7 @@ namespace Elwig.Windows { PriceInput.IsReadOnly = false; OechsleInput.IsReadOnly = false; InitInputs(); - FillInputs(new Graph(GraphList.Items.Count + 1, MinOechsle, MaxOechsle)); + FillInputs(new Graph(GraphList.Items.Count + 1, BillingData.CurveMode.Oe, MinOechsle, MaxOechsle)); //TODO not hardcode oe EnableOptionButtons(); } @@ -629,10 +690,10 @@ namespace Elwig.Windows { if (g == null) return; var r = MessageBox.Show( - $"Soll der Graph {g.Num} (verwendet in folgenden Verträgen: {g.Contracts}) wirklich unwiderruflich gelöscht werden?", + $"Soll der Graph {g.Id} (verwendet in folgenden Verträgen: {g.Contracts}) wirklich unwiderruflich gelöscht werden?", "Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); if (r == MessageBoxResult.Yes) { - bool success = await RemoveGraph(g.Num); + bool success = await RemoveGraph(g.Id); if (!success) { MessageBox.Show("Der Graph konnte nicht gelöscht werden", "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error); } @@ -658,50 +719,6 @@ namespace Elwig.Windows { GraphList.SelectedIndex = index.Value; } - private async Task UpdateGraph(Graph g) { - List paymentVars = await Context.PaymentVariants.Where(p => p.Year == Year && p.AvNr == AvNr).ToListAsync(); - - if (paymentVars.Count != 1) { - return null; - } - - PaymentVar paymentVar = paymentVars[0]; - var data = JsonNode.Parse(paymentVar.Data).AsObject(); - - var auszahlungsSorten = data["AuszahlungSorten"]; - if (auszahlungsSorten == null) { - return null; - } - - var Graphs = auszahlungsSorten["Kurven"].AsArray(); - if (Graphs == null) { - return null; - } - - if (IsEditing) { - Graphs[g.Num - 1] = g.ToJson(); - } else if(IsCreating) { - Graphs.Add(g.ToJson()); - } else { - return null; - } - - EntityEntry? tr = null; - try { - paymentVar.Data = data.ToString(); - tr = Context.Update(paymentVar); - - await Context.SaveChangesAsync(); - } catch (Exception exc) { - if (tr != null) await tr.ReloadAsync(); - var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message; - if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; - MessageBox.Show(str, "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error); - } - - return g.Num - 1; - } - private void ResetButton_Click(object sender, RoutedEventArgs e) { if (IsEditing) { RefreshInputs();