rslog 0.0.15 → 0.0.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e78583883f5087e1ce4e44c7d497ce68f1d7d9b37500bfc8223b4316a7b83853
4
- data.tar.gz: 31f56aadc5936705e58b6e1b1f85b6b141d288e5d58acb542c1ef929d0cb2727
3
+ metadata.gz: '089ce1f53d07365d2cd5a8a132d3f016fd971aec94fb5e1d7d097b83c378d16b'
4
+ data.tar.gz: 690f6b582c62d555192f003bb9bf48f47c05c73e6144663fc5271ef263a8a6e2
5
5
  SHA512:
6
- metadata.gz: 29ebd59a174be7ff7841bf2216b8520752067bddf0a81edfe1f46ad87df25c1f9377bd742ffccd1cb9b2367810ca4bbaf5fe6970e7cb34d2b3c1ddfea480fe4c
7
- data.tar.gz: 0adb1f65ce181f65cb3a0415d9145c39c46c282236b4f4f8da8ae765f3f4a8319b3ccb44ef2ec2f2268cdc593c549cf1b3353c315b4e01277c1af13e85c2cb47
6
+ metadata.gz: 2607d6b3ba40a13ecba89d214d0ef3d92d8d7b28b3b0dedf96942b01ea939efd287797ad4fe56e99c6986eac2dcbe53feca954abe41b69f14633ed9a79249f82
7
+ data.tar.gz: f68723a370022e15d2df26516b60725cad3b20d60a3c59bc3d7c2fc55f4146d874cbd123b1900896f7cc5eeab9dbff3af027241a3e8d57fc1f41c734283c25c8
data/lib/rslog.rb CHANGED
@@ -8,47 +8,47 @@ require_relative 'rslog/presenter'
8
8
  require 'set'
9
9
 
10
10
  module RSlog
11
- VERSION = '0.0.15'
11
+ VERSION = '0.0.16'
12
12
 
13
- class Main
13
+ # Module to hold main process
14
+ #
15
+ module Main
14
16
  def self.run
15
- file_names = RSlog::ArgsHandler.handle(ARGV)
16
-
17
- return unless file_names.any?
18
-
19
17
  file_names.each do |file_name|
20
- unless file_names.all?{|f| File.file?(f) }
21
- puts "There is no file names given. Check input."
22
- return
23
- end
24
-
18
+ puts "Statistics for file #{file_name}"
19
+
25
20
  lines = IO.readlines(file_name)
26
21
 
27
22
  RSlog::Validator.execute(lines)
28
-
29
- config_sets.each do |conf|
30
- parsed = RSlog::Parser.new(lines, conf).execute
31
- RSlog::Presenter.new(parsed, conf).present
32
- end
23
+
24
+ process(config_sets, lines)
25
+ end
26
+ end
27
+
28
+ def self.process(config_sets, lines)
29
+ config_sets.each do |conf|
30
+ parsed = RSlog::Parser.new(lines, conf).execute
31
+ RSlog::Presenter.new(parsed, conf).present
33
32
  end
34
33
  end
35
-
34
+
35
+ def self.file_names
36
+ file_names = RSlog::ArgsHandler.new(ARGV).handle
37
+ return file_names if file_names.all? { |file_name| File.file?(file_name) }
38
+
39
+ puts 'There is no file names given. Check input.'
40
+ []
41
+ end
42
+
36
43
  def self.config_sets
37
- [
38
- { title: %(List of webpages with most page views ordered from most pages views to less page views:),
39
- format_string: "%-20s %3d",
40
- suffix: "visits",
41
- calc: proc { |visits| visits.size } },
42
-
43
- { title: "List of webpages with most unique page views also ordered:",
44
- format_string: "%-20s %3d",
45
- suffix: 'unique views',
46
- calc: proc { |visits| Set.new(visits).size } },
47
-
48
- { title: "Average visits sorted:",
49
- suffix: 'average visits',
50
- calc: proc { |visits| Set.new(visits).size.to_f / visits.size } }
51
- ]
44
+ [{ title: %(List of webpages with most page views ordered from most pages views to less page views:),
45
+ # head_titles: %w[Url Visits Average],
46
+ head_titles: %w[Url Visits],
47
+ calc: proc { |visits| visits.size } },
48
+ { title: 'List of webpages with most unique page views also ordered:',
49
+ # head_titles: %w[Url Unique\ views Average],
50
+ head_titles: %w[Url Unique\ views],
51
+ calc: proc { |visits| Set.new(visits).size } }]
52
52
  end
53
53
  end
54
54
  end
@@ -1,19 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Class to hold data and implement processing
4
- #
5
3
  module RSlog
6
- module ArgsHandler
7
- def self.handle(args)
8
- options = args.select{|el| !(el =~ /^-/).nil?}
9
- file_names = args - options
4
+ # Class to parse options and arguments
5
+ #
6
+ # returns Array of file names
7
+ #
8
+ class ArgsHandler
9
+ attr_reader :args, :options
10
10
 
11
- puts "R(uby)S(imple)log statistics" if options.delete('-h') || args.empty?
12
- puts "Version #{RSlog::VERSION}" if options.delete('-v') || args.empty?
13
- puts "Unknown options #{options.join(', ')}" if options.any?
11
+ def initialize(args)
12
+ @args = args
13
+ @options = @args.select { |el| el =~ /^-/ }
14
+ end
15
+
16
+ def handle
17
+ if options.any? || args.empty?
18
+ _handle_options
19
+ return []
20
+ end
21
+
22
+ # file_names array
23
+ args - options
24
+ end
25
+
26
+ private
27
+
28
+ def _handle_options
29
+ _show_help || _show_version || _show_unknown_options_warning
30
+ end
31
+
32
+ def _show_help
33
+ if options.delete('-h') || args.empty?
34
+ puts _help_message
35
+ return true
36
+ end
37
+ false
38
+ end
39
+
40
+ def _help_message
41
+ %[
42
+ R(uby)S(imple)log statistics
43
+ Usage:
44
+ > rslog filename[.log|.txt]
45
+
46
+ > rslog [-h|-v]
47
+ -h - show this info
48
+ -v - show version
49
+ ]
50
+ end
51
+
52
+ def _show_version
53
+ if @options.delete('-v')
54
+ puts " Version #{RSlog::VERSION}"
55
+ return true
56
+ end
57
+ false
58
+ end
14
59
 
15
- file_names
60
+ def _show_unknown_options_warning
61
+ if @options.any?
62
+ puts " Unknown options #{@options.join(', ')}"
63
+ return true
64
+ end
65
+ false
16
66
  end
17
67
  end
18
68
  end
19
-
data/lib/rslog/parser.rb CHANGED
@@ -1,25 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Class to hold data and implement processing
4
- #
5
3
  module RSlog
6
- class Parser
7
- attr_reader :calc, :separator
8
- attr_accessor :source, :container
4
+ # Class to hold data_processing methods
5
+ #
6
+ class DataProcessing
7
+ attr_reader :result
9
8
 
10
9
  def initialize(source, conf)
11
10
  @calc = conf.fetch(:calc) { proc }
12
- @separator = conf.fetch(:separator) { ' ' }
13
- @source = source
11
+ @separator = conf.fetch(:separator, ' ')
12
+ @result = Array(source)
13
+ end
14
+
15
+ # extract
16
+ def extract
17
+ @result = @result.map { |item| item.split(@separator) }
18
+ self
19
+ end
20
+
21
+ # group
22
+ def group
23
+ @result = @result.group_by { |url, _visits| url }.to_a
24
+ self
25
+ end
26
+
27
+ # calculate
28
+ def calculate
29
+ # calculate visits
30
+ @result = @result.map { |url, visits| [url, @calc.call(visits)] }
31
+ # calculate average
32
+ # @result = @result.map { |url, visits_qty| [url, visits_qty, (visits_qty.to_f / _total)] }
33
+ self
34
+ end
35
+
36
+ # sort
37
+ def order
38
+ @result = @result.sort_by { |_url, visits_by_page| visits_by_page }
39
+ @result.reverse!
40
+ self
41
+ end
42
+
43
+ private
44
+
45
+ # calculate total
46
+ def _total
47
+ @result.sum { |_url, visits_qty| visits_qty }
48
+ end
49
+ end
50
+
51
+ require 'forwardable'
52
+ # Class to parse data
53
+ #
54
+ class Parser
55
+ attr_reader :data_processing
56
+
57
+ extend Forwardable
58
+ def_delegators :@data_processing, :extract, :group, :calculate, :order
59
+
60
+ def initialize(source, conf)
61
+ @data_processing = DataProcessing.new(source, conf)
14
62
  end
15
63
 
16
64
  def execute
17
- Array(source)
18
- .map{|item| item.split(separator)} #extract, returns Array
19
- .group_by{|page_name, _visits| page_name } #group, returns Hash
20
- .map{|page_name, visits| [page_name, calc.call(visits)] } #calculate, returns Array
21
- .sort_by{|_page_name, visits_by_page| visits_by_page } #sort, returns Array
22
- .reverse
65
+ data_processing.extract.group.calculate.order.result
23
66
  end
24
67
  end
25
68
  end
@@ -1,39 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Class for format result according to passed 'format_string'
4
- #
5
- # result is array of formatted strings
6
- # e.g
7
- # [ "/about 1 visits",
8
- # "/about/2 1 visits",
9
- # "/home 1 visits",
10
- # "/contact 1 visits",
11
- # "/help_page/1 1 visits" ]
12
- #
13
3
  module RSlog
4
+ # Class for format result according to passed 'format_string'
5
+ #
6
+ # result is array of formatted strings
7
+ # e.g
8
+ # [ "/about 1 visits",
9
+ # "/about/2 1 visits",
10
+ # "/home 1 visits",
11
+ # "/contact 1 visits",
12
+ # "/help_page/1 1 visits" ]
13
+ #
14
14
  class Presenter
15
- attr_reader :title, :format_string, :suffix
16
- attr_accessor :source
17
-
15
+ LEFT_UP_CORNER = "\u250c"
16
+ RIGHT_UP_CORNER = "\u2510"
17
+ LEFT_DOWN_CORNER = "\u2514"
18
+ RIGHT_DOWN_CORNER = "\u2518"
19
+ VERTICAL_BORDER = "\u2502"
20
+ HORIZONTAL_BORDER = "\u2500"
21
+ VERTICAL_LEFT_BORDER = "\u251C"
22
+ VERTICAL_RIGHT_BORDER = "\u2524"
23
+
18
24
  def initialize(source, conf)
19
25
  @source = source
20
- @title = conf.fetch(:title) { 'Stat Pages' }
21
- @format_string = conf.fetch(:format_string) { "%-20s %5.2f" }
22
- @suffix = conf.fetch(:suffix) { 'visits' }
26
+ @col_size = conf.fetch(:col_size, 20)
27
+ @title = conf.fetch(:title, 'Stat Pages')
28
+ @formatter = conf.fetch(:formatter, "%-#{@col_size}s")
29
+ @columns = conf.fetch(:columns, @source&.first&.size || 1)
30
+ @head_titles = conf.fetch(:head_titles, Array.new(@columns, 'title'))
23
31
  end
24
-
32
+
25
33
  def present
26
- puts title
27
- puts _formatted
34
+ puts @title
35
+ puts _top_border
36
+ puts VERTICAL_BORDER + format(@formatter * @columns, *@head_titles) + VERTICAL_BORDER
37
+ puts _middle_border
38
+ puts _formatted_data
39
+ puts _bottom_border
28
40
  puts
29
41
  end
30
-
42
+
31
43
  private
32
-
33
- def _formatted
34
- source.map do |row|
35
- "#{format(format_string, *row)} #{suffix}"
36
- end
44
+
45
+ def _top_border
46
+ LEFT_UP_CORNER + _horisontal_line + RIGHT_UP_CORNER
47
+ end
48
+
49
+ def _middle_border
50
+ VERTICAL_LEFT_BORDER + _horisontal_line + VERTICAL_RIGHT_BORDER
51
+ end
52
+
53
+ def _bottom_border
54
+ LEFT_DOWN_CORNER + _horisontal_line + RIGHT_DOWN_CORNER
55
+ end
56
+
57
+ def _horisontal_line
58
+ HORIZONTAL_BORDER * @col_size * @columns
59
+ end
60
+
61
+ def _formatted_data
62
+ @source.map do |row|
63
+ row = row.map(&:to_s)
64
+ VERTICAL_BORDER + format(@formatter * @columns, *row).to_s + VERTICAL_BORDER
65
+ end
37
66
  end
38
67
  end
39
68
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Class to validate if we have valid data in lines, for example well formatted IPs
4
- #
5
- # Checks if IPs are comply with regex
6
- # Output message "Valid IPs"/"Invalid IPs"
7
- #
8
3
  module RSlog
4
+ # Class to validate if we have valid data in lines, for example well formatted IPs
5
+ #
6
+ # Checks if IPs are comply with regex
7
+ # Output message "Valid IPs"/"Invalid IPs"
8
+ #
9
9
  module Validator
10
10
  TEMPLATES = {
11
11
  # IP address regex, source https://regexr.com/38odc
@@ -23,8 +23,6 @@ module RSlog
23
23
  puts
24
24
  end
25
25
 
26
- private
27
-
28
26
  def self.valid?(source)
29
27
  return :valid if source.all? TEMPLATES[:ip]
30
28
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rslog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Eremeev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2021-06-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby script to get overall Statistic for weblog logs!
14
14
  email: a.eremeev@outlook.com