Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'AVCS Voice Calculator & Conversions (v1.1) -- Calculate expressions with up to 2 operations and 3 values "Any way you say it"
- 'by SemlerPDX Mar2020/Mar2021
- 'VETERANS-GAMING.COM
- 'demonstration video on youtube: https://youtu.be/bCjuYh92M-I
- 'When I say: *[divided by;divide by;divided that;divide that;divided;divide;multiply;times;multiplied by;multiply that;multiplied that;times that;add;add that;added that;plus;subtract;subtracted;minus;% of;to the power of;percent of;swear;square;square root of;square of;squared;cubed;cube;cuban;° c;° f;kelvin;celcius;celsius;centigrade;fahrenheit;kelvin;calvin;cm;centimeters;centimetres;inches;foot;feet;meters;metres;yards;yours;miles;km;kilometers;kilometres;feet per second;mph;miles per hour;kph;kilometers per hour;kilometres per hour;knots;mach;mock;mark]*;*[-1;-2;-3;-4;-5;-6;-7;-8;-9]*
- 'Set text [~avcs_cmd] to '{TXTWORDTONUM:"{CMD}"}' (Trim) (Lower Case)
- ' (and the next action is to run this inline, after that, just says the result with TTS)
- Imports Microsoft.VisualBasic
- Imports System
- Imports System.Linq
- Imports System.Math
- Imports System.Globalization
- Public Class VAInline
- dim decimalSeparator as string = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator
- dim decimalPlaces as Int32 = 3 'Default = 3 | rounds results -- change via voice command 'Set Decimal Places [to;] [0..16]'
- 'Operational Keyword Arrays
- dim OperatorsArray() as string = {
- "divided",
- "divide",
- "times",
- "multiplied",
- "multiply",
- "add",
- "plus",
- "subtract",
- "subtracted",
- "minus",
- "-",
- "%",
- "percent",
- "power",
- "square",
- "squared",
- "squareroot",
- "cubed",
- "cubes",
- "cube",
- "cuban",
- "cuba"
- }
- dim ConvertorsArray() as string = {
- "c",
- "f",
- "k",
- "cm",
- "celsius",
- "celcius",
- "centigrade",
- "fahrenheit",
- "kelvin",
- "calvin",
- "inches",
- "centimeters",
- "centimetres",
- "foot",
- "feet",
- "m",
- "meters",
- "metres",
- "yards",
- "yours",
- "miles",
- "km",
- "kilometers",
- "kilometres",
- "fps",
- "feetpersecond",
- "mps",
- "meterspersecond",
- "metrespersecond",
- "mph",
- "milesperhour",
- "kph",
- "kilometersperhour",
- "kilometresperhour",
- "knots",
- "mach",
- "mark",
- "mock"
- }
- dim OpsArray() as string = {
- "sum",
- "sub",
- "prd",
- "dif",
- "exp",
- "per",
- "sqr"
- }
- dim DoubleOpsArray() as string = {
- "sum",
- "sub",
- "prd",
- "dif"
- }
- dim SymbolsArray() as string = {
- "°",
- "%",
- "^",
- "-",
- ":",
- "$",
- "£",
- "€",
- "¢",
- "¥",
- "ƒ"
- }
- dim PiArray() as string = {
- "pi",
- "pie",
- "tie",
- "high",
- "bye",
- "eye",
- "espy",
- "pine",
- "pied",
- "ply",
- "tie"
- }
- 'Speech Parsing Vars
- dim cmd as string = ""
- dim charArray() as char
- dim cmdSegments() as string
- 'Values Decimal Vars
- dim operand1 as decimal?
- dim operand2 as decimal?
- dim operand3 as decimal?
- dim operandLast as decimal?
- dim result as decimal?
- dim resultLast as decimal?
- 'Operations String Vars
- dim operator1 as string
- dim operator2 as string
- dim operatorText1 as string = ""
- dim operatorText2 as string = ""
- dim equationText as string = ""
- 'Calc Systems Vars
- dim operationsOrder as integer = 0
- dim countHistory as integer = 1
- dim countFaults as integer = 0
- dim randomText as string
- dim subReverse as boolean
- dim calcActive as boolean
- 'Function to remove spaces from keywords, handle homophones & edge case words
- Private Function ReplaceEdgeCaseWords(ByRef cmd as string)
- if (cmd.StartsWith("ad "))
- cmd = cmd.Replace("ad ","add ")
- end if
- cmd = cmd.Replace(
- " too "," to "
- ).Replace(
- "swear ","square "
- ).Replace(
- "square root","squareroot"
- ).Replace(
- "to the power","power"
- ).Replace(
- "to value"," value"
- ).Replace(
- "2 value"," value"
- ).Replace(
- "value ","value"
- ).Replace(
- "to that"," that"
- ).Replace(
- "2 that"," that"
- ).Replace(
- " tell them"," kelvin"
- ).Replace(
- " per ","per"
- ).Replace(
- " ad "," add "
- ).Replace(
- "added to","add "
- ).Replace(
- "added 2","add "
- ).Replace(
- "added ","add "
- ).Replace(
- "add that 2","add that "
- ).Replace(
- "add that to","add that "
- ).Replace(
- "÷"," divided by "
- ).Replace(
- "¼","0.25"
- ).Replace(
- "½","0.5"
- ).Replace(
- "¾","0.75"
- )
- end function
- 'Function to fix large number separators by culture
- Private Function FixLargeNumberSeparator(ByRef cmd as string)
- 'ex. (7,000.32 into 7000.32) [or] (7.000,32 into 7000,32)
- if ((cmd.Contains(".")) or (cmd.Contains(",")))
- if (decimalSeparator <> ".")
- if (cmd.Contains("."))
- cmd = cmd.Replace(".","")
- end if
- elseif (decimalSeparator <> ",")
- if (cmd.Contains(","))
- cmd = cmd.Replace(",","")
- end if
- end if
- end if
- end function
- 'Function to transform large number words and concat with the number said just before
- Private Function FixLargeWordNum(ByRef largeType as string, ByRef lastNum as decimal?)
- select case largeType
- case "million"
- lastNum *= 1000000
- case "billion"
- lastNum *= 1000000000
- case "trillion"
- lastNum *= 1000000000000
- case "quadrillion"
- lastNum *= 1000000000000000
- case else
- largeType = "AVCS Calculation Error - unable to resolve '" + lastNum.ToString() + " " + largeType + "' as an opperand"
- end select
- end function
- 'Function to test for "by" as Pi in specific cases
- Private Function HasPi(ByVal operatorName as string)
- if (not((operatorName.Contains("root")) or (operatorName.StartsWith("square")) or (operatorName.StartsWith("cub"))))
- cmd = cmd.Replace(" "," ").Replace(" "," ").Replace("divided by","").Replace("divide by","").Replace("multiplied by","").Replace("multiply by","").Replace("that by","")
- if ((cmd.StartsWith("by ")) or (cmd.Contains(" by ")) or (cmd.EndsWith(" by")))
- Return true
- end if
- end if
- end function
- 'Function to set keyword and readable text/symbol for Operators
- Private Function SetOperator(ByRef operatorName as string, ByRef operatorText as string)
- if ((operatorName.Contains("%")) or (operatorName.Contains("percent")))
- operatorText = "% of"
- operatorName = "per"
- elseif (operatorName.StartsWith("divide"))
- operatorText = "/"
- operatorName = "dif"
- elseif ((operatorName.Contains("times")) or (operatorName.StartsWith("multipl")))
- operatorText = "x"
- operatorName = "prd"
- elseif ((operatorName.Contains("plus")) or (operatorName.StartsWith("add")))
- operatorText = "+"
- operatorName = "sum"
- elseif ((operatorName.StartsWith("subtract")) or (operatorName.Contains("minus")) or (operatorName.Contains("-")))
- operatorText = "-"
- operatorName = "sub"
- elseif (operatorName.Contains("power"))
- operatorText = "ⁿ" 'to the power of
- operatorName = "exp"
- elseif (operatorName.Contains("squareroot"))
- operatorText = "√" 'the square root of
- operatorName = "sqr"
- elseif (operatorName.StartsWith("square"))
- operatorText = "²" 'squared
- operatorName = "exp"
- elseif (operatorName.StartsWith("cub"))
- operatorText = "³" 'cubed
- operatorName = "exp"
- end if
- end function
- 'Function to set keyword and readable text/symbol for Conversions
- Private Function SetConvertor(ByRef operatorName as string, ByRef operatorText as string)
- 'VELOCITY CONVERSIONS==============
- if ((operatorName.Contains("fps")) or (operatorName.Contains("feetpersecond")))
- operatorText = "feet per second"
- operatorName = "fps2"
- elseif ((operatorName.Contains("mps")) or (operatorName.Contains("meterspersecond")) or (operatorName.Contains("metrespersecond")))
- operatorText = "meters per second"
- operatorName = "mps2"
- elseif ((operatorName.Contains("mph")) or (operatorName.Contains("milesperhour")))
- operatorText = "miles per hour"
- operatorName = "mph2"
- elseif ((operatorName.Contains("kph")) or (operatorName.Contains("kilometersperhour")) or (operatorName.Contains("kilometresperhour")))
- operatorText = "kilometers per hour"
- operatorName = "kph2"
- elseif (operatorName.Contains("knots"))
- operatorText = "knots"
- operatorName = "kts2"
- elseif ((operatorName.Contains("mach")) or (operatorName.Contains("mock")) or (operatorName.Contains("mark")))
- operatorText = "mach"
- operatorName = "mch2"
- 'DISTANCE CONVERSIONS==============
- elseif (operatorName.Contains("inches"))
- operatorText = "inches"
- operatorName = "in2"
- elseif ((operatorName.Contains("cm")) or (operatorName.Contains("centimeters")) or (operatorName.Contains("centimetres")))
- operatorText = "centimeters"
- operatorName = "cm2"
- elseif ((operatorName.Contains("feet")) or (operatorName.Contains("foot")))
- operatorText = "feet"
- operatorName = "ft2"
- elseif ((operatorName.Contains("yards")) or (operatorName.Contains("yours")))
- operatorText = "yards"
- operatorName = "yd2"
- elseif ((operatorName.Contains("km")) or (operatorName.Contains("kilometers")) or (operatorName.Contains("kilometres")))
- operatorText = "kilometers"
- operatorName = "km2"
- elseif ((operatorName.Contains("mi")) or (operatorName.Contains("miles")))
- operatorText = "miles"
- operatorName = "mi2"
- elseif ((operatorName.Contains("meters")) or (operatorName.Contains("metres")))
- operatorText = "meters"
- operatorName = "mt2"
- 'TEMPERATURE CONVERSIONS==============
- elseif (operatorName.Contains("fahrenheit"))
- operatorText = "degrees fahrenheit"
- operatorName = "f2"
- elseif ((operatorName.Contains("celcius")) or (operatorName.Contains("celsius")))
- operatorText = "degrees celcius"
- operatorName = "c2"
- elseif (operatorName.Contains("centigrade"))
- operatorText = "degrees centigrade"
- operatorName = "c2"
- elseif ((operatorName.Contains("kelvin")) or (operatorName.Contains("calvin")))
- operatorText = "kelvin"
- operatorName = "k2"
- end if
- end function
- 'Main Maths Function
- Private Function GetResult(ByVal ops as string, ByVal val1 as decimal?, Optional ByVal val2 as decimal? = 0)
- select case ops
- case "sum"
- val1 += val2
- case "sub"
- val1 -= val2
- case "prd"
- val1 *= val2
- case "dif"
- val1 /= val2
- case "per"
- val1 *= (val2 / 100)
- case "exp"
- val1 = Pow(val1, val2)
- case "sqr"
- val1 = Sqrt(val1)
- case else
- val1 = nothing
- end select
- Return val1
- end function
- 'Main Conversions Function
- Private Function GetConversion(ByVal ops as string, ByVal val as decimal?)
- select case ops
- '==DISTANCE===========
- 'inches
- case "in2cm"
- val *= 0.393701
- case "in2ft"
- val *= 0.0833333
- case "in2mt"
- val *= 0.0254
- case "in2yd"
- val *= 0.0277778
- case "in2km"
- val /= 39370
- case "in2mi"
- val /= 63360
- 'cm
- case "cm2in"
- val *= 0.393701
- case "cm2ft"
- val *= 0.0328084
- case "cm2mt"
- val /= 100
- case "cm2yd"
- val *= 0.0109361
- case "cm2km"
- val /= 100000
- case "cm2mi"
- val /= 160934
- 'ft
- case "ft2in"
- val *= 12
- case "ft2cm"
- val *= 30.48
- case "ft2mt"
- val *= 0.3048
- case "ft2yd"
- val *= 0.333333
- case "ft2km"
- val /= 3280.84
- case "ft2mi"
- val /= 5280
- 'mt
- case "mt2in"
- val *= 39.3701
- case "mt2cm"
- val *= 100
- case "mt2ft"
- val *= 3.28084
- case "mt2yd"
- val *= 1.09361
- case "mt2km"
- val /= 1000
- case "mt2mi"
- val /= 1609
- 'yd
- case "yd2in"
- val *= 36
- case "yd2cm"
- val *= 91.44
- case "yd2ft"
- val *= 3
- case "yd2mt"
- val *= 0.9144
- case "yd2km"
- val /= 1093.61
- case "yd2mi"
- val /= 1760
- 'km
- case "km2in"
- val *= 39370.1
- case "km2cm"
- val *= 100000
- case "km2ft"
- val *= 3280.84
- case "km2mt"
- val *= 1000
- case "km2yd"
- val *= 1093.61
- case "km2mi"
- val *= 0.621371
- 'miles
- case "mi2in"
- val *= 63360
- case "mi2cm"
- val *= 160934.4
- case "mi2ft"
- val *= 5280
- case "mi2mt"
- val *= 1609.34
- case "mi2yd"
- val *= 1760
- case "mi2km"
- val *= 1.60934
- '==VELOCITY===========
- 'fps
- case "fps2mps"
- val *= 0.3048
- case "fps2kph"
- val *= 1.09728
- case "fps2mph"
- val *= 0.681818
- case "fps2kts"
- val *= 0.592484
- case "fps2mch"
- val *= 0.00088863
- 'mps
- case "mps2fps"
- val *= 3.28084
- case "mps2kph"
- val *= 3.6
- case "mps2mph"
- val *= 2.23694
- case "mps2kts"
- val *= 1.94384
- case "mps2mch"
- val *= 0.00291545
- 'kph
- case "kph2fps"
- val *= 0.911344
- case "kph2mps"
- val *= 0.277778
- case "kph2mph"
- val *= 0.6214
- case "kph2kts"
- val *= 1.852
- case "kph2mch"
- val *= 1234.8
- 'mph
- case "mph2fps"
- val *= 1.46667
- case "mph2mps"
- val *= 0.44704
- case "mph2kph"
- val *= 1.60934
- case "mph2kts"
- val *= 0.868976
- case "mph2mch"
- val *= 0.00130332
- 'knots
- case "kts2fps"
- val *= 1.68781
- case "kts2mps"
- val *= 0.514444
- case "kts2mph"
- val *= 1.15078
- case "kts2kph"
- val *= 1.852
- case "kts2mch"
- val *= 0.0015
- 'mach
- case "mch2fps"
- val *= 1125.33
- case "mch2mps"
- val *= 343
- case "mch2mph"
- val *= 767.269
- case "mch2kph"
- val *= 1234.8
- case "mch2kts"
- val *= 666.73866
- '==TEMPERATURE===========
- 'f
- case "f2c"
- val = ((val - 32) * 5) / 9
- case "f2k"
- val = ((val + 459.67) * 5) / 9
- 'c
- case "c2f"
- val = ((val * 9) / 5) + 32
- case "c2k"
- val = ((val * 9) / 5) + 32
- val = ((val + 459.67) * 5) / 9
- 'kelvin
- case "k2f"
- val = ((val * 9) / 5) - 459.67
- case "k2c"
- val = ((val * 9) / 5) - 459.67
- val = ((val - 32) * 5) / 9
- case else
- val = nothing
- end select
- Return val
- end function
- Public Sub Main()
- VA.SetText("avcs_calc_return", nothing)
- 'Debugging and Testing Check (bypassed if called via spoken command)
- dim cmdTest as string = vaProxy.Utility.ParseTokens("{CMD}")
- if (cmdTest = "")
- VA.SetText("~avcs_cmd", "by the way what is 3 plus 3 times by")
- VA.SetInt("AVCS_CALC_ResultsDecimalPlaces", 2)
- else
- 'Check Calc Mode state, exit if off
- if ((VA.GetBoolean("AVCS_CALC_MODE_ON")) isNot nothing)
- calcActive = VA.GetBoolean("AVCS_CALC_MODE_ON")
- end if
- 'Provide Message for wildcard recognition when Calculator Mode OFF (infrequent prompt in case user does not know)
- if (not(calcActive))
- if ((VA.GetInt("AVCS_CALC_FAULT")) isNot nothing)
- countFaults = VA.GetInt("AVCS_CALC_FAULT") + 1
- if (countFaults >= 3)
- if (countFaults >= 15)
- VA.WriteToLog("Calculation recognized, but won't be computed (this is common when calculator is OFF)", "purple")
- VA.SetInt("AVCS_CALC_FAULT", nothing)
- countFaults = 0
- end if
- else
- randomText = "Calculator is OFF. To enable, say, '" + vaProxy.Utility.ParseTokens("{TXTRANDOM:Enable;Begin;Turn On;Start}") + " Voice Calculator'"
- VA.WriteToLog(randomText, "purple")
- end if
- VA.SetInt("AVCS_CALC_FAULT", countFaults)
- else
- VA.SetInt("AVCS_CALC_FAULT", 1)
- end if
- 'Exit Calc Function when Mode OFF
- Exit Sub
- end if
- end if
- 'Get Custom Decimal Place Settings (if exists)
- if ((VA.GetInt("AVCS_CALC_ResultsDecimalPlaces")) isNot nothing)
- decimalPlaces = Convert.ToInt32(VA.GetInt("AVCS_CALC_ResultsDecimalPlaces"))
- end if
- 'Parse Spoken Command for Equation(s)
- if ((VA.GetText("~avcs_cmd")) isNot nothing)
- cmd = VA.GetText("~avcs_cmd")
- 'Process spoken command formatting and keywords
- ReplaceEdgeCaseWords(cmd)
- FixLargeNumberSeparator(cmd)
- if (cmd.StartsWith("fore to"))
- cmd = cmd.Substring(7, cmd.Length - 7)
- elseif (cmd.StartsWith("for to"))
- cmd = cmd.Substring(6, cmd.Length - 6)
- elseif (cmd.StartsWith("or to"))
- cmd = cmd.Substring(5, cmd.Length - 5)
- elseif (cmd.StartsWith("1 is"))
- cmd = cmd.Substring(4, cmd.Length - 4)
- end if
- 'Evaluate spoken command split at each character and space out symbols
- charArray = cmd.ToCharArray
- cmd = ""
- for each character as string in charArray
- if (SymbolsArray.Contains(character))
- cmd += " " + character.ToString() + " "
- else
- cmd += character.ToString()
- end if
- next
- 'Evaluate all segments of speech split at {SPACE} and parse for operands and operators
- cmdSegments = cmd.Split(New String() {" "},StringSplitOptions.None)
- for each segment as string in cmdSegments
- if (segment <> "")
- 'Handle numbers recognized as homophone words
- select case segment
- case "too"
- segment = "2"
- case "to"
- segment = "2"
- case "trees"
- segment = "3"
- case "tree"
- segment = "3"
- case "fore"
- segment = "4"
- case "for"
- segment = "4"
- case "ate"
- segment = "8"
- case "ape"
- segment = "8"
- case "valuetoo"
- segment = "value2"
- case "valueto"
- segment = "value2"
- case "valuetrees"
- segment = "value3"
- case "valuetree"
- segment = "value3"
- case "valuefore"
- segment = "value4"
- case "valuefor"
- segment = "value4"
- case "valueate"
- segment = "value8"
- end select
- 'Handle short form of convertors
- select case segment
- case "c"
- segment = "celcius"
- case "f"
- segment = "fahrenheit"
- case "k"
- segment = "kelvin"
- case "m"
- segment = "meters"
- end select
- 'Handle "subtract A from B" order of operations error
- if (segment.Contains("from"))
- if ((operand2 is nothing) and(operand1 isNot nothing) and ((operator1 isNot nothing) and (operator1.Contains("subtract"))))
- subReverse = true
- end if
- end if
- 'Handle "that" reference to last calculation result
- if (segment.Contains("that"))
- if ((VA.GetDecimal("AVCS_CALC_LastResult")) isNot nothing)
- segment = VA.GetDecimal("AVCS_CALC_LastResult").ToString()
- end if
- end if
- 'Handle "value" reference to previous calculation result
- if ((segment.StartsWith("value")) and (IsNumeric(segment.Substring(segment.Length - 1, 1))))
- if ((VA.GetDecimal(segment)) isNot nothing)
- segment = VA.GetDecimal(segment).ToString()
- else
- VA.WriteToLog(segment + " does not exist in memory", "red")
- Exit Sub
- end if
- end if
- 'Handle negative temperatures
- if ((operator2 isNot nothing) and (operand1 isNot nothing))
- if ((operationsOrder = 2) and (ConvertorsArray.Contains(operator2)))
- operator1 = operator2
- operator2 = nothing
- operand1 -= (operand1 * 2)
- operationsOrder = 5
- end if
- end if
- 'Handle "pi" and homophone variants
- if (PiArray.Contains(segment))
- if (operand1 is nothing)
- operand1 = Pi
- elseif (operand2 is nothing)
- operand2 = Pi
- elseif (operand3 is nothing)
- operand3 = Pi
- end if
- 'Set Operands -------
- elseif ((IsNumeric(segment)) and (operand1 is nothing))
- try
- operand1 = Convert.ToDecimal(segment)
- operandLast = operand1
- if (operationsOrder = 0)
- operationsOrder = 1 'for edge case: (b = Pi)
- end if
- catch
- VA.WriteToLog("AVCS Calculation Error at Operand 1", "red")
- end try
- elseif ((IsNumeric(segment)) and (operand2 is nothing))
- try
- operand2 = Convert.ToDecimal(segment)
- operandLast = operand2
- catch
- VA.WriteToLog("AVCS Calculation Error at Operand 2", "red")
- end try
- elseif ((IsNumeric(segment)) and (operand3 is nothing))
- try
- operand3 = Convert.ToDecimal(segment)
- operandLast = operand3
- catch
- VA.WriteToLog("AVCS Calculation Error at Operand 3", "red")
- end try
- 'Set Operators -------
- elseif ((OperatorsArray.Contains(segment)) and (operator1 is nothing))
- operator1 = segment
- if (operationsOrder = 0)
- operationsOrder = 2 'for edge case: (a = Pi)
- end if
- elseif ((OperatorsArray.Contains(segment)) and (operator2 is nothing))
- operator2 = segment
- if ((operationsOrder = 1) and (operand2 isNot nothing))
- operationsOrder = 3 'for edge case: (c = b and b = Pi)
- elseif ((operationsOrder = 1) and (operand2 is nothing))
- operationsOrder = 4 'for edge case: (c = Pi)
- end if
- 'Set Convertors -------
- elseif ((ConvertorsArray.Contains(segment)) and (operator1 is nothing))
- operator1 = segment
- operationsOrder = 5 'for edge case null: (no way Pi)
- elseif ((ConvertorsArray.Contains(segment)) and (operator2 is nothing))
- operator2 = segment
- 'Handle "..illions" -------
- elseif (segment.EndsWith("illion"))
- if ((operand1 isNot nothing) and (operandLast = operand1))
- FixLargeWordNum(segment,operand1)
- elseif ((operand2 isNot nothing) and (operandLast = operand2))
- FixLargeWordNum(segment,operand2)
- elseif ((operand3 isNot nothing) and (operandLast = operand3))
- FixLargeWordNum(segment,operand3)
- end if
- if (segment.StartsWith("AVCS Calculation Error"))
- VA.WriteToLog(segment, "red")
- Exit Sub
- end if
- end if
- end if
- next
- 'Evaluate for Pi recognized as "by" (edge cases)
- if (operationsOrder < 5)
- '-- 1 operation catch
- if ((operator2 is nothing) and (operand2 is nothing))
- if (HasPi(operator1))
- if (operationsOrder = 1)
- operand2 = Pi
- elseif (operationsOrder = 2)
- operand2 = operand1
- operand1 = Pi
- end if
- end if
- '-- 2 operations catch
- elseif ((operator2 isNot nothing) and (operand3 is nothing))
- if ((HasPi(operator1)) or (HasPi(operator2)))
- if (operationsOrder = 4)
- operand3 = operand2
- operand2 = Pi
- elseif (operationsOrder = 3)
- operand3 = Pi
- elseif (operationsOrder = 2)
- operand3 = operand2
- operand2 = operand1
- operand1 = Pi
- end if
- end if
- end if
- end if
- 'Evaluate Operator 1 ======
- if (operator1 isNot nothing)
- 'Handle null operands on Squared/Cubed operators
- if ((operator1.StartsWith("square")) and (not(operator1.Contains("root"))))
- operand2 = 2
- elseif (operator1.StartsWith("cub"))
- operand2 = 3
- 'Handle Reverse order of operations on Subtract
- elseif ((operator1.Contains("subtract")) and (subReverse))
- dim operand4 as decimal? = operand2
- operand2 = operand1
- operand1 = operand4
- end if
- 'Set Operator 1 keyword and get text form of Operator/Convertor
- if (not(OperatorsArray.Contains(operator1)))
- SetConvertor(operator1,operatorText1)
- else
- SetOperator(operator1,operatorText1)
- end if
- else
- VA.WriteToLog("AVCS Calculation Error on Null Operator 1", "red")
- Exit Sub
- end if
- 'Evaluate Operator 2 ======
- if (operator2 isNot nothing)
- 'Handle null operands on Squared/Cubed operators
- if ((operator2.StartsWith("square")) and (not(operator2.Contains("root"))))
- operand3 = 2
- elseif (operator2.Contains("cub"))
- operand3 = 3
- end if
- 'Set Operator 2 keyword and get text form of Operator/Convertor
- if (not(OpsArray.Contains(operator1)))
- SetConvertor(operator2,operatorText2)
- operator1 = operator1 + operator2.Substring(0, operator2.Length - 1)
- operator2 = nothing
- else
- SetOperator(operator2,operatorText2)
- 'Calculate Square Root on Multi-Part Equation to avoid errors on null operand3
- 'ex. 200 subtract square root of 128 = 188.69 = a-(Sqrt(b))
- if ((operator2 = "sqr") and (operand3 is nothing))
- equationText = operand1.ToString() + " " + operatorText1 + " " + operatorText2 + " " + operand2.ToString() + " "
- operand2 = Sqrt(operand2)
- operator2 = nothing
- 'Calculate Percentage before to avoid order of operations and text display errors
- 'ex. 200 subtract 20 % = 160 = a-(b*(a/100))
- elseif ((operator2 = "per") and (operand3 is nothing))
- equationText = operand1.ToString() + " " + operatorText1 + " " + operand2.ToString() + " " + operatorText2 + " " + operand1.ToString() + " "
- operand3 = operand1
- operand2 = operand2*(operand3 / 100)
- operand3 = nothing
- operator2 = nothing
- 'ex. 200 subtract 20 % of 100 = 180 = a-(b*(c/100)
- elseif ((operator2 = "per") and (operand3 isNot nothing))
- equationText = operand1.ToString() + " " + operatorText1 + " " + operand2.ToString() + " " + operatorText2 + " " + operand3.ToString() + " "
- operand2 = operand2*(operand3 / 100)
- operand3 = nothing
- operator2 = nothing
- 'Calculate Exponents before to avoid order of operations and text display errors
- 'ex. 4 plus 7 to the power of 3 = 347 = a+(b^c)
- elseif (((operator2 = "exp") and (operatorText2.StartsWith("to"))) and (operand3 isNot nothing))
- equationText = operand1.ToString() + " " + operatorText1 + " " + operand2.ToString() + " " + operatorText2 + " " + operand3.ToString() + " "
- operand2 = Pow(operand2, operand3)
- operand3 = nothing
- operator2 = nothing
- 'ex. 4 plus 7 cubed = 347 = a+b³ [or] 4 plus 7 squared = 53 = a+b²
- elseif (((operator2 = "exp") and (not(operatorText2.StartsWith("to")))) and (operand3 isNot nothing))
- equationText = operand1.ToString() + " " + operatorText1 + " " + operand2.ToString() + " " + operatorText2 + " "
- operand2 = Pow(operand2, operand3)
- operand3 = nothing
- operator2 = nothing
- end if
- end if
- end if
- 'Final Evaluation for "8" recognized as "a"
- if ((DoubleOpsArray.Contains(operator1)) and (operator2 is nothing) and (operand1 isNot nothing) and (operand2 is nothing))
- if ((cmd.Contains(" a ")) or (cmd.EndsWith(" a")))
- if (operationsOrder = 1)
- operand2 = 8
- else
- operand2 = operand1
- operand1 = 8
- end if
- end if
- end if
- '==CALCULATE RESULT==
- if (OpsArray.Contains(operator1))
- 'Build Equation Text for display in VA Event log
- if (equationText = "")
- if (operand1 isNot nothing)
- equationText += operand1.ToString() + " "
- end if
- if (operator1 isNot nothing)
- equationText += operatorText1 + " "
- end if
- if (operand2 isNot nothing)
- equationText += operand2.ToString() + " "
- end if
- if (operator2 isNot nothing)
- equationText += operatorText2 + " "
- end if
- if (operand3 isNot nothing)
- equationText += operand3.ToString() + " "
- end if
- 'Calculate Square Root on Multi-Part Equation to avoid incorrect operations math and display text
- 'ex. square root of 144 times 7 = 84 = b*(Sqrt(a))
- if ((operator1 = "sqr") and ((operator2 isNot nothing) and (operand2 isNot nothing)))
- equationText = operatorText1 + " " + operand1.ToString() + " " + operatorText2 + " " + operand2.ToString() + " "
- end if
- 'Remove any whitespace between % and number(s)
- if (equationText.Contains(" %"))
- equationText = equationText.Replace(" %","%")
- end if
- end if
- 'MATHS BEGIN--------------------------------
- 'If there are 2 operations
- if (operator2 isNot nothing)
- 'If there are 2 operations with 3 values
- if (operand3 isNot nothing)
- if ((operand1 isNot nothing) and (operand2 isNot nothing))
- result = GetResult(operator1,operand1,operand2)
- end if
- if (result isNot nothing)
- result = GetResult(operator2,result,operand3)
- end if
- 'Else if there are 2 operations with 2 values
- elseif (operand2 isNot nothing)
- 'Handle Square Root on Second Operand
- if ((operator1 = "sqr") and (operand1 isNot nothing))
- result = Sqrt(operand1)
- else
- result = nothing
- end if
- if ((operator1 = "sqr") and (result isNot nothing))
- result = GetResult(operator2,result,operand2)
- else
- if ((result isNot nothing) and (operand1 isNot nothing))
- result = GetResult(operator1,operand1,result)
- elseif (operand1 isNot nothing)
- result = GetResult(operator2,operand1,operand2)
- end if
- end if
- end if
- 'Else if there is 1 operation with up to 2 values
- elseif (operator1 isNot nothing)
- if ((operand1 isNot nothing) and (operand2 isNot nothing))
- result = GetResult(operator1,operand1,operand2)
- if ((operatorText1 = "cubed") or (operatorText1 = "squared"))
- equationText = equationText.Replace(" " + operand2.ToString() + " "," ")
- end if
- elseif ((operand1 isNot nothing) and (not(DoubleOpsArray.Contains(operator1))))
- result = GetResult(operator1,operand1)
- equationText = equationText.Replace(operand1.ToString() + " ","") + operand1.ToString() + " "
- end if
- end if
- else
- 'Else this is a Unit Conversion with 1 value
- if (operator1 isNot nothing)
- if (operand1 isNot nothing)
- result = GetConversion(operator1,operand1)
- equationText = operand1.ToString() + " " + operatorText1 + " = "
- end if
- else
- VA.WriteToLog("AVCS Calculation Error on Null Operator 1", "red")
- end if
- end if
- 'Evaluate Result ======
- if (result isNot nothing)
- try
- 'Try to compare decimal with integer version of itself to discover decimal places, then round
- dim checkResult as Int32 = Convert.ToInt32(result)
- if (result = checkResult)
- 'For TTS brevity use the one that couldn't end with .000
- result = checkResult
- elseif (checkResult <> result)
- dim roundResult as Double = result
- result = Round(roundResult, decimalPlaces)
- end if
- catch
- 'Result is a whole number already, does not need rounding for TTS brevity
- end try
- 'Correct Pi in equation text string to 2 decimal places for TTS brevity
- if (equationText.Contains(Pi.ToString()))
- equationText = equationText.Replace(Pi.ToString(), "3.14")
- end if
- 'Get/Increment/Set Current Operations History Count
- if ((VA.GetInt("AVCS_CALC_CountOperations")) isNot nothing)
- countHistory = VA.GetInt("AVCS_CALC_CountOperations")
- countHistory += 1
- if (countHistory > 99)
- countHistory = 1
- end if
- end if
- VA.SetInt("AVCS_CALC_CountOperations", countHistory)
- 'Save to Calc History & Display Last complete equation with result in Event Log
- if (OpsArray.Contains(operator1))
- equationText = equationText.Replace(" ²","²").Replace(" ³","³").Replace(" ⁿ ","ⁿ").Replace("√ ","√")
- VA.SetText("AVCS_CALC_LastOperation", equationText + "= " + result.ToString())
- VA.SetText("AVCS_CALC_LastOperation_" + countHistory.ToString(), equationText + "= " + result.ToString())
- VA.WriteToLog("Value " + countHistory.ToString() + " = " + equationText + "= " + result.ToString(), "green")
- else
- VA.SetText("AVCS_CALC_LastOperation", equationText + result.ToString() + " " + operatorText2)
- VA.SetText("AVCS_CALC_LastOperation_" + countHistory.ToString(), equationText + result.ToString() + " " + operatorText2)
- VA.WriteToLog("Value " + countHistory.ToString() + " = " + equationText + result.ToString() + " " + operatorText2, "green")
- end if
- 'Save to Memory, Set Last for "that" reference, and Return Result for TTS
- VA.SetDecimal("value" + countHistory.ToString(), result)
- VA.SetDecimal("AVCS_CALC_LastResult", result)
- VA.SetText("avcs_calc_return", result.ToString())
- end if
- end if
- End Sub
- End Class
Comments
-
- // Error at line 375 - equation is for cm to inches... should be: val *= 2.54
Add Comment
Please, Sign In to add comment