timet 1.4.1 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e9f44f4ee2f1ae5aab382b308364ffeaffa5e09bf21d1578e8f5267ff715f0f
4
- data.tar.gz: 13becd17288c93925e91a3c49dcdc7f4f7e7afe41d1469a10a7f931930b2d26d
3
+ metadata.gz: 9c57d8e7c61f25526dda2e7a5d1208814cadbc93192b7c60c342399c83f0b545
4
+ data.tar.gz: 625f4ba71e547e2ebb483d93f1de3812a8b075cacc7afaff7c80554267e5bcc1
5
5
  SHA512:
6
- metadata.gz: 27fca2e9adef3a4695a497b21106a400e7448caff946efccba034f9bbfcb29962822a632f17e3ab51856de764826257f5d6b33458d69fd9b56eebeb91946e5b8
7
- data.tar.gz: df46d99862c3366f63f4ad007fbece638f88ca997fa2085070a78c065306b23888ecbbd5b610ba99582898395201dd00a1a8871de0ef8983d24c9ec3edefe32b
6
+ metadata.gz: 99b2d1783c14024620865d826d11e16c42146ce220a50ae066cf762231129c42d683d88e4bb50086a5743cc923cdacd1d88f6fd4a4af4f5b5934017bfbb7b476
7
+ data.tar.gz: 7d3cb54c375f6fe2b86f0ffedb290d31c5d2348ec877a0848fc9c20d47c90422db6573a5ab0265ef4c0d8f6f89465dda7916f2f6dae59c2296511761b2f63705
data/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.4.2] - 2024-11-01
4
+
5
+ **Improvements:**
6
+
7
+ - Refactored the `table` method in `lib/timet/table.rb` to simplify its return value and remove unnecessary complexity.
8
+ - Updated the `process_time_entries` and `process_time_block_item` methods to streamline the processing of time entries and time block items.
9
+ - Integrated the `TimeStatistics` class into the `TagDistribution` module to calculate and display detailed statistics for each tag.
10
+ - Modified the `tag_distribution` method to use the `TimeStatistics` class for generating tag distribution information.
11
+ - Updated the `display` method in `lib/timet/time_report.rb` to use the refactored methods and integrate the new tag distribution logic.
12
+ - Added the `descriptive_statistics` gem to the Gemfile to support statistical calculations.
13
+ - Created a new `TimeStatistics` class in `lib/timet/time_statistics.rb` to analyze and summarize time duration data associated with various tags.
14
+ - Implemented methods in `TimeStatistics` to calculate total duration by tag, sorted duration by tag, average duration by tag, standard deviation by tag, and additional descriptive statistics by tag.
15
+ - Updated Gemfile.lock to reflect the new dependency.
16
+ - Update README.md
17
+
18
+ **Tasks:**
19
+
20
+ - Refactor time tracking report methods and integrate `TimeStatistics`.
21
+ - Add `descriptive_statistics` gem and create `TimeStatistics` class.
22
+ - Fix typo in `README.md`.
23
+
24
+ **Bug fixes:**
25
+
26
+ - Fixed a typo in `README.md`.
27
+
28
+ ## [1.4.1] - 2024-10-31
29
+
30
+ **Improvements:**
31
+
32
+ - Refactor `resume` method to accept an optional `id` parameter for resuming a specific tracking item.
33
+ - Renamed `last_item_status` method to `item_status` in the `Database` class for better clarity and flexibility.
34
+ - Updated `Application` class methods (`start`, `stop`, `resume`, `cancel`) to use the new `item_status` method.
35
+ - Introduced `determine_status` method within the `Database` class to encapsulate status determination logic.
36
+ - Updated documentation and test cases to reflect the changes and ensure consistent status handling.
37
+ - Bumped version to reflect the changes.
38
+ - Updated README.md to include new features and improvements.
39
+
40
+ **Tasks:**
41
+
42
+ - Refactor `resume` method.
43
+ - Bump version.
44
+ - Update README.md.
45
+ - Refactor `Database` class for improved status determination and encapsulation.
46
+
3
47
  ## [1.4.0] - 2024-10-29
4
48
 
5
49
  **Improvements:**
data/README.md CHANGED
@@ -7,23 +7,23 @@
7
7
 
8
8
  ![Timet](timet.webp)
9
9
 
10
- Timet refers to a command-line tool designed to track your activities by recording the time spent on each task, allowing you to monitor your work hours and productivity directly from your terminal without needing a graphical interface; essentially, it's a way to log your time spent on different projects or tasks using simple text commands
10
+ [Timet](https://rubygems.org/gems/timet) is a command-line tool designed to track your activities by recording the time spent on each task. This allows you to monitor your work hours and productivity directly from your terminal without needing a graphical interface. Essentially, it's a way to log your time spent on different projects or tasks using simple text commands.
11
11
 
12
12
  🔑 **Key Features:**
13
13
 
14
- - **Local Data Storage:** Timet utilizes SQLite to store your time tracking data locally, ensuring privacy and security.
14
+ - **Local Data Storage:** Timet uses SQLite to store your time tracking data locally, ensuring privacy and security.
15
15
  - **Lightweight and Fast:** Its efficient design and local data storage make Timet a speedy and responsive tool.
16
16
  - **Structured Data:** SQLite ensures your data is organized and easily accessible.
17
17
  - **Scalability:** Timet can handle growing time tracking needs.
18
18
  - **Data Integrity:** SQLite maintains the accuracy and consistency of your data.
19
19
  - **Querying and Reporting:** Generate detailed reports for specific periods.
20
20
  - **CSV Export:** Easily export your time tracking data to CSV format for further analysis or sharing.
21
- - **Pomodoro Integration:** The pomodoro option in the start command enhances time tracking by integrating the Pomodoro Technique.
22
- - **Block Time Plot:** Visualizes the distribution of tracked time across a specified range of dates, with bars in each column representing the amount of time tracked during that specific hour. The plot includes a header showing the hours and a row for each date, displaying the time blocks for each hour.
21
+ - **Pomodoro Integration:** The `pomodoro` option in the `start` command enhances time tracking by integrating the Pomodoro Technique.
22
+ - **Block Time Plot:** Visualizes the distribution of tracked time across a specified range of dates. Each column represents the amount of time tracked during a specific hour, with a header showing the hours and a row for each date displaying the time blocks for each hour.
23
23
  - **Tag Distribution Plot:** Illustrates the proportion of total tracked time allocated to each tag, showing the relative contribution of each tag to the overall time tracked.
24
+ - **Detailed Statistics:** Displays detailed statistics for each tag, including total duration, average duration, and standard deviation.
24
25
 
25
-
26
- Examples:
26
+ **Examples:**
27
27
 
28
28
  ![Timet1 demo](timet1.gif)
29
29
 
@@ -32,10 +32,9 @@ Examples:
32
32
  - Ruby version: >= 3.0.0
33
33
  - sqlite3: > 1.7
34
34
 
35
- Old versions of Ruby and Sqlite:
35
+ For older versions of Ruby and Sqlite:
36
36
 
37
37
  - [Ruby >= 2.7](https://github.com/frankvielma/timet/tree/ruby-2.7.0)
38
-
39
38
  - [Ruby >= 2.4](https://github.com/frankvielma/timet/tree/ruby-2.4.0)
40
39
 
41
40
  ## 💾 Installation
@@ -54,7 +53,8 @@ gem install timet
54
53
  - `tt`: An alias for the `timet` command, providing a shorter alternative.
55
54
 
56
55
  ---
57
- - **timet start [tag] --notes="" --pomodoro=[minutes]**: Starts tracking time for a task labeled with the provided [tag], notes and "pomodoro time" in minutes (optional). Example:
56
+
57
+ - **`timet start [tag] --notes="" --pomodoro=[minutes]`:** Starts tracking time for a task labeled with the provided [tag], notes, and "pomodoro time" in minutes (optional). Example:
58
58
 
59
59
  ```bash
60
60
  timet start task1 --notes="Meeting with client" --pomodoro=25
@@ -81,15 +81,15 @@ gem install timet
81
81
 
82
82
  The `pomodoro` option in the `start` command enhances time tracking by integrating the Pomodoro Technique. Users can specify a Pomodoro session length in minutes, like `pomodoro=25`, to start a 25-minute work interval. The app automatically tracks time and notifies users when the interval ends, helping maintain focus.
83
83
 
84
- **Benefits**
84
+ **Benefits:**
85
85
 
86
- - **Flexibility**: Supports various productivity strategies.
87
- - **Focus**: Encourages disciplined work practices.
88
- - **Productivity**: Helps achieve higher productivity and better time management.
86
+ - **Flexibility:** Supports various productivity strategies.
87
+ - **Focus:** Encourages disciplined work practices.
88
+ - **Productivity:** Helps achieve higher productivity and better time management.
89
89
 
90
90
  ---
91
91
 
92
- - **timet stop**: Stops tracking the current task, records the elapsed time, and displays the total time spent on all tasks.
92
+ - **`timet stop`:** Stops tracking the current task, records the elapsed time, and displays the total time spent on all tasks.
93
93
 
94
94
  ```bash
95
95
  timet stop
@@ -105,8 +105,14 @@ gem install timet
105
105
  | Total: | 01:00:00 | |
106
106
  +-------+------------+--------+----------+----------+----------+--------------------------+
107
107
  ```
108
+
108
109
  ---
109
- - **timet resume [id]**: This command allows users to quickly resume tracking a task that was previously in progress. If an id is provided, it resumes the tracking session for the specified task. If no id is provided, it resumes the last completed task.
110
+
111
+ - **`timet resume [id]`:** This command allows users to quickly resume tracking a task that was previously in progress. If an ID is provided, it resumes the tracking session for the specified task. If no ID is provided, it resumes the last completed task.
112
+
113
+ ```bash
114
+ timet resume 1
115
+ ```
110
116
 
111
117
  ```
112
118
  Tracked time report [today]:
@@ -119,10 +125,12 @@ gem install timet
119
125
  | Total: | 01:00:00 | |
120
126
  +-------+------------+--------+----------+----------+----------+--------------------------+
121
127
  ```
128
+
122
129
  ---
123
- - **timet edit**: It allows users to update a task's notes, tag, start, or end fields. Users can either interactively select the field and provide a new value or specify them directly in the command.
124
130
 
125
- - **Interactive Mode:**
131
+ - **`timet edit`:** Allows users to update a task's notes, tag, start, or end fields. Users can either interactively select the field and provide a new value or specify them directly in the command.
132
+
133
+ **Interactive Mode:**
126
134
 
127
135
  ```bash
128
136
  timet edit 1
@@ -145,7 +153,7 @@ gem install timet
145
153
  End
146
154
  ```
147
155
 
148
- - **Direct Specification Mode:**
156
+ **Direct Specification Mode:**
149
157
 
150
158
  ```bash
151
159
  timet e 1 notes "New Meeting Notes"
@@ -163,24 +171,23 @@ gem install timet
163
171
  +-------+------------+--------+----------+----------+----------+--------------------------+
164
172
  ```
165
173
 
166
- ## 📋 Command Reference
174
+ ## 📋 Command Reference
167
175
 
168
- | Command | Description | Example Usage |
169
- | ----------------------------------- | --------------------------------------------------------------------------- | --------------------------------- |
170
- | `timet start [tag] --notes='' --pomodoro=[time]` | Start tracking time for a task labeled [tag] and notes (optional). | `timet start Task "My notes" 25` |
171
- | `timet stop` | Stop tracking time. | `timet start Task "My notes"` |
172
- | `timet summary today (t)` | Display a report of tracked time for today. | `timet su t` or `timet su` |
173
- | `timet summary yesterday (y)` | Display a report of tracked time for yesterday. | `timet su y` |
174
- | `timet summary week (w)` | Display a report of tracked time for the week. | `timet su w` |
175
- | `timet summary month (m)` | Resume tracking the last month. | `timet su m` |
176
- | `timet su t --csv=[filename]` | Display a report of tracked time for today and export it to `filename.csv`. | `timet su t --csv=file.csv` |
177
- | `timet summary resume (r)` | Resume tracking the last task. | `timet su r` |
178
- | `timet delete [id]` | Delete a task by its ID. | `timet d [id]` |
179
- | `timet cancel` | Cancel active time tracking. | `timet c` |
180
- | `timet edit [id]` | Update a task's notes, tag, start or end fields. | `timet e [id]` |
181
- | `timet su [date]` | Display a report of tracked time for a specific date. | `timet su 2024-01-03` |
182
- | `timet su [start_date]..[end_date]` | Display a report of tracked time for a date range. | `timet su 2024-01-02..2024-01-03` |
183
- | `timet resume [id]` | Resume tracking a task by ID or the last completed task. | `timet resume [id]` |
176
+ | Command | Description | Example Usage |
177
+ | -------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------- |
178
+ | `timet start [tag] --notes='' --pomodoro=[time]` | Start tracking time for a task labeled [tag] and notes (optional). | `timet start Task "My notes" 25` |
179
+ | `timet stop` | Stop tracking time. | `timet stop` |
180
+ | `timet summary today (t)` | Display a report of tracked time for today. | `timet su t` or `timet su` |
181
+ | `timet summary yesterday (y)` | Display a report of tracked time for yesterday. | `timet su y` |
182
+ | `timet summary week (w)` | Display a report of tracked time for the week. | `timet su w` |
183
+ | `timet summary month (m)` | Display a report of tracked time for the month. | `timet su m` |
184
+ | `timet su t --csv=[filename]` | Display a report of tracked time for today and export it to `filename.csv`. | `timet su t --csv=file.csv` |
185
+ | `timet delete [id]` | Delete a task by its ID. | `timet d [id]` |
186
+ | `timet cancel` | Cancel active time tracking. | `timet c` |
187
+ | `timet edit [id]` | Update a task's notes, tag, start, or end fields. | `timet e [id]` |
188
+ | `timet su [date]` | Display a report of tracked time for a specific date. | `timet su 2024-01-03` |
189
+ | `timet su [start_date]..[end_date]` | Display a report of tracked time for a date range. | `timet su 2024-01-02..2024-01-03` |
190
+ | `timet resume (r) [id]` | Resume tracking a task by ID or the last completed task. | `timet resume [id]` |
184
191
 
185
192
  ### Date Range in Summary
186
193
 
@@ -188,20 +195,21 @@ The `timet summary` command now supports specifying a date range for generating
188
195
 
189
196
  #### Examples:
190
197
 
191
- - **Single Date**: Display a report for a specific date.
198
+ - **Single Date:** Display a report for a specific date.
192
199
 
193
200
  ```sh
194
201
  timet su 2024-01-03
195
202
  ```
196
203
 
197
- - **Date Range**: Display a report for a date range.
204
+ - **Date Range:** Display a report for a date range.
205
+
198
206
  ```sh
199
207
  timet su 2024-01-02..2024-01-03
200
208
  ```
201
209
 
202
210
  ## Data
203
211
 
204
- Timet's data is stored in ~/.timet.db
212
+ Timet's data is stored in `~/.timet.db`.
205
213
 
206
214
  ## Development
207
215
 
@@ -211,13 +219,14 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
211
219
 
212
220
  ## Contributing
213
221
 
214
- Bug reports and pull requests are welcome on GitHub at https://github.com/frankvielma/timet. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/frankvielma/timet/blob/master/CODE_OF_CONDUCT.md).
222
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/frankvielma/timet](https://github.com/frankvielma/timet). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/frankvielma/timet/blob/master/CODE_OF_CONDUCT.md).
215
223
 
216
224
  ## Buy Me A Coffee! ☕
217
225
 
218
226
  Many people have contacted me asking how to contribute. Any contribution, from a virtual coffee to a kind word, is greatly appreciated and helps me continue my work. Please only donate if you're able, as there are no refunds. Your support is entirely voluntary, and I thank you for your consideration.
219
227
 
220
228
  **Bitcoin Address:**
229
+
221
230
  ```sh
222
231
  bc1qkg9me2jsuhpzu2hp9kkpxagwtf9ewnyfl4kszl
223
232
  ```
@@ -232,4 +241,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
232
241
 
233
242
  ## Code of Conduct
234
243
 
235
- Everyone interacting in the Timet project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/frankvielma/timet/blob/master/CODE_OF_CONDUCT.md).
244
+ Everyone interacting in the Timet project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [code of conduct](https://github.com/frankvielma/timet/blob/master/CODE_OF_CONDUCT.md).
data/lib/timet/table.rb CHANGED
@@ -9,12 +9,12 @@ module Timet
9
9
  # @example
10
10
  # table
11
11
  #
12
- # @return [Array<(String, Hash)>] An array containing the time block string and a hash of durations by tag.
12
+ # @return [String] The time block string.
13
13
  #
14
14
  # @note
15
15
  # - The method relies on the `header`, `process_time_entries`, `separator`, and `total` methods.
16
16
  # - The `header` method is responsible for printing the table header.
17
- # - The `process_time_entries` method processes the time entries and returns the time block and duration by tag.
17
+ # - The `process_time_entries` method processes the time entries and returns the time block.
18
18
  # - The `separator` method returns a string representing the separator line.
19
19
  # - The `total` method prints the total duration.
20
20
  #
@@ -24,10 +24,10 @@ module Timet
24
24
  # @see #total
25
25
  def table
26
26
  header
27
- time_block, duration_by_tag = process_time_entries
27
+ time_block = process_time_entries
28
28
  puts separator
29
29
  total
30
- [time_block, duration_by_tag]
30
+ time_block
31
31
  end
32
32
 
33
33
  # Formats the header of the time tracking report table.
@@ -62,73 +62,53 @@ module Timet
62
62
  '+-------+------------+--------+----------+----------+----------+--------------------+'
63
63
  end
64
64
 
65
- # Processes each time entry in the `items` array and updates the time block and duration by tag.
65
+ # Processes time entries and generates a time block structure.
66
66
  #
67
- # @return [Array<(Hash, Hash)>] An array containing the updated time block and duration by tag.
68
- #
69
- # @example
70
- # items = [
71
- # [start_time1, end_time1, tag1],
72
- # [start_time2, end_time2, tag2]
73
- # ]
74
- # process_time_entries
75
- # #=> [{ '2024-10-21' => { 8 => [duration1, tag1], 9 => [duration2, tag2] } },
76
- # { tag1 => total_duration1, tag2 => total_duration2 }]
67
+ # @return [Hash] A nested hash representing the time block structure.
77
68
  #
78
69
  # @note
79
- # - The method relies on the `items` instance variable, which should be an array of arrays.
80
- # - Each sub-array in `items` is expected to contain a start time, end time, and a tag.
81
- # - The `display_time_entry` method is used to display each time entry.
82
- # - The `process_time_block_item` method processes each time entry and updates the time block and duration by tag.
70
+ # - The method iterates over each item in the `items` array.
71
+ # - For each item, it calls `display_time_entry` to display the time entry.
72
+ # - It then processes the time block item using `process_time_block_item`.
73
+ # - The `TimeHelper.extract_date` method is used to extract the date from the items.
83
74
  #
84
- # @see #items
85
75
  # @see #display_time_entry
86
76
  # @see #process_time_block_item
77
+ # @see TimeHelper#extract_date
87
78
  def process_time_entries
88
- duration_by_tag = Hash.new(0)
89
79
  time_block = Hash.new { |hash, key| hash[key] = {} }
90
80
 
91
81
  items.each_with_index do |item, idx|
92
82
  display_time_entry(item, TimeHelper.extract_date(items, idx))
93
- time_block, duration_by_tag = process_time_block_item(item, time_block, duration_by_tag)
83
+ time_block = process_time_block_item(item, time_block)
94
84
  end
95
- [time_block, duration_by_tag]
85
+
86
+ time_block
96
87
  end
97
88
 
98
- # Processes a time block item and updates the time block hash.
89
+ # Processes a single time block item and updates the time block structure.
99
90
  #
100
- # @param item [Array] The time entry to process, containing the start time, end time, and tag.
101
- # @param time_block [Hash] A hash containing time block data, where keys are dates and values are hashes of time
102
- # slots and their corresponding values.
103
- # @param duration_by_tag [Hash] A hash containing the total duration by tag.
91
+ # @param item [Array] An array containing the item details, including start time, end time, and tag.
92
+ # @param time_block [Hash] The current time block structure.
104
93
  #
105
- # @return [Array<(Hash, Hash)>] An array containing the updated time block hash and the updated duration
106
- # by tag hash.
107
- #
108
- # @example
109
- # item = [nil, Time.new(2024, 10, 21, 8, 0, 0), Time.new(2024, 10, 21, 9, 0, 0), 'work']
110
- # time_block = {}
111
- # duration_by_tag = {}
112
- # process_time_block_item(item, time_block, duration_by_tag)
113
- # #=> [{ '2024-10-21' => { 8 => [3600, 'work'] } }, { 'work' => 3600 }]
94
+ # @return [Hash] The updated time block structure.
114
95
  #
115
96
  # @note
116
- # - The method relies on the `TimeHelper` module for time-related calculations.
117
- # - The `add_hashes` method is used to merge the new time block data into the existing time block hash.
118
- # - The `calculate_duration` method calculates the duration between the start and end times.
97
+ # - The method extracts the start time, end time, and tag from the item.
98
+ # - It calculates the number of seconds per hour block using `TimeHelper.count_seconds_per_hour_block`.
99
+ # - It converts the start time to a date using `TimeHelper.timestamp_to_date`.
100
+ # - It updates the time block structure by adding the new block hour to the existing structure.
119
101
  #
120
102
  # @see TimeHelper#count_seconds_per_hour_block
121
103
  # @see TimeHelper#timestamp_to_date
122
- # @see TimeHelper#calculate_duration
123
104
  # @see #add_hashes
124
- def process_time_block_item(item, time_block, duration_by_tag)
105
+ def process_time_block_item(item, time_block)
125
106
  _, start_time, end_time, tag = item
126
107
 
127
108
  block_hour = TimeHelper.count_seconds_per_hour_block(start_time, end_time, tag)
128
109
  date_line = TimeHelper.timestamp_to_date(start_time)
129
110
  time_block[date_line] = add_hashes(time_block[date_line], block_hour)
130
- duration_by_tag[tag] += TimeHelper.calculate_duration(start_time, end_time)
131
- [time_block, duration_by_tag]
111
+ time_block
132
112
  end
133
113
 
134
114
  # Displays a single time entry in the report.
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'time_statistics'
3
4
  module Timet
4
5
  # The TagDistribution module provides functionality to format and display the distribution of tags based on their
5
6
  # durations. This is particularly useful for visualizing how time is distributed across different tags in a project
@@ -12,20 +13,23 @@ module Timet
12
13
  # Formats and displays the tag distribution.
13
14
  #
14
15
  # @param duration_by_tag [Hash<String, Integer>] A hash where keys are tags and values are durations in seconds.
16
+ # @param colors [Hash<String, String>] A hash where keys are tags and values are color codes for display.
15
17
  # @return [void] This method outputs the formatted tag distribution to the console.
16
18
  #
17
19
  # @example
18
20
  # duration_by_tag = { "timet" => 3600, "nextjs" => 1800 }
19
- # Formatter.format_tag_distribution(duration_by_tag)
21
+ # colors = { "timet" => "\e[31m", "nextjs" => "\e[32m" }
22
+ # Formatter.format_tag_distribution(duration_by_tag, colors)
20
23
  # # Output:
21
- # # timet: 66.67% ====================
22
- # # nextjs: 33.33% ==========
23
- def tag_distribution(duration_by_tag, colors)
24
- total = duration_by_tag.values.sum
24
+ # # \e[31m timet: 66.67% ==================== \e[0m
25
+ # # \e[32m nextjs: 33.33% ========== \e[0m
26
+ def tag_distribution(colors)
27
+ time_stats = TimeStatistics.new(@items)
28
+ total = time_stats.total_duration
29
+
25
30
  return unless total.positive?
26
31
 
27
- sorted_duration_by_tag = duration_by_tag.sort_by { |_, duration| -duration }
28
- process_and_print_tags(sorted_duration_by_tag, total, colors)
32
+ process_and_print_tags(time_stats, total, colors)
29
33
  end
30
34
 
31
35
  # Processes and prints the tag distribution information.
@@ -34,15 +38,50 @@ module Timet
34
38
  # tag and its corresponding duration, sorted by duration in descending order.
35
39
  # @param total [Numeric] The total duration of all tags combined.
36
40
  # @return [void] This method outputs the tag distribution information to the standard output.
37
- def process_and_print_tags(sorted_duration_by_tag, total, colors)
38
- sorted_duration_by_tag.each do |tag, duration|
39
- value, bar_length = calculate_value_and_bar_length(duration, total)
40
- horizontal_bar = (BLOCK_CHAR * bar_length).to_s.color(colors[tag] + 1)
41
- tag = tag[0..TAG_SIZE - 1] if tag.size >= TAG_SIZE
42
- puts "#{tag.rjust(TAG_SIZE)}: #{value.to_s.rjust(5)}% #{horizontal_bar}"
41
+ def process_and_print_tags(time_stats, total, colors)
42
+ time_stats.sorted_duration_by_tag.each do |tag, duration|
43
+ print_tag_info(tag, duration, total, time_stats, colors)
43
44
  end
44
45
  end
45
46
 
47
+ # Prints the detailed information for a specific tag.
48
+ #
49
+ # @param tag [String] The tag for which to print the information.
50
+ # @param duration [Numeric] The duration associated with the tag.
51
+ # @param total [Numeric] The total duration of all tags combined.
52
+ # @param time_stats [Object] An object containing time statistics for the tags.
53
+ # @param colors [Hash] A hash mapping tags to color indices for display.
54
+ # @return [void] This method outputs the tag information to the standard output.
55
+ def print_tag_info(tag, duration, total, time_stats, colors)
56
+ value, bar_length = calculate_value_and_bar_length(duration, total)
57
+ horizontal_bar = generate_horizontal_bar(bar_length, colors[tag])
58
+ formatted_tag = tag[0...TAG_SIZE].rjust(TAG_SIZE)
59
+ stats = generate_stats(tag, time_stats)
60
+
61
+ puts "#{formatted_tag}: #{value.to_s.rjust(5)}% #{horizontal_bar} [#{stats}]"
62
+ end
63
+
64
+ # Generates a horizontal bar for display based on the bar length and color index.
65
+ #
66
+ # @param bar_length [Numeric] The length of the bar to generate.
67
+ # @param color_index [Numeric] The color index to use for the bar.
68
+ # @return [String] The generated horizontal bar string.
69
+ def generate_horizontal_bar(bar_length, color_index)
70
+ (BLOCK_CHAR * bar_length).to_s.color(color_index + 1)
71
+ end
72
+
73
+ # Generates the statistics string for a given tag.
74
+ #
75
+ # @param tag [String] The tag for which to generate the statistics.
76
+ # @param time_stats [Object] An object containing time statistics for the tags.
77
+ # @return [String] The generated statistics string.
78
+ def generate_stats(tag, time_stats)
79
+ total_hours = (time_stats.total_duration_by_tag[tag] / 3600.0).round(1)
80
+ avg_minutes = (time_stats.average_by_tag[tag] / 60.0).round(1)
81
+ sd_minutes = (time_stats.standard_deviation_by_tag[tag] / 60).round(1)
82
+ "T: #{total_hours}h, AVG: #{avg_minutes}min SD: #{sd_minutes}min".gray
83
+ end
84
+
46
85
  # Calculates the percentage value and bar length for a given duration and total duration.
47
86
  #
48
87
  # @param duration [Numeric] The duration for the current tag.
@@ -53,7 +92,7 @@ module Timet
53
92
  # calculate_value_and_bar_length(50, 100, 2) #=> [50.0, 25]
54
93
  def calculate_value_and_bar_length(duration, total)
55
94
  value = duration.to_f / total
56
- percentage_value = (duration.to_f / total * 100).round(2)
95
+ percentage_value = (duration.to_f / total * 100).round(1)
57
96
  bar_length = (value * MAX_BAR_LENGTH).round
58
97
  [percentage_value, bar_length]
59
98
  end
@@ -54,15 +54,22 @@ module Timet
54
54
  # time_report.display
55
55
  #
56
56
  # @note The method formats and prints the table header, rows, and total duration.
57
+ #
58
+ # @param items [Array<Hash>] The list of time entries to be displayed.
59
+ # @param options [Hash] Additional options for customizing the display (e.g., color scheme).
60
+ #
61
+ # @see #table
62
+ # @see #print_time_block_chart
63
+ # @see #tag_distribution
57
64
  def display
58
- return puts 'No tracked time found for the specified filter.' if items.empty?
65
+ return puts 'No tracked time found for the specified filter.' if @items.empty?
59
66
 
60
- time_block, duration_by_tag = table
67
+ time_block = table
61
68
 
62
- colors = duration_by_tag.map { |x| x[0] }.sort.each_with_index.to_h
69
+ colors = @items.map { |x| x[3] }.uniq.each_with_index.to_h
63
70
  print_time_block_chart(time_block, colors)
64
71
 
65
- tag_distribution(duration_by_tag, colors)
72
+ tag_distribution(colors)
66
73
  end
67
74
 
68
75
  # Displays a single row of the report.
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'descriptive_statistics'
4
+ require_relative 'time_helper'
5
+
6
+ module Timet
7
+ # @!attribute [r] duration_by_tag
8
+ # @return [Hash] A hash where keys are tags and values are arrays of durations (in seconds) associated
9
+ # with each tag.
10
+ # @!attribute [r] total_duration
11
+ # @return [Integer] The total duration (in seconds) of all time intervals across all tags.
12
+ class TimeStatistics
13
+ attr_reader :duration_by_tag, :total_duration
14
+
15
+ # Initializes a new instance of TimeStatistics.
16
+ #
17
+ # @param data [Array<Array>] An array of arrays where each sub-array contains:
18
+ # - [0] An identifier (not used in calculations)
19
+ # - [1] The start time (in seconds since the epoch)
20
+ # - [2] The end time (in seconds since the epoch), or nil if the interval is ongoing
21
+ # - [3] The tag associated with the time interval
22
+ # @return [TimeStatistics] A new instance of TimeStatistics.
23
+ def initialize(data)
24
+ @data = data
25
+ @duration_by_tag = Hash.new { |hash, key| hash[key] = [] }
26
+ @total_duration = 0
27
+ calculate_durations_by_tag
28
+ end
29
+
30
+ # Calculates the duration for each tag and updates the @duration_by_tag and @total_duration attributes.
31
+ #
32
+ # @return [void]
33
+ def calculate_durations_by_tag
34
+ @data.each do |row|
35
+ start_time = row[1]
36
+ end_time = row[2] || Time.now.to_i
37
+ tag = row[3]
38
+
39
+ duration = end_time - start_time
40
+ @duration_by_tag[tag] << duration
41
+ @total_duration += duration
42
+ end
43
+ end
44
+
45
+ # Returns a hash where keys are tags and values are the total duration (in seconds) for each tag.
46
+ #
47
+ # @return [Hash<String, Integer>] A hash mapping tags to their total durations.
48
+ def total_duration_by_tag
49
+ @duration_by_tag.transform_values(&:sum)
50
+ end
51
+
52
+ # Returns an array of arrays where each sub-array contains a tag and its total duration, sorted by duration in
53
+ # descending order.
54
+ #
55
+ # @return [Array<Array>] An array of [tag, total_duration] pairs sorted by total_duration in descending order.
56
+ def sorted_duration_by_tag
57
+ @duration_by_tag.map { |tag, durations| [tag, durations.sum] }.sort_by { |_, sum| -sum }
58
+ end
59
+
60
+ # Returns a hash where keys are tags and values are the average duration (in seconds) for each tag.
61
+ #
62
+ # @return [Hash<String, Float>] A hash mapping tags to their average durations.
63
+ def average_by_tag
64
+ @duration_by_tag.transform_values { |durations| durations.sum.to_f / durations.size }
65
+ end
66
+
67
+ # Returns a hash where keys are tags and values are the standard deviation of durations for each tag.
68
+ #
69
+ # @return [Hash<String, Float>] A hash mapping tags to their standard deviations.
70
+ def standard_deviation_by_tag
71
+ @duration_by_tag.transform_values(&:standard_deviation)
72
+ end
73
+
74
+ # Returns a hash where keys are tags and values are additional descriptive statistics for the durations of each tag.
75
+ #
76
+ # @return [Hash<String, Hash>] A hash mapping tags to a hash of descriptive statistics
77
+ # (e.g., min, max, median, etc.).
78
+ def additional_stats_by_tag
79
+ @duration_by_tag.transform_values(&:descriptive_statistics)
80
+ end
81
+ end
82
+ end
data/lib/timet/version.rb CHANGED
@@ -6,6 +6,6 @@ module Timet
6
6
  # @return [String] The version number in the format 'major.minor.patch'.
7
7
  #
8
8
  # @example Get the version of the Timet application
9
- # Timet::VERSION # => '1.4.1'
10
- VERSION = '1.4.1'
9
+ # Timet::VERSION # => '1.4.2'
10
+ VERSION = '1.4.2'
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timet
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Vielma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-31 00:00:00.000000000 Z
11
+ date: 2024-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -88,6 +88,7 @@ files:
88
88
  - lib/timet/time_helper.rb
89
89
  - lib/timet/time_report.rb
90
90
  - lib/timet/time_report_helper.rb
91
+ - lib/timet/time_statistics.rb
91
92
  - lib/timet/validation_edit_helper.rb
92
93
  - lib/timet/version.rb
93
94
  - sig/timet.rbs