timet 1.5.2 → 1.5.3

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: f538523396dc470f91334a3abe44915e63dec009a60901a1ae4ef7b432a9a37f
4
- data.tar.gz: 262da1d62b413102d4ff33932fa7fb05c10c4b13abcb832d6382683d2d314d8d
3
+ metadata.gz: f65773f17ed00b4aff9ff1a3157191f8753686755b6ffd2e985bde5927783c99
4
+ data.tar.gz: b3f6474b4db6fc4f3ebed7b0d976c46061cfc29c85461c6f437a16f48c824aa5
5
5
  SHA512:
6
- metadata.gz: 4d1d90414bda675c2f09827ec99c63b4e86e04f826e969d07af15a757e29b1cb868d412d17b7995012b1091173cd50e2093009600bb55888b06ffd1c1a4397e0
7
- data.tar.gz: cad0f0569224af29941301173dcfa1045c4419db21265b5cdb2d64e5e14f9eeca52d5ada931be7fed1757305ba55bb05823111d974a40c2e57ca0a25c4f8cff7
6
+ metadata.gz: a0db80d8b3671e64d6afc2d1164c74567fedb707a83493042ffb1e3cc87f8242580442e1ad21afc7fb1fd567c1e0b70de96a4647edcc6aef47f44406790d1a5e
7
+ data.tar.gz: 394458e551db981b18b6c1e72a9fa0b734031e6c8408f70f1fd7d2498a98e292204eca0835374b03a7e51df47d0fcc63266d696a9744863a31e153210a3e26d1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.5.3] - 2025-01-02
4
+
5
+ **Improvements:**
6
+
7
+ - Upgraded dependencies in `Gemfile` and `Gemfile.lock` to their latest compatible versions, including `aws-sdk-s3`, `csv`, `sqlite3`, and others.
8
+ - Refactored `TimeBlockChart` from a module to a class, encapsulating `start_hour` and `end_hour` as instance variables for better state management.
9
+ - Added a `print_footer` method to `tag_distribution.rb` to provide clear explanations for summary metrics (total duration, average duration, and standard deviation).
10
+ - Improved documentation for the `TimeBlockChart` class, including example usage and `attr_reader` for `start_hour` and `end_hour`.
11
+ - Simplified method signatures in `TimeBlockChart` by removing redundant parameters and leveraging instance variables.
12
+
13
+ **Bug Fixes:**
14
+
15
+ - Fixed an issue in `tag_distribution.rb` where the calculation of `percentage_value` was redundant and simplified the logic.
16
+ - Corrected the display of the day abbreviation in `TimeBlockChart` to include the full three-letter abbreviation (e.g., "Mon" instead of "Mo").
17
+ - Removed unused code in `time_statistics.rb` that was not contributing to the `totals` method.
18
+
3
19
  ## [1.5.2] - 2024-12-12
4
20
 
5
21
  **Improvements:**
@@ -41,6 +41,17 @@ module Timet
41
41
  def process_and_print_tags(time_stats, total, colors)
42
42
  print_summary(time_stats, total)
43
43
  print_tags_info(time_stats, total, colors)
44
+ print_footer
45
+ end
46
+
47
+ # Prints the footer information.
48
+ #
49
+ # @return [void] This method outputs the footer information to the standard output.
50
+ def print_footer
51
+ puts '-' * 45
52
+ puts 'T:'.rjust(4).red + 'The total duration'.gray
53
+ puts 'AVG:'.rjust(4).red + 'The average duration'.gray
54
+ puts 'SD:'.rjust(4).red + 'The standard deviation of the durations'.gray
44
55
  end
45
56
 
46
57
  # Prints the summary information including total duration, average duration, and standard deviation.
@@ -104,7 +115,7 @@ module Timet
104
115
  # calculate_value_and_bar_length(50, 100, 2) #=> [50.0, 25]
105
116
  def calculate_value_and_bar_length(duration, total)
106
117
  value = duration.to_f / total
107
- percentage_value = (duration.to_f / total * 100).round(1)
118
+ percentage_value = (value * 100).round(1)
108
119
  bar_length = (value * MAX_BAR_LENGTH).round
109
120
  [percentage_value, bar_length]
110
121
  end
