From e164b77a106f3c2d8d262898a75f3034b6718ff4 Mon Sep 17 00:00:00 2001 From: DemonKingSwarn Date: Thu, 21 Aug 2025 12:51:51 +0530 Subject: chore: weekly data added --- GEMINI.md | 71 +++++++++++++++++++++++++++++++ Program.cs | 7 ++- README.md | 7 ++- src/WeeklyReport.cs | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 GEMINI.md create mode 100644 src/WeeklyReport.cs diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..d7ea87e --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,71 @@ +# hypr-wellbeing + +## Project Overview + +`hypr-wellbeing` is a command-line tool for tracking application usage time on Linux, with a specific focus on the Hyprland and niri window managers. It helps users monitor their screen time and promote digital wellbeing by providing detailed statistics on application usage. + +## Features + +- **Time Tracking:** Monitors the active window and logs the time spent on each application. +- **Daily Reports:** Displays a summary of daily application usage, including total screen time and a breakdown of time spent on each application. +- **Data Storage:** Stores usage data in CSV files in the `~/.cache/hyprwatch/daily_data/` directory. +- **Cross-Desktop Support (Limited):** While primarily designed for Hyprland and niri, it may work on other Wayland-based desktops. +- **Analysis:** Includes logic for generating weekly reports and sorting data. + +## Technology Stack + +- **Language:** C# +- **Framework:** .NET 8 +- **Platform:** Linux +- **Compilation:** Published as a self-contained AOT (Ahead-Of-Time) compiled application. + +## File Structure + +``` +/home/swarn/dox/code/hypr-wellbeing/ +├───.gitignore +├───hypr-wellbeing.csproj +├───LICENSE +├───Program.cs +├───README.md +├───.assets/ +│ └───show.png +├───.git/... +├───bin/ +│ ├───Debug/... +│ └───Release/... +├───obj/ +│ ├───Debug/... +│ └───Release/... +└───src/ + ├───Analysis.cs + ├───GetWindows.cs + ├───GetWindowsv2.cs + ├───TimeOperations.cs + └───WatchLog.cs +``` + +## Usage + +### Monitor Mode + +To run the application in the background and monitor application usage, use the following command: + +```sh +hypr-wellbeing -d &> /dev/null & +``` + +### Show Stats + +To display the statistics for the current day, use the following command: + +```sh +hypr-wellbeing --show +``` + +## Future Improvements + +The following features are planned for future releases: + +- Weekly view of application usage +- Monthly view of application usage diff --git a/Program.cs b/Program.cs index d57fe2c..8e4afd1 100644 --- a/Program.cs +++ b/Program.cs @@ -1,6 +1,7 @@ using System.IO; using System.Runtime.InteropServices; using hyprwatch.Logger; +using hyprwatch.Report.Weekly; class Program { @@ -11,7 +12,7 @@ class Program string dailyDataDirectory = Path.Combine(hyprwatchDirectory, "daily_data"); Directory.CreateDirectory(dailyDataDirectory); - if (args.Length == 0 || args[0] != "-d" && args[0] != "--show") + if (args.Length == 0 || args[0] != "-d" && args[0] != "--show" && args[0] != "--weekly") { Console.WriteLine("Usage: -d || --show"); return; @@ -75,6 +76,10 @@ class Program } } + if(args[0] == "--weekly") + { + WeeklyReport.DisplayWeeklyReport(); + } } } diff --git a/README.md b/README.md index a202332..31ef736 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,14 @@ hypr-wellbeing -d &> /dev/null & hypr-wellbeing --show ``` +### Show Weekly Stats + +```sh +hypr-wellbeing --weekly +``` + ## To-Do -- [] Weekly view - [] Monthly view ## Special Thanks diff --git a/src/WeeklyReport.cs b/src/WeeklyReport.cs new file mode 100644 index 0000000..9f81510 --- /dev/null +++ b/src/WeeklyReport.cs @@ -0,0 +1,120 @@ +using System; +using System.IO; +using System.Linq; +using System.Globalization; +using System.Collections.Generic; +using hyprwatch.Time; + +namespace hyprwatch.Report.Weekly +{ + public class WeeklyReport + { + private static string FormatTime(string time) + { + var parts = time.Split(':'); + if (parts.Length == 3) + { + int hr = int.Parse(parts[0]); + int mn = int.Parse(parts[1]); + int sec = int.Parse(parts[2]); + return $"{hr:D2}:{mn:D2}:{sec:D2}"; + } + return "00:00:00"; // Should not happen with valid data + } + + private static int ConvertToSeconds(string time) + { + var parts = time.Split(':'); + if (parts.Length == 3) + { + int hr = int.Parse(parts[0]); + int mn = int.Parse(parts[1]); + int sec = int.Parse(parts[2]); + return hr * 3600 + mn * 60 + sec; + } + return 0; + } + + private static string ConvertFromSeconds(int totalSeconds) + { + int hr = totalSeconds / 3600; + totalSeconds %= 3600; + int mn = totalSeconds / 60; + int sec = totalSeconds % 60; + return $"{hr:D2}:{mn:D2}:{sec:D2}"; + } + + public static Dictionary GetWeeklyReport() + { + var allData = new Dictionary(); + string path = Environment.GetEnvironmentVariable("HOME") + "/.cache/hyprwatch/daily_data/"; + var files = Directory.GetFiles(path, "*.csv"); + + DateTime today = DateTime.Today; + int daysUntilMonday = (int)today.DayOfWeek - (int)DayOfWeek.Monday; + if (daysUntilMonday < 0) daysUntilMonday += 7; + DateTime startOfWeek = today.AddDays(-daysUntilMonday); + + foreach (var file in files) + { + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); + if (DateTime.TryParse(fileNameWithoutExtension, out DateTime fileDate)) + { + if (fileDate >= startOfWeek && fileDate < startOfWeek.AddDays(7)) + { + var report = new Dictionary(); + var rawData = File.ReadAllLines(file); + foreach (var line in rawData) + { + var splitData = line.Split('\t'); + if (splitData.Length >= 2) + { + report[splitData[1].Trim()] = splitData[0]; + } + } + + foreach (var kvp in report) + { + if (!allData.ContainsKey(kvp.Key)) + { + allData[kvp.Key] = 0; + } + allData[kvp.Key] += ConvertToSeconds(FormatTime(kvp.Value)); + } + } + } + } + + return allData; + } + + public static void DisplayWeeklyReport() + { + string green = "\x1b[0;32m"; + string yellow = "\x1b[1;33m"; + string red = "\x1b[0;31m"; + string blue = "\x1b[0;34m"; + string reset = "\x1b[0m"; + + var weeklyData = GetWeeklyReport(); + + var sortedData = from entry in weeklyData orderby entry.Value descending select entry; + + int totalSeconds = weeklyData.Values.Sum(); + string totalTime = ConvertFromSeconds(totalSeconds); + + Console.WriteLine(" "); + Console.WriteLine($"This Week's Screen Usage\t{totalTime}"); + Console.WriteLine($"{red}{new string('-', 60)}{reset}"); + Console.WriteLine($"{yellow}{"App".PadRight(30)}{"Time".PadLeft(30)}{reset}"); + Console.WriteLine($"{red}{new string('-', 60)}{reset}"); + + foreach (var entry in sortedData) + { + string key = entry.Key.Length > 30 ? entry.Key.Substring(0, 27) + "..." : entry.Key; + string time = ConvertFromSeconds(entry.Value); + Console.WriteLine($"{blue}{key.PadRight(30)}{reset}{green}{time.PadLeft(30)}{reset}"); + } + } + } +} -- cgit v1.1