import 'package:d4rt/d4rt.dart'; import 'package:collection/collection.dart'; import 'package:d4rt_formulas/d4rt_formulas.dart'; class Multimap extends DelegatingMap> { final Map> _map; Multimap(super.map) : _map = map; factory Multimap.create() { return Multimap({}); } @override List? operator [](Object? key) { if (_map.containsKey(key)) { return super[key]; } final List newList = []; super[key as K] = newList; return super[key]; } } class FormulaCorpus{ final Multimap _tags = Multimap.create(); final Map _allFormulas = {}; } class UnitCorpus { final Multimap _baseToUnits = Multimap.create(); final Map _allUnits = {}; void loadUnits(List units, [bool replaceOnDuplicates = false]) { for (final unit in units) { if (!replaceOnDuplicates && _allUnits.containsKey(unit.name)) { throw ArgumentError("Duplicate unit:$unit"); } _allUnits[unit.name] = unit; _baseToUnits[unit.baseUnit]?.add(unit.name); } } List unitsOfSameMagnitude(String unit){ final base = this[unit].baseUnit; return _baseToUnits[base] as List; } UnitSpec operator [](String unit) { if (!_allUnits.containsKey(unit)) { throw ArgumentError("Unit not found:$unit"); } return _allUnits.get(unit); } UnitSpec get(String unit) => this[unit]; String _converterFromCodeString(Number x, String codeString) { final buffer = StringBuffer(); buffer.writeln("final x = ${x};"); buffer.writeln("main(){return $codeString;}"); final code = buffer.toString(); return code; } Number _convertToBase(Number x, String fromUnit) { final unit = this[fromUnit]; if (unit.factorFromUnitToBase != null) { return x * (unit.factorFromUnitToBase as Number); } if (unit.codeFromUnitToBase == null) { throw ArgumentError("Unit has no codeFromUnitToBase: $unit"); } final d4rt = D4rt(); final completeSource = _converterFromCodeString(x, unit.codeFromUnitToBase as String); final ret = d4rt.execute(source: completeSource); return ret as Number; } Number _convertFromBase(Number x, String toUnit) { final unit = this[toUnit]; if (unit.factorFromUnitToBase != null) { return x / (unit.factorFromUnitToBase as Number); } if (unit.codeFromBaseToUnit == null) { throw ArgumentError("Unit has no codeFromBaseToUnit: $unit"); } final d4rt = D4rt(); final completeSource = _converterFromCodeString(x, unit.codeFromBaseToUnit as String); final ret = d4rt.execute(source: completeSource); return ret as Number; } Number convert(Number x, String fromUnit, String toUnit) { final xBase = _convertToBase(x, fromUnit); final xTo = _convertFromBase(xBase, toUnit); return xTo; } Iterable allUnits() => _allUnits.values; }