Exemple #1
0
        /// <summary>Gets the chemical formula as a string in Hill notation.</summary>
        /// <param name="chemicalFormula">The chemical formula.</param>
        /// <returns></returns>
        public static string GetChemicalFormulaString(IChemicalFormula chemicalFormula)
        {
            // Local function for converting a single element to a string.
            string GetElementString(IEntityCardinality <IElement> element)
            {
                if (element.Count == 0) // Don't write zero.
                {
                    return(string.Empty);
                }
                if (element.Count == 1) // If the count is 1, just use the symbol.
                {
                    return(element.Entity.Symbol);
                }

                // In all other cases need to write out count too.
                return($"{element.Entity.Symbol}{element.Count}");
            }

            // Main function.
            ICollection <IEntityCardinality <IElement> > elements = chemicalFormula.GetElements().ToList();
            IList <string> elementStrings = new List <string>();

            // Look for carbon first.  If it exists, write it and then hydrogen.
            IEntityCardinality <IElement> carbon = elements.SingleOrDefault(e => e.Entity.AtomicNumber == 6);

            if (carbon != null && carbon.Count > 0)
            {
                elementStrings.Add(GetElementString(carbon));
                elements.Remove(carbon);
                IEntityCardinality <IElement> hydrogen = elements.SingleOrDefault(e => e.Entity.AtomicNumber == 1);
                if (hydrogen != null && hydrogen.Count > 0)
                {
                    elementStrings.Add(GetElementString(hydrogen));
                    elements.Remove(hydrogen);
                }
            }

            // Write out the rest in alphabetical order.
            foreach (IEntityCardinality <IElement> element in elements.OrderBy(e => e.Entity.Symbol))
            {
                if (element.Count > 0)
                {
                    elementStrings.Add(GetElementString(element));
                }
            }

            return(string.Join("", elementStrings));
        }
Exemple #2
0
        private IChemicalFormula SimpleParseTest(string formulaString, params Tuple <string, int>[] elements)
        {
            bool success = ChemicalFormula.TryParseString(formulaString, _elementProvider, out IChemicalFormula chemicalFormula);

            Assert.IsTrue(success);
            Assert.IsNotNull(chemicalFormula);

            IReadOnlyCollection <IEntityCardinality <IElement> > elementCollection = chemicalFormula.GetElements();

            Assert.AreEqual(elements.Length, elementCollection.Count, "Element Count");

            foreach (var(symbol, count) in elements)
            {
                IEntityCardinality <IElement> h = elementCollection.SingleOrDefault(e => e.Entity.Symbol == symbol);
                Assert.IsNotNull(h, $"For element '{symbol}{count}'");
                Assert.AreEqual(count, h.Count, $"For element '{symbol}{count}'");
            }

            return(chemicalFormula);
        }
Exemple #3
0
        private static bool HandleNewElement(ReadOnlySpan <char> formula, IElementProvider elementProvider,
                                             IDictionary <string, IEntityCardinality <IElement> > elementList, int symbolStart, int symbolEnd,
                                             int digitStart, int digitEnd, int isotopeStart, int isotopeEnd)
        {
            if (formula.Length == 0)
            {
                return(false);
            }

            // Handle cardinality
            int count = 1;

            if (digitStart != 0)
            {
                var digitSpan = formula.Slice(digitStart, digitEnd - digitStart + 1);
                if (!int.TryParse(digitSpan, out count))
                {
                    //throw new Exception($"Can't convert {digitSpan.ToString()} to an integer.");
                    return(false);
                }

                if (count == 0)
                {
                    return(true); // A valid cardinality, but nothing should be added to the formula
                }
            }

            // Handle isotopes
            int?isotope = null;

            if (isotopeStart != 0)
            {
                var isotopeSpan = formula.Slice(isotopeStart, isotopeEnd - isotopeStart + 1);
                int isotopeOut;
                if (!int.TryParse(isotopeSpan, out isotopeOut))
                {
                    //throw new Exception($"Can't convert {digitSpan.ToString()} to an integer.");
                    return(false);
                }

                isotope = isotopeOut;
            }

            try
            {
                string symbol = formula.Slice(symbolStart, symbolEnd - symbolStart + 1).ToString();

                var element = GetElement(symbol, isotope, count, elementProvider);

                if (elementList.ContainsKey(element.Entity.Symbol))
                {
                    IEntityCardinality <IElement> entityCardinality = elementList[element.Entity.Symbol];
                    elementList[symbol] = new EntityCardinality <IElement>(entityCardinality.Entity, entityCardinality.Count + count);
                }
                else
                {
                    elementList.Add(element.Entity.Symbol, element);
                }

                return(true);
            }
            catch // Failed to get element for some reason
            {
                return(false);
            }
        }