diff --git a/ENI2/DetailRootControl.xaml.cs b/ENI2/DetailRootControl.xaml.cs index d6066145..3a7b4a1f 100644 --- a/ENI2/DetailRootControl.xaml.cs +++ b/ENI2/DetailRootControl.xaml.cs @@ -1027,35 +1027,37 @@ namespace ENI2 #region Kiel Canal Timing Plausibility - if (!this.Core.IsTransit && (secMessage?.Elements.Count > 0) && (noanodMessage?.Elements.Count > 0)) { - SEC sec = secMessage.Elements[0] as SEC; - NOA_NOD noa_nod = noanodMessage.Elements[0] as NOA_NOD; - - if (sec.KielCanalPassagePlanned ?? false) + if (!this.Core.IsTransit && (secMessage?.Elements.Count > 0) && (noanodMessage?.Elements.Count > 0)) { - // Überprüfung, ob die eingehende NOK-Durchfahrt auch wirklich innerhalb der eingehenden Reise liegt (bei VISIT) - bool isValidIncoming = (noa_nod.ETDFromLastPort < sec.KielCanalPassagePlannedIncomming) && - (sec.KielCanalPassagePlannedIncomming < noa_nod.ETAToPortOfCall); - if (!sec.KielCanalPassagePlannedIncomming.HasValue) isValidIncoming = true; + SEC sec = secMessage.Elements[0] as SEC; + NOA_NOD noa_nod = noanodMessage.Elements[0] as NOA_NOD; - if(!isValidIncoming) + if (sec.KielCanalPassagePlanned ?? false) { - MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Kiel Canal incoming implausible (ETD / ETA ports)!", null, "Kiel Canal timing", null, "SEC"); - mv.MessageGroupName = Properties.Resources.textOverview; - vViolations.Add(mv); - } + // Überprüfung, ob die eingehende NOK-Durchfahrt auch wirklich innerhalb der eingehenden Reise liegt (bei VISIT) + bool isValidIncoming = (noa_nod.ETDFromLastPort < sec.KielCanalPassagePlannedIncomming) && + (sec.KielCanalPassagePlannedIncomming < noa_nod.ETAToPortOfCall); + if (!sec.KielCanalPassagePlannedIncomming.HasValue) isValidIncoming = true; + + if (!isValidIncoming) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Kiel Canal incoming implausible (ETD / ETA ports)!", null, "Kiel Canal timing", null, "SEC"); + mv.MessageGroupName = Properties.Resources.textOverview; + vViolations.Add(mv); + } - bool isValidOutgoing = (noa_nod.ETDFromPortOfCall < sec.KielCanalPassagePlannedOutgoing) && - ((noa_nod.NextPort == "ZZUKN") || (sec.KielCanalPassagePlannedOutgoing < noa_nod.ETAToNextPort)); - if (!sec.KielCanalPassagePlannedOutgoing.HasValue) isValidOutgoing = true; + bool isValidOutgoing = (noa_nod.ETDFromPortOfCall < sec.KielCanalPassagePlannedOutgoing) && + ((noa_nod.NextPort == "ZZUKN") || (sec.KielCanalPassagePlannedOutgoing < noa_nod.ETAToNextPort)); + if (!sec.KielCanalPassagePlannedOutgoing.HasValue) isValidOutgoing = true; - if(!isValidOutgoing) - { - MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Kiel Canal outgoing implausible (ETD / ETA ports)!", null, "Kiel Canal timing", null, "SEC"); - mv.MessageGroupName = Properties.Resources.textOverview; - vViolations.Add(mv); + if (!isValidOutgoing) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Kiel Canal outgoing implausible (ETD / ETA ports)!", null, "Kiel Canal timing", null, "SEC"); + mv.MessageGroupName = Properties.Resources.textOverview; + vViolations.Add(mv); + } } } } @@ -1212,6 +1214,127 @@ namespace ENI2 #endregion + #region WAS special max capa rules regarding next port + + { + // see WAS-Regulation.docx in parent projects misc folder + if ((noanodMessage?.Elements.Count > 0) && wasMessage?.Elements.Count > 0) + { + NOA_NOD noa_nod = noanodMessage.Elements[0] as NOA_NOD; + WAS was = wasMessage.Elements[0] as WAS; + + bool isSpecialNextPort = RuleEngine.IsSpecialNextPort(noa_nod.NextPort); + + if (isSpecialNextPort) + { + foreach (Waste waste in was.Waste) + { + switch (waste.WasteType) + { + case 101: + case 102: + case 103: + case 104: + case 105: + case 401: + if (waste.WasteAmountRetained_MTQ > waste.WasteCapacity_MTQ * 0.5) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Acc. to EU Regulation 2022/89 the amount retained on board is noticeably", null, "WAS", waste.Identifier, "WAS"); + mv.MessageGroupName = Properties.Resources.textPortNotification; + vViolations.Add(mv); + } + break; + case 501: + case 502: + case 503: + case 504: + case 505: + case 506: + case 507: + case 508: + case 509: + case 510: + case 511: + if (waste.WasteAmountRetained_MTQ > waste.WasteCapacity_MTQ * 0.25) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Acc. to EU Regulation 2022/89 the amount retained on board is noticeably", null, "WAS", waste.Identifier, "WAS"); + mv.MessageGroupName = Properties.Resources.textPortNotification; + vViolations.Add(mv); + } + break; + case 601: + case 602: + if (waste.WasteAmountRetained_MTQ > waste.WasteCapacity_MTQ * 0.75) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Acc. to EU Regulation 2022/89 the amount retained on board is noticeably", null, "WAS", waste.Identifier, "WAS"); + mv.MessageGroupName = Properties.Resources.textPortNotification; + vViolations.Add(mv); + } + break; + } + } + } + else + { + foreach (Waste waste in was.Waste) + { + switch (waste.WasteType) + { + case 101: + case 102: + case 103: + case 104: + case 105: + if (waste.WasteAmountRetained_MTQ > waste.WasteCapacity_MTQ * 0.25) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Acc. to EU Regulation 2022/89 the amount retained on board is noticeably", null, "WAS", waste.Identifier, "WAS"); + mv.MessageGroupName = Properties.Resources.textPortNotification; + vViolations.Add(mv); + } + break; + case 401: + if (waste.WasteAmountRetained_MTQ > waste.WasteCapacity_MTQ * 0.5) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Acc. to EU Regulation 2022/89 the amount retained on board is noticeably", null, "WAS", waste.Identifier, "WAS"); + mv.MessageGroupName = Properties.Resources.textPortNotification; + vViolations.Add(mv); + } + break; + case 501: + case 502: + case 503: + case 504: + case 505: + case 506: + case 507: + case 508: + case 509: + case 510: + case 511: + if (waste.WasteAmountRetained_MTQ > waste.WasteCapacity_MTQ * 0.2) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Acc. to EU Regulation 2022/89 the amount retained on board is noticeably", null, "WAS", waste.Identifier, "WAS"); + mv.MessageGroupName = Properties.Resources.textPortNotification; + vViolations.Add(mv); + } + break; + case 601: + case 602: + if (waste.WasteAmountRetained_MTQ > waste.WasteCapacity_MTQ * 0.25) + { + MessageViolation mv = RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Acc. to EU Regulation 2022/89 the amount retained on board is noticeably", null, "WAS", waste.Identifier, "WAS"); + mv.MessageGroupName = Properties.Resources.textPortNotification; + vViolations.Add(mv); + } + break; + } + } + } + } + } + + #endregion + #endregion foreach (MessageError me in vErrors) diff --git a/bsmd.database/RuleEngine.cs b/bsmd.database/RuleEngine.cs index f6c682d6..082712c4 100644 --- a/bsmd.database/RuleEngine.cs +++ b/bsmd.database/RuleEngine.cs @@ -97,6 +97,22 @@ namespace bsmd.database #endregion + #region for extra waste validation + + private static readonly HashSet SpecialNextPortPrefixes = new HashSet + { + "BE", "BG", "DK", "DE", "EE", "FI", "FR", "GR", "IR", "IT", + "HR", "LV", "LT", "LU", "MT", "NL", "AT", "PL", "PT", "RO", + "SE", "SK", "SL", "ES", "CZ", "HU", "CY", "NO", "IS", "GB", "GI" + }; + + private static readonly HashSet SpecialNextPortExact = new HashSet + { + "RUPRI", "RUULU", "RULED", "RUBLT", "RUKGD", "RUVYS" + }; + + #endregion + public enum LocodeMode { STANDARD, @@ -131,6 +147,20 @@ namespace bsmd.database public static LocodeValidHandler LocodeChecker { get { return _locodeChecker; } } public static NationalityValidHandler NationalityChecker { get { return _nationalityChecker; } } + /// + /// Used to test for special next port values for waste messages + /// + /// a locode + /// true if the next port is a special waste port + public static bool IsSpecialNextPort(string nextPort) + { + if (string.IsNullOrEmpty(nextPort) || nextPort.Length < 2) + return false; + + return SpecialNextPortExact.Contains(nextPort) || + SpecialNextPortPrefixes.Contains(nextPort.Substring(0, 2)); + } + #region public static property validation public static void RegisterLocodeChecker(LocodeValidHandler handler) { _locodeChecker = handler; } diff --git a/bsmd.database/Waste.cs b/bsmd.database/Waste.cs index feffc008..42e2b6f2 100644 --- a/bsmd.database/Waste.cs +++ b/bsmd.database/Waste.cs @@ -266,11 +266,13 @@ namespace bsmd.database if (this.WasteAmountGeneratedTillNextPort_MTQ >= 10000) errors.Add(RuleEngine.CreateError(ValidationCode.IMPLAUSIBLE, "Waste generated till next port too high", null, this.Title, this.Identifier, this.Tablename)); - if(this.WasteDisposalAmount_MTQ > this.WasteCapacity_MTQ) - violations.Add(RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Disposal greater than capacity!", null, this.Title, this.Identifier, this.Tablename)); + // Removed this for version 7.2.14 (new rules depending on next port implemented in ENI / DetailRootControl.cs) - if((this.WasteAmountGeneratedTillNextPort_MTQ + this.WasteAmountRetained_MTQ) > this.WasteCapacity_MTQ) - violations.Add(RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Waste generated+retained greater than capacity!", null, this.Title, this.Identifier, this.Tablename)); + // if(this.WasteDisposalAmount_MTQ > this.WasteCapacity_MTQ) + // violations.Add(RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Disposal greater than capacity!", null, this.Title, this.Identifier, this.Tablename)); + + // if((this.WasteAmountGeneratedTillNextPort_MTQ + this.WasteAmountRetained_MTQ) > this.WasteCapacity_MTQ) + // violations.Add(RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Waste generated+retained greater than capacity!", null, this.Title, this.Identifier, this.Tablename)); } #endregion diff --git a/misc/WAS-Regulation.docx b/misc/WAS-Regulation.docx new file mode 100644 index 00000000..9f016a00 Binary files /dev/null and b/misc/WAS-Regulation.docx differ