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 +4 -4
- data/CHANGELOG.md +44 -0
- data/README.md +49 -40
- data/lib/timet/table.rb +24 -44
- data/lib/timet/tag_distribution.rb +53 -14
- data/lib/timet/time_report.rb +11 -4
- data/lib/timet/time_statistics.rb +82 -0
- data/lib/timet/version.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c57d8e7c61f25526dda2e7a5d1208814cadbc93192b7c60c342399c83f0b545
|
4
|
+
data.tar.gz: 625f4ba71e547e2ebb483d93f1de3812a8b075cacc7afaff7c80554267e5bcc1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|

|
9
9
|
|
10
|
-
Timet
|
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
|
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
|
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
|

|
29
29
|
|
@@ -32,10 +32,9 @@ Examples:
|
|
32
32
|
- Ruby version: >= 3.0.0
|
33
33
|
- sqlite3: > 1.7
|
34
34
|
|
35
|
-
|
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
|
-
|
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
|
-
|
87
|
-
|
88
|
-
|
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
|
-
-
|
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
|
-
|
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
|
-
-
|
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
|
-
|
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
|
-
## 📋
|
174
|
+
## 📋 Command Reference
|
167
175
|
|
168
|
-
| Command
|
169
|
-
|
|
170
|
-
| `timet start [tag] --notes=''
|
171
|
-
| `timet stop`
|
172
|
-
| `timet summary today (t)`
|
173
|
-
| `timet summary yesterday (y)`
|
174
|
-
| `timet summary week (w)`
|
175
|
-
| `timet summary month (m)`
|
176
|
-
| `timet su t --csv=[filename]`
|
177
|
-
| `timet
|
178
|
-
| `timet
|
179
|
-
| `timet
|
180
|
-
| `timet
|
181
|
-
| `timet su [
|
182
|
-
| `timet
|
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
|
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
|
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
|
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 [
|
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
|
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
|
27
|
+
time_block = process_time_entries
|
28
28
|
puts separator
|
29
29
|
total
|
30
|
-
|
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
|
65
|
+
# Processes time entries and generates a time block structure.
|
66
66
|
#
|
67
|
-
# @return [
|
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
|
80
|
-
# -
|
81
|
-
# -
|
82
|
-
# - The `
|
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
|
83
|
+
time_block = process_time_block_item(item, time_block)
|
94
84
|
end
|
95
|
-
|
85
|
+
|
86
|
+
time_block
|
96
87
|
end
|
97
88
|
|
98
|
-
# Processes a time block item and updates the time block
|
89
|
+
# Processes a single time block item and updates the time block structure.
|
99
90
|
#
|
100
|
-
# @param item [Array]
|
101
|
-
# @param time_block [Hash]
|
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 [
|
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
|
117
|
-
# -
|
118
|
-
# -
|
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
|
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
|
-
|
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
|
-
#
|
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(
|
24
|
-
|
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
|
-
|
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(
|
38
|
-
sorted_duration_by_tag.each do |tag, duration|
|
39
|
-
|
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(
|
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
|
data/lib/timet/time_report.rb
CHANGED
@@ -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
|
67
|
+
time_block = table
|
61
68
|
|
62
|
-
colors =
|
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(
|
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
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.
|
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-
|
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
|