demo-reader 0.0.2 → 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/lib/demo-reader.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  require "demo_reader_warsow"
2
+ require "demo_reader_defrag"
2
3
 
3
4
 
4
5
  class DemoReader
5
6
 
6
7
 
7
- # tries to parse the given demo file in order to detect a warsow demo
8
+ # tries to parse the given demo file in order to detect first a warsow,
9
+ # then a defrag demo
8
10
  #
9
- # @returns an instance of DemoReaderWarsow or nil on failure
11
+ # @returns an instance of DemoReaderWarsow or DemoReaderDefrag or nil on failure
10
12
  #
11
13
  def self.parse(filename)
12
- try_warsow(filename)
14
+ try_warsow(filename) || try_defrag(filename)
13
15
  end
14
16
 
15
17
 
@@ -21,5 +23,11 @@ class DemoReader
21
23
  demo.valid ? demo : nil
22
24
  end
23
25
 
26
+ def self.try_defrag(filename)
27
+ demo = DemoReaderDefrag.new(filename)
28
+
29
+ demo.valid ? demo : nil
30
+ end
31
+
24
32
  end
25
33
 
@@ -0,0 +1,106 @@
1
+ require 'yaml'
2
+ require 'ext/dm68/dm68'
3
+
4
+ class DemoReaderDefrag
5
+ attr_reader :filename, :version, :mapname, :time, :playernames, :scoreboards, :gamemode, :player, :basegamedir, :gamedir, :valid
6
+
7
+
8
+
9
+ def initialize(filename)
10
+ @filename = filename
11
+
12
+ @version = -1
13
+ @mapname = nil
14
+ @time = nil
15
+ @time_in_msec = nil
16
+ @playernames = []
17
+ @scoreboards = []
18
+ @gamemode = nil
19
+ @player = nil
20
+ @basegamedir = nil
21
+ @gamedir = nil
22
+ @valid = false
23
+ @raw = nil
24
+
25
+ self.init()
26
+ end
27
+
28
+
29
+
30
+ def init
31
+ out = DM68.parse_file(@filename)
32
+ @raw = YAML.load(out)
33
+
34
+ raise out unless @raw
35
+
36
+ @version = @raw['server_info']['protocol'].to_i
37
+ @mapname = @raw['server_info']['mapname'].downcase
38
+
39
+ # @playernames = []
40
+ @scoreboards = @raw['prints']
41
+ @basegamedir = @raw['server_info']['gamename']
42
+ @gamedir = @raw['system_info']['fs_game']
43
+
44
+ if @raw['server_info']['defrag_vers'].to_i > 0
45
+ @gamemode = @raw['server_info']['df_promode'].to_i.zero? ? 'vq3' : 'cpm'
46
+ @time = extract_time(@raw['prints'])
47
+ @player = extract_player(@raw['prints'])
48
+ @playernames << @player # just support one player atm
49
+ end
50
+
51
+ @valid = true
52
+ end
53
+
54
+
55
+
56
+ def time_in_msec
57
+ return @time_in_msec unless @time_in_msec.nil?
58
+
59
+ # time str to int
60
+ if @time.kind_of? String
61
+ min, sec, msec = @time.scan(/^([0-9]+):([0-9]+)\.([0-9]+)$/).flatten.map { |x| x.to_i }
62
+ @time_in_msec = msec + sec * 1000 + min * 60 * 1000
63
+ end
64
+ end
65
+
66
+
67
+
68
+ protected
69
+
70
+ # extract player from server prints
71
+ # supports only one player atm otherwise raises an exception
72
+ #
73
+ def extract_player(prints)
74
+ players = prints.inject([]) do |arr,p|
75
+ arr << $1 if p =~ /^(.+)\^7 reached the finish line/
76
+ arr << $1 if p =~ /^Time performed by (.+)\^7 :/
77
+ arr
78
+ end
79
+
80
+ raise "Not only one player was found #{players.inspect}." if players.length != 1
81
+
82
+ players.first
83
+ end
84
+
85
+ # extract time from server prints
86
+ # supports only one time atm otherwise raises an exception
87
+ #
88
+ def extract_time(prints)
89
+ times = prints.inject([]) do |arr,p|
90
+ arr << $1 if p =~ /(\^[0-9]+:[\^:0-9]+)/
91
+ arr
92
+ end
93
+
94
+ raise "Not only one time was found #{times.inspect}." if times.length != 1
95
+
96
+ time = plain_text(times.first)
97
+
98
+ time = "0:#{time}" if time.count(":") < 2
99
+ "%02d:%02d.%03d" % time.split(":").map(&:to_i)
100
+ end
101
+
102
+ def plain_text(text)
103
+ text.gsub(/\^\d/, '')
104
+ end
105
+ end
106
+
@@ -61,7 +61,7 @@ class DemoReaderWarsow
61
61
 
62
62
 
63
63
  # detect scoreboard
64
- #
64
+
65
65
  regex = /scb \"([^\"]+)/
66
66
  matchdata = regex.match(content)
67
67
 
@@ -73,7 +73,7 @@ class DemoReaderWarsow
73
73
 
74
74
 
75
75
  # detect game mode
76
- #
76
+
77
77
  if @version == 11
78
78
  @gamemode = gamemode_wd11(content)
79
79
  else
@@ -100,7 +100,6 @@ class DemoReaderWarsow
100
100
 
101
101
 
102
102
  # detect time by sent message string with time from server
103
- #
104
103
  if ['race', 'unknown'].include?(@gamemode)
105
104
  matches = []
106
105
  regex = /(server record|race finished)(?:!.*(?:current|times\^7 ))?:[0-9:\. ]* (\d+):(\d+)\.(\d+)/im
@@ -120,7 +119,6 @@ class DemoReaderWarsow
120
119
 
121
120
 
122
121
  #detect all player names
123
- #
124
122
  matches = []
125
123
  regex = /cs ([0-9]+) \"\\name\\([^\0]*)\\hand/
126
124
  rest_content = content
@@ -146,7 +144,7 @@ class DemoReaderWarsow
146
144
 
147
145
 
148
146
  # detect player
149
- #
147
+
150
148
  playernames = @playernames.compact.sort.uniq
151
149
  if playernames.length == 1
152
150
  @player = playernames.first
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class DemoReaderDefragDm68CpmTest < Test::Unit::TestCase
4
+
5
+ version = 68
6
+ gamemode = "cpm"
7
+
8
+ [
9
+ %w(pornchronostar_mdf.cpm_00.49.216_tyaz.germany pornchronostar 00:49.216 *tyaz*),
10
+ %w(puremotion_df.cpm_00.10.600_eS-Rody.russia puremotion 00:10.600 ^2eS-Rody)
11
+ ].each do |entry|
12
+
13
+ file, map, time, player = entry
14
+
15
+ define_method "test_warsow_wd#{version}_demo_#{file.gsub(/[^a-z_0-9]/, "_")}" do
16
+ demo = DemoReader.parse("test/fixtures/defrag/dm_#{version}/#{gamemode}/#{file}.dm_#{version}")
17
+
18
+ assert demo.valid
19
+ assert_equal gamemode, demo.gamemode
20
+ assert_equal version, demo.version
21
+ assert_equal map, demo.mapname
22
+ assert_equal player, demo.player
23
+ assert_equal time, demo.time
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class DemoReaderDefragDm68Vq3Test < Test::Unit::TestCase
4
+
5
+ version = 68
6
+ gamemode = "vq3"
7
+
8
+ [
9
+ %w(runkull2_df.vq3_01.05.904_XunderBIRD.Germany runkull2 01:05.904 ^2XunderBIRD),
10
+ %w(un-dead029_df.vq3_00.16.912_uN-DeaD!WiNTeR.ru un-dead029 00:16.912 ^2uN-DeaD!WiNTeR)
11
+ ].each do |entry|
12
+
13
+ file, map, time, player = entry
14
+
15
+ define_method "test_warsow_wd#{version}_demo_#{file.gsub(/[^a-z_0-9]/, "_")}" do
16
+ demo = DemoReader.parse("test/fixtures/defrag/dm_#{version}/#{gamemode}/#{file}.dm_#{version}")
17
+
18
+ assert demo.valid
19
+ assert_equal gamemode, demo.gamemode
20
+ assert_equal version, demo.version
21
+ assert_equal map, demo.mapname
22
+ assert_equal player, demo.player
23
+ assert_equal time, demo.time
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: demo-reader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - aekym
@@ -9,16 +15,16 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-01-23 00:00:00 +01:00
18
+ date: 2010-08-03 00:00:00 +02:00
13
19
  default_executable:
14
20
  dependencies: []
15
21
 
16
- description: A library to read warsow demo files (.wd8, .wd9, .wd10, .wd11 files)
22
+ description: A library to read warsow demo files (.wd8, .wd9, .wd10, .wd11 files) and q3 demo files (*.dm68)
17
23
  email: me@aekym.com
18
24
  executables: []
19
25
 
20
- extensions: []
21
-
26
+ extensions:
27
+ - ext/dm68/extconf.rb
22
28
  extra_rdoc_files:
23
29
  - LICENSE
24
30
  - README.rdoc
@@ -29,11 +35,31 @@ files:
29
35
  - Rakefile
30
36
  - VERSION
31
37
  - demo-reader.gemspec
38
+ - ext/dm68/README.txt
39
+ - ext/dm68/common.c
40
+ - ext/dm68/common.h
41
+ - ext/dm68/dm68.c
42
+ - ext/dm68/dump.c
43
+ - ext/dm68/extconf.rb
44
+ - ext/dm68/huff.c
45
+ - ext/dm68/huff.h
46
+ - ext/dm68/main.c
47
+ - ext/dm68/main.h
48
+ - ext/dm68/msg.c
49
+ - ext/dm68/msg.h
50
+ - ext/dm68/parse.c
32
51
  - lib/demo-reader.rb
52
+ - lib/demo_reader_defrag.rb
33
53
  - lib/demo_reader_warsow.rb
54
+ - test/demo_reader_defrag_dm_68_cpm_test.rb
55
+ - test/demo_reader_defrag_dm_68_vq3_test.rb
34
56
  - test/demo_reader_test.rb
35
57
  - test/demo_reader_warsow_wd10_race_test.rb
36
58
  - test/demo_reader_warsow_wd11_race_test.rb
59
+ - test/fixtures/defrag/dm_68/cpm/pornchronostar_mdf.cpm_00.49.216_tyaz.germany.dm_68
60
+ - test/fixtures/defrag/dm_68/cpm/puremotion_df.cpm_00.10.600_eS-Rody.russia.dm_68
61
+ - test/fixtures/defrag/dm_68/vq3/runkull2_df.vq3_01.05.904_XunderBIRD.Germany.dm_68
62
+ - test/fixtures/defrag/dm_68/vq3/un-dead029_df.vq3_00.16.912_uN-DeaD!WiNTeR.ru.dm_68
37
63
  - test/fixtures/warsow/wd10/racesow_0.42.b2/dinirun2_racesow_0.42.b2.wd10
38
64
  - test/fixtures/warsow/wd10/racesow_local/boris.wd10
39
65
  - test/fixtures/warsow/wd10/racesow_local/die11.7.wd10
@@ -65,25 +91,33 @@ rdoc_options:
65
91
  require_paths:
66
92
  - lib
67
93
  required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
68
95
  requirements:
69
96
  - - ">="
70
97
  - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
71
101
  version: "0"
72
- version:
73
102
  required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
74
104
  requirements:
75
105
  - - ">="
76
106
  - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
77
110
  version: "0"
78
- version:
79
111
  requirements: []
80
112
 
81
113
  rubyforge_project:
82
- rubygems_version: 1.3.5
114
+ rubygems_version: 1.3.7
83
115
  signing_key:
84
116
  specification_version: 3
85
- summary: A library to read warsow demo files
117
+ summary: A library to read warsow and q3 demo files
86
118
  test_files:
119
+ - test/demo_reader_defrag_dm_68_cpm_test.rb
120
+ - test/demo_reader_defrag_dm_68_vq3_test.rb
87
121
  - test/demo_reader_test.rb
88
122
  - test/demo_reader_warsow_wd10_race_test.rb
89
123
  - test/demo_reader_warsow_wd11_race_test.rb