rmuh 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bdf1618724cb081a979f3b0f6a1a231fef6c1fa9
4
+ data.tar.gz: 240edd31827250c654009aa49db1642522f1a5e0
5
+ SHA512:
6
+ metadata.gz: e691a5b1275db1aec06541e22f7b2d31d75a5240785e8e3fed8240f2f03afec5eca50fa76b905f23a055ad9b9a19943405216e3d3f785f9ed3eb52f2302ff9a0
7
+ data.tar.gz: c0af65480abe5a18f00ecc934f32ed0e9a55724fde529677cbb109db6bdef7993b28d0ca3e86161b14a5a2bf01bcb91084e5c3c3da7ddf2064a4e3fa6ec4d74c
data/.gitignore ADDED
@@ -0,0 +1,33 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+ Gemfile.lock
12
+
13
+ ## Documentation cache and generated files:
14
+ /.yardoc/
15
+ /_yardoc/
16
+ /doc/
17
+ /rdoc/
18
+
19
+ ## Environment normalisation:
20
+ /.bundle/
21
+ /lib/bundler/man/
22
+
23
+ # for a library or gem, you might want to ignore these files since the code is
24
+ # intended to run in multiple environments; otherwise, check them in:
25
+ # Gemfile.lock
26
+ # .ruby-version
27
+ # .ruby-gemset
28
+
29
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
30
+ .rvmrc
31
+
32
+ # misc files
33
+ test.rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format Fuubar
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.0.0
5
+ - 1.9.3
6
+ notifications:
7
+ email:
8
+ - tim+travisci@timheckman.net
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # -*- coding: UTF-8 -*-
2
+ source 'https://rubygems.org'
3
+
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Tim Heckman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,19 @@
1
+ RMuh
2
+ ====
3
+ [![Build Status](https://img.shields.io/travis/theckman/rmuh/master.svg)](https://travis-ci.org/theckman/rpt-ruby)
4
+ [![MIT Licensed](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://tldrlegal.com/license/mit-license)
5
+ [![Coveralls Coverage](https://img.shields.io/coveralls/theckman/rmuh/master.svg)](https://coveralls.io/r/theckman/rmuh)
6
+ [![Code Climate](https://img.shields.io/codeclimate/github/theckman/rmuh.svg)](https://codeclimate.com/github/theckman/rmuh)
7
+
8
+ **RMuh**, a play on the name ArmA (Armed Assault), is a Ruby library for
9
+ interacting with ArmA 2 servers (specifically tested against Operation
10
+ Arrowhead servers).
11
+
12
+ In short, this `README` file usless right now. It is a work in progress.
13
+ Please refer to it in the future for more information as it should be helpful
14
+ then...
15
+
16
+ LICENSE
17
+ -------
18
+ **RMuh** is released under The MIT License. The full text of the license can be
19
+ found in the `LICENSE` file
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ # -*- coding: UTF-8 -*_
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ Rubocop::RakeTask.new(:rubocop) do |task|
8
+ task.patterns = [
9
+ 'lib/**/*.rb', 'spec/*_spec.rb', 'Rakefile', 'rmuh.gemspec', 'Gemfile'
10
+ ]
11
+ # task.formatters = ['files']
12
+ task.fail_on_error = true
13
+ end
14
+
15
+ task default: [:rubocop, :spec]
data/lib/rmuh.rb ADDED
@@ -0,0 +1,22 @@
1
+ # -*- coding: UTF-8 -*-
2
+ # The MIT License (MIT)
3
+
4
+ # Copyright (c) 2014 Tim Heckman
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
@@ -0,0 +1,56 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'httparty'
3
+ require 'ostruct'
4
+
5
+ module RMuh
6
+ module RPT
7
+ module Log
8
+ # TODO: Fetch Class documentation
9
+ #
10
+ class Fetch
11
+ include HTTParty
12
+ attr_accessor :cfg
13
+
14
+ def initialize(log_url, byte_start = 0, byte_end = nil)
15
+ @cfg = OpenStruct.new(
16
+ log_url: log_url,
17
+ byte_start: byte_start,
18
+ byte_end: byte_end
19
+ )
20
+ end
21
+
22
+ def byte_start=(bytes)
23
+ if bytes.is_a?(Integer)
24
+ @cfg.byte_start = bytes
25
+ else
26
+ fail ArgumentError, 'argument 1 must be an integer'
27
+ end
28
+ end
29
+
30
+ def byte_end=(bytes)
31
+ if bytes.nil? || bytes.is_a?(Integer)
32
+ @cfg.byte_end = bytes
33
+ else
34
+ fail ArgumentError, 'argument 1 must be nil or an integer'
35
+ end
36
+ end
37
+
38
+ def size
39
+ self.class.head(@cfg.log_url).headers['content-length'].to_i
40
+ end
41
+
42
+ def log
43
+ headers = { 'Range' => "bytes=#{@cfg.byte_start}-#{@cfg.byte_end}" }
44
+ response = self.class.get(@cfg.log_url, headers: headers)
45
+ StringIO.new(response.lines.map { |l| dos2unix(l) }.join)
46
+ end
47
+
48
+ private
49
+
50
+ def dos2unix(line)
51
+ line.gsub("\r\n", "\n")
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: UTF-8 -*-
2
+ module RMuh
3
+ module RPT
4
+ module Log
5
+ module Parsers
6
+ # This is the base RPT parser class. This does nothing but
7
+ # return each line as a Hash within an Array. There is no
8
+ # metadata extracted, it's a literal copy and paste of the
9
+ # provided log line. This class is primarily used as an example
10
+ # class to be used for subclassing of your own parser
11
+ #
12
+ class Base
13
+ def initialize(opts = {})
14
+ end
15
+
16
+ def parse(loglines)
17
+ fail(
18
+ ArgumentError, 'argument 1 must be a StringIO object'
19
+ ) unless loglines.is_a? StringIO
20
+
21
+ loglines.map do |line|
22
+ { type: :log, message: line }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,94 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'English'
3
+ require 'tzinfo'
4
+ require 'stringio'
5
+ require 'rmuh/rpt/log/parsers/base'
6
+ require 'rmuh/rpt/log/util/unitedoperations'
7
+ require 'rmuh/rpt/log/util/unitedoperationslog'
8
+
9
+ module RMuh
10
+ module RPT
11
+ module Log
12
+ module Parsers
13
+ # TODO: UnitedOperationsLog Class Documentation
14
+ #
15
+ class UnitedOperationsLog < RMuh::RPT::Log::Parsers::Base
16
+ include RMuh::RPT::Log::Util::UnitedOperations
17
+ extend RMuh::RPT::Log::Util::UnitedOperations
18
+ include RMuh::RPT::Log::Util::UnitedOperationsLog # Regexp Constants
19
+ extend RMuh::RPT::Log::Util::UnitedOperationsLog
20
+
21
+ def self.validate_opts(opts)
22
+ fail(
23
+ ArgumentError, 'arg 1 should be an instance of Hash'
24
+ ) unless opts.is_a?(Hash)
25
+ validate_bool_opt(opts, :to_zulu)
26
+ validate_timezone(opts)
27
+ validate_bool_opt(opts, :chat)
28
+ end
29
+
30
+ def initialize(opts = {})
31
+ self.class.validate_opts(opts)
32
+ @include_chat = opts[:chat].nil? ? false : opts[:chat]
33
+ @to_zulu = opts[:to_zulu].nil? ? true : opts[:to_zulu]
34
+ @timezone = opts[:timezone].nil? ? UO_TZ : opts[:timezone]
35
+ end
36
+
37
+ def parse(loglines)
38
+ unless loglines.is_a?(StringIO)
39
+ fail ArgumentError, 'arg 1 must be a StringIO object'
40
+ end
41
+ regex_matches(loglines)
42
+ end
43
+
44
+ private
45
+
46
+ def regex_matches(loglines)
47
+ loglines.map do |l|
48
+ line = nil
49
+ if GUID.match(l)
50
+ line = { type: :beguid }.merge(m_to_h($LAST_MATCH_INFO))
51
+ elsif @include_chat && CHAT.match(l)
52
+ line = { type: :chat }.merge(m_to_h($LAST_MATCH_INFO))
53
+ end
54
+ line_modifiers(line) unless line.nil?
55
+ end.compact
56
+ end
57
+
58
+ def line_modifiers(line)
59
+ when_am_i!(line)
60
+ zulu!(line, @timezone)
61
+ add_guid!(line)
62
+ line
63
+ end
64
+
65
+ def when_am_i!(line)
66
+ case line[:hour]
67
+ when 4..23
68
+ t = date_of_line_based_on_now
69
+ set_line_date!(line, t)
70
+ when 0..3
71
+ set_line_date!(line)
72
+ end
73
+ line
74
+ end
75
+
76
+ def date_of_line_based_on_now(time = Time.now)
77
+ if time.hour.between?(4, 23)
78
+ @timezone.now
79
+ else
80
+ @timezone.now - ONE_DAY
81
+ end
82
+ end
83
+
84
+ def set_line_date!(line, time = @timezone.now)
85
+ line[:year] = time.year
86
+ line[:month] = time.month
87
+ line[:day] = time.day
88
+ line
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,65 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'stringio'
3
+ require 'English'
4
+ require 'tzinfo'
5
+ require 'rmuh/rpt/log/parsers/base'
6
+ require 'rmuh/rpt/log/util/unitedoperations'
7
+ require 'rmuh/rpt/log/util/unitedoperationsrpt'
8
+
9
+ module RMuh
10
+ module RPT
11
+ module Log
12
+ module Parsers
13
+ # TODO: UnitedOperationsRPT Class Documentation
14
+ #
15
+ class UnitedOperationsRPT < RMuh::RPT::Log::Parsers::Base
16
+ include RMuh::RPT::Log::Util::UnitedOperations
17
+ extend RMuh::RPT::Log::Util::UnitedOperations
18
+ include RMuh::RPT::Log::Util::UnitedOperationsRPT # Regexp Constants
19
+
20
+ def self.validate_opts(opts)
21
+ fail ArgumentError,
22
+ 'argument 1 should be a Hash' unless opts.class == Hash
23
+ validate_bool_opt(opts, :to_zulu)
24
+ validate_timezone(opts)
25
+ end
26
+
27
+ def initialize(opts = {})
28
+ self.class.validate_opts(opts)
29
+
30
+ @to_zulu = opts[:to_zulu].nil? ? true : opts[:to_zulu]
31
+ @timezone = opts[:timezone].nil? ? UO_TZ : opts[:timezone]
32
+ end
33
+
34
+ def parse(loglines)
35
+ unless loglines.is_a?(StringIO)
36
+ fail ArgumentError, 'argument 1 must be a StringIO object'
37
+ end
38
+
39
+ loglines.map do |l|
40
+ line = regex_match(l)
41
+ zulu!(line, @timezone) if @to_zulu && !line.nil?
42
+ add_guid!(line) unless line.nil?
43
+ line
44
+ end.compact
45
+ end
46
+
47
+ private
48
+
49
+ def regex_match(l)
50
+ if ANNOUNCEMENT.match(l)
51
+ line = { type: :announcement }.merge(m_to_h($LAST_MATCH_INFO))
52
+ elsif WOUNDED.match(l)
53
+ line = { type: :wounded }.merge(m_to_h($LAST_MATCH_INFO))
54
+ elsif KILLED.match(l)
55
+ line = { type: :killed }.merge(m_to_h($LAST_MATCH_INFO))
56
+ elsif DIED.match(l)
57
+ line = { type: :died }.merge(m_to_h($LAST_MATCH_INFO))
58
+ end
59
+ (defined?(line)) ? line : nil
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,127 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'tzinfo'
3
+ require 'digest'
4
+
5
+ module RMuh
6
+ module RPT
7
+ module Log
8
+ module Util
9
+ # TODO: Module documentation
10
+ #
11
+ module UnitedOperations
12
+ UO_TZ ||= TZInfo::Timezone.get('America/Los_Angeles')
13
+
14
+ def m_to_h(match)
15
+ __check_match_arg(match)
16
+ h = {}
17
+ match.names.each do |m|
18
+ h.merge!(m.to_sym => __line_modifiers(match, m))
19
+ end
20
+ h
21
+ end
22
+
23
+ def __check_match_arg(match)
24
+ fail(
25
+ ArgumentError,
26
+ 'argument 1 must be of type MatchData'
27
+ ) unless match.class == MatchData
28
+ end
29
+
30
+ def __line_modifiers(match, match_name)
31
+ m = match_name
32
+ if [:year, :month, :day, :hour, :min, :sec].include?(m.to_sym)
33
+ return match[m].to_i
34
+ elsif [:server_time, :damage, :distance, :channel, :nearby_players]
35
+ .include?(m.to_sym)
36
+ return __modifiers(match, m)
37
+ else
38
+ return match[m]
39
+ end
40
+ end
41
+
42
+ def __modifiers(match, match_name)
43
+ m = match_name
44
+ if [:server_time, :damage, :distance].include?(m.to_sym)
45
+ return match[m].to_f
46
+ elsif m.to_sym == :channel
47
+ return match[m].downcase
48
+ elsif m.to_sym == :nearby_players
49
+ return __parse_nearby_players(match, m)
50
+ end
51
+ end
52
+
53
+ def __parse_nearby_players(match, match_name)
54
+ m = match_name
55
+ if match[m] != 'None.'
56
+ val = match[m].gsub('[', '').gsub(']', '').gsub('"', '')
57
+ return val.split(',')
58
+ else
59
+ return []
60
+ end
61
+ end
62
+
63
+ def zulu!(line, timezone)
64
+ t = timezone.local_to_utc(Time.new(line[:year], line[:month],
65
+ line[:day], line[:hour],
66
+ line[:min], line[:sec]))
67
+
68
+ [:year, :month, :day, :hour, :min, :sec].each do |k|
69
+ line[k] = t.send(k)
70
+ end
71
+
72
+ line[:iso8601] = t.strftime('%Y-%m-%dT%H:%M:%SZ')
73
+ line[:dtg] = t.strftime('%d%H%MZ %^b %y')
74
+
75
+ line
76
+ end
77
+
78
+ def add_guid!(line)
79
+ data = __guid_data_base(line)
80
+ s = guid_keys.map { |k| __guid_add_data(line, k) }
81
+ line[:event_guid] = Digest::SHA1.hexdigest data + s.join('')
82
+ line
83
+ end
84
+
85
+ def guid_keys
86
+ [
87
+ :message, :victim, :offender, :server_time, :damage,
88
+ :distance, :player, :player_beguid, :channel
89
+ ]
90
+ end
91
+
92
+ def __guid_data_base(line)
93
+ if line[:iso8601].nil?
94
+ return "#{line[:year]}#{line[:month]}#{line[:day]}" \
95
+ "#{line[:hour]}#{line[:min]}#{line[:sec]}" \
96
+ "#{line[:type].to_s}"
97
+ else
98
+ return "#{line[:iso8601]}#{line[:type].to_s}"
99
+ end
100
+ end
101
+
102
+ def __guid_add_data(line, key)
103
+ data = ''
104
+ data << line[key].to_s unless line[key].nil?
105
+ data
106
+ end
107
+
108
+ def validate_bool_opt(opts, key)
109
+ if opts.key?(key) &&
110
+ ![TrueClass, FalseClass].include?(opts[key].class)
111
+ fail ArgumentError,
112
+ "#{key} must be a boolean value (true|false)"
113
+ end
114
+ end
115
+
116
+ def validate_timezone(opts)
117
+ if opts.key?(:timezone) &&
118
+ opts[:timezone].class != TZInfo::DataTimezone
119
+ fail ArgumentError,
120
+ ':tiemzone must be an instance of TZInfo::DataTimezone'
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end