kovid 0.6.8 → 0.6.9

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: 68cf72c0e99add59625ce1a9763db32b5eeecb69220d78b236e929f08adb1dec
4
- data.tar.gz: 84d95391d43e67b62f865f6e0ab585700aae3790e1f968793d11a99bf02e6ce8
3
+ metadata.gz: aa46d5f734b53509d084570bc4a0abc2527d02320ea67c9a85120389492a0d64
4
+ data.tar.gz: 72c0dd54efb153df1996c238a74f42bec0c46062876669051e346f4906feba38
5
5
  SHA512:
6
- metadata.gz: daf6517f2d15ab2670bb9ad1124faa683db07eb3308a37d057b6af08b0d5a3f2ada1a4f76f54048556878df14435a71a82632a2995c28a6c830755aff7263338
7
- data.tar.gz: 77862be6a1adf08d40568326bcf24a4aa1ae0c60ad5f0b462b7ef3e5e1b64292c812e0c96b47d70702dad2635ee3640739883a5afbd28b2e2411b2488a23c279
6
+ metadata.gz: d61d1956c6f309ad70beeb8fe1289bb9e7c15c0b8b26c7ddd72304e888803681f529bdb1c091be603351271b981d8e4b2e0f033972996bed4580aa077d8b4c4a
7
+ data.tar.gz: 82d702ef83e0307424191235d239cc27aad835e0191677e0540cecf359a3756e427fa6c427036e70d2550ef0c08679966d7d21b33bc2b7e691f603e33077bec4
data/Gemfile CHANGED
@@ -6,4 +6,4 @@ source 'https://rubygems.org'
6
6
  gemspec
7
7
 
8
8
  gem 'rake', '~> 12.0'
9
- gem 'rspec', '~> 3.0'
9
+ gem 'rspec', '~> 3.0'
data/Gemfile.lock CHANGED
@@ -2,7 +2,6 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  kovid (0.6.8)
5
- ascii_charts (~> 0.9.1)
6
5
  carmen (~> 1.1.3)
7
6
  rainbow (~> 3.0)
8
7
  terminal-table (~> 1.8)
@@ -18,7 +17,6 @@ GEM
18
17
  minitest (~> 5.1)
19
18
  tzinfo (~> 1.1)
20
19
  zeitwerk (~> 2.2)
21
- ascii_charts (0.9.1)
22
20
  carmen (1.1.3)
23
21
  activesupport (>= 3.0.0)
24
22
  concurrent-ruby (1.1.6)
data/README.md CHANGED
@@ -74,6 +74,7 @@ ___
74
74
  😷 **History**
75
75
  * `kovid history COUNTRY` (full history).
76
76
  * `kovid history COUNTRY N` (history in the last N days).
77
+ * `kovid history STATE --usa`
77
78
  ___
78
79
 
79
80
  **NOTE:** If you find it irritating to have to type `kovid state STATE`, `covid state STATE` works as well.
data/kovid.gemspec CHANGED
@@ -22,12 +22,11 @@ Gem::Specification.new do |spec|
22
22
  spec.metadata['source_code_uri'] = 'https://github.com/siaw23/kovid'
23
23
  spec.metadata['changelog_uri'] = 'https://github.com/siaw23/kovid'
24
24
 
25
- spec.add_dependency 'ascii_charts', '~> 0.9.1'
25
+ spec.add_dependency 'carmen', '~> 1.1.3'
26
26
  spec.add_dependency 'rainbow', '~> 3.0'
27
27
  spec.add_dependency 'terminal-table', '~> 1.8'
28
28
  spec.add_dependency 'thor', '~> 1.0'
29
29
  spec.add_dependency 'typhoeus', '~> 1.3'
30
- spec.add_dependency 'carmen', '~> 1.1.3'
31
30
  spec.add_development_dependency 'simplecov', '~> 0.18'
32
31
 
33
32
  # Specify which files should be added to the gem when it is released.
data/lib/kovid.rb CHANGED
@@ -68,8 +68,12 @@ module Kovid
68
68
  Kovid::Request.cases
69
69
  end
70
70
 
71
- def history(country, last)
72
- Kovid::Request.history(country, last)
71
+ def history(country, days=30)
72
+ Kovid::Request.history(country, days)
73
+ end
74
+
75
+ def history_us_state(state, days=30)
76
+ Kovid::Request.history_us_state(state, days)
73
77
  end
74
78
 
