SemlerPDX

AVCS Voice Calculator & Unit Conversions Inline Function in VB.net for VoiceAttack

Jan 4th, 2021 (edited)
473
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 30.16 KB | None | 0 0
  1. 'AVCS Voice Calculator & Conversions (v1.0) -- Calculate expressions with up to 2 operations and 3 values "Any way you say it"
  2. 'by SemlerPDX Mar2020/Jan2021
  3. 'VETERANS-GAMING.COM
  4.  
  5. '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]*
  6. 'Set text [~avcs_cmd] to '{TXTWORDTONUM:"{CMD}"}' (Trim) (Lower Case)
  7.  
  8. Imports Microsoft.VisualBasic
  9. Imports System
  10. Imports System.Math
  11. Imports System.Globalization
  12.  
  13. Public Class VAInline
  14.     dim decimalSeparator as string = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator
  15.     dim decimalPlaces as Int32 = 3   'Default = 3   |  rounds results -- change via voice command 'Set Decimal Places [to;] [0..16]'
  16.     dim countHistory as integer = 1
  17.    
  18.     'List Comparison Vars - must start and end with whitespace to check for whole word due to wildcard recognition
  19.     dim OperatorsList as string = " divided divide times multiplied multiply add plus subtract subtracted minus - % percent power square squared squareroot cubed cubes cube cuban cuba "
  20.     dim ConvertorsList 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 "
  21.     dim OpsList as string = " per dif prd sum sub exp sqr "
  22.     dim DoubleOpsList as string = " dif prd sum sub "
  23.     dim SymbolsList as string = " ° # $ % ^ & * - + = : / "
  24.     dim PiList as string = " pi pie tie high bye eye espy pine pied ply tie "
  25.     'Speech Parsing Vars
  26.     dim cmd as string = ""
  27.     dim charArray() as char
  28.     dim cmdSegments() as string
  29.     'Values Decimal Vars
  30.     dim operand1 as decimal?
  31.     dim operand2 as decimal?
  32.     dim operand3 as decimal?
  33.     dim operandLast as decimal?
  34.     dim result as decimal?
  35.     dim resultLast as decimal?
  36.     'Operations String Vars
  37.     dim operator1 as string
  38.     dim operator2 as string
  39.     dim operatorText1 as string = ""
  40.     dim operatorText2 as string = ""
  41.     dim equationText as string = ""
  42.    
  43.     dim operationsOrder as integer = 0
  44.     dim faultCount as integer = 0
  45.     dim randomText as string
  46.     dim subReverse as boolean
  47.     dim calcActive as boolean
  48.    
  49.    
  50.     'Function to fix large number separators by culture
  51.     Private Function FixLargeNumberSeparator(ByRef cmd as string)
  52.         'ex. (7,000.32 into 7000.32)  [or]  (7.000,32 into 7000,32)
  53.         if ((cmd.Contains(".")) or (cmd.Contains(",")))
  54.             if (decimalSeparator <> ".")
  55.                 if (cmd.Contains("."))
  56.                     cmd = cmd.Replace(".", "")
  57.                 end if
  58.             elseif (decimalSeparator <> ",")
  59.                 if (cmd.Contains(","))
  60.                     cmd = cmd.Replace(",", "")
  61.                 end if
  62.             end if
  63.         end if 
  64.     end function
  65.    
  66.    
  67.     'Function to transform large number words and concat with the number said just before
  68.     Private Function FixLargeWordNum(ByRef largeType as string, ByRef lastNum as decimal?)
  69.         select case largeType
  70.             case "million"
  71.                 lastNum *= 1000000
  72.             case "billion"
  73.                 lastNum *= 1000000000
  74.             case "trillion"
  75.                 lastNum *= 1000000000000
  76.             case "quadrillion"
  77.                 lastNum *= 1000000000000000
  78.             case else
  79.                 largeType = "AVCS Calculation Error - unable to resolve '" + lastNum.ToString() + " " + largeType + "' as an opperand"
  80.         end select
  81.     end function
  82.    
  83.    
  84.     'Function to test for "by" as Pi in specific cases
  85.     Private Function HasPi(ByVal operatorName as string)
  86.         if (not((operatorName.Contains("root")) or (operatorName.StartsWith("square")) or (operatorName.StartsWith("cub"))))
  87.             cmd = cmd.Replace("   "," ").Replace("  "," ").Replace("divided by","").Replace("divide by","").Replace("multiplied by","").Replace("multiply by","").Replace("that by","")
  88.             if ((cmd.StartsWith("by ")) or (cmd.Contains(" by ")) or (cmd.EndsWith(" by")))
  89.                 Return true
  90.             end if
  91.         end if
  92.     end function
  93.    
  94.    
  95.     'Function to set keyword and readable text/symbol for Operators
  96.     Private Function SetOperator(ByRef operatorName as string, ByRef operatorText as string)
  97.         if ((operatorName.Contains("%")) or (operatorName.Contains("percent")))
  98.             operatorText = "% of"
  99.             operatorName = "per"
  100.         elseif (operatorName.StartsWith("divide"))
  101.             operatorText = "/"
  102.             operatorName = "dif"
  103.         elseif ((operatorName.Contains("times")) or (operatorName.StartsWith("multipl")))
  104.             operatorText = "x"
  105.             operatorName = "prd"
  106.         elseif ((operatorName.Contains("plus")) or (operatorName.StartsWith("add")))
  107.             operatorText = "+"
  108.             operatorName = "sum"
  109.         elseif ((operatorName.StartsWith("subtract")) or (operatorName.Contains("minus")) or (operatorName.Contains("-")))
  110.             operatorText = "-"
  111.             operatorName = "sub"
  112.         elseif (operatorName.Contains("power"))
  113.             operatorText = "to the power of"
  114.             operatorName = "exp"
  115.         elseif (operatorName.Contains("squareroot"))
  116.             operatorText = "the square root of"
  117.             operatorName = "sqr"
  118.         elseif (operatorName.StartsWith("square"))
  119.             operatorText = "squared"
  120.             operatorName = "exp"
  121.         elseif (operatorName.StartsWith("cub"))
  122.             operatorText = "cubed"
  123.             operatorName = "exp"
  124.         end if
  125.     end function
  126.    
  127.    
  128.     'Function to set keyword and readable text/symbol for Conversions
  129.     Private Function SetConvertor(ByRef operatorName as string, ByRef operatorText as string)
  130.         'VELOCITY CONVERSIONS==============
  131.         if ((operatorName.Contains("fps")) or (operatorName.Contains("feetpersecond")))
  132.             operatorText = "feet per second"
  133.             operatorName = "fps2"
  134.         elseif ((operatorName.Contains("mps")) or (operatorName.Contains("meterspersecond")) or (operatorName.Contains("metrespersecond")))
  135.             operatorText = "meters per second"
  136.             operatorName = "mps2"
  137.         elseif ((operatorName.Contains("mph")) or (operatorName.Contains("milesperhour")))
  138.             operatorText = "miles per hour"
  139.             operatorName = "mph2"
  140.         elseif ((operatorName.Contains("kph")) or (operatorName.Contains("kilometersperhour")) or (operatorName.Contains("kilometresperhour")))
  141.             operatorText = "kilometers per hour"
  142.             operatorName = "kph2"
  143.         elseif (operatorName.Contains("knots"))
  144.             operatorText = "knots"
  145.             operatorName = "kts2"
  146.         elseif ((operatorName.Contains("mach")) or (operatorName.Contains("mock")) or (operatorName.Contains("mark")))
  147.             operatorText = "mach"
  148.             operatorName = "mch2"
  149.         'DISTANCE CONVERSIONS==============
  150.         elseif (operatorName.Contains("inches"))
  151.             operatorText = "inches"
  152.             operatorName = "in2"
  153.         elseif ((operatorName.Contains("cm")) or (operatorName.Contains("centimeters")) or (operatorName.Contains("centimetres")))
  154.             operatorText = "centimeters"
  155.             operatorName = "cm2"
  156.         elseif ((operatorName.Contains("feet")) or (operatorName.Contains("foot")))
  157.             operatorText = "feet"
  158.             operatorName = "ft2"
  159.         elseif ((operatorName.Contains("yards")) or (operatorName.Contains("yours")))
  160.             operatorText = "yards"
  161.             operatorName = "yd2"
  162.         elseif ((operatorName.Contains("km")) or (operatorName.Contains("kilometers")) or (operatorName.Contains("kilometres")))
  163.             operatorText = "kilometers"
  164.             operatorName = "km2"
  165.         elseif ((operatorName.Contains("mi")) or (operatorName.Contains("miles")))
  166.             operatorText = "miles"
  167.             operatorName = "mi2"
  168.         elseif ((operatorName.Contains("meters")) or (operatorName.Contains("metres")))
  169.             operatorText = "meters"
  170.             operatorName = "mt2"
  171.         'TEMPERATURE CONVERSIONS==============
  172.         elseif (operatorName.Contains("fahrenheit"))
  173.             operatorText = "degrees fahrenheit"
  174.             operatorName = "f2"
  175.         elseif ((operatorName.Contains("celcius")) or (operatorName.Contains("celsius")))
  176.             operatorText = "degrees celcius"
  177.             operatorName = "c2"
  178.         elseif (operatorName.Contains("centigrade"))
  179.             operatorText = "degrees centigrade"
  180.             operatorName = "c2"
  181.         elseif ((operatorName.Contains("kelvin")) or (operatorName.Contains("calvin")))
  182.             operatorText = "kelvin"
  183.             operatorName = "k2"
  184.         end if
  185.     end function
  186.    
  187.    
  188.     'Main Maths Function
  189.     Private Function GetResult(ByVal ops as string, ByVal val1 as decimal?, Optional ByVal val2 as decimal? = 0)
  190.         select case ops
  191.             case "sum"
  192.                 val1 += val2
  193.             case "sub"
  194.                 val1 -= val2
  195.             case "prd"
  196.                 val1 *=  val2
  197.             case "dif"
  198.                 val1 /= val2
  199.             case "per"
  200.                 val1 *= (operand2 / 100)
  201.             case "exp"
  202.                 val1 = Math.Pow(val1, val2)
  203.             case "sqr"
  204.                 val1 = Math.Sqrt(val1)
  205.             case else
  206.                 val1 = nothing
  207.         end select
  208.         Return val1
  209.     end function
  210.    
  211.    
  212.     'Main Conversions Function
  213.     Private Function GetConversion(ByVal ops as string, ByVal val as decimal?)
  214.         select case ops
  215.         '==DISTANCE===========
  216.             'inches
  217.             case "in2cm"
  218.                 val *= 0.393701
  219.             case "in2ft"
  220.                 val *= 0.0833333
  221.             case "in2mt"
  222.                 val *= 0.0254
  223.             case "in2yd"
  224.                 val *= 0.0277778
  225.             case "in2km"
  226.                 val /= 39370
  227.             case "in2mi"
  228.                 val /= 63360
  229.             'cm
  230.             case "cm2in"
  231.                 val *= 0.393701
  232.             case "cm2ft"
  233.                 val *= 0.0328084
  234.             case "cm2mt"
  235.                 val /= 100
  236.             case "cm2yd"
  237.                 val *= 0.0109361
  238.             case "cm2km"
  239.                 val /= 100000
  240.             case "cm2mi"
  241.                 val /= 160934
  242.             'ft
  243.             case "ft2in"
  244.                 val *= 12
  245.             case "ft2cm"
  246.                 val *= 30.48
  247.             case "ft2mt"
  248.                 val *= 0.3048
  249.             case "ft2yd"
  250.                 val *= 0.333333
  251.             case "ft2km"
  252.                 val /= 3280.84
  253.             case "ft2mi"
  254.                 val /= 5280
  255.             'mt
  256.             case "mt2in"
  257.                 val *= 39.3701
  258.             case "mt2cm"
  259.                 val *= 100
  260.             case "mt2ft"
  261.                 val *= 3.28084
  262.             case "mt2yd"
  263.                 val *= 1.09361
  264.             case "mt2km"
  265.                 val /= 1000
  266.             case "mt2mi"
  267.                 val /= 1609
  268.             'yd
  269.             case "yd2in"
  270.                 val *= 36
  271.             case "yd2cm"
  272.                 val *= 91.44
  273.             case "yd2ft"
  274.                 val *= 3
  275.             case "yd2mt"
  276.                 val *= 0.9144
  277.             case "yd2km"
  278.                 val /= 1093.61
  279.             case "yd2mi"
  280.                 val /= 1760
  281.             'km
  282.             case "km2in"
  283.                 val *= 39370.1
  284.             case "km2cm"
  285.                 val *= 100000
  286.             case "km2ft"
  287.                 val *= 3280.84
  288.             case "km2mt"
  289.                 val *= 1000
  290.             case "km2yd"
  291.                 val *= 1093.61
  292.             case "km2mi"
  293.                 val *= 0.621371
  294.             'mi
  295.             case "mi2in"
  296.                 val *= 63360
  297.             case "mi2cm"
  298.                 val *= 160934.4
  299.             case "mi2ft"
  300.                 val *= 5280
  301.             case "mi2mt"
  302.                 val *= 1609.34
  303.             case "mi2yd"
  304.                 val *= 1760
  305.             case "mi2km"
  306.                 val *= 1.60934
  307.         '==VELOCITY===========
  308.             'fps
  309.             case "fps2mps"
  310.                 val *= 0.3048
  311.             case "fps2kph"
  312.                 val *= 1.09728
  313.             case "fps2mph"
  314.                 val *= 0.681818
  315.             case "fps2kts"
  316.                 val *= 0.592484
  317.             case "fps2mch"
  318.                 val *= 0.00088863
  319.             'mps
  320.             case "mps2fps"
  321.                 val *= 3.28084
  322.             case "mps2kph"
  323.                 val *= 3.6
  324.             case "mps2mph"
  325.                 val *= 2.23694
  326.             case "mps2kts"
  327.                 val *= 1.94384
  328.             case "mps2mch"
  329.                 val *= 0.00291545
  330.             'kph
  331.             case "kph2fps"
  332.                 val *= 0.911344
  333.             case "kph2mps"
  334.                 val *= 0.277778
  335.             case "kph2mph"
  336.                 val *= 0.6214
  337.             case "kph2kts"
  338.                 val *= 1.852
  339.             case "kph2mch"
  340.                 val *= 1234.8
  341.             'mph
  342.             case "mph2fps"
  343.                 val *= 1.46667
  344.             case "mph2mps"
  345.                 val *= 0.44704
  346.             case "mph2kph"
  347.                 val *= 1.60934
  348.             case "mph2kts"
  349.                 val *= 0.868976
  350.             case "mph2mch"
  351.                 val *= 0.00130332
  352.             'kts
  353.             case "kts2fps"
  354.                 val *= 1.68781
  355.             case "kts2mps"
  356.                 val *= 0.514444
  357.             case "kts2mph"
  358.                 val *= 1.15078
  359.             case "kts2kph"
  360.                 val *= 1.852
  361.             case "kts2mch"
  362.                 val *= 0.0015
  363.             'mch
  364.             case "mch2fps"
  365.                 val *= 1125.33
  366.             case "mch2mps"
  367.                 val *= 343
  368.             case "mch2mph"
  369.                 val *= 767.269
  370.             case "mch2kph"
  371.                 val *= 1234.8
  372.             case "mch2kts"
  373.                 val *= 666.73866
  374.         '==TEMPERATURE===========
  375.             'f
  376.             case "f2c"
  377.                 val = ((val - 32) * 5) / 9
  378.             case "f2k"
  379.                 val = ((val + 459.67) * 5) / 9
  380.             'c
  381.             case "c2f"
  382.                 val = ((val * 9) / 5) + 32
  383.             case "c2k"
  384.                 val = ((val * 9) / 5) + 32
  385.                 val = ((val + 459.67) * 5) / 9
  386.             'k
  387.             case "k2f"
  388.                 val = ((val * 9) / 5) - 459.67
  389.             case "k2c"
  390.                 val = ((val * 9) / 5) - 459.67
  391.                 val = ((val - 32) * 5) / 9
  392.             case else
  393.                 val = nothing
  394.         end select
  395.         Return val
  396.     end function
  397.    
  398.    
  399.    
  400.     Public Sub Main()
  401.         VA.SetText("avcs_calc_return", nothing)
  402.         'Debugging and Testing Check (bypassed if called via spoken command)
  403.         dim cmdTest as string = vaProxy.Utility.ParseTokens("{CMD}")
  404.         if (cmdTest = "")
  405.             'VA.SetText("~avcs_cmd","what is 78° f in celcius")
  406.             VA.SetText("~avcs_cmd","what is 3 zillion divided by 2")
  407.             'VA.SetText("~avcs_cmd","by the way what is 3 plus 3 times by")
  408.             '---note: this expression does not work, because it has 3 operations!!
  409.             'VA.SetText("~avcs_cmd","what is the square root of 144 plus 3 cubed")
  410.             VA.SetInt("AVCS_CALC_ResultsDecimalPlaces",3)
  411.             cmdTest = VA.GetText("~avcs_cmd")
  412.         else
  413.            
  414.             'Check Calc Mode state, exit of off
  415.             if ((VA.GetBoolean("AVCS_CALC_MODE_ON")) isNot nothing)
  416.                 calcActive = VA.GetBoolean("AVCS_CALC_MODE_ON")
  417.             end if
  418.            
  419.             'Provide Message for infrequent wildcard recognition when Calculator Mode OFF (prompt in case user does not known)
  420.             if (not(calcActive))
  421.                 if ((VA.GetInt("AVCS_CALC_FAULT")) isNot nothing)
  422.                     faultCount = VA.GetInt("AVCS_CALC_FAULT")
  423.                     faultCount += 1
  424.                     if (faultCount >= 3)
  425.                         if (faultCount >= 15)
  426.                             VA.WriteToLog("Calculation recognized, but won't be computed  (this is common when calculator is OFF)", "purple")
  427.                             VA.SetInt("AVCS_CALC_FAULT", nothing)
  428.                             faultCount = 0
  429.                         end if
  430.                     else
  431.                         randomText = "Calculator is OFF.  To enable, say, '" + vaProxy.Utility.ParseTokens("{TXTRANDOM:Enable;Begin;Turn On}") + " Voice Calculator'"
  432.                         VA.WriteToLog(randomText, "purple")
  433.                     end if
  434.                     VA.SetInt("AVCS_CALC_FAULT", faultCount)
  435.                 else
  436.                     VA.SetInt("AVCS_CALC_FAULT", 1)
  437.                 end if
  438.                 'Exit Calc Function when Mode OFF
  439.                 Exit Sub
  440.             end if
  441.         end if
  442.        
  443.        
  444.         'Get Custom Decimal Place Settings (if exists)
  445.         if (VA.GetInt("AVCS_CALC_ResultsDecimalPlaces"))
  446.             decimalPlaces = Convert.ToInt32(VA.GetInt("AVCS_CALC_ResultsDecimalPlaces"))
  447.         end if
  448.        
  449.         'Parse Spoken Command for Equation(s)
  450.         if (VA.GetText("~avcs_cmd")) isNot nothing
  451.            
  452.            
  453.             'Remove large number separators & spaces from keywords and remove known "to" and "1" in operations
  454.             cmd = VA.GetText("~avcs_cmd").Replace("swear ","square ").Replace("square root","squareroot").Replace("to the power","power").Replace("too value"," value").Replace("to value"," value").Replace("2 value"," value").Replace("value ","value").Replace(" per ","per").Replace(" ad ","add").Replace("add that 2","add that ").Replace("add that to","add that ")
  455.             FixLargeNumberSeparator(cmd)
  456.             if (cmd.StartsWith("fore to"))
  457.                 cmd = cmd.Substring(7, cmd.Length - 7)
  458.             elseif (cmd.StartsWith("for to"))
  459.                 cmd = cmd.Substring(6, cmd.Length - 6)
  460.             elseif (cmd.StartsWith("or to"))
  461.                 cmd = cmd.Substring(5, cmd.Length - 5)
  462.             elseif (cmd.StartsWith("1 is"))
  463.                 cmd = cmd.Substring(4, cmd.Length - 4)
  464.             end if
  465.            
  466.             'Evaluate spoken command split at each character and space out symbols
  467.             charArray = cmd.ToCharArray
  468.             cmd = ""
  469.             for each character as string in charArray
  470.                 if (SymbolsList.Contains(character))
  471.                     cmd += " " + character.ToString() + " "
  472.                 else
  473.                     cmd += character.ToString()
  474.                 end if
  475.             next
  476.            
  477.             'Evaluate all segments of speech split at {SPACE} and parse for operands and operators
  478.             cmdSegments = cmd.Split(New String() {" "},StringSplitOptions.None)
  479.             for each segment as string in cmdSegments
  480.                 if (not(segment = ""))
  481.                    
  482.                     'Handle numbers recognized as homonym words
  483.                     select case segment
  484.                         case "too"
  485.                             segment = "2"
  486.                         case "to"
  487.                             segment = "2"
  488.                         case "trees"
  489.                             segment = "3"
  490.                         case "tree"
  491.                             segment = "3"
  492.                         case "fore"
  493.                             segment = "4"
  494.                         case "for"
  495.                             segment = "4"
  496.                         case "ate"
  497.                             segment = "8"
  498.                         case "ape"
  499.                             segment = "8"
  500.                         case "valuetoo"
  501.                             segment = "value2"
  502.                         case "valueto"
  503.                             segment = "value2"
  504.                         case "valuetrees"
  505.                             segment = "value3"
  506.                         case "valuetree"
  507.                             segment = "value3"
  508.                         case "valuefore"
  509.                             segment = "value4"
  510.                         case "valuefor"
  511.                             segment = "value4"
  512.                         case "valueate"
  513.                             segment = "value8"
  514.                     end select
  515.                    
  516.                     'Handle short form of convertors
  517.                     select case segment
  518.                         case "c"
  519.                             segment = "celcius"
  520.                         case "f"
  521.                             segment = "fahrenheit"
  522.                         case "k"
  523.                             segment = "kelvin"
  524.                         case "m"
  525.                             segment = "meters"
  526.                     end select
  527.                    
  528.                     'Handle "subtract A from B" order of operations error
  529.                     if (segment.Contains("from"))
  530.                         if ((operand2 is nothing) and(operand1 isNot nothing) and ((operator1 isNot nothing) and (operator1.Contains("subtract"))))
  531.                             subReverse = true
  532.                         end if
  533.                     end if
  534.                    
  535.                     'Handle "that" reference to previous calculation result
  536.                     if (segment.Contains("that"))
  537.                         if ((VA.GetDecimal("AVCS_CALC_LastResult")) isNot nothing)
  538.                             segment = VA.GetDecimal("AVCS_CALC_LastResult").ToString()
  539.                         end if
  540.                     end if
  541.                    
  542.                     'Handle MEM reference to previous calculation result
  543.                     if ((segment.StartsWith("value")) and (IsNumeric(segment.Substring(segment.Length - 1, 1))))
  544.                         if ((VA.GetDecimal(segment)) isNot nothing)
  545.                             segment = VA.GetDecimal(segment).ToString()
  546.                         else
  547.                             VA.WriteToLog(segment + " does not exist in memory", "red")
  548.                             Exit Sub
  549.                         end if
  550.                     end if
  551.                    
  552.                     'Handle "pi" and homonym variants
  553.                     if (PiList.Contains(" " + segment + " "))
  554.                         if (operand1 is nothing)
  555.                             operand1 = Math.Pi
  556.                         elseif (operand2 is nothing)
  557.                             operand2 = Math.Pi
  558.                         elseif (operand3 is nothing)
  559.                             operand3 = Math.Pi
  560.                         end if
  561.                        
  562.                     'Set Operands -------
  563.                     elseif ((IsNumeric(segment)) and (operand1 is nothing))
  564.                         try
  565.                             operand1 = Convert.ToDecimal(segment)
  566.                             operandLast = operand1
  567.                             if (operationsOrder = 0)
  568.                                 operationsOrder = 1 'for edge case:  (b = Pi)
  569.                             end if
  570.                         catch
  571.                             VA.WriteToLog("AVCS Calculation Error at Operand 1", "red")
  572.                         end try
  573.                     elseif ((IsNumeric(segment)) and (operand2 is nothing))
  574.                         try
  575.                             operand2 = Convert.ToDecimal(segment)
  576.                             operandLast = operand2
  577.                         catch
  578.                             VA.WriteToLog("AVCS Calculation Error at Operand 2", "red")
  579.                         end try
  580.                     elseif ((IsNumeric(segment)) and (operand3 is nothing))
  581.                         try
  582.                             operand3 = Convert.ToDecimal(segment)
  583.                             operandLast = operand3
  584.                         catch
  585.                             VA.WriteToLog("AVCS Calculation Error at Operand 3", "red")
  586.                         end try
  587.                        
  588.                     'Set Operators -------
  589.                     elseif ((OperatorsList.Contains(" " + segment + " ")) and (operator1 is nothing))
  590.                         operator1 = segment
  591.                         if (operationsOrder = 0)
  592.                             operationsOrder = 2 'for edge case:  (a = Pi)
  593.                         end if
  594.                     elseif ((OperatorsList.Contains(" " + segment + " ")) and (operator2 is nothing))
  595.                         operator2 = segment
  596.                         if ((operationsOrder = 1) and (operand2 isNot nothing))
  597.                             operationsOrder = 3 'for edge case:  (c = b and b = Pi)
  598.                         elseif ((operationsOrder = 1) and (operand2 is nothing))
  599.                             operationsOrder = 4 'for edge case:  (c = Pi)
  600.                         end if
  601.                        
  602.                     'Set Convertors -------
  603.                     elseif ((ConvertorsList.Contains(" " + segment + " ")) and (operator1 is nothing))
  604.                         operator1 = segment
  605.                         operationsOrder = 5 'for edge case null:  (no way Pi)
  606.                     elseif ((ConvertorsList.Contains(" " + segment + " ")) and (operator2 is nothing))
  607.                         operator2 = segment
  608.                        
  609.                     'Handle "..illions" -------
  610.                     elseif (segment.EndsWith("illion"))
  611.                         if ((operand1 isNot nothing) and (operandLast = operand1))
  612.                             FixLargeWordNum(segment,operand1)
  613.                         elseif ((operand2 isNot nothing) and (operandLast = operand2))
  614.                             FixLargeWordNum(segment,operand2)
  615.                         elseif ((operand3 isNot nothing) and (operandLast = operand3))
  616.                             FixLargeWordNum(segment,operand3)
  617.                         end if
  618.                         if (segment.StartsWith("AVCS Calculation Error"))
  619.                             VA.WriteToLog(segment, "red")
  620.                             Exit Sub
  621.                         end if
  622.                     end if
  623.                    
  624.                 end if
  625.             next
  626.            
  627.            
  628.             'Evaluate for Pi recognized as "by" (edge cases)
  629.             if (operationsOrder < 5)
  630.                 '-- 1 operation catch
  631.                 if ((operator2 is nothing) and (operand2 is nothing))
  632.                     if (HasPi(operator1))
  633.                         if (operationsOrder = 1)
  634.                             operand2 = Math.Pi
  635.                         elseif (operationsOrder = 2)
  636.                             operand2 = operand1
  637.                             operand1 = Math.Pi
  638.                         end if
  639.                     end if
  640.                 '-- 2 operations catch
  641.                 elseif ((operator2 isNot nothing) and (operand3 is nothing))
  642.                     if ((HasPi(operator1)) or (HasPi(operator2)))
  643.                         if (operationsOrder = 4)
  644.                             operand3 = operand2
  645.                             operand2 = Math.Pi
  646.                         elseif (operationsOrder = 3)
  647.                             operand3 = Math.Pi
  648.                         elseif (operationsOrder = 2)
  649.                             operand3 = operand2
  650.                             operand2 = operand1
  651.                             operand1 = Math.Pi
  652.                         end if
  653.                     end if
  654.                 end if
  655.             end if
  656.            
  657.             'Evaluate Operator 1 ======
  658.             if (operator1 isNot nothing)
  659.                 'Handle null operands on Squared/Cubed operators
  660.                 if ((operator1.StartsWith("square")) and (not(operator1.Contains("root"))))
  661.                     operand2 = 2
  662.                 elseif (operator1.StartsWith("cub"))
  663.                     operand2 = 3
  664.                 'Handle Reverse order of operations on Subtract
  665.                 elseif ((operator1.Contains("subtract")) and (subReverse))
  666.                     dim operand4 as decimal? = operand2
  667.                     operand2 = operand1
  668.                     operand1 = operand4
  669.                 end if
  670.                
  671.                 'Set Operator 1 keyword and get text form of Operator/Convertor
  672.                 if (not(OperatorsList.Contains(operator1)))
  673.                     SetConvertor(operator1,operatorText1)
  674.                 else
  675.                     SetOperator(operator1,operatorText1)
  676.                 end if
  677.             else
  678.                 VA.WriteToLog("AVCS Calculation Error on Null Operator 1", "red")
  679.                 Exit Sub
  680.             end if
  681.            
  682.             'Evaluate Operator 2 ======
  683.             if (operator2 isNot nothing)
  684.                 'Handle null operands on Squared/Cubed operators
  685.                 if ((operator2.StartsWith("square")) and (not(operator2.Contains("root"))))
  686.                     operand3 = 2
  687.                 elseif (operator2.Contains("cub"))
  688.                     operand3 = 3
  689.                 end if
  690.                 'Set Operator 2 keyword and get text form of Operator/Convertor
  691.                 if (not(OpsList.Contains(operator1)))
  692.                     SetConvertor(operator2,operatorText2)
  693.                     operator1 = operator1 + operator2.Substring(0, operator2.Length - 1)
  694.                     operator2 = nothing
  695.                 else
  696.                     SetOperator(operator2,operatorText2)
  697.                     'Calculate Square Root on Multi-Part Equation to avoid errors on null operand3
  698.                     'ex. 200 subtract square root of 128 = 188.69 = a-(Sqrt(b))
  699.                     if ((operator2 = "sqr") and (operand3 is nothing))
  700.                         equationText = operand1.ToString() + " " + operatorText1 + " " + operatorText2 + " " + operand2.ToString() + " "
  701.                         operand2 = Math.Sqrt(operand2)
  702.                         operator2 = nothing
  703.                     end if
  704.                    
  705.                     'Calculate Percentage before to avoid order of operations and text display errors
  706.                     'ex. 200 subtract 20 % = 160 = a-(b*(a/100))
  707.                     if ((operator2 = "per") and (operand3 is nothing))
  708.                         equationText = operand1.ToString() + " " + operatorText1 + " " + operand2.ToString() + " " + operatorText2 + " " + operand1.ToString() + " "
  709.                         operand3 = operand1
  710.                         operand2 = operand2*(operand3 / 100)
  711.                         operand3 = nothing
  712.                         operator2 = nothing
  713.                     'ex. 200 subtract 20 % of 100 = 180 = a-(b*(c/100)
  714.                     elseif ((operator2 = "per") and (operand3 isNot nothing))
  715.                         equationText = operand1.ToString() + " " + operatorText1 + " " + operand2.ToString() + " " + operatorText2 + " " + operand3.ToString() + " "
  716.                         operand2 = operand2*(operand3 / 100)
  717.                         operand3 = nothing
  718.                         operator2 = nothing
  719.                     'ex. 4 plus 7 to the power of 3 = 347 = a+(b^c)
  720.                     elseif (((operator2 = "exp") and (operatorText2.StartsWith("to"))) and (operand3 isNot nothing))
  721.                         equationText = operand1.ToString() + " " + operatorText1 + " " + operand2.ToString() + " " + operatorText2 + " " + operand3.ToString() + " "
  722.                         operand2 = Math.Pow(operand2, operand3)
  723.                         operand3 = nothing
  724.                         operator2 = nothing
  725.                     'ex. 4 plus 7 cubed = 347 = a+b³   [or]   4 plus 7 squared = 53 = a+b²
  726.                     elseif (((operator2 = "exp") and (not(operatorText2.StartsWith("to")))) and (operand3 isNot nothing))
  727.                         equationText = operand1.ToString() + " " + operatorText1 + " " + operand2.ToString() + " " + operatorText2 + " "
  728.                         operand2 = Math.Pow(operand2, operand3)
  729.                         operand3 = nothing
  730.                         operator2 = nothing
  731.                     end if
  732.                 end if
  733.             end if
  734.            
  735.             'Final Evaluation for "8" recognized as "a"
  736.             if ((DoubleOpsList.Contains(operator1)) and (operator2 is nothing) and (operand1 isNot nothing) and (operand2 is nothing))
  737.                 if ((cmd.Contains(" a ")) or (cmd.EndsWith(" a")))
  738.                     if (operationsOrder = 1)
  739.                         operand2 = 8
  740.                     else
  741.                         operand2 = operand1
  742.                         operand1 = 8
  743.                     end if
  744.                 end if
  745.             end if
  746.            
  747.            
  748.             '==EVALUATE RESULT==
  749.             if (OpsList.Contains(operator1))
  750.                
  751.                 if (equationText = "")
  752.                     'Build Equation Text for display in VA Event log
  753.                     if (operand1 isNot nothing)
  754.                         equationText += operand1.ToString() + " "
  755.                     end if
  756.                     if (operator1 isNot nothing)
  757.                         equationText += operatorText1 + " "
  758.                     end if
  759.                     if (operand2 isNot nothing)
  760.                         equationText += operand2.ToString() + " "
  761.                     end if
  762.                     if (operator2 isNot nothing)
  763.                         equationText += operatorText2 + " "
  764.                     end if
  765.                     if (operand3 isNot nothing)
  766.                         equationText += operand3.ToString() + " "
  767.                     end if
  768.                    
  769.                     'Calculate Square Root on Multi-Part Equation to avoid incorrect operations math and display text
  770.                     'ex. square root of 144 times 7 = 84 = b*(Sqrt(a))
  771.                     if ((operator1 = "sqr") and ((operator2 isNot nothing) and (operand2 isNot nothing)))
  772.                         equationText = operatorText1 + " " + operand1.ToString() + " " + operatorText2 + " " + operand2.ToString() + " "
  773.                     end if
  774.                     'Remove any whitespace between % and number(s)
  775.                     if (equationText.Contains(" %"))
  776.                         equationText = equationText.Replace(" %","%")
  777.                     end if
  778.                    
  779.                 end if
  780.                
  781.                 'MATHS BEGIN--------------------------------
  782.                 'If there are 2 operations
  783.                 if (operator2 isNot nothing)
  784.                     'If there are 2 operations with 3 values
  785.                     if (operand3 isNot nothing)
  786.                         if ((operand1 isNot nothing) and (operand2 isNot nothing))
  787.                             result = GetResult(operator1,operand1,operand2)
  788.                         end if
  789.                         if (result isNot nothing)
  790.                             result = GetResult(operator2,result,operand3)
  791.                         end if
  792.                    
  793.                     'Else if there are 2 operations with 2 values
  794.                     elseif (operand2 isNot nothing)
  795.                         'Handle Square Root on Second Operand
  796.                         if ((operator1 = "sqr") and (operand1 isNot nothing))
  797.                             result = Math.Sqrt(operand1)
  798.                         else
  799.                             result = nothing
  800.                         end if
  801.                        
  802.                         if ((operator1 = "sqr") and (result isNot nothing))
  803.                             result = GetResult(operator2,result,operand2)
  804.                         else
  805.                             if ((result isNot nothing) and (operand1 isNot nothing))
  806.                                 result = GetResult(operator1,operand1,result)
  807.                             elseif (operand1 isNot nothing)
  808.                                 result = GetResult(operator2,operand1,operand2)
  809.                             end if
  810.                         end if
  811.                     end if
  812.                
  813.                 'Else if there is 1 operations with up to 2 values
  814.                 elseif (operator1 isNot nothing)
  815.                     if ((operand1 isNot nothing) and  (operand2 isNot nothing))
  816.                         result = GetResult(operator1,operand1,operand2)
  817.                         if ((operatorText1 = "cubed") or (operatorText1 = "squared"))
  818.                             equationText = equationText.Replace(" " + operand2.ToString() + " "," ")
  819.                         end if
  820.                     elseif ((operand1 isNot nothing) and (not(DoubleOpsList.Contains(operator1))))
  821.                         result = GetResult(operator1,operand1)
  822.                         equationText = equationText.Replace(operand1.ToString() + " ","") + operand1.ToString() + " "
  823.                     end if
  824.                 end if
  825.             else
  826.                 'Else this is a Unit Conversion with 1 value
  827.                 if (operator1 isNot nothing)
  828.                     if (operand1 isNot nothing)
  829.                         result = GetConversion(operator1,operand1)
  830.                         equationText = operand1.ToString() + " " + operatorText1 + " = "
  831.                     end if
  832.                 else
  833.                     VA.WriteToLog("AVCS Calculation Error on Null Operator 1", "red")
  834.                 end if
  835.             end if
  836.            
  837.            
  838.             'Evaluate Result ======
  839.             if (result isNot nothing)
  840.                 try
  841.                     'Try to compare decimal with integer version of itself to discover decimal places, then round
  842.                     dim checkResult as Int32 = Convert.ToInt32(result)
  843.                     if (result = checkResult)
  844.                         'For TTS brevity use the one that couldn't end with .000
  845.                         result = checkResult
  846.                     elseif (checkResult <> result)
  847.                         dim roundResult as Double = result
  848.                         result = Math.Round(roundResult, decimalPlaces)
  849.                     end if
  850.                 catch
  851.                     'Result is a whole number already, does not need rounding for TTS brevity
  852.                 end try
  853.                
  854.                 'Correct Pi in equation text string to 2 decimal places for TTS brevity
  855.                 if(equationText.Contains(Math.Pi.ToString()))
  856.                     equationText = equationText.Replace(Math.Pi.ToString(), "3.14")
  857.                 end if
  858.                
  859.                 'Get Current History Count and/or Increment
  860.                 if((VA.GetInt("AVCS_CALC_CountOperations")) isNot nothing)
  861.                     countHistory = VA.GetInt("AVCS_CALC_CountOperations")
  862.                     countHistory += 1
  863.                     if (countHistory > 99)
  864.                         countHistory = 1
  865.                     end if
  866.                 end if
  867.                 VA.SetInt("AVCS_CALC_CountOperations", countHistory)
  868.                
  869.                 'Save to Calc History & Display Last complete equation with result in Event Log
  870.                 if (OpsList.Contains(operator1))
  871.                     VA.SetText("AVCS_CALC_LastOperation", equationText + "= " + result.ToString())
  872.                     VA.SetText("AVCS_CALC_LastOperation_" + countHistory.ToString(), equationText + "= " + result.ToString())
  873.                     VA.WriteToLog("Value " + countHistory.ToString() + " = " + equationText + "= " + result.ToString(), "green")
  874.                 else
  875.                     VA.SetText("AVCS_CALC_LastOperation", equationText + result.ToString() + " " + operatorText2)
  876.                     VA.SetText("AVCS_CALC_LastOperation_" + countHistory.ToString(), equationText + result.ToString() + " " + operatorText2)
  877.                     VA.WriteToLog("Value " + countHistory.ToString() + " = " + equationText + result.ToString() + " " + operatorText2, "green")                
  878.                 end if
  879.                
  880.                 'Save to Memory, Set Last for "that" reference, and Return Result for TTS
  881.                 VA.SetDecimal("value" + countHistory.ToString(), result)
  882.                 VA.SetDecimal("AVCS_CALC_LastResult", result)
  883.                 VA.SetText("avcs_calc_return", result.ToString())
  884.                
  885.             end if
  886.            
  887.            
  888.         end if
  889.    
  890.     End Sub
  891.  
  892. End Class
Add Comment
Please, Sign In to add comment