Skip to content

Instantly share code, notes, and snippets.

@jlogsdon
Created April 3, 2012 23:16
Show Gist options
  • Save jlogsdon/2296219 to your computer and use it in GitHub Desktop.
Save jlogsdon/2296219 to your computer and use it in GitHub Desktop.
class Mineral < ActiveRecord::Base
has_many :ore_contents
has_many :ores, :through => :ore_contents
end
class Ore < ActiveRecord::Base
has_many :ore_contents
has_many :minerals, :through => :ore_contents
validates_presence_of :batch_size
def add_mineral(name, amount)
return unless mineral = Mineral.find_by_name(name)
unless content = ore_contents.find_by_mineral_id(mineral.id)
content = ore_contents.build(:mineral_id => mineral.id)
end
content.amount = amount
content.save!
end
def batch_value
ore_contents.map(&:value).reduce(&:+)
end
def refine(amount, value = false)
batches = (amount / batch_size)
refined = Hash.new
ore_contents.dup.each do |content|
refined[content.mineral.name] = batches * (value ? content.mineral.value : content.amount)
end
refined
end
end
class OreContent < ActiveRecord::Base
belongs_to :ore
belongs_to :mineral
validates_presence_of :amount
def value
mineral.price * amount
end
end
class OreCalculator
attr_accessor :stock
def initialize(stock)
@stock = stock
end
def calculate_amounts
refined = Hash.new(0)
stock.each do |ore_name, amount|
ore = Ore.find_by_name(ore_name)
next unless ore
ore.refine(amount).each do |mineral, amount|
refined[mineral] += amount
end
end
refined
end
end
require 'spec_helper'
require 'ore_calculator'
describe OreCalculator do
describe '#calculate_amounts' do
context 'one exact batch of veldspar' do
it 'should return a hash with tritanium' do
amounts = { 'veldspar' => 333 }
expected_result = { 'tritanium' => 1000 }
described_class.new(amounts).calculate_amounts.should == expected_result
end
end
context 'one brimming batch of veldspar' do
it 'should discard the excess ore and return a hash with tritanium' do
amounts = { 'veldspar' => 400 }
expected_result = { 'tritanium' => 1000 }
described_class.new(amounts).calculate_amounts.should == expected_result
end
end
context 'one exact batch of veldspar and one of scordite' do
it 'should return a hash with tritanium and pyerite' do
amounts = { 'veldspar' => 333, 'scordite' => 333 }
expected_result = { 'tritanium' => 1833, 'pyerite' => 416 }
described_class.new(amounts).calculate_amounts.should == expected_result
end
end
end
end
Mineral.create(name: "tritanium", price: 3)
Mineral.create(name: "pyerite", price: 5)
Mineral.create(name: "mexallon", price: 30)
Mineral.create(name: "isogen", price: 65)
Mineral.create(name: "nocxium", price: 450)
Mineral.create(name: "zydrine", price: 750)
Mineral.create(name: "megacyte", price: 2700)
Mineral.create(name: "morphite", price: 3300)
Ore.create(name: "veldspar", batch_size: 333, unit_volume: 0.1) do |ore|
ore.add_mineral('tritanium', 1000)
end
Ore.create(name: "scordite", batch_size: 333, unit_volume: 0.15) do |ore|
ore.add_mineral("tritanium", 833)
ore.add_mineral("pyerite", 416)
end
Ore.create(name: "plagioclase", batch_size: 333, unit_volume: 0.35) do |ore|
ore.add_mineral("tritanium", 256)
ore.add_mineral("pyerite", 512)
ore.add_mineral("mexallon", 256)
end
Ore.create(name: "pyroxeres", batch_size: 333, unit_volume: 0.3) do |ore|
ore.add_mineral("tritanium", 844)
ore.add_mineral("pyerite", 59)
ore.add_mineral("mexallon", 120)
ore.add_mineral("nocxium", 11)
end
Ore.create(name: "omber", batch_size: 500, unit_volume: 0.6) do |ore|
ore.add_mineral("tritanium", 307)
ore.add_mineral("pyerite", 123)
ore.add_mineral("isogen", 307)
end
Ore.create(name: "kernite", batch_size: 400, unit_volume: 1.2) do |ore|
ore.add_mineral("tritanium", 386)
ore.add_mineral("mexallon", 773)
ore.add_mineral("isogen", 386)
end
Ore.create(name: "jaspet", batch_size: 500, unit_volume: 2) do |ore|
ore.add_mineral("tritanium", 259)
ore.add_mineral("pyerite", 259)
ore.add_mineral("mexallon", 518)
ore.add_mineral("nocxium", 259)
ore.add_mineral("zydrine", 8)
end
Ore.create(name: "hemorphite", batch_size: 500, unit_volume: 3) do |ore|
ore.add_mineral("tritanium", 212)
ore.add_mineral("isogen", 212)
ore.add_mineral("nocxium", 424)
ore.add_mineral("zydrine", 28)
end
Ore.create(name: "hedbergite", batch_size: 500, unit_volume: 3) do |ore|
ore.add_mineral("isogen", 708)
ore.add_mineral("nocxium", 354)
ore.add_mineral("zydrine", 32)
end
Ore.create(name: "gneiss", batch_size: 400, unit_volume: 5) do |ore|
ore.add_mineral("tritanium", 171)
ore.add_mineral("mexallon", 171)
ore.add_mineral("isogen", 343)
ore.add_mineral("zydrine", 250)
end
Ore.create(name: "dark ochre", batch_size: 400, unit_volume: 8) do |ore|
end
Ore.create(name: "spodumain", batch_size: 250, unit_volume: 16) do |ore|
ore.add_mineral("tritanium", 700)
ore.add_mineral("pyerite", 140)
ore.add_mineral("megacyte", 140)
end
Ore.create(name: "crokite", batch_size: 250, unit_volume: 16) do |ore|
ore.add_mineral("tritanium", 331)
ore.add_mineral("nocxium", 331)
ore.add_mineral("zydrine", 663)
end
Ore.create(name: "bistot", batch_size: 200, unit_volume: 16) do |ore|
ore.add_mineral("pyerite", 170)
ore.add_mineral("zydrine", 341)
ore.add_mineral("megacyte", 170)
end
Ore.create(name: "arkonor", batch_size: 250, unit_volume: 16) do |ore|
ore.add_mineral("tritanium", 300)
ore.add_mineral("zydrine", 166)
ore.add_mineral("megacyte", 333)
end
Ore.create(name: "mercoxit", batch_size: 250, unit_volume: 40) do |ore|
ore.add_mineral("morphite", 530)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment