kovid 0.6.3 → 0.6.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c21479be2e8fdc2c40fd9f38d37808bd3a3d13ec36080119896fa95cc291d127
4
- data.tar.gz: 94431cdc81ea6de25240aada27cdf680a4bd6a37a88e060ba51b6197cac015bd
3
+ metadata.gz: 68cf72c0e99add59625ce1a9763db32b5eeecb69220d78b236e929f08adb1dec
4
+ data.tar.gz: 84d95391d43e67b62f865f6e0ab585700aae3790e1f968793d11a99bf02e6ce8
5
5
  SHA512:
6
- metadata.gz: 865a466405a2b6be0068781dc4f11f1573c761fc9bde7994ed32f28573842b95df4cbcbd609436e1c1713c05ac5564fb582755b35e7586af938df145b77e5bf4
7
- data.tar.gz: b477fc309bd688bc7195e90cb3e4bcfd201a37a38170abbb95aaa018d89e9afa18bae3e35a1dddf7211adab8f00d483c13984597f837bb4a98cdeca9a1c3d00c
6
+ metadata.gz: daf6517f2d15ab2670bb9ad1124faa683db07eb3308a37d057b6af08b0d5a3f2ada1a4f76f54048556878df14435a71a82632a2995c28a6c830755aff7263338
7
+ data.tar.gz: 77862be6a1adf08d40568326bcf24a4aa1ae0c60ad5f0b462b7ef3e5e1b64292c812e0c96b47d70702dad2635ee3640739883a5afbd28b2e2411b2488a23c279
@@ -0,0 +1,7 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.6
5
+
6
+ Style/Documentation:
7
+ Enabled: false
@@ -0,0 +1,59 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2020-04-07 20:38:28 -0300 using RuboCop version 0.67.2.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ Metrics/AbcSize:
11
+ Max: 54
12
+ Exclude:
13
+ - 'lib/kovid/historians.rb'
14
+
15
+ # Offense count: 2
16
+ Metrics/BlockLength:
17
+ Exclude:
18
+ - 'kovid.gemspec'
19
+ - 'spec/kovid_spec.rb'
20
+
21
+ # Offense count: 3
22
+ # Configuration parameters: CountComments.
23
+ Metrics/ClassLength:
24
+ Max: 220
25
+ Exclude:
26
+ - 'lib/kovid/cli.rb'
27
+ - 'lib/kovid/request.rb'
28
+ - 'lib/kovid/tablelize.rb'
29
+
30
+ # Offense count: 2
31
+ # Configuration parameters: CountComments, ExcludedMethods.
32
+ Metrics/MethodLength:
33
+ Max: 44
34
+ Exclude:
35
+ - 'lib/kovid/historians.rb'
36
+
37
+ # Offense count: 1
38
+ Metrics/PerceivedComplexity:
39
+ Max: 8
40
+ Exclude:
41
+ - 'lib/kovid/historians.rb'
42
+
43
+ # Offense count: 1
44
+ Style/CaseEquality:
45
+ Exclude:
46
+ - 'lib/kovid/request.rb'
47
+
48
+ Style/Documentation:
49
+ Exclude:
50
+ - 'spec/**/*'
51
+ - 'test/**/*'
52
+ - 'lib/kovid.rb'
53
+ - 'lib/kovid/helpers.rb'
54
+
55
+ # Offense count: 5
56
+ Style/MultilineBlockChain:
57
+ Exclude:
58
+ - 'lib/kovid/historians.rb'
59
+ - 'lib/kovid/request.rb'
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'
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kovid (0.6.2)
4
+ kovid (0.6.8)
5
5
  ascii_charts (~> 0.9.1)
6
+ carmen (~> 1.1.3)
6
7
  rainbow (~> 3.0)
7
8
  terminal-table (~> 1.8)
8
9
  thor (~> 1.0)
@@ -11,12 +12,24 @@ PATH
11
12
  GEM
12
13
  remote: https://rubygems.org/
13
14
  specs:
15
+ activesupport (6.0.2.2)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 0.7, < 2)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ zeitwerk (~> 2.2)
14
21
  ascii_charts (0.9.1)
22
+ carmen (1.1.3)
23
+ activesupport (>= 3.0.0)
24
+ concurrent-ruby (1.1.6)
15
25
  diff-lcs (1.3)
16
26
  docile (1.3.2)
17
27
  ethon (0.12.0)
18
28
  ffi (>= 1.3.0)
19
29
  ffi (1.12.2)
30
+ i18n (1.8.2)
31
+ concurrent-ruby (~> 1.0)
32
+ minitest (5.14.0)
20
33
  rainbow (3.0.0)
21
34
  rake (12.3.3)
22
35
  rspec (3.9.0)
@@ -39,9 +52,13 @@ GEM
39
52
  terminal-table (1.8.0)
40
53
  unicode-display_width (~> 1.1, >= 1.1.1)
41
54
  thor (1.0.1)
55
+ thread_safe (0.3.6)
42
56
  typhoeus (1.3.1)
43
57
  ethon (>= 0.9.0)
58
+ tzinfo (1.2.7)
59
+ thread_safe (~> 0.1)
44
60
  unicode-display_width (1.7.0)
61
+ zeitwerk (2.3.0)
45
62
 
