Author Topic: Say 'set timer' then have VA create a variable based on what number is typed  (Read 9003 times)

stoopidsxyflanders

  • Guest
The title pretty much explains it. I want to be able to set timers (e.g. 'set timer for 37 seconds') which would execute the following command:

Code: [Select]
Say, 'Timer set for 36 seconds'
Set small int (condition) [customtimer] value to 36
Start Loop While : [customtimer] Does Not Equal 0
Pause 1 second
Set small int (condition) [customtimer] value as decremented by 1
End Loop
Say, 'It has been 36 seconds'

The only feasible way I can see to do this would be to create a new command for every second, so if I wanted to be able to set custom timers for up to 8 minutes then I would need to create 480 commands! I tried dictation mode to capture the number (using prefix and suffix) but it's far too unreliable.

So I had another idea. What if I create a command that occurs when I say 'set custom timer' and would do the following:

- Wait for user to enter a number (3 digits) using numpad
- Convert that number to a small integer {customtimer_input}
- Execute the following code"

Code: [Select]
Say, 'Timer set for {SMALL:customtimer_input} seconds'
Set small int (condition) [customtimer] value to {SMALL:customtimer_input}
Start Loop While : [customtimer] Does Not Equal 0
Pause 1 second
Set small int (condition) [customtimer] value as decremented by 1
End Loop
Say, 'It has been {SMALL:customtimer_input} seconds'

How do I do the first 2 steps - the user input for setting the custom timer? Can it even be done? Is there a better way to achieve what I want to do? Has anyone else created a profile for timers that I could simply import into mine?

stoopidsxyflanders

  • Guest
Actually I figured out a better way to get it to work as originally intended via voice-commands only (no numpad input required). Only 64 commands will be required instead of the original 480, and they are all easily duplicated.

- Create 4 prefix commands:
   1. Say: 'Set timer for' (Command: Set small int (condition) [customtimer] value to 0)
   2. Say: 'Set timer for one hundred and' (Command: Set small int (condition) [customtimer] value to 100)
   3. Say: 'Set timer for two hundred and' (Command: Set small int (condition) [customtimer] value to 200)   
   4. Say: 'Set timer for four hundred and' (Command: Set small int (condition) [customtimer] value to 300)

- Create 60 suffix commands :
  1. 1 second
  2. 2 seconds
  ...
  60. 60 seconds
  Code:
Code: [Select]
Set small int (condition) [customtimer] value as incremented by 60
Execute command, 'CUSTOM TIMER SETTINGS' (and wait until it completes)

- Create a master command for the timer CUSTOM TIMER SETTINGS (keep it turned off)
  Code:
Code: [Select]
Set small int (condition) [customtimer_started] value to the value of [customtimer]
Say, 'Timer set for {SMALL:customtimer} seconds'
Start Loop While : [customtimer] Does Not Equal 0
Pause 1 second
Set small int (condition) [customtimer] value as decremented by 1
End Loop
Say, 'It has been {SMALL:customtimer_started} seconds'


stoopidsxyflanders

  • Guest
And I'm an idiot... I need 100 suffix commands, not 60.

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4778
  • RTFM
Or...you could extract the time from the command phrase?

Set timer for [one hundred and;two hundred and;three hundred and;four hundred and;][0..60] seconds
Code: [Select]
Set small int (condition) [~Timer] value to 0
Begin Text Compare : [{CMD}] Contains 'one hundred'
    Set small int (condition) [~Timer] value as incremented by 100
Else If Text Compare : [{CMD}] Contains 'two hundred'
    Set small int (condition) [~Timer] value as incremented by 200
Else If Text Compare : [{CMD}] Contains 'three hundred'
    Set small int (condition) [~Timer] value as incremented by 300
Else If Text Compare : [{CMD}] Contains 'four hundred'
    Set small int (condition) [~Timer] value as incremented by 400
End Condition
Begin Text Compare : [{EXP:{TXTNUM:"{CMD}"} > 0}] Equals '1'
    Set small int (condition) [~Timer] value to the converted value of {EXP:{SMALL:~Timer} + {TXTNUM:"{CMD}"}}
End Condition
Say, 'Timer set for {SMALL:~Timer} seconds'
Set small int (condition) [~TimerCount] value to the value of [~Timer]
Start Loop While : [~TimerCount] Does Not Equal 0
    Pause 1 second
    Set small int (condition) [~TimerCount] value as decremented by 1
