reading 0.9.0 → 1.0.0

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.
@@ -1,3 +1,5 @@
1
+ require "bigdecimal/util"
2
+
1
3
  module Reading
2
4
  module Stats
3
5
  # The beginning of a query which specifies what it does, e.g.
@@ -50,14 +52,14 @@ module Reading
50
52
  # Items) of the given hash of grouped items.
51
53
  # @param grouped_items [Hash]
52
54
  # @yield [Array<Item>]
53
- def self.apply_to_inner_items(grouped_items, &)
55
+ def self.apply_to_inner_items(grouped_items, &block)
54
56
  if grouped_items.values.first.is_a? Array
55
57
  grouped_items.transform_values! { |inner_items|
56
58
  yield inner_items
57
59
  }
58
60
  else # It's a Hash, so go one level deeper.
59
61
  grouped_items.each do |group_name, grouped|
60
- apply_to_inner_items(grouped, &)
62
+ apply_to_inner_items(grouped, &block)
61
63
  end
62
64
  end
63
65
  end
@@ -89,7 +91,7 @@ module Reading
89
91
  (lengths.sum / lengths.count.to_f).to_i_if_whole
90
92
  end
91
93
  },
92
- :"average_amount" => proc { |items|
94
+ average_amount: proc { |items|
93
95
  total_amount = items.sum { |item|
94
96
  item.experiences.sum { |experience|
95
97
  experience.spans.sum(&:amount)
@@ -105,6 +107,9 @@ module Reading
105
107
  amounts_by_date.values.sum / amounts_by_date.count
106
108
  end
107
109
  },
110
+ list_item: proc { |items|
111
+ items.map { |item| author_and_title(item) }
112
+ },
108
113
  total_item: proc { |items|
109
114
  items.count
110
115
  },
@@ -112,77 +117,153 @@ module Reading
112
117
  items.sum { |item|
113
118
  item.experiences.sum { |experience|
114
119
  experience.spans.sum { |span|
115
- (span.amount * span.progress).to_i_if_whole
120
+ (span.amount * (span.progress || 0.0)).to_i_if_whole
116
121
  }
117
122
  }
118
123
  }
119
124
  },
120
125
  top_rating: proc { |items, number_arg|
121
126
  items
122
- .max_by(number_arg || DEFAULT_NUMBER_ARG, &:rating)
123
127
  .map { |item| [author_and_title(item), item.rating] }
128
+ .max_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, rating|
129
+ rating || 0
130
+ }
124
131
  },
125
132
  top_length: proc { |items, number_arg|
126
133
  items
127
- .map { |item| [author_and_title(item), item.variants.map(&:length).max] }
134
+ .map { |item|
135
+ # Longest length, or if undefined length then longest experience
136
+ # (code adapted from top_amount below).
137
+ length = item.variants.map(&:length).max ||
138
+ item.experiences.map { |experience|
139
+ experience.spans.sum { |span|
140
+ (span.amount * (span.progress || 0.0)).to_i_if_whole
141
+ }
142
+ }.max
143
+
144
+ [author_and_title(item), length]
145
+ }
128
146
  .reject { |_title, length| length.nil? }
129
- .max_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, length| length }
147
+ .max_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, length|
148
+ length
149
+ }
130
150
  },
131
151
  top_amount: proc { |items, number_arg|
132
152
  items
133
153
  .map { |item|
134
154
  amount = item.experiences.sum { |experience|
135
155
  experience.spans.sum { |span|
136
- (span.amount * span.progress).to_i_if_whole
156
+ (span.amount * (span.progress || 0.0)).to_i_if_whole
137
157
  }
138
158
  }
139
159
 
140
160
  [author_and_title(item), amount]
141
161
  }
142
162
  .reject { |_title, amount| amount.zero? }
143
- .max_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, amount| amount }
163
+ .max_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, amount|
164
+ amount
165
+ }
144
166
  },
145
167
  top_speed: proc { |items, number_arg|
146
168
  items
147
- .map { |item| calculate_speed(item) }
169
+ .map { |item|
170
+ speed = calculate_speed(item)
171
+ [author_and_title(item), speed] if speed
172
+ }
148
173
  .compact
149
174
  .max_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, speed_hash|
150
175
  speed_hash[:amount] / speed_hash[:days].to_f
151
176
  }
152
177
  },
178
+ top_experience: proc { |items, number_arg|
179
+ items
180
+ .map { |item|
181
+ experience_count = item
182
+ .experiences
183
+ .count { |experience|
184
+ experience.spans.all? { _1.progress.to_d == "1.0".to_d }
185
+ }
186
+
187
+ [author_and_title(item), [experience_count, item.rating || 0]]
188
+ }
189
+ .max_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, experience_count_and_rating|
190
+ experience_count_and_rating
191
+ }
192
+ .map { |title, (experience_count, _rating)|
193
+ [title, experience_count]
194
+ }
195
+ },
196
+ top_note: proc { |items, number_arg|
197
+ items
198
+ .map { |item|
199
+ notes_word_count = item
200
+ .notes
201
+ .sum { |note|
202
+ note.content.scan(/[\w[:punct:]]+/).count
203
+ }
204
+
205
+ [author_and_title(item), notes_word_count]
206
+ }
207
+ .max_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, notes_word_count|
208
+ notes_word_count
209
+ }
210
+ },
153
211
  bottom_rating: proc { |items, number_arg|
154
212
  items
155
- .min_by(number_arg || DEFAULT_NUMBER_ARG, &:rating)
156
213
  .map { |item| [author_and_title(item), item.rating] }
214
+ .min_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, rating|
215
+ rating || 0
216
+ }
157
217
  },
158
218
  bottom_length: proc { |items, number_arg|
159
219
  items
160
- .map { |item| [author_and_title(item), item.variants.map(&:length).max] }
220
+ .map { |item|
221
+ # Longest length, or if undefined length then longest experience
222
+ # (code adapted from bottom_amount below).
223
+ length = item.variants.map(&:length).max ||
224
+ item.experiences.map { |experience|
225
+ experience.spans.sum { |span|
226
+ (span.amount * (span.progress || 0.0)).to_i_if_whole
227
+ }
228
+ }.max
229
+
230
+ [author_and_title(item), length]
231
+ }
161
232
  .reject { |_title, length| length.nil? }
162
- .min_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, length| length }
233
+ .min_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, length|
234
+ length
235
+ }
163
236
  },
164
237
  bottom_amount: proc { |items, number_arg|
165
238
  items
166
239
  .map { |item|
167
240
  amount = item.experiences.sum { |experience|
168
241
  experience.spans.sum { |span|
169
- (span.amount * span.progress).to_i_if_whole
242
+ (span.amount * (span.progress || 0.0)).to_i_if_whole
170
243
  }
171
244
  }
172
245
 
173
246
  [author_and_title(item), amount]
174
247
  }
175
248
  .reject { |_title, amount| amount.zero? }
176
- .min_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, amount| amount }
249
+ .min_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, amount|
250
+ amount
251
+ }
177
252
  },
178
253
  bottom_speed: proc { |items, number_arg|
179
254
  items
180
- .map { |item| calculate_speed(item) }
255
+ .map { |item|
256
+ speed = calculate_speed(item)
257
+ [author_and_title(item), speed] if speed
258
+ }
181
259
  .compact
182
260
  .min_by(number_arg || DEFAULT_NUMBER_ARG) { |_title, speed_hash|
183
261
  speed_hash[:amount] / speed_hash[:days].to_f
184
262
  }
185
263
  },
264
+ debug: proc { |items|
265
+ items
266
+ },
186
267
  }
187
268
 
188
269
  ALIASES = {
@@ -190,20 +271,24 @@ module Reading
190
271
  average_length: %w[al],
191
272
  average_amount: %w[aia ai],
192
273
  :"average_daily-amount" => %w[ada ad],
274
+ list_item: %w[li list],
193
275
  total_item: %w[item count],
194
276
  total_amount: %w[amount],
195
277
  top_rating: %w[tr],
196
278
  top_length: %w[tl],
197
279
  top_amount: %w[ta],
198
280
  top_speed: %w[ts],
281
+ top_experience: %w[te],
282
+ top_note: %w[tn],
199
283
  bottom_rating: %w[br],
200
284
  bottom_length: %w[bl],
201
285
  bottom_amount: %w[ba],
202
286
  bottom_speed: %w[bs],
287
+ debug: %w[d],
203
288
  }
