Exemple #1
0
 public ReactionCollector(Mixture mixture)
 {
     m_mixture                     = mixture;
     m_reactions                   = new ArrayList();
     m_reactionInstances           = new ArrayList();
     m_reactionHandler             = OnReactionHappened;
     m_mixture.OnReactionHappened += m_reactionHandler;
 }
Exemple #2
0
        /// <summary>
        /// Causes the reaction to take place, if possible, in (and perform modifications to, the provided target mixture.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        public ReactionInstance React(Mixture target)
        {
            // We will handle a reaction's completion percentage/equilibrium
            // calculation by first using the reverse reaction to move all of
            // the already-existent (in proportion) products over to the
            // reactant side, and then move rxnPct % back to the product side.
            double fwdScale = double.MaxValue;
            double revScale = double.MaxValue;

            if (m_reactants.Count != 0)
            {
                foreach (ReactionParticipant rp in m_reactants)
                {
                    double howMuch = target.ContainedMassOf(rp.MaterialType);
                    if (howMuch > 0 && rp.IsCatalyst)
                    {
                        howMuch = double.MaxValue;
                    }
                    fwdScale = Math.Min(fwdScale, howMuch / rp.Mass);
                    if (s_diagnostics)
                    {
                        _Debug.WriteLine("target contains " + howMuch + " of reactant " + rp.MaterialType.Name + " so fwdScale is " + fwdScale);
                    }
                }
                if (fwdScale == double.MaxValue)
                {
                    fwdScale = 0.0;
                }
            }
            else
            {
                fwdScale = 0.0;
            }
            fwdScale *= m_rxPct;

            if (m_products.Count != 0)
            {
                foreach (ReactionParticipant rp in m_products)
                {
                    double howMuch = target.ContainedMassOf(rp.MaterialType);
                    if (howMuch > 0 && rp.IsCatalyst)
                    {
                        howMuch = double.MaxValue;
                    }
                    revScale = Math.Min(revScale, howMuch / rp.Mass);
                    if (s_diagnostics)
                    {
                        _Debug.WriteLine("target contains " + howMuch + " of product " + rp.MaterialType.Name + " so revScale is " + revScale);
                    }
                }

                if (revScale == double.MaxValue)
                {
                    revScale = 0.0;
                }
            }
            else
            {
                revScale = 0.0;
            }
            revScale *= (1 - m_rxPct);

            // If we're going to undo and then redo the same thing, the reaction didn't happen.
            if ((fwdScale == 0.0 && revScale == 0.0) || (Math.Abs(fwdScale - revScale) < 0.000001))
            {
                if (s_diagnostics)
                {
                    _Debug.WriteLine("Reaction " + Name + " won't happen in mixture " + target);
                }
                return(null);
            }

            if (s_diagnostics)
            {
                _Debug.WriteLine("Mixture is " + target);
            }
            if (s_diagnostics)
            {
                _Debug.WriteLine("Reaction " + Name + " is happening. " + ToString());
            }

            ReactionGoingToHappenEvent?.Invoke(this, target);
            target.ReactionGoingToHappen(this);

            Mixture mixtureWas = (Mixture)target.Clone();

            target.SuspendChangeEvents();

            if (s_diagnostics)
            {
                _Debug.WriteLine(revScale > 0.0 ? "Performing reverse reaction..." : "Reverse reaction won't happen.");
            }
            if (revScale > 0.0)
            {
                React(target, m_products, m_reactants, revScale);
            }

            if (s_diagnostics)
            {
                _Debug.WriteLine(fwdScale > 0.0 ? "Performing forward reaction..." : "Forward reaction won't happen.");
            }
            if (fwdScale > 0.0)
            {
                React(target, m_reactants, m_products, fwdScale * m_rxPct);
            }

            // Percent completion is pulled out of the Reaction object.

            ReactionInstance ri = new ReactionInstance(this, fwdScale, revScale, m_nextRiGuid);

            m_nextRiGuid = GuidOps.Increment(m_nextRiGuid);

            ReactionHappenedEvent?.Invoke(ri);
            target.ReactionHappened(ri);

            target.AddEnergy(m_energy * (fwdScale - revScale));

            target.ResumeChangeEvents(!mixtureWas.ToString("F2", "F3").Equals(target.ToString("F2", "F3"))); // Only emit summary events if the mixture has changed.

            return(ri);
        }