clicks 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 75c4fd4c1763c9eff3c4600079fa58e566a123075fe9077546e36a220f5bb3af
4
+ data.tar.gz: a5d53cfc61f59a979653fac9b66e8cb268f802e5182d90aaf014970180dcc790
5
+ SHA512:
6
+ metadata.gz: 9aca8e6ca897216ae9c9c7e355ca517e2d3d92265ccd1669e353ccc849ab6a0c6cedbae00337ad7c4a8c592426f76e4b29dbaa1df4f088f31bef072b08a4091e
7
+ data.tar.gz: 1a51fbb6c1d0dedca61fecff44b4665ab9b3078c75a20e14cd3916b62a39c9bdf287040dfeab62089f1d5d1101448c1d1e024d432df77a74ae243ce8db71b7de
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/all'
4
+ require 'pry'
5
+
6
+ module Clicks
7
+ class ClicksManagement
8
+ def initialize(hash_clicks, options)
9
+ @result = []
10
+ @candidates = Array.new
11
+ @limit = if options.present? && options[:limit].present?
12
+ options[:limit].to_i
13
+ else
14
+ 10
15
+ end
16
+ perform(hash_clicks)
17
+ end
18
+
19
+ def perform(hash_clicks)
20
+ clicks = filter_clicks(group_by_ip(hash_clicks))
21
+ clean_massive_clicks_per_ip(clicks)
22
+ end
23
+
24
+ def group_by_ip(clicks)
25
+ clicks.group_by {|record| record['ip']}
26
+ end
27
+
28
+ def filter_clicks(clicks)
29
+ clicks.each do |_k, v|
30
+ if v.size == 1
31
+ @result.push(v.first)
32
+ else
33
+ most_expensive_one_per_group(v)
34
+ end
35
+ end
36
+ @result
37
+ end
38
+
39
+ def clean_massive_clicks_per_ip(clicks)
40
+ group_by_ip(clicks).delete_if{|k,v| v.size >= @limit}
41
+ end
42
+
43
+
44
+ def most_expensive_one_per_group(clicks_by_ip)
45
+ selected_record_within_one_hour(clicks_by_ip)
46
+ end
47
+
48
+ def selected_record_within_one_hour(clicks)
49
+ clicks.each_with_index do |record, index|
50
+ (index...clicks.size).each do |comparator_position|
51
+ if comparator_position > index
52
+ if eligible_diff_time?(clicks[comparator_position]["timestamp"], record["timestamp"])
53
+ push_to_collection(@candidates, record)
54
+ push_to_collection(@candidates, clicks[comparator_position])
55
+ else
56
+ if @candidates.blank?
57
+ break if manage_record_with_no_siblings(record, clicks, index)
58
+ else
59
+ manage_last_sibling(record)
60
+ break
61
+ end
62
+ end
63
+ elsif index==clicks.size-1
64
+ manage_last_click(record)
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ def manage_last_click(record)
71
+ return manage_candidates if array_contains?(@candidates, record)
72
+
73
+ push_to_collection(@result, record)
74
+ end
75
+
76
+ def manage_last_sibling(record)
77
+ push_to_collection(@candidates, record)
78
+ manage_candidates
79
+ end
80
+
81
+ def manage_record_with_no_siblings(record, clicks, index)
82
+ if (!eligible_diff_time?(record["timestamp"], clicks[index-1]["timestamp"]) && !eligible_diff_time?(clicks[index+1]["timestamp"], record["timestamp"])) || index.zero?
83
+ push_to_collection(@result, record)
84
+ return true
85
+ end
86
+ end
87
+
88
+ def records_from_different_ips?(record_1, record_2)
89
+ record_1["ip"] != record_2["ip"]
90
+ end
91
+
92
+ def push_to_collection(collection, record)
93
+ collection.push(record) unless array_contains?(collection, record)
94
+ end
95
+
96
+ def manage_candidates
97
+ duplicated_amount_clicks = select_duplicated_records
98
+ if duplicated_amount_clicks.count == 1
99
+ add_to_result(duplicated_amount_clicks.first)
100
+ else
101
+ winner = most_recent_one(duplicated_amount_clicks)
102
+ push_to_collection(@result, winner)
103
+ end
104
+ @candidates = []
105
+ end
106
+
107
+ def select_duplicated_records
108
+ candidates_ordered_amount = candidates_by_amount
109
+ candidates_ordered_amount.select do |click|
110
+ click["amount"] == candidates_ordered_amount[0]["amount"]
111
+ end
112
+ end
113
+
114
+ def add_to_result(record)
115
+ push_to_collection(@result, record) unless compare_dates_diff(@result.last, record)
116
+ end
117
+
118
+ def compare_dates_diff(record_1, record_2)
119
+ eligible_diff_time?(record_1["timestamp"], record_2["timestamp"])
120
+ end
121
+
122
+ def most_recent_one(clicks)
123
+ clicks.sort_by { |hsh| Time.parse(hsh["timestamp"]) }.reverse!.first
124
+ end
125
+
126
+ def array_contains?(array, record)
127
+ array.each { |click| return true if click == record }
128
+ false
129
+ end
130
+
131
+ def candidates_by_amount
132
+ @candidates.sort_by { |hsh| -hsh["amount"] }
133
+ end
134
+
135
+ def eligible_diff_time?(time_end, time_start)
136
+ puts "Hora final"
137
+ puts time_end
138
+ puts "hora comienzo"
139
+ puts time_start
140
+ time_end.to_time&.hour == time_start.to_time&.hour
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ module Clicks
5
+ class Serializer
6
+ def initialize(options = nil)
7
+ @path = if options.present? && options[:path].present?
8
+ options[:path].to_s
9
+ else
10
+ "./lib/clicks.json"
11
+ end
12
+ end
13
+ def read_file
14
+ file = File.read(@path)
15
+ parsed_file = JSON.parse(file)
16
+ parsed_file
17
+ end
18
+ def write_file(clicks)
19
+
20
+ end
21
+ end
22
+ end
data/lib/clicks.rb ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "clicks/clicks_management"
4
+ require "clicks/serializer"
5
+
6
+ module Click
7
+ class Error < StandardError; end
8
+ def self.call(options = nil)
9
+ serializer = if options.present?
10
+ Clicks::Serializer.new(options)
11
+ else
12
+ Clicks::Serializer.new
13
+ end
14
+ clicks_list = serializer.read_file
15
+ Clicks::ClicksManagement.new(clicks_list, options)
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clicks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - María Teresa Simancas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-02-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Given a json file, will get clicks records by following an specific criteria.
14
+ email: teresasimancasfdez@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/clicks.rb
20
+ - lib/clicks/clicks_management.rb
21
+ - lib/clicks/serializer.rb
22
+ homepage:
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 2.6.3
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubygems_version: 3.0.3
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: Clicks gem
45
+ test_files: []