Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kirill Hryvicki - 0 #20

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
5 changes: 5 additions & 0 deletions Hryvicki Kirill/0/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source 'https://rubygems.org'

gem 'mechanize'
gem 'roo'
gem 'roo-xls'
11 changes: 11 additions & 0 deletions Hryvicki Kirill/0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Usage
```
bundle install
```
```
ruby load_files.rb
```
```
ruby run.rb
```
before loading files create empty folder named as 'data'
19 changes: 19 additions & 0 deletions Hryvicki Kirill/0/load_files.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require 'mechanize'
require 'open-uri'
require 'uri'
require 'webrick'

agent = Mechanize.new
page = agent.get('http://www.belstat.gov.by/ofitsialnaya-statistika/makroekonomika-i-okruzhayushchaya-sreda/tseny/operativnaya-informatsiya_4/srednie-tseny-na-potrebitelskie-tovary-i-uslugi-po-respublike-belarus')
page.links_with(href: /.xls/).each do |link|
str_link = link.href.to_s
str_link = WEBrick::HTTPUtils.unescape(str_link)
str_link = WEBrick::HTTPUtils.escape(str_link)
f_link = if str_link.start_with?('/')
str_link
else
'http://www.belstat.gov.by' + str_link
end
download = URI.open(f_link)
IO.copy_stream(download, "./data/#{download.base_uri.to_s.split('/')[-1]}")
end
265 changes: 265 additions & 0 deletions Hryvicki Kirill/0/run.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
require 'roo'
RGBD marked this conversation as resolved.
Show resolved Hide resolved
require 'roo-xls'

def get_file_instance(file_path)
ext = file_path.split('.')[2]
file_instance = nil
if ext.include?('xls')
file_instance = conditional_load(ext, file_path)
else
puts 'unsupported file type: ' + file_path
end
file_instance
end

def conditional_load(ext, file_path)
case ext
when 'xls'
sheet = Roo::Excel.new(file_path)
when 'xlsx'
sheet = Roo::Excelx.new(file_path)
end
sheet
end

def fetch_products_data(file_instance, products, regions)
(9..file_instance.last_row).each do |n|
next if file_instance.cell('E', n).nil?

year = file_instance.cell('A', 3).split(' ')[2]
month = file_instance.cell('A', 3).split(' ')[1]
key = file_instance.cell('A', n).strip.downcase
meta = [key, year, month]
add_product(products, meta, regions, file_instance, n)
end
end

def add_product(products, meta, regions, file_instance, num)
key = meta[0]
year = meta[1]
month = meta[2]
parse_product(products, key, year)
products[key][year][month] = { regions[4] => format_value(file_instance.cell('O', num), year) }
end

def parse_product(products, key, year)
products[key] = {} unless products[key]
products[key][year] = {} unless products[key][year]
end

def format_value(val, year)
return if val.nil?

result = val.to_f
result /= 10_000 if year.to_i < 2017
result.round(2)
end

def get_recent_price_data(key, products, month_map)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/AbcSize: Assignment Branch Condition size for get_recent_price_data is too high. [15.68/15]

current_year = Time.now.strftime('%Y').to_s
current_month = parse_month(month_map)
product_year_data = products[key]
year_key = get_closest_year(current_year, product_year_data)
product_month_data = product_year_data[year_key]
month_key = get_closest_month(current_month, product_month_data, month_map)
form_recent_price_data(product_month_data[month_key]['Minsk'], year_key, month_key, key)
end

def form_recent_price_data(price, year, month, product)
{
'price' => price,
'year' => year,
'month' => month,
'product' => product
}
end

def parse_month(month_map)
current_month = Time.now.strftime('%m')
month_map.each { |month, month_number| current_month = month if month_number == current_month }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint/UselessAssignment: Useless assignment to variable - current_month.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

==

current_month
end

def get_closest_year(current_year, product_data)
current_year if product_data[current_year]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

строка бесполезна

product_data.keys.max_by(&:to_i) unless product_data[current_year]
end

def get_closest_month(current_month, product_data, month_map)
current_month if product_data[current_month]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

если не имелось в виду return current_month if то строка бесполезна

product_data.keys.max { |a, b| month_map[a].to_i <=> month_map[b].to_i } unless product_data[current_month]
end

def get_min_price(hash)
min_year_price = Float::INFINITY
result = {}
hash.each do |year, year_hash|
min_month_data = find_min_month(year_hash)
min_year_data = find_min_year(year, min_month_data, min_year_price)
min_year_price = min_year_data['price'] if min_year_data['price']
result = actual_data(result, min_year_data)
end
result
end

def find_min_month(year_hash, min_month_price = Float::INFINITY, min_month = nil)
year_hash.each do |month, month_hash|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

параметры не нужны, объяви переменные внутри метода