End Loop
Say, 'It has been {SMALL:~Timer} seconds'
Whether you use prefix/suffix or dynamic command sections, you need the same amount of permutations, so why not make it a single command.

Note that I'm using the "~" character to define the variables as local in the command context. This allows you to run multiple timers together(though not to ask how many seconds are remaining, so pick whichever is more important to you).

stoopidsxyflanders

  • Guest
Thanks for the help! It's all working except for this part:

Code: [Select]
Begin Text Compare : [{EXP:{TXTNUM:"{CMD}"} > 0}] Equals '1'
    Set small int (condition) [~Timer] value to the converted value of {EXP:{SMALL:~Timer} + {TXTNUM:"{CMD}"}}
End Condition

If I say 'set timer for three hundred and twenty two seconds', it will respond with 'Timer set for three hundred seconds'. When I ask how long is remaining it confirms that the twenty two seconds wasn't added on.

I removed the ~ as it's more important that I'm able to check how long is remaining on the timer (plus I can always duplicate the timer using different variables if I need more), but apart from that everything is the same.

My full code:

Say: create a new timer for [one hundred and; two hundred and; three hundred and; four hundred and;] [1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;85;86;87;88;89;90;91;92;93;94;95;96;97;98;99;] seconds

Code: [Select]
Set small int (condition) [Timer] value to 0
Begin Text Compare : [{CMD}] Contains 'one hundred'
    Set small int (condition) [Timer] value as incremented by 100
Else If Text Compare : [{CMD}] Contains 'two hundred'
    Set small int (condition) [Timer] value as incremented by 200
Else If Text Compare : [{CMD}] Contains 'three hundred'
    Set small int (condition) [Timer] value as incremented by 300
Else If Text Compare : [{CMD}] Contains 'four hundred'
    Set small int (condition) [Timer] value as incremented by 400
End Condition
Begin Text Compare : [{EXP:{TXTNUM:"{CMD}"] Equals '1'
    Set small int (condition) [Timer] value to the converted value of {EXP:{SMALL:Timer} + {TXTNUM:"{CMD}"}}
End Condition
Say, 'Timer set for {SMALL:Timer} seconds'
Set small int (condition) [TimerCount] value to the value of [Timer]
Start Loop While : [TimerCount] Does Not Equal 0
    Pause 1 second
    Set small int (condition) [TimerCount] value as decremented by 1
End Loop
Say, 'It has been {SMALL:Timer} seconds'
« Last Edit: February 24, 2017, 06:05:48 PM by stoopidsxyflanders »

stoopidsxyflanders

  • Guest
Nevermind.. I'm blind. Missed the > 0 part

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4778
  • RTFM
Say: create a new timer for [one hundred and; two hundred and; three hundred and; four hundred and;] [1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;85;86;87;88;89;90;91;92;93;94;95;96;97;98;99;] seconds
Any particular reason why you're specifying every single permutation?

You can accomplish the exact same thing with the command phrase "create a new timer for [one hundred and;two hundred and;three hundred and;four hundred and;][1..99] seconds", the ".." tells VoiceAttack to automatically fill in the intermediate numbers.

Note that, per your example, I've excluded "0", so it's not possible to set exactly 100, 200, 300, or 400 seconds(only 101, 201, 301, and 401).

stoopidsxyflanders

  • Guest
Only because I didn't know you could do it that way. Nice tip!

I tweaked it slightly so that the "and" after the "hundred" is separated and optional. So if you just say 'set timer for one hundred seconds' it works fine. You don't need to say 'set timer for one hundred and zero seconds'.

Checked and confirmed working. I can also easily pause/reset the timer and check how long is remaining with other commands.

Thanks heaps for the help!

For anyone else who may need a VoiceAttack timer/countdown/stopwatch profile, here's the working code:
Say: set timer for [one hundred; two hundred; three hundred; four hundred;] [and;] [1..99;] seconds
Code: [Select]
Set small int (condition) [Timer] value to 0
Begin Text Compare : [{CMD}] Contains 'one hundred'
    Set small int (condition) [Timer] value as incremented by 100
Else If Text Compare : [{CMD}] Contains 'two hundred'
    Set small int (condition) [Timer] value as incremented by 200
Else If Text Compare : [{CMD}] Contains 'three hundred'
    Set small int (condition) [Timer] value as incremented by 300
Else If Text Compare : [{CMD}] Contains 'four hundred'
    Set small int (condition) [Timer] value as incremented by 400
End Condition
Begin Text Compare : [{EXP:{TXTNUM:"{CMD}"} > 0}] Equals '1'
    Set small int (condition) [Timer] value to the converted value of {EXP:{SMALL:Timer} + {TXTNUM:"{CMD}"}}
End Condition
Say, 'Timer set for {SMALL:Timer} seconds'
Set small int (condition) [TimerCount] value to the value of [Timer]
Start Loop While : [TimerCount] Does Not Equal 0
    Pause 1 second
    Set small int (condition) [TimerCount] value as decremented by 1
End Loop
Say, 'It has been {SMALL:Timer} seconds'

stoopidsxyflanders

  • Guest
Also I added this code in case I decide to set a timer for minutes:

Say: set timer for [1..15] minutes
Code: [Select]
Set small int (condition) [Timer] value to 0
Begin Text Compare : [{EXP:{TXTNUM:"{CMD}"} > 0}] Equals '1'
    Set small int (condition) [Timer] value to the converted value of {EXP:({SMALL:Timer} + {TXTNUM:"{CMD}"})*60}
End Condition
Say, 'Timer set for {SMALL:Timer} seconds'
Set small int (condition) [TimerCount] value to the value of [Timer]
Start Loop While : [TimerCount] Does Not Equal 0
    Pause 1 second
    Set small int (condition) [TimerCount] value as decremented by 1
End Loop
Say, 'It has been {SMALL:Timer} seconds'

PsiQss

  • Guest
I've noticed that the speech engine is quite good at recognizing numbers. I don't have a very clear accent, so my speech engine usually has trouble recognizing what I say (without it being specified in VA as a command) but it does a pretty good job recognizing the numbers. And that's with only 3 training sessions.

So technically, you could even use:

Say: "Set timer for* [seconds; minutes]"

And then set the timer value to {TXTNUM:"{CMD_AFTER}"}

That way, you could set the timer to pretty much any amount, without having to specify the maximum allowed number, for example set it to 100.000.000 seconds without adding any permutations at all. The only thing you would have to add is a way to check if the number was recognized correctly. I suppose you don't really NEED such a huge timer, but thought I'll mention it in case you find it useful ;)

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4778
  • RTFM
So technically, you could even use:

Say: "Set timer for* [seconds; minutes]"

And then set the timer value to {TXTNUM:"{CMD_AFTER}"}
Wildcards can only be applied to the beginning or end of a command phrase. The one you've presented will only be recognized as "set timer for seconds" and "set timer for minutes".

What you could use is a phrase like "Set [seconds;minutes] timer for*", which would allow the use of "{CMD_AFTER}" but is less intuitive to say.

PsiQss

  • Guest
Hmm, that's interesting.. How about a dynamic command, where "Set timer for*" Would be a prefix, and [seconds, minutes] a suffix?

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4778
  • RTFM
How about a dynamic command, where "Set timer for*" Would be a prefix, and [seconds, minutes] a suffix?
Prefix/Suffix is just a different way to do dynamic commands.

"Set timer for [one;two]" does the exact same thing as the prefix command "Set timer for" and the suffix commands "one" and "two".

PsiQss

  • Guest
I see. Well, here's me trying to be smart :P

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Quote
Prefix/Suffix is just a different way to do dynamic commands.

"Set timer for [one;two]" does the exact same thing as the prefix command "Set timer for" and the suffix commands "one" and "two".

I'm so glad someone finally spelled this out! I've been wondering about Prefix/Suffix for a little while now O_o

Gary

  • Administrator
  • Hero Member
  • *****
  • Posts: 2831
Although it *is* another way to accomplish the same sort of thing, there's a little more to it.  Composite (prefix/suffix) commands join together two whole commands (the prefix command + the suffix command) to create one larger command.  Dynamic command segments only relate to the one command in which they are associated.

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4778
  • RTFM
Although it *is* another way to accomplish the same sort of thing, there's a little more to it.
Let me clarify that I'm speaking from the perspective of the speech recognition engine, which is given two phrases to recognize in either case(as far as I'm aware).

The way I see it prefix/suffix is a convenience feature which offers an alternative to manually implementing a system of branching conditional statements.

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Thanks for the additional clarification Gary and Pfeil.

Do you (or the rest of the community) have any simple examples of the prefix/suffix commands in action (besides what's in the help document)? I'm trying to understand the advantages (if any) of the prefix/suffix combination as opposed to equivalent dynamic commands.

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4778
  • RTFM
I'm trying to understand the advantages (if any) of the prefix/suffix combination as opposed to equivalent dynamic commands.
Dynamic command sections are actually a much later addition(v1.5.8) than prefix/suffix(v1.5), and can do more, in a more flexible manner.
Personally, I consider prefix/suffix obsolete.


The best usage case for prefix/suffix would have to be something where you have two distinct steps, which are spoken and executed in the set order of "A then B", with no "C".

You can combine both methods if you do need "C", <opinion> but if you're going to implement logic to deal with "C", you might as well do the same for "A" and "B" and reap the benefits.
Basically, the moment you're using the "{CMD}" token, you've defeated the purpose of prefix/suffix.</opinion>


I'm trying to come up with an example that fits the requirement, so here's an attempt:

Imagine you have a system in which you need to send produce to locations, where the interface first requires you to select an item, then a destination.

You must:
  • Press F3 to initiate a search
  • Type in the name of the item
  • Press enter to select the item
  • Click a button on the screen to select the target location
  • Click a "confirm" button in a dialog box to ship the item

With prefix/suffix, you create the following:
send apples
Code: [Select]
Press F3 key and hold for 0,01 seconds and release
Quick Input, 'apples'
Press Enter key and hold for 0,01 seconds and release

send oranges
Code: [Select]
Press F3 key and hold for 0,01 seconds and release
Quick Input, 'oranges'
Press Enter key and hold for 0,01 seconds and release

send pears
Code: [Select]
Press F3 key and hold for 0,01 seconds and release
Quick Input, 'pears'
Press Enter key and hold for 0,01 seconds and release

to the customer
Code: [Select]
Move mouse cursor to screen coordinates (42, 525)
Click left mouse button
Move mouse cursor to screen coordinates (120, 5)
Click left mouse button

to the store
Code: [Select]
Move mouse cursor to screen coordinates (94, 548)
Click left mouse button
Move mouse cursor to screen coordinates (120, 5)
Click left mouse button

to the warehouse
Code: [Select]
Move mouse cursor to screen coordinates (64, 585)
Click left mouse button
Move mouse cursor to screen coordinates (120, 5)
Click left mouse button


With dynamic command sections, you create:
send [apples;oranges;pears] to the [customer;store;warehouse]
Code: [Select]
Press F3 key and hold for 0,01 seconds and release
Quick Input, '{CMDSEGMENT:1}'
Press Enter key and hold for 0,01 seconds and release
Begin Text Compare : [{CMD}] Contains 'customer'
    Move mouse cursor to screen coordinates (42, 525)
Else If Text Compare : [{CMD}] Contains 'store'
    Move mouse cursor to screen coordinates (94, 548)
Else
    Move mouse cursor to screen coordinates (64, 585)
End Condition
Click left mouse button
Move mouse cursor to screen coordinates (120, 5)
Click left mouse button


Some possibly(certainly, we're human after all) biased positives and negatives:
  • + Each command only contains the actions it needs, making it easy to read at a glance*
  • + You have access to the "{PREFIX}", "{SUFFIX}" and "{COMPOSITEGROUP}" tokens
  • + No knowledge of conditions required
  • + Different commands can have different confidence levels; E.G. "send oranges to the warehouse" to require 50%, but "send oranges to the customer" 90%
  • - Constrained to a very strict "A then B"(See my remark above about "C")
  • - Because each command is distinctly separate, many may contain a largely similar set of actions
  • - *If you need an overview of what the command does through the entire execution, you need to open the prefix, then the suffix; You can't view or modify both at once
  • -When anything needs to be changed that occurs in multiple commands, you need to edit each command individually
  • - Many variations create command list clutter
« Last Edit: March 01, 2017, 02:51:15 PM by Pfeil »

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Thanks for the AWESOME detailed response Pfeil! :D

Quote
- When anything needs to be changed that occurs in multiple commands, you need to edit each command individually
- Many variations create command list clutter

These are probably the main reasons why I've avoided prefix/suffix and stuck with the dynamic commands so far.

Cheers!!