@@ -1,9 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Timet
4
- # This module is responsible for formatting the output of the `timet` application.
5
- # It provides methods for formatting the table header, separators, and rows.
6
- module TimeBlockChart
4
+ #
5
+ # The TimeBlockChart class is responsible for generating and printing a visual representation
6
+ # of time blocks for a given set of data. It uses character mapping to represent different
7
+ # time ranges and provides methods to print the chart with headers, footers, and colored blocks.
8
+ #
9
+ # Example usage:
10
+ # time_block = {
11
+ # "2023-10-01" => { "08" => [3600, "work"], "09" => [1800, "break"] },
12
+ # "2023-10-02" => { "10" => [4500, "work"] }
13
+ # }
14
+ # colors = { "work" => 31, "break" => 32 }
15
+ # chart = TimeBlockChart.new(time_block)
16
+ # chart.print_time_block_chart(time_block, colors)
17
+ #
18
+ # @attr_reader [Integer] start_hour The starting hour of the time block
19
+ # @attr_reader [Integer] end_hour The ending hour of the time block
20
+ class TimeBlockChart
21
+ # Character mapping for different time ranges
7
22
  CHAR_MAPPING = {
8
23
  0..120 => '_',
9
24
  121..450 => '▁',
@@ -16,87 +31,66 @@ module Timet
16
31
  3151..3600 => '█'
17
32
  }.freeze
18
33
 
34
+ # Separator character for the chart
19
35
  SEPARATOR_CHAR = '░'
20
36
 
21
- # Prints a time block chart based on the provided time block and colors.
37
+ # Initializes a new TimeBlockChart
22
38
  #
23
- # @param time_block [Hash] A hash where the keys are time blocks and the values are hashes of time slots and their
24
- # corresponding values.
25
- # Example: { "block1" => { 10 => "value1", 11 => "value2" }, "block2" => { 12 => "value3" } }
26
- # @param colors [Hash] A hash where the keys are time slots and the values are the colors to be used
27
- # for those slots.
28
- # Example: { 10 => "red", 11 => "blue", 12 => "green" }
29
- #
30
- # @return [void] This method does not return a value; it prints the chart directly to the output.
31
- #
32
- # @example
33
- # time_block = { "block1" => { 10 => "value1", 11 => "value2" }, "block2" => { 12 => "value3" } }
34
- # colors = { 10 => "red", 11 => "blue", 12 => "green" }
35
- # print_time_block_chart(time_block, colors)
36
- #
37
- # @note This method relies on two helper methods: `print_header` and `print_blocks`.
38
- # Ensure these methods are defined and available in the scope where `print_time_block_chart` is called.
39
+ # @param [Hash] time_block The time block data
40
+ def initialize(time_block)
41
+ @start_hour = time_block.values.map(&:keys).flatten.uniq.min.to_i
42
+ @end_hour = time_block.values.map(&:keys).flatten.uniq.max.to_i
43
+ end
44
+
45
+ # Prints the time block chart
39
46
  #
40
- # @see #print_header
41
- # @see #print_blocks
47
+ # @param [Hash] time_block The time block data
48
+ # @param [Hash] colors The color mapping for different tags
49
+ # @return [void]
42
50
  def print_time_block_chart(time_block, colors)
43
- start_hour = time_block.values.map(&:keys).flatten.uniq.min.to_i
44
- print_header(start_hour)
45
- print_blocks(time_block, colors, start_hour)
51
+ print_header
52
+ print_blocks(time_block, colors)
46
53
  end
47
54
 
48
- # Prints the header of the time block chart.
49
- #
50
- # The header includes a visual representation of the time slots from the given start time to 23.
51
- # Each time slot is formatted as a two-digit number and aligned to the right within a fixed width.
52
- #
53
- # @param start_hour [Integer] The starting time for the chart. This should be an integer between 0 and 23.
54
- #
55
- # @return [void] This method does not return a value; it prints the header directly to the output.
56
- #
57
- # @example
58
- # print_header(10)
59
- # # Output:
60
- # #
61
- # # ⏳ ↦ [ 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
55
+ private
56
+
57
+ # Prints the header of the chart
62
58
  #
63
- # @note The method assumes that the start_hour is within the valid range of 0 to 23.
64
- # If the start_hour is outside this range, the output may not be as expected.
65
- def print_header(start_hour)
59
+ # @return [void]
60
+ def print_header
66
61
  puts
67
62
  print ' ' * 19
68
- (start_hour..23).each { |hour| print format('%02d', hour).rjust(4) }
63
+ (@start_hour..@end_hour + 1).each { |hour| print format('%02d', hour).rjust(4) }
69
64
  puts
