lib/eulim/chemistry/compound.rb in eulim-0.0.6 vs lib/eulim/chemistry/compound.rb in eulim-0.0.7
- old
+ new
@@ -1,65 +1,53 @@
module Eulim::Chemistry
class Compound
VALID_COMPOUND_REGEXP = /[A-Z][a-z]{0,2}\d*|\((?:[^()]*(?:\(.*\))?[^()]*)+\)\d*/
- VAILD_ELEMENT_REGEXP = /[A-Z][a-z]{0,2}\d*/
+ attr_accessor :molecular_mass, :constituents, :formula
+
def initialize(arg)
@formula = arg
+ @constituents = get_constituents
+ @molecular_mass = get_molecular_mass
end
- def molecular_mass
- mass = 0
- element_atom_count = get_element_atom_count
- element_atom_count.each do |symbol, count|
- mass += Element.get_by_symbol(symbol).atomic_mass * count
+ private
+ def get_molecular_mass
+ mass = 0
+ @constituents.each do |constituent|
+ mass += constituent[:element].atomic_mass * constituent[:atom_count]
+ end
+ mass
end
- mass
- end
- def elements
- elements = []
- element_atom_count = get_element_atom_count
- element_atom_count.each do |symbol, count|
- elements << Element.get_by_symbol(symbol)
+ def get_constituents
+ constituents = []
+ get_constituent_atoms.each do |symbol, count|
+ constituents << {element: Element.get_by_symbol(symbol), atom_count: count}
+ end
+ constituents
end
- elements
- end
- private
- def get_element_atom_count formula = @formula, group_multiplier = 1, result = {}, groups = []
- formula
- elements_n_groups = formula.scan VALID_COMPOUND_REGEXP
- loop do
- break if !elements_n_groups.last
- elements = elements_n_groups.last.scan VAILD_ELEMENT_REGEXP
- if elements.first === elements_n_groups.last
- element_multipler = elements.first.match(/\d*$/).to_a.first.to_i
- element_multipler = element_multipler > 0 ? element_multipler : 1
- element_symbol = elements.first.match(/[A-Z][a-z]{0,2}/).to_a.first
- if result[element_symbol]
- result[element_symbol] += (element_multipler * group_multiplier)
- else
- result[element_symbol] = (element_multipler * group_multiplier)
- end
+ def get_constituent_atoms formula=@formula, result={}
+ constituents = formula.scan VALID_COMPOUND_REGEXP
+ constituents.each do |constituent|
+ multipler = get_multipler constituent
+ if constituent[0] != '(' && multipler == 0
+ result[constituent] = result[constituent] ? result[constituent] + 1 : 1
else
- groups << elements_n_groups.last
- end
- elements_n_groups.pop
+ (multipler == 0 ? 1 : multipler).times do
+ sub_constituents = constituent.match(/^\(?(.*?)\)?($|\d*$)/).to_a
+ idx = constituent == sub_constituents.first ? 1 : 0
+ get_constituent_atoms sub_constituents[idx], result
+ end
+ end
end
- loop do
- break if !groups.last
- group = groups.pop
- grml = get_group_multiplier(group)
- get_element_atom_count group[1..-(grml.to_s.length+1)], grml*group_multiplier, result, groups
- end
result
end
- def get_group_multiplier formula
- group_multiplier = formula.scan(VALID_COMPOUND_REGEXP).first.match(/\d*$/).to_a.first.to_i
- group_multiplier > 0 ? group_multiplier : 1
+ def get_multipler constituent
+ multipler = constituent.match(/\d*$/).to_a.first.to_i
end
end
end