diff --git a/CBSVisualizer/CBSVisualizer.Core/RegionNames.cs b/CBSVisualizer/CBSVisualizer.Core/RegionNames.cs index 4c12cfccee4734569196cc0fd19d5d59113dba12..8665e11825c97566c9c0da808328d8686823b6c1 100644 --- a/CBSVisualizer/CBSVisualizer.Core/RegionNames.cs +++ b/CBSVisualizer/CBSVisualizer.Core/RegionNames.cs @@ -5,5 +5,6 @@ public const string MenuBarRegion = "MenuBar"; public const string QueueGroupRegion = "QueueGroup"; public const string LinkRegion = "Link"; + public const string ChartsRegion = "Charts"; } } diff --git a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/CreditChangedEvent.cs b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/CreditChangedEvent.cs new file mode 100644 index 0000000000000000000000000000000000000000..6eea1f8e5bd287facb5615b9dabb4d8b8ff7a3e8 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/CreditChangedEvent.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Prism.Events; + +namespace CBSVisualizer.Messaging.Events +{ + public class CreditChangedEvent : PubSubEvent<(int Prio, long Credit)> + { + } +} diff --git a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/PacketCountChangedEvent.cs b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/PacketCountChangedEvent.cs new file mode 100644 index 0000000000000000000000000000000000000000..c61db7740b1e74d2ec4159ea62222d9435e3a9cf --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/PacketCountChangedEvent.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Prism.Events; + +namespace CBSVisualizer.Messaging.Events +{ + public class PacketCountChangedEvent : PubSubEvent<(int Prio, long NewCount)> + { + } +} diff --git a/CBSVisualizer/CBSVisualizer.Modules.Charts/CBSVisualizer.Modules.Charts.csproj b/CBSVisualizer/CBSVisualizer.Modules.Charts/CBSVisualizer.Modules.Charts.csproj new file mode 100644 index 0000000000000000000000000000000000000000..c8aace383614431cd8ff3fac64f0569571453e81 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Charts/CBSVisualizer.Modules.Charts.csproj @@ -0,0 +1,15 @@ +<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + <UseWPF>true</UseWPF> + <AssemblyName>CBSVisualizer.Modules.Charts</AssemblyName> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="LiveCharts.Wpf" Version="0.9.7" /> + <PackageReference Include="Prism.Wpf" Version="7.2.0.1422" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" /> + <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" /> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Charts/ChartsModule.cs b/CBSVisualizer/CBSVisualizer.Modules.Charts/ChartsModule.cs new file mode 100644 index 0000000000000000000000000000000000000000..a631601f189124f6d9128b5123c183ae033d8946 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Charts/ChartsModule.cs @@ -0,0 +1,28 @@ +using CBSVisualizer.Core; +using CBSVisualizer.Modules.Charts.Views; +using Prism.Ioc; +using Prism.Modularity; +using Prism.Regions; + +namespace CBSVisualizer.Modules.Charts +{ + public class ChartsModule : IModule + { + private readonly IRegionManager regionManager; + + public ChartsModule(IRegionManager regionManager) + { + this.regionManager = regionManager; + } + + public void OnInitialized(IContainerProvider containerProvider) + { + regionManager.RequestNavigate(RegionNames.ChartsRegion, "Charts"); + } + + public void RegisterTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterForNavigation<Views.Charts>(); + } + } +} \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..dfaa317b871f6cc17a920020f67f8606d1c9266d --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using CBSVisualizer.Core.Mvvm; +using CBSVisualizer.Messaging.Events; +using LiveCharts; +using LiveCharts.Defaults; +using LiveCharts.Wpf; +using Prism.Events; +using Prism.Regions; + +namespace CBSVisualizer.Modules.Charts.ViewModels +{ + public class ChartsViewModel : RegionViewModelBase + { + + public Func<double, string> Formatter { get; } = x => new DateTime((long) x).ToString("HH:mm:ss"); + + public Dictionary<int, SeriesCollection> CombinedCollectionDictionary { get; private set; } + + public SeriesCollection CreditValuesCollections { get; set; } + + public SeriesCollection PacketCountCollections { get; set; } + + public ChartsViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) + : base(regionManager) + { + InitCharts(); + InitPacketHandler(eventAggregator); + InitCreditHandler(eventAggregator); + } + + private void InitCreditHandler(IEventAggregator eventAggregator) + { + eventAggregator.GetEvent<CreditChangedEvent>().Subscribe(tuple => + { + var (prio, credit) = tuple; + CreditValuesCollections[prio].Values.Add(new DateTimePoint(DateTime.Now, credit)); + }); + } + + private void InitPacketHandler(IEventAggregator eventAggregator) + { + eventAggregator.GetEvent<PacketCountChangedEvent>().Subscribe(tuple => + { + var (prio, newCount) = tuple; + PacketCountCollections[prio].Values.Add(new DateTimePoint(DateTime.Now, newCount)); + }); + } + + private void InitCharts() + { + CreditValuesCollections = new SeriesCollection + { + new LineSeries { + Title = "Queue 0 Credit", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 1 Credit", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 2 Credit", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 3 Credit", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 4 Credit", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 5 Credit", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 6 Credit", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 7 Credit", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + } + }; + + PacketCountCollections = new SeriesCollection + { + new LineSeries { + Title = "Queue 0 Packets", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 1 Packets", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 2 Packets", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 3 Packets", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 4 Packets", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 5 Packets", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 6 Packets", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + }, + new LineSeries { + Title = "Queue 7 Packets", + Values = new ChartValues<DateTimePoint>{new DateTimePoint(DateTime.Now, 0)} + } + }; + + CombinedCollectionDictionary = new Dictionary<int, SeriesCollection>(); + for (var idx = 0; idx < PacketCountCollections.Count; idx++) + { + CombinedCollectionDictionary[idx] = new SeriesCollection() + { + PacketCountCollections[idx], + CreditValuesCollections[idx], + }; + } + } + } +} diff --git a/CBSVisualizer/CBSVisualizer.Modules.Charts/Views/Charts.xaml b/CBSVisualizer/CBSVisualizer.Modules.Charts/Views/Charts.xaml new file mode 100644 index 0000000000000000000000000000000000000000..10eaeb1da07671fc5b350b674e1fd2096dabeb25 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Charts/Views/Charts.xaml @@ -0,0 +1,89 @@ +<UserControl x:Class="CBSVisualizer.Modules.Charts.Views.Charts" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300" + xmlns:prism="http://prismlibrary.com/" + xmlns:wpf="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf" + prism:ViewModelLocator.AutoWireViewModel="True" > + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="*"/> + <RowDefinition Height="*"/> + <RowDefinition Height="*"/> + <RowDefinition Height="*"/> + <RowDefinition Height="*"/> + <RowDefinition Height="*"/> + <RowDefinition Height="*"/> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + + <wpf:CartesianChart Grid.Row="0" Series="{Binding CombinedCollectionDictionary[7]}" LegendLocation="Left"> + <wpf:CartesianChart.AxisX> + <wpf:Axis Title="Timestamp" LabelFormatter="{Binding Formatter}"/> + </wpf:CartesianChart.AxisX> + <wpf:CartesianChart.AxisY> + <wpf:Axis Title="Packet Count / Credit"/> + </wpf:CartesianChart.AxisY> + </wpf:CartesianChart> + <wpf:CartesianChart Grid.Row="1" Series="{Binding CombinedCollectionDictionary[6]}" LegendLocation="Left"> + <wpf:CartesianChart.AxisX> + <wpf:Axis Title="Timestamp" LabelFormatter="{Binding Formatter}"/> + </wpf:CartesianChart.AxisX> + <wpf:CartesianChart.AxisY> + <wpf:Axis Title="Packet Count / Credit"/> + </wpf:CartesianChart.AxisY> + </wpf:CartesianChart> + <wpf:CartesianChart Grid.Row="2" Series="{Binding CombinedCollectionDictionary[5]}" LegendLocation="Left"> + <wpf:CartesianChart.AxisX> + <wpf:Axis Title="Timestamp" LabelFormatter="{Binding Formatter}"/> + </wpf:CartesianChart.AxisX> + <wpf:CartesianChart.AxisY> + <wpf:Axis Title="Packet Count / Credit"/> + </wpf:CartesianChart.AxisY> + </wpf:CartesianChart> + <wpf:CartesianChart Grid.Row="3" Series="{Binding CombinedCollectionDictionary[4]}" LegendLocation="Left"> + <wpf:CartesianChart.AxisX> + <wpf:Axis Title="Timestamp" LabelFormatter="{Binding Formatter}"/> + </wpf:CartesianChart.AxisX> + <wpf:CartesianChart.AxisY> + <wpf:Axis Title="Packet Count / Credit"/> + </wpf:CartesianChart.AxisY> + </wpf:CartesianChart> + <wpf:CartesianChart Grid.Row="4" Series="{Binding CombinedCollectionDictionary[3]}" LegendLocation="Left"> + <wpf:CartesianChart.AxisX> + <wpf:Axis Title="Timestamp" LabelFormatter="{Binding Formatter}"/> + </wpf:CartesianChart.AxisX> + <wpf:CartesianChart.AxisY> + <wpf:Axis Title="Packet Count / Credit"/> + </wpf:CartesianChart.AxisY> + </wpf:CartesianChart> + <wpf:CartesianChart Grid.Row="5" Series="{Binding CombinedCollectionDictionary[2]}" LegendLocation="Left"> + <wpf:CartesianChart.AxisX> + <wpf:Axis Title="Timestamp" LabelFormatter="{Binding Formatter}"/> + </wpf:CartesianChart.AxisX> + <wpf:CartesianChart.AxisY> + <wpf:Axis Title="Packet Count / Credit"/> + </wpf:CartesianChart.AxisY> + </wpf:CartesianChart> + <wpf:CartesianChart Grid.Row="6" Series="{Binding CombinedCollectionDictionary[1]}" LegendLocation="Left"> + <wpf:CartesianChart.AxisX> + <wpf:Axis Title="Timestamp" LabelFormatter="{Binding Formatter}"/> + </wpf:CartesianChart.AxisX> + <wpf:CartesianChart.AxisY> + <wpf:Axis Title="Packet Count / Credit"/> + </wpf:CartesianChart.AxisY> + </wpf:CartesianChart> + <wpf:CartesianChart Grid.Row="7" Series="{Binding CombinedCollectionDictionary[0]}" LegendLocation="Left"> + <wpf:CartesianChart.AxisX> + <wpf:Axis Title="Timestamp" LabelFormatter="{Binding Formatter}"/> + </wpf:CartesianChart.AxisX> + <wpf:CartesianChart.AxisY> + <wpf:Axis Title="Packet Count / Credit"/> + </wpf:CartesianChart.AxisY> + </wpf:CartesianChart> + + </Grid> +</UserControl> diff --git a/CBSVisualizer/CBSVisualizer.Modules.Charts/Views/Charts.xaml.cs b/CBSVisualizer/CBSVisualizer.Modules.Charts/Views/Charts.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..e6f990c7737a92ad595b26c8b3a15a8c7957b86e --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Charts/Views/Charts.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace CBSVisualizer.Modules.Charts.Views +{ + /// <summary> + /// Interaction logic for Charts.xaml + /// </summary> + public partial class Charts : UserControl + { + public Charts() + { + InitializeComponent(); + } + } +} diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs index 995c0f51dc1010bdffd7935bb805e6b17dc43e1a..bcddad19a7889aca97cad20ea922c046e01312f2 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs @@ -193,7 +193,6 @@ namespace CBSVisualizer.Modules.Link.ViewModels { await Task.Delay(REFRESH_TIME_MS, tokenSource.Token); transmittedBytes += REFRESH_TIME_MS * (bitrate / 1000); - log.Info($"Transmitted {transmittedBytes} of {packetInTransit.Size} bytes of packet {packetInTransit}."); } } catch (TaskCanceledException) { } finally diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.FrozenLinkCallback.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.FrozenLinkCallback.cs new file mode 100644 index 0000000000000000000000000000000000000000..b8445caa64618a1da553957bc35bf02aa14c376b --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.FrozenLinkCallback.cs @@ -0,0 +1,66 @@ +using System; +using System.Linq; +using CBSVisualizer.Messaging; +using CBSVisualizer.Messaging.Events; + +namespace CBSVisualizer.Modules.Queue.ViewModels +{ + public partial class QueueViewModel + { + private class FrozenLinkCallback : LinkCallbackBase + { + public FrozenLinkCallback(QueueViewModel parent) + : base(parent) + { + } + + public override void Initialize() + { + Parent.StartCreditThread(Parent.IdleSlope); + } + + public override void GateClosed() + { + // Nothing special happens here. The credit handling is done in the GateOpened method. + } + + public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket) + { + // Start the credit thread. + Parent.StartCreditThread(Parent.IdleSlope); + + // Try to submit the latest packet. If it was denied due to pre-closing, freeze the credit. + TrySendPacket( + trySubmitFirstPacket, null, + (packet) => + { + Parent.StopCreditThread(); + }, null); + + } + + public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes) + { + // Put the leftovers of the packet back into the queue. + lock (Parent.queueLock) + { + Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes)); + } + } + + public override void TransmissionCompleted() + { + // Stop and restart the credit thread. + Parent.StopCreditThread(); + Parent.StartCreditThread(Parent.IdleSlope); + } + + public override void TransmissionStarted(long bytesPerSecondRate) + { + // Decrease the credit by the idle slope. + Parent.StopCreditThread(); + Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate)); + } + } + } +} \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbackBase.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbackBase.cs new file mode 100644 index 0000000000000000000000000000000000000000..f40834a250d09480fdafb84c38016c4412015c50 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbackBase.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq; +using CBSVisualizer.Messaging; +using CBSVisualizer.Messaging.Events; + +namespace CBSVisualizer.Modules.Queue.ViewModels +{ + public partial class QueueViewModel + { + private abstract class LinkCallbackBase : ILinkCallback + { + protected readonly QueueViewModel Parent; + + protected LinkCallbackBase(QueueViewModel parentViewModel) + { + Parent = parentViewModel; + } + + protected long GetSendSlope(long rate) + { + return Parent.IdleSlope - rate; + } + + public int GetPriority() + { + return Parent.Priority; + } + + public virtual void Initialize() + { + // Do nothing by default. + } + + protected bool CanSend() + { + lock (Parent.queueLock) + { + return Parent.Queue.Count > 0 && Parent.CurrentCredit >= 0; + } + } + + + protected void TrySendPacket(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket, Action<PriorityPacket> additionalAcceptedAction, + Action<PriorityPacket> deniedPreClosingAction, Action<PriorityPacket> deniedHigherPrioAction) + { + lock (Parent.queueLock) + { + lock (Parent.creditLock) + { + if (!CanSend()) + { + return; + } + + var firstPacket = Parent.Queue.First(); + + switch (trySubmitFirstPacket.Invoke(firstPacket)) + { + case PacketSubmitResult.Accepted: + Parent.Queue.Remove(firstPacket); + additionalAcceptedAction?.Invoke(firstPacket); + break; + + case PacketSubmitResult.DeniedHigherPrio: + deniedHigherPrioAction?.Invoke(firstPacket); + break; + + case PacketSubmitResult.DeniedPreClosing: + deniedPreClosingAction?.Invoke(firstPacket); + break; + } + } + } + } + + public abstract void GateClosed(); + + public abstract void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket); + + public abstract void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes); + + public abstract void TransmissionCompleted(); + + public abstract void TransmissionStarted(long bytesPerSecondRate); + } + } +} \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbacks.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbacks.cs deleted file mode 100644 index 505317183a826de3767fb4d741c5988c90edbb97..0000000000000000000000000000000000000000 --- a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbacks.cs +++ /dev/null @@ -1,350 +0,0 @@ -using CBSVisualizer.Messaging; -using CBSVisualizer.Messaging.Events; -using System; -using System.Diagnostics; -using System.Linq; - -namespace CBSVisualizer.Modules.Queue.ViewModels -{ - public partial class QueueViewModel - { - public enum CreditBehaviour - { - // This is selected when there should be no credit-based shaper for this queue. - NoCbs, - - // Frozen credit behaviour - Frozen, - - // The standard credit behaviour - Standard, - - // Return to zero. - ReturnToZero - } - - private abstract class LinkCallbackBase : ILinkCallback - { - protected readonly QueueViewModel Parent; - - protected LinkCallbackBase(QueueViewModel parentViewModel) - { - Parent = parentViewModel; - } - - protected long GetSendSlope(long rate) - { - return Parent.IdleSlope - rate; - } - - public int GetPriority() - { - return Parent.Priority; - } - - public virtual void Initialize() - { - // Do nothing by default. - } - - protected bool CanSend() - { - lock (Parent.queueLock) - { - return Parent.Queue.Count > 0 && Parent.CurrentCredit >= 0; - } - } - - - protected void TrySendPacket(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket, Action<PriorityPacket> additionalAcceptedAction, - Action<PriorityPacket> deniedPreClosingAction, Action<PriorityPacket> deniedHigherPrioAction) - { - lock (Parent.queueLock) - { - lock (Parent.creditLock) - { - if (Parent.Queue.Count <= 0 || Parent.CurrentCredit < 0) - { - return; - } - - var firstPacket = Parent.Queue.First(); - - switch (trySubmitFirstPacket.Invoke(firstPacket)) - { - case PacketSubmitResult.Accepted: - Parent.Queue.Remove(firstPacket); - additionalAcceptedAction?.Invoke(firstPacket); - break; - - case PacketSubmitResult.DeniedHigherPrio: - deniedHigherPrioAction?.Invoke(firstPacket); - break; - - case PacketSubmitResult.DeniedPreClosing: - deniedPreClosingAction?.Invoke(firstPacket); - break; - } - } - } - } - - public abstract void GateClosed(); - - public abstract void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket); - - public abstract void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes); - - public abstract void TransmissionCompleted(); - - public abstract void TransmissionStarted(long bytesPerSecondRate); - } - - #region NoCbsLinkCallback - private class NoCbsLinkCallback : LinkCallbackBase - { - public NoCbsLinkCallback(QueueViewModel parent) - : base(parent) - { - } - - public override void GateClosed() - { - // Nothing to be done. - } - - public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket) - { - // Try to submit the "oldest" packet. - lock (Parent.queueLock) - { - // If the queue is empty, return. - if (Parent.Queue.Count <= 0) - { - return; - } - - // If the packet was accepted, remove it from the queue. - var firstPacket = Parent.Queue.First(); - - if (trySubmitFirstPacket.Invoke(firstPacket) == PacketSubmitResult.Accepted) - { - Parent.Queue.Remove(firstPacket); - } - - // Otherwise, just don't do anything :-) - } - } - - public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes) - { - // Build a new packet that just contains the leftover bytes and put it into the queue. - lock (Parent.queueLock) - { - Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes)); - } - } - - public override void TransmissionStarted(long bytesPerSecondRate) - { - // Just write some log. - Debug.WriteLine($"Packet of Queue {Parent.Priority} has started transmission with {bytesPerSecondRate} bytes/s."); - } - - public override void TransmissionCompleted() - { - // Nothing to be done. - } - } - #endregion - - #region StandardLinkCallback - private class StandardLinkCallback : LinkCallbackBase - { - public StandardLinkCallback(QueueViewModel parentViewModel) - : base(parentViewModel) - { - } - - public override void Initialize() - { - Parent.StartCreditThread(Parent.IdleSlope); - } - - public override void GateClosed() - { - // Stop the credit thread. - Parent.StopCreditThread(); - } - - public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket) - { - // Start the credit thread - Parent.StartCreditThread(Parent.IdleSlope); - - // Try to send the packet if we can. - TrySendPacket(trySubmitFirstPacket, null, null, null); - } - - public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes) - { - lock (Parent.queueLock) - { - Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes)); - } - } - - public override void TransmissionCompleted() - { - Log.Info("Transmission Completed"); - Parent.StopCreditThread(); - Parent.StartCreditThread(Parent.IdleSlope); - } - - public override void TransmissionStarted(long bytesPerSecondRate) - { - Log.Info("TransmissionStarted"); - Parent.StopCreditThread(); - Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate)); - } - } - #endregion - - #region FrozenLinkCallback - private class FrozenLinkCallback : LinkCallbackBase - { - public FrozenLinkCallback(QueueViewModel parent) - : base(parent) - { - } - - public override void Initialize() - { - Parent.StartCreditThread(Parent.IdleSlope); - } - - public override void GateClosed() - { - // Nothing special happens here. The credit handling is done in the GateOpened method. - } - - public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket) - { - // Try to submit first packet. - lock (Parent.queueLock) - { - if (!CanSend()) - { - return; - } - - var firstPacket = Parent.Queue.First(); - var submitResult = trySubmitFirstPacket.Invoke(firstPacket); - - // If the packet was accepted, remove it from the queue. - if (submitResult == PacketSubmitResult.Accepted) - { - Parent.Queue.Remove(firstPacket); - - // If my packet was denied due to pre-closing, freeze my credit. - } - else if (submitResult == PacketSubmitResult.DeniedPreClosing) - { - Parent.StopCreditThread(); - } - } - - // Otherwise, just let the credit grow for now. - } - - public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes) - { - // Put the leftovers of the packet back into the queue. - lock (Parent.queueLock) - { - Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes)); - } - } - - public override void TransmissionCompleted() - { - // Stop and restart the credit thread. - Parent.StopCreditThread(); - Parent.StartCreditThread(Parent.IdleSlope); - } - - public override void TransmissionStarted(long bytesPerSecondRate) - { - // Decrease the credit by the idle slope. - Parent.StopCreditThread(); - Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate)); - } - } - #endregion - - #region ReturnToZeroLinkCallback - private class ReturnToZeroLinkCallback : LinkCallbackBase - { - public ReturnToZeroLinkCallback(QueueViewModel parentViewModel) - : base(parentViewModel) - { - } - - public override void Initialize() - { - Parent.StartCreditThread(Parent.IdleSlope); - } - - public override void GateClosed() - { - // Nothing special to be done here. - } - - public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket) - { - lock (Parent.queueLock) - { - // Again, check if we can submit anything. - if (!CanSend()) - { - return; - } - - var firstPacket = Parent.Queue.First(); - var submitResult = trySubmitFirstPacket.Invoke(firstPacket); - - if (submitResult == PacketSubmitResult.Accepted) - { - Parent.Queue.Remove(firstPacket); - } - else if (submitResult == PacketSubmitResult.DeniedPreClosing) // In the pre-closing case, we signal the thread to increase our credit to zero. - { - Parent.StopCreditThread(); - Parent.StartCreditThread(Parent.IdleSlope, 0); - } - } - } - - public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes) - { - lock (Parent.queueLock) - { - Parent.Queue.Insert(0, new PriorityPacket(GetPriority(), leftoverBytes)); - } - } - - public override void TransmissionCompleted() - { - Parent.StopCreditThread(); - Parent.StartCreditThread(Parent.IdleSlope, 0); - } - - public override void TransmissionStarted(long bytesPerSecondRate) - { - Parent.StopCreditThread(); - Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate), 0); - } - } - #endregion - } -} \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.NoCbsLinkCallback.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.NoCbsLinkCallback.cs new file mode 100644 index 0000000000000000000000000000000000000000..5439a2e746bc5df6b3ae97c98b0acb7a5fee9625 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.NoCbsLinkCallback.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CBSVisualizer.Messaging; +using CBSVisualizer.Messaging.Events; + +namespace CBSVisualizer.Modules.Queue.ViewModels +{ + partial class QueueViewModel + { + private class NoCbsLinkCallback : LinkCallbackBase + { + public NoCbsLinkCallback(QueueViewModel parent) + : base(parent) + { + } + + public override void GateClosed() + { + // Nothing to be done. + } + + public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket) + { + // Try to submit the "oldest" packet. + lock (Parent.queueLock) + { + // If the queue is empty, return. + if (Parent.Queue.Count <= 0) + { + return; + } + + // If the packet was accepted, remove it from the queue. + var firstPacket = Parent.Queue.First(); + + if (trySubmitFirstPacket.Invoke(firstPacket) == PacketSubmitResult.Accepted) + { + Parent.Queue.Remove(firstPacket); + } + + // Otherwise, just don't do anything :-) + } + } + + public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes) + { + // Build a new packet that just contains the leftover bytes and put it into the queue. + lock (Parent.queueLock) + { + Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes)); + } + } + + public override void TransmissionStarted(long bytesPerSecondRate) + { + // Just write some log. + Log.Debug($"Packet of Queue {Parent.Priority} has started transmission with {bytesPerSecondRate} bytes/s."); + } + + public override void TransmissionCompleted() + { + // Nothing to be done. + } + } + + } +} diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.ReturnToZeroLinkCallback.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.ReturnToZeroLinkCallback.cs new file mode 100644 index 0000000000000000000000000000000000000000..90ee54b23794bc5af77af3e21e572c429c12b1d7 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.ReturnToZeroLinkCallback.cs @@ -0,0 +1,73 @@ +using System; +using System.Linq; +using CBSVisualizer.Messaging; +using CBSVisualizer.Messaging.Events; + +namespace CBSVisualizer.Modules.Queue.ViewModels +{ + public partial class QueueViewModel + { + private class ReturnToZeroLinkCallback : LinkCallbackBase + { + public ReturnToZeroLinkCallback(QueueViewModel parentViewModel) + : base(parentViewModel) + { + } + + public override void Initialize() + { + Parent.StartCreditThread(Parent.IdleSlope); + } + + public override void GateClosed() + { + // Nothing special to be done here. + } + + public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket) + { + lock (Parent.queueLock) + { + // Again, check if we can submit anything. + if (!CanSend()) + { + return; + } + + var firstPacket = Parent.Queue.First(); + var submitResult = trySubmitFirstPacket.Invoke(firstPacket); + + if (submitResult == PacketSubmitResult.Accepted) + { + Parent.Queue.Remove(firstPacket); + } + else if (submitResult == PacketSubmitResult.DeniedPreClosing) // In the pre-closing case, we signal the thread to increase our credit to zero. + { + Parent.StopCreditThread(); + Parent.StartCreditThread(Parent.IdleSlope, 0); + } + } + } + + public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes) + { + lock (Parent.queueLock) + { + Parent.Queue.Insert(0, new PriorityPacket(GetPriority(), leftoverBytes)); + } + } + + public override void TransmissionCompleted() + { + Parent.StopCreditThread(); + Parent.StartCreditThread(Parent.IdleSlope, 0); + } + + public override void TransmissionStarted(long bytesPerSecondRate) + { + Parent.StopCreditThread(); + Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate), 0); + } + } + } +} \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.StandardLinkCallback.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.StandardLinkCallback.cs new file mode 100644 index 0000000000000000000000000000000000000000..7da22685df2d1f38eabd388f9dc0a55e04a0ddf5 --- /dev/null +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.StandardLinkCallback.cs @@ -0,0 +1,59 @@ +using System; +using CBSVisualizer.Messaging; +using CBSVisualizer.Messaging.Events; + +namespace CBSVisualizer.Modules.Queue.ViewModels +{ + public partial class QueueViewModel + { + private class StandardLinkCallback : LinkCallbackBase + { + public StandardLinkCallback(QueueViewModel parentViewModel) + : base(parentViewModel) + { + } + + public override void Initialize() + { + Parent.StartCreditThread(Parent.IdleSlope); + } + + public override void GateClosed() + { + // Stop the credit thread. + Parent.StopCreditThread(); + } + + public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket) + { + // Start the credit thread + Parent.StartCreditThread(Parent.IdleSlope); + + // Try to send the packet if we can. + TrySendPacket(trySubmitFirstPacket, null, null, null); + } + + public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes) + { + lock (Parent.queueLock) + { + Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes)); + } + } + + public override void TransmissionCompleted() + { + Log.Info("Transmission Completed"); + Parent.StopCreditThread(); + Parent.StartCreditThread(Parent.IdleSlope); + } + + public override void TransmissionStarted(long bytesPerSecondRate) + { + Log.Debug($"Packet of Queue {Parent.Priority} has started transmission with {bytesPerSecondRate} bytes/s."); + Parent.StopCreditThread(); + Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate)); + } + } + } +} \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs index e3b9186fbf62cfba98648c931e9bcd7aa7cef90d..2be1aebf4c0256a81d3706070f8d1a567a8c627c 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs @@ -2,9 +2,6 @@ using CBSVisualizer.Messaging; using CBSVisualizer.Messaging.Events; using CBSVisualizer.Services.PacketService.Interface; -using LiveCharts; -using LiveCharts.Defaults; -using LiveCharts.Wpf; using log4net; using Prism.Commands; using Prism.Events; @@ -17,8 +14,23 @@ using System.Threading.Tasks; namespace CBSVisualizer.Modules.Queue.ViewModels { - public partial class QueueViewModel : RegionViewModelBase + public sealed partial class QueueViewModel : RegionViewModelBase, IDisposable { + public enum CreditBehaviour + { + // This is selected when there should be no credit-based shaper for this queue. + NoCbs, + + // Frozen credit behaviour + Frozen, + + // The standard credit behaviour + Standard, + + // Return to zero. + ReturnToZero + } + private const int ThreadJoinTimeoutS = 1; private const long CreditRefreshRateS = 5; @@ -80,8 +92,6 @@ namespace CBSVisualizer.Modules.Queue.ViewModels /// </summary> public int IdleSlope { get; set; } = 100; - public SeriesCollection Series { get; set; } - public DelegateCommand GeneratePacketOnClick { get; private set; } public QueueViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, int prio, IPacketService packetProvider) : @@ -100,8 +110,6 @@ namespace CBSVisualizer.Modules.Queue.ViewModels Queue.CollectionChanged += QueueChangedHandler; eventAggregator.GetEvent<RegisterLinkCallbackEvent>().Publish(GetLinkCallback()); - - InitCharts(); } private void HandleLabels() @@ -120,29 +128,16 @@ namespace CBSVisualizer.Modules.Queue.ViewModels private void QueueChangedHandler(object sender, NotifyCollectionChangedEventArgs e) { + eventAggregator.GetEvent<PacketCountChangedEvent>().Publish((Priority, Queue.Count)); + // Add the new value to the series. if (selectedCreditBehaviour != CreditBehaviour.NoCbs) { - Series[0].Values.Add(new DateTimePoint(DateTime.Now, CurrentCredit)); + eventAggregator.GetEvent<CreditChangedEvent>().Publish((Priority, CurrentCredit)); } - Series[1].Values.Add(new DateTimePoint(DateTime.Now, Queue.Count)); } - private void InitCharts() - { - Series = new SeriesCollection - { - new LineSeries { - Title = "Credit Values", - Values = new ChartValues<DateTimePoint>() { new DateTimePoint(DateTime.Now, 0) } - }, - - new LineSeries { - Title = "Packet Count", - Values = new ChartValues<DateTimePoint>() { new DateTimePoint(DateTime.Now, 0) } - } - }; - } + private void HandleCreditBehaviourChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { @@ -190,6 +185,8 @@ namespace CBSVisualizer.Modules.Queue.ViewModels private void StartCreditThread(long bytesPerSecondSlope, long limit = long.MaxValue) { + StopCreditThread(); + // Init new cancellation token. creditGrowthCancellationSource = new CancellationTokenSource(); @@ -225,7 +222,7 @@ namespace CBSVisualizer.Modules.Queue.ViewModels { creditGrowthCancellationSource?.Cancel(); - if (creditUpdateThread != null) + if (creditUpdateThread != null && creditUpdateThread.IsAlive) { Log.Info(creditUpdateThread.Join(TimeSpan.FromSeconds(ThreadJoinTimeoutS)) ? $"Queue {Priority}: Unable to stop credit thread." @@ -266,5 +263,11 @@ namespace CBSVisualizer.Modules.Queue.ViewModels }); }); } + + public void Dispose() + { + StopCreditThread(); + creditGrowthCancellationSource?.Dispose(); + } } } \ No newline at end of file diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml b/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml index 13428af22fec25fd6cfea6b91ea44b90a5ae6289..7d34ca0c094b942e11bdf17a51b5afb0663683bf 100644 --- a/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml +++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml @@ -20,7 +20,6 @@ <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> - <ColumnDefinition Width="3*"/> </Grid.ColumnDefinitions> <TextBlock Text="{Binding PrioLabel}" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center"/> <TextBlock Text="{Binding Priority}" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center"/> @@ -40,14 +39,5 @@ materialDesign:TextFieldAssist.UnderlineBrush="{DynamicResource SecondaryAccentBrush}" materialDesign:HintAssist.Hint="Credit Behaviour" x:Name="CreditBehaviourBox" SelectedItem="{Binding SelectedCreditBehaviour}" Grid.Column="3" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center"/> - - <lvc:CartesianChart Series="{Binding Series}" LegendLocation="Right" Grid.Column="4" Grid.RowSpan="2"> - <lvc:CartesianChart.AxisX> - <lvc:Axis Title="Time" LabelFormatter="{Binding XFormatter}" /> - </lvc:CartesianChart.AxisX> - <lvc:CartesianChart.AxisY> - <lvc:Axis Title="Credit"/> - </lvc:CartesianChart.AxisY> - </lvc:CartesianChart> </Grid> </UserControl> diff --git a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs index 3be0dffa2a4ad4d9c86d27bd977ff8e1e5f87906..884097646dcfa51fd725c1d7c34e3ffaa2f35547 100644 --- a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs +++ b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs @@ -46,8 +46,8 @@ namespace CBSVisualizer.Services.SettingsService.Implementation schedulersGroupMembers.Add(new SelectionSetting("scheduler", "Used Scheduler", schedulers.First(), schedulers)); // Random Scheduler: Max & Min delays. - schedulersGroupMembers.Add(new StringSetting("random_scheduler_min_delay", "Random Scheduler: Minimum Delay [ms]", "500")); - schedulersGroupMembers.Add(new StringSetting("random_scheduler_max_delay", "Random Scheduler: Maximum Delay [ms]", "5000")); + schedulersGroupMembers.Add(new StringSetting("random_scheduler_min_delay", "Random Scheduler: Minimum Gate Opened Time [ms]", "500")); + schedulersGroupMembers.Add(new StringSetting("random_scheduler_max_delay", "Random Scheduler: Maximum Gate Opened Time [ms]", "5000")); settingGroups.Add(new SettingGroup("Schedulers", schedulersGroupMembers)); } diff --git a/CBSVisualizer/CBSVisualizer.sln b/CBSVisualizer/CBSVisualizer.sln index ccf16e17435bdb3c9dd3020208640f94ca44a4ad..a35220e25683621ccb5e98381308bf9758335be9 100644 --- a/CBSVisualizer/CBSVisualizer.sln +++ b/CBSVisualizer/CBSVisualizer.sln @@ -36,7 +36,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CBSVisualizer.Core", "CBSVi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CBSVisualizer.Common", "CBSVisualizer.Common\CBSVisualizer.Common.csproj", "{9B1B603C-601C-4F31-ADD9-D0962C0011AF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CBSVisualizer.Services.PacketService", "CBSVisualizer.Services.PacketService\CBSVisualizer.Services.PacketService.csproj", "{274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CBSVisualizer.Services.PacketService", "CBSVisualizer.Services.PacketService\CBSVisualizer.Services.PacketService.csproj", "{274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CBSVisualizer.Modules.Charts", "CBSVisualizer.Modules.Charts\CBSVisualizer.Modules.Charts.csproj", "{CC0C2DDE-D058-4075-84A6-016C0518724A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -92,6 +94,10 @@ Global {274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}.Debug|Any CPU.Build.0 = Debug|Any CPU {274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}.Release|Any CPU.ActiveCfg = Release|Any CPU {274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}.Release|Any CPU.Build.0 = Release|Any CPU + {CC0C2DDE-D058-4075-84A6-016C0518724A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC0C2DDE-D058-4075-84A6-016C0518724A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC0C2DDE-D058-4075-84A6-016C0518724A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC0C2DDE-D058-4075-84A6-016C0518724A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -106,6 +112,7 @@ Global {AB9EA79C-F11F-4B93-A08E-8C52A9716666} = {BFDCC6CE-CAA6-45AA-832F-0CBAB9A3C8BA} {61B7FF00-1B9D-4ABF-B3BF-667A1505415F} = {BFDCC6CE-CAA6-45AA-832F-0CBAB9A3C8BA} {274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1} = {BFDCC6CE-CAA6-45AA-832F-0CBAB9A3C8BA} + {CC0C2DDE-D058-4075-84A6-016C0518724A} = {6D2194E0-E17B-44D6-AD8C-F3699549D259} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {EE8EFE44-67AF-451F-9DFD-7B458AA3B3B3} diff --git a/CBSVisualizer/CBSVisualizer/App.xaml.cs b/CBSVisualizer/CBSVisualizer/App.xaml.cs index dfe06d67ea0b4a22bbb891d7d3700fa8282a2f58..7aaf0bf5dec77f4e8309916b9396c08bc451d1e2 100644 --- a/CBSVisualizer/CBSVisualizer/App.xaml.cs +++ b/CBSVisualizer/CBSVisualizer/App.xaml.cs @@ -10,6 +10,7 @@ using CBSVisualizer.Modules.Link; using CBSVisualizer.Modules.SettingsDialog; using CBSVisualizer.Modules.MenuBar; using System.IO; +using CBSVisualizer.Modules.Charts; using CBSVisualizer.Services.PacketService.Implementation; using CBSVisualizer.Services.PacketService.Interface; using CBSVisualizer.Services.SchedulingService.Interface; @@ -41,6 +42,7 @@ namespace CBSVisualizer moduleCatalog.AddModule<LinkModule>(); moduleCatalog.AddModule<QueueGroupModule>(); moduleCatalog.AddModule<MenuBarModule>(); + moduleCatalog.AddModule<ChartsModule>(); } } } diff --git a/CBSVisualizer/CBSVisualizer/CBSVisualizer.csproj b/CBSVisualizer/CBSVisualizer/CBSVisualizer.csproj index 3a731bff7ba3bd2a27daaa261a8d5559858f9eae..a34f54c868506f60c713a2343f501a8f50e037fa 100644 --- a/CBSVisualizer/CBSVisualizer/CBSVisualizer.csproj +++ b/CBSVisualizer/CBSVisualizer/CBSVisualizer.csproj @@ -12,6 +12,7 @@ <PackageReference Include="Prism.DryIoc" Version="7.2.0.1422" /> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\CBSVisualizer.Modules.Charts\CBSVisualizer.Modules.Charts.csproj" /> <ProjectReference Include="..\CBSVisualizer.Modules.Link\CBSVisualizer.Modules.Link.csproj" /> <ProjectReference Include="..\CBSVisualizer.Modules.MenuBar\CBSVisualizer.Modules.MenuBar.csproj" /> <ProjectReference Include="..\CBSVisualizer.Modules.Queue.QueueGroup\CBSVisualizer.Modules.QueueGroup.csproj" /> diff --git a/CBSVisualizer/CBSVisualizer/Views/MainWindow.xaml b/CBSVisualizer/CBSVisualizer/Views/MainWindow.xaml index 1d124522c5525de76cc46166a5d4519982551b33..e8f27f4db3919e229369693c8ae02230b5e07b50 100644 --- a/CBSVisualizer/CBSVisualizer/Views/MainWindow.xaml +++ b/CBSVisualizer/CBSVisualizer/Views/MainWindow.xaml @@ -10,8 +10,7 @@ Background="{DynamicResource MaterialDesignPaper}" TextElement.FontWeight="Medium" TextElement.FontSize="14" - FontFamily="{materialDesign:MaterialDesignFont}" - > + FontFamily="{materialDesign:MaterialDesignFont}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> @@ -20,9 +19,11 @@ <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> + <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> - <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.MenuBarRegion}" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"/> - <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.QueueGroupRegion}" Grid.Column="1" Grid.Row="1"/> + <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.MenuBarRegion}" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3"/> <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.LinkRegion}" Grid.Column="0" Grid.Row="1" Margin="30, 0, 0, 0"/> + <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.QueueGroupRegion}" Grid.Column="1" Grid.Row="1"/> + <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.ChartsRegion}" Grid.Column="2" Grid.Row="1"/> </Grid> </Window>