// Copyright (C) Stichting Deltares 2025. All rights reserved.
//
// This file is part of the application DAM - UI.
//
// DAM - UI is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Xml.Serialization;
using Deltares.Dam.Data;
using Deltares.Standard;
using Deltares.Standard.Attributes;
using Deltares.Standard.EventPublisher;
namespace Deltares.Dam.Forms
{
[Impact(Impact.None)]
public class LocationJobSymbol : Symbol, IVisibleEnabled
{
private readonly Func bad = f => f <= 1.0 && f > 0;
private readonly Func warning = f => f > 1.0 && f <= 1.05;
private readonly Func good = f => f > 1.05 && f < 1.17;
private readonly Func excellent = f => f >= 1.17 && f < DamGlobalConstants.NoRunValue;
private readonly Func failed = f => double.IsNaN(f) || f <= 0;
private readonly Func notCalculated = f => f >= DamGlobalConstants.NoRunValue;
private int currentView;
private DateTime currentDateTime = DateTime.Today;
private DateTime minDateTime = DateTime.Today;
private DateTime maxDateTime = DateTime.Today;
private string currentProfileName;
private string currentScenarioName;
private string currentCalculation;
private DamProjectData damProjectData;
public LocationJobSymbol()
{
RegisterColorAndLabel("f >= 1.17", Color.Lime, excellent);
RegisterColorAndLabel("1.05 < f < 1.17", Color.Yellow, good);
RegisterColorAndLabel("1.0 < f <= 1.05", Color.Orange, warning);
RegisterColorAndLabel("f <= 1.0", Color.Red, bad);
RegisterColorAndLabel("failed calculation", Color.White, failed);
RegisterColorAndLabel("not yet calculated", Color.Gray, notCalculated);
DataEventPublisher.OnAfterChange += DataEventPublisher_OnAfterChange;
}
public LocationJob CurrentLocationJob { get; private set; }
[XmlIgnore]
public string CurrentProfileName
{
get
{
return currentProfileName;
}
set
{
DataEventPublisher.BeforeChange(this, "CurrentProfileName");
currentProfileName = value;
LocationJob.CurrentProfileName = value;
DataEventPublisher.DataListModified(DamProjectData.LocationJobs);
DataEventPublisher.AfterChange(this, "CurrentProfileName");
}
}
[XmlIgnore]
public string CurrentScenarioName
{
get
{
return currentScenarioName;
}
set
{
DataEventPublisher.BeforeChange(this, "CurrentScenarioName");
currentScenarioName = value;
LocationJob.CurrentScenarioName = value;
DataEventPublisher.DataListModified(DamProjectData.LocationJobs);
DataEventPublisher.AfterChange(this, "CurrentScenarioName");
}
}
[XmlIgnore]
public string CurrentCalculation
{
get
{
return currentCalculation;
}
set
{
DataEventPublisher.BeforeChange(this, "CurrentCalculation");
currentCalculation = value;
LocationJob.CurrentCalculation = value;
DataEventPublisher.DataListModified(DamProjectData.LocationJobs);
DataEventPublisher.AfterChange(this, "CurrentCalculation");
}
}
[XmlIgnore]
public DateTime CurrentDateTime
{
get
{
return currentDateTime;
}
set
{
DataEventPublisher.BeforeChange(this, "CurrentDateTime");
currentDateTime = value;
UpdateView();
LocationJob.CurrentTime = value;
DataEventPublisher.DataListModified(DamProjectData.LocationJobs);
DataEventPublisher.AfterChange(this, "CurrentDateTime");
}
}
[XmlIgnore]
public int CurrentView
{
get
{
return currentView;
}
set
{
DataEventPublisher.BeforeChange(this, "CurrentView");
currentView = value;
UpdateCurrentDateTime();
DataEventPublisher.AfterChange(this, "CurrentView");
}
}
public DamProjectData DamProjectData
{
get
{
return damProjectData;
}
set
{
damProjectData = value;
DataEventPublisher.AfterChange(this, "DamProjectData");
}
}
public void Update(IEnumerable locationJobs)
{
minDateTime = DateTime.MaxValue;
maxDateTime = DateTime.MinValue;
//Todo Why is this timeserie part of ..Symbol and not part of LocationJob itself
foreach (LocationJob locationJob in locationJobs)
{
if (locationJob.LocationResult != null)
{
foreach (TimeSerieEntry entry in locationJob.LocationResult.StabilityTimeSerie.Entries)
{
if (entry.DateTime < minDateTime)
{
minDateTime = entry.DateTime;
}
if (entry.DateTime > maxDateTime)
{
maxDateTime = entry.DateTime;
}
}
if (locationJob.LocationResult.StabilityTimeSerie.Entries.Count == 0 && locationJob.WaterLevelTimeSerie != null)
{
foreach (TimeSerieEntry entry in locationJob.WaterLevelTimeSerie.Entries)
{
if (entry.DateTime < minDateTime)
{
minDateTime = entry.DateTime;
}
if (entry.DateTime > maxDateTime)
{
maxDateTime = entry.DateTime;
}
}
}
}
}
UpdateCurrentDateTime();
}
private void DataEventPublisher_OnAfterChange(object sender, PublishEventArgs e)
{
if (sender == damProjectData)
{
DataEventPublisher.AfterChange(this);
}
}
private void UpdateCurrentDateTime()
{
TimeSpan span = maxDateTime - minDateTime;
if (span.TotalSeconds >= 0)
{
CurrentDateTime = minDateTime.AddSeconds(currentView * span.TotalSeconds / 100);
}
}
private void UpdateView()
{
TimeSpan span = maxDateTime - minDateTime;
TimeSpan spanUntilView = currentDateTime - minDateTime;
if (span.TotalSeconds == 0)
{
currentView = 0;
}
else
{
currentView = Convert.ToInt32(100 * spanUntilView.TotalSeconds / span.TotalSeconds);
currentView = Math.Max(0, currentView);
currentView = Math.Min(100, currentView);
}
}
#region IVisibleEnabled Members
public bool IsVisible(string property)
{
if (damProjectData != null)
{
switch (property)
{
case "CurrentView":
case "CurrentDateTime":
return DamProjectData.DamProjectType == DamProjectType.DamLiveConfiguration;
case "CurrentProfileName": return false;
case "CurrentScenarioName": return false;
case "CurrentCalculation": return false;
default:
return true;
}
}
return true;
}
public bool IsEnabled(string property)
{
if (damProjectData != null)
{
switch (property)
{
case "CurrentView":
case "CurrentDateTime":
return DamProjectData != null && DamProjectData.DamProjectType == DamProjectType.DamLiveConfiguration &&
DamProjectData.LocationJobs != null && DamProjectData.LocationJobs.Count > 0;
case "CurrentProfileName": return false;
case "CurrentScenarioName": return false;
case "CurrentCalculation": return false;
default:
return true;
}
}
return true;
}
#endregion
}
}