75
79
  def histogram(country, date)
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2011 Ben Lund
4
+
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Kovid
24
+ module AsciiCharts
25
+ VERSION = '0.9.1'
26
+
27
+ class Chart
28
+ attr_reader :options, :data
29
+
30
+ DEFAULT_MAX_Y_VALS = 20
31
+ DEFAULT_MIN_Y_VALS = 10
32
+
33
+ # data is a sorted array of [x, y] pairs
34
+
35
+ def initialize(data, options = {})
36
+ @data = data
37
+ @options = options
38
+ end
39
+
40
+ def rounded_data
41
+ @rounded_data ||= data.map { |pair| [pair[0], round_value(pair[1])] }
42
+ end
43
+
44
+ def step_size
45
+ unless defined? @step_size
46
+ if options[:y_step_size]
47
+ @step_size = options[:y_step_size]
48
+ else
49
+ max_y_vals = options[:max_y_vals] || DEFAULT_MAX_Y_VALS
50
+ min_y_vals = options[:max_y_vals] || DEFAULT_MIN_Y_VALS
51
+ y_span = (max_yval - min_yval).to_f
52
+
53
+ step_size = nearest_step(y_span.to_f / (data.size + 1))
54
+
55
+ if @all_ints && (step_size < 1)
56
+ step_size = 1
57
+ else
58
+ while (y_span / step_size) < min_y_vals
59
+ candidate_step_size = next_step_down(step_size)
60
+ if @all_ints && (candidate_step_size < 1)
61
+ break
62
+ end ## don't go below one
63
+
64
+ step_size = candidate_step_size
65
+ end
66
+ end
67
+
68
+ # go up if we undershot, or were never over
69
+ while (y_span / step_size) > max_y_vals
70
+ step_size = next_step_up(step_size)
71
+ end
72
+ @step_size = step_size
73
+ end
74
+ if !@all_ints && @step_size.is_a?(Integer)
75
+ @step_size = @step_size.to_f
76
+ end
77
+ end
78
+ @step_size
79
+ end
80
+
81
+ STEPS = [1, 2, 5].freeze
82
+
83
+ def from_step(val)
84
+ if val == 0
85
+ [0, 0]
86
+ else
87
+ order = Math.log10(val).floor.to_i
88
+ num = (val / (10**order))
89
+ [num, order]
90
+ end
91
+ end
92
+
93
+ def to_step(num, order)
94
+ s = num * (10**order)
95
+ if order < 0
96
+ s.to_f
97
+ else
98
+ s
99
+ end
100
+ end
101
+
102
+ def nearest_step(val)
103
+ num, order = from_step(val)
104
+ to_step(2, order) # #@@
105
+ end
106
+
107
+ def next_step_up(val)
108
+ num, order = from_step(val)
109
+ next_index = STEPS.index(num.to_i) + 1
110
+ if STEPS.size == next_index
111
+ next_index = 0
112
+ order += 1
113
+ end
114
+ to_step(STEPS[next_index], order)
115
+ end
116
+
117
+ def next_step_down(val)
118
+ num, order = from_step(val)
119
+ next_index = STEPS.index(num.to_i) - 1
120
+ if next_index == -1
121
+ STEPS.size - 1
122
+ order -= 1
123
+ end
124
+ to_step(STEPS[next_index], order)
125
+ end
126
+
127
+ # round to nearest step size, making sure we curtail precision to same order of magnitude as the step size to avoid 0.4 + 0.2 = 0.6000000000000001
128
+ def round_value(val)
129
+ remainder = val % step_size
130
+ unprecised = if (remainder * 2) >= step_size
131
+ (val - remainder) + step_size
132
+ else
133
+ val - remainder
134
+ end
135
+ if step_size < 1
136
+ precision = -Math.log10(step_size).floor
137
+ (unprecised * (10**precision)).to_i.to_f / (10**precision)
138
+ else
139
+ unprecised
140
+ end
141
+ end
142
+
143
+ def max_yval
144
+ scan_data unless defined? @max_yval
145
+ @max_yval
146
+ end
147
+
148
+ def min_yval
149
+ scan_data unless defined? @min_yval
150
+ @min_yval
151
+ end
152
+
153
+ def all_ints
154
+ scan_data unless defined? @all_ints
155
+ @all_ints
156
+ end
157
+
158
+ def scan_data
159
+ @max_yval = 0
160
+ @min_yval = 0
161
+ @all_ints = true
162
+
163
+ @max_xval_width = 1
164
+
165
+ data.each do |pair|
166
+ @max_yval = pair[1] if pair[1] > @max_yval
167
+ @min_yval = pair[1] if pair[1] < @min_yval
168
+ @all_ints = false if @all_ints && !pair[1].is_a?(Integer)
169
+
170
+ if (xw = pair[0].to_s.length) > @max_xval_width
171
+ @max_xval_width = xw
172
+ end
173
+ end
174
+ end
175
+
176
+ def max_xval_width
177
+ scan_data unless defined? @max_xval_width
178
+ @max_xval_width
179
+ end
180
+
181
+ def max_yval_width
182
+ scan_y_range unless defined? @max_yval_width
183
+ @max_yval_width
184
+ end
185
+
186
+ def scan_y_range
187
+ @max_yval_width = 1
188
+
189
+ y_range.each do |yval|
190
+ if (yw = yval.to_s.length) > @max_yval_width
191
+ @max_yval_width = yw
192
+ end
193
+ end
194
+ end
195
+
196
+ def y_range
197
+ unless defined? @y_range
198
+ @y_range = []
199
+ first_y = round_value(min_yval)
200
+ first_y -= step_size if first_y > min_yval
201
+ last_y = round_value(max_yval)
202
+ last_y += step_size if last_y < max_yval
203
+ current_y = first_y
204
+ while current_y <= last_y
205
+ @y_range << current_y
206
+ current_y = round_value(current_y + step_size) ## to avoid fp arithmetic oddness
207
+ end
208
+ end
209
+ @y_range
210
+ end
211
+
212
+ def lines
213
+ raise 'lines must be overridden'
214
+ end
215
+
216
+ def draw
217
+ lines.join("\n")
218
+ end
219
+
220
+ def to_string
221
+ draw
222
+ end
223
+ end
224
+
225
+ class Cartesian < Chart
226
+ def lines
227
+ return [[' ', options[:title], ' ', '|', '+-', ' ']] if data.empty?
228
+
229
+ lines = [' ']
230
+
231
+ bar_width = max_xval_width + 1
232
+
233
+ lines << (' ' * max_yval_width) + ' ' + rounded_data.map { |pair| pair[0].to_s.center(bar_width) }.join('')
234
+
235
+ y_range.each_with_index do |current_y, i|
236
+ yval = current_y.to_s
237
+ bar = if i == 0
238
+ '+'
239
+ else
240
+ '|'
241
+ end
242
+ current_line = [(' ' * (max_yval_width - yval.length)) + "#{current_y}#{bar}"]
243
+
244
+ rounded_data.each do |pair|
245
+ marker = if (i == 0) && options[:hide_zero]
246
+ '-'
247
+ else
248
+ '*'
249
+ end
250
+ filler = if i == 0
251
+ '-'
252
+ else
253
+ ' '
254
+ end
255
+ comparison = if options[:bar]
256
+ current_y <= pair[1]
257
+ else
258
+ current_y == pair[1]
259
+ end
260
+ current_line << if comparison
261
+ marker.center(bar_width, filler)
262
+ else
263
+ filler * bar_width
264
+ end
265
+ end
266
+ lines << current_line.join('')
267
+ current_y += step_size
268
+ end
269
+ lines << ' '
270
+ lines << options[:title].center(lines[1].length) if options[:title]
271
+ lines << ' '
272
+ lines.reverse
273
+ end
274
+ end
275
+ end
276
+ end
data/lib/kovid/cli.rb CHANGED
@@ -75,13 +75,15 @@ module Kovid
75
75
  data_source