price = month_hash['Minsk']
next unless price

if price < min_month_price
min_month_price = price
min_month = month
end
end
{ 'price' => min_month_price, 'month' => min_month }
end

def find_min_year(year, min_month_data, min_year_price)
result = {}
min_month_price = min_month_data['price']
result['month'] = min_month_data['month']
if min_month_price < min_year_price
result['price'] = min_month_price
result['year'] = year
end
result
end

def get_max_price(hash)
max_year_price = 0
result = {}
hash.each do |year, year_hash|
max_month_data = find_max_month(year_hash)
max_year_data = find_max_year(year, max_month_data, max_year_price)
max_year_price = max_year_data['price'] if max_year_data['price']
result = actual_data(result, max_year_data)
end
result
end

def find_max_month(year_hash, max_month_price = 0, max_month = nil)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

последние два параметра не нужны, объяви переменные в методе
а лучше используй select, max_by

year_hash.each do |month, month_hash|
price = month_hash['Minsk']
next unless price

if price > max_month_price
max_month_price = price
max_month = month
end
end
{ 'price' => max_month_price, 'month' => max_month }
end

def find_max_year(year, max_month_data, max_year_price)
result = {}
max_month_price = max_month_data['price']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Используй max_by

result['month'] = max_month_data['month']
if max_month_price > max_year_price
result['price'] = max_month_price
result['year'] = year
end
result
end

def actual_data(result, year_data)
result['month'] = year_data['month']
result['price'] = year_data['price'] if year_data['price']
result['year'] = year_data['year'] if year_data['year']
result
end

def get_similar_price_products(data, products)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/AbcSize: Assignment Branch Condition size for get_similar_price_products is too high. [15.39/15]
Metrics/MethodLength: Method has too many lines. [11/10]

price = data['price']
year = data['year']
month = data['month']
origin_product = data['product']
form_similar_products_array(products, price, year, month, origin_product)
end

def form_similar_products_array(products, price, year, month, origin_product)
result = []
products.each do |product, product_data|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

products.select
и не понадобится result

next unless product_data[year]

next unless product_data[year][month]

result.push(product) if product_data[year][month]['Minsk'] == price && product != origin_product
end
result
end

def first_level(key, recent_price_data)
puts ''
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just

puts

puts key.capitalize + ' is ' + recent_price_data['price'].to_s + ' BYN in Minsk these days.'
end

def second_level_min_price(product_data, month_map)
min_price = get_min_price(product_data)
puts 'Lowest was on ' + min_price['year'] + '/' + month_map[min_price['month']].to_s + ' at price '
print min_price['price'].to_s + ' BYN'
end

def second_level_max_price(product_data, month_map)
max_price = get_max_price(product_data)
puts 'Maximum was on ' + max_price['year'] + '/' + month_map[max_price['month']].to_s + ' at price '
print max_price['price'].to_s + ' BYN'
end

def third_level(recent_price_data, products)
similar_products = get_similar_price_products(recent_price_data, products)
if similar_products.empty?
puts 'No products for similar price'
else
puts 'For similar price you also can afford'
puts similar_products
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Layout/EmptyLines: Extra blank line detected.

def make_products_container
regions = ['Brest', 'Vitebsk', 'Gomel', 'Grodno', 'Minsk', 'Minsk Region', 'Mogilyov']
products = {}
file_paths = Dir['./data/*']
file_paths.each do |file_path|
file_instance = get_file_instance(file_path)
fetch_products_data(file_instance, products, regions) if file_instance
end
products
end

def user_wish(products)
puts 'What price are you looking for?'
word = gets.chomp.downcase.encode('UTF-8')
products.keys.select { |key| key.include?(word) }
end

def month_map_former
RGBD marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не нужен метод, можно обойтись константой

{
'январь' => 1, 'февраль' => 2,
'март' => 3, 'апрель' => 4,
'май' => 5, 'июнь' => 6,
'июль' => 7, 'авуст' => 8,
'сентябрь' => 9, 'октябрь' => 10,
'ноябрь' => 11, 'декабрь' => 12
}
end

def process_request(products, key, month_map)
recent_price_data = get_recent_price_data(key, products, month_map)
first_level(key, recent_price_data)
second_level_min_price(products[key], month_map)
second_level_max_price(products[key], month_map)
third_level(recent_price_data, products)
end

def main

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/AbcSize: Assignment Branch Condition size for main is too high. [20.25/15]
Metrics/MethodLength: Method has too many lines. [17/10]

month_map = month_map_former
products = make_products_container
loop do
keys = user_wish(products)
puts word.capitalize + ' can not be found in database' if keys.empty?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

дважды проверяется одно условие. лучше так

if keys.empty?
  puts ...
  next
end
...

keys.each { |key| process_request(products, key, month_map) } unless keys.empty?
end
end

main