private Dictionary <string, string> GetStringValues(UnitP unitP)
        {
            Dictionary <string, string> outDict = new Dictionary <string, string>();

            if (unitP.Error.Type != UnitP.ErrorTypes.None)
            {
                outDict.Add("Error", "Error");
            }
            else
            {
                outDict.Add("Value and unit", unitP.ValueAndUnitString);
                outDict.Add("Value", unitP.Value.ToString());
                outDict.Add("Unit prefix", StringRepresentations.GetIndividualUnitOrPrefix(unitP.UnitPrefix));
                outDict.Add("Unit", StringRepresentations.GetIndividualUnitOrPrefix(unitP.Unit));
                outDict.Add("Unit parts", StringRepresentations.GetUnitParts(unitP));
                outDict.Add
                (
                    "System of units",
                    (
                        unitP.Unit == Units.None || unitP.Unit == Units.Unitless ?
                        UnitSystems.None : unitP.UnitSystem
                    )
                    .ToString()
                );
                outDict.Add("Unit type", unitP.UnitType.ToString());
            }

            return(outDict);
        }
            public static string GetUnitParts(UnitP unitP)
            {
                if (unitP.UnitParts.Count == 0)
                {
                    return(GetUnitOrPrefixName(unitP.Unit));
                }
                string output = "";

                foreach (UnitPart part in unitP.UnitParts)
                {
                    if (output != "")
                    {
                        output += ", ";
                    }

                    if (part.Prefix.Factor != 1m)
                    {
                        output += GetUnitOrPrefixName(part.Prefix);
                    }
                    output += GetUnitOrPrefixName(part.Unit);
                    if (part.Exponent != 1m)
                    {
                        output += "^" + part.Exponent.ToString();
                    }
                }

                return(output);
            }
Esempio n. 3
0
        //This method prints the main string representations and some basic information for all the named units.
        //In any case, note that UnitParser supports a wide range of variations which aren't referred here.
        //Examples: plurals of string representation other than symbols or ignoring certain invalid characters
        //(e.g., blank spaces or conventionally-used characters like "^").
        //Additionally, bear in mind that these are just the members of the Units enum, a small fraction of
        //all the units supported by UnitParser. Any unit belonging to a supported type (UnitTypes enum) which
        //is formed by the combination of one or more named units (Units enum) is also supported. For example,
        //the named unit Units.Foot can be part of many other unnamed units like ft/h (velocity), rood*ft (volume)
        //or tn*ft/s2 (force).
        private static void PrintAllNamedUnits()
        {
            foreach (Units unit in Enum.GetValues(typeof(Units)))
            {
                if (unit == Units.None || unit == Units.Unitless)
                {
                    continue;
                }

                UnitTypes   type   = UnitP.GetUnitType(unit);
                UnitSystems system = UnitP.GetUnitSystem(unit);

                if (type == UnitTypes.None)
                {
                    continue;
                }

                Console.WriteLine("Unit: " + unit.ToString());
                Console.WriteLine("Type: " + type.ToString());
                Console.WriteLine("System: " + system.ToString());

                string representations = "";
                foreach (string representation in UnitP.GetStringsForUnit(unit, true))
                {
                    if (representations != "")
                    {
                        representations += ", ";
                    }
                    representations += representation;
                }

                Console.WriteLine("Representations: " + representations);
                Console.WriteLine();
            }
        }
Esempio n. 4
0
 private static void PrintSampleItem(string sampleId, UnitP unitP)
 {
     Console.WriteLine
     (
         sampleId + " - " +
         (
             unitP.Error.Type != UnitP.ErrorTypes.None ?
             "Error. " + unitP.Error.Message :
             unitP.ValueAndUnitString + " (" +
             unitP.Unit.ToString() + ", " +
             unitP.UnitType.ToString() + ", " +
             unitP.UnitSystem.ToString() + ")."
         )
     );
 }
            private static string GetUnitOrPrefixSymbol(Units unit)
            {
                string output = null;

                if (unit == Units.None)
                {
                    return(output);
                }

                var strings = UnitP.GetStringsForUnit(unit);

                if (strings != null && strings.Count > 0)
                {
                    output = strings[0];
                }

                return(output);
            }
