anthonyw-dyno 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +19 -0
- data/README.markdown +14 -0
- data/Rakefile +44 -0
- data/VERSION.yml +4 -0
- data/lib/dyno.rb +18 -0
- data/lib/dyno/competitor.rb +19 -0
- data/lib/dyno/event.rb +16 -0
- data/lib/dyno/parsers/race07_parser.rb +133 -0
- data/spec/competitor_spec.rb +74 -0
- data/spec/event_spec.rb +59 -0
- data/spec/fixtures/race07/full.ini +131 -0
- data/spec/fixtures/race07/header_no_track.ini +11 -0
- data/spec/fixtures/race07/header_only.ini +12 -0
- data/spec/fixtures/race07/no_header_section.ini +6 -0
- data/spec/fixtures/race07/no_steam_id.ini +37 -0
- data/spec/fixtures/race07/readme.markdown +5 -0
- data/spec/fixtures/race07/single_driver.ini +37 -0
- data/spec/parsers/race07_parser_spec.rb +143 -0
- data/spec/spec_helper.rb +3 -0
- metadata +85 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 Anthony Williams
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
dyno
|
2
|
+
====
|
3
|
+
|
4
|
+
A Ruby library for parsing sim-racing results files. Presently supports:
|
5
|
+
|
6
|
+
* Race 07 / GTR: Evolution
|
7
|
+
|
8
|
+
With support for the following in the near future:
|
9
|
+
|
10
|
+
* rFactor
|
11
|
+
* LFS
|
12
|
+
* Arca
|
13
|
+
|
14
|
+
... once I've got my hands on some sample results files.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |s|
|
7
|
+
s.name = 'dyno'
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.summary = 'A rubygem for parsing sim-racing results files.'
|
11
|
+
s.description = s.summary
|
12
|
+
s.author = 'Anthony Williams'
|
13
|
+
s.email = 'anthony@ninecraft.com'
|
14
|
+
s.homepage = 'http://github.com/anthonyw/dyno'
|
15
|
+
|
16
|
+
s.extra_rdoc_files = ['README.markdown', 'MIT-LICENSE']
|
17
|
+
|
18
|
+
# Dependencies.
|
19
|
+
s.add_dependency "iniparse", ">= 0.2.0"
|
20
|
+
|
21
|
+
s.files = %w(MIT-LICENSE README.markdown Rakefile VERSION.yml) +
|
22
|
+
Dir.glob("{lib,spec}/**/*")
|
23
|
+
end
|
24
|
+
rescue LoadError
|
25
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
26
|
+
end
|
27
|
+
|
28
|
+
################################################################################
|
29
|
+
# rSpec & rcov
|
30
|
+
################################################################################
|
31
|
+
|
32
|
+
desc "Run all examples"
|
33
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
34
|
+
t.spec_files = FileList['spec/**/*.rb']
|
35
|
+
t.spec_opts = ['-c -f s']
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Run all examples with RCov"
|
39
|
+
Spec::Rake::SpecTask.new('spec:rcov') do |t|
|
40
|
+
t.spec_files = FileList['spec/**/*.rb']
|
41
|
+
t.spec_opts = ['-c -f s']
|
42
|
+
t.rcov = true
|
43
|
+
t.rcov_opts = ['--exclude', 'spec']
|
44
|
+
end
|
data/VERSION.yml
ADDED
data/lib/dyno.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module Dyno
|
5
|
+
# Base exception class.
|
6
|
+
class DynoError < StandardError; end
|
7
|
+
|
8
|
+
# Raised if an input source couldn't be parsed, or was missing something.
|
9
|
+
class MalformedInputError < DynoError; end
|
10
|
+
end
|
11
|
+
|
12
|
+
%w( competitor event ).each do |file|
|
13
|
+
require File.join( File.dirname(__FILE__), "dyno", file )
|
14
|
+
end
|
15
|
+
|
16
|
+
Dir["#{ File.dirname(__FILE__) }/dyno/parsers/*_parser.rb"].sort.each do |parser|
|
17
|
+
require parser
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Dyno
|
2
|
+
class Competitor
|
3
|
+
attr_accessor :name, :uid, :position, :vehicle, :laps, :race_time,
|
4
|
+
:best_lap, :lap_times
|
5
|
+
|
6
|
+
##
|
7
|
+
# @param [String] name The competitor's name.
|
8
|
+
# @param [Hash] properties Extra information about the competitor.
|
9
|
+
#
|
10
|
+
def initialize(name, properties = {})
|
11
|
+
@name = name
|
12
|
+
@lap_times = properties.fetch(:laps, [])
|
13
|
+
|
14
|
+
[:uid, :position, :vehicle, :laps, :race_time, :best_lap].each do |prop|
|
15
|
+
instance_variable_set "@#{prop}", properties[prop]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/dyno/event.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Dyno
|
2
|
+
class Event
|
3
|
+
attr_accessor :time, :game, :game_version, :track, :competitors
|
4
|
+
|
5
|
+
##
|
6
|
+
# @param [Hash] properties Event information.
|
7
|
+
#
|
8
|
+
def initialize(properties = {})
|
9
|
+
@time = properties.fetch( :time, Time.now )
|
10
|
+
@track = properties[:track]
|
11
|
+
@game = properties[:game]
|
12
|
+
@game_version = properties[:game_version]
|
13
|
+
@competitors = properties.fetch( :competitors, [] )
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'iniparse'
|
2
|
+
|
3
|
+
module Dyno::Parsers
|
4
|
+
##
|
5
|
+
# Parses a Race 07 results file (which appears to be some variation of the
|
6
|
+
# ini format).
|
7
|
+
#
|
8
|
+
# TODO: Remove dependency on inifile and write our own ini parser so that:
|
9
|
+
# * we can extract individual lap information.
|
10
|
+
# * we don't have to have a results file on disk.
|
11
|
+
#
|
12
|
+
class Race07Parser
|
13
|
+
##
|
14
|
+
# Takes a file path and parses it.
|
15
|
+
#
|
16
|
+
# @param [String] filename The path to the results file.
|
17
|
+
#
|
18
|
+
def self.parse_file( filename )
|
19
|
+
parse( IniParse.open( filename ) )
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Takes an IniFile instance, parses the contents, and returns a
|
24
|
+
# Dyno::Event containing your results.
|
25
|
+
#
|
26
|
+
# @param [IniFile] results The results.
|
27
|
+
# @return [Dyno::Event]
|
28
|
+
#
|
29
|
+
def self.parse( results )
|
30
|
+
new( results ).parse
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns your parsed event and competitor information.
|
35
|
+
#
|
36
|
+
def parse
|
37
|
+
parse_event!
|
38
|
+
parse_competitors!
|
39
|
+
@event
|
40
|
+
end
|
41
|
+
|
42
|
+
#######
|
43
|
+
private
|
44
|
+
#######
|
45
|
+
|
46
|
+
##
|
47
|
+
# Takes an IniFile instance and parses the contents.
|
48
|
+
#
|
49
|
+
# @param [IniFile] results The results.
|
50
|
+
#
|
51
|
+
def initialize( results )
|
52
|
+
@raw = results
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Extracts the event information from the results.
|
57
|
+
#
|
58
|
+
def parse_event!
|
59
|
+
raise Dyno::MalformedInputError unless @raw.has_section?('Header')
|
60
|
+
|
61
|
+
@event = Dyno::Event.new( :game => 'Race 07' )
|
62
|
+
@event.time = Time.parse( @raw['Header']['TimeString'] )
|
63
|
+
@event.game_version = @raw['Header']['Version']
|
64
|
+
|
65
|
+
# Extract the track name from Race/Scene
|
66
|
+
if @raw.has_section?('Race') && @raw['Race']['Scene']
|
67
|
+
@event.track = @raw['Race']['Scene'].split( '\\' )[-2].gsub( /[_-]+/, ' ' )
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Extracts information about each of the competitors.
|
73
|
+
#
|
74
|
+
def parse_competitors!
|
75
|
+
finished_competitors = []
|
76
|
+
dnf_competitors = []
|
77
|
+
|
78
|
+
@raw.each do |section|
|
79
|
+
# Competitor sections are named SlotNNN.
|
80
|
+
next unless section.key =~ /Slot\d\d\d/
|
81
|
+
|
82
|
+
competitor = Dyno::Competitor.new(section['Driver'],
|
83
|
+
:vehicle => section['Vehicle'],
|
84
|
+
:laps => section['Laps'].to_i
|
85
|
+
)
|
86
|
+
|
87
|
+
# Some results files have a blank ID.
|
88
|
+
if section['SteamId'] && section['SteamId'].kind_of?(Numeric)
|
89
|
+
competitor.uid = section['SteamId']
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sort out the competitors lap times.
|
93
|
+
competitor.best_lap = lap_time_to_float(section['BestLap'])
|
94
|
+
|
95
|
+
competitor.lap_times = section['Lap'].map do |lap|
|
96
|
+
lap = lap.gsub(/\((.*)\)/, '\1')
|
97
|
+
lap_time_to_float(lap.split(',').last.strip)
|
98
|
+
end
|
99
|
+
|
100
|
+
if section['RaceTime'] == 'DNF'
|
101
|
+
competitor.race_time = 'DNF'
|
102
|
+
dnf_competitors << competitor
|
103
|
+
else
|
104
|
+
time = section['RaceTime'].split( /:|\./ )
|
105
|
+
|
106
|
+
competitor.race_time = time[2].to_f + ( time[1].to_i * 60 ) +
|
107
|
+
( time[0].to_i * 60 * 60 ) + "0.#{time[3]}".to_f
|
108
|
+
|
109
|
+
finished_competitors << competitor
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Sort finished competitors by their race time, lowest (P1) first.
|
114
|
+
finished_competitors = finished_competitors.sort_by { |c| c.race_time }
|
115
|
+
|
116
|
+
# ... and DNF'ed competitors by how many laps they've done.
|
117
|
+
dnf_competitors = dnf_competitors.sort_by { |c| c.laps }.reverse!
|
118
|
+
|
119
|
+
# Finally let's assign their finishing positions.
|
120
|
+
competitors = finished_competitors + dnf_competitors
|
121
|
+
competitors.each_with_index { |c, i| c.position = i + 1 }
|
122
|
+
|
123
|
+
# All done!
|
124
|
+
@event.competitors = competitors
|
125
|
+
end
|
126
|
+
|
127
|
+
# Converts a lap time (in the format of M:SS:SSS) to a float.
|
128
|
+
def lap_time_to_float(time)
|
129
|
+
time = time.split( /:|\./ )
|
130
|
+
time[1].to_f + ( time[0].to_i * 60 ) + "0.#{time[2]}".to_f
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Dyno::Competitor do
|
4
|
+
before(:all) do
|
5
|
+
@competitor = Dyno::Competitor.new("Jake Lucas")
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should have a +name+ accessor' do
|
9
|
+
@competitor.should respond_to(:name)
|
10
|
+
@competitor.should respond_to(:name=)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have a +uid+ accessor' do
|
14
|
+
@competitor.should respond_to(:uid)
|
15
|
+
@competitor.should respond_to(:uid=)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should have a +position+ accessor' do
|
19
|
+
@competitor.should respond_to(:position)
|
20
|
+
@competitor.should respond_to(:position=)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should have a +vehicle+ accessor' do
|
24
|
+
@competitor.should respond_to(:vehicle)
|
25
|
+
@competitor.should respond_to(:vehicle=)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should have a +laps+ accessor' do
|
29
|
+
@competitor.should respond_to(:laps)
|
30
|
+
@competitor.should respond_to(:laps=)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should have a +race_time+ accessor' do
|
34
|
+
@competitor.should respond_to(:race_time)
|
35
|
+
@competitor.should respond_to(:race_time=)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should have a +best_lap+ accessor' do
|
39
|
+
@competitor.should respond_to(:best_lap)
|
40
|
+
@competitor.should respond_to(:best_lap=)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should respond_to #dnf?' do
|
44
|
+
pending do
|
45
|
+
@competitor.should respond_to(:dnf)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# ----------
|
50
|
+
# initialize
|
51
|
+
|
52
|
+
it 'should use the given values when creating a Event' do
|
53
|
+
properties = {
|
54
|
+
:uid => 1337,
|
55
|
+
:position => 3,
|
56
|
+
:vehicle => "BMW 320si E90 2007",
|
57
|
+
:laps => 13,
|
58
|
+
:race_time => "0:21:31.183",
|
59
|
+
:best_lap => "1:37.960"
|
60
|
+
}
|
61
|
+
|
62
|
+
competitor = Dyno::Competitor.new("Jake Lucas", properties)
|
63
|
+
competitor.name.should == "Jake Lucas"
|
64
|
+
|
65
|
+
properties.each do |prop, value|
|
66
|
+
competitor.send(prop).should == value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should require that a name be supplied' do
|
71
|
+
lambda { Dyno::Competitor.new }.should raise_error(ArgumentError)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
data/spec/event_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Dyno::Event do
|
4
|
+
before(:all) do
|
5
|
+
@event = Dyno::Event.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should have a +time+ accessor' do
|
9
|
+
@event.should respond_to(:time)
|
10
|
+
@event.should respond_to(:time=)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have a +track+ accessor' do
|
14
|
+
@event.should respond_to(:track)
|
15
|
+
@event.should respond_to(:track=)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should have a +game+ accessor' do
|
19
|
+
@event.should respond_to(:game)
|
20
|
+
@event.should respond_to(:game=)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should have a +game_version+ accessor' do
|
24
|
+
@event.should respond_to(:game_version)
|
25
|
+
@event.should respond_to(:game_version=)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should have a +competitors+ accessor' do
|
29
|
+
@event.should respond_to(:competitors)
|
30
|
+
@event.should respond_to(:competitors=)
|
31
|
+
end
|
32
|
+
|
33
|
+
# -----------
|
34
|
+
# #initialize
|
35
|
+
|
36
|
+
it 'should use the given values when creating a Event' do
|
37
|
+
event = Dyno::Event.new(
|
38
|
+
:time => Time.now - 10,
|
39
|
+
:track => "Anderstorp 2007",
|
40
|
+
:game => "Event 07",
|
41
|
+
:game_version => "1.1.1.14",
|
42
|
+
:competitors => [1]
|
43
|
+
)
|
44
|
+
|
45
|
+
event.time.should be_close(Time.now - 10, 0.5)
|
46
|
+
event.track.should == "Anderstorp 2007"
|
47
|
+
event.game.should == "Event 07"
|
48
|
+
event.game_version.should == "1.1.1.14"
|
49
|
+
event.competitors.should == [1]
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should set a default time if none is given' do
|
53
|
+
Dyno::Event.new.time.should be_close(Time.now, 1)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should default competitors to [] if none are given' do
|
57
|
+
Dyno::Event.new.competitors.should == []
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
[Header]
|
2
|
+
Game=RACE 07
|
3
|
+
Version=1.1.1.14
|
4
|
+
TimeString=2008/09/13 23:26:32
|
5
|
+
Aids=0,0,0,0,0,1,1,0,0
|
6
|
+
|
7
|
+
[Race]
|
8
|
+
RaceMode=5
|
9
|
+
Scene=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.TRK
|
10
|
+
AIDB=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW
|
11
|
+
Race Length=0.100
|
12
|
+
Track Length=4018.8376
|
13
|
+
|
14
|
+
[Slot010]
|
15
|
+
Driver=Mark Voss
|
16
|
+
SteamUser=mvoss
|
17
|
+
SteamId=1865369
|
18
|
+
Vehicle=Chevrolet Lacetti 2007
|
19
|
+
Team=TEMPLATE_TEAM
|
20
|
+
QualTime=1:37.839
|
21
|
+
Laps=13
|
22
|
+
Lap=(0, -1.000, 1:48.697)
|
23
|
+
Lap=(1, 89.397, 1:39.455)
|
24
|
+
Lap=(2, 198.095, 1:38.060)
|
25
|
+
Lap=(3, 297.550, 1:38.632)
|
26
|
+
Lap=(4, 395.610, 1:38.031)
|
27
|
+
Lap=(5, 494.242, 1:39.562)
|
28
|
+
Lap=(6, 592.273, 1:39.950)
|
29
|
+
Lap=(7, 691.835, 1:38.366)
|
30
|
+
Lap=(8, 791.785, 1:39.889)
|
31
|
+
Lap=(9, 890.151, 1:39.420)
|
32
|
+
Lap=(10, 990.040, 1:39.401)
|
33
|
+
Lap=(11, 1089.460, 1:39.506)
|
34
|
+
Lap=(12, 1188.862, 1:40.017)
|
35
|
+
LapDistanceTravelled=3857.750244
|
36
|
+
BestLap=1:38.031
|
37
|
+
RaceTime=0:21:38.988
|
38
|
+
|
39
|
+
[Slot016]
|
40
|
+
Driver=Corey Ball
|
41
|
+
SteamUser=cball
|
42
|
+
SteamId=889853
|
43
|
+
Vehicle=SEAT Leon 2007
|
44
|
+
Team=TEMPLATE_TEAM
|
45
|
+
QualTime=1:37.904
|
46
|
+
Laps=9
|
47
|
+
Lap=(0, -1.000, 1:51.434)
|
48
|
+
Lap=(1, 89.397, 1:39.427)
|
49
|
+
Lap=(2, 200.831, 1:38.394)
|
50
|
+
Lap=(3, 300.258, 1:40.239)
|
51
|
+
Lap=(4, 398.653, 1:38.172)
|
52
|
+
Lap=(5, 498.891, 1:38.427)
|
53
|
+
Lap=(6, 597.063, 1:39.271)
|
54
|
+
Lap=(7, 695.490, 1:39.922)
|
55
|
+
Lap=(8, 794.761, 1:40.305)
|
56
|
+
LapDistanceTravelled=532.898193
|
57
|
+
BestLap=1:38.172
|
58
|
+
RaceTime=DNF
|
59
|
+
Reason=0
|
60
|
+
|
61
|
+
[Slot013]
|
62
|
+
Driver=Gabriel Lloyd
|
63
|
+
SteamUser=glloyd
|
64
|
+
SteamId=635
|
65
|
+
Vehicle=Chevrolet Lacetti 2007
|
66
|
+
Team=TEMPLATE_TEAM
|
67
|
+
QualTime=1:36.607
|
68
|
+
Laps=13
|
69
|
+
Lap=(0, -1.000, 1:50.816)
|
70
|
+
Lap=(1, 89.397, 1:38.835)
|
71
|
+
Lap=(2, 200.213, 1:38.082)
|
72
|
+
Lap=(3, 299.048, 1:38.367)
|
73
|
+
Lap=(4, 397.131, 1:37.825)
|
74
|
+
Lap=(5, 495.497, 1:38.757)
|
75
|
+
Lap=(6, 593.322, 1:38.718)
|
76
|
+
Lap=(7, 692.080, 1:38.478)
|
77
|
+
Lap=(8, 790.797, 1:39.347)
|
78
|
+
Lap=(9, 889.275, 1:38.713)
|
79
|
+
Lap=(10, 988.622, 1:38.952)
|
80
|
+
Lap=(11, 1087.336, 1:39.285)
|
81
|
+
Lap=(12, 1186.288, 1:40.555)
|
82
|
+
LapDistanceTravelled=3898.517578
|
83
|
+
BestLap=1:37.825
|
84
|
+
RaceTime=0:21:36.730
|
85
|
+
|
86
|
+
[Slot018]
|
87
|
+
Driver=Reino Lintula
|
88
|
+
SteamUser=rlintula
|
89
|
+
SteamId=1816
|
90
|
+
Vehicle=SEAT Leon 2007
|
91
|
+
Team=TEMPLATE_TEAM
|
92
|
+
QualTime=1:39.602
|
93
|
+
Laps=7
|
94
|
+
Lap=(0, -1.000, 1:52.788)
|
95
|
+
Lap=(1, 112.593, 1:39.346)
|
96
|
+
Lap=(2, 225.381, 1:40.680)
|
97
|
+
Lap=(3, 324.727, 1:38.775)
|
98
|
+
Lap=(4, 425.407, 1:40.149)
|
99
|
+
Lap=(5, 524.182, 1:41.551)
|
100
|
+
Lap=(6, 624.331, 1:46.908)
|
101
|
+
LapDistanceTravelled=1333.551270
|
102
|
+
BestLap=1:38.775
|
103
|
+
RaceTime=DNF
|
104
|
+
Reason=0
|
105
|
+
|
106
|
+
[Slot002]
|
107
|
+
Driver=Jerry Lalich
|
108
|
+
SteamUser=jlalich
|
109
|
+
SteamId=236892
|
110
|
+
Vehicle=Chevrolet Lacetti 2007
|
111
|
+
Team=TEMPLATE_TEAM
|
112
|
+
QualTime=1:38.081
|
113
|
+
Laps=13
|
114
|
+
Lap=(0, -1.000, 1:48.530)
|
115
|
+
Lap=(1, 89.397, 1:39.213)
|
116
|
+
Lap=(2, 197.927, 1:37.933)
|
117
|
+
Lap=(3, 297.140, 1:37.717)
|
118
|
+
Lap=(4, 395.073, 1:38.500)
|
119
|
+
Lap=(5, 492.790, 1:38.641)
|
120
|
+
Lap=(6, 591.290, 1:39.810)
|
121
|
+
Lap=(7, 689.931, 1:39.177)
|
122
|
+
Lap=(8, 789.742, 1:40.122)
|
123
|
+
Lap=(9, 888.918, 1:38.928)
|
124
|
+
Lap=(10, 989.040, 1:39.238)
|
125
|
+
Lap=(11, 1087.968, 1:39.223)
|
126
|
+
Lap=(12, 1187.206, 1:39.888)
|
127
|
+
LapDistanceTravelled=3892.720215
|
128
|
+
BestLap=1:37.717
|
129
|
+
RaceTime=0:21:36.920
|
130
|
+
|
131
|
+
[END]
|
@@ -0,0 +1,12 @@
|
|
1
|
+
[Header]
|
2
|
+
Game=RACE 07
|
3
|
+
Version=1.1.1.14
|
4
|
+
TimeString=2008/09/13 23:00:50
|
5
|
+
Aids=0,0,0,0,0,1,1,0,0
|
6
|
+
|
7
|
+
[Race]
|
8
|
+
RaceMode=5
|
9
|
+
Scene=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.TRK
|
10
|
+
AIDB=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW
|
11
|
+
Race Length=0.100
|
12
|
+
Track Length=4018.8376
|
@@ -0,0 +1,37 @@
|
|
1
|
+
[Header]
|
2
|
+
Game=RACE 07
|
3
|
+
Version=1.1.1.14
|
4
|
+
TimeString=2008/09/13 23:26:32
|
5
|
+
Aids=0,0,0,0,0,1,1,0,0
|
6
|
+
|
7
|
+
[Race]
|
8
|
+
RaceMode=5
|
9
|
+
Scene=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.TRK
|
10
|
+
AIDB=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW
|
11
|
+
Race Length=0.100
|
12
|
+
Track Length=4018.8376
|
13
|
+
|
14
|
+
[Slot013]
|
15
|
+
Driver=Gabriel Lloyd
|
16
|
+
SteamUser=
|
17
|
+
SteamId=
|
18
|
+
Vehicle=Chevrolet Lacetti 2007
|
19
|
+
Team=TEMPLATE_TEAM
|
20
|
+
QualTime=1:36.607
|
21
|
+
Laps=13
|
22
|
+
Lap=(0, -1.000, 1:50.816)
|
23
|
+
Lap=(1, 89.397, 1:38.835)
|
24
|
+
Lap=(2, 200.213, 1:38.082)
|
25
|
+
Lap=(3, 299.048, 1:38.367)
|
26
|
+
Lap=(4, 397.131, 1:37.825)
|
27
|
+
Lap=(5, 495.497, 1:38.757)
|
28
|
+
Lap=(6, 593.322, 1:38.718)
|
29
|
+
Lap=(7, 692.080, 1:38.478)
|
30
|
+
Lap=(8, 790.797, 1:39.347)
|
31
|
+
Lap=(9, 889.275, 1:38.713)
|
32
|
+
Lap=(10, 988.622, 1:38.952)
|
33
|
+
Lap=(11, 1087.336, 1:39.285)
|
34
|
+
Lap=(12, 1186.288, 1:40.555)
|
35
|
+
LapDistanceTravelled=3898.517578
|
36
|
+
BestLap=1:37.825
|
37
|
+
RaceTime=0:21:36.730
|
@@ -0,0 +1,37 @@
|
|
1
|
+
[Header]
|
2
|
+
Game=RACE 07
|
3
|
+
Version=1.1.1.14
|
4
|
+
TimeString=2008/09/13 23:26:32
|
5
|
+
Aids=0,0,0,0,0,1,1,0,0
|
6
|
+
|
7
|
+
[Race]
|
8
|
+
RaceMode=5
|
9
|
+
Scene=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.TRK
|
10
|
+
AIDB=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW
|
11
|
+
Race Length=0.100
|
12
|
+
Track Length=4018.8376
|
13
|
+
|
14
|
+
[Slot013]
|
15
|
+
Driver=Gabriel Lloyd
|
16
|
+
SteamUser=glloyd
|
17
|
+
SteamId=635
|
18
|
+
Vehicle=Chevrolet Lacetti 2007
|
19
|
+
Team=TEMPLATE_TEAM
|
20
|
+
QualTime=1:36.607
|
21
|
+
Laps=13
|
22
|
+
Lap=(0, -1.000, 1:50.816)
|
23
|
+
Lap=(1, 89.397, 1:38.835)
|
24
|
+
Lap=(2, 200.213, 1:38.082)
|
25
|
+
Lap=(3, 299.048, 1:38.367)
|
26
|
+
Lap=(4, 397.131, 1:37.825)
|
27
|
+
Lap=(5, 495.497, 1:38.757)
|
28
|
+
Lap=(6, 593.322, 1:38.718)
|
29
|
+
Lap=(7, 692.080, 1:38.478)
|
30
|
+
Lap=(8, 790.797, 1:39.347)
|
31
|
+
Lap=(9, 889.275, 1:38.713)
|
32
|
+
Lap=(10, 988.622, 1:38.952)
|
33
|
+
Lap=(11, 1087.336, 1:39.285)
|
34
|
+
Lap=(12, 1186.288, 1:40.555)
|
35
|
+
LapDistanceTravelled=3898.517578
|
36
|
+
BestLap=1:37.825
|
37
|
+
RaceTime=0:21:36.730
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', 'spec_helper' )
|
2
|
+
|
3
|
+
describe Dyno::Parsers::Race07Parser do
|
4
|
+
|
5
|
+
it 'should respond to .parse' do
|
6
|
+
Dyno::Parsers::Race07Parser.should respond_to(:parse)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should respond to .parse_file' do
|
10
|
+
Dyno::Parsers::Race07Parser.should respond_to(:parse_file)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should respond to #parse' do
|
14
|
+
Dyno::Parsers::Race07Parser.public_instance_methods.should include('parse')
|
15
|
+
end
|
16
|
+
|
17
|
+
# --------------
|
18
|
+
# Event parsing.
|
19
|
+
|
20
|
+
describe 'parse_event!' do
|
21
|
+
before(:all) do
|
22
|
+
@event = Dyno::Parsers::Race07Parser.parse_file(
|
23
|
+
'spec/fixtures/race07/header_only.ini'
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should set the game' do
|
28
|
+
@event.game.should == 'Race 07'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should correctly set the game version' do
|
32
|
+
# 1.1.1.14
|
33
|
+
@event.game_version.should == '1.1.1.14'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should correctly set the event time' do
|
37
|
+
# 2008/09/13 23:00:50
|
38
|
+
@event.time.should == Time.local(2008, 9, 13, 23, 00, 50)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should correctly set the track' do
|
42
|
+
@event.track.should == 'Anderstorp 2007'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should not set the track if one could not be discerned' do
|
46
|
+
event = Dyno::Parsers::Race07Parser.parse_file(
|
47
|
+
'spec/fixtures/race07/header_no_track.ini'
|
48
|
+
)
|
49
|
+
|
50
|
+
event.track.should be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should whine loudly if there is no "Header" section' do
|
54
|
+
lambda {
|
55
|
+
Dyno::Parsers::Race07Parser.parse_file(
|
56
|
+
'spec/fixtures/race07/no_header_section.ini'
|
57
|
+
)
|
58
|
+
}.should raise_error(Dyno::MalformedInputError)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# -------------------
|
63
|
+
# Competitor parsing.
|
64
|
+
|
65
|
+
describe 'parse_competitors!' do
|
66
|
+
before(:all) do
|
67
|
+
@event = Dyno::Parsers::Race07Parser.parse_file(
|
68
|
+
'spec/fixtures/race07/single_driver.ini'
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should set the driver name correctly' do
|
73
|
+
@event.competitors.first.name.should == 'Gabriel Lloyd'
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should set the vehicle correctly' do
|
77
|
+
@event.competitors.first.vehicle.should == 'Chevrolet Lacetti 2007'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should set the steam id (uid) correctly' do
|
81
|
+
@event.competitors.first.uid.should == 635
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should not set the steam id if one is not present' do
|
85
|
+
event = Dyno::Parsers::Race07Parser.parse_file(
|
86
|
+
'spec/fixtures/race07/no_steam_id.ini'
|
87
|
+
)
|
88
|
+
|
89
|
+
event.competitors.first.uid.should be_nil
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should set the lap count correctly' do
|
93
|
+
@event.competitors.first.laps.should == 13
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should convert the race time to a float' do
|
97
|
+
@event.competitors.first.race_time.should == 1296.73
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should convert the best lap time to a float' do
|
101
|
+
@event.competitors.first.best_lap.should == 97.825
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should correctly set the competitors lap times" do
|
105
|
+
@event.competitors.first.lap_times.should == [
|
106
|
+
110.816, # Lap=(0, -1.000, 1:50.816)
|
107
|
+
98.835, # Lap=(1, 89.397, 1:38.835)
|
108
|
+
98.082, # Lap=(2, 200.213, 1:38.082)
|
109
|
+
98.367, # Lap=(3, 299.048, 1:38.367)
|
110
|
+
97.825, # Lap=(4, 397.131, 1:37.825)
|
111
|
+
98.757, # Lap=(5, 495.497, 1:38.757)
|
112
|
+
98.718, # Lap=(6, 593.322, 1:38.718)
|
113
|
+
98.478, # Lap=(7, 692.080, 1:38.478)
|
114
|
+
99.347, # Lap=(8, 790.797, 1:39.347)
|
115
|
+
98.713, # Lap=(9, 889.275, 1:38.713)
|
116
|
+
98.952, # Lap=(10, 988.622, 1:38.952)
|
117
|
+
99.285, # Lap=(11, 1087.336, 1:39.285)
|
118
|
+
100.555 # Lap=(12, 1186.288, 1:40.555)
|
119
|
+
]
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should correctly sort drivers by their finishing time, and assign their position' do
|
123
|
+
event = Dyno::Parsers::Race07Parser.parse_file(
|
124
|
+
'spec/fixtures/race07/full.ini'
|
125
|
+
)
|
126
|
+
|
127
|
+
event.competitors[0].name.should == 'Gabriel Lloyd'
|
128
|
+
event.competitors[0].position.should == 1
|
129
|
+
|
130
|
+
event.competitors[1].name.should == 'Jerry Lalich'
|
131
|
+
event.competitors[1].position.should == 2
|
132
|
+
|
133
|
+
event.competitors[2].name.should == 'Mark Voss'
|
134
|
+
event.competitors[2].position.should == 3
|
135
|
+
|
136
|
+
event.competitors[3].name.should == 'Corey Ball'
|
137
|
+
event.competitors[3].position.should == 4
|
138
|
+
|
139
|
+
event.competitors[4].name.should == 'Reino Lintula'
|
140
|
+
event.competitors[4].position.should == 5
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: anthonyw-dyno
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anthony Williams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-15 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: iniparse
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.2.0
|
23
|
+
version:
|
24
|
+
description: A rubygem for parsing sim-racing results files.
|
25
|
+
email: anthony@ninecraft.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- README.markdown
|
32
|
+
- MIT-LICENSE
|
33
|
+
files:
|
34
|
+
- MIT-LICENSE
|
35
|
+
- README.markdown
|
36
|
+
- Rakefile
|
37
|
+
- VERSION.yml
|
38
|
+
- lib/dyno
|
39
|
+
- lib/dyno/competitor.rb
|
40
|
+
- lib/dyno/event.rb
|
41
|
+
- lib/dyno/parsers
|
42
|
+
- lib/dyno/parsers/race07_parser.rb
|
43
|
+
- lib/dyno.rb
|
44
|
+
- spec/competitor_spec.rb
|
45
|
+
- spec/event_spec.rb
|
46
|
+
- spec/fixtures
|
47
|
+
- spec/fixtures/race07
|
48
|
+
- spec/fixtures/race07/full.ini
|
49
|
+
- spec/fixtures/race07/header_no_track.ini
|
50
|
+
- spec/fixtures/race07/header_only.ini
|
51
|
+
- spec/fixtures/race07/no_header_section.ini
|
52
|
+
- spec/fixtures/race07/no_steam_id.ini
|
53
|
+
- spec/fixtures/race07/readme.markdown
|
54
|
+
- spec/fixtures/race07/single_driver.ini
|
55
|
+
- spec/parsers
|
56
|
+
- spec/parsers/race07_parser_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/anthonyw/dyno
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: "0"
|
76
|
+
version:
|
77
|
+
requirements: []
|
78
|
+
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.2.0
|
81
|
+
signing_key:
|
82
|
+
specification_version: 2
|
83
|
+
summary: A rubygem for parsing sim-racing results files.
|
84
|
+
test_files: []
|
85
|
+
|