diff --git a/VECTO3GUI2020/ViewModel/Implementation/JobListViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/JobListViewModel.cs index 20b83f277ab7535ebda70e3f76b8643e0a3665c2..5a801bd941630033208466d04d6bb85e1ee33756 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/JobListViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/JobListViewModel.cs @@ -22,6 +22,7 @@ using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Resources; +using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.InputData.FileIO.JSON; @@ -157,27 +158,21 @@ namespace VECTO3GUI2020.ViewModel.Implementation { cancellationTokenSource = new CancellationTokenSource(); SimulationRunning = true; - await RunSimulationAsync(cancellationTokenSource.Token, + await Task.Run(() => RunSimulationAsync(cancellationTokenSource.Token, new Progress<MessageEntry>((message) => { _outputViewModel.Messages.Add(message); }), - new Progress<int>((i) => _outputViewModel.Progress = i)); + new Progress<int>((i) => _outputViewModel.Progress = i), + new Progress<string>((msg) => _outputViewModel.StatusMessage = msg))); SimulationRunning = false; - _outputViewModel.Progress = 0; + _outputViewModel.SumProgress = 0; cancellationTokenSource.Dispose(); } - private async Task RunSimulationAsync(CancellationToken ct, IProgress<MessageEntry> outputMessages, IProgress<int> progress) + private async Task RunSimulationAsync(CancellationToken ct, IProgress<MessageEntry> outputMessages, + IProgress<int> progress, IProgress<string> status) { progress.Report(0); - //for (int i = 0; i <= 100; i++) { - // await Task.Delay(100); - // progress.Report(i); - // if (ct.IsCancellationRequested) { - // return; - // } - //} - - - + status.Report("starting..."); + IDocumentViewModel[] jobs; lock (_jobsLock) { jobs = Jobs.Where(x => x.Selected).ToArray(); @@ -187,22 +182,14 @@ namespace VECTO3GUI2020.ViewModel.Implementation Time = DateTime.Now, Type = MessageType.InfoMessage, }); + status.Report("No jobs selected"); return; } } - //TODO add output path to settings - var outputPath = Settings.Default.DefaultFilePath; - var sumFileWriter = new FileOutputWriter(GetOutputDirectory(Jobs.First(x => x.Selected).DataSource.SourceFile)); - - - var sumContainer = new SummaryDataContainer(sumFileWriter); var jobContainer = new JobContainer(sumContainer); - - - var mode = ExecutionMode.Declaration; var fileWriters = new Dictionary<int, FileOutputWriter>(); @@ -210,9 +197,6 @@ namespace VECTO3GUI2020.ViewModel.Implementation var xmlReader = _inputDataReader; - - - foreach (var jobEntry in jobs) { try { @@ -299,24 +283,37 @@ namespace VECTO3GUI2020.ViewModel.Implementation SerializeVectoRunData = Settings.Default.SerializeVectoRunData, }; + + var stopwatch = new Stopwatch(); + stopwatch.Start(); foreach (var runId in jobContainer.AddRuns(runsFactory)) { + if (ct.IsCancellationRequested) { + outputMessages.Report(new MessageEntry() + { + Message = "Simulation canceled", + Type = MessageType.StatusMessage, + }); + return; + } fileWriters.Add(runId, fileWriter); } + stopwatch.Stop(); + // TODO MQ-20200525: Remove the following loop in production (or after evaluation of LAC!! - /* - if (!string.IsNullOrWhiteSpace(LookAheadMinSpeedOverride)) - { - foreach (var run in jobContainer.Runs) - { - var tmpDriver = ((VectoRun)run.Run).GetContainer().RunData.DriverData; - tmpDriver.LookAheadCoasting.Enabled = true; - tmpDriver.LookAheadCoasting.MinSpeed = LookAheadMinSpeedOverride.ToDouble().KMPHtoMeterPerSecond(); - } - } - */ + + //if (!string.IsNullOrWhiteSpace(LookAheadMinSpeedOverride)) + //{ + // foreach (var run in jobContainer.Runs) + // { + // var tmpDriver = ((VectoRun)run.Run).GetContainer().RunData.DriverData; + // tmpDriver.LookAheadCoasting.Enabled = true; + // tmpDriver.LookAheadCoasting.MinSpeed = LookAheadMinSpeedOverride.ToDouble().KMPHtoMeterPerSecond(); + // } + //} + outputMessages.Report( new MessageEntry() @@ -360,27 +357,27 @@ namespace VECTO3GUI2020.ViewModel.Implementation if (ct.IsCancellationRequested) { jobContainer.Cancel(); + outputMessages.Report(new MessageEntry() { + Message = "Simulation canceled", + Type = MessageType.StatusMessage, + }); return; } var jobProgress = jobContainer.GetProgress(); var sumProgress = jobProgress.Sum(x => x.Value.Progress); var duration = start.Elapsed.TotalSeconds; + jobProgress.Select(x => x.Value.Progress); progress.Report(Convert.ToInt32(sumProgress * 100 / jobProgress.Count)); - //outputMessages.Report( - // new MessageEntry() - // { - // Type = VectoSimulationProgress.MsgType.Progress, - // Message = string.Format( - // "Duration: {0:F1}s, Curernt Progress: {1:P} ({2})", duration, sumProgress / progress.Count, - // string.Join(", ", progress.Select(x => string.Format("{0,4:P}", x.Value.Progress)))) - // }); - var justFinished = jobProgress.Where(x => x.Value.Done & !finishedRuns.Contains(x.Key)) + status.Report(string.Format( + "Duration: {0:F1}s, Current Progress: {1:P} ({2})", duration, sumProgress / jobProgress.Count, + string.Join(", ", jobProgress.Select(x => string.Format("{0,4:P}", x.Value.Progress))))); + var justFinished = jobProgress.Where(x => x.Value.Done & !finishedRuns.Contains(x.Key)) .ToDictionary(x => x.Key, x => x.Value); //PrintRuns(justFinished, fileWriters); finishedRuns.AddRange(justFinished.Select(x => x.Key)); - await Task.Delay(100); + await Task.Delay(100, ct); } start.Stop(); @@ -447,10 +444,45 @@ namespace VECTO3GUI2020.ViewModel.Implementation Type = MessageType.StatusMessage, Message = string.Format("Simulation finished in {0:F1}s", start.Elapsed.TotalSeconds) }); - - + } + private void PrintRuns(Dictionary<int, JobContainer.ProgressEntry> progress, Dictionary<int, FileOutputWriter> fileWriters, IProgress<MessageEntry> outputMessages) + { + foreach (var p in progress) { + var modFilename = fileWriters[p.Key] + .GetModDataFileName(p.Value.RunName, p.Value.CycleName, p.Value.RunSuffix); + var runName = string.Format("{0} {1} {2}", p.Value.RunName, p.Value.CycleName, p.Value.RunSuffix); + + // if (p.Value.Error != null) + // { + // SimulationWorker.ReportProgress(0, new VectoSimulationProgress() + // { + // Type = VectoSimulationProgress.MsgType.StatusMessage, + // Message = string.Format("Finished Run {0} with ERROR: {1}", runName, + // p.Value.Error.Message), + // Link = "<CSV>" + modFilename + // }); + // } + // else + // { + // SimulationWorker.ReportProgress(0, new VectoSimulationProgress() + // { + // Type = VectoSimulationProgress.MsgType.StatusMessage, + // Message = string.Format("Finished run {0} successfully.", runName) + // }); + // } + // if (File.Exists(modFilename)) + // { + // SimulationWorker.ReportProgress(0, new VectoSimulationProgress() + // { + // Type = VectoSimulationProgress.MsgType.StatusMessage, + // Message = string.Format("Run {0}: Modal results written to {1}", runName, modFilename), + // Link = "<CSV>" + modFilename + // }); + // } + } } + private string GetOutputDirectory(string jobFilePath) { var outFile = jobFilePath; @@ -477,7 +509,13 @@ namespace VECTO3GUI2020.ViewModel.Implementation { get { - return _cancelSimulationCommand ?? new RelayCommand(() => { cancellationTokenSource.Cancel(); }, + return _cancelSimulationCommand ?? new RelayCommand(() => { + _outputViewModel.Messages.Add(new MessageEntry() { + Message="Canceling Simulation", + Type=MessageType.StatusMessage, + }); + cancellationTokenSource.Cancel(); + }, () => SimulationRunning); } } diff --git a/VECTO3GUI2020/ViewModel/Implementation/MessageEntry.cs b/VECTO3GUI2020/ViewModel/Implementation/MessageEntry.cs index af0ed0fcac68caf3bbfef1c8b134bc840c0b3562..d1bff4229030242c6a959b12fad118562ffb7422 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/MessageEntry.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/MessageEntry.cs @@ -20,6 +20,7 @@ namespace VECTO3GUI2020.ViewModel.Implementation private DateTime _time = DateTime.Now; private string _source; private MessageType _type; + private string _link; public string Message { @@ -27,6 +28,12 @@ namespace VECTO3GUI2020.ViewModel.Implementation set { SetProperty(ref _message, value); } } + public string Link + { + get { return _link; } + set {} + } + public MessageType Type { get { return _type; } diff --git a/VECTO3GUI2020/ViewModel/Implementation/OutputViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/OutputViewModel.cs index 88ea0207fc5b29c0c9cc417dd1abb3b4018677b2..2782a7156f425dcdbbf91b6e420b3296f5b203f6 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/OutputViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/OutputViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Windows.Data; using VECTO3GUI2020.ViewModel.Implementation; @@ -15,6 +16,7 @@ namespace VECTO3GUI2020.ViewModel private object _messageLock = new Object(); private ObservableCollection<MessageEntry> _messages = new ObservableCollection<MessageEntry>(); private int _progress; + private string _statusMessage; public ObservableCollection<MessageEntry> Messages { @@ -24,10 +26,16 @@ namespace VECTO3GUI2020.ViewModel } } - public int Progress + public double SumProgress { - get => _progress; - set => SetProperty(ref _progress, value); + get => _sumProgress; + set => SetProperty(ref _sumProgress, value); + } + + public string StatusMessage + { + get { return _statusMessage; } + set { SetProperty(ref _statusMessage, value); } } @@ -36,14 +44,19 @@ namespace VECTO3GUI2020.ViewModel BindingOperations.EnableCollectionSynchronization(Messages, _messageLock ); } + public void SetProgress(double sumProgress, IList<double> subProgress) + { + SumProgress = sumProgress; + SubProgress = subProgress; - } + } public interface IOutputViewModel : IMainViewModel { ObservableCollection<MessageEntry> Messages { get; } int Progress { get; set; } + string StatusMessage { get; set; } } } \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/Implementation/SettingsViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/SettingsViewModel.cs index e1a1adcb5081ee54ec837f75d327609e0cc477ca..76246e6e1f270d47a5b61b183a99efa48c697a9a 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/SettingsViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/SettingsViewModel.cs @@ -61,6 +61,7 @@ namespace VECTO3GUI2020.ViewModel.Implementation _actualModalData = _settings.ActualModalData; _serializeVectoRunData = _settings.SerializeVectoRunData; _dialogHelper = dialogHelper; + _defaultOutputPath = _settings.DefaultOutputPath; } private ICommand _closeWindowCommand; diff --git a/VECTO3GUI2020/Views/JoblistView.xaml b/VECTO3GUI2020/Views/JoblistView.xaml index b714c17aea7e2cb3acc6bea2d88b3a4bfb0119f8..d0f691c0a4e7068dd7a99da7317d765d81417634 100644 --- a/VECTO3GUI2020/Views/JoblistView.xaml +++ b/VECTO3GUI2020/Views/JoblistView.xaml @@ -89,18 +89,18 @@ <Button x:Name="button3" Margin="4" HorizontalAlignment="Stretch" Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding AddJobAsyncCommand}" Background="#FFDDDDDD"> - OpenFile</Button> + Add Job</Button> <Button x:Name="button4" Margin ="4" HorizontalAlignment="Stretch" Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding EditJob}" - CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">EditFile</Button> + CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">Edit Job</Button> <Button x:Name="button5" Margin="4" HorizontalAlignment="Stretch" Style="{StaticResource MultiStageButtonStyle1}" - Command="{Binding NewManufacturingStageFile}" AutomationProperties.AutomationId="JobListViewNewManufacturingStageFileButton">New Multistage File</Button> + Command="{Binding NewManufacturingStageFile}" AutomationProperties.AutomationId="JobListViewNewManufacturingStageFileButton">New Multistage Job</Button> <Button x:Name="button6" Margin="4" HorizontalAlignment="Stretch" Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding RemoveJob}" - CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">DeleteFile</Button> + CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">Remove Job</Button> </StackPanel> </Border> </Grid> diff --git a/VECTO3GUI2020/Views/OutputView.xaml b/VECTO3GUI2020/Views/OutputView.xaml index 89a5c64cec674706e509832a5e5295d41a458ee2..3cc600686185c0ef8730eafe6322bde72ce61c06 100644 --- a/VECTO3GUI2020/Views/OutputView.xaml +++ b/VECTO3GUI2020/Views/OutputView.xaml @@ -5,8 +5,9 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:VECTO3GUI2020.Views" xmlns:impl="clr-namespace:VECTO3GUI2020.ViewModel.Implementation" + xmlns:viewModel="clr-namespace:VECTO3GUI2020.ViewModel" mc:Ignorable="d" - d:DesignHeight="450" d:DesignWidth="800"> + d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignData Type=viewModel:IOutputViewModel}"> <Grid> <DockPanel> <ProgressBar DockPanel.Dock="Top" Minimum="0" Maximum="100" Value="{Binding Progress}"></ProgressBar> @@ -14,13 +15,18 @@ IsReadOnly="True" HeadersVisibility="All" RowHeaderWidth="5" Name="MessageList"> <DataGrid.Columns> - <DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="*"> - <DataGridTextColumn.ElementStyle> - <Style> - <Setter Property="TextBlock.TextWrapping" Value="Wrap" /> - </Style> - </DataGridTextColumn.ElementStyle> - </DataGridTextColumn> + <DataGridTemplateColumn Header="Message" Width="*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <StackPanel> + <TextBlock Text="{Binding Message}" Visibility="{Binding Message, Converter={StaticResource NullToVisibilityConverter}}" + TextWrapping="Wrap"/> + <TextBlock Text="{Binding Link}" Visibility="{Binding Message, Converter={StaticResource NullToVisibilityConverter}}" + TextWrapping="Wrap"/> + </StackPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> <DataGridTextColumn Header="Time" Binding="{Binding Time}" Width="130" /> </DataGrid.Columns> <DataGrid.RowStyle> @@ -63,6 +69,7 @@ </Style> </DataGrid.CellStyle> </DataGrid> + <StatusBar DockPanel.Dock="Bottom" VerticalAlignment="Bottom"><TextBlock Text="{Binding StatusMessage}"/></StatusBar> </DockPanel> </Grid> </UserControl> diff --git a/VectoCore/VectoCore/OutputData/FileIO/FileOutputWriter.cs b/VectoCore/VectoCore/OutputData/FileIO/FileOutputWriter.cs index e722365d334ca7528e119b505b515eaaa8193ddf..cf36a8dd30ddda62e1a4721f7e504c15806a14d6 100644 --- a/VectoCore/VectoCore/OutputData/FileIO/FileOutputWriter.cs +++ b/VectoCore/VectoCore/OutputData/FileIO/FileOutputWriter.cs @@ -67,7 +67,7 @@ namespace TUGraz.VectoCore.OutputData.FileIO public string XMLPrimaryVehicleReportName { - get { return Path.ChangeExtension(_jobFile, "RSLT_PIF.xml"); } + get { return Path.ChangeExtension(_jobFile, "RSLT_VIF.xml"); } } public string XMLMonitoringReportName