1 module dunitconversion.conversionfamily; 2 3 import dunitconversion.linearfunction; 4 import dunitconversion.conversionrule; 5 import dunitconversion.tools; 6 7 /** 8 * The ConversionFamily class is an internal class that provides 9 * a conversion by holding all of the conversion rules for a single family 10 */ 11 class ConversionFamily { 12 13 /** 14 * Constructs a family with empty base unit and family name 15 */ 16 this() { 17 18 } 19 20 /** 21 * Constructs a family with the given base unit and family name 22 */ 23 this(string baseUnit, string family) { 24 m_baseUnit = baseUnit; 25 m_family = family; 26 } 27 28 /** 29 * Adds a conversion rule to convertor 30 * Params: rule = rule to add 31 */ 32 void addConversionRule(ConversionRule rule) { 33 if (m_rules is null) 34 { 35 m_family = rule.family; 36 m_baseUnit = rule.baseUnit; 37 } 38 else 39 { 40 if (m_family != rule.family || m_baseUnit != rule.baseUnit) 41 throw new Exception("Incorrect rule added to family"); 42 } 43 m_rules[rule.unit] = rule; 44 } 45 46 /** 47 * Converts from in unit to out unit 48 * Params: 49 * inUnit = unit to convert from 50 * outUnit = unit to convert to 51 * Returns: LinearFunction object containing conversion from in to out unit 52 */ 53 LinearFunction convert(string inUnit, string outUnit) const { 54 if (m_rules is null) 55 throw new Exception("No conversion rules known for " ~ m_family ~ " family"); 56 57 if (inUnit == m_baseUnit && outUnit in m_rules) // conversion from base unit to unit 58 return m_rules[outUnit].convertFunction; 59 if (inUnit in m_rules && outUnit == m_baseUnit) // conversion from unit to base unit 60 return m_rules[inUnit].convertFunction.inversed(); 61 62 // conversion from one unit to another through the base unit if possible 63 if (inUnit !in m_rules || outUnit !in m_rules) // one of the conversions is not present 64 throw new Exception("Conversion from " ~ inUnit ~ " to " ~ outUnit ~ " not found"); 65 LinearFunction inToBase = m_rules[inUnit].convertFunction.inversed(); 66 LinearFunction baseToOut = m_rules[outUnit].convertFunction; 67 68 return combined(inToBase, baseToOut); 69 } 70 71 /** 72 * Converts a given value from in unit to out unit 73 * Params: 74 * value = value to convert 75 * inUnit = unit to convert from 76 * outUnit = unit to convert to 77 * Returns: value converted to 78 */ 79 double convert(double value, string inUnit, string outUnit) const { 80 auto f = convert(inUnit, outUnit); 81 if (f.isValid()) 82 return f.y(value); 83 return double.nan; 84 } 85 86 protected: 87 ConversionRule [string] m_rules; /// Key is a unit, it's assumed that all rules have the same base unit 88 string m_baseUnit; /// Base unit for this family 89 string m_family; /// Family name 90 }