204
289
 
205
290
  REGEXES = ACTIONS.map { |key, _action|
206
- first_word, second_word = key.to_s.split('_')
291
+ first_word, second_word = key.to_s.split("_")
207
292
  aliases = ALIASES.fetch(key)
208
293
 
209
294
  regex =
@@ -228,7 +313,7 @@ module Reading
228
313
  (
229
314
  \A
230
315
  \s*
231
- (#{aliases.join('|')})
316
+ (#{aliases.join("|")})
232
317
  s?
233
318
  \s*
234
319
  (?<number_arg>
@@ -296,10 +381,7 @@ module Reading
296
381
 
297
382
  return nil unless speeds.any?
298
383
 
299
- speed = speeds
300
- .max_by { |hash| hash[:amount] / hash[:days].to_f }
301
-
302
- [author_and_title(item), speed]
384
+ speeds.max_by { |hash| hash[:amount] / hash[:days].to_f }
303
385
  end
304
386
 
305
387
  # A shorter version of Item::View#name.
@@ -1,7 +1,8 @@
1
- require 'pastel'
2
- require_relative 'operation'
3
- require_relative 'filter'
4
- require_relative 'grouping'
1
+ require "pastel"
2
+ require_relative "operation"
3
+ require_relative "filter"
4
+ require_relative "grouping"
5
+ require_relative "result_formatters"
5
6
 
6
7
  module Reading
7
8
  module Stats
@@ -13,9 +14,8 @@ module Reading
13
14
  # @param items [Array<Item>] the Items to be queried.
14
15
  # @param result_formatters [Boolean, Hash{Symbol => Proc}] to alter the
15
16
  # appearance of results; keys should be from among the keys of
16
- # Operation::ACTIONS. Pre-made formatters for terminal output are in
17
- # terminal_result_formatters.rb.
18
- def initialize(input:, items:, result_formatters: {})
17
+ # Operation::ACTIONS. Pre-made formatters are in result_formatters.rb.
18
+ def initialize(input:, items:, result_formatters: Reading::Stats::ResultFormatters::TRUNCATED_TITLES)
19
19
  @input = input
20
20
  @items = items
21
21
  @result_formatters = result_formatters
@@ -0,0 +1,140 @@
1
+ require "pastel"
2
+
3
+ module Reading
4
+ module Stats
5
+ module ResultFormatters
6
+ TRUNCATED_TITLES = {
7
+ top_length: ->(result) { with_truncated_title(result) },
8
+ top_amount: ->(result) { with_truncated_title(result) },
9
+ top_speed: ->(result) { with_truncated_title(result) },
10
+ top_experience: ->(result) { with_truncated_title(result) },
11
+ top_note: ->(result) { with_truncated_title(result) },
12
+ bottom_length: ->(result) { with_truncated_title(result) },
13
+ botom_amount: ->(result) { with_truncated_title(result) },
14
+ bottom_speed: ->(result) { with_truncated_title(result) },
15
+ }
16
+
17
+ TERMINAL = {
18
+ average_length: ->(result) { length_to_s(result) },
19
+ average_amount: ->(result) { length_to_s(result) },
20
+ :"average_daily-amount" => ->(result) { "#{length_to_s(result)} per day" },
21
+ total_item: ->(result) {
22
+ if result.zero?
23
+ PASTEL.bright_black("none")
24
+ else
25
+ color("#{result} #{result == 1 ? "item" : "items"}")
26
+ end
27
+ },
28
+ total_amount: ->(result) { length_to_s(result) },
29
+ top_rating: ->(result) { top_or_bottom_numbers_string(result, noun: "star") },
30
+ top_length: ->(result) { top_or_bottom_lengths_string(result) },
31
+ top_amount: ->(result) { top_or_bottom_lengths_string(result) },
32
+ top_speed: ->(result) { top_or_bottom_speeds_string(result) },
33
+ top_experience: ->(result) { top_or_bottom_numbers_string(result, noun: "experience") },
34
+ top_note: ->(result) { top_or_bottom_numbers_string(result, noun: "word") },
35
+ bottom_rating: ->(result) { top_or_bottom_numbers_string(result, noun: "star") },
36
+ bottom_length: ->(result) { top_or_bottom_lengths_string(result) },
37
+ botom_amount: ->(result) { top_or_bottom_lengths_string(result) },
38
+ bottom_speed: ->(result) { top_or_bottom_speeds_string(result) },
39
+ }
40
+
41
+ private
42
+
43
+ PASTEL = Pastel.new
44
+
45
+ # Applies a terminal color.
46
+ # @param string [String]
47
+ # @return [String]
48
+ private_class_method def self.color(string)
49
+ PASTEL.bright_blue(string)
50
+ end
51
+
52
+ # Converts a length/amount (pages or time) into a string.
53
+ # @param length [Numeric, Reading::Item::TimeLength]
54
+ # @param color [Boolean] whether a terminal color should be applied.
55
+ # @return [String]
56
+ private_class_method def self.length_to_s(length, color: true)
57
+ if length.is_a?(Numeric)
58
+ length_string = "#{length.round} pages"
59
+ else
60
+ length_string = length.to_s
61
+ end
62
+
63
+ color ? color(length_string) : length_string
64
+ end
65
+
66
+ # Formats a list of top/bottom length results as a string.
67
+ # @param result [Array]
68
+ # @return [String]
69
+ private_class_method def self.top_or_bottom_lengths_string(result)
70
+ offset = result.count.digits.count
71
+
72
+ result
73
+ .map.with_index { |(title, length), index|
74
+ pad = " " * (offset - (index + 1).digits.count)
75
+
76
+ title_line = "#{index + 1}. #{pad}#{title}"
77
+ indent = " #{" " * offset}"
78
+
79
+ "#{title_line}\n#{indent}#{length_to_s(length)}"
80
+ }
81
+ .join("\n")
82
+ end
83
+
84
+ # Formats a list of top/bottom speed results as a string.
85
+ # @param result [Array]
86
+ # @return [String]
87
+ private_class_method def self.top_or_bottom_speeds_string(result)
88
+ offset = result.count.digits.count
89
+
90
+ result
91
+ .map.with_index { |(title, hash), index|
92
+ amount = length_to_s(hash[:amount], color: false)
93
+ days = "#{hash[:days]} #{hash[:days] == 1 ? "day" : "days"}"
94
+ pad = " " * (offset - (index + 1).digits.count)
95
+
96
+ title_line = "#{index + 1}. #{pad}#{title}"
97
+ indent = " #{" " * offset}"
98
+ colored_speed = color("#{amount} in #{days}")
99
+
100
+ "#{title_line}\n#{indent}#{colored_speed}"
101
+ }
102
+ .join("\n")
103
+ end
104
+
105
+ # Formats a list of top/bottom number results as a string.
106
+ private_class_method def self.top_or_bottom_numbers_string(result, noun:)
107
+ offset = result.count.digits.count
108
+
109
+ result
110
+ .map.with_index { |(title, number), index|
111
+ pad = " " * (offset - (index + 1).digits.count)
112
+
113
+ title_line = "#{index + 1}. #{pad}#{title}"
114
+ indent = " #{" " * offset}"
115
+ number_string = color("#{number} #{number == 1 ? noun : "#{noun}s"}")
116
+
117
+ "#{title_line}\n#{indent}#{number_string}"
118
+ }
119
+ .join("\n")
120
+ end
121
+
122
+ # Truncates the title of each result to a specified length.
123
+ # @param result [Array]
124
+ # @param length [Integer] the maximum length of the title.
125
+ # @return [Array]
126
+ private_class_method def self.with_truncated_title(result, length: 45)
127
+ result.map do |title, value|
128
+ truncated_title =
129
+ if title.length + 1 > length
130
+ "#{title[0...length]}…"
131
+ else
132
+ title
133
+ end
134
+
135
+ [truncated_title, value]
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -1,31 +1,9 @@
1
1
  module Reading
2
2
  module Util
3
- class FetchDepthExceededError < StandardError
4
- end
5
-
6
3
  # Similar to Array#dig and Hash#dig but raises an error for not found elements.
7
- #
8
- # More flexible but slightly slower alternative:
9
- # keys.reduce(self) { |a, e| a.fetch(e) }
10
- #
11
- # See performance comparisons:
12
- # https://fpsvogel.com/posts/2022/ruby-hash-dot-syntax-deep-fetch
13
4
  module HashArrayDeepFetch
14
5
  def deep_fetch(*keys)
15
- case keys.length
16
- when 1
17
- fetch(keys[0])
18
- when 2
19
- fetch(keys[0]).fetch(keys[1])
20
- when 3
21
- fetch(keys[0]).fetch(keys[1]).fetch(keys[2])
22
- when 4
23
- fetch(keys[0]).fetch(keys[1]).fetch(keys[2]).fetch(keys[3])
24
- when 5
25
- fetch(keys[0]).fetch(keys[1]).fetch(keys[2]).fetch(keys[3]).fetch(keys[4])
26
- else
27
- raise FetchDepthExceededError, "#deep_fetch can't fetch that deep!"
28
- end
6
+ keys.reduce(self) { |a, e| a.fetch(e) }
29
7
  end
30
8
 
31
9
  refine Hash do
@@ -1,3 +1,3 @@
1
1
  module Reading
2
- VERSION = '0.9.0'
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/reading.rb CHANGED
@@ -1,10 +1,10 @@
1
- Dir[File.join(__dir__, 'reading', 'util', '*.rb')].each { |file| require file }
2
- require_relative 'reading/errors'
3
- require_relative 'reading/config'
4
- require_relative 'reading/parsing/csv'
5
- require_relative 'reading/filter'
6
- require_relative 'reading/stats/query'
7
- require_relative 'reading/item/time_length.rb'
1
+ Dir[File.join(__dir__, "reading", "util", "*.rb")].each { |file| require file }
2
+ require_relative "reading/errors"
3
+ require_relative "reading/config"
4
+ require_relative "reading/parsing/csv"
5
+ require_relative "reading/filter"
6
+ require_relative "reading/stats/query"
7
+ require_relative "reading/item/time_length.rb"
8
8
 
9
9
  # The gem's public API. See https://github.com/fpsvogel/reading#usage
10
10
  #
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reading
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felipe Vogel
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-07-15 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: pastel
@@ -24,48 +23,76 @@ dependencies:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
25
  version: '0.8'
26
+ - !ruby/object:Gem::Dependency
27
+ name: amazing_print
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: bigdecimal
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
27
54
  - !ruby/object:Gem::Dependency
28
55
  name: debug
29
56
  requirement: !ruby/object:Gem::Requirement
30
57
  requirements:
31
58
  - - "~>"
32
59
  - !ruby/object:Gem::Version
33
- version: '1.7'
60
+ version: '1.0'
34
61
  type: :development
35
62
  prerelease: false
36
63
  version_requirements: !ruby/object:Gem::Requirement
37
64
  requirements:
38
65
  - - "~>"
39
66
  - !ruby/object:Gem::Version
40
- version: '1.7'
67
+ version: '1.0'
41
68
  - !ruby/object:Gem::Dependency
42
69
  name: minitest
43
70
  requirement: !ruby/object:Gem::Requirement
44
71
  requirements:
45
72
  - - "~>"
46
73
  - !ruby/object:Gem::Version
47
- version: '5.18'
74
+ version: '5.0'
48
75
  type: :development
49
76
  prerelease: false
50
77
  version_requirements: !ruby/object:Gem::Requirement
51
78
  requirements:
52
79
  - - "~>"
53
80
  - !ruby/object:Gem::Version
54
- version: '5.18'
81
+ version: '5.0'
55
82
  - !ruby/object:Gem::Dependency
56
83
  name: minitest-reporters
57
84
  requirement: !ruby/object:Gem::Requirement
58
85
  requirements:
59
86
  - - "~>"
60
87
  - !ruby/object:Gem::Version
61
- version: '1.6'
88
+ version: '1.0'
62
89
  type: :development
63
90
  prerelease: false
64
91
  version_requirements: !ruby/object:Gem::Requirement
65
92
  requirements:
66
93
  - - "~>"
67
94
  - !ruby/object:Gem::Version
68
- version: '1.6'
95
+ version: '1.0'
69
96
  - !ruby/object:Gem::Dependency
70
97
  name: shoulda-context
71
98
  requirement: !ruby/object:Gem::Requirement
@@ -95,34 +122,33 @@ dependencies:
95
122
  - !ruby/object:Gem::Version
96
123
  version: '1.0'
97
124
  - !ruby/object:Gem::Dependency
98
- name: amazing_print
125
+ name: rake
99
126
  requirement: !ruby/object:Gem::Requirement
100
127
  requirements:
101
128
  - - "~>"
102
129
  - !ruby/object:Gem::Version
103
- version: '1.4'
130
+ version: '13.0'
104
131
  type: :development
105
132
  prerelease: false
106
133
  version_requirements: !ruby/object:Gem::Requirement
107
134
  requirements:
108
135
  - - "~>"
109
136
  - !ruby/object:Gem::Version
110
- version: '1.4'
137
+ version: '13.0'
111
138
  - !ruby/object:Gem::Dependency
112
139
  name: rubycritic
113
140
  requirement: !ruby/object:Gem::Requirement
114
141
  requirements:
115
142
  - - "~>"
116
143
  - !ruby/object:Gem::Version
117
- version: '4.7'
144
+ version: '4.0'
118
145
  type: :development
119
146
  prerelease: false
120
147
  version_requirements: !ruby/object:Gem::Requirement
121
148
  requirements:
122
149
  - - "~>"
123
150
  - !ruby/object:Gem::Version
124
- version: '4.7'
125
- description:
151
+ version: '4.0'
126
152
  email:
127
153
  - fps.vogel@gmail.com
128
154
  executables:
@@ -173,7 +199,7 @@ files:
173
199
  - lib/reading/stats/grouping.rb
174
200
  - lib/reading/stats/operation.rb
175
201
  - lib/reading/stats/query.rb
176
- - lib/reading/stats/terminal_result_formatters.rb
202
+ - lib/reading/stats/result_formatters.rb
177
203
  - lib/reading/util/blank.rb
178
204
  - lib/reading/util/exclude.rb
179
205
  - lib/reading/util/hash_array_deep_fetch.rb
@@ -189,24 +215,22 @@ metadata:
189
215
  allowed_push_host: https://rubygems.org
190
216
  homepage_uri: https://github.com/fpsvogel/reading
191
217
  source_code_uri: https://github.com/fpsvogel/reading
192
- changelog_uri: https://github.com/fpsvogel/reading/blob/master/CHANGELOG.md
193
- post_install_message:
218
+ changelog_uri: https://github.com/fpsvogel/reading/blob/main/CHANGELOG.md
194
219
  rdoc_options: []
195
220
  require_paths:
196
221
  - lib
197
222
  required_ruby_version: !ruby/object:Gem::Requirement
198
223
  requirements:
199
- - - ">="
224
+ - - "~>"
200
225
  - !ruby/object:Gem::Version
201
- version: 3.0.0
226
+ version: 3.4.4
202
227
  required_rubygems_version: !ruby/object:Gem::Requirement
203
228
  requirements:
204
229
  - - ">="
205
230
  - !ruby/object:Gem::Version
206
231
  version: '0'
207
232
  requirements: []
208
- rubygems_version: 3.4.9
209
- signing_key:
233
+ rubygems_version: 3.6.7
210
234
  specification_version: 4
211
235
  summary: Parses a CSV reading log.
212
236
  test_files: []