kovid 0.6.2 → 0.6.7
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 +4 -4
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +59 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +18 -1
- data/README.md +3 -1
- data/Rakefile +1 -0
- data/kovid.gemspec +9 -4
- data/lib/kovid.rb +0 -2
- data/lib/kovid/aggregators.rb +28 -0
- data/lib/kovid/cache.rb +0 -1
- data/lib/kovid/cli.rb +33 -33
- data/lib/kovid/constants.rb +112 -0
- data/lib/kovid/helpers.rb +22 -0
- data/lib/kovid/historians.rb +108 -0
- data/lib/kovid/painter.rb +0 -1
- data/lib/kovid/request.rb +62 -28
- data/lib/kovid/tablelize.rb +118 -346
- data/lib/kovid/version.rb +1 -1
- metadata +7 -2
data/lib/kovid/helpers.rb
CHANGED
@@ -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
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kovid
|
4
|
+
module Historians
|
5
|
+
include Constants
|
6
|
+
|
7
|
+
def history(country, last)
|
8
|
+
# TODO: Write checks for when country is spelt wrong.
|
9
|
+
rows = []
|
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
|
16
|
+
|
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
|
24
|
+
stats = stats.reject { |stat| stat[0].to_i.zero? && stat[1].to_i.zero? }
|
25
|
+
dates = dates.last(stats.count)
|
26
|
+
end
|
27
|
+
|
28
|
+
stats.each_with_index do |val, index|
|
29
|
+
val.unshift(Kovid.dateman(dates[index]))
|
30
|
+
end.each do |row|
|
31
|
+
rows << row
|
32
|
+
end
|
33
|
+
|
34
|
+
if stats.size > 10
|
35
|
+
rows << FOOTER_LINE
|
36
|
+
rows << DATE_CASES_DEATHS_RECOVERED
|
37
|
+
end
|
38
|
+
|
39
|
+
Terminal::Table.new(
|
40
|
+
title: country['country'].upcase,
|
41
|
+
headings: DATE_CASES_DEATHS_RECOVERED,
|
42
|
+
rows: rows
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def histogram(country, date_string)
|
47
|
+
@date = date_string.split('.')
|
48
|
+
|
49
|
+
if @date.last.to_i != 20
|
50
|
+
Kovid.info_table('Only 2020 histgrams are available.')
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
# From dates where number of !cases.zero?
|
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
|
+
data = []
|
59
|
+
|
60
|
+
# TODO: Refactor
|
61
|
+
# Returns array of days.to_i from the date param
|
62
|
+
dates = dates.map do |date|
|
63
|
+
date.split('/')
|
64
|
+
end.select do |date|
|
65
|
+
date.last == @date.last
|
66
|
+
end.select do |date|
|
67
|
+
date.first == @date.first
|
68
|
+
end.map do |array|
|
69
|
+
array[1]
|
70
|
+
end.map(&:to_i).last(positive_cases_figures.count)
|
71
|
+
|
72
|
+
# Arranges dates and figures in [x,y] for histogram
|
73
|
+
# With x being day, y being number of cases
|
74
|
+
if dates.empty?
|
75
|
+
if @date.first.to_i > Time.now.month
|
76
|
+
msgs = [
|
77
|
+
'Seriously...??! 😏', 'Did you just check the future??',
|
78
|
+
'You just checked the future Morgan.',
|
79
|
+
'Knowing too much of your future is never a good thing.'
|
80
|
+
]
|
81
|
+
|
82
|
+
Kovid.info_table(msgs.sample)
|
83
|
+
else
|
84
|
+
Kovid.info_table('Check your spelling/No infections for this month.')
|
85
|
+
end
|
86
|
+
|
87
|
+
else
|
88
|
+
dates.each_with_index do |val, index|
|
89
|
+
data << [val, positive_cases_figures[index]]
|
90
|
+
end
|
91
|
+
y_range = AsciiCharts::Cartesian.new(
|
92
|
+
data, bar: true, hide_zero: true
|
93
|
+
).y_range
|
94
|
+
|
95
|
+
last_two_y = y_range.last 2
|
96
|
+
y_interval = last_two_y.last - last_two_y.first
|
97
|
+
|
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}")
|
101
|
+
|
102
|
+
puts 'Experimental feature, please report issues.'
|
103
|
+
|
104
|
+
AsciiCharts::Cartesian.new(data, bar: true, hide_zero: true).draw
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/kovid/painter.rb
CHANGED
data/lib/kovid/request.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
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'
|
@@ -15,16 +16,18 @@ module Kovid
|
|
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
|
22
|
-
NG RW ST SN SC SL SO ZA SS SD
|
23
|
-
|
24
|
-
|
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
|
27
|
-
PS QA SA SG SY TH TJ TL TM TR TW
|
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
|
@@ -70,7 +73,7 @@ module Kovid
|
|
70
73
|
def by_country(country_name)
|
71
74
|
response = fetch_country(country_name)
|
72
75
|
|
73
|
-
if response.
|
76
|
+
if response.key?('message')
|
74
77
|
not_found(country_name)
|
75
78
|
else
|
76
79
|
Kovid::Tablelize.country_table(response)
|
@@ -82,7 +85,7 @@ module Kovid
|
|
82
85
|
def by_country_full(country_name)
|
83
86
|
response = fetch_country(country_name)
|
84
87
|
|
85
|
-
if response.
|
88
|
+
if response.key?('message')
|
86
89
|
not_found(country_name)
|
87
90
|
else
|
88
91
|
Kovid::Tablelize.full_country_table(response)
|
@@ -107,7 +110,7 @@ module Kovid
|
|
107
110
|
end
|
108
111
|
|
109
112
|
def state(state)
|
110
|
-
response = fetch_state(state)
|
113
|
+
response = fetch_state(Kovid.lookup_us_state(state))
|
111
114
|
if response.nil?
|
112
115
|
not_found(state)
|
113
116
|
else
|
@@ -119,7 +122,6 @@ module Kovid
|
|
119
122
|
|
120
123
|
def states(states)
|
121
124
|
compared_states = fetch_compared_states(states)
|
122
|
-
|
123
125
|
Kovid::Tablelize.compare_us_states(compared_states)
|
124
126
|
rescue JSON::ParserError
|
125
127
|
puts SERVER_DOWN
|
@@ -147,7 +149,9 @@ module Kovid
|
|
147
149
|
end
|
148
150
|
|
149
151
|
def cases
|
150
|
-
response = JSON.parse(
|
152
|
+
response = JSON.parse(
|
153
|
+
Typhoeus.get(UriBuilder.new('/all').url, cache_ttl: 900).response_body
|
154
|
+
)
|
151
155
|
|
152
156
|
Kovid::Tablelize.cases(response)
|
153
157
|
rescue JSON::ParserError
|
@@ -156,7 +160,11 @@ module Kovid
|
|
156
160
|
|
157
161
|
def history(country, last)
|
158
162
|
history_path = UriBuilder.new('/v2/historical').url
|
159
|
-
response = JSON.parse(
|
163
|
+
response = JSON.parse(
|
164
|
+
Typhoeus.get(
|
165
|
+
history_path + "/#{country}", cache_ttl: 900
|
166
|
+
).response_body
|
167
|
+
)
|
160
168
|
|
161
169
|
Kovid::Tablelize.history(response, last)
|
162
170
|
rescue JSON::ParserError
|
@@ -165,7 +173,11 @@ module Kovid
|
|
165
173
|
|
166
174
|
def histogram(country, date)
|
167
175
|
history_path = UriBuilder.new('/v2/historical').url
|
168
|
-
response = JSON.parse(
|
176
|
+
response = JSON.parse(
|
177
|
+
Typhoeus.get(
|
178
|
+
history_path + "/#{country}", cache_ttl: 900
|
179
|
+
).response_body
|
180
|
+
)
|
169
181
|
|
170
182
|
Kovid::Tablelize.histogram(response, date)
|
171
183
|
end
|
@@ -183,14 +195,20 @@ module Kovid
|
|
183
195
|
|
184
196
|
def fetch_countries(list)
|
185
197
|
list.map do |country|
|
186
|
-
JSON.parse(
|
198
|
+
JSON.parse(
|
199
|
+
Typhoeus.get(
|
200
|
+
COUNTRIES_PATH + "/#{country}", cache_ttl: 900
|
201
|
+
).response_body
|
202
|
+
)
|
187
203
|
end.sort_by { |json| -json['cases'] }
|
188
204
|
end
|
189
205
|
|
190
206
|
def fetch_compared_states(submitted_states)
|
191
|
-
|
207
|
+
submitted_states.map! { |s| Kovid.lookup_us_state(s) }
|
192
208
|
|
193
|
-
|
209
|
+
fetch_state_data.select do |state|
|
210
|
+
submitted_states.include?(state['state'])
|
211
|
+
end
|
194
212
|
end
|
195
213
|
|
196
214
|
def fetch_state_data
|
@@ -198,6 +216,8 @@ module Kovid
|
|
198
216
|
end
|
199
217
|
|
200
218
|
def fetch_country(country_name)
|
219
|
+
# TODO: Match ISOs to full country names
|
220
|
+
country_name = 'nl' if country_name == 'netherlands'
|
201
221
|
country_url = COUNTRIES_PATH + "/#{country_name}"
|
202
222
|
|
203
223
|
JSON.parse(Typhoeus.get(country_url, cache_ttl: 900).response_body)
|
@@ -209,7 +229,9 @@ module Kovid
|
|
209
229
|
|
210
230
|
def fetch_province(province)
|
211
231
|
response = fetch_jhucsse
|
212
|
-
response.select
|
232
|
+
response.select do |datum|
|
233
|
+
datum['province'] == capitalize_words(province)
|
234
|
+
end.first
|
213
235
|
end
|
214
236
|
|
215
237
|
def fetch_provinces(provinces)
|
@@ -219,19 +241,35 @@ module Kovid
|
|
219
241
|
end
|
220
242
|
|
221
243
|
def fetch_state(state)
|
222
|
-
states_array = JSON.parse(
|
244
|
+
states_array = JSON.parse(
|
245
|
+
Typhoeus.get(STATES_URL, cache_ttl: 900).response_body
|
246
|
+
)
|
223
247
|
|
224
|
-
states_array.select
|
248
|
+
states_array.select do |state_name|
|
249
|
+
state_name['state'] == capitalize_words(state)
|
250
|
+
end.first
|
225
251
|
end
|
226
252
|
|
227
253
|
def aggregator(isos, meth)
|
228
|
-
countries_array = JSON.parse(
|
229
|
-
|
254
|
+
countries_array = JSON.parse(countries_request)
|
230
255
|
country_array = countries_array.select do |hash|
|
231
256
|
isos.include?(hash['countryInfo']['iso2'])
|
232
257
|
end
|
258
|
+
data = countries_aggregator(country_array)
|
233
259
|
|
234
|
-
|
260
|
+
meth === data
|
261
|
+
rescue JSON::ParserError
|
262
|
+
puts SERVER_DOWN
|
263
|
+
end
|
264
|
+
|
265
|
+
def countries_request
|
266
|
+
Typhoeus.get(
|
267
|
+
UriBuilder.new('/countries').url, cache_ttl: 900
|
268
|
+
).response_body
|
269
|
+
end
|
270
|
+
|
271
|
+
def countries_aggregator(country_array)
|
272
|
+
country_array.inject do |base, other|
|
235
273
|
base.merge(other) do |key, left, right|
|
236
274
|
left ||= 0
|
237
275
|
right ||= 0
|
@@ -239,10 +277,6 @@ module Kovid
|
|
239
277
|
left + right unless %w[country countryInfo].include?(key)
|
240
278
|
end
|
241
279
|
end.compact
|
242
|
-
|
243
|
-
meth === data
|
244
|
-
rescue JSON::ParserError
|
245
|
-
puts SERVER_DOWN
|
246
280
|
end
|
247
281
|
end
|
248
282
|
end
|
data/lib/kovid/tablelize.rb
CHANGED
@@ -4,206 +4,62 @@ require 'terminal-table'
|
|
4
4
|
require 'date'
|
5
5
|
require 'ascii_charts'
|
6
6
|
require_relative 'painter'
|
7
|
+
require_relative 'constants'
|
8
|
+
require_relative 'aggregators'
|
9
|
+
require_relative 'historians'
|
7
10
|
|
8
11
|
module Kovid
|
9
12
|
class Tablelize
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
'Deaths'.paint_red,
|
14
|
-
'Recovered'.paint_green
|
15
|
-
].freeze
|
16
|
-
|
17
|
-
CASES_DEATHS_RECOVERED_CTODAY_DTODAY = [
|
18
|
-
'Cases'.paint_white,
|
19
|
-
'Cases Today'.paint_white,
|
20
|
-
'Deaths'.paint_red,
|
21
|
-
'Deaths Today'.paint_red,
|
22
|
-
'Recovered'.paint_green
|
23
|
-
].freeze
|
24
|
-
|
25
|
-
DATE_CASES_DEATHS_RECOVERED = [
|
26
|
-
'Date'.paint_white,
|
27
|
-
'Cases'.paint_white,
|
28
|
-
'Deaths'.paint_red,
|
29
|
-
'Recovered'.paint_green
|
30
|
-
].freeze
|
31
|
-
|
32
|
-
CONTINENTAL_AGGREGATE_HEADINGS = [
|
33
|
-
'Cases'.paint_white,
|
34
|
-
'Cases Today'.paint_white,
|
35
|
-
'Deaths'.paint_red,
|
36
|
-
'Deaths Today'.paint_red,
|
37
|
-
'Recovered'.paint_green,
|
38
|
-
'Active'.paint_yellow,
|
39
|
-
'Critical'.paint_red
|
40
|
-
].freeze
|
41
|
-
|
42
|
-
COMPARE_COUNTRY_TABLE_FULL = [
|
43
|
-
'Country'.paint_white,
|
44
|
-
'Cases'.paint_white,
|
45
|
-
'Deaths'.paint_red,
|
46
|
-
'Recovered'.paint_green,
|
47
|
-
'Cases Today'.paint_white,
|
48
|
-
'Deaths Today'.paint_red,
|
49
|
-
'Critical'.paint_yellow,
|
50
|
-
'Cases/Million'.paint_white
|
51
|
-
].freeze
|
52
|
-
|
53
|
-
COMPARE_COUNTRIES_TABLE_HEADINGS = [
|
54
|
-
'Country'.paint_white,
|
55
|
-
'Cases'.paint_white,
|
56
|
-
'Cases Today'.paint_white,
|
57
|
-
'Deaths'.paint_red,
|
58
|
-
'Deaths Today'.paint_red,
|
59
|
-
'Recovered'.paint_green
|
60
|
-
].freeze
|
61
|
-
|
62
|
-
FULL_COUNTRY_TABLE_HEADINGS = [
|
63
|
-
'Cases'.paint_white,
|
64
|
-
'Deaths'.paint_red,
|
65
|
-
'Recovered'.paint_green,
|
66
|
-
'Cases Today'.paint_white,
|
67
|
-
'Deaths Today'.paint_red,
|
68
|
-
'Critical'.paint_yellow,
|
69
|
-
'Cases/Million'.paint_white
|
70
|
-
].freeze
|
71
|
-
|
72
|
-
COMPARE_STATES_HEADINGS = [
|
73
|
-
'State'.paint_white,
|
74
|
-
'Cases'.paint_white,
|
75
|
-
'Cases Today'.paint_white,
|
76
|
-
'Deaths'.paint_red,
|
77
|
-
'Deaths Today'.paint_red,
|
78
|
-
'Active'.paint_yellow
|
79
|
-
].freeze
|
80
|
-
|
81
|
-
COMPARE_PROVINCES_HEADINGS = [
|
82
|
-
'Province'.paint_white,
|
83
|
-
'Confirmed'.paint_white,
|
84
|
-
'Deaths'.paint_red,
|
85
|
-
'Recovered'.paint_green
|
86
|
-
].freeze
|
87
|
-
|
88
|
-
FOOTER_LINE = ['------------', '------------', '------------', '------------'].freeze
|
89
|
-
COUNTRY_LETTERS = 'A'.upto('Z').with_index(127_462).to_h.freeze
|
90
|
-
|
91
|
-
RIGHT_ALIGN_COLUMNS = {
|
92
|
-
compare_country_table_full: [1, 2, 3, 4, 5, 6, 7],
|
93
|
-
compare_country_table: [1, 2, 3, 4, 5],
|
94
|
-
compare_us_states: [1, 2, 3, 4, 5],
|
95
|
-
compare_provinces: [1, 2, 3]
|
96
|
-
}.freeze
|
13
|
+
extend Kovid::Constants
|
14
|
+
extend Kovid::Aggregators
|
15
|
+
extend Kovid::Historians
|
97
16
|
|
17
|
+
class << self
|
98
18
|
def country_table(data)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
check_if_positve(data['todayCases']),
|
103
|
-
comma_delimit(data['deaths']),
|
104
|
-
check_if_positve(data['todayDeaths']),
|
105
|
-
comma_delimit(data['recovered'])
|
106
|
-
]
|
107
|
-
]
|
108
|
-
|
109
|
-
if (iso = data['countryInfo']['iso2'])
|
110
|
-
Terminal::Table.new(title: "#{country_emoji(iso)} #{data['country'].upcase}",
|
111
|
-
headings: CASES_DEATHS_RECOVERED_CTODAY_DTODAY,
|
112
|
-
rows: rows)
|
113
|
-
else
|
114
|
-
Terminal::Table.new(title: data['country'].upcase,
|
115
|
-
headings: CASES_DEATHS_RECOVERED_CTODAY_DTODAY,
|
116
|
-
rows: rows)
|
117
|
-
end
|
19
|
+
Terminal::Table.new(title: country_title(data),
|
20
|
+
headings: CASES_DEATHS_RECOVERED_CTODAY_DTODAY,
|
21
|
+
rows: [country_row(data)])
|
118
22
|
end
|
119
23
|
|
120
24
|
def full_country_table(data)
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
comma_delimit(data['deaths']),
|
125
|
-
comma_delimit(data['recovered']),
|
126
|
-
check_if_positve(data['todayCases']),
|
127
|
-
check_if_positve(data['todayDeaths']),
|
128
|
-
comma_delimit(data['critical']),
|
129
|
-
comma_delimit(data['casesPerOneMillion'])
|
130
|
-
]
|
131
|
-
|
132
|
-
if iso = data['countryInfo']['iso2']
|
133
|
-
Terminal::Table.new(title: "#{country_emoji(iso)} #{data['country'].upcase}",
|
134
|
-
headings: FULL_COUNTRY_TABLE_HEADINGS,
|
135
|
-
rows: rows)
|
136
|
-
else
|
137
|
-
Terminal::Table.new(title: data['country'].upcase,
|
138
|
-
headings: FULL_COUNTRY_TABLE_HEADINGS,
|
139
|
-
rows: rows)
|
140
|
-
end
|
25
|
+
Terminal::Table.new(title: country_title(data),
|
26
|
+
headings: FULL_COUNTRY_TABLE_HEADINGS,
|
27
|
+
rows: [full_country_row(data)])
|
141
28
|
end
|
142
29
|
|
143
30
|
def full_province_table(province)
|
144
|
-
|
145
|
-
'
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
rows = []
|
150
|
-
rows << [province['stats']['confirmed'], province['stats']['deaths'], province['stats']['recovered']]
|
151
|
-
|
152
|
-
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
|
+
)
|
153
36
|
end
|
154
37
|
|
155
38
|
def full_state_table(state)
|
156
|
-
|
157
|
-
'
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
'Active'.paint_yellow
|
162
|
-
]
|
163
|
-
|
164
|
-
rows = []
|
165
|
-
rows << [state['cases'], check_if_positve(state['todayCases']), state['deaths'], check_if_positve(state['todayDeaths']), state['active']]
|
166
|
-
|
167
|
-
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
|
+
)
|
168
44
|
end
|
169
45
|
|
170
46
|
def compare_countries_table(data)
|
171
47
|
rows = []
|
172
48
|
|
173
49
|
data.each do |country|
|
174
|
-
base_rows =
|
175
|
-
|
176
|
-
check_if_positve(country['todayCases']),
|
177
|
-
comma_delimit(country['deaths']),
|
178
|
-
check_if_positve(country['todayDeaths']),
|
179
|
-
comma_delimit(country['recovered'])
|
180
|
-
]
|
181
|
-
|
182
|
-
rows << if (iso = country['countryInfo']['iso2'])
|
183
|
-
base_rows.unshift("#{country_emoji(iso)} #{country['country'].upcase}")
|
184
|
-
else
|
185
|
-
base_rows.unshift(country['country'].upcase.to_s)
|
186
|
-
end
|
50
|
+
base_rows = country_row(country)
|
51
|
+
rows << base_rows.unshift(country_title(country))
|
187
52
|
end
|
188
53
|
|
189
54
|
align_columns(:compare_country_table,
|
190
|
-
Terminal::Table.new(
|
191
|
-
|
55
|
+
Terminal::Table.new(
|
56
|
+
headings: COMPARE_COUNTRIES_TABLE_HEADINGS,
|
57
|
+
rows: rows
|
58
|
+
))
|
192
59
|
end
|
193
60
|
|
194
61
|
def compare_countries_table_full(data)
|
195
|
-
rows = data.map
|
196
|
-
[
|
197
|
-
country.fetch('country'),
|
198
|
-
comma_delimit(country.fetch('cases')),
|
199
|
-
comma_delimit(country.fetch('deaths')),
|
200
|
-
comma_delimit(country.fetch('recovered')),
|
201
|
-
check_if_positve(country.fetch('todayCases')),
|
202
|
-
check_if_positve(country.fetch('todayDeaths')),
|
203
|
-
comma_delimit(country.fetch('critical')),
|
204
|
-
comma_delimit(country.fetch('casesPerOneMillion'))
|
205
|
-
]
|
206
|
-
end
|
62
|
+
rows = data.map { |country| compare_countries_full_row(country) }
|
207
63
|
|
208
64
|
align_columns(:compare_country_table_full,
|
209
65
|
Terminal::Table.new(headings: COMPARE_COUNTRY_TABLE_FULL,
|
@@ -213,23 +69,9 @@ module Kovid
|
|
213
69
|
def compare_us_states(data)
|
214
70
|
rows = data.map.with_index do |state, index|
|
215
71
|
if index.odd?
|
216
|
-
|
217
|
-
state.fetch('state').upcase,
|
218
|
-
comma_delimit(state.fetch('cases')),
|
219
|
-
check_if_positve(state['todayCases']),
|
220
|
-
comma_delimit(state['deaths']),
|
221
|
-
check_if_positve(state['todayDeaths']),
|
222
|
-
comma_delimit(state.fetch('active'))
|
223
|
-
]
|
72
|
+
us_state_row(state)
|
224
73
|
else
|
225
|
-
|
226
|
-
state.fetch('state').upcase.paint_highlight,
|
227
|
-
comma_delimit(state.fetch('cases')).paint_highlight,
|
228
|
-
check_if_positve(state['todayCases']).paint_highlight,
|
229
|
-
comma_delimit(state['deaths']).paint_highlight,
|
230
|
-
check_if_positve(state['todayDeaths']).paint_highlight,
|
231
|
-
comma_delimit(state.fetch('active')).paint_highlight
|
232
|
-
]
|
74
|
+
us_state_row(state).map(&:paint_highlight)
|
233
75
|
end
|
234
76
|
end
|
235
77
|
|
@@ -239,14 +81,7 @@ module Kovid
|
|
239
81
|
end
|
240
82
|
|
241
83
|
def compare_provinces(data)
|
242
|
-
rows = data.map
|
243
|
-
[
|
244
|
-
province['province'].upcase,
|
245
|
-
province['stats']['confirmed'],
|
246
|
-
province['stats']['deaths'],
|
247
|
-
province['stats']['recovered']
|
248
|
-
]
|
249
|
-
end
|
84
|
+
rows = data.map { |province| compare_provinces_row(province) }
|
250
85
|
|
251
86
|
align_columns(:compare_provinces,
|
252
87
|
Terminal::Table.new(headings: COMPARE_PROVINCES_HEADINGS,
|
@@ -254,160 +89,103 @@ module Kovid
|
|
254
89
|
end
|
255
90
|
|
256
91
|
def cases(cases)
|
257
|
-
headings = CASES_DEATHS_RECOVERED
|
258
|
-
rows = [
|
259
|
-
[
|
260
|
-
comma_delimit(cases['cases']),
|
261
|
-
comma_delimit(cases['deaths']),
|
262
|
-
comma_delimit(cases['recovered'])
|
263
|
-
]
|
264
|
-
]
|
265
|
-
|
266
|
-
Terminal::Table.new(title: '🌍 Total Number of Incidents Worldwide'.upcase, headings: headings, rows: rows)
|
267
|
-
end
|
268
|
-
|
269
|
-
def history(country, last)
|
270
|
-
# Write checks for when country is spelt wrong.
|
271
|
-
headings = DATE_CASES_DEATHS_RECOVERED
|
272
|
-
rows = []
|
273
|
-
|
274
|
-
stats = if last
|
275
|
-
transpose(country).last(last.to_i)
|
276
|
-
else
|
277
|
-
transpose(country)
|
278
|
-
end
|
279
|
-
|
280
|
-
dates = if last
|
281
|
-
country['timeline']['cases'].keys.last(last.to_i)
|
282
|
-
else
|
283
|
-
country['timeline']['cases'].keys
|
284
|
-
end
|
285
|
-
|
286
|
-
unless last
|
287
|
-
stats = stats.reject { |stat| stat[0].to_i.zero? && stat[1].to_i.zero? }
|
288
|
-
dates = dates.last(stats.count)
|
289
|
-
end
|
290
|
-
|
291
|
-
stats.each_with_index do |val, index|
|
292
|
-
val.unshift(Kovid.dateman(dates[index]))
|
293
|
-
end.each do |row|
|
294
|
-
rows << row
|
295
|
-
end
|
296
|
-
|
297
|
-
if stats.size > 10
|
298
|
-
rows << FOOTER_LINE
|
299
|
-
rows << DATE_CASES_DEATHS_RECOVERED
|
300
|
-
end
|
301
|
-
|
302
92
|
Terminal::Table.new(
|
303
|
-
title:
|
304
|
-
headings:
|
305
|
-
rows:
|
93
|
+
title: '🌍 Total Number of Incidents Worldwide'.upcase,
|
94
|
+
headings: CASES_DEATHS_RECOVERED,
|
95
|
+
rows: [cases_row(cases)]
|
306
96
|
)
|
307
97
|
end
|
308
98
|
|
309
|
-
|
310
|
-
@date = date_string.split('.')
|
311
|
-
|
312
|
-
if @date.last.to_i != 20
|
313
|
-
Kovid.info_table('Only 2020 histgrams are available.')
|
314
|
-
return
|
315
|
-
end
|
316
|
-
|
317
|
-
# From dates where number of !cases.zero?
|
318
|
-
positive_cases_figures = country['timeline']['cases'].values.reject(&:zero?)
|
319
|
-
dates = country['timeline']['cases'].reject { |_k, v| v.zero? }.keys
|
320
|
-
data = []
|
321
|
-
|
322
|
-
# Improve this later, like everything else.
|
323
|
-
# Returns array of days.to_i from the date param
|
324
|
-
dates = dates.map do |date|
|
325
|
-
date.split('/')
|
326
|
-
end.select do |date|
|
327
|
-
date.last == @date.last
|
328
|
-
end.select do |date|
|
329
|
-
date.first == @date.first
|
330
|
-
end.map do |array|
|
331
|
-
array[1]
|
332
|
-
end.map(&:to_i).last(positive_cases_figures.count)
|
333
|
-
|
334
|
-
# Arranges dates and figures in [x,y] for histogram
|
335
|
-
# With x being day, y being number of cases
|
336
|
-
if dates.empty?
|
337
|
-
if @date.first.to_i > Time.now.month
|
338
|
-
msgs = [
|
339
|
-
'Seriously...??! 😏', 'Did you just check the future??',
|
340
|
-
'You just checked the future Morgan.',
|
341
|
-
'Knowing too much of your future is never a good thing.'
|
342
|
-
]
|
343
|
-
|
344
|
-
Kovid.info_table(msgs.sample)
|
345
|
-
else
|
346
|
-
Kovid.info_table('Check your spelling/No infections for this month.')
|
347
|
-
end
|
99
|
+
private
|
348
100
|
|
101
|
+
def country_title(data)
|
102
|
+
iso = data['countryInfo']['iso2']
|
103
|
+
if iso.nil?
|
104
|
+
data['country'].upcase
|
349
105
|
else
|
350
|
-
|
351
|
-
data << [val, positive_cases_figures[index]]
|
352
|
-
end
|
353
|
-
y_range = AsciiCharts::Cartesian.new(data, bar: true, hide_zero: true).y_range
|
354
|
-
|
355
|
-
last_two_y = y_range.last 2
|
356
|
-
y_interval = last_two_y.last - last_two_y.first
|
357
|
-
|
358
|
-
scale("Scale on Y: #{y_interval}:#{(y_interval / last_two_y.last.to_f * positive_cases_figures.last).round(2) / y_interval}")
|
359
|
-
|
360
|
-
puts 'Experimental feature, please report issues.'
|
361
|
-
|
362
|
-
AsciiCharts::Cartesian.new(data, bar: true, hide_zero: true).draw
|
106
|
+
"#{country_emoji(iso)} #{data['country'].upcase}"
|
363
107
|
end
|
364
108
|
end
|
365
109
|
|
366
|
-
def
|
367
|
-
|
110
|
+
def country_emoji(iso)
|
111
|
+
COUNTRY_LETTERS.values_at(*iso.chars).pack('U*') + \
|
112
|
+
8203.chr(Encoding::UTF_8)
|
368
113
|
end
|
369
114
|
|
370
|
-
def
|
371
|
-
|
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
|
+
]
|
372
121
|
end
|
373
122
|
|
374
|
-
|
375
|
-
|
376
|
-
|
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
|
+
]
|
377
132
|
end
|
378
133
|
|
379
|
-
def
|
380
|
-
|
381
|
-
|
382
|
-
|
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
|
+
]
|
383
144
|
end
|
384
145
|
|
385
|
-
def
|
386
|
-
|
146
|
+
def province_row(data)
|
147
|
+
[
|
148
|
+
data['stats']['confirmed'],
|
149
|
+
data['stats']['deaths'],
|
150
|
+
data['stats']['recovered']
|
151
|
+
]
|
387
152
|
end
|
388
153
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
.join(',')
|
395
|
-
.reverse
|
154
|
+
def compare_provinces_row(data)
|
155
|
+
[
|
156
|
+
data['province'].upcase,
|
157
|
+
province_row(data)
|
158
|
+
].flatten
|
396
159
|
end
|
397
160
|
|
398
|
-
def
|
399
|
-
|
161
|
+
def compare_countries_full_row(data)
|
162
|
+
[
|
163
|
+
data.fetch('country'),
|
164
|
+
full_country_row(data)
|
165
|
+
].flatten
|
400
166
|
end
|
401
167
|
|
402
|
-
def
|
403
|
-
|
404
|
-
|
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
|
+
]
|
405
177
|
end
|
406
178
|
|
407
|
-
def
|
408
|
-
|
409
|
-
|
410
|
-
|
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
|
+
]
|
411
189
|
end
|
412
190
|
|
413
191
|
def scale(msg)
|
@@ -416,32 +194,26 @@ module Kovid
|
|
416
194
|
end
|
417
195
|
|
418
196
|
def aggregated_table(collated_data, continent, iso, emoji)
|
419
|
-
title =
|
420
|
-
emoji + 8203.chr(Encoding::UTF_8) + \
|
421
|
-
" Aggregated Data on #{continent} (#{iso.size} States)".upcase
|
422
|
-
else
|
423
|
-
emoji + \
|
424
|
-
" Aggregated Data on #{continent} (#{iso.size} States)".upcase
|
425
|
-
end
|
426
|
-
|
427
|
-
rows = []
|
428
|
-
rows << [
|
429
|
-
comma_delimit(collated_data['cases']),
|
430
|
-
check_if_positve(collated_data['todayCases']),
|
431
|
-
comma_delimit(collated_data['deaths']),
|
432
|
-
check_if_positve(collated_data['todayDeaths']),
|
433
|
-
comma_delimit(collated_data['recovered']),
|
434
|
-
comma_delimit(collated_data['active']),
|
435
|
-
comma_delimit(collated_data['critical'])
|
436
|
-
]
|
197
|
+
title = aggregated_table_title(continent, iso, emoji)
|
437
198
|
|
438
199
|
Terminal::Table.new(
|
439
200
|
title: title,
|
440
201
|
headings: CONTINENTAL_AGGREGATE_HEADINGS,
|
441
|
-
rows:
|
202
|
+
rows: [aggregated_row(collated_data)]
|
442
203
|
)
|
443
204
|
end
|
444
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
|
+
|
445
217
|
def align_columns(table_type, table)
|
446
218
|
return table unless RIGHT_ALIGN_COLUMNS[table_type]
|
447
219
|
|