Esempio n. 6
0
        public static void StartTest()
        {
            Console.WriteLine("-------------- UnitParser --------------");
            Console.WriteLine();

            //------ The base class is UnitP. There are multiple ways to instantiate a UnitP variable.
            PrintSampleItem("Inst1", new UnitP("1 N"));        //Unit symbol. Case does matter.
            PrintSampleItem("Inst2", new UnitP(1m, UnitSymbols.Newton));
            PrintSampleItem("Inst3", new UnitP(1m, "nEwTon")); //Unit secondary string representation. Case doesn't matter.
            PrintSampleItem("Inst4", new UnitP(Units.Newton)); //Value assumed to be 1.
            PrintSampleItem("Inst5", new UnitP());             //Value and unit assumed to be 1 and unitless, respectively.


            //--- All the public classes support (un)equality comparisons accounting for their more relevant variables.
            if (new UnitP("1 N") == new UnitP(1m, UnitSymbols.Newton) && new UnitP(1m, UnitSymbols.Newton) == new UnitP(1m, "nEwTon") && new UnitP(1m, "nEwTon") == new UnitP(Units.Newton))
            {
                //This condition is true.
            }

            //------ UnitP variables can be seen as abstract concepts including many specific types.

            //--- Same type variables can be added/subtracted.
            PrintSampleItem("Add1", new UnitP("1 N") + new UnitP(1m, UnitSymbols.Newton)); //Both variables have the same type (force).

            //--- Different type variables can be multiplied/divided, but only when the resulting output belongs to a supported type.
            PrintSampleItem("Mult1", new UnitP("1 N") * new UnitP("m")); //N*m = J, what is a supported type (energy).

            //--- Any operation outputting unsupported types triggers an error.
            PrintSampleItem("Mult2", new UnitP("1 N") * new UnitP("1 m") * new UnitP("1 m")); //N*m2 doesn't match any valid type.


            //------ Multiplication/division with decimal/double values is also supported.

            PrintSampleItem("Mult3", new UnitP("1 N") * 1.23456);  //Multiplication involving UnitP and double variables.
            PrintSampleItem("Div1", new UnitP("1 N") / 7.891011m); //Division involving UnitP and decimal variables.

            //--- Dividing a number by a UnitP variable does affect the given unit.
            try
            {
                PrintSampleItem("Div2", 7.891011m / new UnitP("1 N"));
            }
            catch
            {
                //Error because 1/N doesn't represent a supported type.
                //The reasons for the exception are explained below.
                Console.WriteLine("Div2 - Caught Exception.");
            }


            //------ Compounds, unit parts and individual units.

            PrintSampleItem("Ind1", new UnitP("1 sec"));  //s, a valid SI time unit. It is an individual unit (i.e., 1 single unit part whose exponent is 1).
            PrintSampleItem("Comp1", new UnitP("1 m/s")); //m/s, a valid SI velocity unit. It is a compound (i.e., various parts or one with a different-than-1 exponent).
            PrintSampleItem("Comp2", new UnitP("1 N"));   //N, a valid SI force unit. It is a compound with an official name.

            //--- Compounds can be formed through string parsing or arithmetic operations.
            PrintSampleItem("Comp3", new UnitP("1 m") / new UnitP("s")); //m/s, a valid SI velocity unit, created by dividing two UnitP variables.
            PrintSampleItem("Comp4", new UnitP("kg*m/s2"));              //N (= kg*m/s2), a valid SI force unit, created via string parsing.
            if (new UnitP("1 m/sec") == new UnitP("1 m") / new UnitP("s") && new UnitP("1 N") == new UnitP("1 kg*m/s2"))
            {
                //This condition is true.
            }

            //--- It is recommendable to create compounds via strings rather than operations.
            PrintSampleItem("Comp5", new UnitP("1 m") / new UnitP("1 s2")); //Error because s2 doesn't represent a valid type (type check for each UnitP variable).
            PrintSampleItem("Comp6", new UnitP("m/s2"));                    //m/s2, a valid SI acceleration unit (one type check after all the unit operations/simplifications were performed).

            //--- The unit parts are automatically populated when instantiating a valid UnitP variable.
            if (new UnitP("1 N").UnitParts.FirstOrDefault(x => !new UnitP("1 kg*m/s2").UnitParts.Contains(x)) == null)
            {
                //This condition is true.
            }

            //--- When various units have the same constituent parts, the string-based recognition might not match the input unit.
            PrintSampleItem("Comp7", new UnitP("V/m"));              //Understood as NewtonPerCoulomb. Although V/m is a valid SI electric field strength unit, N/C has the same parts and is the default unit under these conditions.
            PrintSampleItem("Comp8", new UnitP(Units.VoltPerMetre)); //Understood as VoltPerMetre. There is no string parsing/unit-part analysis and, consequently, no possible confusion.

            //------ Format of input string units.

            //--- UnitP constructors without numeric inputs expect strings formed by a number (it might be missing) and a unit.
            PrintSampleItem("Str1", new UnitP("10 m")); //10 metre (length).
            PrintSampleItem("Str2", new UnitP("1m"));   //1 metre (length). Since UnitParser.dll v.1.0.6301.23655, there is no need to include a blank space between value and unit.
            PrintSampleItem("Str3", new UnitP("m"));    //1 metre (length).

            //--- Multi-part strings are expected to be formed by units, multiplication/division symbols and integer exponents.
            PrintSampleItem("Str4", new UnitP("1 J/s"));  //1 joule per second (power unit).
            PrintSampleItem("Str5", new UnitP("1 Jxs"));  //1 joule second (angular momentum).
            PrintSampleItem("Str6", new UnitP("1 J⋅s2")); //1 kilogram square metre (moment of inertia).
            PrintSampleItem("Str7", new UnitP("J÷s-2"));  //1 kilogram square metre (moment of inertia).

            //--- Only one division sign is expected. It separates the numerator and denominator parts.
            PrintSampleItem("Str8", new UnitP("1 J*J/s*J2*J-1*s*s-1")); //1 watt (power).
            PrintSampleItem("Str9", new UnitP("J*J/(s*J2*s)*J*s"));     //Error. It is understood as J*J/(s*J2*s*J*s).

            //--- Not-supported-but-commonly-used characters are plainly ignored.
            PrintSampleItem("Str10", new UnitP(1m, "ft."));        //1 foot (length).
            PrintSampleItem("Str11", new UnitP(1m, "ft^2"));       //1 square foot (area).
            PrintSampleItem("Str12", new UnitP(1m, "ft*(ft*ft)")); //1 cubic foot (volume).

            //--- Ideally, no blank spaces should be included. The parser can deal with them anyway.
            PrintSampleItem("Str13", new UnitP(1m, "AU/min"));       //1 astronomical unit per minute (velocity).
            PrintSampleItem("Str14", new UnitP(1m, "A U/     min")); //1 astronomical unit per minute (velocity).


            //------ Format of input string numbers.

            //--- The used culture is always CultureInfo.InvariantCulture (e.g., "." as decimal separator).
            PrintSampleItem("StrNum1", new UnitP("1.1 m")); //Always 1.1 m, independently upon the applicable culture.
            PrintSampleItem("StrNum2", new UnitP("1,1 s")); //Always 11 s, independently upon the applicable culture.

            //--- The differences between double/decimal types are managed internally.
            PrintSampleItem("StrNum3", new UnitP("1.0000000000000001 ft"));                                            //1.0000000000000001 ft.
            PrintSampleItem("StrNum4", new UnitP("1000000000000000000000000000000000000000000000000000000000000 mi")); //1000000*10^54 mi.

            //--- It is also possible to input beyond-double numbers via strings. The exponential format follows the .NET rules.
            PrintSampleItem("StrNum5", new UnitP("9999.99999E1000")); //999999.99*10^998 unitless.
            PrintSampleItem("StrNum6", new UnitP("1234E1.5"));        //Error. Equivalently to what happens with .NET numeric parsing, only integer exponents are supported.


            //------ Errors and exceptions.

            //--- All the error information is stored under UnitPVariable.Error.
            if (new UnitP("1 m/s").Error.Type == UnitP.ErrorTypes.None)
            {
                //This condition is true.
            }
            if (new UnitP("wrong").Error.Type != UnitP.ErrorTypes.None)
            {
                //This condition is true.
            }

            //--- By default, errors don't trigger exceptions.
            PrintSampleItem("Err1", new UnitP("wrong")); //No exception is triggered.

            //--- The default behaviour can be modified when instantiating the variable.
            try
            {
                PrintSampleItem("Err2", new UnitP("wrong", UnitP.ExceptionHandlingTypes.AlwaysTriggerException));
            }
            catch
            {
                //An exception is triggered.
                Console.WriteLine("Err2 - Caught Exception.");
            }

            //--- In case of incompatibility, the configuration of the first operand is applied.
            PrintSampleItem
            (
                "Err3",  //No exception is triggered.
                new UnitP("wrong") *
                new UnitP("1 m", UnitP.ExceptionHandlingTypes.AlwaysTriggerException)
            );

            try
            {
                PrintSampleItem
                (
                    "Err4", //An exception is triggered.
                    new UnitP("1 m", UnitP.ExceptionHandlingTypes.AlwaysTriggerException) *
                    new UnitP("wrong")
                );
            }
            catch
            {
                Console.WriteLine("Err4 - Caught Exception.");
            }

            //--- When the first operand is a number, an exception is always triggered.
            try
            {
                //An exception is triggered.
                PrintSampleItem("Err5", 5.0 * new UnitP("wrong"));
            }
            catch
            {
                Console.WriteLine("Err5 - Caught Exception.");
            }


            //------ Unit prefixes.

            //--- Two types of prefixes are supported: SI and binary.
            PrintSampleItem("Pref1", new UnitP(1m, "km"));  //SI prefix kilo + metre.
            PrintSampleItem("Pref2", new UnitP("1 Kibit")); //Binary prefix Kibi + bit.

            //--- All the prefix-related information is stored under UnitPVariable.UnitPrefix.
            if (new UnitP(1m, "km").UnitPrefix == new UnitP(1m, "ks").UnitPrefix)
            {
                //This condition is true.
            }

            //--- Prefixes are automatically updated/simplified in any operation.
            PrintSampleItem("Pref3", new UnitP("1 kJ"));                                                    //1 kJ.
            PrintSampleItem("Pref4", new UnitP("555 mJ"));                                                  //555 mJ.
            PrintSampleItem("Pref5", new UnitP("0.00000001 MJ"));                                           //0.01 J.
            PrintSampleItem("Pref6", new UnitP("1 kJ") + new UnitP("555 mJ") + new UnitP("0.00000001 MJ")); //1.000565 kJ.

            //--- Prefix symbols are case sensitive, but string representations are not.
            PrintSampleItem("Pref7", new UnitP(1m, "Km"));    //Error.
            PrintSampleItem("Pref8", new UnitP(1m, "mEGam")); //SI prefix mega + metre.

            //--- By default, prefixes can only be used with units which officially/commonly support them.
            PrintSampleItem("Pref9", new UnitP("1 Mft")); //Error because the unit foot doesn't support SI prefixes.
            PrintSampleItem("Pref10", new UnitP("Eim"));  //Error because the unit metre doesn't support binary prefixes.

            //--- The default behaviour can be modified when instantiating the variable.
            PrintSampleItem("Pref11", new UnitP("Mft", PrefixUsageTypes.AllUnits));   //SI prefix mega + foot.
            PrintSampleItem("Pref12", new UnitP("1 Eim", PrefixUsageTypes.AllUnits)); //Binary prefix exbi + metre.

            //--- Same rules apply to officially-named compounds. Non-named compounds recognise prefixes, but don't use them.
            PrintSampleItem("Pref13", new UnitP("1 GN"));                                          //SI prefix giga + newton.
            PrintSampleItem("Pref14", new UnitP(1m, SIPrefixSymbols.Giga + Units.MetrePerSecond)); //1000000*10^3 m/s.

            //--- In certain situations, PrefixUsageTypes.AllUnits doesn't allow to use prefixes.
            PrintSampleItem("Pref15", new UnitP(1m, SIPrefixSymbols.Giga + Units.MetrePerSecond, PrefixUsageTypes.AllUnits)); //Compounds with no official name don't support prefixes.
            PrintSampleItem("Pref16", new UnitP("100000000000 unitless", PrefixUsageTypes.AllUnits));                         //Unitless variables don't support prefixes.

            //--- The unit parts can also have prefixes, which might be compensated with the main prefix.
            PrintSampleItem("Pref17", new UnitP(1m, SIPrefixSymbols.Kilo + UnitSymbols.Newton)); //kN. SI prefix kilo directly affecting the unit newton.
            PrintSampleItem("Pref18", new UnitP("1 Mg*m/s2"));                                   //kN. SI prefix kilo indirectly affecting newton, via one of its constituent parts (kilo-kg = Mg).
            if (new UnitP(1m, SIPrefixSymbols.Kilo + UnitSymbols.Newton) == new UnitP("1 Mg*m/s2"))
            {
                //This condition is true.
                //Note that both UnitP variables being equal implies identical prefixes.
            }


            //------ Systems of units.

            //--- The system is automatically determined at variable instantiation. Each unit can belong to just one system.
            PrintSampleItem("Sys1", new UnitP(Units.MetrePerSquareSecond));        //SI acceleration unit (m/s2).
            PrintSampleItem("Sys2", new UnitP("cm/s2"));                           //CGS acceleration unit (Gal).
            PrintSampleItem("Sys3", new UnitP(1m, UnitSymbols.Rod + "/h2"));       //Imperial acceleration unit (rd/h2).
            PrintSampleItem("Sys4", new UnitP(1m, UnitSymbols.SurveyRod + "/s2")); //USCS acceleration unit (surrd/s2).
            PrintSampleItem("Sys5", new UnitP(1m, "AU/min2"));                     //Acceleration unit not belonging to any system (AU/min2).


            //------ Automatic unit conversions.

            //--- Automatic conversions (to the system of the first operand) happen in operations between a big proportion of different-system units.
            PrintSampleItem("Conv1", new UnitP(1m, Units.Metre) * new UnitP("1 ft"));   //After converting ft to metre, SI area unit m2.
            PrintSampleItem("Conv2", new UnitP(Units.PoundForce) + new UnitP(5m, "N")); //After converting N to lbf, Imperial/USCS force unit lbf.

            //--- Same rules apply to compounds whose unit parts belong to different systems.
            PrintSampleItem("Conv3", new UnitP(1m, "m*lb/s2"));   //After converting lb to kg, SI force unit N.
            PrintSampleItem("Conv4", new UnitP(1m, "surin3/in")); //After converting in to surin, USCS area unit surin2.


            //------ Numeric support.

            //--- UnitP variables support two different numeric types: decimal and double.
            PrintSampleItem("Num1", new UnitP(1.23456m, "m"));      //The UnitP constructor overloads only support decimal type.
            PrintSampleItem("Num2", new UnitP("ft") * 7.891011m);   //Decimal variables can be used in multiplications/divisions.
            PrintSampleItem("Num3", new UnitP("s") * 1213141516.0); //Double variables can be used in multiplications/divisions.

            //--- All the numeric inputs are converted into decimal type. UnitPVariable.BaseTenExponent avoids eventual type-conversion overflow problems.
            PrintSampleItem
            (
                //UnitP variable with a Numeric value notably above decimal.MaxValue.
                "Num4", new UnitP(9999999999999999m, "YAU2", PrefixUsageTypes.AllUnits)
                / new UnitP("0.000000000000001 yf", PrefixUsageTypes.AllUnits)
            );
            PrintSampleItem
            (
                //UnitP variable with a Numeric value notably below decimal.MinValue.
                "Num5", 0.0000000000000000000000000000000000000000000000001 *
                new UnitP(0.000000000000000000001m, "ym2") / new UnitP("999999999999999999999 Ym")
            );


            //------ No unit, unitless & unnamed units.

            //--- No unit (Units.None).
            PrintSampleItem("No1", new UnitP(1m, Units.None)); //Units.None cannot be used as an input.
            PrintSampleItem("No2", new UnitP("1 wrong"));      //Units.None is the unit associated with all the errors.

            //--- Unitless (Units.Unitless).
            PrintSampleItem("No3", new UnitP(1m, Units.Unitless));                     //Units.Unitless can be used as an input.
            PrintSampleItem("No4", new UnitP("5e1234"));                               //Units.Unitless is the unit for purely-numeric calculations.
            PrintSampleItem("No5", new UnitP("5 km") / new UnitP(1m, Units.Unitless)); //Units.Unitless can be used together with other valid units without triggering an error.
            PrintSampleItem("No6", new UnitP("1 ft/m"));                               //Units.Unitless is associated with the output of operations where all the units cancel each other (with or without automatic conversions).

            //--- Unnamed units (Units.Valid[system]Unit).
            PrintSampleItem("No7", new UnitP("yd/s"));                 //All the parsed compounds not matching any named unit are automatically included in this category.
            PrintSampleItem("No8", new UnitP(1m, Units.ValidCGSUnit)); //Error. Unnamed units cannot be used as inputs.


            //------ Public functions.

            //--- All the functions have static/UnitP and non-static/UnitPVariable versions.
            Console.WriteLine
            (
                "Func1 - " + Units.Abampere.ToString() + " -> " +
                string.Join(",", UnitP.GetStringsForUnit(Units.Abampere, true)) //Static method returning all the string representations associated with the input unit.
            );
            Console.WriteLine
            (
                "Func2 - " + Units.Abampere.ToString() + " -> " +
                string.Join(",", new UnitP(1m, Units.Abampere).GetStringsForCurrentUnit(true)) //Non-static method returning all the string representations associated with the current unit.
            );

            //--- The most relevant function is the one performing unit conversions.
            PrintSampleItem("Func3", UnitP.ConvertTo(new UnitP("1 m"), Units.Foot));     //Static version of the unit conversion method.
            PrintSampleItem("Func4", new UnitP("1 m/s").ConvertCurrentUnitTo("ft/h"));   //Non-static version of the unit conversion method.
            PrintSampleItem("Func5", new UnitP("1 m").ConvertCurrentUnitTo(Units.Gram)); //Error. No conversion is possible between different-type units.


            //------ Other FlexibleParser parts.
            //All the FlexibleParser parts are independent among each other and only the corresponding DLL file needs to be referred.
            //On the other, codes relying on various parts can take advantage of certain compatibility among their main classes.

            //--- NumberParser.
            PrintSampleItem("NP1", new UnitP(new Number(123m, 5), Units.Abampere));   //12.3 MabA.
            PrintSampleItem("NP2", new UnitP(new NumberD(0.000000000001, -5), "Gs")); //0.01 µs.
            PrintSampleItem("NP3", new UnitP(new NumberP("Error"), "m/s"));           //Error.


            //-------------------------------------------------------------


            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("Do you want to print all the named units? Y/N");
            string input = Console.ReadLine();

            if (input.ToLower() == "y")
            {
                //--- Printing all the supported named units out.
                PrintAllNamedUnits();
                Console.Read();
            }
            Console.WriteLine();
            Console.WriteLine("------------------------------------------");
            Console.WriteLine();
            Console.ReadLine();
        }
Esempio n. 7
0
 public UnitParserModel(string input)
 {
     UnitP = new UnitP((input == null ? "" : input));
 }