fonte 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -7,7 +7,7 @@ More info can be found at [HL Engine Log Standard documentation](https://develop
7
7
 
8
8
  ## Examples
9
9
 
10
- Fonte comes with a bunch of parsers that can be used individually. Also, there is the `LogParser` which will then includes all the other `_*Parser_` to parse a full log file.
10
+ Fonte comes with a bunch of parsers that can be used individually. Also, there is the `LogParser` which will then includes all the other `*Parser` to parse a full log file.
11
11
 
12
12
  For example, if you wish to parse only a player informaton, you could use the PlayerParser:
13
13
 
@@ -20,20 +20,21 @@ player.steam_id.account_number.value # => 24968171
20
20
  player.team.value # => "Red"
21
21
  ```
22
22
 
23
- Or you could parse a rcon authentication individually or within a log:
23
+ Another case is parsing a rcon authentication individually and within a log:
24
24
 
25
25
  ```ruby
26
- rcon_authentication = Fonte::Parsers::PlayerParser.new.parse('Rcon: "rcon challenge "super secret" command" from "192.168.10.1:17015"')
26
+ rcon_parser = Fonte::Parsers::RconParser.new
27
+ rcon_authentication = rcon_parser.parse('Rcon: "rcon challenge "super secret" command" from "192.168.10.1:17015"')
27
28
  rcon_authentication.password.value # => "super secret"
28
- ```
29
-
30
- ```ruby
31
- log = Fonte::Parsers::LogParser.new.parse('L 12/26/2011 - 02:14:33: Rcon: "rcon challenge "super secret" command" from "192.168.10.1:17015"')
32
29
 
30
+ log_parser = Fonte::Parsers::LogParser.new
31
+ log = log_parser.parse('L 12/26/2011 - 02:14:33: Rcon: "rcon challenge "super secret" command" from "192.168.10.1:17015"')
33
32
  log.command.password.value # => "super secret"
34
33
  log.date_time.day # => 26
35
34
  ```
36
35
 
37
- ## Disclaimer
36
+ ## Games it supports
37
+ In the current version it can parse all TF2, CSS and DOD files. Left4Dead is not supported yet due LOTS of "custom" events.
38
38
 
39
- This is a very early approach and can be a considered a proof of concept in the current version. Lots of things should (and will) be changed. For instance, I am not quite happy with the forced _".value"_ API, but for now, it was the easiest way to implement. Also, it doesn't support real games log yet, so, there should be a way to easily "plug" specific game "log commands".
39
+ ## Disclaimer
40
+ This is a very early approach and can be a considered a proof of concept. Lots of things should (and will) be changed. For instance, I am not quite happy with the forced _".value"_ API, but for now, it was the easiest way to implement. Also, it doesn't support real games log yet, so, there should be a way to easily "plug" specific game "log commands".
@@ -17,6 +17,6 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_development_dependency "rspec"
21
- s.add_runtime_dependency "treetop"
20
+ s.add_development_dependency "rspec", "~> 2.8.0"
21
+ s.add_runtime_dependency "treetop", "~> 1.4.8"
22
22
  end
@@ -1,6 +1,6 @@
1
1
  module Fonte
2
2
  module Parsers
3
- %w(number word temporal address rcon steam_id player log).each do |parser|
3
+ %w(number word temporal address rcon steam_id property player action log).each do |parser|
4
4
  Treetop.load File.join(File.dirname(__FILE__), "parsers", parser)
5
5
  end
6
6
  end
@@ -0,0 +1,342 @@
1
+ module Fonte
2
+ module Parsers
3
+ grammar Action
4
+ include Word
5
+ include Player
6
+ include Address
7
+ include Property
8
+
9
+ rule action
10
+ log_started_action
11
+ / log_ended_action
12
+ / cvar_start_action
13
+ / cvar_end_action
14
+ / cvar_set_action
15
+ / map_loading_action
16
+ / map_started_action
17
+ / server_name_action
18
+ / connection_action
19
+ / validation_action
20
+ / enter_game_action
21
+ / disconnection_action
22
+ / kick_action
23
+ / kick_and_ban_action
24
+ / suicide_action
25
+ / join_team_action
26
+ / role_selection_action
27
+ / name_change_action
28
+ / kill_action
29
+ / injure_action
30
+ / triggered_player_action_against_player
31
+ / triggered_player_action
32
+ / triggered_team_action
33
+ / triggered_world_action
34
+ / chat_action
35
+ / team_chat_action
36
+ / private_chat_action
37
+ / server_chat_action
38
+ / team_alliance_action
39
+ / score_report
40
+ / weapon_selection_action
41
+ / weapon_pickup_action
42
+ end
43
+
44
+ rule log_started_action
45
+ "Log file started" properties:action_properties? {
46
+ def value
47
+ "log start"
48
+ end
49
+ }
50
+ end
51
+
52
+ rule log_ended_action
53
+ "Log file closed" {
54
+ def value
55
+ "log end"
56
+ end
57
+ }
58
+ end
59
+
60
+ rule cvar_start_action
61
+ [Ss] "erver cvars start" {
62
+ def value
63
+ "cvar start"
64
+ end
65
+ }
66
+ end
67
+
68
+ rule cvar_end_action
69
+ [Ss] "erver cvars end" {
70
+ def value
71
+ "cvar end"
72
+ end
73
+ }
74
+ end
75
+
76
+ rule cvar_set_action
77
+ ([Ss] "erver cvar" SPACE)? key:quoted_word SPACE "=" SPACE val:quoted_word {
78
+ def value
79
+ "cvar set"
80
+ end
81
+
82
+ def to_hash
83
+ { key.value => val.value }
84
+ end
85
+ }
86
+ end
87
+
88
+ rule map_loading_action
89
+ "Loading map" SPACE name:map_name {
90
+ def value
91
+ "map load"
92
+ end
93
+ }
94
+ end
95
+
96
+ rule map_started_action
97
+ "Started map" SPACE name:map_name SPACE "(" crc:map_crc ")" {
98
+ def value
99
+ "map start"
100
+ end
101
+ }
102
+ end
103
+
104
+ rule map_name
105
+ quoted_word
106
+ end
107
+
108
+ rule map_crc
109
+ "CRC" SPACE quoted_word <Fonte::Nodes::SingleWordNode>
110
+ end
111
+
112
+ rule server_name_action
113
+ "Server name is" SPACE name:quoted_word {
114
+ def value
115
+ "server name"
116
+ end
117
+ }
118
+ end
119
+
120
+ rule server_chat_action
121
+ "Server say" SPACE message:quoted_word {
122
+ def value
123
+ "server chat"
124
+ end
125
+ }
126
+ end
127
+
128
+ rule connection_action
129
+ QUOTE player QUOTE SPACE "connected, address" SPACE QUOTE ip QUOTE {
130
+ def value
131
+ "connection"
132
+ end
133
+ }
134
+ end
135
+
136
+ rule validation_action
137
+ QUOTE player QUOTE SPACE "STEAM USERID validated" {
138
+ def value
139
+ "validation"
140
+ end
141
+ }
142
+ end
143
+
144
+ rule enter_game_action
145
+ QUOTE player QUOTE SPACE "entered the game" {
146
+ def value
147
+ "enter"
148
+ end
149
+ }
150
+ end
151
+
152
+ rule disconnection_action
153
+ QUOTE player QUOTE SPACE "disconnected" properties:action_properties? {
154
+ def value
155
+ "disconnection"
156
+ end
157
+ }
158
+ end
159
+
160
+ rule kick_action
161
+ QUOTE player QUOTE SPACE "was kicked by" SPACE '"Console"' properties:action_properties? {
162
+ def value
163
+ "kick"
164
+ end
165
+ }
166
+ end
167
+
168
+ rule kick_and_ban_action
169
+ QUOTE player QUOTE SPACE "was kicked and banned by" SPACE '"Console"' properties:action_properties? {
170
+ def value
171
+ "kickban"
172
+ end
173
+ }
174
+ end
175
+
176
+ rule suicide_action
177
+ QUOTE player QUOTE SPACE "committed suicide with" SPACE QUOTE weapon QUOTE properties:action_properties? {
178
+ def value
179
+ "suicide"
180
+ end
181
+ }
182
+ end
183
+
184
+ rule join_team_action
185
+ QUOTE player QUOTE SPACE "joined team" SPACE QUOTE team QUOTE {
186
+ def value
187
+ "join"
188
+ end
189
+ }
190
+ end
191
+
192
+ rule role_selection_action
193
+ QUOTE player QUOTE SPACE "changed role to" SPACE QUOTE role QUOTE {
194
+ def value
195
+ "role selection"
196
+ end
197
+ }
198
+ end
199
+
200
+ rule name_change_action
201
+ QUOTE player QUOTE SPACE "changed name to" SPACE new_name:quoted_word {
202
+ def value
203
+ "name change"
204
+ end
205
+ }
206
+ end
207
+
208
+ rule kill_action
209
+ QUOTE attacker:player QUOTE SPACE "killed" SPACE QUOTE victim:player QUOTE SPACE "with" SPACE QUOTE weapon QUOTE properties:action_properties? {
210
+ def value
211
+ "kill"
212
+ end
213
+ }
214
+ end
215
+
216
+ rule injure_action
217
+ QUOTE attacker:player QUOTE SPACE "attacked" SPACE QUOTE victim:player QUOTE SPACE "with" SPACE QUOTE weapon QUOTE properties:action_properties? {
218
+ def value
219
+ "injure"
220
+ end
221
+ }
222
+ end
223
+
224
+ rule triggered_player_action_against_player
225
+ QUOTE attacker:player QUOTE SPACE "triggered" SPACE action:quoted_word SPACE "against" SPACE QUOTE victim:player QUOTE (SPACE "with" SPACE QUOTE weapon QUOTE)? properties:action_properties? {
226
+ def value
227
+ action.value
228
+ end
229
+ }
230
+ end
231
+
232
+ rule triggered_player_action
233
+ QUOTE player QUOTE SPACE "triggered" SPACE action:quoted_word properties:action_properties? {
234
+ def value
235
+ action.value
236
+ end
237
+ }
238
+ end
239
+
240
+ rule triggered_team_action
241
+ "Team" SPACE QUOTE team QUOTE SPACE "triggered" SPACE action:quoted_word properties:action_properties? {
242
+ def value
243
+ action.value
244
+ end
245
+ }
246
+ end
247
+
248
+ rule triggered_world_action
249
+ "World triggered" SPACE action:quoted_word properties:action_properties? {
250
+ def value
251
+ action.value
252
+ end
253
+ }
254
+ end
255
+
256
+ rule chat_action
257
+ QUOTE player QUOTE SPACE "say" SPACE message:quoted_word {
258
+ def value
259
+ "chat"
260
+ end
261
+ }
262
+ end
263
+
264
+ rule team_chat_action
265
+ QUOTE player QUOTE SPACE "say_team" SPACE message:quoted_word {
266
+ def value
267
+ "team chat"
268
+ end
269
+ }
270
+ end
271
+
272
+ rule private_chat_action
273
+ QUOTE player QUOTE SPACE "tell" SPACE QUOTE target:player QUOTE SPACE "message" SPACE message:quoted_word {
274
+ def value
275
+ "private chat"
276
+ end
277
+ }
278
+ end
279
+
280
+ rule team_alliance_action
281
+ "Team" SPACE QUOTE team QUOTE SPACE "formed alliance with team" SPACE QUOTE allied_team:team QUOTE {
282
+ def value
283
+ "alliance"
284
+ end
285
+ }
286
+ end
287
+
288
+ rule score_report
289
+ "Team" SPACE QUOTE team QUOTE SPACE score_type SPACE QUOTE points:integer QUOTE SPACE "with" SPACE QUOTE players_count:integer QUOTE SPACE "players" {
290
+ def value
291
+ score_type.value
292
+ end
293
+ }
294
+ end
295
+
296
+ rule score_type
297
+ ("current score" / "final score" / "scored") {
298
+ def value
299
+ case text_value
300
+ when "scored"
301
+ "team score"
302
+ else
303
+ text_value
304
+ end
305
+ end
306
+ }
307
+ end
308
+
309
+ rule weapon_selection_action
310
+ QUOTE player QUOTE SPACE "selected weapon" SPACE QUOTE weapon QUOTE {
311
+ def value
312
+ "weapon selection"
313
+ end
314
+ }
315
+ end
316
+
317
+ rule weapon_pickup_action
318
+ QUOTE player QUOTE SPACE "acquired weapon" SPACE QUOTE weapon QUOTE {
319
+ def value
320
+ "weapon pickup"
321
+ end
322
+ }
323
+ end
324
+
325
+ rule role
326
+ word
327
+ end
328
+
329
+ rule weapon
330
+ word
331
+ end
332
+
333
+ rule action_properties
334
+ SPACE properties {
335
+ def value
336
+ properties.value
337
+ end
338
+ }
339
+ end
340
+ end
341
+ end
342
+ end
@@ -4,86 +4,14 @@ module Fonte
4
4
  include Word
5
5
  include Temporal
6
6
  include Rcon
7
+ include Action
7
8
 
8
9
  rule entry
9
- "L" SPACE date_time ":" SPACE command
10
+ "L" SPACE date_time ":" SPACE command "\n"?
10
11
  end
11
12
 
12
13
  rule command
13
- log_started
14
- / log_ended
15
- / cvar_start
16
- / cvar_end
17
- / cvar_set
18
- / map_loading
19
- / map_started
20
- / server_name
21
- / server_say
22
- / rcon_command
23
- end
24
-
25
- rule log_ended
26
- "Log file closed"
27
- end
28
-
29
- rule log_started
30
- "Log file started" SPACE log_filename SPACE log_game_path SPACE log_game_version
31
- end
32
-
33
- rule log_filename
34
- "(file" SPACE quoted_word ")" <Fonte::Nodes::SingleWordNode>
35
- end
36
-
37
- rule log_game_path
38
- "(game" SPACE quoted_word ")" <Fonte::Nodes::SingleWordNode>
39
- end
40
-
41
- rule log_game_version
42
- "(version" SPACE quoted_word ")" <Fonte::Nodes::SingleWordNode>
43
- end
44
-
45
- rule cvar_start
46
- [Ss] "erver cvars start"
47
- end
48
-
49
- rule cvar_end
50
- [Ss] "erver cvars end"
51
- end
52
-
53
- rule cvar_set
54
- ([Ss] "erver cvar" SPACE)? key:quoted_word SPACE "=" SPACE val:quoted_word {
55
- def name
56
- key.value
57
- end
58
-
59
- def value
60
- val.value
61
- end
62
- }
63
- end
64
-
65
- rule map_loading
66
- "Loading map" SPACE map_name
67
- end
68
-
69
- rule map_started
70
- "Started map" SPACE map_name SPACE "(" map_crc ")"
71
- end
72
-
73
- rule map_name
74
- quoted_word
75
- end
76
-
77
- rule map_crc
78
- "CRC" SPACE quoted_word <Fonte::Nodes::SingleWordNode>
79
- end
80
-
81
- rule server_name
82
- "Server name is" SPACE server_name:quoted_word <Fonte::Nodes::SingleWordNode>
83
- end
84
-
85
- rule server_say
86
- "Server say" SPACE server_say:quoted_word <Fonte::Nodes::SingleWordNode>
14
+ action / rcon_command
87
15
  end
88
16
  end
89
17
  end
@@ -6,7 +6,11 @@ module Fonte
6
6
  include SteamID
7
7
 
8
8
  rule player
9
- nickname "<" uid ">" "<" steam_id ">" "<" team ">"
9
+ nickname "<" uid ">" "<" steam_id ">" "<" team ">" {
10
+ def value
11
+ text_value
12
+ end
13
+ }
10
14
  end
11
15
 
12
16
  rule nickname
@@ -22,7 +26,7 @@ module Fonte
22
26
  end
23
27
 
24
28
  rule team
25
- (![<>] .)* {
29
+ (![<>] character)* {
26
30
  def value
27
31
  text_value == "Unassigned" || text_value == "Console" || text_value == "" ? nil : text_value
28
32
  end
@@ -0,0 +1,47 @@
1
+ module Fonte
2
+ module Parsers
3
+ grammar Property
4
+ include Word
5
+
6
+ rule properties
7
+ property+ {
8
+ def value
9
+ elements.inject({}) { |properties, property| properties.merge property.value }
10
+ end
11
+ }
12
+ end
13
+
14
+ rule property
15
+ key_only_property / key_value_property
16
+ end
17
+
18
+ rule key_only_property
19
+ "(" property_key ")" SPACE? {
20
+ def value
21
+ { property_key.value => true }
22
+ end
23
+ }
24
+ end
25
+
26
+ rule key_value_property
27
+ "(" property_key SPACE property_value ")" SPACE? {
28
+ def value
29
+ { property_key.value => property_value.value }
30
+ end
31
+ }
32
+ end
33
+
34
+ rule property_key
35
+ (!SPACE ![()] character)+ {
36
+ def value
37
+ text_value
38
+ end
39
+ }
40
+ end
41
+
42
+ rule property_value
43
+ quoted_word
44
+ end
45
+ end
46
+ end
47
+ end
@@ -10,13 +10,17 @@ module Fonte
10
10
  end
11
11
 
12
12
  rule word
13
- (ESCAPED_QUOTE / !QUOTE .)* {
13
+ character* {
14
14
  def value
15
15
  text_value
16
16
  end
17
17
  }
18
18
  end
19
19
 
20
+ rule character
21
+ (ESCAPED_QUOTE / !QUOTE .)
22
+ end
23
+
20
24
  rule SPACE
21
25
  " "+
22
26
  end
@@ -1,3 +1,3 @@
1
1
  module Fonte
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,322 @@
1
+ require "spec_helper"
2
+
3
+ module Fonte
4
+ module Parsers
5
+ describe ActionParser do
6
+ let(:parser) { described_class.new }
7
+
8
+ subject { parser.parse(action) }
9
+
10
+ describe "log start" do
11
+ let(:action) { "Log file started" }
12
+ its(:value) { should == "log start" }
13
+
14
+ context "with properties" do
15
+ let(:action) { 'Log file started (file "logs/L0109005.log") (game "/home/ubuntu/srcds/orangebox/tf") (version "4785")' }
16
+ it_should_behave_like "a action with properties", "file", "game", "version"
17
+ end
18
+ end
19
+
20
+ describe "log end" do
21
+ let(:action) { "Log file closed" }
22
+ its(:value) { should == "log end" }
23
+ end
24
+
25
+ describe "cvar start" do
26
+ let(:action) { 'Server cvars start' }
27
+ its(:value) { should == "cvar start" }
28
+
29
+ context "when it starts with an downcase 'S'" do
30
+ let(:action) { 'server cvars start' }
31
+ its(:value) { should == "cvar start" }
32
+ end
33
+ end
34
+
35
+ describe "cvar end" do
36
+ let(:action) { 'Server cvars end' }
37
+ its(:value) { should == "cvar end" }
38
+
39
+ context "when it starts with an downcase 'S'" do
40
+ let(:action) { 'server cvars end' }
41
+ its(:value) { should == "cvar end" }
42
+ end
43
+ end
44
+
45
+ describe "cvar set" do
46
+ context "when it starts with 'Server'" do
47
+ let(:action) { 'Server cvar "key" = "value"' }
48
+ its(:value) { should == "cvar set" }
49
+ its(:"to_hash") { should == { "key" => "value"} }
50
+ end
51
+
52
+ context "when it starts with 'server'" do
53
+ let(:action) { 'server cvar "key" = "value"' }
54
+ its(:value) { should == "cvar set" }
55
+ its(:"to_hash") { should == { "key" => "value"} }
56
+ end
57
+
58
+ context "without the 'Server' entry" do
59
+ let(:action) { '"key" = "value"' }
60
+ its(:value) { should == "cvar set" }
61
+ its(:"to_hash") { should == { "key" => "value"} }
62
+ end
63
+ end
64
+
65
+ describe "sever name" do
66
+ let(:action) { 'Server name is "Manapot Server"' }
67
+ its(:value) { should == "server name" }
68
+ its(:"name.value") { should == "Manapot Server" }
69
+ end
70
+
71
+ describe "connection" do
72
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" connected, address "187.123.17.180:27005"' }
73
+ its(:value) { should == "connection" }
74
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><>" }
75
+ end
76
+
77
+ describe "validation" do
78
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" STEAM USERID validated' }
79
+ its(:value) { should == "validation" }
80
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><>" }
81
+ end
82
+
83
+ describe "enter game" do
84
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" entered the game' }
85
+ its(:value) { should == "enter" }
86
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><>" }
87
+ end
88
+
89
+ describe "map load" do
90
+ let(:action) { 'Loading map "c4m2_sugarmill_a"' }
91
+ its(:value) { should == "map load" }
92
+ its(:"name.value") { should == "c4m2_sugarmill_a" }
93
+ end
94
+
95
+ describe "map start" do
96
+ let(:action) { 'Started map "c4m2_sugarmill_a" (CRC "-431283537")' }
97
+ its(:value) { should == "map start" }
98
+ its(:"name.value") { should == "c4m2_sugarmill_a" }
99
+ its(:"crc.value") { should == "-431283537" }
100
+ end
101
+
102
+ describe "disconnection" do
103
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" disconnected' }
104
+ its(:value) { should == "disconnection" }
105
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><>" }
106
+
107
+ context "with properties" do
108
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" disconnected (reason "Disconnect by user.")' }
109
+ it_should_behave_like "a action with properties", "reason"
110
+ end
111
+ end
112
+
113
+ describe "kick" do
114
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" was kicked by "Console"' }
115
+ its(:value) { should == "kick" }
116
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><>" }
117
+
118
+ context "with properties" do
119
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" was kicked by "Console" (reason "Disconnect by user.")' }
120
+ it_should_behave_like "a action with properties", "reason"
121
+ end
122
+ end
123
+
124
+ describe "kick and ban" do
125
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" was kicked and banned by "Console"' }
126
+ its(:value) { should == "kickban" }
127
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><>" }
128
+
129
+ context "with properties" do
130
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" was kicked and banned by "Console" (reason "Disconnect by user.")' }
131
+ it_should_behave_like "a action with properties", "reason"
132
+ end
133
+ end
134
+
135
+ describe "suicide" do
136
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" committed suicide with "weapon"' }
137
+ its(:value) { should == "suicide" }
138
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><>" }
139
+ its(:"weapon.value") { should == "weapon" }
140
+
141
+ context "with properties" do
142
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" committed suicide with "weapon" (attacker_position "-3361 1361 -864")' }
143
+ it_should_behave_like "a action with properties", "attacker_position"
144
+ end
145
+ end
146
+
147
+ describe "join team" do
148
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><>" joined team "Spectator"' }
149
+ its(:value) { should == "join" }
150
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><>" }
151
+ its(:"team.value") { should == "Spectator" }
152
+ end
153
+
154
+ describe "role selection" do
155
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" changed role to "spy"' }
156
+ its(:value) { should == "role selection" }
157
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
158
+ its(:"role.value") { should == "spy" }
159
+ end
160
+
161
+ describe "name change" do
162
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" changed name to "Navarro"' }
163
+ its(:value) { should == "name change" }
164
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
165
+ its(:"new_name.value") { should == "Navarro" }
166
+ end
167
+
168
+ describe "kill" do
169
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" killed "guimello<13><STEAM_1:1:34492580><Red>" with "minigun"' }
170
+ its(:value) { should == "kill" }
171
+ its(:"attacker.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
172
+ its(:"victim.value") { should == "guimello<13><STEAM_1:1:34492580><Red>" }
173
+
174
+ context "with properties" do
175
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" killed "guimello<13><STEAM_1:1:34492580><Red>" with "minigun" (attacker_position "3354 -2485 -187") (victim_position "3410 -2518 -149")' }
176
+ it_should_behave_like "a action with properties", "attacker_position", "victim_position"
177
+ end
178
+ end
179
+
180
+ describe "injure" do
181
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" attacked "guimello<13><STEAM_1:1:34492580><Red>" with "minigun"' }
182
+ its(:value) { should == "injure" }
183
+ its(:"attacker.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
184
+ its(:"victim.value") { should == "guimello<13><STEAM_1:1:34492580><Red>" }
185
+
186
+ context "with properties" do
187
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" attacked "guimello<13><STEAM_1:1:34492580><Red>" with "minigun" (attacker_position "3354 -2485 -187") (victim_position "3410 -2518 -149")' }
188
+ it_should_behave_like "a action with properties", "attacker_position", "victim_position"
189
+ end
190
+ end
191
+
192
+ describe "action trigger against player" do
193
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" triggered "player_extinguished" against "guimello<13><STEAM_1:1:34492580><Red>"' }
194
+ its(:value) { should == "player_extinguished" }
195
+ its(:"attacker.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
196
+ its(:"victim.value") { should == "guimello<13><STEAM_1:1:34492580><Red>" }
197
+
198
+ context "with extra arguments" do
199
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" triggered "player_extinguished" against "guimello<13><STEAM_1:1:34492580><Red>"' }
200
+ its(:value) { should == "player_extinguished" }
201
+ its(:"attacker.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
202
+ its(:"victim.value") { should == "guimello<13><STEAM_1:1:34492580><Red>" }
203
+ end
204
+
205
+ context "with properties" do
206
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" triggered "player_extinguished" against "guimello<13><STEAM_1:1:34492580><Red>" (attacker_position "3354 -2485 -187") (victim_position "3410 -2518 -149")' }
207
+ it_should_behave_like "a action with properties", "attacker_position", "victim_position"
208
+ its(:value) { should == "player_extinguished" }
209
+ its(:"attacker.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
210
+ its(:"victim.value") { should == "guimello<13><STEAM_1:1:34492580><Red>" }
211
+ end
212
+
213
+ context "with properties and extra arguments" do
214
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" triggered "player_extinguished" against "guimello<13><STEAM_1:1:34492580><Red>" with "tf_weapon_medigun" (attacker_position "3354 -2485 -187") (victim_position "3410 -2518 -149")' }
215
+ it_should_behave_like "a action with properties", "attacker_position", "victim_position"
216
+ its(:value) { should == "player_extinguished" }
217
+ its(:"attacker.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
218
+ its(:"victim.value") { should == "guimello<13><STEAM_1:1:34492580><Red>" }
219
+ end
220
+ end
221
+
222
+ describe "player action" do
223
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" triggered "builtobject"' }
224
+ its(:value) { should == "builtobject" }
225
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
226
+
227
+ context "with properties" do
228
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" triggered "builtobject" (attacker_position "3354 -2485 -187") (victim_position "3410 -2518 -149")' }
229
+ it_should_behave_like "a action with properties", "attacker_position", "victim_position"
230
+ end
231
+ end
232
+
233
+ describe "team action" do
234
+ let(:action) { 'Team "Red" triggered "capture"' }
235
+ its(:value) { should == "capture" }
236
+ its(:"team.value") { should == "Red" }
237
+
238
+ context "with properties" do
239
+ let(:action) { 'Team "Red" triggered "pointcaptured" (cp "3") (cpname "#Badwater_cap_4") (numcappers "1") (player1 "Reu<2><STEAM_1:1:24968171><Blue>") (position1 "-2902 1411 617")' }
240
+ it_should_behave_like "a action with properties", "cp", "cpname", "numcappers", "player1", "position1"
241
+ end
242
+ end
243
+
244
+ describe "world action" do
245
+ let(:action) { 'World triggered "Round_Start"' }
246
+ its(:value) { should == "Round_Start" }
247
+
248
+ context "with properties" do
249
+ let(:action) { 'World triggered "Mini_Round_Selected" (round "Round_A")' }
250
+ it_should_behave_like "a action with properties", "round"
251
+ end
252
+ end
253
+
254
+ describe "chat" do
255
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" say "hai"' }
256
+ its(:value) { should == "chat" }
257
+ its(:"message.value") { should == "hai" }
258
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
259
+ end
260
+
261
+ describe "team chat" do
262
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" say_team "hai"' }
263
+ its(:value) { should == "team chat" }
264
+ its(:"message.value") { should == "hai" }
265
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
266
+ end
267
+
268
+ describe "private chat" do
269
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" tell "guimello<13><STEAM_1:1:34492580><Blue>" message "gogogo"' }
270
+ its(:value) { should == "private chat" }
271
+ its(:"message.value") { should == "gogogo" }
272
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
273
+ its(:"target.value") { should == "guimello<13><STEAM_1:1:34492580><Blue>" }
274
+ end
275
+
276
+ describe "sever chat" do
277
+ let(:action) { 'Server say "Hai"' }
278
+ its(:value) { should == "server chat" }
279
+ its(:"message.value") { should == "Hai" }
280
+ end
281
+
282
+ describe "team alliance" do
283
+ let(:action) { 'Team "Red" formed alliance with team "Blue"' }
284
+ its(:value) { should == "alliance" }
285
+ its(:"team.value") { should == "Red" }
286
+ its(:"allied_team.value") { should == "Blue" }
287
+ end
288
+
289
+ describe "score report" do
290
+ let(:action) { 'Team "Red" scored "3" with "12" players' }
291
+ its(:value) { should == "team score" }
292
+ its(:"team.value") { should == "Red" }
293
+ its(:"points.value") { should == 3 }
294
+ its(:"players_count.value") { should == 12 }
295
+
296
+ context "final score" do
297
+ let(:action) { 'Team "Red" final score "3" with "12" players' }
298
+ its(:value) { should == "final score" }
299
+ end
300
+
301
+ context "current score" do
302
+ let(:action) { 'Team "Red" current score "3" with "12" players' }
303
+ its(:value) { should == "current score" }
304
+ end
305
+ end
306
+
307
+ describe "weapon selection" do
308
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" selected weapon "AWP"' }
309
+ its(:value) { should == "weapon selection" }
310
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
311
+ its(:"weapon.value") { should == "AWP" }
312
+ end
313
+
314
+ describe "weapon pickup" do
315
+ let(:action) { '"Reu<2><STEAM_1:1:24968171><Blue>" acquired weapon "Shotgun"' }
316
+ its(:value) { should == "weapon pickup" }
317
+ its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
318
+ its(:"weapon.value") { should == "Shotgun" }
319
+ end
320
+ end
321
+ end
322
+ end
@@ -23,166 +23,6 @@ module Fonte
23
23
  end
24
24
 
25
25
  describe "commands" do
26
- describe "log started command" do
27
- let(:text) { 'L 12/26/2011 - 02:14:29: Log file started (file "logs/L127_000_001_001_27015_201112260214_000.log") (game "/home/ubuntu/srcds/left4dead2/left4dead2") (version "4777")' }
28
- it { should be }
29
-
30
- let(:command) { parser.parse(text).command }
31
-
32
- describe "log filename" do
33
- subject { command.log_filename.value }
34
- it { should == "logs/L127_000_001_001_27015_201112260214_000.log" }
35
- end
36
-
37
- describe "game path" do
38
- subject { command.log_game_path.value }
39
- it { should == "/home/ubuntu/srcds/left4dead2/left4dead2" }
40
- end
41
-
42
- describe "game version" do
43
- subject { command.log_game_version.value }
44
- it { should == "4777" }
45
- end
46
- end
47
-
48
- describe "cvar start command" do
49
- let(:command) { parser.parse(text).command }
50
-
51
- context "when server starts with an upcase 'S'" do
52
- let(:text) { 'L 12/26/2011 - 02:14:29: Server cvars start' }
53
- it { should be }
54
- end
55
-
56
- context "when server starts with an downcase 'S'" do
57
- let(:text) { 'L 12/26/2011 - 02:14:29: server cvars start' }
58
- it { should be }
59
- end
60
- end
61
-
62
- describe "cvar end command" do
63
- let(:command) { parser.parse(text).command }
64
-
65
- context "when server starts with an upcase 'S'" do
66
- let(:text) { 'L 12/26/2011 - 02:14:29: Server cvars end' }
67
- it { should be }
68
- end
69
-
70
- context "when server starts with an downcase 'S'" do
71
- let(:text) { 'L 12/26/2011 - 02:14:29: server cvars end' }
72
- it { should be }
73
- end
74
- end
75
-
76
- describe "cvar set command" do
77
- let(:command) { parser.parse(text).command }
78
-
79
- context "when server starts with an upcase 'S'" do
80
- let(:text) { 'L 12/26/2011 - 02:14:29: Server cvar "var" = "value"' }
81
- it { should be }
82
-
83
- describe "the variable" do
84
- subject { command }
85
-
86
- its(:value) { should == "value" }
87
- its(:name) { should == "var" }
88
- end
89
- end
90
-
91
- context "when server starts with an downcase 'S'" do
92
- let(:text) { 'L 12/26/2011 - 02:14:29: server cvar "var" = "value"' }
93
- it { should be }
94
-
95
- describe "the variable" do
96
- subject { command }
97
-
98
- its(:value) { should == "value" }
99
- its(:name) { should == "var" }
100
- end
101
- end
102
-
103
- context "when server starts without the Server cvar entry " do
104
- let(:text) { 'L 12/26/2011 - 02:14:29: "var" = "value"' }
105
- it { should be }
106
-
107
- describe "the variable" do
108
- subject { command }
109
-
110
- its(:value) { should == "value" }
111
- its(:name) { should == "var" }
112
- end
113
- end
114
- end
115
-
116
- describe "map loading command" do
117
- let(:text) { 'L 12/26/2011 - 02:14:29: Loading map "c4m2_sugarmill_a"' }
118
- it { should be }
119
-
120
- let(:command) { parser.parse(text).command }
121
-
122
- describe "map name" do
123
- subject { command.map_name.value }
124
- it { should == "c4m2_sugarmill_a" }
125
- end
126
- end
127
-
128
- describe "map started command" do
129
- let(:text) { 'L 12/26/2011 - 02:14:33: Started map "c4m2_sugarmill_a" (CRC "-431283537")' }
130
- it { should be }
131
-
132
- let(:command) { parser.parse(text).command }
133
-
134
- describe "map name" do
135
- subject { command.map_name.value }
136
- it { should == "c4m2_sugarmill_a" }
137
- end
138
-
139
- describe "map CRC" do
140
- subject { command.map_crc.value }
141
- it { should == "-431283537" }
142
- end
143
- end
144
-
145
- describe "map started command" do
146
- let(:text) { 'L 12/26/2011 - 02:14:33: Started map "c4m2_sugarmill_a" (CRC "-431283537")' }
147
- it { should be }
148
-
149
- let(:command) { parser.parse(text).command }
150
-
151
- describe "map name" do
152
- subject { command.map_name.value }
153
- it { should == "c4m2_sugarmill_a" }
154
- end
155
-
156
- describe "map CRC" do
157
- subject { command.map_crc.value }
158
- it { should == "-431283537" }
159
- end
160
- end
161
-
162
- describe "sever name command" do
163
- let(:text) { 'L 12/26/2011 - 02:14:33: Server name is "Manapot Server"' }
164
- it { should be }
165
-
166
- let(:command) { parser.parse(text).command }
167
-
168
- describe "server name" do
169
- subject { command.server_name.value }
170
- it { should == "Manapot Server" }
171
- end
172
- end
173
-
174
- describe "sever say command" do
175
- let(:text) { 'L 12/26/2011 - 02:14:33: Server say "Hai"' }
176
- it { should be }
177
-
178
- let(:command) { parser.parse(text).command }
179
-
180
- describe "server say" do
181
- subject { command.server_say.value }
182
- it { should == "Hai" }
183
- end
184
- end
185
-
186
26
  describe "rcon command" do
187
27
  let(:text) { 'L 12/26/2011 - 02:14:33: Rcon: "rcon challenge "password" command" from "192.168.10.1:17015"' }
188
28
  subject { parser.parse(text).command }
@@ -8,6 +8,8 @@ module Fonte
8
8
 
9
9
  subject { parser.parse(player) }
10
10
 
11
+ its(:value) { should == "Reu<2><STEAM_1:1:24968171><Red>" }
12
+
11
13
  its(:"nickname.value") { should == "Reu" }
12
14
  its(:"uid.value") { should == 2 }
13
15
  its(:"steam_id.value") { should == "STEAM_1:1:24968171" }
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ module Fonte
4
+ module Parsers
5
+ describe PropertyParser do
6
+ let(:parser) { described_class.new }
7
+
8
+ subject { parser.parse(properties) }
9
+
10
+ context "with one property" do
11
+ let(:properties) { '(key "value")' }
12
+ it { should be }
13
+ its(:value) { should == { "key" => "value" } }
14
+ end
15
+
16
+ context "with multiple properties" do
17
+ let(:properties) { '(key1 "value1") (key2 "value2")' }
18
+ it { should be }
19
+ its(:value) { should == { "key1" => "value1", "key2" => "value2" } }
20
+ end
21
+
22
+ context "with properties without values" do
23
+ let(:properties) { '(headshot)' }
24
+ it { should be }
25
+ its(:value) { should == { "headshot" => true } }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ shared_examples "a action with properties" do |*properties|
2
+ its(:"properties.value") { should respond_to :keys }
3
+ its(:"properties.value") { should respond_to :values }
4
+
5
+ if properties
6
+ properties.each do |property|
7
+ its(:"properties.value.keys") { should include property }
8
+ end
9
+ end
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fonte
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,30 +9,30 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-14 00:00:00.000000000Z
12
+ date: 2012-01-16 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2160380860 !ruby/object:Gem::Requirement
16
+ requirement: &2151839440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: 2.8.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2160380860
24
+ version_requirements: *2151839440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: treetop
27
- requirement: &2160380280 !ruby/object:Gem::Requirement
27
+ requirement: &2151837980 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
- - - ! '>='
30
+ - - ~>
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
32
+ version: 1.4.8
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2160380280
35
+ version_requirements: *2151837980
36
36
  description:
37
37
  email:
38
38
  - rnavarro1@gmail.com
@@ -56,24 +56,29 @@ files:
56
56
  - lib/fonte/nodes/steam_id_node.rb
57
57
  - lib/fonte/nodes/steam_id_universe_node.rb
58
58
  - lib/fonte/parsers.rb
59
+ - lib/fonte/parsers/action.treetop
59
60
  - lib/fonte/parsers/address.treetop
60
61
  - lib/fonte/parsers/log.treetop
61
62
  - lib/fonte/parsers/number.treetop
62
63
  - lib/fonte/parsers/player.treetop
64
+ - lib/fonte/parsers/property.treetop
63
65
  - lib/fonte/parsers/rcon.treetop
64
66
  - lib/fonte/parsers/steam_id.treetop
65
67
  - lib/fonte/parsers/temporal.treetop
66
68
  - lib/fonte/parsers/word.treetop
67
69
  - lib/fonte/version.rb
70
+ - spec/parsers/action_parser_spec.rb
68
71
  - spec/parsers/address_parser_spec.rb
69
72
  - spec/parsers/log_parser_spec.rb
70
73
  - spec/parsers/number_parser_spec.rb
71
74
  - spec/parsers/player_parser_spec.rb
75
+ - spec/parsers/property_parser_spec.rb
72
76
  - spec/parsers/rcon_parser_spec.rb
73
77
  - spec/parsers/steam_id_parser_spec.rb
74
78
  - spec/parsers/temporal_parser_spec.rb
75
79
  - spec/parsers/word_parser_spec.rb
76
80
  - spec/spec_helper.rb
81
+ - spec/support/shared_examples/properties.rb
77
82
  - spec/support/shared_examples/rcon_command.rb
78
83
  homepage: https://github.com/reu/fonte
79
84
  licenses: []
@@ -89,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
89
94
  version: '0'
90
95
  segments:
91
96
  - 0
92
- hash: 3476406977491015761
97
+ hash: 3614551501371426417
93
98
  required_rubygems_version: !ruby/object:Gem::Requirement
94
99
  none: false
95
100
  requirements:
@@ -98,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
103
  version: '0'
99
104
  segments:
100
105
  - 0
101
- hash: 3476406977491015761
106
+ hash: 3614551501371426417
102
107
  requirements: []
103
108
  rubyforge_project: fonte
104
109
  rubygems_version: 1.8.10
@@ -106,13 +111,16 @@ signing_key:
106
111
  specification_version: 3
107
112
  summary: Valve Source Engine log parser
108
113
  test_files:
114
+ - spec/parsers/action_parser_spec.rb
109
115
  - spec/parsers/address_parser_spec.rb
110
116
  - spec/parsers/log_parser_spec.rb
111
117
  - spec/parsers/number_parser_spec.rb
112
118
  - spec/parsers/player_parser_spec.rb
119
+ - spec/parsers/property_parser_spec.rb
113
120
  - spec/parsers/rcon_parser_spec.rb
114
121
  - spec/parsers/steam_id_parser_spec.rb
115
122
  - spec/parsers/temporal_parser_spec.rb
116
123
  - spec/parsers/word_parser_spec.rb
117
124
  - spec/spec_helper.rb
125
+ - spec/support/shared_examples/properties.rb
118
126
  - spec/support/shared_examples/rcon_command.rb