Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

split up FUE class

  • Loading branch information...
commit e02565e4c147d431185a587edcfd804cb6767a7a 1 parent b8c2b80
@seamusabshere seamusabshere authored
View
122 lib/flight/impact_model/fuel_use_equation.rb
@@ -1,14 +1,13 @@
+require 'flight/impact_model/fuel_use_equation/derived'
+require 'flight/impact_model/fuel_use_equation/given'
+
module BrighterPlanet
module Flight
module ImpactModel
class FuelUseEquation
class << self
def from_coefficients(m3, m2, m1, b)
- equation = new
- equation.m3 = m3
- equation.m2 = m2
- equation.m1 = m1
- equation.b = b
+ equation = Given.new(m3, m2, m1, b)
if equation.valid?
equation
else
@@ -16,9 +15,8 @@ def from_coefficients(m3, m2, m1, b)
end
end
- def from_flight_segments(relation)
- equation = new
- equation.where_sql = relation.where_sql
+ def from_flight_segments(flight_segments)
+ equation = Derived.new flight_segments
if equation.valid?
equation
else
@@ -27,121 +25,13 @@ def from_flight_segments(relation)
end
end
- attr_writer :m3, :m2, :m1, :b
- attr_accessor :where_sql
-
def valid?
coefficients.all?(&:present?) and coefficients.any?(&:nonzero?)
end
- def m3
- calculate!
- @m3
- end
-
- def m2
- calculate!
- @m2
- end
-
- def m1
- calculate!
- @m1
- end
-
- def b
- calculate!
- @b
- end
-
def coefficients
[ m3, m2, m1, b ]
end
-
- private
-
- def calculate!
- return if @calculated == true
- @calculated = true
- return unless where_sql
-
- # - Create a temporary table to hold the values we need
- c = ::ActiveRecord::Base.connection
-
- table_name = "flight_fuel_use_coefficients_#{::Kernel.rand(1e11)}"
-
- create_table_sql = %{
- CREATE TEMPORARY TABLE #{table_name} (
- description VARCHAR(255),
- m3 FLOAT,
- m2 FLOAT,
- m1 FLOAT,
- b FLOAT,
- passengers INT
- )
- }
-
- # make this run faster if you're on mysql
- create_table_sql << 'ENGINE=MEMORY' if c.adapter_name =~ /mysql/i
-
- c.execute create_table_sql
-
- # - Look up the unique aircraft descriptions in `where_sql`
- aircraft_descriptions = c.select_values %{
- SELECT DISTINCT aircraft_description
- FROM #{::FlightSegment.quoted_table_name}
- #{where_sql}
- }
-
- # - For each unique aircraft description:
- # - 1. look up all the aircraft it refers to
- # - 2. average those aircraft's fuel use coefficients
- # - 3. store the resulting values in the temporary table along with the unique aircraft_description
- c.execute %{
- INSERT INTO #{table_name} (description, m3, m2, m1, b)
- SELECT t1.b, AVG(t2.m3), AVG(t2.m2), AVG(t2.m1), AVG(t2.b)
- FROM #{::FuzzyMatch::CachedResult.quoted_table_name} AS t1
- INNER JOIN #{::Aircraft.quoted_table_name} AS t2
- ON t1.a = t2.description
- WHERE t1.b IN ('#{aircraft_descriptions.join("', '")}')
- GROUP BY t1.b
- }
-
- # - For each unique aircraft description:
- # - 1. look up all the flight segments in `where_sql` that match the aircraft description
- # - 2. sum passengers across those flight segments
- # - 3. store the resulting value in the temporary table
- c.execute %{
- UPDATE #{table_name}
- SET passengers = (
- SELECT SUM(passengers)
- FROM #{::FlightSegment.quoted_table_name}
- #{where_sql} AND #{::FlightSegment.quoted_table_name}.aircraft_description = #{table_name}.description
- )
- }
-
- # - Calculate the average of the coefficients in the temporary table, weighted by passengers
- row = c.select_one %{
- SELECT
- SUM(1.0 * m3 * passengers)/SUM(passengers) AS a_m3,
- SUM(1.0 * m2 * passengers)/SUM(passengers) AS a_m2,
- SUM(1.0 * m1 * passengers)/SUM(passengers) AS a_m1,
- SUM(1.0 * b * passengers)/SUM(passengers) AS a_b
- FROM #{table_name}
- WHERE
- m3 IS NOT NULL
- AND m2 IS NOT NULL
- AND m1 IS NOT NULL
- AND b IS NOT NULL
- AND passengers > 0
- }
-
- @m3, @m2, @m1, @b = row['a_m3'], row['a_m2'], row['a_m1'], row['a_b']
-
- c.execute %{
- DROP TABLE #{table_name}
- }
- end
end
end
end
View
118 lib/flight/impact_model/fuel_use_equation/derived.rb
@@ -0,0 +1,118 @@
+module BrighterPlanet
+ module Flight
+ module ImpactModel
+ class FuelUseEquation
+ class Derived < FuelUseEquation
+ def initialize(flight_segments)
+ @where_sql = flight_segments.where_sql
+ end
+
+ def m3
+ calculate!
+ @m3
+ end
+
+ def m2
+ calculate!
+ @m2
+ end
+
+ def m1
+ calculate!
+ @m1
+ end
+
+ def b
+ calculate!
+ @b
+ end
+
+ private
+
+ def calculate!
+ return if @calculated == true
+ @calculated = true
+ raise ArgumentError if @where_sql.blank?
+
+ # - Create a temporary table to hold the values we need
+ c = ::ActiveRecord::Base.connection
+
+ table_name = "flight_fuel_use_coefficients_#{::Kernel.rand(1e11)}"
+
+ create_table_sql = %{
+ CREATE TEMPORARY TABLE #{table_name} (
+ description VARCHAR(255),
+ m3 FLOAT,
+ m2 FLOAT,
+ m1 FLOAT,
+ b FLOAT,
+ passengers INT
+ )
+ }
+
+ # make this run faster if you're on mysql
+ create_table_sql << 'ENGINE=MEMORY' if c.adapter_name =~ /mysql/i
+
+ c.execute create_table_sql
+
+ # - Look up the unique aircraft descriptions in `@where_sql`
+ aircraft_descriptions = c.select_values %{
+ SELECT DISTINCT aircraft_description
+ FROM #{::FlightSegment.quoted_table_name}
+ #{@where_sql}
+ }
+
+ # - For each unique aircraft description:
+ # - 1. look up all the aircraft it refers to
+ # - 2. average those aircraft's fuel use coefficients
+ # - 3. store the resulting values in the temporary table along with the unique aircraft_description
+ c.execute %{
+ INSERT INTO #{table_name} (description, m3, m2, m1, b)
+ SELECT t1.b, AVG(t2.m3), AVG(t2.m2), AVG(t2.m1), AVG(t2.b)
+ FROM #{::FuzzyMatch::CachedResult.quoted_table_name} AS t1
+ INNER JOIN #{::Aircraft.quoted_table_name} AS t2
+ ON t1.a = t2.description
+ WHERE t1.b IN ('#{aircraft_descriptions.join("', '")}')
+ GROUP BY t1.b
+ }
+
+ # - For each unique aircraft description:
+ # - 1. look up all the flight segments in `@where_sql` that match the aircraft description
+ # - 2. sum passengers across those flight segments
+ # - 3. store the resulting value in the temporary table
+ c.execute %{
+ UPDATE #{table_name}
+ SET passengers = (
+ SELECT SUM(passengers)
+ FROM #{::FlightSegment.quoted_table_name}
+ #{@where_sql} AND #{::FlightSegment.quoted_table_name}.aircraft_description = #{table_name}.description
+ )
+ }
+
+ # - Calculate the average of the coefficients in the temporary table, weighted by passengers
+ row = c.select_one %{
+ SELECT
+ SUM(1.0 * m3 * passengers)/SUM(passengers) AS a_m3,
+ SUM(1.0 * m2 * passengers)/SUM(passengers) AS a_m2,
+ SUM(1.0 * m1 * passengers)/SUM(passengers) AS a_m1,
+ SUM(1.0 * b * passengers)/SUM(passengers) AS a_b
+ FROM #{table_name}
+ WHERE
+ m3 IS NOT NULL
+ AND m2 IS NOT NULL
+ AND m1 IS NOT NULL
+ AND b IS NOT NULL
+ AND passengers > 0
+ }
+
+ @m3, @m2, @m1, @b = row['a_m3'], row['a_m2'], row['a_m1'], row['a_b']
+
+ c.execute %{
+ DROP TABLE #{table_name}
+ }
+ end
+ end
+ end
+ end
+ end
+end
View
17 lib/flight/impact_model/fuel_use_equation/given.rb
@@ -0,0 +1,17 @@
+module BrighterPlanet
+ module Flight
+ module ImpactModel
+ class FuelUseEquation
+ class Given < FuelUseEquation
+ attr_reader :m3, :m2, :m1, :b
+ def initialize(m3, m2, m1, b)
+ @m3 = m3
+ @m2 = m2
+ @m1 = m1
+ @b = b
+ end
+ end
+ end
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.