70
- puts '┌╴W ╴╴╴╴╴╴⏰╴╴╴╴╴╴┼'.gray + "#{'╴' * (24 - start_hour) * 4}╴╴╴┼".gray
65
+ puts '┌╴W ╴╴╴╴╴╴⏰╴╴╴╴╴╴┼'.gray + "#{'╴' * (@end_hour - @start_hour + 1) * 4}╴╴╴┼".gray
71
66
  end
72
67
 
73
- # Prints the time blocks for each date in the given time block data structure.
68
+ # Prints the time blocks
74
69
  #
75
- # @param time_block [Hash] A hash where keys are date strings and values are time block data.
76
- # @param colors [Hash] A hash containing color codes for formatting.
77
- # @param start_hour [Integer] The starting hour for the time blocks.
70
+ # @param [Hash] time_block The time block data
71
+ # @param [Hash] colors The color mapping for different tags
78
72
  # @return [void]
79
- def print_blocks(time_block, colors, start_hour)
73
+ def print_blocks(time_block, colors)
80
74
  return unless time_block
81
75
 
82
76
  weeks = []
83
77
  time_block.each_key do |date_string|
84
78
  date = Date.parse(date_string)
85
- day = date.strftime('%a')[0..1]
79
+ day = date.strftime('%a')[0..2]
86
80
 
87
- format_and_print_date_info(date_string, day, weeks, start_hour)
81
+ format_and_print_date_info(date_string, day, weeks)
88
82
 
89
83
  time_block_initial = time_block[date_string]
90
- print_time_blocks(start_hour, time_block_initial, colors)
84
+ print_time_blocks(time_block_initial, colors)
91
85
 
92
86
  calculate_and_print_hours(time_block_initial)
93
87
  end
94
- print_footer(start_hour)
88
+ print_footer
95
89
  end
96
90
 
97
- # Calculates the total hours from the given time block data and prints it.
91
+ # Calculates and prints the total hours for a day
98
92
  #
99
- # @param time_block_initial [Hash] A hash containing time block data for a specific date.
93
+ # @param [Hash] time_block_initial The initial time block data for a day
100
94
  # @return [void]
101
95
  def calculate_and_print_hours(time_block_initial)
102
96
  total_seconds = time_block_initial.values.map { |item| item[0] }.sum
@@ -105,104 +99,88 @@ module Timet
105
99
  puts
106
100
  end
107
101
 
108
- # Formats and prints the date information including the week and day.
102
+ # Formats and prints the date information
109
103
  #
110
- # @param date_string [String] The date string in a parsable format.
111
- # @param day [String] The abbreviated day of the week (e.g., "Mo" for Monday).
112
- # @param weeks [Array<Integer>] An array storing the week numbers.
113
- # @param start_hour [Integer] The starting hour for the time blocks.
104
+ # @param [String] date_string The date string
105
+ # @param [String] day The day of the week
106
+ # @param [Array] weeks The list of weeks
114
107
  # @return [void]
115
- def format_and_print_date_info(date_string, day, weeks, start_hour)
108
+ def format_and_print_date_info(date_string, day, weeks)
116
109
  weekend = date_string
117
110
  day = day.red if %w[Sa Su].include?(day)
118
111
  weekend = weekend.red if %w[Sa Su].include?(day)
119
112
 
120
- week = format_and_print_week(date_string, weeks, start_hour)
113
+ week = format_and_print_week(date_string, weeks)
121
114
 
122
- print '┆'.gray + "#{week} #{weekend} #{day} " + '┆- '.gray
115
+ print '┆'.gray + "#{week} #{weekend} #{day}" + '┆- '.gray
123
116
  end
124
117
 
125
- # Formats and prints the week information including the separator if necessary.
118
+ # Formats and prints the week information
126
119
  #
127
- # @param date_string [String] The date string in a parsable format.
128
- # @param weeks [Array<Integer>] An array storing the week numbers.
129
- # @param start_hour [Integer] The starting hour for the time blocks.
130
- # @return [String] The formatted week string.
131
- def format_and_print_week(date_string, weeks, start_hour)
120
+ # @param [String] date_string The date string
121
+ # @param [Array] weeks The list of weeks
122
+ # @return [String] The formatted week string
123
+ def format_and_print_week(date_string, weeks)
132
124
  week, current_index = determine_week(date_string, weeks)
133
- print_separator(start_hour, week, current_index)
125
+ print_separator(week, current_index)
134
126
  week
135
127
  end
136
128
 
137
- # Determines the week string based on the date and the previous week.
129
+ # Determines the week for a given date
138
130
  #
