rama creada apartir de master en j

This commit is contained in:
jrojas
2026-06-26 10:29:23 +02:00
parent 319fd3dfb0
commit c1517fda87
2810 changed files with 1927392 additions and 25392 deletions
@@ -13,6 +13,9 @@ namespace adas_core.Application.Subscriptions;
/**
* This class is used to group the subscribers by the same group
*/
/// <summary>
/// Represents a grouped WebSocket subscriber that aggregates and manages multiple related subscription registrations.
/// </summary>
public class WsSubscriberGrouped
{
private readonly EventHandler<string> _sendEvent;
@@ -57,23 +60,27 @@ public class WsSubscriberGrouped
public Dictionary<string, string> Group { get; set; } = new();
public Timer Timer { get; set; }
/// <summary>
/// Refreshes the cached last observations by matching each known name against the supplied grouped observation, falling back to the most recent observation when no match is found.
/// </summary>
/// <param name="lastGroupedObservationObs">The source grouped observation whose observations are searched to populate the last-observation cache.</param>
public void UpdateLastGo(GroupedObservation lastGroupedObservationObs)
{
LastGroupedObservationObs.Clear();
foreach (var name in Names)
{
var lastObs = lastGroupedObservationObs.Observations.LastOrDefault(c => c.Name == name);
if (lastObs != null)
LastGroupedObservationObs.Clear();
foreach (var name in Names)
{
LastGroupedObservationObs.Add(lastObs);
}
else
{
lastObs = lastGroupedObservationObs.Observations.LastOrDefault();
if (lastObs != null) LastGroupedObservationObs.Add(lastObs);
var lastObs = lastGroupedObservationObs.Observations.LastOrDefault(c => c.Name == name);
if (lastObs != null)
{
LastGroupedObservationObs.Add(lastObs);
}
else
{
lastObs = lastGroupedObservationObs.Observations.LastOrDefault();
if (lastObs != null) LastGroupedObservationObs.Add(lastObs);
}
}
}
}
private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
{
@@ -124,104 +131,135 @@ public class WsSubscriberGrouped
TimerReestart();
}
/// <summary>
/// Restarts the timer by recalculating its interval through <c>SetUpTimerInterval</c> and then starting it.
/// </summary>
private void TimerReestart()
{
Timer.Interval = SetUpTimerInterval();
Timer.Start();
}
private int SetUpTimerInterval()
{
var currentDateTime = DateTime.Now;
int graceTime;
DateTime nextIntervalTime;
switch (Regularity)
{
case GroupedObservationEnum.Regularity.Second:
nextIntervalTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
currentDateTime.Hour,
currentDateTime.Minute,
currentDateTime.Second
).AddSeconds(1);
graceTime = 500;
break;
case GroupedObservationEnum.Regularity.Minute:
nextIntervalTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
currentDateTime.Hour,
currentDateTime.Minute,
0
).AddMinutes(1);
graceTime = 30000;
break;
case GroupedObservationEnum.Regularity.Day:
nextIntervalTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
0,
0,
0
).AddDays(1);
graceTime = 60000;
break;
default:
nextIntervalTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
currentDateTime.Hour,
0,
0
).AddHours(1);
graceTime = 30000;
break;
Timer.Interval = SetUpTimerInterval();
Timer.Start();
}
var timeSpanToNextInterval = nextIntervalTime - currentDateTime;
Log.Information(
"Obs {Obs}, currentDateTime: {CurrentDateTime}, nextIntervalTime: {NextIntervalTime}, timeSpanToNextInterval: {TimeSpanToNextInterval}, timeSpanToNextInterval.TotalMilliseconds+graceTime: {Tt}",
Group, currentDateTime, nextIntervalTime, timeSpanToNextInterval,
(int)timeSpanToNextInterval.TotalMilliseconds + graceTime);
return (int)timeSpanToNextInterval.TotalMilliseconds + graceTime;
}
/// <summary>
/// Calculates the timer interval in milliseconds until the next scheduled occurrence based on the configured <see cref="Regularity"/>, supporting Second, Minute, Day, and a default (Hour) case, and adds a per-regularity grace time.
/// </summary>
/// <returns>The number of milliseconds to wait until the next interval, including the grace time.</returns>
private int SetUpTimerInterval()
{
var currentDateTime = DateTime.Now;
int graceTime;
DateTime nextIntervalTime;
switch (Regularity)
{
case GroupedObservationEnum.Regularity.Second:
nextIntervalTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
currentDateTime.Hour,
currentDateTime.Minute,
currentDateTime.Second
).AddSeconds(1);
graceTime = 500;
break;
case GroupedObservationEnum.Regularity.Minute:
nextIntervalTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
currentDateTime.Hour,
currentDateTime.Minute,
0
).AddMinutes(1);
graceTime = 30000;
break;
case GroupedObservationEnum.Regularity.Day:
nextIntervalTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
0,
0,
0
).AddDays(1);
graceTime = 60000;
break;
default:
nextIntervalTime = new DateTime(
currentDateTime.Year,
currentDateTime.Month,
currentDateTime.Day,
currentDateTime.Hour,
0,
0
).AddHours(1);
graceTime = 30000;
break;
}
var timeSpanToNextInterval = nextIntervalTime - currentDateTime;
Log.Information(
"Obs {Obs}, currentDateTime: {CurrentDateTime}, nextIntervalTime: {NextIntervalTime}, timeSpanToNextInterval: {TimeSpanToNextInterval}, timeSpanToNextInterval.TotalMilliseconds+graceTime: {Tt}",
Group, currentDateTime, nextIntervalTime, timeSpanToNextInterval,
(int)timeSpanToNextInterval.TotalMilliseconds + graceTime);
return (int)timeSpanToNextInterval.TotalMilliseconds + graceTime;
}
}
/// <summary>
/// Provides static extension methods to enhance WebSocket subscriber functionality.
/// </summary>
public static class WsSubscriberExtension
{
/// <summary>
/// Determines whether the specified <see cref="GroupedField"/> and patient identifier match the current <see cref="WsSubscriberGrouped"/> instance by comparing regularity, since, start time shift, maximum, result sequence, patient identifier, and names (treating a null <paramref name="r"/>.Name as an empty string).
/// </summary>
/// <param name="source">The current <see cref="WsSubscriberGrouped"/> instance being compared.</param>
/// <param name="r">The <see cref="GroupedField"/> to compare against the source.</param>
/// <param name="patientId">The patient identifier to match against the source patient identifier.</param>
/// <returns><c>true</c> if all compared properties are equal; otherwise, <c>false</c>.</returns>
public static bool Compare(this WsSubscriberGrouped source, GroupedField r, ObjectId patientId)
{
return r.Regularity == source.Regularity &&
r.Since == source.Since &&
CompareStringShiftList(r.StartTimeShift, source.StartTimeShift) &&
r.Max == source.Max &&
r.Result.SequenceEqual(source.Result) &&
patientId.ToString() == source.PatientId.ToString() &&
CompareNamesStringList(r.Names, [r.Name ?? string.Empty], source.Names);
}
{
return r.Regularity == source.Regularity &&
r.Since == source.Since &&
CompareStringShiftList(r.StartTimeShift, source.StartTimeShift) &&
r.Max == source.Max &&
r.Result.SequenceEqual(source.Result) &&
patientId.ToString() == source.PatientId.ToString() &&
CompareNamesStringList(r.Names, [r.Name ?? string.Empty], source.Names);
}
/// <summary>
/// Compares two string shift lists for equality, returning true when both lists are null or when both contain the same elements in the same order, and false when only one of the lists is null.
/// </summary>
/// <param name="shift">The target shift list to compare.</param>
/// <param name="sourceShift">The source shift list to compare against.</param>
/// <returns><c>true</c> if both lists are null or if their sequence of strings is equal; otherwise, <c>false</c>.</returns>
private static bool CompareStringShiftList(List<string>? shift, List<string>? sourceShift)
{
if (shift != null && sourceShift != null) return sourceShift.SequenceEqual(shift);
if (shift == null && sourceShift == null) return true;
return false;
}
{
if (shift != null && sourceShift != null) return sourceShift.SequenceEqual(shift);
if (shift == null && sourceShift == null) return true;
return false;
}
/// <summary>
/// Compares the <paramref name="sourceNames"/> list against two candidate name lists and returns whether either one matches.
/// Falls back to the second list (<paramref name="name"/>) when the first (<paramref name="names"/>) is empty or null, or does not match.
/// </summary>
/// <param name="names">The primary candidate list of names to compare against <paramref name="sourceNames"/>.</param>
/// <param name="name">The fallback candidate list of names to compare against <paramref name="sourceNames"/> when <paramref name="names"/> cannot be used.</param>
/// <param name="sourceNames">The source list of names being compared.</param>
/// <returns><c>true</c> if <paramref name="sourceNames"/> is a sequence match for either <paramref name="names"/> or <paramref name="name"/>; otherwise, <c>false</c>.</returns>
private static bool CompareNamesStringList(List<string> names, List<string> name, List<string> sourceNames)
{
if (!CollectionsUtils.IsEmptyOrNull(names) && sourceNames.SequenceEqual(names)) return true;
return !CollectionsUtils.IsEmptyOrNull(name) && sourceNames.SequenceEqual(name);
}
{
if (!CollectionsUtils.IsEmptyOrNull(names) && sourceNames.SequenceEqual(names)) return true;
return !CollectionsUtils.IsEmptyOrNull(name) && sourceNames.SequenceEqual(name);
}
/// <summary>
/// Check if the incoming observation affect to the group and is new info or is irrelevant