diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml index 2cd4a7add9d9c6cfab1d1f8d8baa601d4e7ffd31..fccccfdf3c52b8beec471932468ebe8a20b4f3f2 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml @@ -40,7 +40,7 @@ </StackPanel> <!-- <header:HeaderTemplate VerticalAlignment="Center" Height="534"/> --> - <Button Margin="0,100,150,10" Width="40" Height="40" HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" BorderBrush="Transparent" Click="discardSession_Click"> + <Button Margin="0,100,150,10" Width="40" Height="40" HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" BorderBrush="Transparent" Click="DiscardSession_Click"> <Grid > <Line X1="5" Y1="5" X2="35" Y2="35" Stroke="Gray" StrokeThickness="5" /> <Line X1="5" Y1="35" X2="35" Y2="5" Stroke="Gray" StrokeThickness="5" /> @@ -53,10 +53,8 @@ </StackPanel> <Button Content="Pause" Name="PlayPauseButton" Style="{StaticResource PlayPauseButton}" HorizontalAlignment="Center" Margin="0,320,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Click="PlayPause_Click"></Button> - <!-- - <Button Content="Mascott Up" Click="Button_Click_1" HorizontalAlignment="Left" Margin="116,375,0,0" VerticalAlignment="Top"/> + <Button Content="Mascott Up" Click="Button_Click_1" HorizontalAlignment="Left" Margin="116,375,0,0" VerticalAlignment="Top"/> <Button Content="Mascott Down" Click="Button_Click" HorizontalAlignment="Left" Margin="116,400,0,0" VerticalAlignment="Top"/> <TextBlock HorizontalAlignment="Left" Margin="116,350,0,0" Text="0" VerticalAlignment="Top" Name="StageText"/> - --> </Grid> </Page> \ No newline at end of file diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml.cs index 011d391712f59fa76abd275e4cc0c2ead3d91b91..c5323c2a97250c4e6826cb4b4572880c8b50061e 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml.cs +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml.cs @@ -1,17 +1,8 @@ using InnoLabProjektDektopApp.Screens.Regulaer; using InnoLabProjektDektopApp.Services; -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Text; 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; using System.Windows.Threading; @@ -34,8 +25,7 @@ namespace InnoLabProjektDektopApp private Mascott mascott; - - private Timer timer; + private DispatcherTimer timer; private int maxTime; private int seconds; private int step = -1; //Indicates whether the timer is running (-1) or paused (0) @@ -64,95 +54,101 @@ namespace InnoLabProjektDektopApp this.seconds = this.maxTime; this.sessions = cycles; - - timer = new Timer(timertick, null, 0, 1000); //A background timer calls timertick every second - - //StageText.Text = ProcessMonitor.tmpStage.ToString(); + timer = new DispatcherTimer(); + timer.Interval = TimeSpan.FromSeconds(1); + timer.Tick += Timertick; + timer.Start(); mascott = new Mascott(); mascott.Show(); processMonitor.StartMonitoring(); CreateCycleIndicators(); // Kreise erstellen - updateTexts(); + UpdateTexts(); + + // Subscribe to the events of the process monitor + processMonitor.MonitorCycleStarted += HandleMonitorCycleStarted; + processMonitor.MonitorPaused += HandleMonitorPaused; + processMonitor.MonitorResumed += HandleMonitorResumed; + processMonitor.MonitorBreakStarted += HandleMonitorBreakStarted; + processMonitor.MonitorSessionFinished += HandleMonitorSessionFinished; } - private void timertick(object state) + private void HandleMonitorCycleStarted(object sender, EventArgs e) { - Dispatcher.Invoke(() => - { - seconds += step; // Reduziere Zeit, wenn der Timer läuft - updateTexts(); // Aktualisiere die UI - - // Fortschrittsanzeige nur während der Fokusperiode aktualisieren - - CreateCycleIndicators(); // Fortschritt für Fokus-Perioden anzeigen - - - if (seconds <= 0) // Wenn die Zeit abgelaufen ist - { - stopTimer(); // Timer stoppen + seconds = maxTime; // Zeit für die Fokusperiode + isBreakPeriod = false; // Zurück zum Fokus + currentSession++; // Gehe zum nächsten Zyklus + PlayPauseButton.Content = "Pause"; + } - if (currentSession >= sessions) // Wenn alle Zyklen abgeschlossen sind - { - timer.Dispose(); // Timer stoppen und aufräumen - MessageBox.Show("All sessions completed!", "Info", MessageBoxButton.OK, MessageBoxImage.Information); - var jsonpath = processMonitor.FinishSession(); - this.NavigationService.Navigate(new SessionStatistics(jsonpath)); - return; - } - if (isBreakPeriod) // Wenn wir in einer Pause sind - { - isBreakPeriod = false; // Zurück zum Fokus - seconds = maxTime; // Zeit für die Fokusperiode - currentSession++; // Gehe zum nächsten Zyklus - processMonitor.EndBreak(); - PlayPauseButton.Content = "Pause"; - } - else // Wenn wir im Fokus sind - { - isBreakPeriod = true; // Wechsel in den Pausenmodus - seconds = breakPeriod; // Zeit für die Pause - processMonitor.StartBreak(); - } - + private void HandleMonitorPaused(object sender, EventArgs e) + { + timer.Stop(); // Stop the time + step = 0; // Stop counting down + PlayPauseButton.Content = "Continue"; // Update button text + } - startTimer(); // Starte den Timer für die nächste Periode - } else - { - if(isBreakPeriod) - { - PlayPauseButton.Content = "Skip Break"; - } - } - }); + private void HandleMonitorResumed(object sender, EventArgs e) + { + timer.Start(); + step = -1; // Set step to countdown + PlayPauseButton.Content = "Pause"; } + private void HandleMonitorBreakStarted(object sender, EventArgs e) + { + PlayPauseButton.Content = "Skip Break"; + seconds = breakPeriod; // Zeit für die Pause + isBreakPeriod = true; // Wechsel in den Pausenmodus + } - public void startTimer() + private void HandleMonitorSessionFinished(object sender, EventArgs e) { - if (seconds <= 0) return; // Prevent starting if time is zero - step = -1; // Set step to countdown - PlayPauseButton.Content = "Pause"; // Update button text - processMonitor.EndPause(); + timer.Stop(); + string jsonpath = ((ProcessMonitor)sender).lastSessionInfoFilePath; + NavigateTo(new SessionStatistics(jsonpath)); + MessageBox.Show("All sessions completed!", "Info", MessageBoxButton.OK, MessageBoxImage.Information); } - public void stopTimer() + + + private void Timertick(object sender, EventArgs e) { - step = 0; // Stop counting down - PlayPauseButton.Content = "Start"; // Update button text - processMonitor.StartPause(); + seconds += step; // Reduziere Zeit, wenn der Timer läuft + + UpdateTexts(); // Aktualisiere die UI + + // Fortschrittsanzeige nur während der Fokusperiode aktualisieren + + CreateCycleIndicators(); // Fortschritt für Fokus-Perioden anzeigen + + if (seconds <= 0) // Wenn die Zeit abgelaufen ist + { + if (currentSession >= sessions) // Wenn alle Zyklen abgeschlossen sind + { + processMonitor.FinishSession(); + return; + } + if (isBreakPeriod) // Wenn wir in einer Pause sind + { + processMonitor.EndBreak(); + } + else // Wenn wir im Fokus sind + { + processMonitor.StartBreak(); + } + } } - public void setTime(int minutes, int seconds) + public void SetTime(int minutes, int seconds) { if (minutes < 0 || minutes > maxTime / 60 || seconds < 0 || seconds > maxTime % 60) return; - seconds = minutes * 60 + seconds; - updateTexts(); + this.seconds = minutes * 60 + seconds; + UpdateTexts(); } - - private void updateTexts() + private void UpdateTexts() { Clock.Text = seconds / 60 + ":" + (seconds % 60 < 10 ? "0" : "") + seconds % 60; @@ -166,32 +162,25 @@ namespace InnoLabProjektDektopApp } } - private void PlayPause_Click(object sender, RoutedEventArgs e) { if (step < 0) { - if(isBreakPeriod) + if (isBreakPeriod) { - isBreakPeriod = false; // Zurück zum Fokus - seconds = maxTime; // Zeit für die Fokusperiode - currentSession++; // Gehe zum nächsten Zyklus processMonitor.EndBreak(); - PlayPauseButton.Content = "Pause"; } else { - stopTimer(); + processMonitor.StartPause(); } } else { - startTimer(); + processMonitor.EndPause(); } - } - private void CreateCycleIndicators() { // Clear existing indicators @@ -204,7 +193,7 @@ namespace InnoLabProjektDektopApp if (isBreakPeriod) // Während der BreakPeriod { // Zeige ausgefüllten Kreis für die aktuelle Session - Ellipse filledCircle = new Ellipse + Ellipse filledCircle = new() { Width = 20, Height = 20, @@ -216,7 +205,7 @@ namespace InnoLabProjektDektopApp else // Während der FocusPeriod { // Zeige die ProgressBar für die aktuelle Session - Grid cycleGrid = new Grid + Grid cycleGrid = new() { Width = 50, Height = 20, // Höhe des erweiterten Kreises @@ -224,11 +213,11 @@ namespace InnoLabProjektDektopApp }; // ProgressBar - Rectangle progressBar = new Rectangle + Rectangle progressBar = new() { Width = 50, // Gleiche Breite wie der Hintergrund Height = 20, // Gleiche Höhe wie der Hintergrund - Fill = GradientGenerator.generateTwoColorBrush( + Fill = GradientGenerator.GenerateTwoColorBrush( Color.FromRgb(72, 98, 132), Color.FromRgb(222, 222, 222), 1 - (seconds / (double)maxTime) @@ -245,7 +234,7 @@ namespace InnoLabProjektDektopApp else { // Standardkreis für abgeschlossene oder zukünftige Zyklen - Ellipse cycleIndicator = new Ellipse + Ellipse cycleIndicator = new() { Width = 20, Height = 20, @@ -258,10 +247,10 @@ namespace InnoLabProjektDektopApp } } - private void discardSession_Click(object sender, RoutedEventArgs e) + private void DiscardSession_Click(object sender, RoutedEventArgs e) { // Neues Fenster für die Auswahl des Abbruchgrunds erstellen - Window reasonWindow = new Window + Window reasonWindow = new() { Title = "Warum beenden Sie die Sitzung?", Width = 600, @@ -271,17 +260,17 @@ namespace InnoLabProjektDektopApp }; // Haupt-StackPanel für die Radiobuttons und den OK-Button - StackPanel stackPanel = new StackPanel + StackPanel stackPanel = new() { Margin = new Thickness(10) }; // Radiobuttons für die Gründe - RadioButton reason1 = new RadioButton { Content = "Ich habe mich dazu entschieden, frühzeitig zu beenden (wird in die Statistik mit aufgenommen).", Margin = new Thickness(5), IsChecked = true }; - RadioButton reason2 = new RadioButton { Content = "Mir ist etwas sehr Wichtiges dazwischengekommen, was ich nicht verschieben konnte.", Margin = new Thickness(5) }; + RadioButton reason1 = new() { Content = "Ich habe mich dazu entschieden, frühzeitig zu beenden (wird in die Statistik mit aufgenommen).", Margin = new Thickness(5), IsChecked = true }; + RadioButton reason2 = new() { Content = "Mir ist etwas sehr Wichtiges dazwischengekommen, was ich nicht verschieben konnte.", Margin = new Thickness(5) }; // OK-Button - Button okButton = new Button + Button okButton = new() { Content = "Ok", Margin = new Thickness(5), @@ -296,8 +285,7 @@ namespace InnoLabProjektDektopApp MessageBox.Show($"Abbruchgrund: {selectedReason}", "Sitzung beendet", MessageBoxButton.OK, MessageBoxImage.Information); reasonWindow.Close(); - var jsonpath = processMonitor.FinishSession(); - this.NavigationService.Navigate(new SessionStatistics(jsonpath)); + processMonitor.FinishSession(); }; // Radiobuttons und Button zum StackPanel hinzufügen @@ -313,7 +301,7 @@ namespace InnoLabProjektDektopApp reasonWindow.Show(); } - public DateTime timeLeft() + public DateTime TimeLeft() { return DateTime.Now.AddSeconds(maxTime - seconds); } @@ -325,19 +313,20 @@ namespace InnoLabProjektDektopApp private void Button_Click_1(object sender, RoutedEventArgs e) { - //mascott.emotionUp(); + mascott.emotionUp_(); ProcessMonitor.tmpStage++; - //StageText.Text = ProcessMonitor.tmpStage.ToString(); + StageText.Text = ProcessMonitor.tmpStage.ToString(); } private void Button_Click(object sender, RoutedEventArgs e) { - //mascott.emotionDown(); + mascott.emotionDown_(); ProcessMonitor.tmpStage--; - //StageText.Text = ProcessMonitor.tmpStage.ToString(); + StageText.Text = ProcessMonitor.tmpStage.ToString(); } - public void navigateTo(Object page) { + public void NavigateTo(Object page) + { this.NavigationService.Navigate(page); } @@ -385,18 +374,21 @@ namespace InnoLabProjektDektopApp public static class GradientGenerator { - public static Brush generateTwoColorBrush(Color color1, Color color2, double ratio) + public static Brush GenerateTwoColorBrush(Color color1, Color color2, double ratio) { - GradientStopCollection collection = new GradientStopCollection(); - - collection.Add(new GradientStop(color1, 0)); - collection.Add(new GradientStop(color1, ratio)); - collection.Add(new GradientStop(color2, ratio)); - collection.Add(new GradientStop(color2, 1.0)); - - LinearGradientBrush brush = new LinearGradientBrush(collection); - brush.StartPoint = new Point(0, 0); - brush.EndPoint = new Point(1, 0); + GradientStopCollection collection = + [ + new GradientStop(color1, 0), + new GradientStop(color1, ratio), + new GradientStop(color2, ratio), + new GradientStop(color2, 1.0), + ]; + + LinearGradientBrush brush = new(collection) + { + StartPoint = new Point(0, 0), + EndPoint = new Point(1, 0) + }; return brush; } diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/Mascott.xaml.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/Mascott.xaml.cs index c7269fcb1dbd32e227191ce781284c121a4f1942..0b2058e38cd48cb0613af5a88f820e845c151504 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/Mascott.xaml.cs +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/Mascott.xaml.cs @@ -1,25 +1,13 @@ using InnoLabProjektDektopApp.Services; -using System; -using System.Collections.Generic; +using System.Diagnostics; using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Security.Policy; -using System.Text; using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; using System.Windows; -using System.Windows.Automation.Text; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Forms.VisualStyles; using System.Windows.Input; +using System.Windows.Interop; using System.Windows.Media; -using System.Windows.Media.Animation; using System.Windows.Media.Imaging; -using System.Windows.Shapes; +using System.Windows.Threading; namespace InnoLabProjektDektopApp.Screens.Regulaer { @@ -28,8 +16,8 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer /// </summary> public partial class Mascott : Window { - private Timer frameTimer; - private Timer animationTimer; + private DispatcherTimer frameTimer; + private DispatcherTimer animationTimer; private int frameCounter = 0; private int distractionStage = 4; private string framePath = ""; @@ -37,7 +25,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer private string animationDirection = "Up"; ProcessMonitor processMonitor; - + public Mascott() { @@ -54,37 +42,44 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer this.Left = -30; //SystemParameters.PrimaryScreenWidth - this.Width; this.Top = SystemParameters.PrimaryScreenHeight - this.Height - 30; - animationTimer = new Timer(animationTick, null, 0, 4000); - } + animationTimer = new DispatcherTimer(); + animationTimer.Interval = TimeSpan.FromMilliseconds(4000); + animationTimer.Tick += animationTick; + animationTimer.Start(); + RenderOptions.SetBitmapScalingMode(MascottImage, BitmapScalingMode.LowQuality); + RenderOptions.ProcessRenderMode = RenderMode.Default; + + } - private void animationTick(object state) + private void animationTick(object sender, EventArgs e) { + DateTime timeLeft = Overview.getSessionInstance().TimeLeft(); + int processMonitorStage = processMonitor.CalculateCurrentDistractionStage(DateTime.Now); - Application.Current.Dispatcher.Invoke(() => + if (processMonitorStage == oldDistractionStage) { - - DateTime timeLeft = Overview.getSessionInstance().timeLeft(); - int processMonitorStage = processMonitor.CalculateCurrentDistractionStage(DateTime.Now); - - - if (processMonitorStage == oldDistractionStage) { - Counterxd.Text = "x: " + processMonitorStage.ToString(); - return; - } else if (processMonitorStage < oldDistractionStage) { - emotionDown_(); - Counterxd.Text = "d: " + processMonitorStage.ToString(); - } else if(processMonitorStage > oldDistractionStage) { - emotionUp_(); - Counterxd.Text = "u: " + processMonitorStage.ToString(); - } - oldDistractionStage = processMonitorStage; - }); + Counterxd.Text = "x: " + processMonitorStage.ToString(); + return; + } + else if (processMonitorStage < oldDistractionStage) + { + emotionUp_(); + Counterxd.Text = "d: " + processMonitorStage.ToString(); + } + else if (processMonitorStage > oldDistractionStage) + { + emotionDown_(); + Counterxd.Text = "u: " + processMonitorStage.ToString(); + } + oldDistractionStage = processMonitorStage; } - public void emotionUp_() { + public void emotionUp_() + { if (animationDirection == "Down") distractionStage--; - if (distractionStage < 1) { + if (distractionStage < 1) + { distractionStage = 1; return; } @@ -92,12 +87,17 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer frameCounter = 1; Counterxd.Text = distractionStage.ToString(); - frameTimer = new Timer(frameTick, null, 0, 42); + frameTimer = new DispatcherTimer(); + frameTimer.Interval = TimeSpan.FromMilliseconds(42); + frameTimer.Tick += frameTick; + frameTimer.Start(); } - public void emotionDown_() { + public void emotionDown_() + { if (animationDirection == "Up") distractionStage++; - if (distractionStage > 7) { + if (distractionStage > 7) + { distractionStage = 7; return; } @@ -105,39 +105,39 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer frameCounter = 1; Counterxd.Text = distractionStage.ToString(); - frameTimer = new Timer(frameTick, null, 0, 42); + frameTimer = new DispatcherTimer(); + frameTimer.Interval = TimeSpan.FromMilliseconds(42); + frameTimer.Tick += frameTick; + frameTimer.Start(); } - private void frameTick(object state) + private void frameTick(object sender, EventArgs e) { + framePath = $"pack://application:,,,/Assets/MascottAnimation/{animationDirection}/{distractionStage}/frame{frameCounter}.png"; - Application.Current.Dispatcher.Invoke(() => - { - framePath = $"pack://application:,,,/Assets/MascottAnimation/{animationDirection}/{distractionStage}/frame{frameCounter}.png"; - - bool sucessfulySet = setFrame(); + bool successfullySet = setFrame(); - if (!sucessfulySet) - { - frameTimer.Dispose(); - ellipse1.Fill = Brushes.Red; - } else { - ellipse1.Fill = Brushes.Lime; - } + if (!successfullySet) + { + frameTimer.Stop(); + ellipse1.Fill = Brushes.Red; + } + else + { + ellipse1.Fill = Brushes.Lime; + } - frameCounter++; - }); + frameCounter++; } - private bool setFrame() //returns, if the frame was sucessfuly set + private bool setFrame() //returns, if the frame was successfully set { try { - - //MascottImage.Source = new BitmapImage(new Uri($"pack://application:,,,/Assets/MascottAnimation/Down/{animation}/frame{frame_}.png")); - MascottImage.Source = new BitmapImage(new Uri(framePath)); + MascottImage.Source = new BitmapImage(new Uri(framePath)); } - catch (Exception e) { + catch (Exception) + { return false; } @@ -145,7 +145,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer } private bool mascottVisible() - { + { String profile = "profile1"; String SettingsFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "settings.json"); @@ -189,7 +189,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer if (this.Left + this.Width > SystemParameters.PrimaryScreenWidth) this.Left = SystemParameters.PrimaryScreenWidth - this.Width; if (this.Top + this.Height > SystemParameters.PrimaryScreenHeight - 30) - this.Top = SystemParameters.PrimaryScreenHeight - this.Height -30; + this.Top = SystemParameters.PrimaryScreenHeight - this.Height - 30; } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/SessionStatistics.xaml.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/SessionStatistics.xaml.cs index 26c1e9b3172c44d7ef8fa1a689b5eac8a934e8b3..2150ccc530eddc722c4f78fca572e03467663910 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/SessionStatistics.xaml.cs +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/SessionStatistics.xaml.cs @@ -1,27 +1,15 @@ -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; +using InnoLabProjektDektopApp.Services; using LiveChartsCore; -using System.Collections.Generic; -using LiveChartsCore.SkiaSharpView.Extensions; using LiveChartsCore.SkiaSharpView; using LiveChartsCore.SkiaSharpView.Painting; using SkiaSharp; -using Newtonsoft.Json.Linq; -using InnoLabProjektDektopApp.Services; -using System.IO; using System.ComponentModel; +using System.IO; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; namespace InnoLabProjektDektopApp.Screens.Regulaer { @@ -35,13 +23,13 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer TimeSpan pausedTotal = new(); TimeSpan productiveTotal; int final_stage = 0; - int offset = 130; + readonly int offset = 130; - public IEnumerable<ISeries> Series { get; set; } + public IEnumerable<ISeries> Series { get; set; } = []; - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; - private BitmapImage _centerImageSource; + private BitmapImage _centerImageSource = new(); public BitmapImage CenterImageSource { get => _centerImageSource; @@ -57,7 +45,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } - public SessionStatistics(string sessionDataJsonPath = "C:\\Users\\Phil\\Source\\Repos\\CoFlow\\InnoLabProjektDektopApp\\InnoLabProjektDektopApp\\bin\\Debug\\net8.0-windows\\Assets\\sessionData\\2025\\3\\4\\4.json") + public SessionStatistics(string sessionDataJsonPath) { DataContext = this; InitializeComponent(); @@ -96,7 +84,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer TimeSpan cycleDuration = cycleEndTime - cycleStartTime; // Draw the entire cycle in green - Rectangle cycleSegment = new Rectangle + Rectangle cycleSegment = new() { Width = bar_width, Height = bar_height, @@ -108,7 +96,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer chartCanvas.Children.Add(cycleSegment); // Add cycle number text - TextBlock cycleText = new TextBlock + TextBlock cycleText = new() { Text = $"Cycle {cycle.Key}", Foreground = Brushes.Black, @@ -180,7 +168,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer Canvas.SetTop(breakSegment, (cycle.Key - 1) * 1.5 * bar_height + offset); chartCanvas.Children.Add(breakSegment); } - + } productiveTotal = DateTime.Parse(sessionData.SessionEndTime) - (DateTime.Parse(sessionData.CycleStartTimes[1]) + breakTotal + pausedTotal + distractedTotal); // Add legend @@ -226,12 +214,12 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer { // Create legend items var legendItems = new List<(string Text, Brush Color)> - { - ("Productive Work", Brushes.Green), - ("Distraction", Brushes.Red), - ("Break", Brushes.Blue), - ("Pause", Brushes.LightBlue) - }; + { + ("Productive Work", Brushes.Green), + ("Distraction", Brushes.Red), + ("Break", Brushes.Blue), + ("Pause", Brushes.LightBlue) + }; // Draw legend for (int i = 0; i < legendItems.Count; i++) @@ -239,7 +227,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer var legendItem = legendItems[i]; // Draw legend color box - Rectangle colorBox = new Rectangle + Rectangle colorBox = new() { Width = 20, Height = 20, @@ -250,7 +238,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer chartCanvas.Children.Add(colorBox); // Draw legend text - TextBlock legendText = new TextBlock + TextBlock legendText = new() { Text = legendItem.Text, Foreground = Brushes.Black, @@ -280,37 +268,37 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer string productiveTimeFormatted = FormatTimeSpan(productiveTime); // Update the series values - Series = new List<ISeries> - { - new PieSeries<double> { - Name = $"Distractions:", - Values = distractedTime.TotalSeconds > 1 ? [distractedTime.TotalMinutes] : new List<double>(), - MaxRadialColumnWidth = 50, - Fill = new SolidColorPaint(SKColors.Red), - ToolTipLabelFormatter = value => $"{distractedTimeFormatted} minutes" - }, - new PieSeries<double> { - Name = $"Breaks:", - Values = breakTime.TotalMinutes > 0 ? [breakTime.TotalMinutes] : new List<double>(), - MaxRadialColumnWidth = 50, - Fill = new SolidColorPaint(SKColors.Blue), - ToolTipLabelFormatter = value => $"{breakTimeFormatted} minutes" - }, - new PieSeries<double> { - Name = $"Manually paused:", - Values = pausedTime.TotalMinutes > 0 ? [pausedTime.TotalMinutes] : new List<double>(), - MaxRadialColumnWidth = 50, - Fill = new SolidColorPaint(SKColors.LightBlue), - ToolTipLabelFormatter = value => $"{pausedTimeFormatted} minutes" - }, - new PieSeries<double> { - Name = $"Productive:", - Values = productiveTime.TotalMinutes > 0 ? [productiveTime.TotalMinutes] : new List<double>(), - MaxRadialColumnWidth = 50, - Fill = new SolidColorPaint(SKColors.Green), - ToolTipLabelFormatter = value => $"{productiveTimeFormatted} minutes" - } - }; + Series = + [ + new PieSeries<double> { + Name = $"Distractions:", + Values = distractedTime.TotalSeconds > 1 ? [distractedTime.TotalMinutes] : new List<double>(), + MaxRadialColumnWidth = 50, + Fill = new SolidColorPaint(SKColors.Red), + ToolTipLabelFormatter = value => $"{distractedTimeFormatted} minutes" + }, + new PieSeries<double> { + Name = $"Breaks:", + Values = breakTime.TotalSeconds > 1 ? [breakTime.TotalMinutes] : new List<double>(), + MaxRadialColumnWidth = 50, + Fill = new SolidColorPaint(SKColors.Blue), + ToolTipLabelFormatter = value => $"{breakTimeFormatted} minutes" + }, + new PieSeries<double> { + Name = $"Manually paused:", + Values = pausedTime.TotalSeconds > 1 ? [pausedTime.TotalMinutes] : new List<double>(), + MaxRadialColumnWidth = 50, + Fill = new SolidColorPaint(SKColors.LightBlue), + ToolTipLabelFormatter = value => $"{pausedTimeFormatted} minutes" + }, + new PieSeries<double> { + Name = $"Productive:", + Values = productiveTime.TotalSeconds > 1 ? [productiveTime.TotalMinutes] : new List<double>(), + MaxRadialColumnWidth = 50, + Fill = new SolidColorPaint(SKColors.Green), + ToolTipLabelFormatter = value => $"{productiveTimeFormatted} minutes" + } + ]; CenterImageSource = new BitmapImage(new Uri($"pack://application:,,,/Assets/MascottAnimation/Up/{final_stage}/frame0.png")); @@ -320,7 +308,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer } // Helper method to format TimeSpan as "mm:ss" - private string FormatTimeSpan(TimeSpan timeSpan) + private static string FormatTimeSpan(TimeSpan timeSpan) { return $"{(int)timeSpan.TotalMinutes}:{timeSpan.Seconds:D2}"; } diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Services/ProcessMonitor.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Services/ProcessMonitor.cs index b6fc9b9a67fdb1e57503c0d9f27da1bec90e9b97..da09c2656611d96ac655cea4e4461fa9d1fc547f 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Services/ProcessMonitor.cs +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Services/ProcessMonitor.cs @@ -39,11 +39,13 @@ namespace InnoLabProjektDektopApp.Services public bool IsPause { get; private set; } private DateTime breakStartTime; public int currentCycle = 1; + public string lastSessionInfoFilePath; public event EventHandler MonitorCycleStarted; public event EventHandler MonitorPaused; public event EventHandler MonitorResumed; public event EventHandler MonitorBreakStarted; + public event EventHandler MonitorSessionFinished; public ProcessMonitor() { @@ -166,8 +168,12 @@ namespace InnoLabProjektDektopApp.Services public string FinishSession() { StopMonitoring(); - EndBreak(); - + if (IsBreak) + { + breakInfoList.Add(new BreakInfo(breakStartTime, DateTime.Now, IsBreak, currentCycle)); + IsBreak = false; + } + // Create a session info object var sessionInfo = new { @@ -190,6 +196,10 @@ namespace InnoLabProjektDektopApp.Services var sessionInfoJson = JsonConvert.SerializeObject(sessionInfo, Formatting.Indented); File.WriteAllText(sessionInfoFilePath, sessionInfoJson); + // Raise event + lastSessionInfoFilePath = sessionInfoFilePath; + MonitorSessionFinished?.Invoke(this, EventArgs.Empty); + // Reset the processInfoList and breakInfoList processInfoList.Clear(); breakInfoList.Clear(); @@ -210,7 +220,7 @@ namespace InnoLabProjektDektopApp.Services if (cycleStartTimeList.Count == 0) return 4; TimeSpan totalDistractionTime = CalculateTotalDistractionTime(); TimeSpan totalBreakTime = breakInfoList.Aggregate(TimeSpan.Zero, (sum, interval) => sum + (interval.EndTime - interval.StartTime)); - Debug.WriteLine("Total distraction time: {0}", totalDistractionTime); + Debug.WriteLine($"Total distraction time: {totalDistractionTime}"); // Adds a dummy value to the distractedMinutes and totalMinutes so the stage starts in the middle double dummyTimeInMinutes = 8; @@ -421,7 +431,6 @@ namespace InnoLabProjektDektopApp.Services List<(DateTime Start, DateTime End)> mergedDistractionIntervals, List<(DateTime Start, DateTime End)> breakIntervals) { - Debug.WriteLine(mergedDistractionIntervals.Aggregate(TimeSpan.Zero, (sum, interval) => sum + (interval.End - interval.Start)).ToString()); foreach (var breakInfo in breakIntervals) { mergedDistractionIntervals = [.. mergedDistractionIntervals.SelectMany(interval => @@ -457,7 +466,6 @@ namespace InnoLabProjektDektopApp.Services } })]; } - Debug.WriteLine(mergedDistractionIntervals.Aggregate(TimeSpan.Zero, (sum, interval) => sum + (interval.End - interval.Start)).ToString()); return mergedDistractionIntervals.Aggregate(TimeSpan.Zero, (sum, interval) => sum + (interval.End - interval.Start)); } diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Utils/NotifyIconManager.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Utils/NotifyIconManager.cs index 3a06ec8cf3ebc85a000f03a69646803c4a76fcab..5e2585d295847c8eb2e8975e51956169c11e8ac1 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Utils/NotifyIconManager.cs +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Utils/NotifyIconManager.cs @@ -1,15 +1,12 @@ -using InnoLabProjektDektopApp.Services; -using System; -using Drawing = System.Drawing; +using InnoLabProjektDektopApp.Screens.Regulaer; +using InnoLabProjektDektopApp.Services; +using System.IO; +using System.Text.Json; using System.Windows; -using System.Windows.Controls; +using System.Windows.Navigation; using System.Windows.Threading; +using Drawing = System.Drawing; using Forms = System.Windows.Forms; -using System.Windows.Media; -using System.Windows.Navigation; -using System.IO; -using System.Text.Json; -using InnoLabProjektDektopApp.Screens.Regulaer; namespace InnoLabProjektDektopApp.Utils { @@ -106,9 +103,6 @@ namespace InnoLabProjektDektopApp.Utils var jsonpath = _processMonitor.FinishSession(); StopCountdown(); RerenderContextMenu(); - Window mainWindow = Application.Current.MainWindow; - NavigationService mainNavigation = ((System.Windows.Navigation.NavigationWindow)mainWindow).NavigationService; - mainNavigation.Navigate(new SessionStatistics(jsonpath)); }); } else @@ -204,24 +198,18 @@ namespace InnoLabProjektDektopApp.Utils { if (_processMonitor.IsBreak) { - _processMonitor.EndBreak(); RerenderContextMenu(); } else { if (_processMonitor.currentCycle < _settings.cycles) { - _processMonitor.StartBreak(); RerenderContextMenu(); } else { - var jsonpath = _processMonitor.FinishSession(); StopCountdown(); RerenderContextMenu(); - Window mainWindow = Application.Current.MainWindow; - NavigationService mainNavigation = ((System.Windows.Navigation.NavigationWindow)mainWindow).NavigationService; - mainNavigation.Navigate(new SessionStatistics(jsonpath)); } } }