kovid 0.6.3 → 0.6.8

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: 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