From 7b95cf422112e3bed0c0b534e25c3b5d0e5d88cf Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Tue, 4 Aug 2026 15:30:08 +0200 Subject: [PATCH] Add clearance logic to PamhagenPlant --- .../Helpers/NoClearanceException.cs | 4 + PamhagenSysCtrl/Helpers/PamhagenGraph.cs | 86 ++++--- PamhagenSysCtrl/Helpers/PamhagenPlant.cs | 235 +++++++++++++++++- PamhagenSysCtrl/Helpers/Pipeline/Auger.cs | 2 +- .../Helpers/Pipeline/ConveyorBelt.cs | 25 +- .../Helpers/Pipeline/EncasedAuger.cs | 27 +- .../Helpers/Pipeline/EntryTrough.cs | 27 +- PamhagenSysCtrl/Helpers/Pipeline/Pump.cs | 22 +- PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs | 7 +- .../Windows/PlantSchemeWindow.xaml.cs | 118 +++++++-- 10 files changed, 459 insertions(+), 94 deletions(-) create mode 100644 PamhagenSysCtrl/Helpers/NoClearanceException.cs diff --git a/PamhagenSysCtrl/Helpers/NoClearanceException.cs b/PamhagenSysCtrl/Helpers/NoClearanceException.cs new file mode 100644 index 0000000..4235cd8 --- /dev/null +++ b/PamhagenSysCtrl/Helpers/NoClearanceException.cs @@ -0,0 +1,4 @@ +namespace PamhagenSysCtrl.Helpers { + public class NoClearanceException(string msg) : Exception(msg) { + } +} diff --git a/PamhagenSysCtrl/Helpers/PamhagenGraph.cs b/PamhagenSysCtrl/Helpers/PamhagenGraph.cs index fb1efe4..6be80db 100644 --- a/PamhagenSysCtrl/Helpers/PamhagenGraph.cs +++ b/PamhagenSysCtrl/Helpers/PamhagenGraph.cs @@ -9,6 +9,13 @@ namespace PamhagenSysCtrl.Helpers { public readonly Trough MW1; public readonly Trough MW2; + public readonly Pump MP1; + public readonly Pump MP2; + public readonly Pump P12; + public readonly Pump P3; + public readonly Pump P4; + public readonly Pump P5; + public readonly Pump P6; public PamhagenGraph() { double mw2X = 180; @@ -38,31 +45,31 @@ namespace PamhagenSysCtrl.Helpers { var pr1X = 750; var pr2X = 900; - var trough = new EntryTrough("Auffangwanne", mw1X + 70, 100); + var trough = new EntryTrough("Auffangwanne", mw1X + 70, 100, () => App.Plant?.IsTroughAugerActive ?? false); Nodes.Add(trough); - var auger1 = new EncasedAuger("", (mw1X + mw2X) / 2 - 100, 200); - var auger2 = new EncasedAuger("Pressen-\nQuerschnecke", 40, 200, 180); - var auger3 = new EncasedAuger("", 120, 80, 135); - var belt = new ConveyorBelt("", 90, 160); + var auger1 = new EncasedAuger("", (mw1X + mw2X) / 2 - 100, 200, () => App.Plant?.IsAuger1Active ?? false); + var auger2 = new EncasedAuger("Pressen-\nQuerschnecke", 40, 200, () => App.Plant?.IsPresseQuerSchneckeActive ?? false, 180); + var auger3 = new EncasedAuger("", 120, 80, () => App.Plant?.IsAuger2Active ?? false, 135); + var belt = new ConveyorBelt("", 90, 160, () => App.Plant?.IsBeltActive ?? false); Nodes.Add(belt); Nodes.Add(auger1); Nodes.Add(auger2); Nodes.Add(auger3); - var rebler = new Rebler("Rebler", (mw1X + mw2X) / 2, 200); + var rebler = new Rebler("Rebler", (mw1X + mw2X) / 2, 200, () => App.Plant?.IsReblerActive ?? false); Nodes.Add(rebler); MW1 = new Trough("MW1", mw1X, mpY - 70, () => App.Plant?.FillLevelA1 ?? FillState.Unknown); MW2 = new Trough("MW2", mw2X, mpY - 70, () => App.Plant?.FillLevelA1 ?? FillState.Unknown); - var mp1 = new Pump("MP1", mw1X, mpY); - var mp2 = new Pump("MP2", mw2X, mpY); + MP1 = new Pump("MP1", mw1X, mpY, () => App.Plant?.IsMP1Active ?? false, () => App.Plant?.MP1HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); + MP2 = new Pump("MP2", mw2X, mpY, () => App.Plant?.IsMP2Active ?? false, () => App.Plant?.MP2HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); var x1 = new PipeJoin(mw1X, mpY + 40); var x2 = new PipeJoin(mw2X, mpY + 40); - CreateOutlet(MW1, mp1); - CreateOutlet(MW2, mp2); - CreatePipe(mp1, x1); - CreatePipe(mp2, x2); + CreateOutlet(MW1, MP1); + CreateOutlet(MW2, MP2); + CreatePipe(MP1, x1); + CreatePipe(MP2, x2); var v1 = CreateValve(1, mw1X, mpY + 70); var v2 = CreateValve(2, mw2X, mpY + 70); @@ -279,17 +286,17 @@ namespace PamhagenSysCtrl.Helpers { CreateInlet(v43, t9); var xp12 = new PipeJoin((t1X + t2X) / 2, tanksY + 80); - var p12 = new Pump("P1/2", (t1X + t2X) / 2, tanksY + 110); + P12 = new Pump("P1/2", (t1X + t2X) / 2, tanksY + 110, () => App.Plant?.IsP12Active ?? false, () => App.Plant?.P12HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); CreateOutlet(t1, xp12); CreateOutlet(t2, xp12); - CreatePipe(xp12, p12); + CreatePipe(xp12, P12); - var p3 = new Pump("P3", t3X, tanksY + 110); - var p4 = new Pump("P4", t4X, tanksY + 110); - var p5 = new Pump("P5", t5X, tanksY + 110); - CreateOutlet(t3, p3); - CreateOutlet(t4, p4); - CreateOutlet(t5, p5); + P3 = new Pump("P3", t3X, tanksY + 110, () => App.Plant?.IsP3Active ?? false, () => App.Plant?.P3HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); + P4 = new Pump("P4", t4X, tanksY + 110, () => App.Plant?.IsP4Active ?? false, () => App.Plant?.P4HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); + P5 = new Pump("P5", t5X, tanksY + 110, () => App.Plant?.IsP5Active ?? false, () => App.Plant?.P5HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); + CreateOutlet(t3, P3); + CreateOutlet(t4, P4); + CreateOutlet(t5, P5); var v44 = CreateValve(44, (t1X + t2X) / 2, tanksY + 150); var v45 = CreateValve(45, t3X, tanksY + 150); @@ -299,10 +306,10 @@ namespace PamhagenSysCtrl.Helpers { var xv44 = new PipeJoin((t1X + t2X) / 2, tanksY + 180); var xv45 = new PipeJoin(t3X, tanksY + 180); var xv47 = new PipeJoin(t4X, tanksY + 180); - CreatePipe(p12, v44); - CreatePipe(p3, v45); - CreatePipe(p4, v47); - CreatePipe(p5, v48); + CreatePipe(P12, v44); + CreatePipe(P3, v45); + CreatePipe(P4, v47); + CreatePipe(P5, v48); CreatePipe(v44, xv44); CreatePipe(v45, xv45); CreatePipe(v47, xv47); @@ -316,14 +323,14 @@ namespace PamhagenSysCtrl.Helpers { var xt6 = new PipeJoin(t6X, tanksY + 110); var xt7 = new PipeJoin(t7X, tanksY + 110); var xt8 = new PipeJoin(t8X, tanksY + 110); - var p6 = new Pump("P6", t6X, tanksY + 150); + P6 = new Pump("P6", t6X, tanksY + 150, () => App.Plant?.IsP6Active ?? false, () => App.Plant?.P6HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); CreateOutlet(t6, xt6); CreateOutlet(t7, xt7); CreateOutlet(t8, xt8); CreateOutlet(t9, xt8); CreatePipe(xt8, xt7); CreatePipe(xt7, xt6); - CreatePipe(xt6, p6); + CreatePipe(xt6, P6); var v49 = CreateValve(49, t4X, tanksY + 220); CreatePipe(xv47, v49); @@ -346,7 +353,7 @@ namespace PamhagenSysCtrl.Helpers { CreatePipe(v6, xp1, true); CreatePipe(v8, xp2, true); CreatePipe(v49, xp3, true); - CreatePipe(p6, xp4, true); + CreatePipe(P6, xp4, true); CreatePipe(xp1, v51); CreatePipe(xp1, v55); CreatePipe(xp2, v52); @@ -367,7 +374,7 @@ namespace PamhagenSysCtrl.Helpers { } protected static Valve CreateValve(int n, double x, double y) { - return new(n, x, y, () => App.Plant?.IsValveOpen(4) ?? false, () => App.Plant?.WantValveOpen(4) ?? false); + return new(n, x, y, () => App.Plant?.IsValveOpen(n) ?? false, () => App.Plant?.WantValveOpen(n) ?? false); } protected static Tank CreateTank(int n, double x, double y, int capacity) { @@ -400,10 +407,10 @@ namespace PamhagenSysCtrl.Helpers { public void AddPath(Path path) { _selectedPaths.Add(path); - UpdateValvesAdjacientToPath(path, true); + UpdateValvesAdjacientToPath(path, true, false); if (App.Plant is PamhagenPlant plant) { - foreach (var (edge, _) in path.Hops) { - if (edge is Valve v) { + foreach (var (_, node) in path.Hops) { + if (node is Valve v) { plant.OpenV(v.Nr); } } @@ -416,8 +423,8 @@ namespace PamhagenSysCtrl.Helpers { UpdateValvesAdjacientToPath(path, false); foreach (var p in _selectedPaths) UpdateValvesAdjacientToPath(p, true); if (App.Plant is PamhagenPlant plant) { - foreach (var (edge, _) in path.Hops) { - if (edge is Valve v) { + foreach (var (_, node) in path.Hops) { + if (node is Valve v) { plant.CloseV(v.Nr); } } @@ -425,9 +432,18 @@ namespace PamhagenSysCtrl.Helpers { } } - private void UpdateValvesAdjacientToPath(Path path, bool locked) { + private void UpdateValvesAdjacientToPath(Path path, bool locked, bool? wantOpen = null) { foreach (var (edge, node) in path.Hops) { - TraverseSubgraph(node, valveAction: (v) => v.IsLocked = locked); + TraverseSubgraph(node, valveAction: (v) => { + v.IsLocked = locked; + if (wantOpen.HasValue) { + if (wantOpen.Value) { + App.Plant?.OpenV(v.Nr); + } else { + App.Plant?.CloseV(v.Nr); + } + } + }); } } diff --git a/PamhagenSysCtrl/Helpers/PamhagenPlant.cs b/PamhagenSysCtrl/Helpers/PamhagenPlant.cs index 474a5d6..c8fc4a8 100644 --- a/PamhagenSysCtrl/Helpers/PamhagenPlant.cs +++ b/PamhagenSysCtrl/Helpers/PamhagenPlant.cs @@ -1,4 +1,5 @@ -using System.IO; +using PamhagenSysCtrl.Helpers.Pipeline; +using System.IO; using System.Windows; namespace PamhagenSysCtrl.Helpers { @@ -13,13 +14,18 @@ namespace PamhagenSysCtrl.Helpers { protected bool ActuatorsChanged = false; protected PamhagenPlc.ActuatorStates Actuators; - protected PamhagenPlc.SensorStates Sensors; + protected PamhagenPlc.SensorStates Sensors = new(default, default, default, default, [ + FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown + ], default); public bool IsValveOpen(int n) => !IsValveClosed(n); public bool IsValveClosed(int n) => Sensors.GetDS(n); public bool WantValveClosed(int n) => !WantValveOpen(n); public bool WantValveOpen(int n) => Actuators.GetV(n); + public bool AreValvesOpen(params int[] ns) => ns.All(IsValveOpen); + public bool AreValvesClosed(params int[] ns) => ns.All(IsValveClosed); + public bool IsA1Selected => Sensors.TroughSelector == 1; public bool IsA2Selected => Sensors.TroughSelector == 2; public FillState FillLevelA1 => Sensors.FillingLevels.A1; @@ -38,6 +44,7 @@ namespace PamhagenSysCtrl.Helpers { public FillState[] TankFillLevels => Sensors.FillingLevelTanks; public double GradationOe => Sensors.GradationOe; public MotorState PresseQuerSchnecke => Sensors.PresseQuerSchnecke; + public bool IsPresseQuerSchneckeActive => PresseQuerSchnecke == MotorState.Forward; public bool WantA1Selected => Actuators.GetV(58); public bool WantA2Selected => !Actuators.GetV(58); @@ -52,14 +59,40 @@ namespace PamhagenSysCtrl.Helpers { public bool IsWasteDisposalActive => IsBeltActive || IsAuger1Active || IsAuger2Active; public bool IsGradationPumpActive => Actuators.GradationPump; + public bool IsMP1Active => Actuators.MP1 == MotorState.Forward || Actuators.MP1 == MotorState.Backward; + public bool IsMP2Active => Actuators.MP2 == MotorState.Forward || Actuators.MP2 == MotorState.Backward; + public bool IsP12Active => Actuators.P12 == MotorState.Forward; + public bool IsP3Active => Actuators.P3 == MotorState.Forward; + public bool IsP4Active => Actuators.P4 == MotorState.Forward; + public bool IsP5Active => Actuators.P5 == MotorState.Forward; + public bool IsP6Active => Actuators.P6 == MotorState.Forward; + public PamhagenPlant(string portName) { Plc = new(portName); + Update += OnUpdate; } protected virtual void RaiseUpdateEvent(PlantEventArgs evt) { App.MainDispatcher.BeginInvoke(() => Update?.Invoke(this, evt)); } + protected static void OnUpdate(object? sender, PlantEventArgs evt) { + if (sender is not PamhagenPlant p) return; + if (p.IsPresseQuerSchneckeActive && !p.IsBeltActive) p.StartBelt(); + if (p.IsReblerActive && !p.IsAuger1Active) p.StartAuger1(); + if (p.IsAuger1Active && !p.IsBeltActive) p.StartBelt(); + if (p.IsBeltActive && !p.IsAuger2Active) p.StartAuger2(); + if (p.IsTroughAugerActive && (!p.IsReblerActive || (p.IsA1Selected && p.FillLevelA1 == FillState.Full) || (p.IsA2Selected && p.FillLevelA2 == FillState.Full))) + p.StopTroughAuger(); + if (p.IsMP1Active && !p.MP1HasClearance) p.StopMP1(); + if (p.IsMP2Active && !p.MP2HasClearance) p.StopMP2(); + if (p.IsP12Active && !p.P12HasClearance) p.StopP12(); + if (p.IsP3Active && !p.P3HasClearance) p.StopP3(); + if (p.IsP4Active && !p.P4HasClearance) p.StopP4(); + if (p.IsP5Active && !p.P5HasClearance) p.StopP5(); + if (p.IsP6Active && !p.P6HasClearance) p.StopP6(); + } + public async Task StartThread() { if (Plc == null) throw new Exception(); await Plc.TestConnection(); @@ -111,36 +144,222 @@ namespace PamhagenSysCtrl.Helpers { ActuatorsChanged = true; } + protected bool HasWTClearanceAA => + (AreValvesOpen(12) && AreValvesClosed(15, 16, 20)) || // bypass + (AreValvesOpen(15, 18, 16) && AreValvesClosed(11, 12, 14, 17, 19, 20)) || // WT1 + (AreValvesOpen(15, 17, 20) && AreValvesClosed(11, 12, 18, 19, 21)) || // WT2 + (AreValvesOpen(15, 18, 19, 20) && AreValvesClosed(11, 12, 14, 16, 17, 21)) || // WT1+WT2 + false; + protected bool HasWTClearanceAB => + (AreValvesOpen(15, 18, 14) && AreValvesClosed(11, 12, 13, 16, 17, 19, 21)) || // WT1 + (AreValvesOpen(15, 17, 21) && AreValvesClosed(11, 12, 13, 18, 19, 20)) || // WT2 + (AreValvesOpen(15, 18, 19, 21) && AreValvesClosed(11, 12, 13, 14, 16, 17, 20)) || // WT1+WT2 + false; + protected bool HasWTClearanceBA => + (AreValvesOpen(11, 18, 16) && AreValvesClosed(15, 12, 13, 14, 17, 19, 20)) || // WT1 + (AreValvesOpen(11, 17, 20) && AreValvesClosed(15, 12, 13, 18, 19, 21)) || // WT2 + (AreValvesOpen(11, 18, 19, 20) && AreValvesClosed(15, 12, 13, 14, 16, 17, 21)) || // WT1+WT2 + false; + protected bool HasWTClearanceBB => + (AreValvesOpen(13) && AreValvesClosed(11, 14, 21)) || // bypass + (AreValvesOpen(11, 18, 14) && AreValvesClosed(15, 13, 16, 17, 19, 21)) || // WT1 + (AreValvesOpen(11, 17, 21) && AreValvesClosed(15, 13, 18, 19, 20)) || // WT2 + (AreValvesOpen(11, 18, 19, 21) && AreValvesClosed(15, 13, 14, 16, 17, 20)) || // WT1+WT2 + false; + + protected bool HasT1ClearanceA => AreValvesOpen(22) && AreValvesClosed(24, 26, 28); + protected bool HasT1ClearanceB => AreValvesOpen(23) && AreValvesClosed(25, 27, 29); + protected bool HasT2ClearanceA => AreValvesOpen(24) && AreValvesClosed(22, 26, 28); + protected bool HasT2ClearanceB => AreValvesOpen(25) && AreValvesClosed(23, 27, 29); + protected bool HasT3ClearanceA => AreValvesOpen(26) && AreValvesClosed(22, 24, 28); + protected bool HasT3ClearanceB => AreValvesOpen(27) && AreValvesClosed(23, 25, 29); + protected bool HasT4ClearanceA => AreValvesOpen(28, 30) && AreValvesClosed(22, 24, 26, 32, 34); + protected bool HasT4ClearanceB => AreValvesOpen(29, 31) && AreValvesClosed(23, 25, 27, 33, 35); + protected bool HasT5ClearanceA => AreValvesOpen(28, 32) && AreValvesClosed(22, 24, 26, 30, 34); + protected bool HasT5ClearanceB => AreValvesOpen(29, 33) && AreValvesClosed(23, 25, 27, 31, 35); + protected bool HasT6ClearanceA => AreValvesOpen(28, 34, 37) && AreValvesClosed(22, 24, 26, 30, 32, 39, 41, 43); + protected bool HasT6ClearanceB => AreValvesOpen(29, 35, 36) && AreValvesClosed(23, 25, 27, 31, 33, 38, 40, 42); + protected bool HasT7ClearanceA => AreValvesOpen(28, 34, 39) && AreValvesClosed(22, 24, 26, 30, 32, 37, 41, 43); + protected bool HasT7ClearanceB => AreValvesOpen(29, 35, 38) && AreValvesClosed(23, 25, 27, 31, 33, 36, 40, 42); + protected bool HasT8ClearanceA => AreValvesOpen(28, 34, 41) && AreValvesClosed(22, 24, 26, 30, 32, 37, 39, 43); + protected bool HasT8ClearanceB => AreValvesOpen(29, 35, 40) && AreValvesClosed(23, 25, 27, 31, 33, 36, 38, 42); + protected bool HasT9ClearanceA => AreValvesOpen(28, 34, 43) && AreValvesClosed(22, 24, 26, 30, 32, 37, 39, 41); + protected bool HasT9ClearanceB => AreValvesOpen(29, 35, 42) && AreValvesClosed(23, 25, 27, 31, 33, 36, 38, 40); + + protected bool HasClearanceTank1(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT1ClearanceA) || (HasWTClearanceAB && HasT1ClearanceB))) || + (b && ((HasWTClearanceBA && HasT1ClearanceA) || (HasWTClearanceBB && HasT1ClearanceB))); + protected bool HasClearanceTank2(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT2ClearanceA) || (HasWTClearanceAB && HasT2ClearanceB))) || + (b && ((HasWTClearanceBA && HasT2ClearanceA) || (HasWTClearanceBB && HasT2ClearanceB))); + protected bool HasClearanceTank3(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT3ClearanceA) || (HasWTClearanceAB && HasT3ClearanceB))) || + (b && ((HasWTClearanceBA && HasT3ClearanceA) || (HasWTClearanceBB && HasT3ClearanceB))); + protected bool HasClearanceTank4(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT4ClearanceA) || (HasWTClearanceAB && HasT4ClearanceB))) || + (b && ((HasWTClearanceBA && HasT4ClearanceA) || (HasWTClearanceBB && HasT4ClearanceB))); + protected bool HasClearanceTank5(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT5ClearanceA) || (HasWTClearanceAB && HasT5ClearanceB))) || + (b && ((HasWTClearanceBA && HasT5ClearanceA) || (HasWTClearanceBB && HasT5ClearanceB))); + protected bool HasClearanceTank6(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT6ClearanceA) || (HasWTClearanceAB && HasT6ClearanceB))) || + (b && ((HasWTClearanceBA && HasT6ClearanceA) || (HasWTClearanceBB && HasT6ClearanceB))); + protected bool HasClearanceTank7(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT7ClearanceA) || (HasWTClearanceAB && HasT7ClearanceB))) || + (b && ((HasWTClearanceBA && HasT7ClearanceA) || (HasWTClearanceBB && HasT7ClearanceB))); + protected bool HasClearanceTank8(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT8ClearanceA) || (HasWTClearanceAB && HasT8ClearanceB))) || + (b && ((HasWTClearanceBA && HasT8ClearanceA) || (HasWTClearanceBB && HasT8ClearanceB))); + protected bool HasClearanceTank9(bool a, bool b) => + (a && ((HasWTClearanceAA && HasT9ClearanceA) || (HasWTClearanceAB && HasT9ClearanceB))) || + (b && ((HasWTClearanceBA && HasT9ClearanceA) || (HasWTClearanceBB && HasT9ClearanceB))); + + public bool MP1HasClearance => FillLevelA1 != FillState.Empty && ( + (MP1HasClearancePress1 && FillLevelPress1 != FillState.Full) || + (MP1HasClearancePress2 && FillLevelPress2 != FillState.Full) || + (HasClearanceTank1(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT1 != FillState.Full) || + (HasClearanceTank2(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT2 != FillState.Full) || + (HasClearanceTank3(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT3 != FillState.Full) || + (HasClearanceTank4(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT4 != FillState.Full) || + (HasClearanceTank5(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT5 != FillState.Full) || + (HasClearanceTank6(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT6 != FillState.Full) || + (HasClearanceTank7(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT7 != FillState.Full) || + (HasClearanceTank8(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT8 != FillState.Full) || + (HasClearanceTank9(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT9 != FillState.Full) || + false); + protected bool MP1HasClearancePress1 => + (AreValvesOpen(1, 6, 51) && AreValvesClosed(3, 4, 5, 55)) || + (AreValvesOpen(4, 8, 52) && AreValvesClosed(1, 2, 7, 56)); + protected bool MP1HasClearancePress2 => + (AreValvesOpen(1, 6, 55) && AreValvesClosed(3, 4, 5, 51)) || + (AreValvesOpen(4, 8, 56) && AreValvesClosed(1, 2, 7, 52)); + protected bool MP1HasClearanceTanksA => AreValvesOpen(1, 5) && AreValvesClosed(3, 4, 6); + protected bool MP1HasClearanceTanksB => AreValvesOpen(4, 7, 9) && AreValvesClosed(1, 2, 8, 10); + public MotorState MP1 { get => Actuators.MP1; set => Actuators.MP1 = (value != MotorState.Halt && value != MotorState.Forward && value != MotorState.Backward) ? throw new ArgumentException("Invalid state for MP1") : value; } + public bool MP2HasClearance => FillLevelA2 != FillState.Empty && ( + (MP2HasClearancePress1 && FillLevelPress1 != FillState.Full) || + (MP2HasClearancePress2 && FillLevelPress2 != FillState.Full) || + (HasClearanceTank1(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT1 != FillState.Full) || + (HasClearanceTank2(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT2 != FillState.Full) || + (HasClearanceTank3(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT3 != FillState.Full) || + (HasClearanceTank4(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT4 != FillState.Full) || + (HasClearanceTank5(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT5 != FillState.Full) || + (HasClearanceTank6(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT6 != FillState.Full) || + (HasClearanceTank7(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT7 != FillState.Full) || + (HasClearanceTank8(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT8 != FillState.Full) || + (HasClearanceTank9(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT9 != FillState.Full) || + false); + protected bool MP2HasClearancePress1 => + (AreValvesOpen(2, 8, 52) && AreValvesClosed(3, 4, 7, 56)) || + (AreValvesOpen(3, 6, 51) && AreValvesClosed(1, 2, 5, 55)); + protected bool MP2HasClearancePress2 => + (AreValvesOpen(2, 8, 56) && AreValvesClosed(3, 4, 7, 52)) || + (AreValvesOpen(3, 6, 55) && AreValvesClosed(2, 1, 5, 51)); + protected bool MP2HasClearanceTanksA => AreValvesOpen(3, 5) && AreValvesClosed(1, 2, 6); + protected bool MP2HasClearanceTanksB => AreValvesOpen(2, 7, 9) && AreValvesClosed(3, 4, 8, 10); + public MotorState MP2 { get => Actuators.MP2; set => Actuators.MP2 = (value != MotorState.Halt && value != MotorState.Forward && value != MotorState.Backward) ? throw new ArgumentException("Invalid state for MP2") : value; } + public bool P12HasClearance => (FillLevelT1 != FillState.Empty || FillLevelT2 != FillState.Empty) && ( + (P12HasClearancePress1 && FillLevelPress1 != FillState.Full) || + (P12HasClearancePress2 && FillLevelPress2 != FillState.Full) || + (HasClearanceTank1(false, P12HasClearanceTanksB) && FillLevelT1 != FillState.Full) || + (HasClearanceTank2(false, P12HasClearanceTanksB) && FillLevelT2 != FillState.Full) || + (HasClearanceTank3(false, P12HasClearanceTanksB) && FillLevelT3 != FillState.Full) || + (HasClearanceTank4(false, P12HasClearanceTanksB) && FillLevelT4 != FillState.Full) || + (HasClearanceTank5(false, P12HasClearanceTanksB) && FillLevelT5 != FillState.Full) || + (HasClearanceTank6(false, P12HasClearanceTanksB) && FillLevelT6 != FillState.Full) || + (HasClearanceTank7(false, P12HasClearanceTanksB) && FillLevelT7 != FillState.Full) || + (HasClearanceTank8(false, P12HasClearanceTanksB) && FillLevelT8 != FillState.Full) || + (HasClearanceTank9(false, P12HasClearanceTanksB) && FillLevelT9 != FillState.Full) || + false); + protected bool P12HasClearancePress1 => AreValvesOpen(44, 46, 49, 50) && AreValvesClosed(10, 45, 47, 48, 54); + protected bool P12HasClearancePress2 => AreValvesOpen(44, 46, 49, 54) && AreValvesClosed(10, 45, 47, 48, 50); + protected bool P12HasClearanceTanksB => AreValvesOpen(44, 10) && AreValvesClosed(9, 45, 46); + public MotorState P12 { get => Actuators.P12; set => Actuators.P12 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P12") : value; } + public bool P3HasClearance => FillLevelT3 != FillState.Empty && ( + (P3HasClearancePress1 && FillLevelPress1 != FillState.Full) || + (P3HasClearancePress2 && FillLevelPress2 != FillState.Full) || + (HasClearanceTank1(false, P3HasClearanceTanksB) && FillLevelT1 != FillState.Full) || + (HasClearanceTank2(false, P3HasClearanceTanksB) && FillLevelT2 != FillState.Full) || + (HasClearanceTank3(false, P3HasClearanceTanksB) && FillLevelT3 != FillState.Full) || + (HasClearanceTank4(false, P3HasClearanceTanksB) && FillLevelT4 != FillState.Full) || + (HasClearanceTank5(false, P3HasClearanceTanksB) && FillLevelT5 != FillState.Full) || + (HasClearanceTank6(false, P3HasClearanceTanksB) && FillLevelT6 != FillState.Full) || + (HasClearanceTank7(false, P3HasClearanceTanksB) && FillLevelT7 != FillState.Full) || + (HasClearanceTank8(false, P3HasClearanceTanksB) && FillLevelT8 != FillState.Full) || + (HasClearanceTank9(false, P3HasClearanceTanksB) && FillLevelT9 != FillState.Full) || + false); + protected bool P3HasClearancePress1 => AreValvesOpen(45, 46, 49, 50) && AreValvesClosed(10, 44, 47, 48, 54); + protected bool P3HasClearancePress2 => AreValvesOpen(45, 46, 49, 54) && AreValvesClosed(10, 44, 47, 48, 50); + protected bool P3HasClearanceTanksB => AreValvesOpen(45, 10) && AreValvesClosed(9, 44, 46); + public MotorState P3 { get => Actuators.P3; set => Actuators.P3 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P3") : value; } + public bool P4HasClearance => FillLevelT4 != FillState.Empty && ( + (P4HasClearancePress1 && FillLevelPress1 != FillState.Full) || + (P4HasClearancePress2 && FillLevelPress2 != FillState.Full) || + (HasClearanceTank1(false, P4HasClearanceTanksB) && FillLevelT1 != FillState.Full) || + (HasClearanceTank2(false, P4HasClearanceTanksB) && FillLevelT2 != FillState.Full) || + (HasClearanceTank3(false, P4HasClearanceTanksB) && FillLevelT3 != FillState.Full) || + (HasClearanceTank4(false, P4HasClearanceTanksB) && FillLevelT4 != FillState.Full) || + (HasClearanceTank5(false, P4HasClearanceTanksB) && FillLevelT5 != FillState.Full) || + (HasClearanceTank6(false, P4HasClearanceTanksB) && FillLevelT6 != FillState.Full) || + (HasClearanceTank7(false, P4HasClearanceTanksB) && FillLevelT7 != FillState.Full) || + (HasClearanceTank8(false, P4HasClearanceTanksB) && FillLevelT8 != FillState.Full) || + (HasClearanceTank9(false, P4HasClearanceTanksB) && FillLevelT9 != FillState.Full) || + false); + protected bool P4HasClearancePress1 => AreValvesOpen(47, 49, 50) && AreValvesClosed(46, 48, 54); + protected bool P4HasClearancePress2 => AreValvesOpen(47, 49, 54) && AreValvesClosed(46, 48, 50); + protected bool P4HasClearanceTanksB => AreValvesOpen(47, 46, 10) && AreValvesClosed(9, 44, 45, 48, 49); + public MotorState P4 { get => Actuators.P4; set => Actuators.P4 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P4") : value; } + public bool P5HasClearance => FillLevelT4 != FillState.Empty && ( + (P5HasClearancePress1 && FillLevelPress1 != FillState.Full) || + (P5HasClearancePress2 && FillLevelPress2 != FillState.Full) || + (HasClearanceTank1(false, P5HasClearanceTanksB) && FillLevelT1 != FillState.Full) || + (HasClearanceTank2(false, P5HasClearanceTanksB) && FillLevelT2 != FillState.Full) || + (HasClearanceTank3(false, P5HasClearanceTanksB) && FillLevelT3 != FillState.Full) || + (HasClearanceTank4(false, P5HasClearanceTanksB) && FillLevelT4 != FillState.Full) || + (HasClearanceTank5(false, P5HasClearanceTanksB) && FillLevelT5 != FillState.Full) || + (HasClearanceTank6(false, P5HasClearanceTanksB) && FillLevelT6 != FillState.Full) || + (HasClearanceTank7(false, P5HasClearanceTanksB) && FillLevelT7 != FillState.Full) || + (HasClearanceTank8(false, P5HasClearanceTanksB) && FillLevelT8 != FillState.Full) || + (HasClearanceTank9(false, P5HasClearanceTanksB) && FillLevelT9 != FillState.Full) || + false); + protected bool P5HasClearancePress1 => AreValvesOpen(48, 49, 50) && AreValvesClosed(46, 47, 54); + protected bool P5HasClearancePress2 => AreValvesOpen(48, 49, 54) && AreValvesClosed(46, 47, 50); + protected bool P5HasClearanceTanksB => AreValvesOpen(48, 46, 10) && AreValvesClosed(9, 44, 45, 47, 49); + public MotorState P5 { get => Actuators.P5; set => Actuators.P5 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P5") : value; } + public bool P6HasClearance => + (IsValveOpen(53) && IsValveClosed(57) && FillLevelPress1 != FillState.Full) || + (IsValveOpen(57) && IsValveClosed(53) && FillLevelPress2 != FillState.Full); + public MotorState P6 { get => Actuators.P6; set => Actuators.P6 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P6") : value; @@ -167,6 +386,8 @@ namespace PamhagenSysCtrl.Helpers { } public void StartTroughAuger() { + if (!IsReblerActive || !((IsA1Selected && FillLevelA1 != FillState.Full) || (IsA2Selected && FillLevelA2 != FillState.Full))) + throw new NoClearanceException("Schnecke Auffangwanne hat keine Freigabe"); Actuators.TroughAuger = true; } @@ -179,6 +400,7 @@ namespace PamhagenSysCtrl.Helpers { } public void StopRebler() { + StopTroughAuger(); Actuators.Rebler = false; } @@ -243,10 +465,12 @@ namespace PamhagenSysCtrl.Helpers { } public void StartMP1Forward() { + if (!MP1HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe"); Actuators.MP1 = MotorState.Forward; } public void StartMP1Backward() { + if (!MP1HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe"); Actuators.MP1 = MotorState.Backward; } @@ -255,10 +479,12 @@ namespace PamhagenSysCtrl.Helpers { } public void StartMP2Forward() { + if (!MP2HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe"); Actuators.MP2 = MotorState.Forward; } public void StartMP2Backward() { + if (!MP2HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe"); Actuators.MP2 = MotorState.Backward; } @@ -267,6 +493,7 @@ namespace PamhagenSysCtrl.Helpers { } public void StartP12() { + if (!P12HasClearance) throw new NoClearanceException("P1/2 hat keine Freigabe"); Actuators.P12 = MotorState.Forward; } @@ -275,6 +502,7 @@ namespace PamhagenSysCtrl.Helpers { } public void StartP3() { + if (!P3HasClearance) throw new NoClearanceException("P3 hat keine Freigabe"); Actuators.P3 = MotorState.Forward; } @@ -283,6 +511,7 @@ namespace PamhagenSysCtrl.Helpers { } public void StartP4() { + if (!P4HasClearance) throw new NoClearanceException("P4 hat keine Freigabe"); Actuators.P4 = MotorState.Forward; } @@ -291,6 +520,7 @@ namespace PamhagenSysCtrl.Helpers { } public void StartP5() { + if (!P5HasClearance) throw new NoClearanceException("P5 hat keine Freigabe"); Actuators.P5 = MotorState.Forward; } @@ -299,6 +529,7 @@ namespace PamhagenSysCtrl.Helpers { } public void StartP6() { + if (!P6HasClearance) throw new NoClearanceException("P6 hat keine Freigabe"); Actuators.P6 = MotorState.Forward; } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Auger.cs b/PamhagenSysCtrl/Helpers/Pipeline/Auger.cs index 089b919..d2b27e5 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Auger.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Auger.cs @@ -13,7 +13,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public double Height { get; set; } public double Angle { get; set; } - public bool IsActive { + public bool IsAnimationActive { set { if (value) { _storyboard?.Resume(); diff --git a/PamhagenSysCtrl/Helpers/Pipeline/ConveyorBelt.cs b/PamhagenSysCtrl/Helpers/Pipeline/ConveyorBelt.cs index 3f8d0ec..3094c44 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/ConveyorBelt.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/ConveyorBelt.cs @@ -17,10 +17,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public ISet Inputs { get; init; } public ISet Outputs { get; init; } - public bool IsActive { - get => _active; + public bool IsActive => CallbackActive(); + public bool IsAnimationActive { + get => _animationActive; set { - _active = value; + _animationActive = value; if (value) { _storyboard?.Resume(); } else { @@ -29,15 +30,18 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } } - private bool _active; + protected Func CallbackActive; + + private bool _animationActive; private Shape? _rect; private Polyline? _polyline; private Storyboard? _storyboard; - public ConveyorBelt(string label, double x, double y) { + public ConveyorBelt(string label, double x, double y, Func cbActive) { CenterX = x; CenterY = y; Label = label; + CallbackActive = cbActive; Inputs = new HashSet(); Outputs = new HashSet(); } @@ -97,12 +101,13 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } public void Update(bool isHovering, bool isPressed) { + IsAnimationActive = IsActive; _rect?.Fill = - IsActive && isHovering && isPressed ? PamhagenBrushes.Red : - IsActive && isHovering ? PamhagenBrushes.Red : - !IsActive && isHovering && isPressed ? PamhagenBrushes.Green : - !IsActive && isHovering ? PamhagenBrushes.Green : - IsActive ? PamhagenBrushes.Green : + IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Red : + IsAnimationActive && isHovering ? PamhagenBrushes.Red : + !IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Green : + !IsAnimationActive && isHovering ? PamhagenBrushes.Green : + IsAnimationActive ? PamhagenBrushes.Green : Brushes.WhiteSmoke; } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/EncasedAuger.cs b/PamhagenSysCtrl/Helpers/Pipeline/EncasedAuger.cs index 3f66391..cf87c0e 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/EncasedAuger.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/EncasedAuger.cs @@ -16,25 +16,29 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public ISet Inputs { get; init; } public ISet Outputs { get; init; } - public bool IsActive { - get => _active; + public bool IsActive => CallbackActive(); + public bool IsAnimationActive { + get => _animationActive; set { - _active = value; - _auger?.IsActive = value; + _animationActive = value; + _auger?.IsAnimationActive = value; } } - private bool _active; + protected Func CallbackActive; + + private bool _animationActive; private Shape? _inner; private Shape? _outer; private Auger? _auger; private TextBlock? _text; - public EncasedAuger(string label, double x, double y, double angle = 0) { + public EncasedAuger(string label, double x, double y, Func cbActive, double angle = 0) { CenterX = x; CenterY = y; Label = label; Angle = angle; + CallbackActive = cbActive; Inputs = new HashSet(); Outputs = new HashSet(); } @@ -80,12 +84,13 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } public void Update(bool isHovering, bool isPressed) { + IsAnimationActive = IsActive; _inner?.Fill = - IsActive && isHovering && isPressed ? PamhagenBrushes.Red : - IsActive && isHovering ? PamhagenBrushes.Red : - !IsActive && isHovering && isPressed ? PamhagenBrushes.Green : - !IsActive && isHovering ? PamhagenBrushes.Green : - IsActive ? PamhagenBrushes.Green : + IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Red : + IsAnimationActive && isHovering ? PamhagenBrushes.Red : + !IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Green : + !IsAnimationActive && isHovering ? PamhagenBrushes.Green : + IsAnimationActive ? PamhagenBrushes.Green : Brushes.WhiteSmoke; } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/EntryTrough.cs b/PamhagenSysCtrl/Helpers/Pipeline/EntryTrough.cs index 6167f04..8fd0dca 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/EntryTrough.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/EntryTrough.cs @@ -16,11 +16,12 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public ISet Inputs { get; init; } public ISet Outputs { get; init; } - public bool IsActive { - get => _active; + public bool IsActive => CallbackActive(); + public bool IsAnimationActive { + get => _animationActive; set { - _active = value; - _auger?.IsActive = value; + _animationActive = value; + _auger?.IsAnimationActive = value; if (value) { _doorTransform?.BeginAnimation( RotateTransform.AngleProperty, @@ -41,7 +42,9 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } } - private bool _active; + protected Func CallbackActive; + + private bool _animationActive; private Shape? _inner; private Shape? _outer; private TextBlock? _text; @@ -49,10 +52,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { private Shape? _door; private RotateTransform? _doorTransform; - public EntryTrough(string label, double x, double y) { + public EntryTrough(string label, double x, double y, Func cbActive) { CenterX = x; CenterY = y; Label = label; + CallbackActive = cbActive; Inputs = new HashSet(); Outputs = new HashSet(); } @@ -99,12 +103,13 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } public void Update(bool isHovering, bool isPressed) { + IsAnimationActive = IsActive; _inner?.Fill = - IsActive && isHovering && isPressed ? PamhagenBrushes.Red : - IsActive && isHovering ? PamhagenBrushes.Red : - !IsActive && isHovering && isPressed ? PamhagenBrushes.Green : - !IsActive && isHovering ? PamhagenBrushes.Green : - IsActive ? PamhagenBrushes.Green : + IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Red : + IsAnimationActive && isHovering ? PamhagenBrushes.Red : + !IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Green : + !IsAnimationActive && isHovering ? PamhagenBrushes.Green : + IsAnimationActive ? PamhagenBrushes.Green : Brushes.WhiteSmoke; } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Pump.cs b/PamhagenSysCtrl/Helpers/Pipeline/Pump.cs index cdcc03c..f2c491a 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Pump.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Pump.cs @@ -15,14 +15,26 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public ISet Inputs { get; init; } public ISet Outputs { get; init; } + public Brush? Highlight { get; set; } + public bool IsActive => CallbackActive(); + public bool HasClearance => CallbackClearance(); + public bool IsSelected => CallbackSelected(this); + + protected Func CallbackActive; + protected Func CallbackClearance; + protected Func CallbackSelected; + private Shape? _circle; private Shape? _triangle; private TextBlock? _text; - public Pump(string label, double x, double y) { + public Pump(string label, double x, double y, Func cbActive, Func cbClearance, Func cbSelected) { CenterX = x; CenterY = y; Label = label; + CallbackActive = cbActive; + CallbackClearance = cbClearance; + CallbackSelected = cbSelected; Inputs = new HashSet(); Outputs = new HashSet(); } @@ -63,7 +75,13 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } public void Update(bool isHovering, bool isPresed) { - _circle?.Fill = isHovering ? Brushes.LightGray : Brushes.WhiteSmoke; + _circle?.Fill = Highlight ?? ( + IsActive && isHovering ? PamhagenBrushes.Red : + IsActive ? PamhagenBrushes.Green : + HasClearance && IsSelected && isHovering ? PamhagenBrushes.Green : + HasClearance && IsSelected ? PamhagenBrushes.Yellow : + IsSelected ? PamhagenBrushes.Red : + isHovering ? Brushes.LightGray : Brushes.WhiteSmoke); } } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs b/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs index 309ae1d..c284c55 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs @@ -15,7 +15,9 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public ISet Inputs { get; init; } public ISet Outputs { get; init; } - public bool IsActive { get; set; } + public bool IsActive => CallbackActive(); + + protected Func CallbackActive; private TextBlock? _text; private Shape? _rect; @@ -24,10 +26,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { private Shape? _bottomInner; private Shape? _bottomOuter; - public Rebler(string label, double x, double y) { + public Rebler(string label, double x, double y, Func cbActive) { CenterX = x; CenterY = y; Label = label; + CallbackActive = cbActive; Inputs = new HashSet(); Outputs = new HashSet(); } diff --git a/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs b/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs index b522be0..d74ea67 100644 --- a/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs +++ b/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs @@ -11,6 +11,8 @@ namespace PamhagenSysCtrl.Windows { private ISource? _lastSource; private List _path = []; private ISet? _lastSelected; + private ISet? _hover; + private bool _mouseDown; public PlantSchemeWindow() { InitializeComponent(); @@ -39,7 +41,9 @@ namespace PamhagenSysCtrl.Windows { foreach (var c in clicked) { if (_lastSource == null && Graph.SelectedPaths.Any(p => p.Start == c)) { var path = Graph.SelectedPaths.First(p => p.Start == c); - Graph.RemovePath(path); + if (!path.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false)) { + Graph.RemovePath(path); + } } else if (_lastSource != null && c is ISink sink) { var res = Graph.GetPath([_lastSource, .._path, sink], (n) => n is not ISink && (n is not Valve v || !v.IsLocked)); if (res is Path path) { @@ -57,14 +61,74 @@ namespace PamhagenSysCtrl.Windows { } else { _lastSource = null; } - if (c is EntryTrough trough) { - trough.IsActive = !trough.IsActive; - } else if (c is Rebler rebler) { - rebler.IsActive = !rebler.IsActive; - } else if (c is EncasedAuger auger) { - auger.IsActive = !auger.IsActive; - } else if (c is ConveyorBelt belt) { - belt.IsActive = !belt.IsActive; + try { + if (c is EntryTrough trough) { + if (trough.IsActive) { + App.Plant?.StopTroughAuger(); + } else { + App.Plant?.StartTroughAuger(); + } + } else if (c is Rebler rebler) { + if (rebler.IsActive) { + App.Plant?.StopRebler(); + } else { + App.Plant?.StartRebler(); + } + } else if (c is EncasedAuger auger) { + // + } else if (c is ConveyorBelt belt) { + if (belt.IsActive) { + App.Plant?.StopBelt(); + } else { + App.Plant?.StartBelt(); + } + } else if (c is Pump pump) { + if (pump == Graph.MP1) { + if (pump.IsActive) { + App.Plant?.StopMP1(); + } else { + App.Plant?.StartMP1Forward(); + } + } else if (pump == Graph.MP2) { + if (pump.IsActive) { + App.Plant?.StopMP2(); + } else { + App.Plant?.StartMP2Forward(); + } + } else if (pump == Graph.P12) { + if (pump.IsActive) { + App.Plant?.StopP12(); + } else { + App.Plant?.StartP12(); + } + } else if (pump == Graph.P3) { + if (pump.IsActive) { + App.Plant?.StopP3(); + } else { + App.Plant?.StartP3(); + } + } else if (pump == Graph.P4) { + if (pump.IsActive) { + App.Plant?.StopP4(); + } else { + App.Plant?.StartP4(); + } + } else if (pump == Graph.P5) { + if (pump.IsActive) { + App.Plant?.StopP5(); + } else { + App.Plant?.StartP5(); + } + } else if (pump == Graph.P6) { + if (pump.IsActive) { + App.Plant?.StopP6(); + } else { + App.Plant?.StartP6(); + } + } + } + } catch (NoClearanceException exc) { + MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error); } } UpdateScheme(pos, evt.LeftButton == MouseButtonState.Pressed); @@ -75,14 +139,20 @@ namespace PamhagenSysCtrl.Windows { e.Highlight = null; e.Flow = null; } - foreach (var p in Graph.SelectedPaths) { - Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, true, PamhagenBrushes.DimOrange); + foreach (var n in Graph.Nodes) { + if (n is Pump p) { + p.Highlight = null; + } } - var hover = Graph.GetHover(pos.X, pos.Y); - if (_lastSource != null && (hover.Count > 0 || _path.Count > 0)) { + foreach (var p in Graph.SelectedPaths) { + Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, p.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false), PamhagenBrushes.DimOrange); + } + _hover = Graph.GetHover(pos.X, pos.Y); + _mouseDown = down; + if (_lastSource != null && (_hover.Count > 0 || _path.Count > 0)) { List points = [_lastSource, .. _path]; - if (hover.Count > 0 && !points.Contains(hover.First())) { - points.Add(hover.First()); + if (_hover.Count > 0 && !points.Contains(_hover.First())) { + points.Add(_hover.First()); } if (points.Count >= 2) { var res = Graph.GetPath(points, (n) => n is not ISink && (n is not Valve v || !v.IsLocked)); @@ -90,21 +160,29 @@ namespace PamhagenSysCtrl.Windows { Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Green, false, PamhagenBrushes.DimOrange); } } - } else if (_lastSource == null && hover.Count > 0 && Graph.SelectedPaths.Any(p => p.Start == hover.First())) { - var path = Graph.SelectedPaths.First(p => p.Start == hover.First()); - Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Red, true, null); + } else if (_lastSource == null && _hover.Count > 0 && Graph.SelectedPaths.Any(p => p.Start == _hover.First())) { + var path = Graph.SelectedPaths.First(p => p.Start == _hover.First()); + var pumpActive = path.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false); + if (pumpActive) { + foreach (var pump in path.Hops.Select(h => h.Node as Pump).Where(p => p != null)) { + pump?.Highlight = PamhagenBrushes.Red; + } + } else { + Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Red, false, null); + } } if (_lastSource != null) { foreach (var edge in _lastSource.Outputs) { edge.Highlight = PamhagenBrushes.Green; } } - Graph.Update(hover, down); - return hover; + Graph.Update(_hover, down); + return _hover; } public void OnUpdate(object? sender, PlantEventArgs evt) { if (sender is not PamhagenPlant plant) return; + Graph.Update(_hover ?? new HashSet(), _mouseDown); } } }