meteoservice 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +54 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +130 -0
- data/LICENSE.txt +21 -0
- data/README.md +101 -0
- data/Rakefile +22 -0
- data/lib/main.rb +17 -0
- data/lib/meteoservice/constants.rb +34 -0
- data/lib/meteoservice/data/towns.json +11 -0
- data/lib/meteoservice/error.rb +43 -0
- data/lib/meteoservice/meteo.rb +18 -0
- data/lib/meteoservice/nested_hash_value.rb +16 -0
- data/lib/meteoservice/parser_xml.rb +39 -0
- data/lib/meteoservice/predict.rb +65 -0
- data/lib/meteoservice/read_data.rb +75 -0
- data/lib/meteoservice/towns_data.rb +67 -0
- data/lib/meteoservice/version.rb +5 -0
- data/lib/meteoservice.rb +25 -0
- data/sig/meteoservice.rbs +4 -0
- metadata +126 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: eb3502dc35e5eec707fe5f4f4369933694c38c60eaa12e43062d0cab1aefb635
|
|
4
|
+
data.tar.gz: c7a53bdd74dd3b5567a4103354027cf0060fc00fdd2bcf9b00894b120723d28f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 885a7487c76588e0d8708f2444ecea1a335aa73fffd14214f67d4917e590d4d2eeacac09afab0238f4208e2155c56243c03437b14e6026a830f12e3d131077fa
|
|
7
|
+
data.tar.gz: 1ae0d8ab03f884d7f1ccab4579c1af1d0342f3464083123f012d4c18270256c19d3bd2ce18ff1d679ef27066a7231a6449f498569dd30123d1b23f34f0c63a97
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require:
|
|
2
|
+
- rubocop-performance
|
|
3
|
+
- rubocop-rspec
|
|
4
|
+
|
|
5
|
+
AllCops:
|
|
6
|
+
NewCops: enable
|
|
7
|
+
TargetRubyVersion: 3.0.3
|
|
8
|
+
|
|
9
|
+
Style/StringLiteralsInInterpolation:
|
|
10
|
+
Enabled: false
|
|
11
|
+
|
|
12
|
+
Layout/LineLength:
|
|
13
|
+
Max: 150
|
|
14
|
+
Exclude:
|
|
15
|
+
- spec/**/*.rb
|
|
16
|
+
|
|
17
|
+
Metrics/BlockLength:
|
|
18
|
+
Enabled: false
|
|
19
|
+
|
|
20
|
+
Metrics/AbcSize:
|
|
21
|
+
Enabled: false
|
|
22
|
+
|
|
23
|
+
Style/Documentation:
|
|
24
|
+
Enabled: false
|
|
25
|
+
|
|
26
|
+
Metrics/MethodLength:
|
|
27
|
+
Max: 150
|
|
28
|
+
|
|
29
|
+
RSpec/MultipleExpectations:
|
|
30
|
+
Max: 10
|
|
31
|
+
|
|
32
|
+
RSpec/ExampleLength:
|
|
33
|
+
Max: 100
|
|
34
|
+
|
|
35
|
+
RSpec/FilePath:
|
|
36
|
+
Enabled: false
|
|
37
|
+
|
|
38
|
+
RSpec/NoExpectationExample:
|
|
39
|
+
Enabled: false
|
|
40
|
+
|
|
41
|
+
Metrics/CyclomaticComplexity:
|
|
42
|
+
Enabled: false
|
|
43
|
+
|
|
44
|
+
Metrics/PerceivedComplexity:
|
|
45
|
+
Enabled: false
|
|
46
|
+
|
|
47
|
+
LineEndStringConcatenationIndentation:
|
|
48
|
+
Enabled: false
|
|
49
|
+
|
|
50
|
+
Style/FrozenStringLiteralComment:
|
|
51
|
+
Enabled: false
|
|
52
|
+
|
|
53
|
+
Style/StringLiterals:
|
|
54
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
source 'https://rubygems.org'
|
|
4
|
+
|
|
5
|
+
# Specify your gem's dependencies in meteoservice.gemspec
|
|
6
|
+
gemspec
|
|
7
|
+
|
|
8
|
+
gem 'rake', '~> 13.0'
|
|
9
|
+
|
|
10
|
+
group :test do
|
|
11
|
+
gem 'byebug'
|
|
12
|
+
gem 'codecov', '~> 0.4'
|
|
13
|
+
gem 'rspec', '~> 3.1'
|
|
14
|
+
gem 'rubocop', '~> 1.3'
|
|
15
|
+
gem 'rubocop-performance', '~> 1.1'
|
|
16
|
+
gem 'rubocop-rspec', '~> 2.1'
|
|
17
|
+
gem 'simplecov', '~> 0.21'
|
|
18
|
+
gem 'vcr', '~> 6.1'
|
|
19
|
+
gem 'webmock', '~> 3.1'
|
|
20
|
+
end
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
meteoservice (0.1.0)
|
|
5
|
+
faraday-encode_xml
|
|
6
|
+
faraday_middleware
|
|
7
|
+
multi_xml (~> 0.6)
|
|
8
|
+
uri
|
|
9
|
+
|
|
10
|
+
GEM
|
|
11
|
+
remote: https://rubygems.org/
|
|
12
|
+
specs:
|
|
13
|
+
addressable (2.8.1)
|
|
14
|
+
public_suffix (>= 2.0.2, < 6.0)
|
|
15
|
+
ast (2.4.2)
|
|
16
|
+
builder (3.2.4)
|
|
17
|
+
byebug (11.1.3)
|
|
18
|
+
codecov (0.6.0)
|
|
19
|
+
simplecov (>= 0.15, < 0.22)
|
|
20
|
+
crack (0.4.5)
|
|
21
|
+
rexml
|
|
22
|
+
diff-lcs (1.5.0)
|
|
23
|
+
docile (1.4.0)
|
|
24
|
+
faraday (1.10.2)
|
|
25
|
+
faraday-em_http (~> 1.0)
|
|
26
|
+
faraday-em_synchrony (~> 1.0)
|
|
27
|
+
faraday-excon (~> 1.1)
|
|
28
|
+
faraday-httpclient (~> 1.0)
|
|
29
|
+
faraday-multipart (~> 1.0)
|
|
30
|
+
faraday-net_http (~> 1.0)
|
|
31
|
+
faraday-net_http_persistent (~> 1.0)
|
|
32
|
+
faraday-patron (~> 1.0)
|
|
33
|
+
faraday-rack (~> 1.0)
|
|
34
|
+
faraday-retry (~> 1.0)
|
|
35
|
+
ruby2_keywords (>= 0.0.4)
|
|
36
|
+
faraday-em_http (1.0.0)
|
|
37
|
+
faraday-em_synchrony (1.0.0)
|
|
38
|
+
faraday-encode_xml (0.2.0)
|
|
39
|
+
faraday (~> 1.0)
|
|
40
|
+
gyoku (~> 1.3)
|
|
41
|
+
faraday-excon (1.1.0)
|
|
42
|
+
faraday-httpclient (1.0.1)
|
|
43
|
+
faraday-multipart (1.0.4)
|
|
44
|
+
multipart-post (~> 2)
|
|
45
|
+
faraday-net_http (1.0.1)
|
|
46
|
+
faraday-net_http_persistent (1.2.0)
|
|
47
|
+
faraday-patron (1.0.0)
|
|
48
|
+
faraday-rack (1.0.0)
|
|
49
|
+
faraday-retry (1.0.3)
|
|
50
|
+
faraday_middleware (1.2.0)
|
|
51
|
+
faraday (~> 1.0)
|
|
52
|
+
gyoku (1.4.0)
|
|
53
|
+
builder (>= 2.1.2)
|
|
54
|
+
rexml (~> 3.0)
|
|
55
|
+
hashdiff (1.0.1)
|
|
56
|
+
json (2.6.2)
|
|
57
|
+
multi_xml (0.6.0)
|
|
58
|
+
multipart-post (2.2.3)
|
|
59
|
+
parallel (1.22.1)
|
|
60
|
+
parser (3.1.2.1)
|
|
61
|
+
ast (~> 2.4.1)
|
|
62
|
+
public_suffix (5.0.0)
|
|
63
|
+
rainbow (3.1.1)
|
|
64
|
+
rake (13.0.6)
|
|
65
|
+
regexp_parser (2.6.1)
|
|
66
|
+
rexml (3.2.5)
|
|
67
|
+
rspec (3.12.0)
|
|
68
|
+
rspec-core (~> 3.12.0)
|
|
69
|
+
rspec-expectations (~> 3.12.0)
|
|
70
|
+
rspec-mocks (~> 3.12.0)
|
|
71
|
+
rspec-core (3.12.0)
|
|
72
|
+
rspec-support (~> 3.12.0)
|
|
73
|
+
rspec-expectations (3.12.0)
|
|
74
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
75
|
+
rspec-support (~> 3.12.0)
|
|
76
|
+
rspec-mocks (3.12.0)
|
|
77
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
78
|
+
rspec-support (~> 3.12.0)
|
|
79
|
+
rspec-support (3.12.0)
|
|
80
|
+
rubocop (1.39.0)
|
|
81
|
+
json (~> 2.3)
|
|
82
|
+
parallel (~> 1.10)
|
|
83
|
+
parser (>= 3.1.2.1)
|
|
84
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
85
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
86
|
+
rexml (>= 3.2.5, < 4.0)
|
|
87
|
+
rubocop-ast (>= 1.23.0, < 2.0)
|
|
88
|
+
ruby-progressbar (~> 1.7)
|
|
89
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
90
|
+
rubocop-ast (1.23.0)
|
|
91
|
+
parser (>= 3.1.1.0)
|
|
92
|
+
rubocop-performance (1.15.1)
|
|
93
|
+
rubocop (>= 1.7.0, < 2.0)
|
|
94
|
+
rubocop-ast (>= 0.4.0)
|
|
95
|
+
rubocop-rspec (2.15.0)
|
|
96
|
+
rubocop (~> 1.33)
|
|
97
|
+
ruby-progressbar (1.11.0)
|
|
98
|
+
ruby2_keywords (0.0.5)
|
|
99
|
+
simplecov (0.21.2)
|
|
100
|
+
docile (~> 1.1)
|
|
101
|
+
simplecov-html (~> 0.11)
|
|
102
|
+
simplecov_json_formatter (~> 0.1)
|
|
103
|
+
simplecov-html (0.12.3)
|
|
104
|
+
simplecov_json_formatter (0.1.4)
|
|
105
|
+
unicode-display_width (2.3.0)
|
|
106
|
+
uri (0.11.0)
|
|
107
|
+
vcr (6.1.0)
|
|
108
|
+
webmock (3.18.1)
|
|
109
|
+
addressable (>= 2.8.0)
|
|
110
|
+
crack (>= 0.3.2)
|
|
111
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
112
|
+
|
|
113
|
+
PLATFORMS
|
|
114
|
+
x86_64-linux
|
|
115
|
+
|
|
116
|
+
DEPENDENCIES
|
|
117
|
+
byebug
|
|
118
|
+
codecov (~> 0.4)
|
|
119
|
+
meteoservice!
|
|
120
|
+
rake (~> 13.0)
|
|
121
|
+
rspec (~> 3.1)
|
|
122
|
+
rubocop (~> 1.3)
|
|
123
|
+
rubocop-performance (~> 1.1)
|
|
124
|
+
rubocop-rspec (~> 2.1)
|
|
125
|
+
simplecov (~> 0.21)
|
|
126
|
+
vcr (~> 6.1)
|
|
127
|
+
webmock (~> 3.1)
|
|
128
|
+
|
|
129
|
+
BUNDLED WITH
|
|
130
|
+
2.3.24
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Gleb V. Zhegilin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# `meteoservice`
|
|
2
|
+
|
|
3
|
+
###### Язык написания - Ruby 3.0.3
|
|
4
|
+
|
|
5
|
+
## Описание:
|
|
6
|
+
> Программа показывает текущую погоду, используя свежие данные в XML-структуре от `Метеосервиса`.
|
|
7
|
+
> Пользователю предлагается указать, для какого города он хочет посмотреть прогноз.
|
|
8
|
+
> В библиотеке заведен словарик (`towns.json`) из 10 городов с уникальными индексами
|
|
9
|
+
> (см. <http://www.meteoservice.ru/content/export.html>). Вы можете продолжить заполнять его,
|
|
10
|
+
> используя консольную версию программы.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Установка:
|
|
15
|
+
|
|
16
|
+
Добавьте
|
|
17
|
+
|
|
18
|
+
``` rb
|
|
19
|
+
gem 'meteoservice'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
И сделайте
|
|
23
|
+
|
|
24
|
+
bundle
|
|
25
|
+
|
|
26
|
+
Или сделайте
|
|
27
|
+
|
|
28
|
+
gem install meteoservice
|
|
29
|
+
|
|
30
|
+
## Использование:
|
|
31
|
+
|
|
32
|
+
``` rb
|
|
33
|
+
require 'meteoservice'
|
|
34
|
+
|
|
35
|
+
Meteoservice.result
|
|
36
|
+
|
|
37
|
+
# Или, если не хотите использовать консоль для ввода данных
|
|
38
|
+
# укажите 'id' города в скобках:
|
|
39
|
+
|
|
40
|
+
Meteoservice.result('113')
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Пример (вариант с вводом 'id' в консоли):
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Погоду для какого города Вы хотите узнать?
|
|
47
|
+
Введите уникальный индекс города и нажмите "enter". Если вашего города
|
|
48
|
+
нет в списке, перейдите по ссылке https://www.meteoservice.ru/content/export.html,
|
|
49
|
+
найдите интересуемый индекс и введите его ниже. Название города с индексом добавятся
|
|
50
|
+
в список автоматически:
|
|
51
|
+
|
|
52
|
+
1: ["4", "Архангельск"]
|
|
53
|
+
2: ["105", "Калининград"]
|
|
54
|
+
3: ["199", "Краснодар"]
|
|
55
|
+
4: ["37", "Москва"]
|
|
56
|
+
5: ["113", "Мурманск"]
|
|
57
|
+
6: ["99", "Новосибирск"]
|
|
58
|
+
7: ["111", "Петропавловск-Камчатский"]
|
|
59
|
+
8: ["135", "Ростов-на-Дону"]
|
|
60
|
+
9: ["69", "Санкт-Петербург"]
|
|
61
|
+
69
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Санкт-Петербург
|
|
65
|
+
|
|
66
|
+
Относительная влажность воздуха: 67..69 %
|
|
67
|
+
Комфорт: -11..-11 °С
|
|
68
|
+
|
|
69
|
+
2022-11-22 в вторник утром
|
|
70
|
+
Температура: -6..-5 °С
|
|
71
|
+
Ветер: 2..3 м/с, юго-восточный
|
|
72
|
+
Атмосферное давление: 764..764 мм.рт.ст.
|
|
73
|
+
Облачность: облачно
|
|
74
|
+
Осадки:
|
|
75
|
+
Интенсивность осадков: возможен дождь/снег
|
|
76
|
+
Вероятность грозы: возможна гроза
|
|
77
|
+
Относительная влажность воздуха: 65..66 %
|
|
78
|
+
Комфорт: -11..-11 °С
|
|
79
|
+
|
|
80
|
+
2022-11-22 в вторник днём
|
|
81
|
+
Температура: -4..-3 °С
|
|
82
|
+
Ветер: 3..3 м/с, восточный
|
|
83
|
+
Атмосферное давление: 764..764 мм.рт.ст.
|
|
84
|
+
Облачность: облачно
|
|
85
|
+
Осадки:
|
|
86
|
+
Интенсивность осадков: возможен дождь/снег
|
|
87
|
+
Вероятность грозы: возможна гроза
|
|
88
|
+
Относительная влажность воздуха: 63..65 %
|
|
89
|
+
Комфорт: -9..-9 °С
|
|
90
|
+
|
|
91
|
+
2022-11-22 в вторник вечером
|
|
92
|
+
Температура: -3..-2 °С
|
|
93
|
+
Ветер: 3..4 м/с, восточный
|
|
94
|
+
Атмосферное давление: 763..764 мм.рт.ст.
|
|
95
|
+
Облачность: облачно
|
|
96
|
+
Осадки:
|
|
97
|
+
Интенсивность осадков: возможен дождь/снег
|
|
98
|
+
Вероятность грозы: возможна гроза
|
|
99
|
+
Относительная влажность воздуха: 60..62 %
|
|
100
|
+
Комфорт: -9..-9 °С
|
|
101
|
+
```
|
data/Rakefile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rake'
|
|
4
|
+
|
|
5
|
+
begin
|
|
6
|
+
require 'bundler/setup'
|
|
7
|
+
Bundler::GemHelper.install_tasks
|
|
8
|
+
rescue LoadError
|
|
9
|
+
puts 'although not required, bundler is recommened for running the tests'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
task default: :spec
|
|
13
|
+
|
|
14
|
+
require 'bundler/gem_tasks'
|
|
15
|
+
require 'rspec/core/rake_task'
|
|
16
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
17
|
+
|
|
18
|
+
require 'rubocop/rake_task'
|
|
19
|
+
RuboCop::RakeTask.new do |task|
|
|
20
|
+
task.requires << 'rubocop-performance'
|
|
21
|
+
task.requires << 'rubocop-rspec'
|
|
22
|
+
end
|
data/lib/main.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'date'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'json'
|
|
6
|
+
require 'byebug'
|
|
7
|
+
require 'faraday/encode_xml'
|
|
8
|
+
require 'faraday_middleware'
|
|
9
|
+
require 'multi_xml'
|
|
10
|
+
require_relative 'meteoservice/constants'
|
|
11
|
+
require_relative 'meteoservice/nested_hash_value'
|
|
12
|
+
require_relative 'meteoservice/parser_xml'
|
|
13
|
+
require_relative 'meteoservice/meteo'
|
|
14
|
+
require_relative 'meteoservice/towns_data'
|
|
15
|
+
require_relative 'meteoservice/read_data'
|
|
16
|
+
require_relative 'meteoservice/predict'
|
|
17
|
+
require_relative 'meteoservice/error'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Meteoservice
|
|
4
|
+
module Constants
|
|
5
|
+
# Облачность
|
|
6
|
+
CLOUDINESS = %w[туман ясно малооблачно облачно пасмурно].freeze
|
|
7
|
+
|
|
8
|
+
# Осадки
|
|
9
|
+
PRECIPITATION = %w[смешанные дождь ливень снег гроза нет данных без осадков].freeze
|
|
10
|
+
|
|
11
|
+
# Интенсивность осадков, если они есть
|
|
12
|
+
RPOWER = ['возможен дождь/снег', 'дождь/снег'].freeze
|
|
13
|
+
|
|
14
|
+
# Вероятность грозы, если прогнозируется
|
|
15
|
+
SPOWER = ['возможна гроза', 'гроза'].freeze
|
|
16
|
+
|
|
17
|
+
# Ветер (направление)
|
|
18
|
+
WIND_DIRECTION = %w[северный северо-восточный восточный юго-восточный южный
|
|
19
|
+
юго-западный западный северо-западный].freeze
|
|
20
|
+
|
|
21
|
+
# Дни недели
|
|
22
|
+
DAYS_OF_WEEK = %w[понедельник вторник среда четверг пятница суббота воскресенье].freeze
|
|
23
|
+
|
|
24
|
+
# аттрибуты xml
|
|
25
|
+
KEYS_DATA = %w[year month day hour weekday].freeze
|
|
26
|
+
|
|
27
|
+
# Погодные явления
|
|
28
|
+
KEYS_PHENOMENA = %w[cloudiness precipitation rpower spower].freeze
|
|
29
|
+
|
|
30
|
+
KEYS_LIMIT = %w[min max].freeze
|
|
31
|
+
|
|
32
|
+
BASE_URL = 'https://xml.meteoservice.ru'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Meteoservice
|
|
4
|
+
class Error < StandardError
|
|
5
|
+
ClientError = Class.new(self)
|
|
6
|
+
ServerError = Class.new(self)
|
|
7
|
+
|
|
8
|
+
BadRequest = Class.new(ClientError)
|
|
9
|
+
Unauthorized = Class.new(ClientError)
|
|
10
|
+
NotAcceptable = Class.new(ClientError)
|
|
11
|
+
NotFound = Class.new(ClientError)
|
|
12
|
+
Conflict = Class.new(ClientError)
|
|
13
|
+
TooManyRequests = Class.new(ClientError)
|
|
14
|
+
Forbidden = Class.new(ClientError)
|
|
15
|
+
Locked = Class.new(ClientError)
|
|
16
|
+
MethodNotAllowed = Class.new(ClientError)
|
|
17
|
+
NotImplemented = Class.new(ServerError)
|
|
18
|
+
BadGateway = Class.new(ServerError)
|
|
19
|
+
ServiceUnavailable = Class.new(ServerError)
|
|
20
|
+
GatewayTimeout = Class.new(ServerError)
|
|
21
|
+
|
|
22
|
+
ERRORS = {
|
|
23
|
+
400 => Meteoservice::Error::BadRequest,
|
|
24
|
+
401 => Meteoservice::Error::Unauthorized,
|
|
25
|
+
403 => Meteoservice::Error::Forbidden,
|
|
26
|
+
404 => Meteoservice::Error::NotFound,
|
|
27
|
+
405 => Meteoservice::Error::MethodNotAllowed,
|
|
28
|
+
406 => Meteoservice::Error::NotAcceptable,
|
|
29
|
+
409 => Meteoservice::Error::Conflict,
|
|
30
|
+
423 => Meteoservice::Error::Locked,
|
|
31
|
+
429 => Meteoservice::Error::TooManyRequests,
|
|
32
|
+
500 => Meteoservice::Error::ServerError,
|
|
33
|
+
502 => Meteoservice::Error::BadGateway,
|
|
34
|
+
503 => Meteoservice::Error::ServiceUnavailable,
|
|
35
|
+
504 => Meteoservice::Error::GatewayTimeout
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
def self.from_response(body)
|
|
39
|
+
msg = body['detail'] || body['message'] || body
|
|
40
|
+
new msg.to_s
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Meteoservice
|
|
4
|
+
class Meteo
|
|
5
|
+
attr_reader :data, :phenomena, :pressure, :temperature, :wind,
|
|
6
|
+
:relwet, :heat
|
|
7
|
+
|
|
8
|
+
def initialize(tags)
|
|
9
|
+
@data = tags[:data]
|
|
10
|
+
@phenomena = tags[:phenomena]
|
|
11
|
+
@pressure = tags[:pressure]
|
|
12
|
+
@temperature = tags[:temperature]
|
|
13
|
+
@wind = tags[:wind]
|
|
14
|
+
@relwet = tags[:relwet]
|
|
15
|
+
@heat = tags[:heat]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Meteoservice
|
|
4
|
+
module NestedHashValue
|
|
5
|
+
def nested_hash_value(obj, key)
|
|
6
|
+
if obj.respond_to?(:key?) && obj.key?(key)
|
|
7
|
+
obj[key]
|
|
8
|
+
elsif obj.respond_to?(:each)
|
|
9
|
+
r = nil
|
|
10
|
+
|
|
11
|
+
obj.find { |*a| r = nested_hash_value(a.last, key) }
|
|
12
|
+
r
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Meteoservice
|
|
4
|
+
module ParserXml
|
|
5
|
+
include Meteoservice::Constants
|
|
6
|
+
|
|
7
|
+
def connection(path)
|
|
8
|
+
connection = Faraday.new(url: BASE_URL) do |faraday|
|
|
9
|
+
faraday.request :xml, content_type: /\bxml$/
|
|
10
|
+
faraday.adapter Faraday.default_adapter
|
|
11
|
+
faraday.response :xml
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
response ||= connection.get(path)
|
|
15
|
+
rescue Faraday::Error => e
|
|
16
|
+
puts "Ошибка соединения с сервером: #{e.message}"
|
|
17
|
+
abort e.message
|
|
18
|
+
else
|
|
19
|
+
begin
|
|
20
|
+
body = response.body
|
|
21
|
+
rescue StandardError => e
|
|
22
|
+
puts e.class.name
|
|
23
|
+
abort e.message
|
|
24
|
+
else
|
|
25
|
+
respond_with_error(response.status, body) unless response.success?
|
|
26
|
+
body
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# code - это код состояния HTTP (504, 429, 404...)
|
|
33
|
+
def respond_with_error(code, body)
|
|
34
|
+
raise(Meteoservice::Error, body) unless Meteoservice::Error::ERRORS.key?(code)
|
|
35
|
+
|
|
36
|
+
raise Meteoservice::Error::ERRORS[code].from_response(body)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Meteoservice
|
|
2
|
+
class Predict
|
|
3
|
+
include Meteoservice::Constants
|
|
4
|
+
|
|
5
|
+
def initialize(forecasts)
|
|
6
|
+
@date = forecasts.data
|
|
7
|
+
@phenomena = forecasts.phenomena
|
|
8
|
+
@pressure = forecasts.pressure
|
|
9
|
+
@temperature = forecasts.temperature
|
|
10
|
+
@wind = forecasts.wind
|
|
11
|
+
@relwet = forecasts.relwet
|
|
12
|
+
@heat = forecasts.heat
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Какой день недели?
|
|
16
|
+
def day_week
|
|
17
|
+
firstday_wday = Date.new(@date[0], @date[1], @date[2]).wday
|
|
18
|
+
|
|
19
|
+
firstday_wday = 7 if firstday_wday.zero?
|
|
20
|
+
|
|
21
|
+
DAYS_OF_WEEK[firstday_wday - 1]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Вывод результата в терминал
|
|
25
|
+
def to_s
|
|
26
|
+
times_day = 'ночью' if Range.new(*[0, 5].map(&:to_i)).include? @date[3]
|
|
27
|
+
times_day = 'утром' if Range.new(*[6, 12].map(&:to_i)).include? @date[3]
|
|
28
|
+
times_day = 'днём' if Range.new(*[13, 17].map(&:to_i)).include? @date[3]
|
|
29
|
+
times_day = 'вечером' if Range.new(*[18, 23].map(&:to_i)).include? @date[3]
|
|
30
|
+
|
|
31
|
+
result = if today?
|
|
32
|
+
"Сегодня в #{day_week} #{times_day}\n"
|
|
33
|
+
else
|
|
34
|
+
"#{DateTime.new(@date[0], @date[1], @date[2], @date[3], 0, 0)
|
|
35
|
+
.strftime('%F')} в #{day_week} #{times_day}\n"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
result << "Температура: #{temperature_range_string} °С\n" \
|
|
39
|
+
"Ветер: #{@wind[0]}..#{@wind[1]} м/с, #{WIND_DIRECTION[@wind[2].to_i]}\n" \
|
|
40
|
+
"Атмосферное давление: #{@pressure[0]}..#{@pressure[1]} мм.рт.ст.\n" \
|
|
41
|
+
"Облачность: #{CLOUDINESS[@phenomena[0].to_i]}\n" \
|
|
42
|
+
"Осадки: #{PRECIPITATION[@phenomena[1].to_i]}\n" \
|
|
43
|
+
"Интенсивность осадков: #{RPOWER[@phenomena[2].to_i]}\n" \
|
|
44
|
+
"Вероятность грозы: #{SPOWER[@phenomena[3].to_i]}\n" \
|
|
45
|
+
"Относительная влажность воздуха: #{@relwet[0]}..#{@relwet[1]} %\n" \
|
|
46
|
+
"Комфорт: #{@heat[0]}..#{@heat[1]} °С"
|
|
47
|
+
|
|
48
|
+
result
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Добавим знак "+" к температуре, если она положительная
|
|
52
|
+
def temperature_range_string
|
|
53
|
+
result = ''
|
|
54
|
+
result << '+' if @temperature[0].positive?
|
|
55
|
+
result << "#{@temperature[0]}.."
|
|
56
|
+
result << '+' if @temperature[1].positive?
|
|
57
|
+
result << @temperature[1].to_s
|
|
58
|
+
result
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def today?
|
|
62
|
+
@date == Date.today
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Meteoservice
|
|
4
|
+
class ReadData
|
|
5
|
+
def self.from_array(doc)
|
|
6
|
+
include Meteoservice::Constants
|
|
7
|
+
|
|
8
|
+
forecasts = doc.map do |prediction|
|
|
9
|
+
predict_data = {}
|
|
10
|
+
|
|
11
|
+
# дата "год, месяц, день, час, день недели"
|
|
12
|
+
data = KEYS_DATA.map do |key|
|
|
13
|
+
prediction[key].to_i
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
predict_data[:data] = data
|
|
17
|
+
|
|
18
|
+
# атмосферные явления
|
|
19
|
+
phenomena = KEYS_PHENOMENA.map do |key|
|
|
20
|
+
prediction['PHENOMENA'][key].to_i
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
predict_data[:phenomena] = phenomena
|
|
24
|
+
|
|
25
|
+
# атмосферное давление
|
|
26
|
+
pressure = KEYS_LIMIT.map do |key|
|
|
27
|
+
prediction['PRESSURE'][key].to_i
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
predict_data[:pressure] = pressure
|
|
31
|
+
|
|
32
|
+
# температура
|
|
33
|
+
temperature = KEYS_LIMIT.map do |key|
|
|
34
|
+
prediction['TEMPERATURE'][key].to_i
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
predict_data[:temperature] = temperature
|
|
38
|
+
|
|
39
|
+
# относительная влажность воздуха
|
|
40
|
+
relwet = KEYS_LIMIT.map do |key|
|
|
41
|
+
prediction['RELWET'][key].to_i
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
predict_data[:relwet] = relwet
|
|
45
|
+
|
|
46
|
+
# комфорт - температура воздуха по ощущению одетого по сезону
|
|
47
|
+
# человека, выходящего на улицу
|
|
48
|
+
heat = KEYS_LIMIT.map do |key|
|
|
49
|
+
prediction['HEAT'][key].to_i
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
predict_data[:heat] = heat
|
|
53
|
+
|
|
54
|
+
# приземный ветер
|
|
55
|
+
max_wind = prediction['WIND']['max']
|
|
56
|
+
min_wind = prediction['WIND']['min']
|
|
57
|
+
direction_wind = prediction['WIND']['direction']
|
|
58
|
+
|
|
59
|
+
predict_data[:wind] = [min_wind, max_wind, direction_wind]
|
|
60
|
+
|
|
61
|
+
Meteoservice::Meteo.new(predict_data)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
new(forecasts)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def initialize(forecasts)
|
|
68
|
+
@forecasts = forecasts
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def to_a
|
|
72
|
+
@forecasts
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Meteoservice
|
|
4
|
+
module TownsData
|
|
5
|
+
extend Meteoservice::NestedHashValue
|
|
6
|
+
extend Meteoservice::Constants
|
|
7
|
+
extend Meteoservice::ParserXml
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def process
|
|
11
|
+
catalogue = load
|
|
12
|
+
|
|
13
|
+
puts <<~TOWNS
|
|
14
|
+
\nПогоду для какого города Вы хотите узнать?
|
|
15
|
+
Введите уникальный индекс города и нажмите "enter". Если вашего города#{' '}
|
|
16
|
+
нет в списке, перейдите по ссылке https://www.meteoservice.ru/content/export.html,
|
|
17
|
+
найдите интересуемый индекс и введите его ниже. Название города с индексом добавятся
|
|
18
|
+
в список автоматически:\n
|
|
19
|
+
TOWNS
|
|
20
|
+
|
|
21
|
+
catalogue.sort_by { |_key, value| value }
|
|
22
|
+
.to_h.each_with_index { |name, index| puts "#{index + 1}: #{name}" }
|
|
23
|
+
|
|
24
|
+
city_index = gets.to_i
|
|
25
|
+
path = "/export/gismeteo/point/#{city_index}.xml"
|
|
26
|
+
if catalogue.key?('city_index')
|
|
27
|
+
data_taking(path, city_index)
|
|
28
|
+
else
|
|
29
|
+
data_taking(path, city_index, catalogue, conservation: true)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def auto_process(city_index)
|
|
34
|
+
path = "/export/gismeteo/point/#{city_index}.xml"
|
|
35
|
+
|
|
36
|
+
data_taking(path, city_index)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def load
|
|
42
|
+
data = nil
|
|
43
|
+
File.open("#{__dir__}/data/towns.json", encoding: 'utf-8') do |f|
|
|
44
|
+
data = JSON.parse(f.read)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
data
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def save(data, index, name)
|
|
51
|
+
File.open("#{__dir__}/data/towns.json", 'w+') do |f|
|
|
52
|
+
f.puts(JSON.pretty_generate(data.merge({ index.to_s => name.to_s })))
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def data_taking(path, index, data = nil, conservation: false)
|
|
57
|
+
result = connection(path)
|
|
58
|
+
|
|
59
|
+
city_name = URI.decode_www_form_component(nested_hash_value(result, 'TOWN')['sname'])
|
|
60
|
+
|
|
61
|
+
save(data, index, city_name) if conservation
|
|
62
|
+
|
|
63
|
+
[nested_hash_value(result, 'FORECAST'), city_name]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
data/lib/meteoservice.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'main'
|
|
4
|
+
|
|
5
|
+
# Main Meteoservice module
|
|
6
|
+
module Meteoservice
|
|
7
|
+
def self.result(city_index = nil)
|
|
8
|
+
doc = if city_index
|
|
9
|
+
Meteoservice::TownsData.auto_process(city_index.to_i)
|
|
10
|
+
else
|
|
11
|
+
Meteoservice::TownsData.process
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
puts "\e[H\e[2J"
|
|
15
|
+
|
|
16
|
+
weather = Meteoservice::ReadData.from_array(doc[0]).to_a
|
|
17
|
+
|
|
18
|
+
puts "#{doc[1]}\n\n"
|
|
19
|
+
|
|
20
|
+
weather.each_with_index do |_day, index|
|
|
21
|
+
puts Meteoservice::Predict.new(weather[index])
|
|
22
|
+
puts
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: meteoservice
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Gleb V. Zhegulin
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2022-11-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: faraday-encode_xml
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: faraday_middleware
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: multi_xml
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.6'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.6'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: uri
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
description: |-
|
|
70
|
+
The program shows the current weather using fresh data in an XML structure.
|
|
71
|
+
The user is prompted to indicate for which city he wants to see the forecast.
|
|
72
|
+
email:
|
|
73
|
+
- gleboceanborn@gmail.com
|
|
74
|
+
executables: []
|
|
75
|
+
extensions: []
|
|
76
|
+
extra_rdoc_files:
|
|
77
|
+
- README.md
|
|
78
|
+
files:
|
|
79
|
+
- ".rspec"
|
|
80
|
+
- ".rubocop.yml"
|
|
81
|
+
- CHANGELOG.md
|
|
82
|
+
- Gemfile
|
|
83
|
+
- Gemfile.lock
|
|
84
|
+
- LICENSE.txt
|
|
85
|
+
- README.md
|
|
86
|
+
- Rakefile
|
|
87
|
+
- lib/main.rb
|
|
88
|
+
- lib/meteoservice.rb
|
|
89
|
+
- lib/meteoservice/constants.rb
|
|
90
|
+
- lib/meteoservice/data/towns.json
|
|
91
|
+
- lib/meteoservice/error.rb
|
|
92
|
+
- lib/meteoservice/meteo.rb
|
|
93
|
+
- lib/meteoservice/nested_hash_value.rb
|
|
94
|
+
- lib/meteoservice/parser_xml.rb
|
|
95
|
+
- lib/meteoservice/predict.rb
|
|
96
|
+
- lib/meteoservice/read_data.rb
|
|
97
|
+
- lib/meteoservice/towns_data.rb
|
|
98
|
+
- lib/meteoservice/version.rb
|
|
99
|
+
- sig/meteoservice.rbs
|
|
100
|
+
homepage: https://github.com/ProfessorNemo/meteoservice
|
|
101
|
+
licenses:
|
|
102
|
+
- MIT
|
|
103
|
+
metadata:
|
|
104
|
+
homepage_uri: https://github.com/ProfessorNemo/meteoservice
|
|
105
|
+
source_code_uri: https://github.com/ProfessorNemo/meteoservice
|
|
106
|
+
rubygems_mfa_required: 'true'
|
|
107
|
+
post_install_message:
|
|
108
|
+
rdoc_options: []
|
|
109
|
+
require_paths:
|
|
110
|
+
- lib
|
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: 3.0.2
|
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
|
+
requirements:
|
|
118
|
+
- - ">="
|
|
119
|
+
- !ruby/object:Gem::Version
|
|
120
|
+
version: '0'
|
|
121
|
+
requirements: []
|
|
122
|
+
rubygems_version: 3.3.23
|
|
123
|
+
signing_key:
|
|
124
|
+
specification_version: 4
|
|
125
|
+
summary: Weather forecast for the next day.
|
|
126
|
+
test_files: []
|