139
- # @param date_string [String] The date string in a parsable format.
140
- # @param weeks [Array<Integer>] An array storing the week numbers.
141
- # @return [Array<String, Integer>] An array containing the formatted week string and the current index.
131
+ # @param [String] date_string The date string
132
+ # @param [Array] weeks The list of weeks
133
+ # @return [Array] The week string and current index
142
134
  def determine_week(date_string, weeks)
143
135
  weeks << Date.parse(date_string).cweek
144
136
  current_index = weeks.size - 1
145
137
  current_week = weeks[current_index]
146
- week = current_week == weeks[current_index - 1] && current_index.positive? ? ' ' : current_week.to_s.underline
138
+ week = if current_week == weeks[current_index - 1] && current_index.positive?
139
+ ' '
140
+ else
141
+ format('%02d', current_week).to_s.underline
142
+ end
147
143
  [week, current_index]
148
144
  end
149
145
 
150
- # Prints the separator line if the week string is not empty and the current index is positive.
146
+ # Prints the separator line
151
147
  #
152
- # @param start_hour [Integer] The starting hour for the time blocks.
153
- # @param week [String] The formatted week string.
154
- # @param current_index [Integer] The current index in the weeks array.
148
+ # @param [String] week The week string
149
+ # @param [Integer] current_index The current index
155
150
  # @return [void]
156
- def print_separator(start_hour, week, current_index)
151
+ def print_separator(week, current_index)
157
152
  return unless week != ' ' && current_index.positive?
158
153
 
159
154
  sep = SEPARATOR_CHAR
160
- puts "┆#{sep * 17}┼#{sep * (24 - start_hour) * 4}#{sep * 3}┼#{sep * 4}".gray
155
+ puts "┆#{sep * 17}┼#{sep * (@end_hour - @start_hour + 1) * 4}#{sep * 3}┼#{sep * 4}".gray
161
156
  end
162
157
 
163
- # Prints the footer of the report.
158
+ # Prints the footer of the chart
164
159
  #
165
- # @param start_hour [Integer] The start time used to calculate the footer length.
166
- # @return [void] This method does not return a value; it prints directly to the standard output.
167
- def print_footer(start_hour)
160
+ # @return [void]
161
+ def print_footer
168
162
  timet = "\e]8;;https://github.com/frankvielma/timet/\aTimet\e]8;;\a".green
169
- puts '└╴╴╴╴╴╴╴'.gray + timet + "╴╴╴╴╴┴#{'╴' * (24 - start_hour) * 4}╴╴╴┴".gray
163
+ puts '└╴╴╴╴╴╴╴'.gray + timet + "╴╴╴╴╴┴#{'╴' * (@end_hour - @start_hour + 1) * 4}╴╴╴┴".gray
170
164
  puts
171
165
  end
172
166
 
173
- # Prints time blocks for each hour from the start time to 23.
167
+ # Prints the time blocks for a given day
174
168
  #
175
- # @param start_time [Integer] The starting hour for printing time blocks.
176
- # @param time_block_initial [Hash] A hash containing time block data, where keys are formatted hours and values
177
- # are arrays containing block data.
178
- # @param colors [Hash] A hash mapping tags to color codes.
169
+ # @param [Hash] time_block_initial The initial time block data for a day
170
+ # @param [Hash] colors The color mapping for different tags
179
171
  # @return [void]
180
- #
181
- # @example
182
- # time_block_initial = {
183
- # '01' => ['block_char_data', 'tag']
184
- # }
185
- # colors = { 'tag' => 1 }
186
- # print_time_blocks(1, time_block_initial, colors) # Prints time blocks for hours 1 to 23
187
- def print_time_blocks(start_time, time_block_initial, colors)
188
- (start_time..23).each do |hour|
172
+ def print_time_blocks(time_block_initial, colors)
173
+ (@start_hour..@end_hour).each do |hour|
189
174
  tag, block_char = get_formatted_block_char(hour, time_block_initial)
190
175
  print_colored_block(block_char, tag, colors)
191
176
  end
192
177
  end
193
178
 
194
- # Returns the formatted block character and its associated tag for a given hour.
195
- #
196
- # @param hour [Integer] The hour for which to retrieve the block character.
197
- # @param time_block_initial [Hash] A hash containing time block data, where keys are formatted hours and values
198
- # are arrays containing block data.
199
- # @return [Array<(String, String)>] An array containing the tag and the block character.
179
+ # Gets the formatted block character for a given hour
200
180
  #
