engine-tune 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +81 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/engine-tune.gemspec +59 -0
- data/lib/engine-tune/calculations.rb +103 -0
- data/lib/engine-tune/calculator.rb +131 -0
- data/lib/engine-tune.rb +20 -0
- data/test/helper.rb +34 -0
- data/test/test_calculations.rb +42 -0
- data/test/test_calculator.rb +95 -0
- data/test/test_engine_tune.rb +9 -0
- data/test/test_suite.rb +5 -0
- metadata +86 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Guts & Bolts LLC
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
= EngineTune
|
2
|
+
|
3
|
+
Interested in determining how well your engine will run under certain meteorological and geological conditions?
|
4
|
+
|
5
|
+
This is the gem for you! (And I am sure there are a lot of you out there.)
|
6
|
+
|
7
|
+
EngineTune returns the following calculations when supplied with altitude, altimeter (barometric pressure), temperature and dew point:
|
8
|
+
|
9
|
+
* AE Relative Horsepower
|
10
|
+
* Dyno Correction Factor
|
11
|
+
* Air Density
|
12
|
+
* Density Altitude
|
13
|
+
* ICAO Relative Air Density
|
14
|
+
* Virtual Temperature
|
15
|
+
* Absolute Air Pressure
|
16
|
+
* Vapor Pressure
|
17
|
+
* Relative Humidity
|
18
|
+
|
19
|
+
The calculations in this gem are modeled after Richard Shelquist's Engine Tuner's Calculator, but have been re-factored to be more ruby-like. I urge you to read his technical articles on Density Altitude and Corrected Horsepower for detailed explanations of these concepts.
|
20
|
+
|
21
|
+
http://wahiduddin.net/calc/calc_hp_dp.htm
|
22
|
+
|
23
|
+
== Standard Usage
|
24
|
+
|
25
|
+
<i>Note that all observations must be supplied using the metric system of measurement.</i>
|
26
|
+
|
27
|
+
observations = Hash.new
|
28
|
+
observations[:temperature] = 32.0 # Celsius
|
29
|
+
observations[:dew_point] = 22.0 # Celsius
|
30
|
+
observations[:altitude] = 149.0 # Meters
|
31
|
+
observations[:altimeter] = 1013.4 # Millibars
|
32
|
+
|
33
|
+
calculations = EngineTune.calculate(observations)
|
34
|
+
|
35
|
+
calculations.relative_horsepower
|
36
|
+
#=> 96.2 (as percentage)
|
37
|
+
|
38
|
+
calculations.density_altitude
|
39
|
+
#=> 876 (as meters)
|
40
|
+
|
41
|
+
|
42
|
+
Calculations are returned in metric units, but if you prefer your calculations using the English system of measurement, do this:
|
43
|
+
|
44
|
+
calculations.metric = false
|
45
|
+
|
46
|
+
calculations.density_altitude
|
47
|
+
#=> 2874 (as feet)
|
48
|
+
|
49
|
+
And if you forget what system of measurement your calculations object is using, just ask it:
|
50
|
+
|
51
|
+
calculations.metric = false
|
52
|
+
|
53
|
+
calculations.metric?
|
54
|
+
#=> false
|
55
|
+
|
56
|
+
calculations.english?
|
57
|
+
#=> true
|
58
|
+
|
59
|
+
== The Calculator
|
60
|
+
|
61
|
+
You can also bypass the calculations object and directly use the calculator:
|
62
|
+
|
63
|
+
temperature = 32.0 # Celsius
|
64
|
+
dew_point = 22.0 # Celsius
|
65
|
+
altitude = 149.0 # Meters
|
66
|
+
altimeter = 1013.4 # Millibars
|
67
|
+
|
68
|
+
EngineTune::Calculator.relative_horsepower(altimeter, altitude, dew_point, temperature)
|
69
|
+
#=> 96.2 (as percentage)
|
70
|
+
|
71
|
+
Convenience methods to convert between metric and English units are provided as well:
|
72
|
+
|
73
|
+
EngineTune::Calculator.meters_to_feet 1054
|
74
|
+
#=> 3458.0052546
|
75
|
+
|
76
|
+
EngineTune::Calculator.inches_to_millibars 1223
|
77
|
+
#=> 41415.3694298
|
78
|
+
|
79
|
+
== Copyright
|
80
|
+
|
81
|
+
Copyright (c) 2010 Guts & Bolts LLC. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "engine-tune"
|
8
|
+
gem.summary = "Determine how well your engine will run under certain meteorological and geological conditions."
|
9
|
+
gem.description = "Determine how well your engine will run under certain meteorological and geological conditions."
|
10
|
+
gem.email = "theo@gutsbolts.com"
|
11
|
+
gem.homepage = "http://github.com/gutsbolts/engine-tune"
|
12
|
+
gem.authors = ["Theodore Mills"]
|
13
|
+
end
|
14
|
+
Jeweler::GemcutterTasks.new
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
Rake::TestTask.new(:test) do |test|
|
21
|
+
test.libs << 'lib' << 'test'
|
22
|
+
test.pattern = 'test/**/test_*.rb'
|
23
|
+
test.verbose = true
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'rcov/rcovtask'
|
28
|
+
Rcov::RcovTask.new do |test|
|
29
|
+
test.libs << 'test'
|
30
|
+
test.pattern = 'test/**/test_*.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
rescue LoadError
|
34
|
+
task :rcov do
|
35
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
task :test => :check_dependencies
|
40
|
+
|
41
|
+
task :default => :test
|
42
|
+
|
43
|
+
require 'rake/rdoctask'
|
44
|
+
Rake::RDocTask.new do |rdoc|
|
45
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
46
|
+
|
47
|
+
rdoc.rdoc_dir = 'rdoc'
|
48
|
+
rdoc.title = "engine-tune #{version}"
|
49
|
+
rdoc.rdoc_files.include('README*')
|
50
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
51
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.1
|
data/engine-tune.gemspec
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{engine-tune}
|
8
|
+
s.version = "0.4.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Theodore Mills"]
|
12
|
+
s.date = %q{2010-07-07}
|
13
|
+
s.description = %q{Determine how well your engine will run under certain meteorological and geological conditions.}
|
14
|
+
s.email = %q{theo@gutsbolts.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"engine-tune.gemspec",
|
27
|
+
"lib/engine-tune.rb",
|
28
|
+
"lib/engine-tune/calculations.rb",
|
29
|
+
"lib/engine-tune/calculator.rb",
|
30
|
+
"test/helper.rb",
|
31
|
+
"test/test_calculations.rb",
|
32
|
+
"test/test_calculator.rb",
|
33
|
+
"test/test_engine_tune.rb",
|
34
|
+
"test/test_suite.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/gutsbolts/engine-tune}
|
37
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = %q{1.3.7}
|
40
|
+
s.summary = %q{Determine how well your engine will run under certain meteorological and geological conditions.}
|
41
|
+
s.test_files = [
|
42
|
+
"test/helper.rb",
|
43
|
+
"test/test_calculations.rb",
|
44
|
+
"test/test_calculator.rb",
|
45
|
+
"test/test_engine_tune.rb",
|
46
|
+
"test/test_suite.rb"
|
47
|
+
]
|
48
|
+
|
49
|
+
if s.respond_to? :specification_version then
|
50
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
51
|
+
s.specification_version = 3
|
52
|
+
|
53
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
54
|
+
else
|
55
|
+
end
|
56
|
+
else
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module EngineTune
|
2
|
+
|
3
|
+
#
|
4
|
+
# After getting instantiated with a set of meterological and geological observations,
|
5
|
+
# a Calculations object can determine a number of calculations related to engine
|
6
|
+
# efficiency.
|
7
|
+
#
|
8
|
+
class Calculations
|
9
|
+
|
10
|
+
# Names of observations required for calculations to compute
|
11
|
+
OBSERVATION_ATTRS = [:temperature, :dew_point, :altitude, :altimeter]
|
12
|
+
OBSERVATION_ATTRS.each { |a| attr_accessor a }
|
13
|
+
|
14
|
+
attr_writer :metric
|
15
|
+
|
16
|
+
#
|
17
|
+
# Instantiates a new instance with a hash of observations including temperature,
|
18
|
+
# dew_point, altimeter and altitude. These observations are the only required data
|
19
|
+
# to calculate all the engine tuning metrics exposed in this object.
|
20
|
+
#
|
21
|
+
def initialize(observations)
|
22
|
+
observations.each { |method, value| send("#{method}=", value) }
|
23
|
+
@metric = true
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Objects are equal if their observations are identical
|
28
|
+
#
|
29
|
+
def ==(object)
|
30
|
+
self.observations == object.observations
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Returns a hash of observations for this set of calculations
|
35
|
+
#
|
36
|
+
def observations
|
37
|
+
OBSERVATION_ATTRS.inject({}) do |result, o|
|
38
|
+
result[o] = send(o)
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Returns true if calculations should be returned using the metric system
|
45
|
+
#
|
46
|
+
def metric?
|
47
|
+
@metric
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Returns true if calculations should be returned using the English system
|
52
|
+
#
|
53
|
+
def english?
|
54
|
+
!@metric
|
55
|
+
end
|
56
|
+
|
57
|
+
def vapor_pressure
|
58
|
+
@vapor_pressure ||= EngineTune::Calculator.vapor_pressure(dew_point)
|
59
|
+
@vapor_pressure_inches ||= EngineTune::Calculator.millibars_to_inches(@vapor_pressure)
|
60
|
+
metric? ? @vapor_pressure : @vapor_pressure_inches
|
61
|
+
end
|
62
|
+
|
63
|
+
def relative_humidity
|
64
|
+
@relative_humidity ||= EngineTune::Calculator.relative_humidity(temperature, dew_point)
|
65
|
+
end
|
66
|
+
|
67
|
+
def absolute_pressure
|
68
|
+
@absolute_air_pressure ||= EngineTune::Calculator.absolute_pressure(altimeter, altitude)
|
69
|
+
@absolute_air_pressure_inches ||= EngineTune::Calculator.millibars_to_inches(@absolute_air_pressure)
|
70
|
+
metric? ? @absolute_air_pressure : @absolute_air_pressure_inches
|
71
|
+
end
|
72
|
+
|
73
|
+
def density
|
74
|
+
@density ||= EngineTune::Calculator.density(altimeter, altitude, dew_point, temperature)
|
75
|
+
end
|
76
|
+
|
77
|
+
def relative_density
|
78
|
+
@relative_density ||= EngineTune::Calculator.relative_density(altimeter, altitude, dew_point, temperature)
|
79
|
+
end
|
80
|
+
|
81
|
+
def dyno_correction_factor
|
82
|
+
@dyno_correction_factor ||= EngineTune::Calculator.dyno_correction_factor(altimeter, altitude, dew_point, temperature)
|
83
|
+
end
|
84
|
+
|
85
|
+
def virtual_temperature
|
86
|
+
@virtual_temperature ||= EngineTune::Calculator.virtual_temperature(altimeter, altitude, dew_point, temperature)
|
87
|
+
@virtual_temperature_f ||= EngineTune::Calculator.celsius_to_fahrenheit(@virtual_temperature)
|
88
|
+
metric? ? @virtual_temperature : @virtual_temperature_f
|
89
|
+
end
|
90
|
+
|
91
|
+
def density_altitude
|
92
|
+
@density_altitude ||= EngineTune::Calculator.density_altitude(altimeter, altitude, dew_point, temperature)
|
93
|
+
@density_altitude_feet ||= EngineTune::Calculator.meters_to_feet(@density_altitude)
|
94
|
+
metric? ? @density_altitude : @density_altitude_feet
|
95
|
+
end
|
96
|
+
|
97
|
+
def relative_horsepower
|
98
|
+
@relative_horsepower ||= EngineTune::Calculator.relative_horsepower(altimeter, altitude, dew_point, temperature)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module EngineTune
|
2
|
+
|
3
|
+
#
|
4
|
+
# A collection of formulas and calculations used to determine, among other things,
|
5
|
+
# the relative horsepower of an engine given different environmental conditions.
|
6
|
+
#
|
7
|
+
# These calculations are modeled after Richard Shelquist's Engine Tuner's Calculator,
|
8
|
+
# but have been re-factored to be more ruby-like. I urge you to read his technical
|
9
|
+
# articles on Density Altitude and Corrected Horsepower for detailed explanations of
|
10
|
+
# these concepts.
|
11
|
+
#
|
12
|
+
# In some cases I took a guess at what a method should be named based on the calculation
|
13
|
+
# it is returning, so any better suggestions are welcomed.
|
14
|
+
#
|
15
|
+
module Calculator
|
16
|
+
class << self
|
17
|
+
|
18
|
+
def density_altitude(altimeter, altitude, dew_point, temperature)
|
19
|
+
# Calculate geometric altitude Z (m) from geopotential altitude (m) H
|
20
|
+
densaltzm = self.altitude_z(altimeter, altitude, dew_point, temperature)
|
21
|
+
unless (-5000..11000).include?(densaltzm)
|
22
|
+
raise "Out of range for Troposhere Algorithm: Altitude =" + densaltzm.round + " meters"
|
23
|
+
end
|
24
|
+
densaltzm.round
|
25
|
+
end
|
26
|
+
|
27
|
+
def dyno_correction_factor(altimeter, altitude, dew_point, temperature)
|
28
|
+
vapor_pressure_mb = self.vapor_pressure(dew_point)
|
29
|
+
absolute_pressure_mb = self.absolute_pressure(altimeter, altitude)
|
30
|
+
absolute_pressure_in = millibars_to_inches(absolute_pressure_mb)
|
31
|
+
vapor_pressure_in = millibars_to_inches(vapor_pressure_mb)
|
32
|
+
p1 = 29.235 / (absolute_pressure_in - vapor_pressure_in)
|
33
|
+
p2 = ((temperature + 273) / 298)**0.5
|
34
|
+
(1.18 * (p1 * p2) - 0.18)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def virtual_temperature(altimeter, altitude, dew_point, temperature)
|
39
|
+
absolute_pressure = self.absolute_pressure(altimeter, altitude)
|
40
|
+
vapor_pressure = self.vapor_pressure(dew_point)
|
41
|
+
((temperature + 273.15) / (1- (0.377995 * vapor_pressure / absolute_pressure)))-273.15
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Polynomial from Herman Wobus
|
46
|
+
#
|
47
|
+
def vapor_pressure(temperature_c)
|
48
|
+
values = [ 1.1112018e-17, -1.7892321e-15, 2.1874425e-13, -2.9883885e-11, 4.3884187e-09, -6.1117958e-07, 7.8736169e-05, -0.0090826951, 0.99999683 ]
|
49
|
+
pol = values.inject(-0.30994571E-19) { |result, v| result = v + temperature_c * result }
|
50
|
+
6.1078 / (pol**8)
|
51
|
+
end
|
52
|
+
|
53
|
+
def geopotential_altitude(elevation_in_meters)
|
54
|
+
r = 6369E3;
|
55
|
+
((r * elevation_in_meters) / (r + elevation_in_meters))
|
56
|
+
end
|
57
|
+
|
58
|
+
def density(altimeter, altitude, dew_point, temperature)
|
59
|
+
vapor_pressure = self.vapor_pressure(dew_point)
|
60
|
+
absolute_pressure = self.absolute_pressure(altimeter, altitude)
|
61
|
+
|
62
|
+
rv, rd = 461.4964, 287.0531
|
63
|
+
temperature_k = temperature + 273.15
|
64
|
+
pv = vapor_pressure * 100
|
65
|
+
pd = (absolute_pressure - vapor_pressure) * 100
|
66
|
+
(pv / (rv * temperature_k)) + (pd / (rd * temperature_k))
|
67
|
+
end
|
68
|
+
|
69
|
+
def altitude(altimeter, elevation, dew_point, temperature)
|
70
|
+
density = self.density(altimeter, elevation, dew_point, temperature)
|
71
|
+
g, po, to, l, r, m = 9.80665, 101325, 288.15, 6.5, 8.314320, 28.9644
|
72
|
+
density = density * 1000
|
73
|
+
p2 = ( (l * r)/(g* m - l * r) ) * Math.log( (r * to * density) / (m * po) )
|
74
|
+
h = -(to / l)*( Math.exp(p2) -1 )
|
75
|
+
h * 1000
|
76
|
+
end
|
77
|
+
|
78
|
+
def altitude_z(altimeter, elevation, dew_point, temperature)
|
79
|
+
altitude = self.altitude(altimeter, elevation, dew_point, temperature)
|
80
|
+
r = 6369E3
|
81
|
+
((r * altitude) / (r - altitude))
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def absolute_pressure(altimeter, altitude)
|
86
|
+
k1, k2 = 0.190263, 8.417286E-5
|
87
|
+
((altimeter**k1)-(k2 * self.geopotential_altitude(altitude)))**(1/k1)
|
88
|
+
end
|
89
|
+
|
90
|
+
def relative_density(altimeter, altitude, dew_point, temperature)
|
91
|
+
density = self.density(altimeter, altitude, dew_point, temperature)
|
92
|
+
100 * (density / 1.225)
|
93
|
+
end
|
94
|
+
|
95
|
+
def relative_humidity(temperature, dew_point)
|
96
|
+
(vapor_pressure(dew_point) / vapor_pressure(temperature)) * 100
|
97
|
+
end
|
98
|
+
|
99
|
+
def relative_horsepower(altimeter, altitude, dew_point, temperature)
|
100
|
+
dyno_correction_factor = self.dyno_correction_factor(altimeter, altitude, dew_point, temperature)
|
101
|
+
round((100 / dyno_correction_factor), 1)
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Systems of measurement conversion methods
|
106
|
+
#
|
107
|
+
|
108
|
+
def millibars_to_inches(mb)
|
109
|
+
mb * (1/33.86389)
|
110
|
+
end
|
111
|
+
|
112
|
+
def inches_to_millibars(inches)
|
113
|
+
inches * 33.8637526
|
114
|
+
end
|
115
|
+
|
116
|
+
def meters_to_feet(meters)
|
117
|
+
meters * 3.2808399
|
118
|
+
end
|
119
|
+
|
120
|
+
def round(f, d)
|
121
|
+
(f * 10**d).round.to_f / 10**d
|
122
|
+
end
|
123
|
+
|
124
|
+
def celsius_to_fahrenheit(temp)
|
125
|
+
((temp * 9.0) / 5.0) + 32.0
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
data/lib/engine-tune.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require "engine-tune/calculations"
|
6
|
+
require "engine-tune/calculator"
|
7
|
+
|
8
|
+
#
|
9
|
+
# An engine's efficiency can be impacted by environmental factors such as
|
10
|
+
# altitude and temperature. EngineForecast first collects environmental data
|
11
|
+
# based on the supplied latitude and longitude and then returns a set of calculations
|
12
|
+
# to determine how great that impact is.
|
13
|
+
#
|
14
|
+
module EngineTune
|
15
|
+
|
16
|
+
def self.calculate(observations)
|
17
|
+
EngineTune::Calculations.new(observations)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'engine-tune'
|
8
|
+
|
9
|
+
class Test::Unit::TestCase
|
10
|
+
def observations
|
11
|
+
{ :altitude => 149.0, :temperature => 32.0, :dew_point=>22.0, :altimeter=>1013.4 }
|
12
|
+
end
|
13
|
+
|
14
|
+
def round(f, d)
|
15
|
+
(f * 10**d).round.to_f / 10**d
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.correct_answers
|
19
|
+
{
|
20
|
+
:vapor_pressure => 26.4295210976309,
|
21
|
+
:density_altitude => 876,
|
22
|
+
:dyno_correction_factor => 1.0394157966139073,
|
23
|
+
:relative_horsepower => 96.2,
|
24
|
+
:virtual_temperature => 35.09294483203081,
|
25
|
+
:geopotential_altitude => 148.99651429099868,
|
26
|
+
:density => 1.1252290472090851,
|
27
|
+
:relative_density => 91.85543242523143,
|
28
|
+
:altitude => 876.1337602041878,
|
29
|
+
:altitude_z => 876.2542996883268,
|
30
|
+
:absolute_pressure => 995.6262086849655,
|
31
|
+
:relative_humidity => 55.58171762613951
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class EngineTune::TestCalculations < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@calculations = EngineTune::Calculations.new(observations)
|
7
|
+
end
|
8
|
+
|
9
|
+
self.correct_answers.each do |method, answer|
|
10
|
+
|
11
|
+
# List of methods inside correct answers hash that are not exposed
|
12
|
+
# on the Calculations object so don't create a test for them
|
13
|
+
exceptions = [:geopotential_altitude, :altitude, :altitude_z]
|
14
|
+
|
15
|
+
unless exceptions.include?(method)
|
16
|
+
define_method "test_calculations_#{method}" do
|
17
|
+
assert_equal round(answer, 13), round(@calculations.send(method), 13)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_vapor_pressure_inches
|
23
|
+
@calculations.metric = false
|
24
|
+
assert_equal 0.780463233775887, round(@calculations.vapor_pressure, 15)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_absolute_pressure_inches
|
28
|
+
@calculations.metric = false
|
29
|
+
assert_equal 29.4008221939348, round(@calculations.absolute_pressure, 13)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_virtual_temperature_fahrenheit
|
33
|
+
@calculations.metric = false
|
34
|
+
assert_equal 95.1673006976555, round(@calculations.virtual_temperature, 13)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_density_altitude_feet
|
38
|
+
@calculations.metric = false
|
39
|
+
assert_equal 2874.0157524, round(@calculations.density_altitude, 7)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class EngineTune::TestCalculator < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
observations.each { |k, v| instance_variable_set("@#{k}", v)}
|
7
|
+
end
|
8
|
+
|
9
|
+
def correct_answers
|
10
|
+
Test::Unit::TestCase.correct_answers
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_vapor_pressure
|
14
|
+
value = EngineTune::Calculator.vapor_pressure(@dew_point)
|
15
|
+
assert_equal correct_answers[:vapor_pressure] , round(value, 13)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_density_altitude
|
19
|
+
value = EngineTune::Calculator.density_altitude(@altimeter, @altitude, @dew_point, @temperature)
|
20
|
+
assert_equal correct_answers[:density_altitude], value
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_dyno_correction_factor
|
24
|
+
value = EngineTune::Calculator.dyno_correction_factor(@altimeter, @altitude, @dew_point, @temperature)
|
25
|
+
assert_equal correct_answers[:dyno_correction_factor], value
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_relative_horsepower
|
29
|
+
value = EngineTune::Calculator.relative_horsepower(@altimeter, @altitude, @dew_point, @temperature)
|
30
|
+
assert_equal correct_answers[:relative_horsepower], value
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_virtual_temperature
|
34
|
+
value = EngineTune::Calculator.virtual_temperature(@altimeter, @altitude, @dew_point, @temperature)
|
35
|
+
assert_equal correct_answers[:virtual_temperature], value
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_geopotential_altitude
|
39
|
+
assert_equal correct_answers[:geopotential_altitude], EngineTune::Calculator.geopotential_altitude(@altitude)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_density
|
43
|
+
value = EngineTune::Calculator.density(@altimeter, @altitude, @dew_point, @temperature)
|
44
|
+
assert_equal correct_answers[:density], value
|
45
|
+
end
|
46
|
+
|
47
|
+
def relative_density
|
48
|
+
value = EngineTune::Calculator.relative_density(@altimeter, @altitude, @dew_point, @temperature)
|
49
|
+
assert_equal correct_answers[:relative_density], value
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_altitude
|
53
|
+
value = EngineTune::Calculator.altitude(@altimeter, @altitude, @dew_point, @temperature)
|
54
|
+
assert_equal correct_answers[:altitude], value
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_altitude_z
|
58
|
+
value = EngineTune::Calculator.altitude_z(@altimeter, @altitude, @dew_point, @temperature)
|
59
|
+
assert_equal correct_answers[:altitude_z], value
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_absolute_pressure
|
63
|
+
value = EngineTune::Calculator.absolute_pressure(@altimeter, @altitude)
|
64
|
+
assert_equal correct_answers[:absolute_pressure], value
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_relative_humidity
|
68
|
+
z = EngineTune::Calculator.relative_humidity(@temperature, @dew_point)
|
69
|
+
assert_equal round(correct_answers[:relative_humidity], 13), round(z, 13)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Measurement conversion tests
|
73
|
+
|
74
|
+
def test_inches_to_millibars
|
75
|
+
assert_equal 997.96, round(EngineTune::Calculator.inches_to_millibars(29.47), 2)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_millibars_to_inches
|
79
|
+
assert_equal 29.47, round(EngineTune::Calculator.millibars_to_inches(998), 2)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_meters_to_feet
|
83
|
+
assert_equal 3458.0052546, EngineTune::Calculator.meters_to_feet(1054)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_round
|
87
|
+
number = 21345.56789999
|
88
|
+
assert_equal 21345.57, EngineTune::Calculator.round(number, 2)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_celsius_to_fahrenheit
|
92
|
+
assert_equal 80.6, EngineTune::Calculator.celsius_to_fahrenheit(27)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
data/test/test_suite.rb
ADDED
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: engine-tune
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 13
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 1
|
10
|
+
version: 0.4.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Theodore Mills
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-07 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Determine how well your engine will run under certain meteorological and geological conditions.
|
23
|
+
email: theo@gutsbolts.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- LICENSE
|
30
|
+
- README.rdoc
|
31
|
+
files:
|
32
|
+
- .document
|
33
|
+
- .gitignore
|
34
|
+
- LICENSE
|
35
|
+
- README.rdoc
|
36
|
+
- Rakefile
|
37
|
+
- VERSION
|
38
|
+
- engine-tune.gemspec
|
39
|
+
- lib/engine-tune.rb
|
40
|
+
- lib/engine-tune/calculations.rb
|
41
|
+
- lib/engine-tune/calculator.rb
|
42
|
+
- test/helper.rb
|
43
|
+
- test/test_calculations.rb
|
44
|
+
- test/test_calculator.rb
|
45
|
+
- test/test_engine_tune.rb
|
46
|
+
- test/test_suite.rb
|
47
|
+
has_rdoc: true
|
48
|
+
homepage: http://github.com/gutsbolts/engine-tune
|
49
|
+
licenses: []
|
50
|
+
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options:
|
53
|
+
- --charset=UTF-8
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.3.7
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: Determine how well your engine will run under certain meteorological and geological conditions.
|
81
|
+
test_files:
|
82
|
+
- test/helper.rb
|
83
|
+
- test/test_calculations.rb
|
84
|
+
- test/test_calculator.rb
|
85
|
+
- test/test_engine_tune.rb
|
86
|
+
- test/test_suite.rb
|