fonte 0.0.1 → 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.
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