This commit is contained in:
@@ -5,10 +5,12 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
public const double TRANSITION = 1.0 / 4096;
|
||||
|
||||
public static readonly SolidColorBrush Green = new SolidColorBrush(Color.FromRgb(0x20, 0xE0, 0x20));
|
||||
public static readonly SolidColorBrush DimOrange = new SolidColorBrush(Color.FromRgb(0xFF, 0xC0, 0x80));
|
||||
public static readonly SolidColorBrush Yellow = new SolidColorBrush(Color.FromRgb(0xFF, 0xE0, 0x10));
|
||||
public static readonly SolidColorBrush Red = new SolidColorBrush(Color.FromRgb(0xFF, 0x20, 0x20));
|
||||
public static readonly SolidColorBrush Green = new(Color.FromRgb(0x20, 0xE0, 0x20));
|
||||
public static readonly SolidColorBrush DimGreen = new(Color.FromRgb(0xC0, 0xE0, 0xC0));
|
||||
public static readonly SolidColorBrush DimOrange = new(Color.FromRgb(0xFF, 0xC0, 0x80));
|
||||
public static readonly SolidColorBrush Yellow = new(Color.FromRgb(0xFF, 0xE0, 0x10));
|
||||
public static readonly SolidColorBrush Red = new(Color.FromRgb(0xFF, 0x20, 0x20));
|
||||
public static readonly SolidColorBrush DimRed = new(Color.FromRgb(0xFF, 0xC0, 0xC0));
|
||||
|
||||
public static Brush ForFillState(FillState state, Color background) {
|
||||
return state switch {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
protected bool IsRunning = true;
|
||||
protected Thread? BackgroundThread;
|
||||
|
||||
public bool ManualControlMode { get; set; }
|
||||
public bool OverridePathClearances { get; set; }
|
||||
public bool OverrideDryRunClearances { get; set; }
|
||||
|
||||
@@ -93,12 +94,12 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
if (p.IsMP1Active && !p.MP1HasClearance) p.StopMP1();
|
||||
if (p.IsMP2Active && !p.MP2HasClearance) p.StopMP2();
|
||||
|
||||
if (p.IsMP1Active && p.FillLevelMW1 >= FillState.Half && !p.IsStirrerMW1Active) {
|
||||
if (p.MP1 == MotorState.Forward && p.FillLevelMW1 >= FillState.Half && !p.IsStirrerMW1Active) {
|
||||
p.StartStirrerMW1();
|
||||
} else if (p.IsStirrerMW1Active && (!p.IsMP1Active || p.FillLevelMW1 < FillState.Half)) {
|
||||
p.StopStirrerMW1();
|
||||
}
|
||||
if (p.IsMP2Active && p.FillLevelMW2 >= FillState.Half && !p.IsStirrerMW2Active) {
|
||||
if (p.MP2 == MotorState.Forward && p.FillLevelMW2 >= FillState.Half && !p.IsStirrerMW2Active) {
|
||||
p.StartStirrerMW2();
|
||||
} else if (p.IsStirrerMW2Active && (!p.IsMP2Active || p.FillLevelMW2 < FillState.Half)) {
|
||||
p.StopStirrerMW2();
|
||||
|
||||
@@ -16,11 +16,12 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
public ISet<IEdge> Outputs { get; init; }
|
||||
|
||||
public Brush? Highlight { get; set; }
|
||||
public bool IsActive => CallbackActive();
|
||||
public bool IsActive => State == MotorState.Forward || State == MotorState.Backward;
|
||||
public MotorState State => CallbackState();
|
||||
public bool HasClearance => CallbackClearance();
|
||||
public bool IsSelected => CallbackSelected(this);
|
||||
|
||||
protected Func<bool> CallbackActive;
|
||||
protected Func<MotorState> CallbackState;
|
||||
protected Func<bool> CallbackClearance;
|
||||
protected Func<Pump, bool> CallbackSelected;
|
||||
|
||||
@@ -28,11 +29,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
private Shape? _triangle;
|
||||
private TextBlock? _text;
|
||||
|
||||
public Pump(string label, double x, double y, Func<bool> cbActive, Func<bool> cbClearance, Func<Pump, bool> cbSelected) {
|
||||
public Pump(string label, double x, double y, Func<MotorState> cbState, Func<bool> cbClearance, Func<Pump, bool> cbSelected) {
|
||||
CenterX = x;
|
||||
CenterY = y;
|
||||
Label = label;
|
||||
CallbackActive = cbActive;
|
||||
CallbackState = cbState;
|
||||
CallbackClearance = cbClearance;
|
||||
CallbackSelected = cbSelected;
|
||||
Inputs = new HashSet<IEdge>();
|
||||
@@ -75,13 +76,22 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
}
|
||||
|
||||
public void Update(bool isHovering, bool isPresed) {
|
||||
_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);
|
||||
if (App.Plant?.ManualControlMode ?? false) {
|
||||
_circle?.Fill = Highlight ?? (
|
||||
IsActive && isHovering ? PamhagenBrushes.Red :
|
||||
IsActive ? PamhagenBrushes.Green :
|
||||
HasClearance && isHovering ? PamhagenBrushes.Green :
|
||||
HasClearance ? PamhagenBrushes.Yellow :
|
||||
PamhagenBrushes.Red);
|
||||
} else {
|
||||
_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,12 +66,23 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
}
|
||||
|
||||
public void Update(bool isHovering, bool isPressed) {
|
||||
_circle?.Fill =
|
||||
IsLocked && !WantOpen && !IsOpen ? PamhagenBrushes.DimOrange :
|
||||
IsLocked && !WantOpen && IsOpen ? PamhagenBrushes.Red :
|
||||
IsLocked && WantOpen && !IsOpen ? PamhagenBrushes.Yellow :
|
||||
IsLocked && WantOpen && IsOpen ? PamhagenBrushes.Green :
|
||||
Highlight ?? (isHovering ? Brushes.LightGray : Brushes.DarkGray);
|
||||
if (App.Plant?.ManualControlMode ?? false) {
|
||||
_circle?.Fill =
|
||||
!WantOpen && !IsOpen && !isHovering ? PamhagenBrushes.Red :
|
||||
!WantOpen && !IsOpen ? PamhagenBrushes.Green :
|
||||
!WantOpen && IsOpen ? PamhagenBrushes.DimRed :
|
||||
WantOpen && !IsOpen ? PamhagenBrushes.DimGreen :
|
||||
WantOpen && IsOpen && !isHovering ? PamhagenBrushes.Green :
|
||||
WantOpen && IsOpen ? PamhagenBrushes.Red :
|
||||
Highlight ?? (isHovering ? Brushes.LightGray : Brushes.DarkGray);
|
||||
} else {
|
||||
_circle?.Fill =
|
||||
IsLocked && !WantOpen && !IsOpen ? PamhagenBrushes.DimOrange :
|
||||
IsLocked && !WantOpen && IsOpen ? PamhagenBrushes.Red :
|
||||
IsLocked && WantOpen && !IsOpen ? PamhagenBrushes.Yellow :
|
||||
IsLocked && WantOpen && IsOpen ? PamhagenBrushes.Green :
|
||||
Highlight ?? (isHovering ? Brushes.LightGray : Brushes.DarkGray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user