fonte 0.1.0 → 0.2.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.
@@ -1,6 +1,10 @@
1
1
  language: ruby
2
2
  script: bundle exec rspec -bfd spec
3
3
  rvm:
4
+ - 1.8.7
4
5
  - 1.9.2
5
6
  - 1.9.3
6
7
  - jruby
8
+ - ree
9
+ - rbx-18mode
10
+ - rbx-19mode
data/README.md CHANGED
@@ -34,7 +34,7 @@ log.date_time.day # => 26
34
34
  ```
35
35
 
36
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.
37
+ In the current version it can parse all TF2, L4D, CSS and DOD files.
38
38
 
39
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".
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.
@@ -1,6 +1,5 @@
1
1
  require "fonte/version"
2
2
  require "treetop"
3
- require "polyglot"
4
3
  require "fonte/nodes"
5
4
  require "fonte/parsers"
6
5
 
@@ -1,6 +1,6 @@
1
1
  module Fonte
2
2
  module Parsers
3
- %w(number word temporal address rcon steam_id property player action log).each do |parser|
3
+ %w(word number temporal address rcon steam_id source_player l4d2_player player property action log).each do |parser|
4
4
  Treetop.load File.join(File.dirname(__FILE__), "parsers", parser)
5
5
  end
6
6
  end
@@ -5,6 +5,7 @@ module Fonte
5
5
  include Player
6
6
  include Address
7
7
  include Property
8
+ include Rcon
8
9
 
9
10
  rule action
10
11
  log_started_action
@@ -39,6 +40,9 @@ module Fonte
39
40
  / score_report
40
41
  / weapon_selection_action
41
42
  / weapon_pickup_action
43
+ / rcon_command
44
+ / steamauth_failure_action
45
+ / spawn_action
42
46
  end
43
47
 
44
48
  rule log_started_action
@@ -74,7 +78,7 @@ module Fonte
74
78
  end
75
79
 
76
80
  rule cvar_set_action
77
- ([Ss] "erver cvar" SPACE)? key:quoted_word SPACE "=" SPACE val:quoted_word {
81
+ (cvar_set_complete_syntax / cvar_set_colon_sytax) {
78
82
  def value
79
83
  "cvar set"
80
84
  end
@@ -85,6 +89,14 @@ module Fonte
85
89
  }
86
90
  end
87
91
 
92
+ rule cvar_set_complete_syntax
93
+ ([Ss] "erver cvar" SPACE)? key:quoted_word SPACE "=" SPACE val:quoted_word
94
+ end
95
+
96
+ rule cvar_set_colon_sytax
97
+ "server_cvar:" SPACE key:quoted_word SPACE val:quoted_word
98
+ end
99
+
88
100
  rule map_loading_action
89
101
  "Loading map" SPACE name:map_name {
90
102
  def value
@@ -206,6 +218,10 @@ module Fonte
206
218
  end
207
219
 
208
220
  rule kill_action
221
+ source_kill_action / l4d2_kill_action
222
+ end
223
+
224
+ rule source_kill_action
209
225
  QUOTE attacker:player QUOTE SPACE "killed" SPACE QUOTE victim:player QUOTE SPACE "with" SPACE QUOTE weapon QUOTE properties:action_properties? {
210
226
  def value
211
227
  "kill"
@@ -213,6 +229,31 @@ module Fonte
213
229
  }
214
230
  end
215
231
 
232
+ # TODO: move this to separated grammar
233
+ rule l4d2_kill_action
234
+ "(DEATH)" source_kill_action {
235
+ def value
236
+ "kill"
237
+ end
238
+
239
+ def attacker
240
+ source_kill_action.attacker
241
+ end
242
+
243
+ def victim
244
+ source_kill_action.victim
245
+ end
246
+
247
+ def weapon
248
+ source_kill_action.weapon
249
+ end
250
+
251
+ def properties
252
+ source_kill_action.properties
253
+ end
254
+ }
255
+ end
256
+
216
257
  rule injure_action
217
258
  QUOTE attacker:player QUOTE SPACE "attacked" SPACE QUOTE victim:player QUOTE SPACE "with" SPACE QUOTE weapon QUOTE properties:action_properties? {
218
259
  def value
@@ -246,13 +287,21 @@ module Fonte
246
287
  end
247
288
 
248
289
  rule triggered_world_action
249
- "World triggered" SPACE action:quoted_word properties:action_properties? {
290
+ "World triggered" SPACE action:quoted_word reason:triggered_world_action_reason? properties:action_properties? {
250
291
  def value
251
292
  action.value
252
293
  end
253
294
  }
254
295
  end
255
296
 
297
+ rule triggered_world_action_reason
298
+ SPACE "reason" SPACE reason:quoted_word {
299
+ def value
300
+ reason.value
301
+ end
302
+ }
303
+ end
304
+
256
305
  rule chat_action
257
306
  QUOTE player QUOTE SPACE "say" SPACE message:quoted_word {
258
307
  def value
@@ -322,6 +371,30 @@ module Fonte
322
371
  }
323
372
  end
324
373
 
374
+ rule steamauth_failure_action
375
+ "STEAMAUTH: Client" SPACE client:steamauth_client SPACE "received failure code" SPACE code:integer {
376
+ def value
377
+ "authentication failure"
378
+ end
379
+ }
380
+ end
381
+
382
+ rule spawn_action
383
+ QUOTE player QUOTE SPACE "spawned" {
384
+ def value
385
+ "spawn"
386
+ end
387
+ }
388
+ end
389
+
390
+ rule steamauth_client
391
+ (!SPACE .)+ {
392
+ def value
393
+ text_value
394
+ end
395
+ }
396
+ end
397
+
325
398
  rule role
326
399
  word
327
400
  end
@@ -0,0 +1,93 @@
1
+ module Fonte
2
+ module Parsers
3
+ grammar L4D2Player
4
+ include Word
5
+ include Number
6
+ include SourcePlayer
7
+
8
+ rule l4d2_player
9
+ source_player "<" character:l4d2_character ">" "<" status:l4d2_player_status ">" "<" l4d2_life ">" "<" l4d2_position ">" "<" area:l4d2_area ">" {
10
+ def nickname
11
+ source_player.nickname
12
+ end
13
+
14
+ def uid
15
+ source_player.uid
16
+ end
17
+
18
+ def steam_id
19
+ source_player.steam_id
20
+ end
21
+
22
+ def team
23
+ source_player.team
24
+ end
25
+
26
+ def life
27
+ l4d2_life.value[:life]
28
+ end
29
+
30
+ def blood
31
+ l4d2_life.value[:blood]
32
+ end
33
+
34
+ def position
35
+ l4d2_position.position
36
+ end
37
+
38
+ def angle
39
+ l4d2_position.angle
40
+ end
41
+
42
+ def value
43
+ source_player.value
44
+ end
45
+ }
46
+ end
47
+
48
+ rule l4d2_character
49
+ (![<>] character)* {
50
+ def value
51
+ text_value
52
+ end
53
+ }
54
+ end
55
+
56
+ rule l4d2_player_status
57
+ (![<>] character)* {
58
+ def value
59
+ text_value
60
+ end
61
+ }
62
+ end
63
+
64
+ rule l4d2_life
65
+ l4d2_life_blood / "0" {
66
+ def value
67
+ { :life => 0, :blood => 0 }
68
+ end
69
+ }
70
+ end
71
+
72
+ rule l4d2_life_blood
73
+ life:integer "+" blood:integer {
74
+ def value
75
+ { :life => life.value, :blood => blood.value }
76
+ end
77
+ }
78
+ end
79
+
80
+ rule l4d2_position
81
+ "setpos_exact" SPACE position:coordinates ";" SPACE "setang" SPACE angle:coordinates
82
+ end
83
+
84
+ rule l4d2_area
85
+ "Area" SPACE integer {
86
+ def value
87
+ integer.value
88
+ end
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
@@ -3,15 +3,10 @@ module Fonte
3
3
  grammar Log
4
4
  include Word
5
5
  include Temporal
6
- include Rcon
7
6
  include Action
8
7
 
9
8
  rule entry
10
- "L" SPACE date_time ":" SPACE command "\n"?
11
- end
12
-
13
- rule command
14
- action / rcon_command
9
+ (!"L" .)* "L" SPACE date_time ":" SPACE command:action "\n"?
15
10
  end
16
11
  end
17
12
  end
@@ -1,8 +1,10 @@
1
1
  module Fonte
2
2
  module Parsers
3
3
  grammar Number
4
+ include Word
5
+
4
6
  rule number
5
- float / integer
7
+ coordinates / float / integer
6
8
  end
7
9
 
8
10
  rule float
@@ -35,6 +37,18 @@ module Fonte
35
37
  end
36
38
  }
37
39
  end
40
+
41
+ rule coordinates
42
+ x:coordinate SPACE y:coordinate SPACE z:coordinate {
43
+ def value
44
+ [x.value, y.value, z.value]
45
+ end
46
+ }
47
+ end
48
+
49
+ rule coordinate
50
+ float / integer
51
+ end
38
52
  end
39
53
  end
40
54
  end
@@ -1,36 +1,11 @@
1
1
  module Fonte
2
2
  module Parsers
3
3
  grammar Player
4
- include Number
5
- include Word
6
- include SteamID
4
+ include SourcePlayer
5
+ include L4D2Player
7
6
 
8
7
  rule player
9
- nickname "<" uid ">" "<" steam_id ">" "<" team ">" {
10
- def value
11
- text_value
12
- end
13
- }
14
- end
15
-
16
- rule nickname
17
- (![<>] .)* {
18
- def value
19
- text_value
20
- end
21
- }
22
- end
23
-
24
- rule uid
25
- integer
26
- end
27
-
28
- rule team
29
- (![<>] character)* {
30
- def value
31
- text_value == "Unassigned" || text_value == "Console" || text_value == "" ? nil : text_value
32
- end
33
- }
8
+ l4d2_player / source_player
34
9
  end
35
10
  end
36
11
  end
@@ -2,6 +2,8 @@ module Fonte
2
2
  module Parsers
3
3
  grammar Property
4
4
  include Word
5
+ include Number
6
+ include Player
5
7
 
6
8
  rule properties
7
9
  property+ {
@@ -40,7 +42,19 @@ module Fonte
40
42
  end
41
43
 
42
44
  rule property_value
43
- quoted_word
45
+ number_property / player_property / quoted_word
46
+ end
47
+
48
+ rule player_property
49
+ QUOTE value:player QUOTE
50
+ end
51
+
52
+ rule number_property
53
+ QUOTE number QUOTE {
54
+ def value
55
+ number.value
56
+ end
57
+ }
44
58
  end
45
59
  end
46
60
  end
@@ -9,11 +9,19 @@ module Fonte
9
9
  end
10
10
 
11
11
  rule rcon_success
12
- "Rcon:" SPACE rcon_challenge <Fonte::Nodes::RconCommandNode>
12
+ "Rcon:" SPACE rcon_challenge <Fonte::Nodes::RconCommandNode> {
13
+ def value
14
+ "successfully rcon"
15
+ end
16
+ }
13
17
  end
14
18
 
15
19
  rule rcon_failure
16
- "Bad Rcon:" SPACE rcon_challenge <Fonte::Nodes::RconCommandNode>
20
+ "Bad Rcon:" SPACE rcon_challenge <Fonte::Nodes::RconCommandNode> {
21
+ def value
22
+ "bad rcon"
23
+ end
24
+ }
17
25
  end
18
26
 
19
27
  rule rcon_challenge
@@ -0,0 +1,45 @@
1
+ module Fonte
2
+ module Parsers
3
+ grammar SourcePlayer
4
+ include Number
5
+ include Word
6
+ include SteamID
7
+
8
+ rule source_player
9
+ nickname "<" uid ">" "<" steam_id:player_steam_id ">" "<" team ">" {
10
+ def value
11
+ text_value
12
+ end
13
+ }
14
+ end
15
+
16
+ rule nickname
17
+ (![<>] character)* {
18
+ def value
19
+ text_value
20
+ end
21
+ }
22
+ end
23
+
24
+ rule uid
25
+ integer
26
+ end
27
+
28
+ rule player_steam_id
29
+ steam_id / "" {
30
+ def value
31
+ nil
32
+ end
33
+ }
34
+ end
35
+
36
+ rule team
37
+ (![<>] character)* {
38
+ def value
39
+ text_value == "Unassigned" || text_value == "Console" || text_value == "" ? nil : text_value
40
+ end
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -24,7 +24,7 @@ module Fonte
24
24
  end
25
25
 
26
26
  rule steam_id_bot
27
- "Bot" <Fonte::Nodes::SteamIDNode> {
27
+ "B" ("ot" / "OT") <Fonte::Nodes::SteamIDNode> {
28
28
  def bot?
29
29
  true
30
30
  end
@@ -1,3 +1,3 @@
1
1
  module Fonte
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -60,6 +60,12 @@ module Fonte
60
60
  its(:value) { should == "cvar set" }
61
61
  its(:"to_hash") { should == { "key" => "value"} }
62
62
  end
63
+
64
+ context "when it starts with server_cvar" do
65
+ let(:action) { 'server_cvar: "key" "value"' }
66
+ its(:value) { should == "cvar set" }
67
+ its(:"to_hash") { should == { "key" => "value"} }
68
+ end
63
69
  end
64
70
 
65
71
  describe "sever name" do
@@ -175,6 +181,18 @@ module Fonte
175
181
  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
182
  it_should_behave_like "a action with properties", "attacker_position", "victim_position"
177
183
  end
184
+
185
+ context "l4d2 format" do
186
+ let(:action) { '(DEATH)"Reu<2><STEAM_1:1:24968171><Survivor><Gambler><ALIVE><80+0><setpos_exact 4793.19 -3962.89 165.33; setang 18.14 -34.47 0.00><Area 70>" killed "infected<552><><Infected><infected><DEAD><0><setpos_exact 4831.17 -3989.32 104.81; setang 0.00 288.65 0.00><Area 792>" with "melee"' }
187
+ its(:value) { should == "kill" }
188
+ its(:"attacker.value") { should == "Reu<2><STEAM_1:1:24968171><Survivor>" }
189
+ its(:"victim.value") { should == "infected<552><><Infected>" }
190
+
191
+ context "with properties" do
192
+ let(:action) { '(DEATH)"Reu<2><STEAM_1:1:24968171><Survivor><Gambler><ALIVE><80+0><setpos_exact 4793.19 -3962.89 165.33; setang 18.14 -34.47 0.00><Area 70>" killed "infected<552><><Infected><infected><DEAD><0><setpos_exact 4831.17 -3989.32 104.81; setang 0.00 288.65 0.00><Area 792>" with "melee" (headshot)' }
193
+ it_should_behave_like "a action with properties", "headshot"
194
+ end
195
+ end
178
196
  end
179
197
 
180
198
  describe "injure" do
@@ -249,6 +267,11 @@ module Fonte
249
267
  let(:action) { 'World triggered "Mini_Round_Selected" (round "Round_A")' }
250
268
  it_should_behave_like "a action with properties", "round"
251
269
  end
270
+
271
+ context "with reason" do
272
+ let(:action) { 'World triggered "Game_Over" reason "Reached Time Limit"' }
273
+ its(:value) { should == "Game_Over" }
274
+ end
252
275
  end
253
276
 
254
277
  describe "chat" do
@@ -317,6 +340,24 @@ module Fonte
317
340
  its(:"player.value") { should == "Reu<2><STEAM_1:1:24968171><Blue>" }
318
341
  its(:"weapon.value") { should == "Shotgun" }
319
342
  end
343
+
344
+ describe "rcon command" do
345
+ let(:action) { 'Rcon: "rcon challenge "password" command" from "192.168.10.1:17015"' }
346
+ it_should_behave_like "a rcon command", :password => "password", :origin => "//192.168.10.1:17015"
347
+ end
348
+
349
+ describe "steamauth" do
350
+ let(:action) { 'STEAMAUTH: Client reu received failure code 6' }
351
+ its(:value) { should == "authentication failure" }
352
+ its(:"client.value") { should == "reu" }
353
+ its(:"code.value") { should == 6 }
354
+ end
355
+
356
+ describe "spawn" do
357
+ let(:action) { '"Pulo_ms<8><STEAM_1:1:41920953><Survivor><Producer><ALIVE><100+0><setpos_exact 3617.36 -1739.69 294.53; setang 0.00 179.84 0.00><Area 205>" spawned' }
358
+ its(:value) { should == "spawn" }
359
+ its(:"player.value") { should == "Pulo_ms<8><STEAM_1:1:41920953><Survivor>" }
360
+ end
320
361
  end
321
362
  end
322
363
  end
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ module Fonte
4
+ module Parsers
5
+ describe L4D2PlayerParser do
6
+ subject { parser.parse(player) }
7
+ let(:parser) { described_class.new }
8
+
9
+ context "of a real player" do
10
+ let(:player) { "Pulo_ms<8><STEAM_1:1:41920953><Survivor><Producer><ALIVE><100+0><setpos_exact 3617.36 -1739.69 294.53; setang 0.00 179.84 0.00><Area 205>" }
11
+
12
+ it_should_behave_like "a real player"
13
+
14
+ its(:value) { should == "Pulo_ms<8><STEAM_1:1:41920953><Survivor>" }
15
+
16
+ its(:"nickname.value") { should == "Pulo_ms" }
17
+ its(:"uid.value") { should == 8 }
18
+ its(:"steam_id.value") { should == "STEAM_1:1:41920953" }
19
+ its(:"team.value") { should == "Survivor" }
20
+ its(:"character.value") { should == "Producer" }
21
+ its(:"status.value") { should == "ALIVE" }
22
+ its(:life) { should == 100 }
23
+ its(:blood) { should == 0 }
24
+ its(:"position.value") { should == [3617.36, -1739.69, 294.53] }
25
+ its(:"angle.value") { should == [0.00, 179.84, 0.00] }
26
+ its(:"area.value") { should == 205 }
27
+ end
28
+
29
+ context "of a infected" do
30
+ let(:player) { "infected<552><><Infected><infected><DEAD><100+50><setpos_exact 4831.17 -3989.32 104.81; setang 0.00 288.65 0.00><Area 792>" }
31
+
32
+ its(:value) { should == "infected<552><><Infected>" }
33
+
34
+ its(:"nickname.value") { should == "infected" }
35
+ its(:"uid.value") { should == 552 }
36
+ its(:"steam_id.value") { should be_nil }
37
+ its(:"team.value") { should == "Infected" }
38
+ its(:"character.value") { should == "infected" }
39
+ its(:"status.value") { should == "DEAD" }
40
+ its(:life) { should == 100 }
41
+ its(:blood) { should == 50 }
42
+ its(:"position.value") { should == [4831.17, -3989.32, 104.81] }
43
+ its(:"angle.value") { should == [0.00, 288.65, 0.00] }
44
+ its(:"area.value") { should == 792 }
45
+ end
46
+
47
+ context "with zero life" do
48
+ let(:player) { "infected<552><><Infected><infected><DEAD><0><setpos_exact 4831.17 -3989.32 104.81; setang 0.00 288.65 0.00><Area 792>" }
49
+
50
+ its(:life) { should == 0 }
51
+ its(:blood) { should == 0 }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -20,13 +20,15 @@ module Fonte
20
20
  subject { parser.parse(text).command }
21
21
  it { should be }
22
22
  end
23
- end
24
23
 
25
- describe "commands" do
26
- describe "rcon command" do
27
- let(:text) { 'L 12/26/2011 - 02:14:33: Rcon: "rcon challenge "password" command" from "192.168.10.1:17015"' }
28
- subject { parser.parse(text).command }
29
- it_should_behave_like "a rcon command", :password => "password", :origin => "//192.168.10.1:17015"
24
+ context "when there are garbage before the log line" do
25
+ let(:text) { '????RL 12/26/2011 - 02:14:29: Loading map "c4m2_sugarmill_a"' }
26
+ it { should be }
27
+ end
28
+
29
+ context "when there is a line break after the log line" do
30
+ let(:text) { "L 12/26/2011 - 02:14:29: server cvars start\n" }
31
+ it { should be }
30
32
  end
31
33
  end
32
34
  end
@@ -75,6 +75,23 @@ module Fonte
75
75
  end
76
76
  end
77
77
  end
78
+
79
+ describe "coordinates" do
80
+ context "only integers" do
81
+ let(:number) { "10 10 20" }
82
+ it { should == [10, 10, 20] }
83
+ end
84
+
85
+ context "only floats" do
86
+ let(:number) { "3617.36 -1739.69 294.53" }
87
+ it { should == [3617.36, -1739.69, 294.53] }
88
+ end
89
+
90
+ context "mixing integers and floats" do
91
+ let(:number) { "3617.36 -1739 294.53" }
92
+ it { should == [3617.36, -1739, 294.53] }
93
+ end
94
+ end
78
95
  end
79
96
  end
80
97
  end
@@ -4,36 +4,16 @@ module Fonte
4
4
  module Parsers
5
5
  describe PlayerParser do
6
6
  let(:parser) { described_class.new }
7
- let(:player) { "Reu<2><STEAM_1:1:24968171><Red>" }
8
-
9
7
  subject { parser.parse(player) }
10
8
 
11
- its(:value) { should == "Reu<2><STEAM_1:1:24968171><Red>" }
12
-
13
- its(:"nickname.value") { should == "Reu" }
14
- its(:"uid.value") { should == 2 }
15
- its(:"steam_id.value") { should == "STEAM_1:1:24968171" }
16
- its(:"team.value") { should == "Red" }
17
-
18
- context "when the player is a bot" do
19
- let(:player) { "Nick<42><Bot><Red>" }
20
- its(:"steam_id.value") { should be_nil }
21
- end
22
-
23
- context "when the player is the console" do
24
- let(:player) { "Console<0><Console><Console>" }
25
- its(:"steam_id.value") { should be_nil }
26
- its(:"team.value") { should be_nil }
27
- end
28
-
29
- context "when the team is not present" do
30
- let(:player) { "Reu<2><STEAM_1:1:24968171><>" }
31
- its(:"team.value") { should be_nil }
9
+ context "when the player is a default source player" do
10
+ let(:player) { "Reu<2><STEAM_1:1:24968171><Red>" }
11
+ it { should be }
32
12
  end
33
13
 
34
- context "when the team is unissiged" do
35
- let(:player) { "Reu<2><STEAM_1:1:24968171><Unassigned>" }
36
- its(:"team.value") { should be_nil }
14
+ context "when the player is a left4dead2 player" do
15
+ let(:player) { "Pulo_ms<8><STEAM_1:1:41920953><Survivor><Producer><ALIVE><100+0><setpos_exact 3617.36 -1739.69 294.53; setang 0.00 179.84 0.00><Area 205>" }
16
+ it { should be }
37
17
  end
38
18
  end
39
19
  end
@@ -24,6 +24,26 @@ module Fonte
24
24
  it { should be }
25
25
  its(:value) { should == { "headshot" => true } }
26
26
  end
27
+
28
+ context "player property" do
29
+ let(:properties) { '(player "Reu<2><STEAM_1:1:24968171><Red>")' }
30
+ it { should be }
31
+
32
+ describe "player" do
33
+ subject { parser.parse(properties).value["player"] }
34
+ it_should_behave_like "a real player"
35
+ end
36
+ end
37
+
38
+ context "number property" do
39
+ let(:properties) { '(area "10")' }
40
+ its(:value) { should == { "area" => 10 } }
41
+ end
42
+
43
+ context "coordinate property" do
44
+ let(:properties) { '(attacker_position "-1624 1258 617")' }
45
+ its(:value) { should == { "attacker_position" => [-1624, 1258, 617] } }
46
+ end
27
47
  end
28
48
  end
29
49
  end
@@ -10,11 +10,13 @@ module Fonte
10
10
  context "with a successfully rcon challenge" do
11
11
  let(:rcon_command) { 'Rcon: "rcon challenge "password" command" from "192.168.10.1:17015"' }
12
12
  it_should_behave_like "a rcon command", :password => "password", :origin => "//192.168.10.1:17015"
13
+ its(:value) { should == "successfully rcon" }
13
14
  end
14
15
 
15
16
  context "with a bad rcon challenge" do
16
17
  let(:rcon_command) { 'Bad Rcon: "rcon challenge "password" command" from "192.168.10.1:17015"' }
17
18
  it_should_behave_like "a rcon command", :password => "password", :origin => "//192.168.10.1:17015"
19
+ its(:value) { should == "bad rcon" }
18
20
  end
19
21
  end
20
22
  end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ module Fonte
4
+ module Parsers
5
+ describe SourcePlayerParser do
6
+ let(:parser) { described_class.new }
7
+ let(:player) { "Reu<2><STEAM_1:1:24968171><Red>" }
8
+
9
+ subject { parser.parse(player) }
10
+
11
+ its(:value) { should == "Reu<2><STEAM_1:1:24968171><Red>" }
12
+
13
+ its(:"nickname.value") { should == "Reu" }
14
+ its(:"uid.value") { should == 2 }
15
+ its(:"steam_id.value") { should == "STEAM_1:1:24968171" }
16
+ its(:"team.value") { should == "Red" }
17
+
18
+ it_should_behave_like "a real player"
19
+
20
+ context "when the player is a bot" do
21
+ let(:player) { "Nick<42><Bot><Red>" }
22
+ its(:"steam_id.value") { should be_nil }
23
+ end
24
+
25
+ context "when the steam id is blank" do
26
+ let(:player) { "Reu<2><><Unassigned>" }
27
+ its(:"steam_id.value") { should be_nil }
28
+ end
29
+
30
+ context "when the player is the console" do
31
+ let(:player) { "Console<0><Console><Console>" }
32
+ its(:"steam_id.value") { should be_nil }
33
+ its(:"team.value") { should be_nil }
34
+ end
35
+
36
+ context "when the team is not present" do
37
+ let(:player) { "Reu<2><STEAM_1:1:24968171><>" }
38
+ its(:"team.value") { should be_nil }
39
+ end
40
+
41
+ context "when the team is unissiged" do
42
+ let(:player) { "Reu<2><STEAM_1:1:24968171><Unassigned>" }
43
+ its(:"team.value") { should be_nil }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -33,14 +33,27 @@ module Fonte
33
33
  end
34
34
 
35
35
  context "of a bot" do
36
- let(:steam_id) { "Bot" }
37
- its(:value) { should_not be }
38
-
39
- it { should_not be_real_player }
40
- it { should_not be_unknown }
41
- it { should be_bot }
42
- it { should_not be_pending }
43
- it { should_not be_console }
36
+ context "labeled as Bot" do
37
+ let(:steam_id) { "Bot" }
38
+ its(:value) { should_not be }
39
+
40
+ it { should_not be_real_player }
41
+ it { should_not be_unknown }
42
+ it { should be_bot }
43
+ it { should_not be_pending }
44
+ it { should_not be_console }
45
+ end
46
+
47
+ context "labeled as BOT" do
48
+ let(:steam_id) { "BOT" }
49
+ its(:value) { should_not be }
50
+
51
+ it { should_not be_real_player }
52
+ it { should_not be_unknown }
53
+ it { should be_bot }
54
+ it { should_not be_pending }
55
+ it { should_not be_console }
56
+ end
44
57
  end
45
58
 
46
59
  context "of a invalid user" do
@@ -0,0 +1,5 @@
1
+ shared_examples "a real player" do
2
+ its(:"nickname.value") { should be }
3
+ its(:"uid.value") { should be }
4
+ its(:"steam_id.value") { should be }
5
+ 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.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-16 00:00:00.000000000Z
12
+ date: 2012-02-04 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2151839440 !ruby/object:Gem::Requirement
16
+ requirement: &2151838740 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.8.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2151839440
24
+ version_requirements: *2151838740
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: treetop
27
- requirement: &2151837980 !ruby/object:Gem::Requirement
27
+ requirement: &2151837600 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 1.4.8
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2151837980
35
+ version_requirements: *2151837600
36
36
  description:
37
37
  email:
38
38
  - rnavarro1@gmail.com
@@ -58,28 +58,33 @@ files:
58
58
  - lib/fonte/parsers.rb
59
59
  - lib/fonte/parsers/action.treetop
60
60
  - lib/fonte/parsers/address.treetop
61
+ - lib/fonte/parsers/l4d2_player.treetop
61
62
  - lib/fonte/parsers/log.treetop
62
63
  - lib/fonte/parsers/number.treetop
63
64
  - lib/fonte/parsers/player.treetop
64
65
  - lib/fonte/parsers/property.treetop
65
66
  - lib/fonte/parsers/rcon.treetop
67
+ - lib/fonte/parsers/source_player.treetop
66
68
  - lib/fonte/parsers/steam_id.treetop
67
69
  - lib/fonte/parsers/temporal.treetop
68
70
  - lib/fonte/parsers/word.treetop
69
71
  - lib/fonte/version.rb
70
72
  - spec/parsers/action_parser_spec.rb
71
73
  - spec/parsers/address_parser_spec.rb
74
+ - spec/parsers/l4d2_player_spec.rb
72
75
  - spec/parsers/log_parser_spec.rb
73
76
  - spec/parsers/number_parser_spec.rb
74
77
  - spec/parsers/player_parser_spec.rb
75
78
  - spec/parsers/property_parser_spec.rb
76
79
  - spec/parsers/rcon_parser_spec.rb
80
+ - spec/parsers/source_player_parser_spec.rb
77
81
  - spec/parsers/steam_id_parser_spec.rb
78
82
  - spec/parsers/temporal_parser_spec.rb
79
83
  - spec/parsers/word_parser_spec.rb
80
84
  - spec/spec_helper.rb
81
85
  - spec/support/shared_examples/properties.rb
82
86
  - spec/support/shared_examples/rcon_command.rb
87
+ - spec/support/shared_examples/real_player.rb
83
88
  homepage: https://github.com/reu/fonte
84
89
  licenses: []
85
90
  post_install_message:
@@ -94,7 +99,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
94
99
  version: '0'
95
100
  segments:
96
101
  - 0
97
- hash: 3614551501371426417
102
+ hash: -228607665135122413
98
103
  required_rubygems_version: !ruby/object:Gem::Requirement
99
104
  none: false
100
105
  requirements:
@@ -103,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
108
  version: '0'
104
109
  segments:
105
110
  - 0
106
- hash: 3614551501371426417
111
+ hash: -228607665135122413
107
112
  requirements: []
108
113
  rubyforge_project: fonte
109
114
  rubygems_version: 1.8.10
@@ -113,14 +118,17 @@ summary: Valve Source Engine log parser
113
118
  test_files:
114
119
  - spec/parsers/action_parser_spec.rb
115
120
  - spec/parsers/address_parser_spec.rb
121
+ - spec/parsers/l4d2_player_spec.rb
116
122
  - spec/parsers/log_parser_spec.rb
117
123
  - spec/parsers/number_parser_spec.rb
118
124
  - spec/parsers/player_parser_spec.rb
119
125
  - spec/parsers/property_parser_spec.rb
120
126
  - spec/parsers/rcon_parser_spec.rb
127
+ - spec/parsers/source_player_parser_spec.rb
121
128
  - spec/parsers/steam_id_parser_spec.rb
122
129
  - spec/parsers/temporal_parser_spec.rb
123
130
  - spec/parsers/word_parser_spec.rb
124
131
  - spec/spec_helper.rb
125
132
  - spec/support/shared_examples/properties.rb
126
133
  - spec/support/shared_examples/rcon_command.rb
134
+ - spec/support/shared_examples/real_player.rb