Move path logic into Path class
Test / Run tests (push) Successful in 43s

This commit is contained in:
2026-10-15 23:45:32 +02:00
parent c005378368
commit d8c2292b24
9 changed files with 345 additions and 218 deletions
+33 -54
View File
@@ -2,7 +2,6 @@ using PamhagenSysCtrl.Helpers.Pipeline;
using PamhagenSysCtrl.Helpers.Plc;
using System.IO;
using System.Windows;
using System.Windows.Media;
namespace PamhagenSysCtrl.Helpers {
public class PamhagenPlant : IDisposable {
@@ -128,6 +127,12 @@ namespace PamhagenSysCtrl.Helpers {
if (Keyboard == null) {
try {
Keyboard = new();
Keyboard.Error += (s, e) => {
try {
Keyboard.Dispose();
} catch { }
Keyboard = null;
};
Keyboard.KeyDown += Keyboard_KeyDown;
Keyboard.KeysChanged += Keyboard_KeysChanged;
Keyboard.SetFashFrequency(250);
@@ -147,63 +152,45 @@ namespace PamhagenSysCtrl.Helpers {
// TODO update all keys
k.SetBacklight(ShortcutKey.START_REBLER, State.Rebler_IsActive ? Color.FromRgb(0, 255, 0) : State.Auger1_IsActive ? Color.FromRgb(255, 255, 0) : State.WasteDisposal_IsActive ? Color.FromRgb(32, 32, 4) : Color.FromRgb(4, 32, 4));
k.SetBacklight(ShortcutKey.STOP_REBLER, !State.Rebler_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
k.SetBacklight(ShortcutKey.START_REBLER, State.Rebler_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen);
k.SetBacklight(ShortcutKey.STOP_REBLER, !State.Rebler_IsActive ? Xbe24Keyboard.Red : Xbe24Keyboard.LightRed);
k.SetBacklight(ShortcutKey.START_TROUGH_AUGER, !State.TroughAuger_HasClearance ? k.IsKeyPressed(ShortcutKey.START_TROUGH_AUGER) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : State.TroughAuger_IsActive ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4));
k.SetBacklight(ShortcutKey.STOP_TROUGH_AUGER, !State.TroughAuger_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
k.SetBacklight(ShortcutKey.START_TROUGH_AUGER, !State.TroughAuger_HasClearance ? k.IsKeyPressed(ShortcutKey.START_TROUGH_AUGER) ? Xbe24Keyboard.Orange : Xbe24Keyboard.LightRed : State.TroughAuger_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen);
k.SetBacklight(ShortcutKey.STOP_TROUGH_AUGER, !State.TroughAuger_IsActive ? Xbe24Keyboard.Red : Xbe24Keyboard.LightRed);
k.SetBacklight(ShortcutKey.SELECT_MW2, State.MW2_WantSelected || State.MW2_IsSelected ? Color.FromRgb(0, 0, 255) : Color.FromRgb(4, 4, 16), State.MW2_WantSelected && !State.MW2_IsSelected);
k.SetBacklight(ShortcutKey.SELECT_MW1, State.MW1_WantSelected || State.MW1_IsSelected ? Color.FromRgb(0, 0, 255) : Color.FromRgb(4, 4, 16), State.MW1_WantSelected && !State.MW1_IsSelected);
k.SetBacklight(ShortcutKey.SELECT_MW2, State.MW2_WantSelected || State.MW2_IsSelected ? Xbe24Keyboard.Blue : Xbe24Keyboard.LightBlue, State.MW2_WantSelected && !State.MW2_IsSelected);
k.SetBacklight(ShortcutKey.SELECT_MW1, State.MW1_WantSelected || State.MW1_IsSelected ? Xbe24Keyboard.Blue : Xbe24Keyboard.LightBlue, State.MW1_WantSelected && !State.MW1_IsSelected);
bool prepMP1 = false, prepMP2 = false, prepP12 = false, prepP3 = false, prepP4 = false, prepP5 = false, prepP6 = false;
bool hiOffMP1 = false, hiOffMP2 = false, hiOffP12 = false, hiOffP3 = false, hiOffP4 = false, hiOffP5 = false, hiOffP6 = false;
Dictionary<Pump, bool> pumpHighlightOff = [];
foreach (var (key, d) in Graph.PathShortcuts) {
if (App.Config.MapKey(key) is not int idx)
continue;
var isRunning = d.Pump.IsActive;
// TODO consider intermediate
if (plant.Graph.SelectedPaths.Select(p => (Pipeline.Path?)p).FirstOrDefault(p => p?.Start == d.Source && p?.Hops.Last().Node == d.Sink) is Pipeline.Path path) {
// TODO also account for valves guarding path
var isReady = path.Hops.All(h => h.Node is not ControlledValve v || v.IsOpen == v.WantOpen);
if (!isReady) {
if (d.Pump == Graph.MP1) prepMP1 = true;
if (d.Pump == Graph.MP2) prepMP2 = true;
if (d.Pump == Graph.P12) prepP12 = true;
if (d.Pump == Graph.P3) prepP3 = true;
if (d.Pump == Graph.P4) prepP4 = true;
if (d.Pump == Graph.P5) prepP5 = true;
if (d.Pump == Graph.P6) prepP6 = true;
}
var isActive = d.Pump.IsActive;
var paths = plant.Graph.SelectedPaths.Select(p => (Pipeline.Path?)p)
.Where(p => p?.Matches(d.Source, d.Intermediate, d.Sink) ?? false);
if (paths.FirstOrDefault() is Pipeline.Path path) {
var isReady = path.IsReady;
var isDefault = !path.Hops.SkipLast(1).Any(h => h.Node is not Valve && h.Node is not PipeJoin && h.Node is not Pump);
k.SetBacklight(idx, isRunning ? isDefault ? Color.FromRgb(0, 255, 255) : Color.FromRgb(255, 64, 255) : isDefault ? Color.FromRgb(0, 0, 255) : Color.FromRgb(128, 0, 128), !isReady);
k.SetBacklight(idx, isActive ? isDefault ? Xbe24Keyboard.Cyan : Xbe24Keyboard.Purple : isDefault ? Xbe24Keyboard.Blue : Xbe24Keyboard.DarkPurple, !isReady);
} else {
var isFree = Graph.GetFreePath([d.Source, d.Sink], overrideStart: true) != null;
if (isRunning && k.IsKeyPressed(idx)) {
if (d.Pump == Graph.MP1) hiOffMP1 = true;
if (d.Pump == Graph.MP2) hiOffMP2 = true;
if (d.Pump == Graph.P12) hiOffP12 = true;
if (d.Pump == Graph.P3) hiOffP3 = true;
if (d.Pump == Graph.P4) hiOffP4 = true;
if (d.Pump == Graph.P5) hiOffP5 = true;
if (d.Pump == Graph.P6) hiOffP6 = true;
}
k.SetBacklight(idx, isRunning ? k.IsKeyPressed(idx) ? Color.FromRgb(255, 16, 0) : Color.FromRgb(4, 4, 4) : isFree ? Color.FromRgb(8, 8, 32) : k.IsKeyPressed(idx) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(4, 4, 4));
if (isActive && k.IsKeyPressed(idx)) pumpHighlightOff[d.Pump] = true;
k.SetBacklight(idx, isActive ? k.IsKeyPressed(idx) ? Xbe24Keyboard.Orange : Xbe24Keyboard.Neutral : isFree ? Xbe24Keyboard.LightBlue : k.IsKeyPressed(idx) ? Xbe24Keyboard.Orange : Xbe24Keyboard.Neutral);
}
}
if (!plant.State.MP2_HasPathClearance && plant.State.MP2_HasDryRunClearance && prepMP2) {
k.SetBacklight(ShortcutKey.START_MP2, Color.FromRgb(4, 32, 4), true);
if (!plant.State.MP2_HasPathClearance && plant.State.MP2_HasDryRunClearance && plant.State.MP2_WantsPathClearance) {
k.SetBacklight(ShortcutKey.START_MP2, plant.State.MP2_WantActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen, true);
} else {
k.SetBacklight(ShortcutKey.START_MP2, !State.MP2_HasClearance ? k.IsKeyPressed(ShortcutKey.START_MP2) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : State.MP2_IsActive ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4));
k.SetBacklight(ShortcutKey.START_MP2, !State.MP2_HasClearance ? k.IsKeyPressed(ShortcutKey.START_MP2) ? Xbe24Keyboard.Orange : Xbe24Keyboard.LightRed : State.MP2_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen);
}
if (!plant.State.MP1_HasPathClearance && plant.State.MP1_HasDryRunClearance && prepMP1) {
k.SetBacklight(ShortcutKey.START_MP1, Color.FromRgb(4, 32, 4), true);
if (!plant.State.MP1_HasPathClearance && plant.State.MP1_HasDryRunClearance && plant.State.MP1_WantsPathClearance) {
k.SetBacklight(ShortcutKey.START_MP1, plant.State.MP1_WantActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen, true);
} else {
k.SetBacklight(ShortcutKey.START_MP1, !State.MP1_HasClearance ? k.IsKeyPressed(ShortcutKey.START_MP1) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : State.MP1_IsActive ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4));
k.SetBacklight(ShortcutKey.START_MP1, !State.MP1_HasClearance ? k.IsKeyPressed(ShortcutKey.START_MP1) ? Xbe24Keyboard.Orange : Xbe24Keyboard.LightRed : State.MP1_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen);
}
k.SetBacklight(ShortcutKey.STOP_MP2, hiOffMP2 ? Color.FromRgb(255, 32, 0) : !State.MP2_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
k.SetBacklight(ShortcutKey.STOP_MP1, hiOffMP1 ? Color.FromRgb(255, 32, 0) : !State.MP1_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
k.SetBacklight(ShortcutKey.STOP_MP2, pumpHighlightOff.GetValueOrDefault(Graph.MP2) ? Xbe24Keyboard.Orange : !State.MP2_IsActive ? Xbe24Keyboard.Red : Xbe24Keyboard.LightRed);
k.SetBacklight(ShortcutKey.STOP_MP1, pumpHighlightOff.GetValueOrDefault(Graph.MP1) ? Xbe24Keyboard.Orange : !State.MP1_IsActive ? Xbe24Keyboard.Red : Xbe24Keyboard.LightRed);
}
public void Dispose() {
@@ -257,7 +244,7 @@ namespace PamhagenSysCtrl.Helpers {
App.Plant?.Plc?.CloseV(i);
}
foreach (var p in add) {
if (p.Hops.Any(h => h.Node is ControlledValve v && v.IsLocked)) continue;
if (p.InnerValves.Any(v => v.IsLocked)) continue;
Graph.AddPath(p);
}
}
@@ -278,10 +265,10 @@ namespace PamhagenSysCtrl.Helpers {
public void FastSelect(ISource source, INode? intermediate, ISink sink) {
if (Graph.SelectedPaths.Select(p => (Pipeline.Path?)p).FirstOrDefault(p => p?.Start == source, null) is Pipeline.Path p1) {
if (p1.Hops.Any(h => h.Node is Pump p && p.IsActive))
if (p1.HasActivePump)
throw new NoClearanceException("Pumpe aktiv");
Graph.RemovePath(p1);
if (p1.Hops.Last().Node == sink && (intermediate == null || p1.Hops.Any(h => h.Node == intermediate)))
if (p1.End == sink && (intermediate == null || p1.Contains(intermediate)))
return;
}
if (Graph.GetFreePath(intermediate == null ? [source, sink] : [source, intermediate, sink]) is Pipeline.Path p2) {
@@ -295,15 +282,7 @@ namespace PamhagenSysCtrl.Helpers {
if (key == ShortcutKey.START_REBLER) {
Plc.StartRebler();
} else if (key == ShortcutKey.STOP_REBLER) {
if (State.Rebler_IsActive) {
Plc.StopRebler();
} else {
Plc.StopAuger1();
if (!State.PressCrossAuger_IsActive) {
Plc.StopAuger2();
Plc.StopAuger3();
}
}
Plc.StopRebler();
} else if (key == ShortcutKey.START_TROUGH_AUGER) {
Plc.StartTroughAuger();
} else if (key == ShortcutKey.STOP_TROUGH_AUGER) {