From 1e839c8caabbed6b8b0f27b1d0835ce4f9a61f73 Mon Sep 17 00:00:00 2001 From: muellerp <Philipp1.Mueller@Student.Reutlingen-University.de> Date: Wed, 5 Mar 2025 19:36:14 +0100 Subject: [PATCH 1/2] refactoring --- .../Screens/Regulaer/02Session.xaml | 2 +- .../Screens/Regulaer/02Session.xaml.cs | 69 +++++----- .../Screens/Regulaer/Mascott.xaml.cs | 5 +- .../Regulaer/SessionStatistics.xaml.cs | 122 ++++++++---------- 4 files changed, 95 insertions(+), 103 deletions(-) diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml index 2cd4a7a..8e985c3 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" /> diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml.cs index 011d391..7c69876 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml.cs +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml.cs @@ -65,7 +65,7 @@ namespace InnoLabProjektDektopApp this.sessions = cycles; - timer = new Timer(timertick, null, 0, 1000); //A background timer calls timertick every second + timer = new Timer(Timertick, null, 0, 1000); //A background timer calls timertick every second //StageText.Text = ProcessMonitor.tmpStage.ToString(); @@ -74,15 +74,15 @@ namespace InnoLabProjektDektopApp processMonitor.StartMonitoring(); CreateCycleIndicators(); // Kreise erstellen - updateTexts(); + UpdateTexts(); } - private void timertick(object state) + private void Timertick(object state) { Dispatcher.Invoke(() => { seconds += step; // Reduziere Zeit, wenn der Timer läuft - updateTexts(); // Aktualisiere die UI + UpdateTexts(); // Aktualisiere die UI // Fortschrittsanzeige nur während der Fokusperiode aktualisieren @@ -91,7 +91,7 @@ namespace InnoLabProjektDektopApp if (seconds <= 0) // Wenn die Zeit abgelaufen ist { - stopTimer(); // Timer stoppen + StopTimer(); // Timer stoppen if (currentSession >= sessions) // Wenn alle Zyklen abgeschlossen sind { @@ -117,7 +117,7 @@ namespace InnoLabProjektDektopApp } - startTimer(); // Starte den Timer für die nächste Periode + StartTimer(); // Starte den Timer für die nächste Periode } else { if(isBreakPeriod) @@ -129,7 +129,7 @@ namespace InnoLabProjektDektopApp } - public void startTimer() + public void StartTimer() { if (seconds <= 0) return; // Prevent starting if time is zero step = -1; // Set step to countdown @@ -137,22 +137,22 @@ namespace InnoLabProjektDektopApp processMonitor.EndPause(); } - public void stopTimer() + public void StopTimer() { step = 0; // Stop counting down PlayPauseButton.Content = "Start"; // Update button text processMonitor.StartPause(); } - 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; @@ -181,12 +181,12 @@ namespace InnoLabProjektDektopApp } else { - stopTimer(); + StopTimer(); } } else { - startTimer(); + StartTimer(); } } @@ -228,7 +228,7 @@ namespace InnoLabProjektDektopApp { 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) @@ -258,10 +258,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 +271,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), @@ -313,7 +313,7 @@ namespace InnoLabProjektDektopApp reasonWindow.Show(); } - public DateTime timeLeft() + public DateTime TimeLeft() { return DateTime.Now.AddSeconds(maxTime - seconds); } @@ -385,18 +385,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 c7269fc..092feca 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/Mascott.xaml.cs +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/Mascott.xaml.cs @@ -64,7 +64,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer Application.Current.Dispatcher.Invoke(() => { - DateTime timeLeft = Overview.getSessionInstance().timeLeft(); + DateTime timeLeft = Overview.getSessionInstance().TimeLeft(); int processMonitorStage = processMonitor.CalculateCurrentDistractionStage(DateTime.Now); @@ -137,7 +137,8 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer //MascottImage.Source = new BitmapImage(new Uri($"pack://application:,,,/Assets/MascottAnimation/Down/{animation}/frame{frame_}.png")); MascottImage.Source = new BitmapImage(new Uri(framePath)); } - catch (Exception e) { + catch (Exception) + { return false; } diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/SessionStatistics.xaml.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/SessionStatistics.xaml.cs index 26c1e9b..2150ccc 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}"; } -- GitLab From a076c4ff865d6983828633dd94a60f0f8690f4e7 Mon Sep 17 00:00:00 2001 From: muellerp <Philipp1.Mueller@Student.Reutlingen-University.de> Date: Thu, 6 Mar 2025 00:34:03 +0100 Subject: [PATCH 2/2] more refactoring and potential mascot animation fix --- .../Screens/Regulaer/02Session.xaml | 4 +- .../Screens/Regulaer/02Session.xaml.cs | 173 ++++++++---------- .../Screens/Regulaer/Mascott.xaml.cs | 131 +++++++------ .../Services/ProcessMonitor.cs | 18 +- .../Utils/NotifyIconManager.cs | 24 +-- 5 files changed, 166 insertions(+), 184 deletions(-) diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml index 8e985c3..fccccfd 100644 --- a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml +++ b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/02Session.xaml @@ -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 7c69876..c5323c2 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,10 +54,10 @@ 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(); @@ -75,73 +65,80 @@ namespace InnoLabProjektDektopApp processMonitor.StartMonitoring(); CreateCycleIndicators(); // Kreise erstellen 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) @@ -151,7 +148,6 @@ namespace InnoLabProjektDektopApp 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,7 +213,7 @@ 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 @@ -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, @@ -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 @@ -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); } diff --git a/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/Mascott.xaml.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Screens/Regulaer/Mascott.xaml.cs index 092feca..0b2058e 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,37 +105,36 @@ 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 successfullySet = setFrame(); - bool sucessfulySet = 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) { @@ -146,7 +145,7 @@ namespace InnoLabProjektDektopApp.Screens.Regulaer } private bool mascottVisible() - { + { String profile = "profile1"; String SettingsFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "settings.json"); @@ -190,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/Services/ProcessMonitor.cs b/InnoLabProjektDektopApp/InnoLabProjektDektopApp/Services/ProcessMonitor.cs index b6fc9b9..da09c26 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 3a06ec8..5e2585d 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)); } } } -- GitLab