rmuh 0.1.0

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,26 @@
1
+ # -*- coding: UTF-8 -*-
2
+ module RMuh
3
+ module RPT
4
+ module Log
5
+ module Util
6
+ # The utility module for the UnitedOperationsLog parser
7
+ # This provides the constants needed for Regex matches
8
+ # as well as the validate_chat function
9
+ #
10
+ module UnitedOperationsLog
11
+ ONE_DAY ||= 86_400
12
+ TIME ||= '^\s*?(?<hour>\d+?):(?<min>\d+?):(?<sec>\d+)\s' \
13
+ 'BattlEye\sServer:\s'
14
+ GUID ||= Regexp.new(
15
+ "#{TIME}.*Verified\\sGUID\\s\\((?<player_beguid>.*?)\\).*#\\d+?" \
16
+ '\s(?<player>.+)$'
17
+ )
18
+ CHAT ||= Regexp.new(
19
+ "#{TIME}\\((?<channel>Group|Global|Side|Vehicle|Command|Unknown)" \
20
+ '\)\s+?(?<player>.+?):\s(?<message>.*)$'
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ # -*- coding: UTF-8 -*-
2
+ module RMuh
3
+ module RPT
4
+ module Log
5
+ module Util
6
+ # The utility module for the UnitedOperationsRPT parser
7
+ # This provides the constants for Regexp matches
8
+ #
9
+ module UnitedOperationsRPT
10
+ DTR ||= '(?<year>\d+)/(?<month>\d+)/(?<day>\d+),\s+?(?<hour>\d+):' \
11
+ '(?<min>\d+):(?<sec>\d+)'
12
+ KILLED ||= Regexp.new(
13
+ "^#{DTR}\\s\"(?<server_time>[0-9.]+).*?:\\s(?<victim>.*?)\\s\\(" \
14
+ '(?<victim_team>.*?)\)\s.*?by\s(?<offender>.*?)\s\(' \
15
+ '(?<offender_team>.*?)\).*?position: \[(?<victim_position>.*?)\]' \
16
+ '.*?GRID (?<victim_grid>\d+)\).*?position: \[' \
17
+ '(?<offender_position>.*?)\].*?GRID (?<offender_grid>\d*)\).*?:' \
18
+ '\s(?<distance>[0-9e.+]+).*?(?:(?<nearby_players>None.|\[.*?\])")'
19
+ )
20
+ DIED ||= Regexp.new(
21
+ "^#{DTR}\\s\"(?<server_time>[0-9.]+).*?:\\s(?<victim>.*?) " \
22
+ 'has died at \[(?<victim_position>.*?)\].*?GRID ' \
23
+ '(?<victim_grid>\d+)\).*?(?:(?<nearby_players>None.|\[.*?\])")'
24
+ )
25
+ WOUNDED ||= Regexp.new(
26
+ "^#{DTR}\\s\"(?<server_time>[0-9.]+).*?:\\s(?<victim>.*?)\\s" \
27
+ '\((?<victim_team>.*?)\)\s.*?by\s(?<offender>.*?)\s\(' \
28
+ '(?<offender_team>.*?)\).*?(?<damage>[0-9.]+)\sdamage'
29
+ )
30
+ ANNOUNCEMENT ||= Regexp.new(
31
+ "^#{DTR}\\s\"(?<head>[#]+?)\s(?<message>.*?)\s(?<tail>[#]+?)\""
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,55 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require 'gamespy_query'
4
+
5
+ module RMuh
6
+ # TODO: Documentation
7
+ #
8
+ module ServerStats
9
+ # TODO: Documentation
10
+ #
11
+ class Base
12
+ DEFAULT_PORT = 2_302
13
+
14
+ def initialize(opts = {})
15
+ fail ArgumentError, 'arg 1 must be a Hash' unless opts.is_a?(Hash)
16
+ self.class.validate_opts(opts)
17
+ opts_to_instance(opts)
18
+ @gsq = GamespyQuery::Socket.new("#{@host}:#{@port}")
19
+ end
20
+
21
+ def stats
22
+ remote_stats
23
+ end
24
+
25
+ def update_cache
26
+ @serverstats = sync if @cache
27
+ end
28
+
29
+ private
30
+
31
+ def self.validate_opts(opts)
32
+ fail ArgumentError, ':host is required' unless opts.key?(:host)
33
+ opts[:port] ||= DEFAULT_PORT
34
+ opts[:cache] = true unless opts.key?(:cache)
35
+ nil
36
+ end
37
+
38
+ def opts_to_instance(opts)
39
+ opts.each { |k, v| instance_variable_set(:"@#{k}", v) }
40
+ end
41
+
42
+ def remote_stats
43
+ if @cache
44
+ @serverstats
45
+ else
46
+ sync
47
+ end
48
+ end
49
+
50
+ def sync
51
+ @gsq.sync
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,10 @@
1
+ # -*- coding: UTF-8 -*-
2
+ # RMuh : the ArmA 2 Ruby library
3
+ #
4
+ module RMuh
5
+ VERSION_MAJ ||= 0
6
+ VERSION_MIN ||= 1
7
+ VERSION_REV ||= 0
8
+
9
+ VERSION ||= "#{VERSION_MAJ}.#{VERSION_MIN}.#{VERSION_REV}"
10
+ end
data/rmuh.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'English'
3
+
4
+ $LOAD_PATH << File.expand_path('../lib', __FILE__)
5
+
6
+ require 'rmuh/version'
7
+
8
+ Gem::Specification.new do |g|
9
+ g.name = 'rmuh'
10
+ g.version = RMuh::VERSION
11
+ g.date = '2014-02-18'
12
+ g.description = 'ArmA 2 Ruby Library for RPT, Log, and GameSpy'
13
+ g.summary = 'ArmA 2 Ruby Library'
14
+ g.authors = ['Tim Heckman']
15
+ g.email = 't@heckman.io'
16
+ g.homepage = 'https://github.com/theckman/rmuh'
17
+ g.license = 'MIT'
18
+
19
+ g.test_files = %x{git ls-files spec/*}.split
20
+ g.files = %x{git ls-files}.split
21
+
22
+ g.add_development_dependency 'rake', '~>10.1.0'
23
+ g.add_development_dependency 'rspec', '~>2.14.1'
24
+ g.add_development_dependency 'rubocop', '~> 0.18.1'
25
+ g.add_development_dependency 'fuubar', '~> 1.3.2'
26
+ g.add_development_dependency 'simplecov', '~> 0.8.2'
27
+ g.add_development_dependency 'coveralls', '~> 0.7.0'
28
+
29
+ g.add_runtime_dependency 'awesome_print', '~> 1.2.0'
30
+ g.add_runtime_dependency 'tzinfo', '~> 1.1.0'
31
+ g.add_runtime_dependency 'httparty', '~> 0.12.0'
32
+ g.add_runtime_dependency 'gamespy_query', '~> 0.1.5'
33
+ end
@@ -0,0 +1 @@
1
+ RSpec, yo
@@ -0,0 +1,13 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'rspec'
3
+ require 'simplecov'
4
+ require 'coveralls'
5
+
6
+ def repo_root
7
+ File.expand_path('../../..', __FILE__)
8
+ end
9
+
10
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
11
+ SimpleCov.start do
12
+ add_filter '/spec/'
13
+ end
@@ -0,0 +1,106 @@
1
+ require 'digest'
2
+
3
+ def spec_guid_reference_implementation(mock_line)
4
+ line = mock_line.dup
5
+ data = spec_add_data(line)
6
+
7
+ line[:event_guid] = Digest::SHA1.hexdigest data
8
+ line
9
+ end
10
+
11
+ def spec_add_data(line)
12
+ data = spec_minimum_data(line)
13
+ spec_add_data_one!(line, data)
14
+ spec_add_data_two!(line, data)
15
+ data
16
+ end
17
+
18
+ def spec_minimum_data(line)
19
+ if line[:iso8601].nil?
20
+ data = "#{line[:year]}#{line[:month]}#{line[:day]}" \
21
+ "#{line[:hour]}#{line[:min]}#{line[:sec]}" \
22
+ "#{line[:type].to_s}"
23
+ else
24
+ data = "#{line[:iso8601]}#{line[:type].to_s}"
25
+ end
26
+ data
27
+ end
28
+
29
+ def spec_add_data_one!(line, data)
30
+ data << line[:message] unless line[:message].nil?
31
+ data << line[:victim] unless line[:victim].nil?
32
+ data << line[:offender] unless line[:offender].nil?
33
+ data << line[:server_time].to_s unless line[:server_time].nil?
34
+ data << line[:damage].to_s unless line[:damage].nil?
35
+ data
36
+ end
37
+
38
+ def spec_add_data_two!(line, data)
39
+ data << line[:distance].to_s unless line[:distance].nil?
40
+ data << line[:player] unless line[:player].nil?
41
+ data << line[:player_beguid] unless line[:player_beguid].nil?
42
+ data << line[:channel] unless line[:channel].nil?
43
+ data
44
+ end
45
+
46
+ def spec_killed_line
47
+ {
48
+ type: :killed, year: 2014, month: 2, day: 16, hour: 0, min: 7, sec: 22,
49
+ server_time: 4517.73, victim: 'Althain', victim_team: 'WEST',
50
+ offender: 'Geth', offender_team: 'CIV', iso8601: '2014-02-16T00:07:22Z',
51
+ victim_position: '12789.4,12697.3,0.00152588', victim_grid: '1278912697',
52
+ offender_position: '12795.3,12704.7,0.00137329', distance: 9.5636,
53
+ offender_grid: '1279512704', nearby_players: ['Brig.Gold101st'],
54
+ dtg: '160007Z FEB 14'
55
+ }
56
+ end
57
+
58
+ def spec_died_line
59
+ {
60
+ type: :died, year: 2014, month: 2, day: 16, hour: 1, min: 30, sec: 53,
61
+ server_time: 4280.29, victim_position: '4194.01,1633.02,0.00143814',
62
+ dtg: '160130Z FEB 14', nearby_players: [
63
+ 'Synxe', 'Naught', 'Kiesbye', 'Aphex', 'Jeff Kid', 'Adam1', 'Lord Yod',
64
+ 'Small', 'Mixtrate', 'James', 'Nickster', 'Tankman', 'JamaicanJews',
65
+ 'Besiden'],
66
+ iso8601: '2014-02-16T01:30:53Z', victim_grid: '0419401633'
67
+ }
68
+ end
69
+
70
+ def spec_wounded_line
71
+ {
72
+ type: :wounded, year: 2014, month: 2, day: 16, hour: 0, min: 7, sec: 21,
73
+ server_time: 4517.55, victim: 'Althain', victim_team: 'WEST',
74
+ offender: 'Geth', offender_team: 'CIV', damage: 0.0780736,
75
+ iso8601: '2014-02-16T00:07:21Z', dtg: '160007Z FEB 14'
76
+ }
77
+ end
78
+
79
+ def spec_announcement_line
80
+ {
81
+ type: :announcement, year: 2014, month: 2, day: 16, hour: 1, min: 47,
82
+ sec: 43, head: '#############################', dtg: '160147Z FEB 14',
83
+ message: 'Start CO30_Operation_Trident_v2C',
84
+ tail: '#############################',
85
+ iso8601: '2014-02-16T01:47:43Z'
86
+ }
87
+ end
88
+
89
+ def spec_chat_line
90
+ {
91
+ type: :chat, hour: 5, min: 43, sec: 29, channel: 'group', player: 'Chris',
92
+ message: 'Ew ban Mara', year: 2014, month: 2, day: 16,
93
+ iso8601: '2014-02-16T05:43:29Z', dtg: '160543Z FEB 14',
94
+ event_guid: '8365d6da7375fde963371004b52012af0ef03678'
95
+ }
96
+ end
97
+
98
+ def spec_beguid_line
99
+ {
100
+ type: :guid, hour: 5, min: 53, sec: 49,
101
+ player_beguid: 'fd5c7ecf1f986badce8b5ece3f4d853a', player: 'Brock Samson',
102
+ year: 2014, month: 2, day: 16, iso8601: '2014-02-16T05:53:49Z',
103
+ dtg: '160553Z FEB 14',
104
+ event_guid: '89aeda0db1f774936619cd3e3ce392e28c1a3871'
105
+ }
106
+ end
@@ -0,0 +1,112 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'rspec'
3
+ require 'stringio'
4
+ require 'helpers/spec_helper'
5
+ require File.join(repo_root, 'lib/rmuh/rpt/log/fetch')
6
+
7
+ describe RMuh::RPT::Log::Fetch do
8
+ let(:url) do
9
+ 'https://raw2.github.com/theckman/rmuh/master/spec/files/content-length.' \
10
+ 'txt'
11
+ end
12
+ let(:fetch) { RMuh::RPT::Log::Fetch.new(url) }
13
+ context '#new' do
14
+ it 'should return an instance of RMuh::RPT::Log::Fetch' do
15
+ fetch.should be_an_instance_of RMuh::RPT::Log::Fetch
16
+ end
17
+
18
+ it 'should have a @cfg object which is an instance of OpenStruct' do
19
+ fetch.cfg.should be_an_instance_of OpenStruct
20
+ end
21
+
22
+ it 'should set the "byte_start" config item if specified as arg:1' do
23
+ rlfetch = RMuh::RPT::Log::Fetch.new(url, 10)
24
+ rlfetch.cfg.byte_start.should eql 10
25
+ end
26
+
27
+ it 'should set the "byte_end" config item if specified as arg:3' do
28
+ rlfetch = RMuh::RPT::Log::Fetch.new(url, 10, 42)
29
+ rlfetch.cfg.byte_end.should eql 42
30
+ end
31
+ end
32
+
33
+ context '#byte_start' do
34
+ it 'should allow setting the value to Integer' do
35
+ expect { fetch.byte_start = 10 }.not_to raise_error
36
+ end
37
+
38
+ it 'should raise an error if the value is nil' do
39
+ expect { fetch.byte_start = nil }.to raise_error ArgumentError
40
+ end
41
+
42
+ it 'should raise an error if arg:1 is a String' do
43
+ expect { fetch.byte_start = 'urmom' }.to raise_error ArgumentError
44
+ end
45
+
46
+ it 'should raise an error if arg:1 is a Float' do
47
+ expect { fetch.byte_start = 4.2 }.to raise_error ArgumentError
48
+ end
49
+
50
+ it 'should update the @cfg.byte_start value' do
51
+ fetch.byte_start = 10
52
+ fetch.cfg.byte_start.should eql 10
53
+ end
54
+ end
55
+
56
+ context '#byte_end' do
57
+ it 'should allow setting the value to Integer' do
58
+ expect { fetch.byte_end = 10 }.not_to raise_error
59
+ end
60
+
61
+ it 'should allow setting the value is nil' do
62
+ expect { fetch.byte_end = nil }.not_to raise_error
63
+ end
64
+
65
+ it 'should raise an error if arg:1 is a String' do
66
+ expect { fetch.byte_end = 'urmom' }.to raise_error ArgumentError
67
+ end
68
+
69
+ it 'should raise an error if arg:1 is a Float' do
70
+ expect { fetch.byte_end = 4.2 }.to raise_error ArgumentError
71
+ end
72
+
73
+ it 'should update the @cfg.byte_end value' do
74
+ fetch.byte_end = 42
75
+ fetch.cfg.byte_end.should eql 42
76
+ end
77
+ end
78
+
79
+ context '#size' do
80
+ it 'should return a Integer object' do
81
+ fetch.size.should be_an_instance_of Fixnum
82
+ end
83
+
84
+ it 'should return the size' do
85
+ fetch.size.should eql 10
86
+ end
87
+ end
88
+
89
+ context '#log' do
90
+ it 'should return a StringIO object' do
91
+ fetch.log.should be_an_instance_of StringIO
92
+ end
93
+
94
+ it 'should return the log' do
95
+ fetch.log.read.should eql "RSpec, yo\n"
96
+ end
97
+ end
98
+
99
+ context '#dos2unix' do
100
+ let(:dos) { "text\r\n" }
101
+ let(:dos_newline) { /\r\n$/ }
102
+
103
+ it 'should match the Regexp object' do
104
+ expect(dos_newline.match(dos)).not_to be nil
105
+ end
106
+
107
+ it 'should strip out DOS new lines' do
108
+ match = /\r\n/.match(fetch.send(:dos2unix, dos))
109
+ match.should be nil
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,57 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'rspec'
3
+ require 'stringio'
4
+
5
+ REPO_ROOT = File.expand_path('../..', __FILE__)
6
+
7
+ require File.join(REPO_ROOT, 'lib/rmuh/rpt/log/parsers/base')
8
+
9
+ describe RMuh::RPT::Log::Parsers::Base do
10
+ let(:text) { StringIO.new("This is a string.\nSo is this!") }
11
+ let(:base) { RMuh::RPT::Log::Parsers::Base.new }
12
+
13
+ context 'text' do
14
+ it 'should be a StringIO object' do
15
+ text.should be_an_instance_of StringIO
16
+ end
17
+ end
18
+
19
+ context '#new' do
20
+ it 'should take no more than one arg' do
21
+ expect do
22
+ RMuh::RPT::Log::Parsers::Base.new(nil, nil)
23
+ end.to raise_error ArgumentError
24
+ end
25
+
26
+ it 'should return an instance of RMuh::RPT::Log::Parsers::Base' do
27
+ base.should be_an_instance_of RMuh::RPT::Log::Parsers::Base
28
+ end
29
+ end
30
+
31
+ context '#parse' do
32
+ it 'should take at most 1 argument' do
33
+ expect { base.parse(text, text) }.to raise_error ArgumentError
34
+ end
35
+
36
+ it 'should take at least 1 argument' do
37
+ expect { base.parse }.to raise_error ArgumentError
38
+ end
39
+
40
+ it 'should only accept a StringIO object' do
41
+ expect { base.parse('urmom') }.to raise_error ArgumentError
42
+ expect { base.parse(42) }.to raise_error ArgumentError
43
+ end
44
+
45
+ it 'should return an Array' do
46
+ expect(base.parse(text)).to be_an_instance_of Array
47
+ end
48
+
49
+ it 'the Array size should be 2' do
50
+ expect(base.parse(text).size).to be 2
51
+ end
52
+
53
+ it 'should be an Array of hashes' do
54
+ base.parse(text).each { |p| p.should be_an_instance_of Hash }
55
+ end
56
+ end
57
+ end