46
63
  PLATFORMS
47
64
  ruby
data/README.md CHANGED
@@ -46,6 +46,8 @@ You can fetch US state-specific data:
46
46
  * `kovid state STATE` OR `kovid state "STATE NAME"`.
47
47
  * `kovid states --all` or `kovid states -a` for data on all US states.
48
48
 
49
+ You can also use USPS abbreviations. Example: `kovid state me`
50
+
49
51
  Provinces
50
52
 
51
53
  You can fetch province specific data:
@@ -64,7 +66,7 @@ You can compare as many countries as you want; `kovid compare FOO BAR BAZ` OR `k
64
66
  🇺🇸🇺🇸🇺🇸
65
67
 
66
68
  You can compare US states with:
67
- * `kovid states STATE STATE` Example: `kovid states illinois "new york" california`
69
+ * `kovid states STATE STATE` Example: `kovid states illinois "new york" california` OR `kovid states il ny ca`
68
70
 
69
71
  You can compare provicnes with:
70
72
  * `kovid provinces PROVINCE PROVINCE` Example: `kovid provinces ontario manitoba`
data/Rakefile CHANGED
@@ -7,3 +7,4 @@ RSpec::Core::RakeTask.new(:spec)
7
7
 
8
8
  # rubocop:disable Style/HashSyntax
9
9
  task :default => :spec
10
+ # rubocop:enable Style/HashSyntax
@@ -8,8 +8,10 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Emmanuel Hayford']
9
9
  spec.email = ['siawmensah@gmail.com']
10
10
 
11
- spec.summary = 'A CLI to fetch and compare the 2019 coronavirus pandemic statistics.'
12
- spec.description = 'A CLI to fetch and compare the 2019 coronavirus pandemic statistics.'
11
+ summary = 'A CLI to fetch and compare the 2019 ' \
12
+ 'coronavirus pandemic statistics.'
13
+ spec.summary = summary
14
+ spec.description = summary
13
15
  spec.homepage = 'https://github.com/siaw23/kovid'
14
16
  spec.license = 'MIT'
15
17
  spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
@@ -25,13 +27,16 @@ Gem::Specification.new do |spec|
25
27
  spec.add_dependency 'terminal-table', '~> 1.8'
26
28
  spec.add_dependency 'thor', '~> 1.0'
27
29
  spec.add_dependency 'typhoeus', '~> 1.3'
28
-
30
+ spec.add_dependency 'carmen', '~> 1.1.3'
29
31
  spec.add_development_dependency 'simplecov', '~> 0.18'
30
32
 
31
33
  # Specify which files should be added to the gem when it is released.
32
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
34
+ # The `git ls-files -z` loads the files in the RubyGem
35
+ # that have been added into git.
33
36
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
34
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
37
+ `git ls-files -z`.split("\x0").reject do |f|
38
+ f.match(%r{^(test|spec|features)/})
39
+ end
35
40
  end
36
41
  spec.bindir = 'exe'
37
42
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -6,8 +6,6 @@ require 'kovid/request'
6
6
  module Kovid
7
7
  require 'kovid/helpers'
8
8
 
9
- class Error < StandardError; end
10
-
11
9
  module_function
12
10
 
13
11
  def eu_aggregate
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'typhoeus'
4
-
5
4
  module Kovid
6
5
  class Cache
7
6
  def initialize
@@ -9,20 +9,26 @@ module Kovid
9
9
  true
10
10
  end
11
11
 
12
- desc 'province PROVINCE or province "PROVINCE NAME"', 'Returns reported data on provided province. eg "kovid check "new brunswick".'
12
+ desc 'province PROVINCE or province "PROVINCE NAME"',
13
+ 'Returns reported data on provided province. ' \
14
+ 'eg "kovid check "new brunswick".'
13
15
  method_option :full, aliases: '-p'
14
16
  def province(name)
15
17
  puts Kovid.province(name)
16
18
  data_source
17
19
  end
18
20
 
19
- desc 'provinces PROVINCE PROVINCE', 'Returns full comparison table for the given provinces. Accepts multiple provinces.'
21
+ desc 'provinces PROVINCE PROVINCE',
22
+ 'Returns full comparison table for the given provinces. ' \
23
+ 'Accepts multiple provinces.'
20
24
  def provinces(*names)
21
25
  puts Kovid.provinces(names)
22
26
  data_source
23
27
  end
24
28
 
25
- desc 'check COUNTRY or check "COUNTRY NAME"', 'Returns reported data on provided country. eg: "kovid check "hong kong".'
29
+ desc 'check COUNTRY or check "COUNTRY NAME"',
30
+ 'Returns reported data on provided country. ' \
31
+ 'eg: "kovid check "hong kong".'
26
32
  method_option :full, aliases: '-f'
27
33
  def check(*name)
28
34
  if name.size == 1
@@ -48,18 +54,18 @@ module Kovid
48
54
  data_source
49
55
  end
50
56
 
51
- desc 'states STATE STATE', 'Returns full comparison table for the given states. Accepts multiple states.'
57
+ desc 'states STATE STATE or states --all',
58
+ 'Returns full comparison table for the given states. ' \
59
+ 'Accepts multiple states.'
60
+ method_option :all, aliases: '-a'
52
61
  def states(*states)
53
- downcased_states = states.map(&:downcase)
54
-
55
- puts Kovid.states(downcased_states)
56
- data_source
57
- end
62
+ if options[:all]
63
+ puts Kovid.all_us_states
64
+ else
65
+ downcased_states = states.map(&:downcase)
66
+ puts Kovid.states(downcased_states)
67
+ end
58
68
 
59
- desc 'states -a', 'Returns full comparison table for all US states'
60
- method_option :all, aliases: '-a'
61
- def states
62
- puts Kovid.all_us_states
63
69
  data_source
64
70
  end
65
71
 
@@ -69,7 +75,8 @@ module Kovid
69
75
  data_source
70
76
  end
71
77
 
72
- desc 'history COUNTRY or history COUNTRY N', 'Return history of incidents of COUNTRY (in the last N days)'
78
+ desc 'history COUNTRY or history COUNTRY N',
79
+ 'Return history of incidents of COUNTRY (in the last N days)'
73
80
  def history(*params)
74
81
  if params.size == 2
75
82
  puts Kovid.history(params.first, params.last)
@@ -63,6 +63,20 @@ module Kovid
63
63
  'Cases/Million'.paint_white
64
64
  ].freeze
65
65
 
66
+ FULL_PROVINCE_TABLE_HEADINGS = [
67
+ 'Confirmed'.paint_white,
68
+ 'Deaths'.paint_red,
69
+ 'Recovered'.paint_green
70
+ ].freeze
71
+
72
+ FULL_STATE_TABLE_HEADINGS = [
73
+ 'Cases'.paint_white,
74
+ 'Cases Today'.paint_white,
75
+ 'Deaths'.paint_red,
76
+ 'Deaths Today'.paint_red,
77
+ 'Active'.paint_yellow
78
+ ].freeze
79
+
66
80
  COMPARE_STATES_HEADINGS = [
67
81
  'State'.paint_white,
68
82
  'Cases'.paint_white,
@@ -79,7 +93,13 @@ module Kovid
79
93
  'Recovered'.paint_green
80
94
  ].freeze
81
95
 
82
- FOOTER_LINE = ['------------', '------------', '------------', '------------'].freeze
96
+ FOOTER_LINE = [
97
+ '------------',
98
+ '------------',
99
+ '------------',
100
+ '------------'
101
+ ].freeze
102
+
83
103
  COUNTRY_LETTERS = 'A'.upto('Z').with_index(127_462).to_h.freeze
84
104
 
85
105
  RIGHT_ALIGN_COLUMNS = {
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'terminal-table'
4
+
4
5
  module Kovid
5
6
  module_function
6
7
 
@@ -14,4 +15,25 @@ module Kovid
14
15
  date_to_parse = Date.strptime(date, '%m/%d/%y').to_s
15
16
  Date.parse(date_to_parse).strftime('%d %b, %y')
16
17
  end
18
+
19
+ def comma_delimit(number)
20
+ number.to_s.chars.to_a.reverse.each_slice(3).map(&:join).join(',').reverse
21
+ end
22
+
23
+ # Insert + sign to format positive numbers
24
+ def add_plus_sign(num)
25
+ num.to_i.positive? ? "+#{comma_delimit(num)}" : comma_delimit(num).to_s
26
+ end
27
+
28
+ def format_country_history_numbers(load)
29
+ load['timeline'].values.map(&:values).transpose.each do |data|
30
+ data.map! { |number| Kovid.comma_delimit(number) }
31
+ end
32
+ end
33
+
34
+ def lookup_us_state(state)
35
+ us = Carmen::Country.coded('USA')
36
+ lookup = us.subregions.coded(state) || us.subregions.named(state)
37
+ lookup ? lookup.name : state
38
+ end
17
39
  end
@@ -5,14 +5,13 @@ module Kovid
5
5
  include Constants
6
6
 
7
7
  def history(country, last)
8
- # Write checks for when country is spelt wrong.
9
- headings = DATE_CASES_DEATHS_RECOVERED
8
+ # TODO: Write checks for when country is spelt wrong.
10
9
  rows = []
11
10
 
12
11
  stats = if last
13
- transpose(country).last(last.to_i)
12
+ Kovid.format_country_history_numbers(country).last(last.to_i)
14
13
  else
15
- transpose(country)
14
+ Kovid.format_country_history_numbers(country)
16
15
  end
17
16
 
18
17
  dates = if last
@@ -39,7 +38,7 @@ module Kovid
39
38
 
40
39
  Terminal::Table.new(
41
40
  title: country['country'].upcase,
42
- headings: headings,
41
+ headings: DATE_CASES_DEATHS_RECOVERED,
43
42
  rows: rows
44
43
  )
45
44
  end
@@ -53,8 +52,9 @@ module Kovid
53
52
  end
54
53
 
55
54
  # From dates where number of !cases.zero?
56
- positive_cases_figures = country['timeline']['cases'].values.reject(&:zero?)
57
- dates = country['timeline']['cases'].reject { |_k, v| v.zero? }.keys
55
+ country_cases = country['timeline']['cases']
56
+ positive_cases_figures = country_cases.values.reject(&:zero?)
57
+ dates = country_cases.reject { |_k, v| v.zero? }.keys
58
58
  data = []
59
59
 
60
60
  # TODO: Refactor
@@ -88,12 +88,16 @@ module Kovid
88
88
  dates.each_with_index do |val, index|
89
89
  data << [val, positive_cases_figures[index]]
90
90
  end
91
- y_range = AsciiCharts::Cartesian.new(data, bar: true, hide_zero: true).y_range
91
+ y_range = AsciiCharts::Cartesian.new(
92
+ data, bar: true, hide_zero: true
93
+ ).y_range
92
94
 
93
95
  last_two_y = y_range.last 2
94
96
  y_interval = last_two_y.last - last_two_y.first
95
97
 
96
- scale("Scale on Y: #{y_interval}:#{(y_interval / last_two_y.last.to_f * positive_cases_figures.last).round(2) / y_interval}")
98
+ scale("Scale on Y: #{y_interval}:#{(
99
+ y_interval / last_two_y.last.to_f * positive_cases_figures.last
100
+ ).round(2) / y_interval}")
97
101
 
98
102
  puts 'Experimental feature, please report issues.'
99
103
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rainbow'
4
-
5
4
  class String
6
5
  def paint_white
7
6
  Rainbow(self).white.bg(:black).bold
@@ -1,30 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require 'carmen'
4
5
  require_relative 'tablelize'
5
6
  require_relative 'cache'
6
7
  require_relative 'uri_builder'
7
8
 
8
9
  module Kovid
9
10
  class Request
10
- COUNTRIES_PATH = UriBuilder.new('/countries').url
11
- STATES_URL = UriBuilder.new('/states').url
11
+ COUNTRIES_PATH = UriBuilder.new('/v2/countries').url
12
+ STATES_URL = UriBuilder.new('/v2/states').url
12
13
  JHUCSSE_URL = UriBuilder.new('/v2/jhucsse').url
13
14
 
14
15
  SERVER_DOWN = 'Server overwhelmed. Please try again in a moment.'
15
16
 
16
17
  EU_ISOS = %w[AT BE BG CY CZ DE DK EE ES FI FR GR HR HU IE IT LT \
17
18
  LU LV MT NL PL PT RO SE SI SK].freeze
18
- EUROPE_ISOS = EU_ISOS + %w[GB IS NO CH MC AD SM VA BA RS ME MK AL\
19
- BY UA RU MD]
19
+ EUROPE_ISOS = EU_ISOS + %w[GB IS NO CH MC AD SM VA BA RS ME MK AL \
20
+ BY UA RU MD].freeze
20
21
  AFRICA_ISOS = %w[DZ AO BJ BW BF BI CM CV CF TD KM CD CG CI DJ EG \
21
- GQ ER SZ ET GA GM GH GN GW KE LS LR LY MG MW ML MR MU MA MZ NA NE \
22
- NG RW ST SN SC SL SO ZA SS SD TZ TG TN UG ZM ZW EH].freeze
23
- SOUTH_AMERICA_ISOS = ['AR' 'BO', 'BV', 'BR', 'CL', 'CO', 'EC', \
24
- 'FK', 'GF', 'GY', 'PY', 'PE', 'GS', 'SR', 'UY', 'VE'].freeze
22
+ GQ ER SZ ET GA GM GH GN GW KE LS LR LY MG MW ML \
23
+ MR MU MA MZ NA NE NG RW ST SN SC SL SO ZA SS SD \
24
+ TZ TG TN UG ZM ZW EH].freeze
25
+ SOUTH_AMERICA_ISOS = %w[AR BO BV BR CL CO EC FK GF GY PY PE GS SR \
26
+ UY VE].freeze
25
27
  ASIA_ISOS = %w[AE AF AM AZ BD BH BN BT CC CN CX GE HK ID IL IN \
26
- IQ IR JO JP KG KH KP KR KW KZ LA LB LK MM MN MO MY NP OM PH PK \
27
- PS QA SA SG SY TH TJ TL TM TR TW UZ VN YE].freeze
28
+ IQ IR JO JP KG KH KP KR KW KZ LA LB LK MM MN MO \
29
+ MY NP OM PH PK PS QA SA SG SY TH TJ TL TM TR TW \
30
+ UZ VN YE].freeze
28
31
 
29
32
  class << self
30
33
  def eu_aggregate
@@ -69,26 +72,24 @@ module Kovid
69
72
 
70
73
  def by_country(country_name)
71
74
  response = fetch_country(country_name)
72
- Kovid::Tablelize.country_table(response)
73
75
 
74
- # if response.values.first.include?('not found')
75
- # not_found(country_name)
76
- # else
77
- # Kovid::Tablelize.country_table(response)
78
- # end
76
+ if response.key?('message')
77
+ not_found(country_name)
78
+ else
79
+ Kovid::Tablelize.country_table(response)
80
+ end
79
81
  rescue JSON::ParserError
80
82
  puts SERVER_DOWN
81
83
  end
82
84
 
83
85
  def by_country_full(country_name)
84
86
  response = fetch_country(country_name)
85
- Kovid::Tablelize.full_country_table(response)
86
87
 
87
- # if response.values.first.include?('not found')
88
- # not_found(country_name)
89
- # else
90
- # Kovid::Tablelize.full_country_table(response)
91
- # end
88
+ if response.key?('message')
89
+ not_found(country_name)
90
+ else
91
+ Kovid::Tablelize.full_country_table(response)
92
+ end
92
93
  rescue JSON::ParserError
93
94
  puts SERVER_DOWN
94
95
  end
@@ -109,7 +110,7 @@ module Kovid
109
110
  end
110
111
 
111
112
  def state(state)
112
- response = fetch_state(state)
113
+ response = fetch_state(Kovid.lookup_us_state(state))
113
114
  if response.nil?
114
115
  not_found(state)
115
116
  else
@@ -121,7 +122,6 @@ module Kovid
121
122
 
122
123
  def states(states)
123
124
  compared_states = fetch_compared_states(states)
124
-
125
125
  Kovid::Tablelize.compare_us_states(compared_states)
126
126
  rescue JSON::ParserError
127
127
  puts SERVER_DOWN
@@ -149,7 +149,9 @@ module Kovid
149
149
  end
150
150
 
151
151
  def cases
152
- response = JSON.parse(Typhoeus.get(UriBuilder.new('/all').url, cache_ttl: 900).response_body)
152
+ response = JSON.parse(
153
+ Typhoeus.get(UriBuilder.new('/v2/all').url, cache_ttl: 900).response_body
154
+ )
153
155
 
154
156
  Kovid::Tablelize.cases(response)
155
157
  rescue JSON::ParserError
@@ -158,7 +160,11 @@ module Kovid
158
160
 
159
161
  def history(country, last)
160
162
  history_path = UriBuilder.new('/v2/historical').url
161
- response = JSON.parse(Typhoeus.get(history_path + "/#{country}", cache_ttl: 900).response_body)
163
+ response = JSON.parse(
164
+ Typhoeus.get(
165
+ history_path + "/#{country}", cache_ttl: 900
166
+ ).response_body
167
+ )
162
168
 
163
169
  Kovid::Tablelize.history(response, last)
164
170
  rescue JSON::ParserError
@@ -167,7 +173,11 @@ module Kovid
167
173
 
168
174
  def histogram(country, date)
169
175
  history_path = UriBuilder.new('/v2/historical').url
170
- response = JSON.parse(Typhoeus.get(history_path + "/#{country}", cache_ttl: 900).response_body)
176
+ response = JSON.parse(
177
+ Typhoeus.get(
178
+ history_path + "/#{country}", cache_ttl: 900
179
+ ).response_body
180
+ )
171
181
 
172
182
  Kovid::Tablelize.histogram(response, date)
173
183
  end
@@ -185,14 +195,20 @@ module Kovid
185
195
 
186
196
  def fetch_countries(list)
187
197
  list.map do |country|
188
- JSON.parse(Typhoeus.get(COUNTRIES_PATH + "/#{country}", cache_ttl: 900).response_body)
198
+ JSON.parse(
199
+ Typhoeus.get(
200
+ COUNTRIES_PATH + "/#{country}", cache_ttl: 900
201
+ ).response_body
202
+ )
189
203
  end.sort_by { |json| -json['cases'] }
190
204
  end
191
205
 
192
206
  def fetch_compared_states(submitted_states)
193
- state_data = fetch_state_data
207
+ submitted_states.map! { |s| Kovid.lookup_us_state(s) }
194
208
 
195
- state_data.select { |state| submitted_states.include?(state['state'].downcase) }
209
+ fetch_state_data.select do |state|
210
+ submitted_states.include?(state['state'])
211
+ end
196
212
  end
197
213
 
198
214
  def fetch_state_data
@@ -200,6 +216,8 @@ module Kovid
200
216
  end
201
217
 
202
218
  def fetch_country(country_name)
219
+ # TODO: Match ISOs to full country names
220
+ country_name = 'nl' if country_name == 'netherlands'
203
221
  country_url = COUNTRIES_PATH + "/#{country_name}"
204
222
 
205
223
  JSON.parse(Typhoeus.get(country_url, cache_ttl: 900).response_body)
@@ -211,7 +229,9 @@ module Kovid
211
229
 
212
230
  def fetch_province(province)
213
231
  response = fetch_jhucsse
214
- response.select { |datum| datum['province'] == capitalize_words(province) }.first
232
+ response.select do |datum|
233
+ datum['province'] == capitalize_words(province)
234
+ end.first
215
235
  end
216
236
 
217
237
  def fetch_provinces(provinces)
@@ -221,19 +241,35 @@ module Kovid
221
241
  end
222
242
 
223
243
  def fetch_state(state)
224
- states_array = JSON.parse(Typhoeus.get(STATES_URL, cache_ttl: 900).response_body)
244
+ states_array = JSON.parse(
245
+ Typhoeus.get(STATES_URL, cache_ttl: 900).response_body
246
+ )
225
247
 
226
- states_array.select { |state_name| state_name['state'] == capitalize_words(state) }.first
248
+ states_array.select do |state_name|
249
+ state_name['state'] == capitalize_words(state)
250
+ end.first
227
251
  end
228
252
 
229
253
  def aggregator(isos, meth)
230
- countries_array = JSON.parse(Typhoeus.get(UriBuilder.new('/countries').url, cache_ttl: 900).response_body)
231
-
254
+ countries_array = JSON.parse(countries_request)
232
255
  country_array = countries_array.select do |hash|
233
256
  isos.include?(hash['countryInfo']['iso2'])
234
257
  end
258
+ data = countries_aggregator(country_array)
235
259
 
236
- data = country_array.inject do |base, other|
260
+ meth === data
261
+ rescue JSON::ParserError
262
+ puts SERVER_DOWN
263
+ end
264
+
265
+ def countries_request
266
+ Typhoeus.get(
267
+ UriBuilder.new('/v2/countries').url, cache_ttl: 900
268
+ ).response_body
269
+ end
270
+
271
+ def countries_aggregator(country_array)
272
+ country_array.inject do |base, other|
237
273
  base.merge(other) do |key, left, right|
238
274
  left ||= 0
239
275
  right ||= 0
@@ -241,10 +277,6 @@ module Kovid
241
277
  left + right unless %w[country countryInfo].include?(key)
242
278
  end
243
279
  end.compact
244
-
245
- meth === data
246
- rescue JSON::ParserError
247
- puts SERVER_DOWN
248
280
  end
249
281
  end
250
282
  end
@@ -16,120 +16,50 @@ module Kovid
16
16
 
17
17
  class << self
18
18
  def country_table(data)
19
- rows = [
20
- [
21
- comma_delimit(data['cases']),
22
- check_if_positve(data['todayCases']),
23
- comma_delimit(data['deaths']),
24
- check_if_positve(data['todayDeaths']),
25
- comma_delimit(data['recovered'])
26
- ]
27
- ]
28
-
29
- if (iso = data['countryInfo']['iso2'])
30
- Terminal::Table.new(title: "#{country_emoji(iso)} #{data['country'].upcase}",
31
- headings: CASES_DEATHS_RECOVERED_CTODAY_DTODAY,
32
- rows: rows)
33
- else
34
- Terminal::Table.new(title: data['country'].upcase,
35
- headings: CASES_DEATHS_RECOVERED_CTODAY_DTODAY,
36
- rows: rows)
37
- end
19
+ Terminal::Table.new(title: country_title(data),
20
+ headings: CASES_DEATHS_RECOVERED_CTODAY_DTODAY,
21
+ rows: [country_row(data)])
38
22
  end
39
23
 
40
24
  def full_country_table(data)
41
- rows = []
42
- rows << [
43
- comma_delimit(data['cases']),
44
- comma_delimit(data['deaths']),
45
- comma_delimit(data['recovered']),
46
- check_if_positve(data['todayCases']),
47
- check_if_positve(data['todayDeaths']),
48
- comma_delimit(data['critical']),
49
- comma_delimit(data['casesPerOneMillion'])
50
- ]
51
-
52
- if iso = data['countryInfo']['iso2']
53
- Terminal::Table.new(title: "#{country_emoji(iso)} #{data['country'].upcase}",
54
- headings: FULL_COUNTRY_TABLE_HEADINGS,
55
- rows: rows)
56
- else
57
- Terminal::Table.new(title: data['country'].upcase,
58
- headings: FULL_COUNTRY_TABLE_HEADINGS,
59
- rows: rows)
60
- end
25
+ Terminal::Table.new(title: country_title(data),
26
+ headings: FULL_COUNTRY_TABLE_HEADINGS,
27
+ rows: [full_country_row(data)])
61
28
  end
62
29
 
63
30
  def full_province_table(province)
64
- headings = [
65
- 'Confirmed'.paint_white,
66
- 'Deaths'.paint_red,
67
- 'Recovered'.paint_green
68
- ]
69
- rows = []
70
- rows << [province['stats']['confirmed'], province['stats']['deaths'], province['stats']['recovered']]
71
-
72
- Terminal::Table.new(title: province['province'].upcase, headings: headings, rows: rows)
31
+ Terminal::Table.new(
32
+ title: province['province'].upcase,
33
+ headings: FULL_PROVINCE_TABLE_HEADINGS,
34
+ rows: [province_row(province)]
35
+ )
73
36
  end
74
37
 
75
38
  def full_state_table(state)
76
- headings = [
77
- 'Cases'.paint_white,
78
- 'Cases Today'.paint_white,
79
- 'Deaths'.paint_red,
80
- 'Deaths Today'.paint_red,
81
- 'Active'.paint_yellow
82
- ]
83
-
84
- rows = []
85
- rows << [
86
- comma_delimit(state['cases']),
87
- check_if_positve(state['todayCases']),
88
- comma_delimit(state['deaths']),
89
- check_if_positve(state['todayDeaths']),
90
- comma_delimit(state['active'])
91
- ]
92
-
93
- Terminal::Table.new(title: state['state'].upcase, headings: headings, rows: rows)
39
+ Terminal::Table.new(
40
+ title: state['state'].upcase,
41
+ headings: FULL_STATE_TABLE_HEADINGS,
42
+ rows: [country_row(state)]
43
+ )
94
44
  end
95
45
 
96
46
  def compare_countries_table(data)
97
47
  rows = []
98
48
 
99
49
  data.each do |country|
100
- base_rows = [
101
- comma_delimit(country['cases']),
102
- check_if_positve(country['todayCases']),
103
- comma_delimit(country['deaths']),
104
- check_if_positve(country['todayDeaths']),
105
- comma_delimit(country['recovered'])
106
- ]
107
-
108
- rows << if (iso = country['countryInfo']['iso2'])
109
- base_rows.unshift("#{country_emoji(iso)} #{country['country'].upcase}")
110
- else
111
- base_rows.unshift(country['country'].upcase.to_s)
112
- end
50
+ base_rows = country_row(country)
51
+ rows << base_rows.unshift(country_title(country))
113
52
  end
114
53
 
115
54
  align_columns(:compare_country_table,
116
- Terminal::Table.new(headings: COMPARE_COUNTRIES_TABLE_HEADINGS,
117
- rows: rows))
55
+ Terminal::Table.new(
56
+ headings: COMPARE_COUNTRIES_TABLE_HEADINGS,
57
+ rows: rows
58
+ ))
118
59
  end
119
60
 
120
61
  def compare_countries_table_full(data)
121
- rows = data.map do |country|
122
- [
123
- country.fetch('country'),
124
- comma_delimit(country.fetch('cases')),
125
- comma_delimit(country.fetch('deaths')),
126
- comma_delimit(country.fetch('recovered')),
127
- check_if_positve(country.fetch('todayCases')),
128
- check_if_positve(country.fetch('todayDeaths')),
129
- comma_delimit(country.fetch('critical')),
130
- comma_delimit(country.fetch('casesPerOneMillion'))
131
- ]
132
- end
62
+ rows = data.map { |country| compare_countries_full_row(country) }
133
63
 
134
64
  align_columns(:compare_country_table_full,
135
65
  Terminal::Table.new(headings: COMPARE_COUNTRY_TABLE_FULL,
@@ -139,23 +69,9 @@ module Kovid
139
69
  def compare_us_states(data)
140
70
  rows = data.map.with_index do |state, index|
141
71
  if index.odd?
142
- [
143
- state.fetch('state').upcase,
144
- comma_delimit(state.fetch('cases')),
145
- check_if_positve(state['todayCases']),
146
- comma_delimit(state['deaths']),
147
- check_if_positve(state['todayDeaths']),
148
- comma_delimit(state.fetch('active'))
149
- ]
72
+ us_state_row(state)
150
73
  else
151
- [
152
- state.fetch('state').upcase.paint_highlight,
153
- comma_delimit(state.fetch('cases')).paint_highlight,
154
- check_if_positve(state['todayCases']).paint_highlight,
155
- comma_delimit(state['deaths']).paint_highlight,
156
- check_if_positve(state['todayDeaths']).paint_highlight,
157
- comma_delimit(state.fetch('active')).paint_highlight
158
- ]
74
+ us_state_row(state).map(&:paint_highlight)
159
75
  end
160
76
  end
161
77
 
@@ -165,14 +81,7 @@ module Kovid
165
81
  end
166
82
 
167
83
  def compare_provinces(data)
168
- rows = data.map do |province|
169
- [
170
- province['province'].upcase,
171
- province['stats']['confirmed'],
172
- province['stats']['deaths'],
173
- province['stats']['recovered']
174
- ]
175
- end
84
+ rows = data.map { |province| compare_provinces_row(province) }
176
85
 
177
86
  align_columns(:compare_provinces,
178
87
  Terminal::Table.new(headings: COMPARE_PROVINCES_HEADINGS,
@@ -180,29 +89,22 @@ module Kovid
180
89
  end
181
90
 
182
91
  def cases(cases)
183
- headings = CASES_DEATHS_RECOVERED
184
- rows = [
185
- [
186
- comma_delimit(cases['cases']),
187
- comma_delimit(cases['deaths']),
188
- comma_delimit(cases['recovered'])
189
- ]
190
- ]
191
-
192
- Terminal::Table.new(title: '🌍 Total Number of Incidents Worldwide'.upcase, headings: headings, rows: rows)
92
+ Terminal::Table.new(
93
+ title: '🌍 Total Number of Incidents Worldwide'.upcase,
94
+ headings: CASES_DEATHS_RECOVERED,
95
+ rows: [cases_row(cases)]
96
+ )
193
97
  end
194
98
 
195
99
  private
196
100
 
197
- def comma_delimit(number)
198
- number.to_s.chars.to_a.reverse.each_slice(3)
199
- .map(&:join)
200
- .join(',')
201
- .reverse
202
- end
203
-
204
- def check_if_positve(num)
205
- num.to_i.positive? ? "+#{comma_delimit(num)}" : comma_delimit(num).to_s
101
+ def country_title(data)
102
+ iso = data['countryInfo']['iso2']
103
+ if iso.nil?
104
+ data['country'].upcase
105
+ else
106
+ "#{country_emoji(iso)} #{data['country'].upcase}"
107
+ end
206
108
  end
207
109
 
208
110
  def country_emoji(iso)
@@ -210,10 +112,80 @@ module Kovid
210
112
  8203.chr(Encoding::UTF_8)
211
113
  end
212
114
 
213
- def transpose(load)
214
- load['timeline'].values.map(&:values).transpose.each do |data|
215
- data.map! { |number| comma_delimit(number) }
216
- end
115
+ def cases_row(data)
116
+ [
117
+ Kovid.comma_delimit(data['cases']),
118
+ Kovid.comma_delimit(data['deaths']),
119
+ Kovid.comma_delimit(data['recovered'])
120
+ ]
121
+ end
122
+
123
+ # Also works for state
124
+ def country_row(data)
125
+ [
126
+ Kovid.comma_delimit(data['cases']),
127
+ Kovid.add_plus_sign(data['todayCases']),
128
+ Kovid.comma_delimit(data['deaths']),
129
+ Kovid.add_plus_sign(data['todayDeaths']),
130
+ Kovid.comma_delimit(data['recovered'])
131
+ ]
132
+ end
133
+
134
+ def full_country_row(data)
135
+ [
136
+ Kovid.comma_delimit(data['cases']),
137
+ Kovid.comma_delimit(data['deaths']),
138
+ Kovid.comma_delimit(data['recovered']),
139
+ Kovid.add_plus_sign(data['todayCases']),
140
+ Kovid.add_plus_sign(data['todayDeaths']),
141
+ Kovid.comma_delimit(data['critical']),
142
+ Kovid.comma_delimit(data['casesPerOneMillion'])
143
+ ]
144
+ end
145
+
146
+ def province_row(data)
147
+ [
148
+ data['stats']['confirmed'],
149
+ data['stats']['deaths'],
150
+ data['stats']['recovered']
151
+ ]
152
+ end
153
+
154
+ def compare_provinces_row(data)
155
+ [
156
+ data['province'].upcase,
157
+ province_row(data)
158
+ ].flatten
159
+ end
160
+
161
+ def compare_countries_full_row(data)
162
+ [
163
+ data.fetch('country'),
164
+ full_country_row(data)
165
+ ].flatten
166
+ end
167
+
168
+ def us_state_row(data)
169
+ [
170
+ data.fetch('state').upcase,
171
+ Kovid.comma_delimit(data.fetch('cases')),
172
+ Kovid.add_plus_sign(data['todayCases']),
173
+ Kovid.comma_delimit(data['deaths']),
174
+ Kovid.add_plus_sign(data['todayDeaths']),
175
+ Kovid.comma_delimit(data.fetch('active'))
176
+ ]
177
+ end
178
+
179
+ def aggregated_row(data)
180
+ [
181
+ Kovid.comma_delimit(data['cases']),
182
+ Kovid.add_plus_sign(data['todayCases']),
183
+ Kovid.comma_delimit(data['deaths']),
184
+ Kovid.add_plus_sign(data['todayDeaths']),
185
+ Kovid.comma_delimit(data['recovered']),
186
+ Kovid.comma_delimit(data['active']),
187
+ Kovid.comma_delimit(data['critical'])
188
+ ]
217
189
  end
218
190
 
219
191
  def scale(msg)
@@ -222,32 +194,26 @@ module Kovid
222
194
  end
223
195
 
224
196
  def aggregated_table(collated_data, continent, iso, emoji)
225
- title = if emoji.codepoints.size > 1
226
- emoji + 8203.chr(Encoding::UTF_8) + \
227
- " Aggregated Data on #{continent} (#{iso.size} States)".upcase
228
- else
229
- emoji + \
230
- " Aggregated Data on #{continent} (#{iso.size} States)".upcase
231
- end
232
-
233
- rows = []
234
- rows << [
235
- comma_delimit(collated_data['cases']),
236
- check_if_positve(collated_data['todayCases']),
237
- comma_delimit(collated_data['deaths']),
238
- check_if_positve(collated_data['todayDeaths']),
239
- comma_delimit(collated_data['recovered']),
240
- comma_delimit(collated_data['active']),
241
- comma_delimit(collated_data['critical'])
242
- ]
197
+ title = aggregated_table_title(continent, iso, emoji)
243
198
 
244
199
  Terminal::Table.new(
245
200
  title: title,
246
201
  headings: CONTINENTAL_AGGREGATE_HEADINGS,
247
- rows: rows
202
+ rows: [aggregated_row(collated_data)]
248
203
  )
249
204
  end
250
205
 
206
+ def aggregated_table_title(continent, iso, emoji)
207
+ aggregated_data_continent = ' Aggregated Data on ' \
208
+ "#{continent} (#{iso.size} States)".upcase
209
+
210
+ if emoji.codepoints.size > 1
211
+ emoji + 8203.chr(Encoding::UTF_8) + aggregated_data_continent
212
+ else
213
+ emoji + aggregated_data_continent
214
+ end
215
+ end
216
+
251
217
  def align_columns(table_type, table)
252
218
  return table unless RIGHT_ALIGN_COLUMNS[table_type]
253
219
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kovid
4
- VERSION = '0.6.3'
4
+ VERSION = '0.6.8'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kovid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.6.8
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-09 00:00:00.000000000 Z
11
+ date: 2020-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ascii_charts
@@ -80,6 +80,20 @@ 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
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: simplecov
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +119,8 @@ extra_rdoc_files: []
105
119
  files:
106
120
  - ".gitignore"
107
121
  - ".rspec"
122
+ - ".rubocop.yml"
123
+ - ".rubocop_todo.yml"
108
124
  - ".travis.yml"
109
125
  - CODE_OF_CONDUCT.md
110
126
  - Gemfile