diff --git a/ruby/programs/click_handler/click_handler.rb b/ruby/programs/click_handler/click_handler.rb new file mode 100644 index 0000000..2132ff5 --- /dev/null +++ b/ruby/programs/click_handler/click_handler.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +require 'json' +require 'date' + +# Class having json file operations +class JsonFilehandler + def self.read_file(path) + File.open(path).read + end + + def self.write_file(path, res) + File.open(path, 'w+') do |f| + f.write("[\n") + res.each_with_index do |click, idx| + key_val = click.map { |k, v| "#{k.to_json}:#{v.to_json}" }.join(', ') + result = "{ #{key_val} }\n" + result += ',' if idx != res.size - 1 + f.write(result) + end + f.write(']') + end + end +end + +# Class having all data parsing operations +class Parser + def self.to_json(file_data) + JSON.parse(file_data) + end + + def self.collect_valid_clicks(click_data) + click_freq = Hash.new(0) + click_data.each { |ele| click_freq[ele['ip']] += 1 } + # Remove all IPs with clicks greater than 10 + click_freq.each { |k, v| click_freq.delete(k) if v >= 10 } + click_ips = click_freq.keys + click_data.select { |ele| click_ips.include?(ele['ip']) } + end + + def self.clicks_per_period(valid_clicks) + ip_amt_per_period = {} + ip_timestamp_per_period = {} + valid_clicks.each do |click| + period = DateTime.parse(click['timestamp']).hour + if ip_amt_per_period.key?(click['ip']) + if ip_amt_per_period[click['ip']].key?(period) && ip_amt_per_period[click['ip']][period] < click['amount'] + ip_amt_per_period[click['ip']][period] = click['amount'] + ip_timestamp_per_period[click['ip']].merge!({ period => click['timestamp'] }) + elsif ip_amt_per_period[click['ip']].key?(period) && ip_amt_per_period[click['ip']][period] > click['amount'] + next + elsif ip_amt_per_period[click['ip']].key?(period) && ip_amt_per_period[click['ip']][period] == click['amount'] + if DateTime.parse(click['timestamp']) < DateTime.parse(ip_time) + ip_timestamp_per_period[click['ip']][period] = click['timestamp'] + end + else + ip_amt_per_period[click['ip']].merge!({ period => click['amount'] }) + ip_timestamp_per_period[click['ip']].merge!({ period => click['timestamp'] }) + end + + else + ip_amt_per_period[click['ip']] = {} + ip_timestamp_per_period[click['ip']] = {} + ip_amt_per_period[click['ip']][period] = click['amount'] + ip_timestamp_per_period[click['ip']][period] = click['timestamp'] + end + end + [ip_amt_per_period, ip_timestamp_per_period] + end + + def self.form_output_array(ip_amt_per_period, ip_timestamp_per_period) + res = [] + ip_amt_per_period.each do |k, v| + v.each do |period, value| + res.push({ 'ip' => k, 'timestamp' => ip_timestamp_per_period[k][period], 'amount' => value }) + end + end + res + end +end + +# Class having main handler for finding most expensive click +class ClickHandler + def self.main + file_data = JsonFilehandler.read_file('clicks.json') + click_data = Parser.to_json(file_data) + valid_clicks = Parser.collect_valid_clicks(click_data) + ip_amt_per_period, ip_timestamp_per_period = Parser.clicks_per_period(valid_clicks) + res = Parser.form_output_array(ip_amt_per_period, ip_timestamp_per_period) + JsonFilehandler.write_file('result.json', res) + end +end + +ClickHandler.main diff --git a/ruby/programs/click_handler/clicks.json b/ruby/programs/click_handler/clicks.json new file mode 100644 index 0000000..f1ec2f1 --- /dev/null +++ b/ruby/programs/click_handler/clicks.json @@ -0,0 +1,34 @@ +[ + { "ip":"22.22.22.22", "timestamp":"3/11/2020 02:02:58", "amount": 7.00 }, + { "ip":"11.11.11.11", "timestamp":"3/11/2020 02:12:32", "amount": 6.50 }, + { "ip":"11.11.11.11", "timestamp":"3/11/2020 02:13:11", "amount": 7.25 }, + { "ip":"44.44.44.44", "timestamp":"3/11/2020 02:13:54", "amount": 8.75 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 05:02:45", "amount": 11.00 }, + { "ip":"44.44.44.44", "timestamp":"3/11/2020 06:32:42", "amount": 5.00 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 06:35:12", "amount": 2.00 }, + { "ip":"11.11.11.11", "timestamp":"3/11/2020 06:45:01", "amount": 12.00 }, + { "ip":"11.11.11.11", "timestamp":"3/11/2020 06:59:59", "amount": 11.75 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 07:01:53", "amount": 1.00 }, + { "ip":"11.11.11.11", "timestamp":"3/11/2020 07:02:54", "amount": 4.50 }, + { "ip":"33.33.33.33", "timestamp":"3/11/2020 07:02:54", "amount": 15.75 }, + { "ip":"66.66.66.66", "timestamp":"3/11/2020 07:02:54", "amount": 14.25 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 07:03:15", "amount": 12.00 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 08:02:22", "amount": 3.00 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 09:41:50", "amount": 4.00 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 10:02:54", "amount": 5.00 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 11:05:35", "amount": 10.00 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 13:02:21", "amount": 6.00 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 13:02:40", "amount": 8.00 }, + { "ip":"44.44.44.44", "timestamp":"3/11/2020 13:02:55", "amount": 8.00 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 13:33:34", "amount": 8.00 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 13:42:24", "amount": 8.00 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 13:47:44", "amount": 6.25 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 14:02:54", "amount": 4.25 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 14:03:04", "amount": 5.25 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 15:12:55", "amount": 6.25 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 16:02:36", "amount": 8.00 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 16:22:11", "amount": 8.50 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 17:18:19", "amount": 11.25 }, + { "ip":"55.55.55.55", "timestamp":"3/11/2020 18:19:20", "amount": 9.00 }, + { "ip":"22.22.22.22", "timestamp":"3/11/2020 23:59:59", "amount": 9.00 } +] diff --git a/ruby/programs/click_handler/result.json b/ruby/programs/click_handler/result.json new file mode 100644 index 0000000..d90d1ed --- /dev/null +++ b/ruby/programs/click_handler/result.json @@ -0,0 +1,10 @@ +[ +{ "ip":"11.11.11.11", "timestamp":"3/11/2020 02:13:11", "amount":7.25 } +,{ "ip":"11.11.11.11", "timestamp":"3/11/2020 06:45:01", "amount":12.0 } +,{ "ip":"11.11.11.11", "timestamp":"3/11/2020 07:02:54", "amount":4.5 } +,{ "ip":"44.44.44.44", "timestamp":"3/11/2020 02:13:54", "amount":8.75 } +,{ "ip":"44.44.44.44", "timestamp":"3/11/2020 06:32:42", "amount":5.0 } +,{ "ip":"44.44.44.44", "timestamp":"3/11/2020 13:02:55", "amount":8.0 } +,{ "ip":"33.33.33.33", "timestamp":"3/11/2020 07:02:54", "amount":15.75 } +,{ "ip":"66.66.66.66", "timestamp":"3/11/2020 07:02:54", "amount":14.25 } +] \ No newline at end of file