76
76
  end
77
77
 
78
- desc 'history COUNTRY or history COUNTRY N',
79
- 'Return history of incidents of COUNTRY (in the last N days)'
80
- def history(*params)
81
- if params.size == 2
82
- puts Kovid.history(params.first, params.last)
78
+ desc 'history COUNTRY or history COUNTRY N or' \
79
+ 'history STATE --usa',
80
+ 'Return history of incidents of COUNTRY|STATE (in the last N days)'
81
+ option :usa, :type => :boolean
82
+ def history(location, days=30)
83
+ if options[:usa]
84
+ puts Kovid.history_us_state(location, days)
83
85
  else
84
- puts Kovid.history(params.first, nil)
86
+ puts Kovid.history(location, days)
85
87
  end
86
88
  data_source
87
89
  end
@@ -145,8 +147,8 @@ module Kovid
145
147
  source = <<~TEXT
146
148
  #{Time.now}
147
149
  Sources:
148
- * JHU CSSE GISand Data
149
- * https://www.worldometers.info/coronavirus/
150
+ * Johns Hopkins University
151
+ * https://www.worldometers.info/coronavirus
150
152
  TEXT
151
153
  puts source
152
154
  end
@@ -23,6 +23,12 @@ module Kovid
23
23
  'Recovered'.paint_green
