/// <summary> /// Erzeugt eine neue Beschreibung. /// </summary> /// <param name="context">Vom Anwender der Schnittstelle zusätzlich bereitgestellte Daten.</param> /// <param name="name">Eine Name zur Identifikation der Aufzeichnung.</param> /// <param name="uniqueIdentifier">Die eindeutige Kennung der Aufzeichnung.</param> /// <param name="resources">Die Liste aller Geräte, die verwendet werden dürfen.</param> /// <param name="source">Die gewünschte Quelle.</param> /// <param name="start">Der Beginn der Aufzeichnung.</param> /// <param name="duration">Die Dauer der Aufzeichnung.</param> public _OneOffItem(UserDataType context, string name, Guid uniqueIdentifier, IScheduleResource[] resources, IScheduleSource source, DateTime start, TimeSpan duration) { // Validate if (source == null) { throw new ArgumentNullException("source"); } if (start.Year < 2000) { throw new ArgumentOutOfRangeException("start", string.Format(Properties.InterfaceResources.Exception_StartYear, start)); } if (duration.TotalSeconds <= 0) { throw new ArgumentOutOfRangeException("duration", string.Format(Properties.InterfaceResources.Exception_Duration, duration)); } if (resources != null) { if (resources.Any(r => r == null)) { throw new ArgumentNullException("resources"); } } // Create compound information m_Plan = new PlannedTime { Start = start, Duration = duration }; // Remember simple information Resources = resources ?? new IScheduleResource[0]; UniqueIdentifier = uniqueIdentifier; Context = context; Source = source; Name = name; }
/// <summary> /// Erzeugt eine neue Beschreibung. /// </summary> /// <param name="map">Die zugehörige Verwaltung einer Ressource.</param> /// <param name="source">Die Quelle, die verwendet werden soll.</param> /// <param name="plan">Die ursprüngliche Planung.</param> /// <param name="index">Der erste Eintrag in der Verwaltung, der belegt werden soll.</param> public AllocationPlan(AllocationMap map, IScheduleSource source, SuggestedPlannedTime plan, int index) { // Remember m_allocationIndex = index; m_source = source; m_plan = plan; m_map = map; }
/// <summary> /// Fordert eine Entschlüsselung an. /// </summary> /// <param name="source">Die zu verwendende Quelle.</param> /// <param name="timeHolder">Der Zeitraum, für den die Planung stattfinden soll.</param> /// <returns>Gesetzt, wenn eine Zuordnung überhaupt möglich ist. Gemeldet wird dann der Zeitversatz der Zuordnung.</returns> public AllocationPlan PrepareAllocation(IScheduleSource source, SuggestedPlannedTime timeHolder) { // Extract the time to use for plannung var time = timeHolder.Planned; // As long as needed for (var scanStart = 0; ;) { // See if there is at least one allocation area available var allocationIndex = m_Allocations.FindIndex(scanStart, a => a.Overlaps(time)); if (allocationIndex < 0) { return(null); } // On the start skip all having no recording left while (!m_Allocations[allocationIndex].CanAllocate(source)) { if (++allocationIndex == m_Allocations.Count) { return(null); } else if (!m_Allocations[allocationIndex].Overlaps(time)) { return(null); } } // Initial index - where we start the allocation var startIndex = allocationIndex; // Now make sure that we can record to the end - allocation maps from the beginning to the end of all times while (++allocationIndex < m_Allocations.Count) { if (!m_Allocations[allocationIndex].Overlaps(time)) { break; } else if (!m_Allocations[allocationIndex].CanAllocate(source)) { // Prepare to rescan scanStart = allocationIndex + 1; // Do not end startIndex = -1; // Done with loop break; } } // Response if (startIndex >= 0) { return(new AllocationPlan(this, source, timeHolder, startIndex)); } } }
/// <summary> /// Aktiviert eine Aufzeichnung auf einem Gerät. /// </summary> /// <param name="resource">Eines der verwalteten Geräte.</param> /// <param name="source">Optional eine Quelle, die auf dem Gerät angesteuert werden kann.</param> /// <param name="scheduleIdentifier">Die eindeutige Kennung der Aufzeichnung.</param> /// <param name="scheduleName">Der Anzeigename der Aufzeichnung.</param> /// <param name="plannedStart">Der ursprüngliche Start der Aufzeichnung in UTC / GMT Notation.</param> /// <param name="currentEnd">Das aktuelle Ende der Aufzeichnung in UTC / GMT Notation.</param> /// <returns>Gesetzt, wenn die Aufzeichnung auf dem gewünschten Gerät aktiviert werden kann.</returns> /// <exception cref="ArgumentNullException">Es wurde kein Gerät angegeben.</exception> /// <exception cref="ArgumentException">Das Gerät ist nicht bekannt oder kann die Quelle nicht empfangen.</exception> /// <exception cref="ArgumentOutOfRangeException">Die Laufzeit der Aufzeichnung ist nicht positiv.</exception> public bool Start(IScheduleResource resource, IScheduleSource source, Guid scheduleIdentifier, string scheduleName, DateTime plannedStart, DateTime currentEnd) { // Validate if (resource == null) { throw new ArgumentNullException("resource"); } if (!m_Resources.Contains(resource)) { throw new ArgumentException(resource.Name, "resource"); } if (plannedStart >= currentEnd) { throw new ArgumentOutOfRangeException("currentEnd"); } if (m_Recordings.Any(r => r.UniqueIdentifier == scheduleIdentifier)) { throw new ArgumentException("resource"); } // Create helper entry m_Recordings.Add(new ResourceAllocationInformation(resource, source, scheduleIdentifier, scheduleName, plannedStart, currentEnd - plannedStart)); // May require cleanup try { // Create the new plan var plan = CreateSchedulePlan(); // Did it if (plan != null) { // Remember as current m_CurrentPlan = plan; // Report return(true); } } catch { // Cleanup m_Recordings.RemoveAt(m_Recordings.Count - 1); // Report throw; } // Cleanup m_Recordings.RemoveAt(m_Recordings.Count - 1); // Add to list return(false); }
/// <summary> /// Erzeugt eine neue Beschreibung. /// </summary> /// <param name="resource">Das zugehörige Gerät.</param> /// <param name="source">Optional die zu verwendende Quelle.</param> /// <param name="identifier">Die eindeutige Kennung der zugehörigen Aufzeichnung oder Aufgabe.</param> /// <param name="name">Der Name der Aufzeichnung.</param> /// <param name="start">Der Startzeitpunkt.</param> /// <param name="duration">Die Dauer der Aufzeichnung.</param> /// <exception cref="ArgumentOutOfRangeException">Die Dauer der Aufzeichnung ist negativ.</exception> public ResourceAllocationInformation( IScheduleResource resource, IScheduleSource source, Guid identifier, string name, DateTime start, TimeSpan duration ) { // Validate if (duration.TotalSeconds <= 0) throw new ArgumentOutOfRangeException( "duration" ); // Remember all Time = new PlannedTime { Start = start, Duration = duration }; Resources = new[] { resource }; UniqueIdentifier = identifier; Source = source; Name = name; }
/// <summary> /// Reserviert eine Quelle. /// </summary> /// <param name="source">Die Quelle, die nun verwendet werden soll.</param> /// <exception cref="ArgumentNullException">Es wurde keine Quelle angegeben.</exception> public void Allocate(IScheduleSource source) { // Validate if (source == null) { throw new ArgumentNullException("source"); } // Remember if (!Sources.Any(s => s.IsSameAs(source))) { Sources.Add(source); } }
/// <summary> /// Meldet, ob eine Quelle zu einer Liste von Quellen passt. /// </summary> /// <param name="source">Die Quelle.</param> /// <param name="sources">Die Liste der Quellen.</param> /// <returns>Gesetzt, wenn die Quelle passt.</returns> private bool CanMerge(IScheduleSource source, IEnumerable <IScheduleSource> sources) { // Check it var mergeTest = m_MergeTest; if (mergeTest == null) { return(true); } else { return(mergeTest(source, sources)); } }
/// <summary> /// Prüft ob zwei Quellen identisch sind. /// </summary> /// <param name="source">Eine andere Quelle.</param> /// <returns>Gesetzt, wenn die Quellen identisch sind.</returns> public bool IsSameAs(IScheduleSource source) { // Pre-test if (!BelongsToSameSourceGroupAs(source)) { return(false); } // Can now safe cast var typedSource = source as SourceMock; // Just test the identification return(Equals(Name, typedSource.Name)); }
/// <summary> /// Prüft, ob diese Quelle mit einer anderen parallel aufgezeichnet werden kann. /// </summary> /// <param name="source">Eine andere Quelle.</param> /// <returns>Gesetzt, wenn eine parallele Aufzeichnung theoretisch möglich ist.</returns> public bool BelongsToSameSourceGroupAs(IScheduleSource source) { // Check type first var typedSource = source as SourceMock; if (typedSource == null) { return(false); } else { return(SourceGroup == typedSource.SourceGroup); } }
/// <summary> /// Prüft, ob eine Quelle zu einer Liste von Quellen hinzugefügt werden darf. /// </summary> /// <param name="source">Eine neue Quelle.</param> /// <param name="sources">Eine Liste von Quellen, durch genau diese Methode aller auf der /// selben Quellgruppe.</param> /// <returns>Gesetzt, wenn die Quelle die korrekte Quellgruppe verwendet.</returns> private static bool CheckForSourceGroupMatch(IScheduleSource source, IEnumerable <IScheduleSource> sources) { // Process var any = sources.FirstOrDefault(); if (any == null) { return(true); } else { return(any.BelongsToSameSourceGroupAs(source)); } }
/// <summary> /// Prüft, ob eine Quelle reserviert werden kann. /// </summary> /// <param name="source">Die zu prüfende Quelle.</param> /// <returns>Gesetzt, wenn eine Reservierung möglich ist.</returns> public bool CanAllocate(IScheduleSource source) { // Test if (Sources.Any(s => s.IsSameAs(source))) { return(true); } else if (!m_Map.CanMerge(source, Sources)) { return(false); } else { return(Sources.Count < m_Map.TotalNumberOfSources); } }
/// <summary> /// Prüft, ob eine bestimmte Quelle über dieses Gerät angesprochen werden kann. /// </summary> /// <param name="source">Die gewünschte Quelle.</param> /// <returns>Gesetzt, wenn die Quelle angesprochen werden kann.</returns> /// <exception cref="ArgumentNullException">Es wurde keine Quelle angegeben.</exception> /// <exception cref="ArgumentException">Die Quelle passt nicht zu dieser Art von Gerät.</exception> public bool CanAccess(IScheduleSource source) { // Validate if (source == null) { throw new ArgumentNullException("source"); } // Check type var typedSource = source as SourceType; if (typedSource == null) { throw new ArgumentException(source.GetType().FullName, "source"); } // Report return(TestAccess(typedSource)); }
/// <summary> /// Prüft, ob diese Quelle mit einer anderen parallel aufgezeichnet werden kann. /// </summary> /// <param name="source">Eine andere Quelle.</param> /// <returns>Gesetzt, wenn eine parallele Aufzeichnung theoretisch möglich ist.</returns> public bool BelongsToSameSourceGroupAs(IScheduleSource source) { // Check type first var typedSource = source as _Source; if (typedSource == null) { return(false); } // Check groups if (Equals(Source.Group, typedSource.Source.Group)) { return(Equals(Source.Location, typedSource.Source.Location)); } else { return(false); } }
/// <summary> /// Prüft, ob diese Quelle mit einer anderen parallel aufgezeichnet werden kann. /// </summary> /// <param name="source">Eine andere Quelle.</param> /// <returns>Gesetzt, wenn eine parallele Aufzeichnung theoretisch möglich ist.</returns> public bool BelongsToSameSourceGroupAs( IScheduleSource source ) { // Check type first var typedSource = source as SourceMock; if (typedSource == null) return false; else return (SourceGroup == typedSource.SourceGroup); }
/// <summary> /// Aktiviert eine Aufzeichnung auf einem Gerät. /// </summary> /// <param name="resource">Eines der verwalteten Geräte.</param> /// <param name="source">Optional eine Quelle, die auf dem Gerät angesteuert werden kann.</param> /// <param name="scheduleIdentifier">Die eindeutige Kennung der Aufzeichnung.</param> /// <param name="scheduleName">Der Anzeigename der Aufzeichnung.</param> /// <param name="plannedStart">Der ursprüngliche Start der Aufzeichnung in UTC / GMT Notation.</param> /// <param name="currentEnd">Das aktuelle Ende der Aufzeichnung in UTC / GMT Notation.</param> /// <returns>Gesetzt, wenn die Aufzeichnung auf dem gewünschten Gerät aktiviert werden kann.</returns> /// <exception cref="ArgumentNullException">Es wurde kein Gerät angegeben.</exception> /// <exception cref="ArgumentException">Das Gerät ist nicht bekannt oder kann die Quelle nicht empfangen.</exception> /// <exception cref="ArgumentOutOfRangeException">Die Laufzeit der Aufzeichnung ist nicht positiv.</exception> public bool Start( IScheduleResource resource, IScheduleSource source, Guid scheduleIdentifier, string scheduleName, DateTime plannedStart, DateTime currentEnd ) { // Validate if (resource == null) throw new ArgumentNullException( "resource" ); if (!m_Resources.Contains( resource )) throw new ArgumentException( resource.Name, "resource" ); if (plannedStart >= currentEnd) throw new ArgumentOutOfRangeException( "currentEnd" ); if (m_Recordings.Any( r => r.UniqueIdentifier == scheduleIdentifier )) throw new ArgumentException( "resource" ); // Create helper entry m_Recordings.Add( new ResourceAllocationInformation( resource, source, scheduleIdentifier, scheduleName, plannedStart, currentEnd - plannedStart ) ); // May require cleanup try { // Create the new plan var plan = CreateSchedulePlan(); // Did it if (plan != null) { // Remember as current m_CurrentPlan = plan; // Report return true; } } catch { // Cleanup m_Recordings.RemoveAt( m_Recordings.Count - 1 ); // Report throw; } // Cleanup m_Recordings.RemoveAt( m_Recordings.Count - 1 ); // Add to list return false; }
/// <summary> /// Korrigiert einen Abruf einer Entschlüsselung. /// </summary> /// <param name="allocationIndex">Die laufende Nummer des zu belegenden Eintrags.</param> /// <param name="source">Die zu verwendende Quelle.</param> /// <param name="time">Der Zeitraum, in dem eine Entschlüsselung aktiv ist.</param> private void Allocate(int allocationIndex, IScheduleSource source, ref PlannedTime time) { // Reset all caches - just in case... m_cachedResourceStartTimes = null; m_sourceUsage = null; // We are now using the source if (!m_Sources.Any(s => s.IsSameAs(source))) { m_Sources.Add(source); } // Localize time - can not use ref parameters inside a delegate var timeCopy = time; // Find the one the prepare analysis gave us - no further tests will be made! var allocation = m_Allocations[allocationIndex]; // See if we have to clip if (time.Start < allocation.Start) { // Do the clip time.Duration = time.End - allocation.Start; time.Start = allocation.Start; } // Correct it all for (; ;) { // On change we must create a clone var allocationIsPrivate = false; // Create a new starter if (time.Start > allocation.Start) { // Create a new allocation entry var split = allocation.Clone(allocation.Start, time.Start); // Add it just in front of the current one m_Allocations.Insert(allocationIndex++, split); // Must create a brand new one allocation = allocation.Clone(time.Start, allocation.End); // Update in our private list m_Allocations[allocationIndex] = allocation; // We can now safely overwrite it allocationIsPrivate = true; } // Create a new trailer if (time.End < allocation.End) { // Create a new allocation entry var split = allocation.Clone(time.End, allocation.End); // Add it just behind the current one m_Allocations.Insert(allocationIndex + 1, split); // Update the allocation if (allocationIsPrivate) { // We are allowed to change it allocation.End = time.End; } else { // Must create a brand new one allocation = allocation.Clone(allocation.Start, time.End); // Update in our private list m_Allocations[allocationIndex] = allocation; // We are now allowed to write to it allocationIsPrivate = true; } } // Update the allocation if (allocationIsPrivate) { // Just count down allocation.Allocate(source); } else { // Must create a brand new one allocation = allocation.Clone(allocation.Start, allocation.End); // Correct allocation.Allocate(source); // Update in our private list m_Allocations[allocationIndex] = allocation; } // See if we are done if (time.End <= allocation.End) { break; } // Load the next allocation area allocation = m_Allocations[++allocationIndex]; } }
/// <summary> /// Prüft ob zwei Quellen identisch sind. /// </summary> /// <param name="source">Eine andere Quelle.</param> /// <returns>Gesetzt, wenn die Quellen identisch sind.</returns> public bool IsSameAs( IScheduleSource source ) { // Pre-test if (!BelongsToSameSourceGroupAs( source )) return false; // Can now safe cast var typedSource = source as SourceMock; // Just test the identification return Equals( Name, typedSource.Name ); }
/// <summary> /// Erzeugt eine neue Beschreibung. /// </summary> /// <param name="context">Vom Anwender der Schnittstelle zusätzlich bereitgestellte Daten.</param> /// <param name="name">Eine Name zur Identifikation der Aufzeichnung.</param> /// <param name="uniqueIdentifier">Die eindeutige Kennung der Aufzeichnung.</param> /// <param name="resources">Die Liste aller Geräte, die verwendet werden dürfen.</param> /// <param name="source">Die gewünschte Quelle.</param> /// <param name="start">Der Beginn der Aufzeichnung.</param> /// <param name="end">Der Tag der letzten Aufzeichnung.</param> /// <param name="duration">Die Dauer der Aufzeichnung.</param> /// <param name="pattern">Die Liste der Tage, an denen die Aufzeichnung stattfinden soll.</param> public _RepeatingItem(UserDataType context, string name, Guid uniqueIdentifier, IScheduleResource[] resources, IScheduleSource source, DateTime start, DateTime end, TimeSpan duration, IEnumerable <DayOfWeek> pattern) : base(context, name, uniqueIdentifier, resources, source, start, duration) { // Unmap var localStartDate = start.ToLocalTime().Date; var days = pattern.ToArray(); // Remember m_Pattern = new HashSet <DayOfWeek>(days); m_End = end; // Validate if (end.TimeOfDay != TimeSpan.Zero) { throw new ArgumentException(string.Format(Properties.InterfaceResources.Exception_EndNotDay, end), "end"); } if (end < localStartDate) { throw new ArgumentException(string.Format(Properties.InterfaceResources.Exception_EndDay, localStartDate, end), "end"); } if (m_Pattern.Count < 1) { throw new ArgumentException(Properties.InterfaceResources.Exception_EmptyPattern, "pattern"); } if (m_Pattern.Count != days.Length) { throw new ArgumentException(Properties.InterfaceResources.Exception_BadPattern, "pattern"); } }
/// <summary> /// Erzeugt eine einmalige Aufzeichnung. /// </summary> /// <param name="context">Vom Anwender zusätzlich bereitgestellte Daten.</param> /// <param name="name">Eine Name zur Identifikation der Aufzeichnung.</param> /// <param name="uniqueIdentifier">Die eindeutige Kennung der Aufzeichnung.</param> /// <param name="resources">Die Liste aller Geräte, die verwendet werden dürfen.</param> /// <param name="source">Die zu verwendende Quelle.</param> /// <param name="start">Der Beginn der Aufzeichnung in UTC / GMT Notation.</param> /// <param name="duration">Die Dauer der Aufzeichnung.</param> /// <typeparam name="UserDataType">Vom Benutzer zusätzlich bereitgestellte Informationen.</typeparam> /// <returns>Die Beschreibung der Aufzeichnung.</returns> /// <exception cref="ArgumentNullException">Es wurde keine Quelle angegeben.</exception> /// <exception cref="ArgumentOutOfRangeException">Der Startzeitpunkt liegt vor dem Jahr 2000 oder /// die Dauer ist nicht positiv.</exception> public static IRecordingDefinition <UserDataType> Create <UserDataType>(UserDataType context, string name, Guid uniqueIdentifier, IScheduleResource[] resources, IScheduleSource source, DateTime start, TimeSpan duration) { // Use the simple implementation return(new _OneOffItem <UserDataType>(context, name, uniqueIdentifier, resources, source, start, duration)); }
/// <summary> /// Erzeugt eine sich wiederholende Aufzeichnung. /// </summary> /// <param name="context">Vom Anwender zusätzlich bereitgestellte Daten.</param> /// <param name="name">Eine Name zur Identifikation der Aufzeichnung.</param> /// <param name="uniqueIdentifier">Die eindeutige Kennung der Aufzeichnung.</param> /// <param name="resources">Die Liste aller Geräte, die verwendet werden dürfen.</param> /// <param name="source">Die zu verwendende Quelle.</param> /// <param name="start">Der Beginn der Aufzeichnung in UTC / GMT Notation.</param> /// <param name="duration">Die Dauer der Aufzeichnung.</param> /// <param name="end">Der Tag in der lokalen Zeitzone, an dem die Aufzeichnung letztmalig ausgeführt werden soll.</param> /// <param name="dayPattern">Die Tage in der lokalen Zeitzone, an denen eine Aufzeichnung stattfinden soll.</param> /// <typeparam name="UserDataType">Vom Benutzer zusätzlich bereitgestellte Informationen.</typeparam> /// <returns>Die Beschreibung der Aufzeichnung.</returns> /// <exception cref="ArgumentNullException">Es wurde keine Quelle angegeben.</exception> /// <exception cref="ArgumentOutOfRangeException">Der Startzeitpunkt liegt vor dem Jahr 2000 oder /// die Dauer ist nicht positiv.</exception> public static IRecordingDefinition <UserDataType> Create <UserDataType>(UserDataType context, string name, Guid uniqueIdentifier, IScheduleResource[] resources, IScheduleSource source, DateTime start, TimeSpan duration, DateTime end, params DayOfWeek[] dayPattern) { // Use the repeating implementation which will do some more tests return(new _RepeatingItem <UserDataType>(context, name, uniqueIdentifier, resources, source, start, end, duration, dayPattern ?? Enumerable.Empty <DayOfWeek>())); }