page_view_parser 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dc62810f4d5cdcc46810bf3cb009e2173e086f40289103c6de060ebef3916bed
4
+ data.tar.gz: 4f5c6a7d74a12615f98c5a8439c26bfcba6c8d04509033322792f8b2d154b7b5
5
+ SHA512:
6
+ metadata.gz: c361c7e10da596db6600f87b500d3a50dff9646d162f6a59dacf14493d9a72e8dbdbc9db672a87197afb9e307df66fe689894a089450bee05a0684ce2c5d9e1b
7
+ data.tar.gz: c196b8b6fa9e18ed3784d4c04cdb22fbba05a4d740d12245627c9a3cd08ef9f97c2fda524bb91b1c5e1a8decddb55894dedba7e025d7e5b47469405e45dad5ca
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'page.rb'
4
+
5
+ # Takes a log file where each line has the format of:
6
+ # PAGE_NAME VISITOR_IP
7
+ # eg.
8
+ # /about 123.456.789.123
9
+ # and turns it into a list of 'page' objects.
10
+ # The target object to turn each line in the log into is
11
+ # expected to be able to receive page: and visitor: keyword arguments.
12
+ class LogParser
13
+ class MalformedLog < StandardError; end
14
+
15
+ def initialize(page_class: Page)
16
+ @page_class = page_class
17
+ end
18
+
19
+ # arranging by path in a hash first instead of straight into an Array to avoid
20
+ # an iteration of the whole list so far on each check for existence. Instead,
21
+ # using the quicker lookup by key to then later just extract the values into
22
+ # the list.
23
+ def parse_from_file(file_path:)
24
+ page_views = {}.tap do |pages|
25
+ File.open(file_path).each do |line|
26
+ build_page line, pages
27
+ end
28
+ end
29
+ [].push(*page_views.values)
30
+ end
31
+
32
+ def parse_from_string(string:)
33
+ page_views = {}.tap do |pages|
34
+ string.split("\n").each do |line|
35
+ build_page line, pages
36
+ end
37
+ end
38
+ [].push(*page_views.values)
39
+ end
40
+
41
+ private
42
+
43
+ attr_reader :file_path, :page_class
44
+
45
+ def build_page(line, pages)
46
+ path, visitor = line.split(' ')
47
+ raise MalformedLog, 'Log malformed' if
48
+ path.nil? || visitor.nil?
49
+
50
+ if pages[path].nil? # The current path hasn't been seen before
51
+ pages[path] = page_class.new(path: path, visitors: [visitor])
52
+ else
53
+ pages[path].visitors << visitor
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Represents a record of a page that can be visited, holding a record of the
4
+ # visitors via their ip address
5
+ class Page
6
+ attr_reader :path, :visitors
7
+
8
+ def initialize(path:, visitors: [])
9
+ @path = path
10
+ @visitors = visitors
11
+ end
12
+
13
+ def <<(visitor)
14
+ visitors << visitor
15
+ end
16
+
17
+ def view_count
18
+ visitors.count
19
+ end
20
+
21
+ def unique_view_count
22
+ visitors.uniq.count
23
+ end
24
+
25
+ def to_s(strategy: DEFAULT_PAGE_PRESENTATION_STRATEGY)
26
+ strategy.call(self)
27
+ end
28
+
29
+ DEFAULT_PAGE_PRESENTATION_STRATEGY = proc do |page|
30
+ "#{page.path} visited by #{page.visitors.uniq}"
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PageListFormatStrategies
4
+ # Base class that represents the interface all pages format strategy
5
+ # classes must implement.
6
+ class Base
7
+ def initialize(pages:)
8
+ @pages = pages
9
+ end
10
+
11
+ # It is expected that all sub class strategies will override this method and
12
+ # provide it's own formatting algorithm / behaviour. The result however is
13
+ # always an array of the new format the Pages have taken.
14
+ def call
15
+ pages
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :pages
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../page_list_format_strategies/base.rb'
4
+
5
+ module PageListFormatStrategies
6
+ # A presentation strategy that presents a list of pages in descending order
7
+ # by the number of unique views with its unique view count.
8
+ class WithUniqueViewCount < Base
9
+ def call
10
+ presentation_strategy = proc do |page|
11
+ str = ''
12
+ str += "#{page.path} #{page.unique_view_count} "
13
+ str += "unique visit#{page.unique_view_count > 1 ? 's' : ''}"
14
+ str
15
+ end
16
+
17
+ pages.sort_by { |page| -page.unique_view_count }
18
+ .map { |page| page.to_s(strategy: presentation_strategy) }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../page_list_format_strategies/base.rb'
4
+
5
+ module PageListFormatStrategies
6
+ # A presentation strategy that presents a list of page paths in descending
7
+ # order (highest number of views at the top) with their total view count.
8
+ class WithViewCount < Base
9
+ def call
10
+ presentation_strategy = proc do |page|
11
+ "#{page.path} #{page.view_count} visit#{page.view_count > 1 ? 's' : ''}"
12
+ end
13
+
14
+ pages.sort_by { |page| -page.view_count }
15
+ .map { |page| page.to_s(strategy: presentation_strategy) }
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: page_view_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - John Hayes-Reed
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: guard
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: guard-rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.85'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.85'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.18'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.18'
83
+ description: A simple webserver parser that outputs page count information
84
+ email: john.hayes.reed@gmail.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - lib/log_parser.rb
90
+ - lib/page.rb
91
+ - lib/page_list_format_strategies/base.rb
92
+ - lib/page_list_format_strategies/with_unique_view_count.rb
93
+ - lib/page_list_format_strategies/with_view_count.rb
94
+ homepage:
95
+ licenses: []
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubygems_version: 3.0.6
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Page View Parser
116
+ test_files: []