ChartWindow: wip

This commit is contained in:
2024-01-17 22:33:20 +01:00
parent b6fd62f8ca
commit 4dd036babd
4 changed files with 257 additions and 476 deletions

View File

@ -17,10 +17,11 @@ using ScottPlot;
using ScottPlot.Plottable;
namespace Elwig.Windows {
public partial class ChartWindow : AdministrationWindow {
public partial class ChartWindow : ContextWindow {
public readonly int Year;
public readonly int AvNr;
private readonly PaymentVar PaymentVar;
private ScatterPlot OechslePricePlotScatter;
private MarkerPlot HighlightedPoint;
@ -38,21 +39,18 @@ namespace Elwig.Windows {
private const int MinOechsle = 50;
private const int MaxOechsle = 140;
private Graph? Graph;
private List<GraphEntry> GraphEntries = [];
private GraphEntry? SelectedGraphEntry;
public ChartWindow(int year, int avnr) {
InitializeComponent();
Year = year;
AvNr = avnr;
var v = Context.PaymentVariants.Find(year, avnr);
Title = $"{v?.Name} - Lese {year} - Elwig";
ExemptInputs = [
GraphList, OechsleInput, PriceInput, FreeZoomInput, GradationLinesInput, TooltipInput
];
PaymentVar = Context.PaymentVariants.Find(year, avnr) ?? throw new ArgumentException("PaymentVar not found");
Title = $"{PaymentVar?.Name} - Lese {year} - Elwig";
}
private void Window_Loaded(object sender, RoutedEventArgs evt) {
LockInputs();
OechslePricePlot.IsEnabled = false;
}
@ -70,20 +68,27 @@ namespace Elwig.Windows {
}
private async Task RefreshGraphListQuery(bool updateSort = false) {
var paymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr);
if (paymentVar == null) return;
var data = ParseData(paymentVar);
var data = ParseData(PaymentVar);
if (data == null) return;
var curves = BillingData.GetCurves(data, BillingData.CalculationMode.Elwig);
List<Graph> graphs = [];
foreach (var (id, curve) in curves) {
graphs.Add(new Graph(id, curve.Mode, curve.Normal, MinOechsle, MaxOechsle));
GraphEntries.Add(new GraphEntry(id, curve.Mode, curve.Normal, MinOechsle, MaxOechsle));
}
ControlUtils.RenewItemsSource(GraphList, graphs, g => (g as Graph)?.Id);
if (graphs.Count == 1) {
var attrVariants = Context.DeliveryParts
.Where(d => d.Year == Year)
.Select(d => $"{d.SortId}{d.AttrId}")
.Distinct()
.ToList()
.Union(Context.WineVarieties.Select(v => v.SortId))
.Order()
.ToList();
ControlUtils.RenewItemsSource(AppliedInput, attrVariants, g => (g as GraphEntry)?.Id);
ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.Id);
if (GraphEntries.Count == 1) {
GraphList.SelectedIndex = 0;
}
@ -91,201 +96,46 @@ namespace Elwig.Windows {
}
private string ParseContracts(JsonObject auszahlungsSorten, int num) {
List<string> contracts = [];
foreach (var sorte in auszahlungsSorten) {
if (sorte.Key == "Kurven") continue;
foreach (var attribut in sorte.Value.AsObject()) {
foreach (var bindung in attribut.Value.AsObject()) {
if ((int)bindung.Value.AsValue() == num) {
contracts.Add($"{sorte.Key}/{attribut.Key}/{bindung.Key}");
}
}
}
}
return string.Join("\n", contracts);
}
private async Task<bool> RemoveGraph(int num) {
var paymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr);
if (paymentVar == null) return false;
var data = ParseData(paymentVar);
if (data == null) return false;
MessageBox.Show("1");
JsonArray? curves;
JsonObject? payment;
if (data["mode"]?.GetValue<string>() == "elwig") {
curves = data["curves"]?.AsArray();
payment = data["payment"]?.AsObject();
} else if (data["mode"]?.GetValue<string>() == "wgmaster") {
curves = data["Kurven"]?.AsArray();
payment = data["AuszahlungSorten"]?.AsObject();
} else {
return false;
}
MessageBox.Show("2");
if (curves == null || payment == null) {
return false;
}
MessageBox.Show("3");
foreach (var curve in curves) {
MessageBox.Show("LOOP");
if (curve?.AsObject()?["id"]?.GetValue<int>() == num) {
MessageBox.Show(curve.ToJsonString());
curves.Remove(curve);
break;
}
}
MessageBox.Show("4");
var keysToRemove = new List<string>();
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<PaymentVar>? 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 true;
}
private async Task<int?> 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<string>() == "elwig") {
curves = data["curves"]?.AsArray();
payment = data["payment"]?.AsObject();
} else if (data["mode"]?.GetValue<string>() == "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<int>() == g.Id) {
curves[i] = g.ToJson();
break;
}
i++;
}
} else if(IsCreating) {
curves.Add(g.ToJson());
} else {
return null;
}
EntityEntry<PaymentVar>? 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;
return "";
}
private void RefreshInputs(bool validate = false) {
ResetPlot();
ClearInputStates();
if (GraphList.SelectedItem is Graph g) {
EditButton.IsEnabled = true;
DeleteButton.IsEnabled = true;
EnableOptionButtons();
FillInputs(g);
} else {
EditButton.IsEnabled = false;
if (!PaymentVar.TestVariant) {
AddButton.IsEnabled = false;
CopyButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
OechsleInput.IsReadOnly = true;
PriceInput.IsReadOnly = true;
} else if (SelectedGraphEntry != null) {
CopyButton.IsEnabled = true;
DeleteButton.IsEnabled = true;
OechsleInput.IsReadOnly = false;
EnableOptionButtons();
FillInputs();
} else {
CopyButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
OechsleInput.IsReadOnly = true;
DisableOptionButtons();
ClearOriginalValues();
ClearInputs(validate);
ClearInputStates();
}
GC.Collect();
}
private void FillInputs(Graph g) {
ClearOriginalValues();
Graph = (Graph)g.Clone();
GraphNumberInput.Text = Graph.Id.ToString();
if (Graph.Mode == BillingData.CurveMode.Oe) {
OechsleGraphType_Input.IsChecked = true;
} else if (Graph.Mode == BillingData.CurveMode.Kmw) {
KmwGraphType_Input.IsChecked = true;
}
private void FillInputs() {
GraphNum.Text = SelectedGraphEntry.Id.ToString();
InitPlot();
OechslePricePlot.IsEnabled = true;
FinishInputFilling();
}
private void InitInputs() {
GraphNumberInput.Text = (GraphList.Items.Count + 1).ToString();
OechsleGraphType_Input.IsChecked = true;
FinishInputFilling();
}
protected override async Task OnRenewContext() {
await base.OnRenewContext();
await RefreshGraphList();
}
private void InitPlot() {
OechslePricePlotScatter = OechslePricePlot.Plot.AddScatter(Graph.DataX, Graph.DataY);
OechslePricePlotScatter = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry.DataGraph.DataX, SelectedGraphEntry.DataGraph.DataY);
OechslePricePlot.Configuration.DoubleClickBenchmark = false;
OechslePricePlotScatter.LineColor = Color.Blue;
@ -326,7 +176,6 @@ namespace Elwig.Windows {
}
private void ResetPlot() {
Graph = null;
PrimaryMarkedPointIndex = -1;
OechslePricePlot.Plot.Remove(OechslePricePlotScatter);
OechslePricePlot.Plot.Clear();
@ -341,16 +190,12 @@ namespace Elwig.Windows {
}
private void FlattenGraph(int begin, int end, double value) {
for (int i = begin; i <= end; i++) {
Graph.DataY[i] = value;
}
SelectedGraphEntry.DataGraph.FlattenGraph(begin, end, value);
OechslePricePlot.Render();
}
private void LinearIncreaseGraph(int begin, int end, double inc) {
for (int i = begin; i < end; i++) {
Graph.DataY[i + 1] = Graph.DataY[i] + inc;
}
SelectedGraphEntry.DataGraph.LinearIncreaseGraph(begin, end, inc);
OechslePricePlot.Render();
}
@ -441,8 +286,6 @@ namespace Elwig.Windows {
}
private void OechsleInput_TextChanged(object sender, TextChangedEventArgs evt) {
IntegerInput_TextChanged(sender, evt);
bool success = int.TryParse(OechsleInput.Text, out int oechsle);
SecondaryMarkedPointIndex = -1;
@ -451,12 +294,13 @@ namespace Elwig.Windows {
if (success) {
if (oechsle >= MinOechsle && oechsle <= MaxOechsle) {
PrimaryMarkedPointIndex = oechsle - MinOechsle;
ChangeMarker(PrimaryMarkedPoint, true, Graph.DataX[PrimaryMarkedPointIndex], Graph.DataY[PrimaryMarkedPointIndex]);
ChangeMarker(PrimaryMarkedPoint, true, SelectedGraphEntry.DataGraph.DataX[PrimaryMarkedPointIndex], SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex]);
PriceInput.Text = Graph.DataY[PrimaryMarkedPointIndex].ToString();
PriceInput.Text = SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex].ToString();
if (IsEditing || IsCreating) EnableActionButtons();
EnableActionButtons();
OechslePricePlot.Render();
PriceInput.IsReadOnly = false;
return;
}
}
@ -466,6 +310,7 @@ namespace Elwig.Windows {
DisableActionButtons();
PriceInput.Text = "";
OechslePricePlot.Render();
PriceInput.IsReadOnly = true;
}
private void PriceInput_TextChanged(object sender, RoutedEventArgs evt) {
@ -473,10 +318,8 @@ namespace Elwig.Windows {
bool success = Double.TryParse(PriceInput.Text, out double price);
if (success) {
Graph.DataY[PrimaryMarkedPointIndex] = price;
SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex] = price;
PrimaryMarkedPoint.Y = price;
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
OechslePricePlot.Refresh();
}
}
@ -486,18 +329,14 @@ namespace Elwig.Windows {
if (PrimaryMarkedPointIndex == -1) {
return;
}
FlattenGraph(0, PrimaryMarkedPointIndex, Graph.DataY[PrimaryMarkedPointIndex]);
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
FlattenGraph(0, PrimaryMarkedPointIndex, SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex]);
}
private void RightFlatButton_Click(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPointIndex == -1) {
return;
}
FlattenGraph(PrimaryMarkedPointIndex, Graph.DataY.Length - 1, Graph.DataY[PrimaryMarkedPointIndex]);
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
FlattenGraph(PrimaryMarkedPointIndex, SelectedGraphEntry.DataGraph.DataY.Length - 1, SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex]);
}
private void InterpolateButton_Click(object sender, RoutedEventArgs evt) {
@ -507,13 +346,11 @@ namespace Elwig.Windows {
}
var (lowIndex, highIndex) = PrimaryMarkedPointIndex < SecondaryMarkedPointIndex ? (PrimaryMarkedPointIndex, SecondaryMarkedPointIndex): (SecondaryMarkedPointIndex, PrimaryMarkedPointIndex);
double step = (Graph.DataY[highIndex] - Graph.DataY[lowIndex]) / steps;
double step = (SelectedGraphEntry.DataGraph.DataY[highIndex] - SelectedGraphEntry.DataGraph.DataY[lowIndex]) / steps;
for (int i = lowIndex; i < highIndex - 1; i++) {
Graph.DataY[i + 1] = Math.Round(Graph.DataY[i] + step, 4); // TODO richtig runden
SelectedGraphEntry.DataGraph.DataY[i + 1] = Math.Round(SelectedGraphEntry.DataGraph.DataY[i] + step, 4); // TODO richtig runden
}
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
}
private void LinearIncreaseButton_Click(object sender, RoutedEventArgs e) {
@ -524,23 +361,21 @@ namespace Elwig.Windows {
if (priceIncrease == null) {
return;
}
LinearIncreaseGraph(PrimaryMarkedPointIndex, Graph.DataY.Length - 1, priceIncrease.Value);
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
LinearIncreaseGraph(PrimaryMarkedPointIndex, SelectedGraphEntry.DataGraph.DataY.Length - 1, priceIncrease.Value);
}
private void OechslePricePlot_MouseDown(object sender, MouseEventArgs e) {
if (!IsCreating && GraphList.SelectedItem == null) {
if (GraphList.SelectedItem == null) {
return;
}
if (HoverActive) {
if ((IsEditing || IsCreating) && Keyboard.IsKeyDown(Key.LeftCtrl)) {
if (PaymentVar.TestVariant && Keyboard.IsKeyDown(Key.LeftCtrl)) {
if (PrimaryMarkedPointIndex == -1) {
return;
}
SecondaryMarkedPointIndex = HighlightedIndex;
ChangeMarker(SecondaryMarkedPoint, true, Graph.DataX[SecondaryMarkedPointIndex], Graph.DataY[SecondaryMarkedPointIndex]);
ChangeMarker(SecondaryMarkedPoint, true, SelectedGraphEntry.DataGraph.DataX[SecondaryMarkedPointIndex], SelectedGraphEntry.DataGraph.DataY[SecondaryMarkedPointIndex]);
InterpolateButton.IsEnabled = true;
@ -548,12 +383,12 @@ namespace Elwig.Windows {
}
PrimaryMarkedPointIndex = HighlightedIndex;
ChangeMarker(PrimaryMarkedPoint, true, Graph.DataX[PrimaryMarkedPointIndex], Graph.DataY[PrimaryMarkedPointIndex]);
ChangeMarker(PrimaryMarkedPoint, true, SelectedGraphEntry.DataGraph.DataX[PrimaryMarkedPointIndex], SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex]);
OechsleInput.Text = Graph.DataX[HighlightedIndex].ToString();
PriceInput.Text = Graph.DataY[HighlightedIndex].ToString();
OechsleInput.Text = SelectedGraphEntry.DataGraph.DataX[HighlightedIndex].ToString();
PriceInput.Text = SelectedGraphEntry.DataGraph.DataY[HighlightedIndex].ToString();
if (IsEditing || IsCreating) {
if (PaymentVar.TestVariant) {
EnableActionButtons();
}
} else {
@ -570,7 +405,7 @@ namespace Elwig.Windows {
}
private void OechslePricePlot_MouseMove(object sender, MouseEventArgs e) {
if (!IsCreating && GraphList.SelectedItem == null) {
if (GraphList.SelectedItem == null) {
return;
}
@ -607,144 +442,45 @@ namespace Elwig.Windows {
}
}
override protected void UpdateButtons() {
if (!IsEditing && !IsCreating) return;
bool ch = HasChanged, v = IsValid;
private int getMaxGraphId() {
return GraphEntries.Count == 0 ? 0 : GraphEntries.Select(g => g.Id).Max();
}
private void DisableNewEditDeleteButtons() {
NewButton.IsEnabled = false;
EditButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
private void AddButton_Click(object sender, RoutedEventArgs e) {
GraphEntry newGraphEntry = new(getMaxGraphId() + 1, BillingData.CurveMode.Oe, MinOechsle, MaxOechsle);
GraphEntries.Add(newGraphEntry);
GraphList.Items.Refresh();
GraphList.SelectedItem = newGraphEntry;
}
private void EnableNewEditDeleteButtons() {
NewButton.IsEnabled = true;
EditButton.IsEnabled = GraphList.SelectedItem != null;
DeleteButton.IsEnabled = GraphList.SelectedItem != null;
private void CopyButton_Click(object sender, RoutedEventArgs e) {
if (SelectedGraphEntry == null) return;
GraphEntry newGraphEntry = SelectedGraphEntry.Copy(getMaxGraphId() + 1);
GraphEntries.Add(newGraphEntry);
GraphList.Items.Refresh();
GraphList.SelectedItem = newGraphEntry;
}
private void ShowSaveResetCancelButtons() {
SaveButton.IsEnabled = false;
ResetButton.IsEnabled = false;
CancelButton.IsEnabled = true;
SaveButton.Visibility = Visibility.Visible;
ResetButton.Visibility = Visibility.Visible;
CancelButton.Visibility = Visibility.Visible;
}
private void HideSaveResetCancelButtons() {
SaveButton.IsEnabled = false;
ResetButton.IsEnabled = false;
CancelButton.IsEnabled = false;
SaveButton.Visibility = Visibility.Hidden;
ResetButton.Visibility = Visibility.Hidden;
CancelButton.Visibility = Visibility.Hidden;
}
private void ShowNewEditDeleteButtons() {
EnableNewEditDeleteButtons();
NewButton.Visibility = Visibility.Visible;
EditButton.Visibility = Visibility.Visible;
DeleteButton.Visibility = Visibility.Visible;
}
private void HideNewEditDeleteButtons() {
DisableNewEditDeleteButtons();
NewButton.Visibility = Visibility.Hidden;
EditButton.Visibility = Visibility.Hidden;
DeleteButton.Visibility = Visibility.Hidden;
}
private void NewButton_Click(object sender, RoutedEventArgs e) {
IsCreating = true;
GraphList.IsEnabled = false;
GraphList.SelectedItem = null;
HideNewEditDeleteButtons();
ShowSaveResetCancelButtons();
UnlockInputs();
PriceInput.IsReadOnly = false;
OechsleInput.IsReadOnly = false;
InitInputs();
FillInputs(new Graph(GraphList.Items.Count + 1, BillingData.CurveMode.Oe, MinOechsle, MaxOechsle)); //TODO not hardcode oe
EnableOptionButtons();
}
private void EditButton_Click(object sender, RoutedEventArgs e) {
if (GraphList.SelectedItem == null) {
return;
}
IsEditing = true;
GraphList.IsEnabled = false;
HideNewEditDeleteButtons();
ShowSaveResetCancelButtons();
UnlockInputs();
PriceInput.IsReadOnly = false;
OechsleInput.IsReadOnly = false;
if (PrimaryMarkedPointIndex != -1) EnableActionButtons();
}
private async void DeleteButton_Click(object sender, RoutedEventArgs e) {
Graph g = (Graph)GraphList.SelectedItem;
if (g == null) return;
private void DeleteButton_Click(object sender, RoutedEventArgs e) {
if (SelectedGraphEntry == null) return;
var r = MessageBox.Show(
$"Soll der Graph {g.Id} (verwendet in folgenden Verträgen: {g.Contracts}) wirklich unwiderruflich gelöscht werden?",
$"Soll der Graph {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.Contracts}) wirklich gelöscht werden?",
"Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r == MessageBoxResult.Yes) {
bool success = await RemoveGraph(g.Id);
if (!success) {
MessageBox.Show("Der Graph konnte nicht gelöscht werden", "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
}
await RefreshGraphList();
GraphEntries.Remove(SelectedGraphEntry);
GraphList.Items.Refresh();
}
}
private async void SaveButton_Click(object sender, RoutedEventArgs e) {
int? index = await UpdateGraph(Graph);
if (index == null) {
MessageBox.Show("Der Graph konnte nicht gespeichert werden", "Graph speichern", MessageBoxButton.OK, MessageBoxImage.Error);
}
IsEditing = false;
IsCreating = false;
GraphList.IsEnabled = true;
HideSaveResetCancelButtons();
ShowNewEditDeleteButtons();
LockInputs();
PriceInput.IsReadOnly = true;
OechsleInput.IsReadOnly = true;
await RefreshGraphList();
GraphList.SelectedIndex = index.Value;
private void SaveButton_Click(object sender, RoutedEventArgs e) {
//TODO SAVE
}
private void ResetButton_Click(object sender, RoutedEventArgs e) {
if (IsEditing) {
RefreshInputs();
} else if (IsCreating) {
InitInputs();
}
UpdateButtons();
}
private void CancelButton_Click(object sender, RoutedEventArgs e) {
IsEditing = false;
IsCreating = false;
GraphList.IsEnabled = true;
HideSaveResetCancelButtons();
ShowNewEditDeleteButtons();
DisableActionButtons();
RefreshInputs();
PriceInput.Text = "";
OechsleInput.Text = "";
ClearInputStates();
LockInputs();
PriceInput.IsReadOnly = true;
OechsleInput.IsReadOnly = true;
}
private void GraphList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
private void GraphList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
SelectedGraphEntry = (GraphEntry)GraphList.SelectedItem;
RefreshInputs();
//var x = OechslePricePlot.Plot.GetPlottables().OfType<ScatterPlot>();
@ -759,11 +495,7 @@ namespace Elwig.Windows {
}
private void GraphNumberInput_TextChanged(object sender, TextChangedEventArgs e) {
}
private void GraphNumberInput_LostFocus(object sender, RoutedEventArgs e) {
private void GebundenBonus_TextChanged(object sender, TextChangedEventArgs evt) {
}
}