24
24
  ].freeze
25
25
 
26
+ DATE_CASES_DEATHS = [
27
+ 'Date'.paint_white,
28
+ 'Cases'.paint_white,
29
+ 'Deaths'.paint_red
30
+ ].freeze
31
+
26
32
  CONTINENTAL_AGGREGATE_HEADINGS = [
27
33
  'Cases'.paint_white,
28
34
  'Cases Today'.paint_white,
@@ -93,7 +99,13 @@ module Kovid
93
99
  'Recovered'.paint_green
94
100
  ].freeze
95
101
 
96
- FOOTER_LINE = [
102
+ FOOTER_LINE_THREE_COLUMNS = [
103
+ '------------',
104
+ '------------',
105
+ '------------'
106
+ ].freeze
107
+
108
+ FOOTER_LINE_FOUR_COLUMNS = [
97
109
  '------------',
98
110
  '------------',
99
111
  '------------',
@@ -3,24 +3,15 @@
3
3
  module Kovid
4
4
  module Historians
5
5
  include Constants
6
+ include AsciiCharts
6
7
 
7
- def history(country, last)
8
- # TODO: Write checks for when country is spelt wrong.
8
+ def history(location, days)
9
9
  rows = []
10
10
 
11
- stats = if last
12
- Kovid.format_country_history_numbers(country).last(last.to_i)
13
- else
14
- Kovid.format_country_history_numbers(country)
15
- end
11
+ stats = Kovid.format_country_history_numbers(location).last(days.to_i)
12
+ dates = location['timeline']['cases'].keys.last(days.to_i)
16
13
 
17
- dates = if last
18
- country['timeline']['cases'].keys.last(last.to_i)
19
- else
20
- country['timeline']['cases'].keys
21
- end
22
-
23
- unless last
14
+ if days.to_i >= 30
24
15
  stats = stats.reject { |stat| stat[0].to_i.zero? && stat[1].to_i.zero? }
25
16
  dates = dates.last(stats.count)
26
17
  end
@@ -31,14 +22,25 @@ module Kovid
31
22
  rows << row
32
23
  end
33
24
 
25
+ # Title and Column format if Country or US State
26
+ if location['country']
27
+ title = location['country'].try(:upcase)
28
+ col_format = DATE_CASES_DEATHS_RECOVERED
29
+ footer = FOOTER_LINE_FOUR_COLUMNS
30
+ else
31
+ title = location['state'].try(:upcase)
32
+ col_format = DATE_CASES_DEATHS
33
+ footer = FOOTER_LINE_THREE_COLUMNS
34
+ end
35
+
34
36
  if stats.size > 10
35
- rows << FOOTER_LINE
36
- rows << DATE_CASES_DEATHS_RECOVERED
37
+ rows << footer
38
+ rows << col_format
37
39
  end
38
40
 
39
41
  Terminal::Table.new(
40
- title: country['country'].upcase,
41
- headings: DATE_CASES_DEATHS_RECOVERED,
42
+ title: title,
43
+ headings: col_format,
42
44
  rows: rows
43
45
  )
44
46
  end
@@ -88,7 +90,7 @@ module Kovid
88
90
  dates.each_with_index do |val, index|
89
91
  data << [val, positive_cases_figures[index]]
90
92
  end
91
- y_range = AsciiCharts::Cartesian.new(
93
+ y_range = Kovid::AsciiCharts::Cartesian.new(
92
94
  data, bar: true, hide_zero: true
93
95
  ).y_range
94
96
 
data/lib/kovid/request.rb CHANGED
@@ -8,9 +8,11 @@ require_relative 'uri_builder'
8
8
 
9
9
  module Kovid
10
10
  class Request
11
- COUNTRIES_PATH = UriBuilder.new('/v2/countries').url
12
- STATES_URL = UriBuilder.new('/v2/states').url
13
- JHUCSSE_URL = UriBuilder.new('/v2/jhucsse').url
11
+ COUNTRIES_PATH = UriBuilder.new('/v2/countries').url
12
+ STATES_URL = UriBuilder.new('/v2/states').url
13
+ JHUCSSE_URL = UriBuilder.new('/v2/jhucsse').url
14
+ HISTORICAL_URL = UriBuilder.new('/v2/historical').url
15
+ HISTORICAL_US_URL = UriBuilder.new('/v2/historical/usacounties').url
14
16
 
15
17
  SERVER_DOWN = 'Server overwhelmed. Please try again in a moment.'
16
18
 
@@ -158,19 +160,57 @@ module Kovid
158
160
  puts SERVER_DOWN
159
161
  end
160
162
 
161
- def history(country, last)
163
+ def history(country, days)
162
164
  history_path = UriBuilder.new('/v2/historical').url
165
+
163
166
  response = JSON.parse(
164
167
  Typhoeus.get(
165
168
  history_path + "/#{country}", cache_ttl: 900
166
169
  ).response_body
167
170
  )
168
171
 
169
- Kovid::Tablelize.history(response, last)
172
+ if response.key?('message')
173
+ not_found(country) do |c|
174
+ "Could not find cases for #{c}.\nIf searching United States, add --usa option"
175
+ end
176
+ else
177
+ Kovid::Tablelize.history(response, days)
178
+ end
170
179
  rescue JSON::ParserError
171
180
  puts SERVER_DOWN
172
181
  end
173
182
 
183
+ def history_us_state(state, days)
184
+ history_path = UriBuilder.new('/v2/historical/usacounties').url
185
+ state = Kovid.lookup_us_state(state).downcase()
186
+
187
+ response = JSON.parse(
188
+ Typhoeus.get(
189
+ history_path + "/#{state}", cache_ttl: 900
190
+ ).response_body
191
+ )
192
+
193
+ if response.respond_to?(:key?) and response.key?('message')
194
+ return not_found(state)
195
+ end
196
+
197
+ # API Endpoint returns list of counties for given state, so
198
+ # we aggreage cases for all counties
199
+ # Note: no data for 'Recovered'
200
+ cases = usacounties_aggregator(response, 'cases')
201
+ deaths = usacounties_aggregator(response, 'deaths')
202
+
203
+ # normalize data so we can call Kovid::Tablelize.history on US State data
204
+ response = {
205
+ "state" => state,
206
+ "timeline" => { "cases" => cases, "deaths" => deaths }
207
+ }
208
+
209
+ Kovid::Tablelize.history(response, days)
210
+ rescue JSON::ParserError
211
+ puts SERVER_DOWN
212
+ end
213
+
174
214
  def histogram(country, date)
175
215
  history_path = UriBuilder.new('/v2/historical').url
176
216
  response = JSON.parse(
@@ -188,9 +228,17 @@ module Kovid
188
228
 
189
229
  private
190
230
 
191
- def not_found(country)
192
- rows = [["Wrong spelling/No reported cases on #{country.upcase}."]]
193
- Terminal::Table.new title: "You checked: #{country.upcase}", rows: rows
231
+ def not_found(location)
232
+ rows = []
233
+ default_warning = "Wrong spelling/No reported cases on #{location.upcase}."
234
+
235
+ if block_given?
236
+ rows << [ yield(location) ]
237
+ else
238
+ rows << [ default_warning ]
239
+ end
240
+
241
+ Terminal::Table.new title: "You checked: #{location.upcase}", rows: rows
194
242
  end
195
243
 
196
244
  def fetch_countries(list)
@@ -278,6 +326,16 @@ module Kovid
278
326
  end
279
327
  end.compact
280
328
  end
329
+
330
+ def usacounties_aggregator(data, key=nil)
331
+ data.inject({}) do |base,other|
332
+ base.merge(other['timeline'][key]) do |k,l,r|
333
+ l ||= 0
334
+ l ||= 0
335
+ l + r
336
+ end
337
+ end.compact
338
+ end
281
339
  end
282
340
  end
283
341
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'terminal-table'
4
4
  require 'date'
5
- require 'ascii_charts'
5
+ require_relative 'ascii_charts'
6
6
  require_relative 'painter'
7
7
  require_relative 'constants'
8
8
  require_relative 'aggregators'
data/lib/kovid/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kovid
4
- VERSION = '0.6.8'
4
+ VERSION = '0.6.9'
5
5
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kovid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.8
4
+ version: 0.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emmanuel Hayford
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-17 00:00:00.000000000 Z
11
+ date: 2020-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: ascii_charts
14
+ name: carmen
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.9.1
19
+ version: 1.1.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.9.1
26
+ version: 1.1.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rainbow
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.3'
83
- - !ruby/object:Gem::Dependency
84
- name: carmen
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 1.1.3
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 1.1.3
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: simplecov
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -135,6 +121,7 @@ files:
135
121
  - kovid.gemspec
136
122
  - lib/kovid.rb
137
123
  - lib/kovid/aggregators.rb
124
+ - lib/kovid/ascii_charts.rb
138
125
  - lib/kovid/cache.rb
139
126
  - lib/kovid/cli.rb
140
127
  - lib/kovid/constants.rb