Created
May 29, 2020 07:18
-
-
Save 2xG/71f0a448d0e743d3de32b83eeb777e6c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Тут находится программа, выполняющая обработку данных из файла. | |
# Тест показывает как программа должна работать. | |
# В этой программе нужно обработать файл данных data_large.txt. | |
# Задача: | |
# Оптимизировать программу; | |
# Программа должна корректно обработать файл data_large.txt; | |
# Провести рефакторинг при необходимости | |
# Представить время обработки до и после | |
require 'json' | |
require 'pry' | |
require 'date' | |
require 'minitest/autorun' | |
require 'set' | |
class User | |
attr_reader :id, :first_name, :last_name, :age | |
def self.parse(string) | |
fields = string.split(',') | |
attributes = { | |
id: fields[1].to_i, | |
first_name: fields[2], | |
last_name: fields[3], | |
age: fields[4].to_i | |
} | |
self.new attributes | |
end | |
def initialize(attributes) | |
@id = attributes.fetch(:id).to_i | |
@first_name = attributes.fetch(:first_name) | |
@last_name = attributes.fetch(:last_name) | |
@age = attributes.fetch(:age).to_i | |
@sessions = [] | |
@total_time = 0 | |
@longest_session = 0 | |
@browsers = [] | |
@used_ie = false | |
@always_used_chrome = nil | |
end | |
def add_session(session) | |
@sessions << session | |
@total_time += session.time | |
@longest_session = session.time if session.time > @longest_session | |
@browsers << session.browser | |
@used_ie = @used_ie || !!(session.browser.upcase =~ /INTERNET EXPLORER/) | |
if @always_used_chrome.nil? | |
@always_used_chrome = !!(session.browser.upcase =~ /CHROME/) | |
else | |
@always_used_chrome = @always_used_chrome && !!(session.browser.upcase =~ /CHROME/) | |
end | |
end | |
def full_name | |
first_name + ' ' + last_name | |
end | |
def stats | |
{ | |
sessionsCount: @sessions.count, | |
totalTime: @total_time.to_s + ' min.', | |
longestSession: @longest_session.to_s + ' min.', | |
browsers: @browsers.map(&:upcase).sort.join(', '), | |
usedIE: @used_ie, | |
alwaysUsedChrome: @always_used_chrome, | |
dates: session_dates | |
} | |
end | |
private | |
def session_dates | |
@sessions.map(&:date).sort.reverse.map(&:iso8601) | |
end | |
end | |
class Session | |
attr_reader :id, :user_id, :browser, :time, :date | |
def self.parse(string) | |
fields = string.split(',') | |
attributes = { | |
user_id: fields[1].to_i, | |
session_id: fields[2].to_i, | |
browser: fields[3], | |
time: fields[4].to_i, | |
date: fields[5] | |
} | |
self.new attributes | |
end | |
def initialize(attributes) | |
@user_id = attributes[:user_id].to_i | |
@id = attributes[:session_id].to_i | |
@browser = attributes[:browser] | |
@time = attributes[:time].to_i | |
@date = Date.parse(attributes[:date]) | |
end | |
end | |
class Report | |
def self.from_file(filename) | |
data = File.read(filename).split("\n") | |
self.new data | |
end | |
def initialize(data) | |
@users = [] | |
@session_count = 0 | |
@browsers = SortedSet[] | |
data.each do |line| | |
cols = line.split(',') | |
case cols[0] | |
when 'user' | |
user = User.parse line | |
@users[user.id] = user | |
when 'session' | |
session = Session.parse line | |
@users[session.user_id].add_session session | |
@session_count += 1 | |
@browsers << session.browser.upcase | |
else | |
raise 'Unknown line type' | |
end | |
end | |
end | |
# Отчёт в json | |
# - Сколько всего юзеров + | |
# - Сколько всего уникальных браузеров + | |
# - Сколько всего сессий + | |
# - Перечислить уникальные браузеры в алфавитном порядке через запятую и капсом + | |
# | |
# - По каждому пользователю | |
# - сколько всего сессий + | |
# - сколько всего времени + | |
# - самая длинная сессия + | |
# - браузеры через запятую + | |
# - Хоть раз использовал IE? + | |
# - Всегда использовал только Хром? + | |
# - даты сессий в порядке убывания через запятую + | |
def to_json | |
{ | |
totalUsers: @users.count, | |
uniqueBrowsersCount: @browsers.count, | |
totalSessions: @session_count, | |
allBrowsers: @browsers.to_a.join(','), | |
usersStats: user_stats | |
}.to_json | |
end | |
private | |
# Статистика по пользователям | |
def user_stats | |
@users.map { |user| [user.full_name, user.stats] }.to_h | |
end | |
end | |
def work(source_filename, result_filename) | |
report = Report.from_file(source_filename) | |
File.write(result_filename, "#{report.to_json}\n") | |
end | |
class TestMe < Minitest::Test | |
def setup | |
File.write('result.json', '') | |
File.write('data.txt', | |
'user,0,Leida,Cira,0 | |
session,0,0,Safari 29,87,2016-10-23 | |
session,0,1,Firefox 12,118,2017-02-27 | |
session,0,2,Internet Explorer 28,31,2017-03-28 | |
session,0,3,Internet Explorer 28,109,2016-09-15 | |
session,0,4,Safari 39,104,2017-09-27 | |
session,0,5,Internet Explorer 35,6,2016-09-01 | |
user,1,Palmer,Katrina,65 | |
session,1,0,Safari 17,12,2016-10-21 | |
session,1,1,Firefox 32,3,2016-12-20 | |
session,1,2,Chrome 6,59,2016-11-11 | |
session,1,3,Internet Explorer 10,28,2017-04-29 | |
session,1,4,Chrome 13,116,2016-12-28 | |
user,2,Gregory,Santos,86 | |
session,2,0,Chrome 35,6,2018-09-21 | |
session,2,1,Safari 49,85,2017-05-22 | |
session,2,2,Firefox 47,17,2018-02-02 | |
session,2,3,Chrome 20,84,2016-11-25 | |
') | |
end | |
def test_result | |
source_filename = ENV['REPORT_DATA_FILENAME'] || 'data.txt' | |
result_filename = ENV['REPORT_RESULT_FILENAME'] || 'result.json' | |
work source_filename, result_filename | |
expected_result = '{"totalUsers":3,"uniqueBrowsersCount":14,"totalSessions":15,"allBrowsers":"CHROME 13,CHROME 20,CHROME 35,CHROME 6,FIREFOX 12,FIREFOX 32,FIREFOX 47,INTERNET EXPLORER 10,INTERNET EXPLORER 28,INTERNET EXPLORER 35,SAFARI 17,SAFARI 29,SAFARI 39,SAFARI 49","usersStats":{"Leida Cira":{"sessionsCount":6,"totalTime":"455 min.","longestSession":"118 min.","browsers":"FIREFOX 12, INTERNET EXPLORER 28, INTERNET EXPLORER 28, INTERNET EXPLORER 35, SAFARI 29, SAFARI 39","usedIE":true,"alwaysUsedChrome":false,"dates":["2017-09-27","2017-03-28","2017-02-27","2016-10-23","2016-09-15","2016-09-01"]},"Palmer Katrina":{"sessionsCount":5,"totalTime":"218 min.","longestSession":"116 min.","browsers":"CHROME 13, CHROME 6, FIREFOX 32, INTERNET EXPLORER 10, SAFARI 17","usedIE":true,"alwaysUsedChrome":false,"dates":["2017-04-29","2016-12-28","2016-12-20","2016-11-11","2016-10-21"]},"Gregory Santos":{"sessionsCount":4,"totalTime":"192 min.","longestSession":"85 min.","browsers":"CHROME 20, CHROME 35, FIREFOX 47, SAFARI 49","usedIE":false,"alwaysUsedChrome":false,"dates":["2018-09-21","2018-02-02","2017-05-22","2016-11-25"]}}}' + "\n" | |
assert_equal expected_result, File.read(result_filename) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment