Example #1
0
        /// <summary>
        /// Gets the material to be transferred by extracting it from the source material.
        /// </summary>
        /// <param name="source">The material from which the transfer is to be made.</param>
        /// <returns>The material to be transferred.</returns>
        public virtual IMaterial GetExtract(IMaterial source)
        {
            IMaterial retval = null;

            if (m_materialType == null)
            {
                double massToRemove = source.Mass * Percentage;
                if (source is Substance)
                {
                    retval = ((Substance)source).Remove(massToRemove);
                }
                else
                {
                    retval = ((Mixture)source).RemoveMaterial(massToRemove);
                }
            }
            else
            {
                if (source is Substance)
                {
                    Substance s = ((Substance)source);
                    if (s.MaterialType.Equals(m_materialType))
                    {
                        retval = s.Remove(s.Mass * m_percentage);
                    }
                    else
                    {
                        retval = m_materialType.CreateMass(0, 0);
                    }
                }
                else if (source is Mixture)
                {
                    Mixture m = ((Mixture)source);
                    retval = m.RemoveMaterial(m_materialType, m.ContainedMassOf(m_materialType) * m_percentage);
                    if (retval == null)
                    {
                        retval = m_materialType.CreateMass(0, 0);
                    }
                }
                else
                {
                    throw new ApplicationException("Attempt to remove an unknown implementer of IMaterial from a mixture!");
                }
            }

            m_actualMass = retval.Mass;
            m_duration   = TimeSpan.FromTicks((long)(m_durationPerKilogram.Ticks * retval.Mass));
            return(retval);
        }
Example #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);
        }