diff --git a/CBSVisualizer/CBSVisualizer.Common/Extensions/SynchronizationExtensions.cs b/CBSVisualizer/CBSVisualizer.Common/Extensions/SynchronizationExtensions.cs index 127733cb2d16193caa8679f067271d487b8f9f4b..90c4904a2db18c70155aa92673f932d94e946ae1 100644 --- a/CBSVisualizer/CBSVisualizer.Common/Extensions/SynchronizationExtensions.cs +++ b/CBSVisualizer/CBSVisualizer.Common/Extensions/SynchronizationExtensions.cs @@ -14,6 +14,17 @@ namespace CBSVisualizer.Common.Extensions } } + public static void ClearSynchronized(this ObservableCollection<PriorityPacket> collection) + { + lock (collection) + { + if (collection.Count > 0) + { + collection.Clear(); + } + } + } + public static void PrependSynchronized(this ObservableCollection<PriorityPacket> collection, PriorityPacket newPacket) { lock (collection) diff --git a/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISetting.cs b/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISetting.cs new file mode 100644 index 0000000000000000000000000000000000000000..01f8c42ad2fa7efaee286a2356b07424d20f26da --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISetting.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CBSVisualizer.Common.Interfaces +{ + public interface ISetting : INotifyPropertyChanged + { + public string Name { get; } + + public string Key { get; } + } +} diff --git a/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISettingGroup.cs b/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISettingGroup.cs new file mode 100644 index 0000000000000000000000000000000000000000..4e1b2ac9f0e941d64d656df9554ff09e44945721 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISettingGroup.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CBSVisualizer.Common.Interfaces +{ + public interface ISettingGroup + { + public string GroupName { get; } + + public ReadOnlyObservableCollection<ISetting> Members { get; } + } +} diff --git a/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISettingService.cs b/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISettingService.cs new file mode 100644 index 0000000000000000000000000000000000000000..d730634f3ac30349a854b8fff5458fb418522fd9 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Common/Interfaces/ISettingService.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CBSVisualizer.Common.Interfaces +{ + public interface ISettingService + { + + public ReadOnlyObservableCollection<ISettingGroup> SettingGroups { get; } + + /** + * Allows to retrieve the value with the specified key. + */ + T GetSettingValue<T>(string key) where T : IConvertible; + } +} diff --git a/CBSVisualizer/CBSVisualizer.Common/Interfaces/IStatisticsService.cs b/CBSVisualizer/CBSVisualizer.Common/Interfaces/IStatisticsService.cs index 7f50b51528c4d33a0c08a90421ac35c2a11e50c6..b25cf972faabe36d25c26be0965f8f29ac732e04 100644 --- a/CBSVisualizer/CBSVisualizer.Common/Interfaces/IStatisticsService.cs +++ b/CBSVisualizer/CBSVisualizer.Common/Interfaces/IStatisticsService.cs @@ -39,5 +39,10 @@ namespace CBSVisualizer.Common.Interfaces /// </summary> /// <returns>an IStatistics object that contains different statistics.</returns> public Dictionary<int, IStatisticsSet<double>> Statistics { get; } + + /// <summary> + /// Can be queried to check whether the statistics are ready. + /// </summary> + public bool StatisticsReady { get; } } } diff --git a/CBSVisualizer/CBSVisualizer.Common/Interfaces/IStatisticsSet.cs b/CBSVisualizer/CBSVisualizer.Common/Interfaces/IStatisticsSet.cs index c52742a13b2e746fe0b181c0735c15567b5fdbc5..3787e41470bddb146acba8e08f799d632ab7634a 100644 --- a/CBSVisualizer/CBSVisualizer.Common/Interfaces/IStatisticsSet.cs +++ b/CBSVisualizer/CBSVisualizer.Common/Interfaces/IStatisticsSet.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace CBSVisualizer.Common.Interfaces { @@ -9,6 +10,11 @@ namespace CBSVisualizer.Common.Interfaces /// </summary> public IEnumerable<T> RawValues { get; } + /// <summary> + /// The absolute frequencies for each delay. + /// </summary> + public (IEnumerable<double> xCoords, IEnumerable<double> yCoords) DelayAbsoluteFrequencyXy { get; } + /// <summary> /// The Five Number Summary: minimum value, the lower quartile, the median, the upper quartile and the maximum value. /// </summary> diff --git a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/ClearQueuesEvent.cs b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/ClearQueuesEvent.cs new file mode 100644 index 0000000000000000000000000000000000000000..ce447ac4ba3de59e483dc49ccc752b8316341510 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/ClearQueuesEvent.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Prism.Events; + +namespace CBSVisualizer.Messaging.Events.Queue +{ + /** + * Used to clear the queues. + */ + public class ClearQueuesEvent : PubSubEvent + { + } +} diff --git a/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs index 71621b0cfc18c34712a7fc3e5d96e76ab93c4366..84d628efff83e8ec048ff743f4a47ddb08f91e2c 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs @@ -34,11 +34,13 @@ namespace CBSVisualizer.Modules.Charts.ViewModels { eventAggregator.GetEvent<CreditChangedEvent>().Subscribe(tuple => { - var (prio, credit) = tuple; + lock (QueueSeries) + { + var (prio, credit) = tuple; + var data = QueueSeries[prio][1].DataSeries as XyDataSeries<DateTime, double>; + data.Append(DateTime.Now, credit); + } - var data = QueueSeries[prio][1].DataSeries as XyDataSeries<DateTime, double>; - - data.Append(DateTime.Now, credit); }); } @@ -46,11 +48,13 @@ namespace CBSVisualizer.Modules.Charts.ViewModels { eventAggregator.GetEvent<PacketCountChangedEvent>().Subscribe(tuple => { - var (prio, newCount) = tuple; - - var data = QueueSeries[prio][0].DataSeries as XyDataSeries<DateTime, double>; + lock (QueueSeries) + { + var (prio, newCount) = tuple; + var data = QueueSeries[prio][0].DataSeries as XyDataSeries<DateTime, double>; + data.Append(DateTime.Now, newCount); + } - data.Append(DateTime.Now, newCount); }); } diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/CBSVisualizer.Modules.Link.csproj b/CBSVisualizer/CBSVisualizer.Modules.Link/CBSVisualizer.Modules.Link.csproj index c978d2572d24c7d85cb93f62a8d8ac497c1dc435..baf33373de35c4bbc3d7f08236d4d7b8d5243cf3 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Link/CBSVisualizer.Modules.Link.csproj +++ b/CBSVisualizer/CBSVisualizer.Modules.Link/CBSVisualizer.Modules.Link.csproj @@ -14,6 +14,5 @@ <ProjectReference Include="..\CBSVisualizer.Common\CBSVisualizer.Common.csproj" /> <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" /> <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" /> - <ProjectReference Include="..\CBSVisualizer.Services.SchedulingService\CBSVisualizer.Services.SchedulingService.csproj" /> </ItemGroup> </Project> \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs index dabb999980739382b8a7525c862f9fd4901e1441..09e7c569afefca2af75a077c46e37cf5b238f8c3 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs @@ -15,7 +15,6 @@ using CBSVisualizer.Messaging.Events.Queue; using CBSVisualizer.Messaging.Events.Simulation; using CBSVisualizer.Messaging.Models; using CBSVisualizer.Modules.Link.Preemption; -using CBSVisualizer.Services.SettingService; using log4net; using Prism.Events; using Prism.Regions; @@ -46,7 +45,7 @@ namespace CBSVisualizer.Modules.Link.ViewModels /// <summary> /// The Setting Service, for requesting the bitrate and the preemption setting. /// </summary> - private readonly SettingService settingService; + private readonly ISettingService settingService; /// <summary> /// The PreemptionHandler implementation that is used in the current simulation run. @@ -75,7 +74,7 @@ namespace CBSVisualizer.Modules.Link.ViewModels private long preemptingPacketLeftoverBytes; public LinkViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, - ISchedulingService schedulingService, SettingService settingService) + ISchedulingService schedulingService, ISettingService settingService) : base(regionManager) { var scheduler = schedulingService; diff --git a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/CBSVisualizer.Modules.MenuBar.csproj b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/CBSVisualizer.Modules.MenuBar.csproj index 88466bc067172a6dc3dde8b70285776b61f054d8..8bddeb1d9385e166a34cdeec4079990e5bc525c4 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/CBSVisualizer.Modules.MenuBar.csproj +++ b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/CBSVisualizer.Modules.MenuBar.csproj @@ -10,9 +10,8 @@ <PackageReference Include="Prism.Wpf" Version="8.0.0.1909" /> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\CBSVisualizer.Common\CBSVisualizer.Common.csproj" /> <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" /> <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" /> - <ProjectReference Include="..\CBSVisualizer.Services.PacketService\CBSVisualizer.Services.PacketService.csproj" /> - <ProjectReference Include="..\CBSVisualizer.Services.SettingsService\CBSVisualizer.Services.SettingService.csproj" /> </ItemGroup> </Project> \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.cs index 49a7e2291f17d552d16e5d9aad67376640ff1216..f0d1df04c8f1b60238b0dd5f1bb8a6e33980f5d2 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.cs @@ -3,10 +3,11 @@ using System.Threading.Tasks; using CBSVisualizer.Common.Interfaces; using CBSVisualizer.Core.Mvvm; using CBSVisualizer.Messaging.Events.Simulation; -using CBSVisualizer.Services.SettingService; using Prism.Events; using Prism.Regions; using Prism.Services.Dialogs; +using System; +using CBSVisualizer.Messaging.Events.Queue; namespace CBSVisualizer.Modules.MenuBar.ViewModels { @@ -28,6 +29,13 @@ namespace CBSVisualizer.Modules.MenuBar.ViewModels set => SetProperty(ref simulationRunning, value); } + private bool canOpenStatistics; + private bool CanOpenStatistics + { + get => canOpenStatistics; + set => SetProperty(ref canOpenStatistics, value); + } + public DelegateCommand StartLoadGeneration { get; } public DelegateCommand StopLoadGeneration { get; } @@ -40,13 +48,15 @@ namespace CBSVisualizer.Modules.MenuBar.ViewModels public DelegateCommand OpenStatisticsCommand { get; } + public DelegateCommand ClearQueuesCommand { get; } + private readonly IEventAggregator eventAggregator; private readonly IPacketService packetService; - private SettingService settingService; - private IStatisticsService statisticsService; + private readonly ISettingService settingService; + private readonly IStatisticsService statisticsService; - public MenuBarViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IDialogService dialogService, SettingService settingService, IPacketService packetService, + public MenuBarViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IDialogService dialogService, ISettingService settingService, IPacketService packetService, IStatisticsService statisticsService) : base(regionManager) { @@ -56,7 +66,9 @@ namespace CBSVisualizer.Modules.MenuBar.ViewModels this.statisticsService = statisticsService; OpenSettingsCommand = new DelegateCommand(() => dialogService.Show("SettingsDialog", new DialogParameters(), result => { })); - OpenStatisticsCommand = new DelegateCommand(() => dialogService.Show("Statistics", new DialogParameters(), result => { })); + OpenStatisticsCommand = + new DelegateCommand(() => dialogService.Show("Statistics", new DialogParameters(), result => { })) + .ObservesCanExecute(() => CanOpenStatistics); StartSimulationCommand = new DelegateCommand(async () => await SignalSimulationStart(), () => !SimulationRunning).ObservesProperty(() => SimulationRunning); StopSimulationCommand = new DelegateCommand(SignalSimulationStop).ObservesCanExecute(() => SimulationRunning); @@ -64,7 +76,25 @@ namespace CBSVisualizer.Modules.MenuBar.ViewModels StartLoadGeneration = new DelegateCommand(async () => await StartLoadThread(), CanStartLoadGeneration).ObservesProperty(() => LoadGenerationInProgress); StopLoadGeneration = new DelegateCommand(StopLoadThread, () => !CanStartLoadGeneration()).ObservesProperty(() => LoadGenerationInProgress); + ClearQueuesCommand = new DelegateCommand(ClearQueues, () => !SimulationRunning && !LoadGenerationInProgress) + .ObservesProperty(() => SimulationRunning).ObservesProperty(() => LoadGenerationInProgress); + RegisterSimulationConditionListener(); + + statisticsService.PropertyChanged += ObserveStatisticsService; + } + + private void ClearQueues() + { + eventAggregator.GetEvent<ClearQueuesEvent>().Publish(); + } + + private void ObserveStatisticsService(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName != null && e.PropertyName.Equals("StatisticsReady")) + { + CanOpenStatistics = statisticsService.StatisticsReady; + } } private void RegisterSimulationConditionListener() diff --git a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/Views/MenuBar.xaml b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/Views/MenuBar.xaml index 764b928774c2b34b6a08d98b8382ad3f74154010..e64ce5f3e4aad9149b2bbdad70918ca1ad00c0e5 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/Views/MenuBar.xaml +++ b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/Views/MenuBar.xaml @@ -17,6 +17,9 @@ <MenuItem Header="_Load Generation"> <MenuItem Header="_Start Load Generation" Command="{Binding StartLoadGeneration}"/> <MenuItem Header="_Terminate Load Generation" Command="{Binding StopLoadGeneration}"/> + <Separator/> + <MenuItem Header="_Clear Queues" Command="{Binding ClearQueuesCommand}"/> + </MenuItem> <MenuItem Header="Statistics" Command="{Binding OpenStatisticsCommand}"/> </Menu> diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml.cs index db048c75e406c707aa950c4838c45b44676ef378..46fa82d55ea103b354ff8783d7d1cb52c83553b9 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml.cs @@ -1,7 +1,6 @@ using System.Windows.Controls; using CBSVisualizer.Common.Interfaces; using CBSVisualizer.Modules.Queue.ViewModels; -using CBSVisualizer.Services.SettingService; using Prism.Events; using Prism.Regions; @@ -12,13 +11,13 @@ namespace CBSVisualizer.Modules.QueueGroup.Views /// </summary> public partial class QueueGroup : UserControl { - public QueueGroup(IRegionManager regionManager, IEventAggregator eventAggregator, IPacketService packetService, SettingService settingService, IStatisticsService statisticsService) + public QueueGroup(IRegionManager regionManager, IEventAggregator eventAggregator, IStatisticsService statisticsService) { InitializeComponent(); for (var priority = 7; priority >= 0; priority--) { - Queue.Views.Queue newQueue = new Queue.Views.Queue(new QueueViewModel(regionManager, eventAggregator, priority, packetService, settingService, statisticsService)); + Queue.Views.Queue newQueue = new Queue.Views.Queue(new QueueViewModel(regionManager, eventAggregator, priority, statisticsService)); Grid.SetRow(newQueue, 7 - priority); Grid.Children.Add(newQueue); } diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/CBSVisualizer.Modules.Queue.csproj b/CBSVisualizer/CBSVisualizer.Modules.Queue/CBSVisualizer.Modules.Queue.csproj index 9accae29e75186d53e9791cb26fa9282ef7c5d5f..7d22587884b100c39ce23134057587f346332459 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Queue/CBSVisualizer.Modules.Queue.csproj +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/CBSVisualizer.Modules.Queue.csproj @@ -13,7 +13,5 @@ <ProjectReference Include="..\CBSVisualizer.Common\CBSVisualizer.Common.csproj" /> <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" /> <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" /> - <ProjectReference Include="..\CBSVisualizer.Services.PacketService\CBSVisualizer.Services.PacketService.csproj" /> - <ProjectReference Include="..\CBSVisualizer.Services.SettingsService\CBSVisualizer.Services.SettingService.csproj" /> </ItemGroup> </Project> \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/CbsQueueBase.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/CbsQueueBase.cs index 8b722eb0d81aee91d9b48893e77ace9a713f798f..0df5cb50cbf4d40fe81a0a5db37ce97a7579c743 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/CbsQueueBase.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/CbsQueueBase.cs @@ -154,6 +154,12 @@ namespace CBSVisualizer.Modules.Queue.QueueImplementations { var now = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + // Prevent "negative" updates. + if (lastUpdateTimestamp > now) + { + return; + } + var deltaCredit = 0L; if (lastUpdateTimestamp != 0) { diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/ReturnToZeroQueue.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/ReturnToZeroQueue.cs index f34fcf8821f9af1b930b4105f8042f8846e2b5d4..7ac6559937470b4af9c93145cacef0d1f6120c67 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/ReturnToZeroQueue.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/ReturnToZeroQueue.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using CBSVisualizer.Messaging.Models; using Prism.Events; diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs index 1400eda75bd88a92bc6380d9c1971921f5f63129..0f020004f48225dbd71cb6aa1c95c43a53f0f68f 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs @@ -1,9 +1,6 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; -using System.Reflection; -using System.Threading.Tasks; -using CBSVisualizer.Common; using CBSVisualizer.Common.Extensions; using CBSVisualizer.Common.Interfaces; using CBSVisualizer.Core.Mvvm; @@ -12,9 +9,6 @@ using CBSVisualizer.Messaging.Events.Queue; using CBSVisualizer.Messaging.Events.Simulation; using CBSVisualizer.Messaging.Models; using CBSVisualizer.Modules.Queue.QueueImplementations; -using CBSVisualizer.Services.SettingService; -using log4net; -using Prism.Commands; using Prism.Events; using Prism.Regions; @@ -37,25 +31,19 @@ namespace CBSVisualizer.Modules.Queue.ViewModels ReturnToZero } - private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod()?.DeclaringType); private readonly IEventAggregator eventAggregator; - private readonly IPacketService packetService; + private readonly IStatisticsService statisticsService; private volatile bool transmissionFinishedPending; private IQueue queueImplementation; private CreditBehaviour selectedCreditBehaviour; private long idleSlope; - private SettingService settings; - private IStatisticsService statisticsService; - public QueueViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, int priority, - IPacketService packetService, SettingService settings, IStatisticsService statisticsService) : + public QueueViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, int priority, IStatisticsService statisticsService) : base(regionManager) { this.eventAggregator = eventAggregator; - this.packetService = packetService; - this.settings = settings; this.statisticsService = statisticsService; Priority = priority; @@ -97,33 +85,33 @@ namespace CBSVisualizer.Modules.Queue.ViewModels private void RegisterSimulationStartedEventHandlers() { - eventAggregator.GetEvent<SimulationStartedEvent>().Subscribe(async () => + eventAggregator.GetEvent<SimulationStartedEvent>().Subscribe(() => { QueueImplementation.IdleSlope = idleSlope; - await Task.Run(QueueImplementation.OnSimulationStarted); + QueueImplementation.OnSimulationStarted(); }); - eventAggregator.GetEvent<SimulationStoppedEvent>().Subscribe(async () => + eventAggregator.GetEvent<SimulationStoppedEvent>().Subscribe(() => { - await Task.Run(QueueImplementation.OnSimulationStopped); + QueueImplementation.OnSimulationStopped(); }); } private void RegisterLinkEventHandlers() { - eventAggregator.GetEvent<QueueGateOpenedEvent>().Subscribe(async openedGates => + eventAggregator.GetEvent<QueueGateOpenedEvent>().Subscribe(openedGates => { if (openedGates.Contains(Priority)) { - await Task.Run(QueueImplementation.OnGateOpened); + QueueImplementation.OnGateOpened(); } else { - await Task.Run(QueueImplementation.OnGateClosed); + QueueImplementation.OnGateClosed(); } }); - eventAggregator.GetEvent<PacketPreemptedEvent>().Subscribe(async tuple => + eventAggregator.GetEvent<PacketPreemptedEvent>().Subscribe(tuple => { var (priority, leftoverBytes) = tuple; if (priority != Priority) @@ -135,10 +123,10 @@ namespace CBSVisualizer.Modules.Queue.ViewModels // Prepend leftover bytes and call queue implementation. Queue.PrependSynchronized(new PriorityPacket(priority, leftoverBytes)); - await Task.Run(QueueImplementation.OnTransmissionPreempted); + QueueImplementation.OnTransmissionPreempted(); }); - eventAggregator.GetEvent<PacketSubmitResultEvent>().Subscribe(async tuple => + eventAggregator.GetEvent<PacketSubmitResultEvent>().Subscribe(tuple => { var (priority, result) = tuple; if (priority != Priority) @@ -151,18 +139,18 @@ namespace CBSVisualizer.Modules.Queue.ViewModels if (result == PacketSubmitResult.Accepted) { transmissionFinishedPending = true; - await Task.Run(QueueImplementation.OnPacketAccepted); + QueueImplementation.OnPacketAccepted(); } else if (result == PacketSubmitResult.DeniedHigherPriority) { - await Task.Run(QueueImplementation.OnPacketDeniedHigherPriority); + QueueImplementation.OnPacketDeniedHigherPriority(); } else { - await Task.Run(QueueImplementation.OnPacketDeniedPreClosing); + QueueImplementation.OnPacketDeniedPreClosing(); } }); - eventAggregator.GetEvent<TransmissionFinishedEvent>().Subscribe(async tuple => + eventAggregator.GetEvent<TransmissionFinishedEvent>().Subscribe(tuple => { var (priority, bitrate) = tuple; if (priority != Priority) @@ -172,17 +160,17 @@ namespace CBSVisualizer.Modules.Queue.ViewModels transmissionFinishedPending = false; statisticsService.TransmissionFinished(Queue.GetFirstSynchronized()); - await Task.Run(() => QueueImplementation.OnTransmissionFinished(Queue.GetRemoveFirstSynchronized(), bitrate)); + QueueImplementation.OnTransmissionFinished(Queue.GetRemoveFirstSynchronized(), bitrate); }); - eventAggregator.GetEvent<TransmissionStartedEvent>().Subscribe(async priority => + eventAggregator.GetEvent<TransmissionStartedEvent>().Subscribe(priority => { if (priority != Priority) { return; } - await Task.Run(QueueImplementation.OnTransmissionStarted); + QueueImplementation.OnTransmissionStarted(); }); @@ -253,6 +241,11 @@ namespace CBSVisualizer.Modules.Queue.ViewModels statisticsService.RegisterPacket(packet); Queue.AddSynchronized(packet); }); + + eventAggregator.GetEvent<ClearQueuesEvent>().Subscribe(() => + { + Queue.ClearSynchronized(); + }); } } } \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/CBSVisualizer.Modules.SettingsDialog.csproj b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/CBSVisualizer.Modules.SettingsDialog.csproj index b1830d5c113b9803ae081505c0e38d653da2f66e..adf4f55c09405ecd384ad903f7dc856ed9f4d7e7 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/CBSVisualizer.Modules.SettingsDialog.csproj +++ b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/CBSVisualizer.Modules.SettingsDialog.csproj @@ -10,6 +10,7 @@ <PackageReference Include="Prism.Wpf" Version="8.0.0.1909" /> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\CBSVisualizer.Common\CBSVisualizer.Common.csproj" /> <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" /> <ProjectReference Include="..\CBSVisualizer.Services.SettingsService\CBSVisualizer.Services.SettingService.csproj" /> </ItemGroup> diff --git a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/ViewModels/SettingsDialogViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/ViewModels/SettingsDialogViewModel.cs index 85ea84e5458774ab682aa7de12571d98972ca0c8..b453d0914381827ce7502779be6dfd548512b2ff 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/ViewModels/SettingsDialogViewModel.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/ViewModels/SettingsDialogViewModel.cs @@ -2,20 +2,20 @@ using Prism.Regions; using Prism.Services.Dialogs; using System; -using CBSVisualizer.Services.SettingService; +using CBSVisualizer.Common.Interfaces; namespace CBSVisualizer.Modules.SettingsDialog.ViewModels { public class SettingsDialogViewModel : RegionViewModelBase, IDialogAware { - public SettingService SettingService { get; private set; } + public ISettingService SettingService { get; } public string Title => "Settings"; public event Action<IDialogResult> RequestClose; - public SettingsDialogViewModel(IRegionManager regionManager, SettingService settingService) + public SettingsDialogViewModel(IRegionManager regionManager, ISettingService settingService) : base(regionManager) { SettingService = settingService; diff --git a/CBSVisualizer/CBSVisualizer.Modules.StatisticsDialog/ViewModels/StatisticsDialogViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.StatisticsDialog/ViewModels/StatisticsDialogViewModel.cs index 1e0cfaeae5407f276d792ab311846364fad1bc9c..0babb68706397b0f8a4f3ef82ae5d364473b9aac 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.StatisticsDialog/ViewModels/StatisticsDialogViewModel.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.StatisticsDialog/ViewModels/StatisticsDialogViewModel.cs @@ -63,20 +63,10 @@ namespace CBSVisualizer.Modules.StatisticsDialog.ViewModels foreach ((int priority, IStatisticsSet<double> statistics) in statisticsService.Statistics .OrderBy((statisticsData) => statisticsData.Key)) { - // Construct the X-Axis: Cast to ulong and use distinct + some LINQ porn. - var xValues = statistics.RawValues.Select(value => (ulong) value).Distinct().OrderBy(value => value).ToList(); - var yValues = new int[xValues.Count]; - - // Now, do the cast again and count how often each distinct value is contained in the set. - for (var i = 0; i < yValues.Length; i++) - { - var x = xValues[i]; - yValues[i] = statistics.RawValues.Select(value => (ulong) value).Count(raw => raw == x); - } // Add the data to the chart. - var data = new XyDataSeries<ulong, int> {SeriesName = $"Priority {priority}"}; - data.Append(xValues, yValues); + var data = new XyDataSeries<double> {SeriesName = $"Priority {priority}"}; + data.Append(statistics.DelayAbsoluteFrequencyXy.xCoords, statistics.DelayAbsoluteFrequencyXy.yCoords); DelayData.Add(new ColumnRenderableSeriesViewModel() { DataSeries = data @@ -109,9 +99,9 @@ namespace CBSVisualizer.Modules.StatisticsDialog.ViewModels DataSeries = new BoxPlotDataSeries<int, double>() }); - DelayData.Add(new ColumnRenderableSeriesViewModel() + DelayData.Add(new MountainRenderableSeriesViewModel() { - DataSeries = new XyDataSeries<double> {SeriesName = "Delay Distribution for selected queue", AcceptsUnsortedData = true} + DataSeries = new XyDataSeries<ulong>() }); } diff --git a/CBSVisualizer/CBSVisualizer.Modules.StatisticsDialog/Views/StatisticsDialog.xaml b/CBSVisualizer/CBSVisualizer.Modules.StatisticsDialog/Views/StatisticsDialog.xaml index 208d83313586243e85b48802085bf5e8b23aca6c..26f9d121a541955974f6c924d9ade6779ef962e8 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.StatisticsDialog/Views/StatisticsDialog.xaml +++ b/CBSVisualizer/CBSVisualizer.Modules.StatisticsDialog/Views/StatisticsDialog.xaml @@ -35,10 +35,10 @@ <s:SciChartSurface Grid.Row="0" s:RenderableSeries="{s:SeriesBinding BoxPlotData}" ChartTitle="Delay Box Plots"> <s:SciChartSurface.XAxis> - <s:NumericAxis AutoRange="Once" VisibleRange="-0.5, 7.5" FlipCoordinates="True"/> + <s:NumericAxis AutoRange="Once" VisibleRange="-0.5, 7.5" FlipCoordinates="True" AxisTitle="Priority"/> </s:SciChartSurface.XAxis> <s:SciChartSurface.YAxis> - <s:NumericAxis AutoRange="Always"/> + <s:NumericAxis AutoRange="Always" AxisTitle="Delay [ms]"/> </s:SciChartSurface.YAxis> </s:SciChartSurface> @@ -49,15 +49,30 @@ <s:LegendModifier ShowLegend="True" Orientation="Horizontal" Margin="10" LegendPlacement="Inside" GetLegendDataFor="AllSeries" ShowVisibilityCheckboxes="True"/> + + <!-- Allow drag to zoom on Left mouse --> + <s:RubberBandXyZoomModifier ExecuteOn="MouseLeftButton" + RubberBandFill="#33FFFFFF" RubberBandStroke="#AAFFFFFF" + RubberBandStrokeDashArray="2 2"/> + <!-- Allow pan on Right mouse drag --> + <s:ZoomPanModifier ExecuteOn="MouseRightButton" ClipModeX="None" /> + <!-- Allow Dragging YAxis to Scale --> + <s:YAxisDragModifier DragMode="Scale"/> + <!-- Allow Dragging XAxis to Pan --> + <s:XAxisDragModifier DragMode="Pan"/> + <!-- Allow Mousewheel Zoom --> + <s:MouseWheelZoomModifier/> + <!-- Allow Zoom to Extents on double click --> + <s:ZoomExtentsModifier ExecuteOn="MouseDoubleClick" /> </s:ModifierGroup> </s:SciChartSurface.ChartModifier> <s:SciChartSurface.XAxis> - <s:NumericAxis AutoRange="Always"/> + <s:NumericAxis AutoRange="Once" AxisTitle="Delay [ms]"/> </s:SciChartSurface.XAxis> <s:SciChartSurface.YAxis> - <s:NumericAxis AutoRange="Always"/> + <s:NumericAxis AutoRange="Always" AxisTitle="Absolute Frequency"/> </s:SciChartSurface.YAxis> </s:SciChartSurface> </Grid> diff --git a/CBSVisualizer/CBSVisualizer.Services.PacketService/CBSVisualizer.Services.PacketService.csproj b/CBSVisualizer/CBSVisualizer.Services.PacketService/CBSVisualizer.Services.PacketService.csproj index 473dd435a9f73aa0e0bcd604b1996414888d1af6..0fa1d7e25b4411473d4df205398df80d9488d9d5 100644 --- a/CBSVisualizer/CBSVisualizer.Services.PacketService/CBSVisualizer.Services.PacketService.csproj +++ b/CBSVisualizer/CBSVisualizer.Services.PacketService/CBSVisualizer.Services.PacketService.csproj @@ -8,7 +8,6 @@ <ProjectReference Include="..\CBSVisualizer.Common\CBSVisualizer.Common.csproj" /> <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" /> <ProjectReference Include="..\CBSVisualizer.Services.JsonService\CBSVisualizer.Services.JsonService.csproj" /> - <ProjectReference Include="..\CBSVisualizer.Services.SettingsService\CBSVisualizer.Services.SettingService.csproj" /> </ItemGroup> </Project> diff --git a/CBSVisualizer/CBSVisualizer.Services.PacketService/FlowBasedPacketService.cs b/CBSVisualizer/CBSVisualizer.Services.PacketService/FlowBasedPacketService.cs index cc2a4906b4c9c81ca78f9fea7f477fce8a48149c..41ddce7f4c246f5f54ad392e9ee39b11181fc6b0 100644 --- a/CBSVisualizer/CBSVisualizer.Services.PacketService/FlowBasedPacketService.cs +++ b/CBSVisualizer/CBSVisualizer.Services.PacketService/FlowBasedPacketService.cs @@ -17,13 +17,13 @@ namespace CBSVisualizer.Services.PacketService public class FlowBasedPacketService : IPacketService { private readonly IEventAggregator eventAggregator; - private readonly SettingService.SettingService settingService; + private readonly ISettingService settingService; private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private readonly Random random = new Random(); private CancellationTokenSource tokenSrc; - public FlowBasedPacketService(IEventAggregator eventAggregator, SettingService.SettingService settingService) + public FlowBasedPacketService(IEventAggregator eventAggregator, ISettingService settingService) { this.eventAggregator = eventAggregator; this.settingService = settingService; diff --git a/CBSVisualizer/CBSVisualizer.Services.PacketService/PacketServiceProxy.cs b/CBSVisualizer/CBSVisualizer.Services.PacketService/PacketServiceProxy.cs index c0ec6bed0cc5a7f9f9edaceda7b6a79196f7f618..cf7109a5d8bbbbb9da24d237c96c16b4467e6046 100644 --- a/CBSVisualizer/CBSVisualizer.Services.PacketService/PacketServiceProxy.cs +++ b/CBSVisualizer/CBSVisualizer.Services.PacketService/PacketServiceProxy.cs @@ -11,11 +11,11 @@ namespace CBSVisualizer.Services.PacketService { public class PacketServiceProxy : IPacketService { - private readonly SettingService.SettingService settingService; + private readonly ISettingService settingService; private readonly IEventAggregator eventAggregator; private IPacketService internalPacketService; - public PacketServiceProxy(IEventAggregator eventAggregator, SettingService.SettingService settingService) + public PacketServiceProxy(IEventAggregator eventAggregator, ISettingService settingService) { this.eventAggregator = eventAggregator; this.settingService = settingService; diff --git a/CBSVisualizer/CBSVisualizer.Services.PacketService/RandomPacketService.cs b/CBSVisualizer/CBSVisualizer.Services.PacketService/RandomPacketService.cs index d201234967c82584a16ec2382b6e3277a6bffe80..8af4467b467bf2c5c6fad90390a4fdfcf9ca40d5 100644 --- a/CBSVisualizer/CBSVisualizer.Services.PacketService/RandomPacketService.cs +++ b/CBSVisualizer/CBSVisualizer.Services.PacketService/RandomPacketService.cs @@ -18,9 +18,9 @@ namespace CBSVisualizer.Services.PacketService private readonly Random random = new Random(); private readonly IEventAggregator eventAggregator; - private readonly SettingService.SettingService settingService; + private readonly ISettingService settingService; - public RandomPacketService(IEventAggregator eventAggregator, SettingService.SettingService settingService) + public RandomPacketService(IEventAggregator eventAggregator, ISettingService settingService) { this.eventAggregator = eventAggregator; this.settingService = settingService; diff --git a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/CBSVisualizer.Services.SchedulingService.csproj b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/CBSVisualizer.Services.SchedulingService.csproj index afad604d038675c36fe0317b5dc474e2bd2a5916..c76e28614dd6e5c4d5c1f7f26bbbecfd1bda8f43 100644 --- a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/CBSVisualizer.Services.SchedulingService.csproj +++ b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/CBSVisualizer.Services.SchedulingService.csproj @@ -10,9 +10,9 @@ </ItemGroup> <ItemGroup> + <ProjectReference Include="..\CBSVisualizer.Common\CBSVisualizer.Common.csproj" /> <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" /> <ProjectReference Include="..\CBSVisualizer.Services.JsonService\CBSVisualizer.Services.JsonService.csproj" /> - <ProjectReference Include="..\CBSVisualizer.Services.SettingsService\CBSVisualizer.Services.SettingService.csproj" /> </ItemGroup> </Project> diff --git a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/FlowBasedSchedulingService.cs b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/FlowBasedSchedulingService.cs index 7e005dd868b21b1408740500870ece3211c205f8..aae2a3d01539169b85fbebf366a8238a420b600b 100644 --- a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/FlowBasedSchedulingService.cs +++ b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/FlowBasedSchedulingService.cs @@ -18,12 +18,12 @@ namespace CBSVisualizer.Services.SchedulingService { private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private readonly IEventAggregator eventAggregator; - private readonly SettingService.SettingService settingService; + private readonly ISettingService settingService; private readonly ISet<int> highPrioQueue = new HashSet<int>{7}; private readonly Random random = new Random(); private CancellationTokenSource tokenSrc; - public FlowBasedSchedulingService(IEventAggregator eventAggregator, SettingService.SettingService settingService) + public FlowBasedSchedulingService(IEventAggregator eventAggregator, ISettingService settingService) { this.eventAggregator = eventAggregator; this.settingService = settingService; diff --git a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/RandomSchedulingService.cs b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/RandomSchedulingService.cs index 3498b5086e06c24480831c1af5a7a37cf3bcbb5d..20080ae3046dd093279b212b7c4c9b18ddf01ca1 100644 --- a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/RandomSchedulingService.cs +++ b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/RandomSchedulingService.cs @@ -16,10 +16,10 @@ namespace CBSVisualizer.Services.SchedulingService private const string MaxDelaySettingKey = "random_scheduler_max_delay"; private CancellationTokenSource tokenSource; private readonly Random random = new Random(); - private readonly SettingService.SettingService settings; + private readonly ISettingService settings; private readonly IEventAggregator eventAggregator; - public RandomSchedulingService(IEventAggregator aggregator, SettingService.SettingService settingService) + public RandomSchedulingService(IEventAggregator aggregator, ISettingService settingService) { settings = settingService; eventAggregator = aggregator; diff --git a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/SchedulingServiceProxy.cs b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/SchedulingServiceProxy.cs index f71c292af754d1524099ebf2e05b131dcf317c05..10aeb4483ea19334e7eba91e0311ea31aade8804 100644 --- a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/SchedulingServiceProxy.cs +++ b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/SchedulingServiceProxy.cs @@ -15,10 +15,10 @@ namespace CBSVisualizer.Services.SchedulingService public class SchedulingServiceProxy : ISchedulingService { private readonly IEventAggregator eventAggregator; - private readonly SettingService.SettingService settingService; + private readonly ISettingService settingService; private ISchedulingService internalSchedulingService; - public SchedulingServiceProxy(IEventAggregator eventAggregator, SettingService.SettingService settingService) + public SchedulingServiceProxy(IEventAggregator eventAggregator, ISettingService settingService) { this.eventAggregator = eventAggregator; this.settingService = settingService; diff --git a/CBSVisualizer/CBSVisualizer.Services.SettingsService/SettingService.cs b/CBSVisualizer/CBSVisualizer.Services.SettingsService/SettingService.cs index aa81a625fed8c36571682511782ab206fadfa446..23ea12431f6eb83979671181c7256dabbd53d7d2 100644 --- a/CBSVisualizer/CBSVisualizer.Services.SettingsService/SettingService.cs +++ b/CBSVisualizer/CBSVisualizer.Services.SettingsService/SettingService.cs @@ -3,16 +3,16 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using CBSVisualizer.Common.Enums; +using CBSVisualizer.Common.Interfaces; using CBSVisualizer.Services.SettingService.Types; using CBSVisualizer.Services.SettingService.Types.Abstract; namespace CBSVisualizer.Services.SettingService { - public class SettingService + public class SettingService : ISettingService { - private readonly ObservableCollection<SettingGroup> settingGroups = new ObservableCollection<SettingGroup>(); - - public ReadOnlyObservableCollection<SettingGroup> SettingGroups => new ReadOnlyObservableCollection<SettingGroup>(settingGroups); + private readonly ObservableCollection<ISettingGroup> settingGroups = new ObservableCollection<ISettingGroup>(); + public ReadOnlyObservableCollection<ISettingGroup> SettingGroups => new ReadOnlyObservableCollection<ISettingGroup>(settingGroups); public SettingService() { @@ -20,34 +20,48 @@ namespace CBSVisualizer.Services.SettingService InitializeSchedulersGroup(); InitializeLoadGenerationGroup(); InitializePreemptionGroup(); + InitializeStatisticsGroup(); + } + + private void InitializeStatisticsGroup() + { + var statisticsGroupMembers = new ObservableCollection<ISetting>() + { + new StringSetting("histogram_buckets", "Amount of Histogram Bins", "1000") + }; + + var statisticsGroup = new SettingGroup("Statistics", statisticsGroupMembers); + + settingGroups.Add(statisticsGroup); } private void InitializePreemptionGroup() { - var preemptionGroupMembers = new ObservableCollection<Setting>(); + var preemptionGroupMembers = new ObservableCollection<ISetting>(); // Preemption mode. - ISet<String> preemptionModes = new HashSet<string>{Enum.GetName(typeof(PreemptionType), PreemptionType.NonPreemptive), Enum.GetName(typeof(PreemptionType), PreemptionType.PreemptionNoHoldRelease), Enum.GetName(typeof(PreemptionType), PreemptionType.PreemptionWithHoldRelease) }; + ISet<string> preemptionModes = new HashSet<string>{Enum.GetName(typeof(PreemptionType), PreemptionType.NonPreemptive), Enum.GetName(typeof(PreemptionType), PreemptionType.PreemptionNoHoldRelease), Enum.GetName(typeof(PreemptionType), PreemptionType.PreemptionWithHoldRelease) }; preemptionGroupMembers.Add(new SelectionSetting("preemption_mode", "Preemption Mode", preemptionModes.First(), preemptionModes)); settingGroups.Add(new SettingGroup("Preemption", preemptionGroupMembers)); } private void InitializeLoadGenerationGroup() { - var loadGenerationGroupMembers = new ObservableCollection<Setting>(); - - // Start Packet Generation at Simulation Start? - loadGenerationGroupMembers.Add(new BooleanSetting("packetgen_at_simstart", "Start/Stop Packet Generation at Simulation Start/Stop?", true)); + var loadGenerationGroupMembers = new ObservableCollection<ISetting> + { + // Start Packet Generation at Simulation Start? + new BooleanSetting("packetgen_at_simstart", "Start/Stop Packet Generation at Simulation Start/Stop?", true), - // Packet interarrival time. - loadGenerationGroupMembers.Add(new StringSetting("interarrival_time", "Packet Inter-Arrival Time [ms]", "100")); + // Packet interarrival time. + new StringSetting("interarrival_time", "Packet Inter-Arrival Time [ms]", "100") + }; settingGroups.Add(new SettingGroup("Load Generation", loadGenerationGroupMembers)); } private void InitializeSchedulersGroup() { - var schedulersGroupMembers = new ObservableCollection<Setting>(); + var schedulersGroupMembers = new ObservableCollection<ISetting>(); // Used scheduler. ISet<string> schedulers = new HashSet<string> { Enum.GetName(typeof(SchedulerType), SchedulerType.Random), Enum.GetName(typeof(SchedulerType), SchedulerType.FlowBased) }; @@ -65,7 +79,7 @@ namespace CBSVisualizer.Services.SettingService private void InitializeCommonGroup() { - var commonGroupMembers = new ObservableCollection<Setting>(); + var commonGroupMembers = new ObservableCollection<ISetting>(); // Link bitrate. commonGroupMembers.Add(new StringSetting("bitrate", "Link Bitrate [byte/s]", "10000")); diff --git a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Types/Abstract/Setting.cs b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Types/Abstract/Setting.cs index f882a9ee6a14c2bc39c8dda8d3533a0bca5c516b..505cf73f754c8e950412313d0dd54ab06d53b8d5 100644 --- a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Types/Abstract/Setting.cs +++ b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Types/Abstract/Setting.cs @@ -1,9 +1,10 @@ using System; +using CBSVisualizer.Common.Interfaces; using Prism.Mvvm; namespace CBSVisualizer.Services.SettingService.Types.Abstract { - public class Setting : BindableBase + public class Setting : BindableBase, ISetting { public string Name { get; protected set; } @@ -15,15 +16,9 @@ namespace CBSVisualizer.Services.SettingService.Types.Abstract private T settingValue; public T SettingValue { - get - { - return settingValue; - } + get => settingValue; - set - { - SetProperty(ref settingValue, value); - } + set => SetProperty(ref settingValue, value); } protected Setting(string key, string name, T initialValue) diff --git a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Types/Abstract/SettingGroup.cs b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Types/Abstract/SettingGroup.cs index 5bd1d43d3a17e5adb78afdd9cbf682b16bb5e10c..da110c46403f0e1907e2287a41e5c1dfab36d9e5 100644 --- a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Types/Abstract/SettingGroup.cs +++ b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Types/Abstract/SettingGroup.cs @@ -1,17 +1,18 @@ using System.Collections.ObjectModel; +using CBSVisualizer.Common.Interfaces; namespace CBSVisualizer.Services.SettingService.Types.Abstract { - public class SettingGroup + public class SettingGroup : ISettingGroup { public string GroupName { get; private set; } - public ReadOnlyObservableCollection<Setting> Members { get; private set; } + public ReadOnlyObservableCollection<ISetting> Members { get; private set; } - public SettingGroup(string name, ObservableCollection<Setting> members) + public SettingGroup(string name, ObservableCollection<ISetting> members) { GroupName = name; - Members = new ReadOnlyObservableCollection<Setting>(members); + Members = new ReadOnlyObservableCollection<ISetting>(members); } } } diff --git a/CBSVisualizer/CBSVisualizer.Services.StatisticsService/StatisticsService.cs b/CBSVisualizer/CBSVisualizer.Services.StatisticsService/StatisticsService.cs index 1c2b93e05c761f0b0913013b46da88cff32d7566..e44e020ede9828ded9bef1a0a8f8ec4d936bb085 100644 --- a/CBSVisualizer/CBSVisualizer.Services.StatisticsService/StatisticsService.cs +++ b/CBSVisualizer/CBSVisualizer.Services.StatisticsService/StatisticsService.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using CBSVisualizer.Common.Interfaces; using CBSVisualizer.Messaging.Models; using MathNet.Numerics.Statistics; @@ -23,6 +24,21 @@ namespace CBSVisualizer.Services.StatisticsService set => SetProperty(ref statistics, value); } + private bool statisticsReady; + private ISettingService settings; + + public bool StatisticsReady + { + get => statisticsReady; + set => SetProperty(ref statisticsReady, value); + } + + + public StatisticsService(ISettingService settings) + { + this.settings = settings; + } + public void RegisterPacket(PriorityPacket newPacket) { // Don't care about PriorityPacket.NoPacket. @@ -61,6 +77,9 @@ namespace CBSVisualizer.Services.StatisticsService public void SimulationStarted() { + // Tell everyone that the statistics are not ready yet. + StatisticsReady = false; + // Go through all the packets which were present before the simulation start and set their arrival to "Now" so that the arrival time is correct. var now = DateTime.Now; @@ -93,6 +112,9 @@ namespace CBSVisualizer.Services.StatisticsService // Calculate the new statistics. UpdateStatistics(); + + // Tell everyone that the statistics are ready now. + StatisticsReady = true; } } @@ -106,21 +128,52 @@ namespace CBSVisualizer.Services.StatisticsService foreach (var (priority, data) in dataPerPriority) { // Calculate delays. - var delays = data.Select(collection => - { - if (collection.Arrival.HasValue && collection.Departure.HasValue) - { - return collection.Departure.Value.Subtract(collection.Arrival.Value).TotalMilliseconds; - } - return 0; - }).ToList(); + var delays = CalculateDelays(data); + + // Calculate absoluteFrequencies; + var absoluteFrequencies = CalculateAbsoluteFrequencies(delays); // Calculate the statistics. - result[priority] = new StatisticsSet<double> { RawValues = delays, FiveNumberSummary = delays.FiveNumberSummary() }; + result[priority] = new StatisticsSet<double> { RawValues = delays, DelayAbsoluteFrequencyXy = absoluteFrequencies, FiveNumberSummary = delays.FiveNumberSummary() }; } Statistics = result; } } + + private (IEnumerable<double>, IEnumerable<double>) CalculateAbsoluteFrequencies(IList<double> delays) + { + if (delays.Count == 0) + { + return (Enumerable.Empty<double>(), Enumerable.Empty<double>()); + } + // Get a histogram of the data. + var histogram = new Histogram(delays, settings.GetSettingValue<int>("histogram_buckets")); + + // Init some variables for xAxis and yAxis. + var xAxis = new List<double>(); + var yAxis = new List<double>(); + + for (var i = 0; i < histogram.BucketCount; i++) + { + var bucket = histogram[i]; + xAxis.Add((bucket.LowerBound + bucket.LowerBound) / 2); + yAxis.Add(bucket.Count); + } + + return (xAxis, yAxis); + } + + private static List<double> CalculateDelays(ConcurrentBag<PacketTimestampCollection> data) + { + return data.AsParallel().Select(collection => + { + if (collection.Arrival.HasValue && collection.Departure.HasValue) + { + return collection.Departure.Value.Subtract(collection.Arrival.Value).TotalMilliseconds; + } + return 0; + }).ToList(); + } } } diff --git a/CBSVisualizer/CBSVisualizer.Services.StatisticsService/StatisticsSet.cs b/CBSVisualizer/CBSVisualizer.Services.StatisticsService/StatisticsSet.cs index 4120976d7db8d95768b89bc00b77f588575d60c9..155bbbe8aed8e27ad1ec02d37ffb29d77d5c237f 100644 --- a/CBSVisualizer/CBSVisualizer.Services.StatisticsService/StatisticsSet.cs +++ b/CBSVisualizer/CBSVisualizer.Services.StatisticsService/StatisticsSet.cs @@ -15,5 +15,12 @@ namespace CBSVisualizer.Services.StatisticsService private IEnumerable<T> fiveNumberSummary; public IEnumerable<T> FiveNumberSummary { get => fiveNumberSummary; set => SetProperty(ref fiveNumberSummary, value); } + + private (IEnumerable<double>, IEnumerable<double>) delayAbsoluteFrequencyXy; + public (IEnumerable<double> xCoords, IEnumerable<double> yCoords) DelayAbsoluteFrequencyXy + { + get => delayAbsoluteFrequencyXy; + set => SetProperty(ref delayAbsoluteFrequencyXy, value); + } } } diff --git a/CBSVisualizer/CBSVisualizer/App.xaml.cs b/CBSVisualizer/CBSVisualizer/App.xaml.cs index 50924abdd8bcb0bdf4afda048bcb57d84fb4e02a..ad830ca82252728a868533c8c77f1e9ca0dcd934 100644 --- a/CBSVisualizer/CBSVisualizer/App.xaml.cs +++ b/CBSVisualizer/CBSVisualizer/App.xaml.cs @@ -35,7 +35,7 @@ namespace CBSVisualizer protected override void RegisterTypes(IContainerRegistry containerRegistry) { // containerRegistry.RegisterSingleton<IMessageService, MessageService>(); - containerRegistry.RegisterSingleton<SettingService>(); + containerRegistry.RegisterSingleton<ISettingService, SettingService>(); containerRegistry.RegisterSingleton<ISchedulingService, SchedulingServiceProxy>(); containerRegistry.RegisterSingleton<IPacketService, PacketServiceProxy>(); containerRegistry.RegisterSingleton<IStatisticsService, StatisticsService>();