Add Handbetrieb support in scheme window
Test / Run tests (push) Successful in 33s

This commit is contained in:
2026-08-07 15:55:22 +02:00
parent 7c3233361f
commit 0ceab368ce
6 changed files with 153 additions and 86 deletions
+45 -21
View File
@@ -66,8 +66,8 @@ namespace PamhagenSysCtrl.Helpers {
MW1 = new Trough("MW1", mw1X, mpY - 70, () => App.Plant?.FillLevelMW1 ?? FillState.Unknown);
MW2 = new Trough("MW2", mw2X, mpY - 70, () => App.Plant?.FillLevelMW2 ?? FillState.Unknown);
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)));
MP1 = new Pump("MP1", mw1X, mpY, () => App.Plant?.MP1 ?? default, () => App.Plant?.MP1HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
MP2 = new Pump("MP2", mw2X, mpY, () => App.Plant?.MP2 ?? default, () => 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);
@@ -291,14 +291,14 @@ namespace PamhagenSysCtrl.Helpers {
CreateInlet(v43, t9);
var xp12 = new PipeJoin((t1X + t2X) / 2, tanksY + 80);
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)));
P12 = new Pump("P1/2", (t1X + t2X) / 2, tanksY + 110, () => App.Plant?.P12 ?? default, () => App.Plant?.P12HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
CreateOutlet(t1, xp12);
CreateOutlet(t2, xp12);
CreatePipe(xp12, P12);
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)));
P3 = new Pump("P3", t3X, tanksY + 110, () => App.Plant?.P3 ?? default, () => App.Plant?.P3HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
P4 = new Pump("P4", t4X, tanksY + 110, () => App.Plant?.P4 ?? default, () => App.Plant?.P4HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
P5 = new Pump("P5", t5X, tanksY + 110, () => App.Plant?.P5 ?? default, () => App.Plant?.P5HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
CreateOutlet(t3, P3);
CreateOutlet(t4, P4);
CreateOutlet(t5, P5);
@@ -328,7 +328,7 @@ namespace PamhagenSysCtrl.Helpers {
var xt6 = new PipeJoin(t6X, tanksY + 110);
var xt7 = new PipeJoin(t7X, tanksY + 110);
var xt8 = new PipeJoin(t8X, tanksY + 110);
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)));
P6 = new Pump("P6", t6X, tanksY + 150, () => App.Plant?.P6 ?? default, () => App.Plant?.P6HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
CreateOutlet(t6, xt6);
CreateOutlet(t7, xt7);
CreateOutlet(t8, xt8);
@@ -395,34 +395,35 @@ namespace PamhagenSysCtrl.Helpers {
}
protected Valve CreateValve(int n, double x, double y) {
return new(n, x, y, () => App.Plant?.IsValveOpen(n) ?? false, (v) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == v)));
return new(n, x, y, () => App.Plant?.IsValveOpen(n) ?? false, (v) => App.Plant?.ManualControlMode ?? false ? App.Plant.WantValveOpen(n) : SelectedPaths.Any(p => p.Hops.Any(h => h.Node == v)));
}
protected static Tank CreateTank(int n, double x, double y, int capacity) {
return new($"Tank {n}", x, y, capacity, () => App.Plant?.TankFillLevels[n - 1] ?? FillState.Unknown);
}
public void TraverseSubgraph(INode start, HashSet<IEdge>? visited = null, Action<IEdge>? edgeAction = null, Action<Valve>? valveAction = null) {
visited ??= [];
public void TraverseSubgraph(INode start, Func<INode, bool> invalid, HashSet<IEdge>? _visited = null, Action<INode, bool, IEdge>? edgeAction = null, Action<Valve>? valveAction = null, bool reverse = false) {
var visited = _visited ?? [];
if (start is Valve v) {
valveAction?.Invoke(v);
return;
} else if (start is ISink || start is Pump) {
}
if (invalid(start)) {
return;
}
foreach (var edge in start.Inputs) {
if (visited.Contains(edge)) continue;
var o = edge.IsTwoWay && edge.Start == start ? edge.End : edge.Start;
edgeAction?.Invoke(edge);
edgeAction?.Invoke(start, reverse || _visited == null, edge);
visited.Add(edge);
TraverseSubgraph(o, visited, edgeAction, valveAction);
TraverseSubgraph(o, invalid, visited, edgeAction, valveAction, reverse || _visited == null);
}
foreach (var edge in start.Outputs) {
if (visited.Contains(edge)) continue;
var o = edge.IsTwoWay && edge.End == start ? edge.Start : edge.End;
edgeAction?.Invoke(edge);
edgeAction?.Invoke(start, reverse, edge);
visited.Add(edge);
TraverseSubgraph(o, visited, edgeAction, valveAction);
TraverseSubgraph(o, invalid, visited, edgeAction, valveAction, reverse);
}
}
@@ -453,7 +454,7 @@ namespace PamhagenSysCtrl.Helpers {
private void UpdateValvesAdjacientToPath(Path path, bool locked, bool? wantOpen = null) {
foreach (var (edge, node) in path.Hops) {
TraverseSubgraph(node, valveAction: (v) => {
TraverseSubgraph(node, (n) => n is Valve || n is ISink || n is Pump, valveAction: (v) => {
v.IsLocked = locked;
if (wantOpen.HasValue) {
if (wantOpen.Value) {
@@ -466,18 +467,41 @@ namespace PamhagenSysCtrl.Helpers {
}
}
public void ColorPipesAdjacientToPath(Path path, Brush? color1, bool flowArrows, Brush? color2) {
public void ColorPipesAdjacientToPath(Path path, Brush? color1, MotorState flowArrows, Brush? color2) {
var color = color1;
var flowPathOffset = 0.0;
HashSet<IEdge> visited = [];
foreach (var (edge, node) in path.Hops) {
edge.Highlight = color1;
edge.Flow = flowArrows ? (edge.End == node, flowPathOffset) : null;
if (edge.Flow != null) flowPathOffset += edge.FlowLength;
if (flowArrows > MotorState.Halt) {
var dir = edge.End == node;
if (flowArrows == MotorState.Backward) dir = !dir;
edge.Flow = (dir, flowPathOffset);
flowPathOffset += edge.FlowLength;
}
visited.Add(edge);
if (node is Pump) color = color2;
TraverseSubgraph(node, visited, edgeAction: (e) => e.Highlight = color);
TraverseSubgraph(node, (n) => n is Valve || n is ISink || n is Pump, visited, edgeAction: (s, r, e) => e.Highlight = color);
}
}
public void ColorPipesByValves(INode start, Brush? color1, MotorState flowArrows, Brush? color2) {
var flowPathOffset = 0.0;
TraverseSubgraph(start, (n) => n is ISink || n is Outlet || !((n as Valve)?.IsOpen ?? (n as CenterValve)?.IsOpen ?? true), null,
edgeAction: (s, r, e) => {
if (((e.Start as Valve)?.IsOpen ?? true) && ((e.End as Valve)?.IsOpen ?? true)) {
e.Highlight = color1;
if (flowArrows == MotorState.Forward || flowArrows == MotorState.Backward) {
var dir = e.Start == s;
if (r) dir = !dir;
if (flowArrows == MotorState.Backward) dir = !dir;
e.Flow = (dir, flowPathOffset);
flowPathOffset += e.FlowLength;
}
} else {
e.Highlight = color2;
}
});
}
}
}