Skip to content

Instantly share code, notes, and snippets.

@2xG
Created May 29, 2020 07:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 2xG/71f0a448d0e743d3de32b83eeb777e6c to your computer and use it in GitHub Desktop.
Save 2xG/71f0a448d0e743d3de32b83eeb777e6c to your computer and use it in GitHub Desktop.
# Тут находится программа, выполняющая обработку данных из файла.
# Тест показывает как программа должна работать.
# В этой программе нужно обработать файл данных 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