LCOV - code coverage report
Current view: top level - cell - Reaction.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 40 56 71.4 %
Date: 2025-12-26 22:55:38 Functions: 7 9 77.8 %

          Line data    Source code
       1             : #include "Reaction.hpp"
       2             : #include "ExceptionWithLocation.hpp"
       3             : #include "Hashing.hpp"
       4             : 
       5             : namespace cell
       6             : {
       7             : 
       8           4 : bool operator==(const Reaction& a, const Reaction& b)
       9             : {
      10           8 :     return a.getEduct1() == b.getEduct1() && a.hasEduct2() == b.hasEduct2() &&
      11           8 :            (!a.hasEduct2() || a.getEduct2() == b.getEduct2()) && a.getProduct1() == b.getProduct1() &&
      12          12 :            a.hasProduct2() == b.hasProduct2() && (!a.hasProduct2() || a.getProduct2() == b.getProduct2());
      13             : }
      14             : 
      15           4 : std::string toString(const Reaction& reaction, const DiscTypeRegistry& discTypeRegistry)
      16             : {
      17           4 :     std::string result = discTypeRegistry.getByID(reaction.getEduct1()).getName();
      18             : 
      19           4 :     if (reaction.hasEduct2())
      20           2 :         result += " + " + discTypeRegistry.getByID(reaction.getEduct2()).getName();
      21             : 
      22           4 :     result += " -> " + discTypeRegistry.getByID(reaction.getProduct1()).getName();
      23             : 
      24           4 :     if (reaction.hasProduct2())
      25           2 :         result += " + " + discTypeRegistry.getByID(reaction.getProduct2()).getName();
      26             : 
      27           4 :     return result;
      28           0 : }
      29             : 
      30           0 : bool contains(const Reaction& reaction, DiscTypeID discType)
      31             : {
      32           0 :     return reaction.getEduct1() == discType || reaction.getEduct2() == discType || reaction.getProduct1() == discType ||
      33           0 :            reaction.getProduct2() == discType;
      34             : }
      35             : 
      36          11 : Reaction::Type inferReactionType(bool educt2, bool product2)
      37             : {
      38          11 :     if (!educt2 && !product2)
      39           2 :         return Reaction::Type::Transformation;
      40           9 :     else if (educt2 && !product2)
      41           5 :         return Reaction::Type::Combination;
      42           4 :     else if (!educt2 && product2)
      43           2 :         return Reaction::Type::Decomposition;
      44             :     else
      45           2 :         return Reaction::Type::Exchange;
      46             : }
      47             : 
      48          11 : Reaction::Reaction(DiscTypeID educt1, const std::optional<DiscTypeID>& educt2, DiscTypeID product1,
      49          11 :                    const std::optional<DiscTypeID>& product2, double probability)
      50          11 :     : educt1_(educt1)
      51          11 :     , educt2_(educt2)
      52          11 :     , product1_(product1)
      53          11 :     , product2_(product2)
      54          11 :     , type_(inferReactionType(educt2.has_value(), product2.has_value()))
      55             : {
      56          11 :     setProbability(probability);
      57          11 : }
      58             : 
      59          11 : void Reaction::setProbability(double probability)
      60             : {
      61          11 :     if (probability < 0 || probability > 1)
      62           0 :         throw ExceptionWithLocation("Probability must be between 0 and 1");
      63             : 
      64          11 :     probability_ = probability;
      65          11 : }
      66             : 
      67          15 : void Reaction::validate(const DiscTypeRegistry& discTypeRegistry) const
      68             : {
      69          45 :     auto getMass = [&](DiscTypeID discTypeID) { return discTypeRegistry.getByID(discTypeID).getMass(); };
      70             : 
      71          15 :     const auto eductMassSum = getMass(educt1_) + (educt2_ ? getMass(*educt2_) : 0);
      72          15 :     const auto productMassSum = getMass(product1_) + (product2_ ? getMass(*product2_) : 0);
      73             : 
      74          15 :     if (eductMassSum != productMassSum)
      75           0 :         throw ExceptionWithLocation(toString(*this, discTypeRegistry) +
      76           0 :                                     ": Product- and educt masses need to be identical");
      77             : 
      78          15 :     if (type_ == Type::Transformation && educt1_ == product1_)
      79           0 :         throw ExceptionWithLocation(toString(*this, discTypeRegistry) + ": Educt 1 and product 1 are identical");
      80          15 : }
      81             : 
      82           0 : std::string Reaction::getTypeString() const
      83             : {
      84           0 :     switch (type_)
      85             :     {
      86           0 :     case Reaction::Type::Decomposition: return "Decomposition";
      87           0 :     case Reaction::Type::Transformation: return "Transformation";
      88           0 :     case Reaction::Type::Combination: return "Combination";
      89           0 :     case Reaction::Type::Exchange: return "Exchange";
      90           0 :     case Reaction::Type::None: return "None";
      91           0 :     default: throw ExceptionWithLocation("Invalid reaction type");
      92             :     }
      93             : }
      94             : 
      95             : } // namespace cell

Generated by: LCOV version 1.14