// Copyright (C) Stichting Deltares 2024. 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 Image GetSymbol(object data, bool selected) { var locationJob = data as LocationJob; CurrentLocationJob = locationJob; if (locationJob != null) { DamProjectType damProjectType = damProjectData.DamProjectType; if (damProjectType == DamProjectType.Calamity) { if (!locationJob.HasLocationResults) { return GetImage(GetColor(DamGlobalConstants.NoRunValue), selected); } DateTime dateTime = CurrentDateTime; TimeSerie timeSerie = locationJob.LocationResult.StabilityTimeSerie; double value = timeSerie.GetValue(dateTime); return GetImage(GetColor(value), selected); } } return GetImage(Color.Black, selected); } 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.Calamity; 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.Calamity && 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 } }