313 lines
10 KiB
C#
313 lines
10 KiB
C#
// Copyright (c) 2023 schick Informatik
|
|
// Description: Container model for shipcall related info
|
|
//
|
|
|
|
using BreCalClient.misc.Api;
|
|
using BreCalClient.misc.Model;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace BreCalClient
|
|
{
|
|
|
|
/// <summary>
|
|
/// Container model to aggregate separate models for the Shipcall control data binding
|
|
/// </summary>
|
|
public class ShipcallControlModel
|
|
{
|
|
|
|
#region Enumerations
|
|
|
|
[Flags]
|
|
public enum StatusFlags
|
|
{
|
|
RED,
|
|
GREEN,
|
|
YELLOW,
|
|
BLINK_1,
|
|
BLINK_2
|
|
};
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public Shipcall? Shipcall { get; set; }
|
|
|
|
public Ship? Ship { get; set; }
|
|
|
|
public string? Berth { get; set; }
|
|
|
|
internal Dictionary<Extensions.ParticipantType, ParticipantAssignment> AssignedParticipants { get; } = new();
|
|
|
|
public List<Times> Times { get; set; } = new();
|
|
|
|
public DateTime? Eta
|
|
{
|
|
get
|
|
{
|
|
Times? agencyTimes = this.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY);
|
|
if((agencyTimes != null) && (agencyTimes.EtaBerth != null))
|
|
return agencyTimes.EtaBerth;
|
|
return Shipcall?.Eta;
|
|
}
|
|
}
|
|
|
|
public DateTime? Etd
|
|
{
|
|
get
|
|
{
|
|
Times? agencyTimes = this.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY);
|
|
if ((agencyTimes != null) && (agencyTimes.EtdBerth != null))
|
|
return agencyTimes.EtdBerth;
|
|
return Shipcall?.Etd;
|
|
}
|
|
}
|
|
|
|
public EvaluationType LightMode
|
|
{
|
|
get
|
|
{
|
|
EvaluationType elm = EvaluationType.Undefined;
|
|
|
|
if (this.Shipcall != null)
|
|
{
|
|
if(this.Shipcall.Evaluation.HasValue)
|
|
{
|
|
elm = this.Shipcall.Evaluation.Value;
|
|
}
|
|
}
|
|
return elm;
|
|
}
|
|
}
|
|
|
|
public string Title
|
|
{
|
|
get
|
|
{
|
|
if (this.Shipcall == null) return "";
|
|
return string.Format("{0} {1}", this.Shipcall.Type, this.Ship?.Name);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This property attempts to store the (hopefully short) shifting sequence in the topmost
|
|
/// byte of the "flags" integer which will not be used for the forseeable future
|
|
///
|
|
/// This is a workaround to avoid adding another field to the interface and is only used in the
|
|
/// client display anyway. You could say hack as well.
|
|
/// </summary>
|
|
public byte? ShiftSequence
|
|
{
|
|
get
|
|
{
|
|
if((this.Shipcall == null) || (this.Shipcall.Flags == null)) return null;
|
|
return (byte?) (this.Shipcall?.Flags >> 24);
|
|
}
|
|
set
|
|
{
|
|
if ((value != null) && (this.Shipcall != null))
|
|
{
|
|
int currentFlag = this.Shipcall.Flags ?? 0;
|
|
int moveUp = ((value ?? 0) << 24);
|
|
this.Shipcall.Flags = (currentFlag & 0xffffff) | moveUp;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region public methods
|
|
|
|
public void AssignParticipants()
|
|
{
|
|
this.AssignedParticipants.Clear();
|
|
if (Shipcall != null)
|
|
{
|
|
foreach (ParticipantAssignment participantAssignment in Shipcall.Participants)
|
|
{
|
|
AssignedParticipants[(Extensions.ParticipantType)participantAssignment.Type] = participantAssignment;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal Times? GetTimesForParticipantType(Extensions.ParticipantType type)
|
|
{
|
|
|
|
if (AssignedParticipants.ContainsKey(type)) {
|
|
int participantId = AssignedParticipants[type].ParticipantId;
|
|
foreach (Times times in this.Times)
|
|
{
|
|
if ((times.ParticipantId == participantId) && (times.ParticipantType == (int) type))
|
|
return times;
|
|
}
|
|
if(type == Extensions.ParticipantType.AGENCY)
|
|
{
|
|
// if I am BSMD and no agency entry was found this means we are editing the agency entry
|
|
if(App.Participant.Type == (int) Extensions.ParticipantType.BSMD)
|
|
{
|
|
foreach(Times times in this.Times)
|
|
{
|
|
if ((times.ParticipantId == App.Participant.Id) && (times.ParticipantType == (int) Extensions.ParticipantType.AGENCY))
|
|
return times;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public bool ContainsRemarkText(string text)
|
|
{
|
|
if(Shipcall != null)
|
|
{
|
|
foreach(Times times in this.Times)
|
|
{
|
|
if (times.Remarks == null) continue;
|
|
if(times.Remarks.Contains(text)) return true;
|
|
}
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get berth display text for columns AGENT and TERMINAL
|
|
/// </summary>
|
|
public string? GetBerthText(Times? times)
|
|
{
|
|
string? timesBerthText = null;
|
|
string? scArrivalBerthText = null;
|
|
string? scDepartureBerthText = null;
|
|
string? berthText = null;
|
|
Berth? berth;
|
|
|
|
if((times != null) && times.BerthId.HasValue)
|
|
{
|
|
berth = BreCalLists.AllBerths.Find((x) => x.Id == times.BerthId.Value);
|
|
timesBerthText = berth?.Name;
|
|
}
|
|
|
|
berth = BreCalLists.AllBerths?.Find((x) => x.Id == this.Shipcall?.ArrivalBerthId);
|
|
scArrivalBerthText = berth?.Name;
|
|
|
|
berth = BreCalLists.AllBerths?.Find((x) => x.Id == this.Shipcall?.DepartureBerthId);
|
|
scDepartureBerthText= berth?.Name;
|
|
|
|
switch(this.Shipcall?.Type)
|
|
{
|
|
case ShipcallType.Arrival:
|
|
berthText = timesBerthText ?? scArrivalBerthText;
|
|
break;
|
|
case ShipcallType.Departure:
|
|
berthText = timesBerthText ?? scDepartureBerthText;
|
|
break;
|
|
case ShipcallType.Shifting:
|
|
if (times?.ParticipantType != (int)Extensions.ParticipantType.TERMINAL)
|
|
berthText = (scDepartureBerthText ?? "") + " / " + (timesBerthText ?? scArrivalBerthText);
|
|
else
|
|
berthText = scDepartureBerthText ?? "";
|
|
break;
|
|
default: break;
|
|
}
|
|
|
|
return berthText;
|
|
}
|
|
|
|
public string GetETAETD()
|
|
{
|
|
DateTime theDate = DateTime.Now;
|
|
if(this.Shipcall != null)
|
|
{
|
|
if (this.Shipcall.Type == ShipcallType.Arrival)
|
|
theDate = this.Shipcall.Eta ?? DateTime.Now;
|
|
else
|
|
theDate = this.Shipcall.Etd ?? DateTime.Now;
|
|
}
|
|
Times? agentTimes = this.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY);
|
|
if(agentTimes != null)
|
|
{
|
|
if(this.Shipcall?.Type == ShipcallType.Arrival)
|
|
{
|
|
if (agentTimes.EtaBerth != null)
|
|
theDate = agentTimes.EtaBerth.Value;
|
|
}
|
|
else
|
|
{
|
|
if (agentTimes.EtdBerth != null)
|
|
theDate = agentTimes.EtdBerth.Value;
|
|
}
|
|
}
|
|
return theDate.ToString();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// After closing the edit shipcall or edit agency dialogs, the times assignments may have changed.
|
|
/// This function updates the assignments for existing times records accordingly and saves them.
|
|
/// </summary>
|
|
/// <param name="_api">API reference to PUT eidted times</param>
|
|
internal async void UpdateTimesAssignments(TimesApi api)
|
|
{
|
|
foreach (Extensions.ParticipantType participantType in this.AssignedParticipants.Keys)
|
|
{
|
|
Times? times = this.GetTimesForParticipantType(participantType);
|
|
if(times == null) continue;
|
|
if(times.ParticipantId != this.AssignedParticipants[participantType].ParticipantId)
|
|
{
|
|
times.ParticipantId = this.AssignedParticipants[participantType].ParticipantId;
|
|
await api.TimesUpdateAsync(times);
|
|
}
|
|
}
|
|
|
|
// if somebody just removed an assignment it is gone fom AssignedParticipants, but there is still a
|
|
// times record left which must be removed
|
|
|
|
List<Times> deleteTimes = new();
|
|
foreach (Times times in this.Times)
|
|
{
|
|
bool foundTimes = false;
|
|
foreach (ParticipantAssignment pa in this.AssignedParticipants.Values)
|
|
{
|
|
if((pa.ParticipantId == times.ParticipantId) && (pa.Type == times.ParticipantType))
|
|
{
|
|
foundTimes = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!foundTimes)
|
|
{
|
|
deleteTimes.Add(times);
|
|
}
|
|
}
|
|
|
|
foreach(Times times in deleteTimes)
|
|
{
|
|
api.TimesDelete(times.Id);
|
|
this.Times.Remove(times);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region helper
|
|
|
|
internal Participant? GetParticipantForType(Extensions.ParticipantType participantType)
|
|
{
|
|
if(AssignedParticipants.ContainsKey(participantType) && BreCalLists.ParticipantLookupDict.ContainsKey(AssignedParticipants[participantType].ParticipantId))
|
|
return BreCalLists.ParticipantLookupDict[AssignedParticipants[participantType].ParticipantId];
|
|
|
|
return null;
|
|
}
|
|
|
|
private bool IsFlagSet(StatusFlags flag)
|
|
{
|
|
if(this.Shipcall == null) return false;
|
|
return (this.Shipcall.Flags & (int) flag) != 0;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|