Ejemplo n.º 1
0
        private double GetIntValue(List <string> matchStrs)
        {
            var isEnd = new bool[matchStrs.Count];

            for (var i = 0; i < isEnd.Length; i++)
            {
                isEnd[i] = false;
            }

            double tempValue = 0;
            long   endFlag   = 1;

            //Scan from end to start, find the end word
            for (var i = matchStrs.Count - 1; i >= 0; i--)
            {
                if (RoundNumberSet.Contains(matchStrs[i]))
                {
                    //if false,then continue
                    //You will meet hundred first, then thousand.
                    if (endFlag > config.RoundNumberMap[matchStrs[i]])
                    {
                        continue;
                    }
                    isEnd[i] = true;
                    endFlag  = config.RoundNumberMap[matchStrs[i]];
                }
            }

            if (endFlag == 1)
            {
                var tempStack = new Stack <double>();
                var oldSym    = "";
                foreach (var matchStr in matchStrs)
                {
                    var isCardinal = config.CardinalNumberMap.ContainsKey(matchStr);
                    var isOrdinal  = config.OrdinalNumberMap.ContainsKey(matchStr);
                    if (isCardinal || isOrdinal)
                    {
                        var matchValue = isCardinal
                            ? config.CardinalNumberMap[matchStr]
                            : config.OrdinalNumberMap[matchStr];
                        //This is just for ordinal now. Not for fraction ever.
                        if (isOrdinal)
                        {
                            double fracPart = config.OrdinalNumberMap[matchStr];
                            if (tempStack.Any())
                            {
                                var intPart = tempStack.Pop();
                                // if intPart >= fracPart, it means it is an ordinal number
                                // it begins with an integer, ends with an ordinal
                                // e.g. ninety-ninth
                                if (intPart >= fracPart)
                                {
                                    tempStack.Push(intPart + fracPart);
                                }
                                // another case of the type is ordinal
                                // e.g. three hundredth
                                else
                                {
                                    while (tempStack.Any())
                                    {
                                        intPart = intPart + tempStack.Pop();
                                    }
                                    tempStack.Push(intPart * fracPart);
                                }
                            }
                            else
                            {
                                tempStack.Push(fracPart);
                            }
                        }
                        else if (config.CardinalNumberMap.ContainsKey(matchStr))
                        {
                            if (oldSym.Equals("-"))
                            {
                                var sum = tempStack.Pop() + matchValue;
                                tempStack.Push(sum);
                            }
                            else if (oldSym.Equals(config.WrittenIntegerSeparatorTexts.First()) || tempStack.Count() < 2)
                            {
                                tempStack.Push(matchValue);
                            }
                            else if (tempStack.Count() >= 2)
                            {
                                var sum = tempStack.Pop() + matchValue;
                                sum = tempStack.Pop() + sum;
                                tempStack.Push(sum);
                            }
                        }
                    }
                    else
                    {
                        var complexValue = config.ResolveCompositeNumber(matchStr);
                        if (complexValue != 0)
                        {
                            tempStack.Push(complexValue);
                        }
                    }
                    oldSym = matchStr;
                }

                foreach (var stackValue in tempStack)
                {
                    tempValue += stackValue;
                }
            }
            else
            {
                var    lastIndex = 0;
                double mulValue  = 1;
                double partValue = 1;
                for (var i = 0; i < isEnd.Length; i++)
                {
                    if (isEnd[i])
                    {
                        mulValue  = config.RoundNumberMap[matchStrs[i]];
                        partValue = 1;

                        if (i != 0)
                        {
                            partValue = GetIntValue(matchStrs.GetRange(lastIndex, i - lastIndex));
                        }

                        tempValue += mulValue * partValue;
                        lastIndex  = i + 1;
                    }
                }

                //Calculate the part like "thirty-one"
                mulValue = 1;
                if (lastIndex != isEnd.Length)
                {
                    partValue  = GetIntValue(matchStrs.GetRange(lastIndex, isEnd.Length - lastIndex));
                    tempValue += mulValue * partValue;
                }
            }

            return(tempValue);
        }
        // Same behavior as base but accounts for regional Hindi cases like डेढ/सवा/ढाई
        public override double GetIntValue(List <string> matchStrs)
        {
            var isEnd = new bool[matchStrs.Count];

            for (var i = 0; i < isEnd.Length; i++)
            {
                isEnd[i] = false;
            }

            double tempValue = 0;
            long   endFlag   = 1;

            // Scan from end to start, find the end word
            for (var i = matchStrs.Count - 1; i >= 0; i--)
            {
                var matchI = matchStrs[i].ToLowerInvariant();

                if (RoundNumberSet.Contains(matchI))
                {
                    var mappedValue = Config.RoundNumberMap[matchI];

                    // If false, then continue. Will meet hundred first, then thousand.
                    if (endFlag > mappedValue)
                    {
                        continue;
                    }

                    isEnd[i] = true;
                    endFlag  = mappedValue;
                }
            }

            // If no multiplier found
            if (endFlag == 1)
            {
                var tempStack = new Stack <double>();
                var oldSym    = string.Empty;

                foreach (var matchStr in matchStrs)
                {
                    var isCardinal = Config.CardinalNumberMap.ContainsKey(matchStr);
                    var isOrdinal  = Config.OrdinalNumberMap.ContainsKey(matchStr);

                    if (isCardinal || isOrdinal)
                    {
                        var matchValue = isCardinal ?
                                         Config.CardinalNumberMap[matchStr] :
                                         Config.OrdinalNumberMap[matchStr];

                        // This is just for ordinal now. Not for fractions.
                        if (isOrdinal)
                        {
                            double fracPart = Config.OrdinalNumberMap[matchStr];

                            if (tempStack.Any())
                            {
                                var intPart = tempStack.Pop();

                                // If intPart >= fracPart, it means it is an ordinal number
                                // it begins with an integer, ends with an ordinal
                                // e.g. ninety-ninth
                                if (intPart >= fracPart)
                                {
                                    tempStack.Push(intPart + fracPart);
                                }
                                else
                                {
                                    // Another case where the type is ordinal
                                    // e.g. three hundredth
                                    while (tempStack.Any())
                                    {
                                        intPart = intPart + tempStack.Pop();
                                    }

                                    tempStack.Push(intPart * fracPart);
                                }
                            }
                            else
                            {
                                tempStack.Push(fracPart);
                            }
                        }
                        else if (Config.CardinalNumberMap.ContainsKey(matchStr))
                        {
                            if (oldSym.Equals("-", StringComparison.Ordinal))
                            {
                                var sum = tempStack.Pop() + matchValue;
                                tempStack.Push(sum);
                            }
                            else if (oldSym.Equals(Config.WrittenIntegerSeparatorTexts.First(), StringComparison.Ordinal) || tempStack.Count < 2)
                            {
                                tempStack.Push(matchValue);
                            }
                            else if (tempStack.Count >= 2)
                            {
                                var sum = tempStack.Pop() + matchValue;
                                sum = tempStack.Pop() + sum;
                                tempStack.Push(sum);
                            }
                        }
                    }
                    else
                    {
                        // Used to parse regional Hindi cases like डेढ/सवा/ढाई
                        // They are Indian Language specific cases and holds various meaning when prefixed with Number unit.
                        var complexVal = Config.ResolveUnitCompositeNumber(matchStr);
                        if (complexVal != 0)
                        {
                            tempStack.Push(complexVal);
                        }

                        var complexValue = Config.ResolveCompositeNumber(matchStr);
                        if (complexValue != 0)
                        {
                            tempStack.Push(complexValue);
                        }
                    }

                    oldSym = matchStr;
                }

                foreach (var stackValue in tempStack)
                {
                    tempValue += stackValue;
                }
            }
            else
            {
                var    lastIndex = 0;
                double mulValue  = 1;
                double partValue = 1;
                for (var i = 0; i < isEnd.Length; i++)
                {
                    if (isEnd[i])
                    {
                        mulValue  = Config.RoundNumberMap[matchStrs[i]];
                        partValue = 1;

                        if (i != 0)
                        {
                            partValue = GetIntValue(matchStrs.GetRange(lastIndex, i - lastIndex));
                        }

                        tempValue += mulValue * partValue;
                        lastIndex  = i + 1;
                    }
                }

                // Calculate the part like "thirty-one"
                mulValue = 1;

                if (lastIndex != isEnd.Length)
                {
                    partValue  = GetIntValue(matchStrs.GetRange(lastIndex, isEnd.Length - lastIndex));
                    tempValue += mulValue * partValue;
                }
            }

            return(tempValue);
        }