201
- # @example
202
- # time_block_initial = {
203
- # '01' => ['block_char_data', 'tag']
204
- # }
205
- # get_formatted_block_char(1, time_block_initial) #=> ['tag', 'block_char']
181
+ # @param [Integer] hour The hour
182
+ # @param [Hash] time_block_initial The initial time block data for a day
183
+ # @return [Array] The tag and block character
206
184
  def get_formatted_block_char(hour, time_block_initial)
207
185
  formatted_hour = format('%02d', hour)
208
186
  hour_data = time_block_initial[formatted_hour]
@@ -210,15 +188,12 @@ module Timet
210
188
  [tag, get_block_char(hour_data&.first)]
211
189
  end
212
190
 
213
- # Prints a colored block character based on the provided tag and block character.
191
+ # Prints the colored block character
214
192
  #
215
- # @param block_char [String] The block character to be printed.
216
- # @param tag [String] The tag associated with the block character, used to determine the color.
217
- # @param colors [Hash] A hash mapping tags to color codes.
218
- #
219
- # @example
220
- # colors = { 'tag' => 1 }
221
- # print_colored_block('X', 'tag', colors) # Prints a colored block character 'XX'
193
+ # @param [String] block_char The block character
194
+ # @param [String] tag The tag
195
+ # @param [Hash] colors The color mapping for different tags
196
+ # @return [void]
222
197
  def print_colored_block(block_char, tag, colors)
223
198
  color_code = colors[tag]
224
199
  block = block_char * 2
@@ -226,10 +201,10 @@ module Timet
226
201
  print colored_block.rjust(4)
227
202
  end
228
203
 
229
- # Determines the block character based on the value.
204
+ # Gets the block character for a given value
230
205
  #
231
- # @param value [Integer] The value to determine the block character for.
232
- # @return [String] The block character corresponding to the value.
206
+ # @param [Integer, nil] value The value
207
+ # @return [String] The block character
233
208
  def get_block_char(value)
234
209
  return ' ' unless value
235
210
 
@@ -15,7 +15,6 @@ module Timet
15
15
  class TimeReport
16
16
  include TimeReportHelper
17
17
  include Table
18
- include TimeBlockChart
19
18
  include TagDistribution
20
19
 
21
20
  # Provides access to the database instance.
@@ -74,7 +73,8 @@ module Timet
74
73
  time_block = table
75
74
 
76
75
  colors = @items.map { |x| x[3] }.uniq.each_with_index.to_h
77
- print_time_block_chart(time_block, colors)
76
+ chart = TimeBlockChart.new(time_block)
77
+ chart.print_time_block_chart(time_block, colors)
78
78
 
79
79
  tag_distribution(colors)
80
80
  end
@@ -34,8 +34,6 @@ module Timet
34
34
  # - :avg [Numeric] The average duration.
35
35
  # - :sd [Numeric] The standard deviation of the durations.
36
36
  def totals
37
- @duration_by_tag.values.flatten
38
-
39
37
  durations = @duration_by_tag.values.flatten
40
38
  { total: @total_duration, avg: durations.mean, sd: durations.standard_deviation }
41
39
  end
@@ -51,7 +51,8 @@ module Timet
51
51
  # @note The method formats the date value and checks if it is valid.
52
52
  # @note If the date value is valid, it updates the time field with the new value.
53
53
  # @note If the date value is invalid, it prints an error message.
54
- def process_and_update_time_field(item, field, date_value, id)
54
+ def process_and_update_time_field(*args)
55
+ item, field, date_value, id = args
55
56
  formatted_date = TimeHelper.format_time_string(date_value)
56
57
 
57
58
  return print_error(date_value) unless formatted_date
@@ -107,7 +108,8 @@ module Timet
107
108
  #
108
109
  # @example Validate a new 'start' time value
109
110
  # valid_time_value?(item, 'start', 1633072800, 1)
110
- def valid_time_value?(item, field, new_value_epoch, id)
111
+ def valid_time_value?(*args)
112
+ item, field, new_value_epoch, id = args
111
113
  item_start = fetch_item_start(item)
112
114
  item_end = fetch_item_end(item)
113
115
  item_before_end = fetch_item_before_end(id, item_start)
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.5.2'
10
- VERSION = '1.5.2'
9
+ # Timet::VERSION # => '1.5.3'
10
+ VERSION = '1.5.3'
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.5.2
4
+ version: 1.5.3
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-12-12 00:00:00.000000000 Z
11
+ date: 2025-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor