tf2_line_parser 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +43 -0
- data/README.md +15 -0
- data/lib/tf2_line_parser/events/assist.rb +13 -0
- data/lib/tf2_line_parser/events/capture_block.rb +26 -0
- data/lib/tf2_line_parser/events/charge_deployed.rb +23 -0
- data/lib/tf2_line_parser/events/chat.rb +38 -0
- data/lib/tf2_line_parser/events/console_say.rb +24 -0
- data/lib/tf2_line_parser/events/current_score.rb +13 -0
- data/lib/tf2_line_parser/events/damage.rb +24 -0
- data/lib/tf2_line_parser/events/domination.rb +12 -0
- data/lib/tf2_line_parser/events/event.rb +70 -0
- data/lib/tf2_line_parser/events/final_score.rb +13 -0
- data/lib/tf2_line_parser/events/heal.rb +25 -0
- data/lib/tf2_line_parser/events/kill.rb +13 -0
- data/lib/tf2_line_parser/events/match_end.rb +24 -0
- data/lib/tf2_line_parser/events/medic_death.rb +12 -0
- data/lib/tf2_line_parser/events/pickup_item.rb +28 -0
- data/lib/tf2_line_parser/events/point_capture.rb +26 -0
- data/lib/tf2_line_parser/events/revenge.rb +12 -0
- data/lib/tf2_line_parser/events/role_change.rb +28 -0
- data/lib/tf2_line_parser/events/round_length.rb +24 -0
- data/lib/tf2_line_parser/events/round_stalemate.rb +23 -0
- data/lib/tf2_line_parser/events/round_start.rb +23 -0
- data/lib/tf2_line_parser/events/round_win.rb +23 -0
- data/lib/tf2_line_parser/events/score.rb +29 -0
- data/lib/tf2_line_parser/events/suicide.rb +28 -0
- data/lib/tf2_line_parser/events/unknown.rb +28 -0
- data/lib/tf2_line_parser/line.rb +25 -0
- data/lib/tf2_line_parser/parser.rb +15 -0
- data/lib/tf2_line_parser/player.rb +19 -0
- data/lib/tf2_line_parser/version.rb +3 -0
- data/lib/tf2_line_parser.rb +13 -0
- data/script/bundler +10 -0
- data/script/ci +22 -0
- data/spec/fixtures/logs/broder_vs_epsilon.log +4539 -0
- data/spec/fixtures/logs/example.log +4528 -0
- data/spec/fixtures/logs/special_characters.log +275 -0
- data/spec/lib/tf2_line_parser/parser_spec.rb +273 -0
- data/spec/lib/tf2_line_parser/player_spec.rb +15 -0
- data/spec/spec_helper.rb +2 -0
- data/tf2_line_parser.gemspec +20 -0
- metadata +144 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tf2_line_parser (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
coderay (1.0.8)
|
10
|
+
diff-lcs (1.1.3)
|
11
|
+
method_source (0.8.1)
|
12
|
+
multi_json (1.6.1)
|
13
|
+
pry (0.9.12)
|
14
|
+
coderay (~> 1.0.5)
|
15
|
+
method_source (~> 0.8)
|
16
|
+
slop (~> 3.4)
|
17
|
+
pry-nav (0.2.3)
|
18
|
+
pry (~> 0.9.10)
|
19
|
+
rspec (2.12.0)
|
20
|
+
rspec-core (~> 2.12.0)
|
21
|
+
rspec-expectations (~> 2.12.0)
|
22
|
+
rspec-mocks (~> 2.12.0)
|
23
|
+
rspec-core (2.12.2)
|
24
|
+
rspec-expectations (2.12.1)
|
25
|
+
diff-lcs (~> 1.1.3)
|
26
|
+
rspec-mocks (2.12.2)
|
27
|
+
simplecov (0.7.1)
|
28
|
+
multi_json (~> 1.0)
|
29
|
+
simplecov-html (~> 0.7.1)
|
30
|
+
simplecov-html (0.7.1)
|
31
|
+
slop (3.4.3)
|
32
|
+
spec_coverage (0.0.5)
|
33
|
+
rspec (~> 2.0)
|
34
|
+
simplecov
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
pry-nav (~> 0.2.3)
|
41
|
+
rspec (~> 2.12.0)
|
42
|
+
spec_coverage (~> 0.0.5)
|
43
|
+
tf2_line_parser!
|
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# TF2 line parser[![Build Status](https://travis-ci.org/Arie/tf2_line_parser.png?branch=master)](http://travis-ci.org/Arie/tf2_line_parser) [![Code Climate](https://codeclimate.com/github/Arie/tf2_line_parser.png)](https://codeclimate.com/github/Arie/tf2_line_parser)
|
2
|
+
|
3
|
+
A TF2 log line parser. Unlike the other log parsers I've found, this one parses the line and returns a plain old ruby object to describe the event of the line.
|
4
|
+
I plan to use this for my own stats parsing tool.
|
5
|
+
|
6
|
+
## Requirements
|
7
|
+
* Ruby
|
8
|
+
|
9
|
+
## Missing events
|
10
|
+
* Connect
|
11
|
+
* Disconnect
|
12
|
+
* Enter game
|
13
|
+
|
14
|
+
## Credits
|
15
|
+
* nTraum, I stole most of the regexes from him his [TF2Stats](https://github.com/nTraum/tf2stats/) project.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class CaptureBlock < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} #{regex_player} triggered "captureblocked" #{regex_cap}/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :player_nick, :player_steamid, :player_team, :cp_number, :cp_name]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time, :player, :cap_number, :cap_name
|
15
|
+
|
16
|
+
def initialize(time, player_name, player_steam_id, player_team, cap_number, cap_name)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@plaery = Player.new(player_name, player_steam_id, player_team)
|
19
|
+
@cap_number = cap_number
|
20
|
+
@cap_name = cap_name
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class ChargeDeployed < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} #{regex_player} triggered "chargedeployed"/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :player_nick, :player_steamid, :player_team]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time, :player
|
15
|
+
|
16
|
+
def initialize(time, name, steam_id, team)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@player = Player.new(name, steam_id, team)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
|
5
|
+
class Chat < Event
|
6
|
+
|
7
|
+
attr_accessor :time, :player, :message
|
8
|
+
|
9
|
+
def initialize(time, player_name, player_steam_id, player_team, message)
|
10
|
+
@time = parse_time(time)
|
11
|
+
@player = Player.new(player_name, player_steam_id, player_team)
|
12
|
+
@message = message
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.attributes
|
16
|
+
@attributes ||= [:time, :player_nick, :player_steamid, :player_team, :message]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
class Say < Chat
|
22
|
+
|
23
|
+
def self.regex
|
24
|
+
@regex ||= /#{regex_time} #{regex_player} say #{regex_message}/
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class TeamSay < Chat
|
30
|
+
|
31
|
+
def self.regex
|
32
|
+
@regex ||= /#{regex_time} #{regex_player} say_team #{regex_message}/
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class ConsoleSay < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} #{regex_console} say #{regex_message}/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :message]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time, :message
|
15
|
+
|
16
|
+
def initialize(time, message)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@message = message
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class Damage < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} #{regex_player} triggered "damage" \(damage "(?'value'\d+)"\)/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :player_nick, :player_steamid, :player_team, :value]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time, :player, :value
|
15
|
+
|
16
|
+
def initialize(time, player_name, player_steam_id, player_team, value)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@player = Player.new(player_name, player_steam_id, player_team)
|
19
|
+
@value = value.to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
|
3
|
+
module Events
|
4
|
+
|
5
|
+
class Event
|
6
|
+
|
7
|
+
def self.time_format
|
8
|
+
@time_format ||= '%m/%d/%Y - %T'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.regex_time
|
12
|
+
@regex_time ||= 'L (?\'time\'.*):'
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.regex_player
|
16
|
+
@regex_player ||= '"(?\'player_nick\'.+)<(?\'player_uid\'\d+)><(?\'player_steamid\'STEAM_\S+)><(?\'player_team\'Red|Blue)>"'
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.regex_target
|
20
|
+
@regex_target ||= '"(?\'target_nick\'.+)<(?\'target_uid\'\d+)><(?\'target_steamid\'STEAM_\S+)><(?\'target_team\'Red|Blue)>"'
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.regex_cap
|
24
|
+
@regex_cap ||= '\(cp "(?\'cp_number\'\d+)"\) \(cpname "(?\'cp_name\'.\w*)'
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.regex_console
|
28
|
+
@regex_console ||= '"Console<0><Console><Console>"'
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.regex_message
|
32
|
+
@regex_message ||= '"(?\'message\'.*)"'
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.types
|
36
|
+
#ordered by how common the messages are
|
37
|
+
@types ||= [Damage, Heal, PickupItem, Assist, Kill, CaptureBlock, PointCapture, ChargeDeployed,
|
38
|
+
MedicDeath, RoleChange, Suicide, Say, TeamSay, Domination, Revenge, RoundWin, CurrentScore,
|
39
|
+
RoundLength, RoundStart, ConsoleSay, MatchEnd, FinalScore,
|
40
|
+
RoundStalemate, Unknown]
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.regex_results(matched_line)
|
44
|
+
attributes.collect do |attribute|
|
45
|
+
matched_line[attribute]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_time(time_string)
|
50
|
+
Time.strptime(time_string, Event.time_format)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
class PVPEvent < Event
|
56
|
+
def self.attributes
|
57
|
+
@attributes ||= [:time, :player_nick, :player_steamid, :player_team, :target_nick, :target_steamid, :target_team]
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_accessor :time, :player, :target
|
61
|
+
|
62
|
+
def initialize(time, player_name, player_steam_id, player_team, target_name, target_steam_id, target_team)
|
63
|
+
@time = parse_time(time)
|
64
|
+
@player = Player.new(player_name, player_steam_id, player_team)
|
65
|
+
@target = Player.new(target_name, target_steam_id, target_team)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class Heal < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} #{regex_player} triggered "healed" against #{regex_target} \(healing "(?'value'\d+)"\)/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :player_nick, :player_steamid, :player_team, :target_nick, :target_steamid, :target_team, :value]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time, :player, :target, :value
|
15
|
+
|
16
|
+
def initialize(time, player_name, player_steam_id, player_team, target_name, target_steam_id, target_team, value)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@player = Player.new(player_name, player_steam_id, player_team)
|
19
|
+
@target = Player.new(target_name, target_steam_id, target_team)
|
20
|
+
@value = value.to_i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class MatchEnd < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} World triggered "Game_Over" reason "(?'reason'.*)"/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :reason]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time, :reason
|
15
|
+
|
16
|
+
def initialize(time, reason)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@reason = reason
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class PickupItem < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} #{regex_player} picked up item #{regex_item}/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.regex_item
|
11
|
+
@regex_item ||= '\"(?\'item\'.*)\"'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.attributes
|
15
|
+
@attributes ||= [:time, :player_nick, :player_steamid, :player_team, :item]
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessor :time, :player, :item
|
19
|
+
|
20
|
+
def initialize(time, player_name, player_steam_id, player_team, item)
|
21
|
+
@time = parse_time(time)
|
22
|
+
@player = Player.new(player_name, player_steam_id, player_team)
|
23
|
+
@item = item
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class PointCapture < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} Team "(?'team'Red|Blue)" triggered "pointcaptured" \(cp "(?'cp_number'\d+)"\) \(cpname "(?'cp_name'.*)"\) \(numcappers/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :team, :cp_number, :cp_name]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time, :team, :cap_number, :cap_name
|
15
|
+
|
16
|
+
def initialize(time, team, cap_number, cap_name)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@team = team
|
19
|
+
@cap_number = cap_number
|
20
|
+
@cap_name = cap_name
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class RoleChange < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} #{regex_player} changed role to #{regex_role}/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.regex_role
|
11
|
+
@regex_role ||= '\"(?\'role\'.*)\"'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.attributes
|
15
|
+
@attributes ||= [:time, :player_nick, :player_steamid, :player_team, :role]
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessor :time, :player, :role
|
19
|
+
|
20
|
+
def initialize(time, player_name, player_steam_id, player_team, role)
|
21
|
+
@time = parse_time(time)
|
22
|
+
@player = Player.new(player_name, player_steam_id, player_team)
|
23
|
+
@role = role
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class RoundLength < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} World triggered "Round_Length" \(seconds \"(?'length'.*)"\)/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :length]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time, :length
|
15
|
+
|
16
|
+
def initialize(time, length)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@length = length
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class RoundStalemate < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} World triggered "Round_Stalemate"/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time
|
15
|
+
|
16
|
+
def initialize(time)
|
17
|
+
@time = parse_time(time)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class RoundStart < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} World triggered "Round_Start"/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :time
|
15
|
+
|
16
|
+
def initialize(time)
|
17
|
+
@time = parse_time(time)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class RoundWin < Event
|
5
|
+
|
6
|
+
def self.regex
|
7
|
+
@regex ||= /#{regex_time} World triggered "Round_Win" \(winner "(?'team'Red|Blue)"\)/
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= [:time, :team]
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :winner
|
15
|
+
|
16
|
+
def initialize(time, winner)
|
17
|
+
@time = parse_time(time)
|
18
|
+
@winner = winner
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module TF2LineParser
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class Score < Event
|
5
|
+
|
6
|
+
def self.regex_score
|
7
|
+
@regex_score ||= '\"(?\'score\'\d+)\"'
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.regex_team
|
11
|
+
@regex_team ||= 'Team \"(?\'team\'Red|Blue)\"'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.attributes
|
15
|
+
@attributes ||= [:time, :team, :score]
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessor :time, :team, :score
|
19
|
+
|
20
|
+
def initialize(time, team, score)
|
21
|
+
@time = parse_time(time)
|
22
|
+
@team = team
|
23
|
+
@score = score
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|