Author Topic: How to return the index of the spoken word/phrase within a command segment  (Read 1253 times)

AlanBell68

  • Newbie
  • *
  • Posts: 6
Is it possible to return the index of the spoken word/phrase within a command segment.

Example:
I have an a series of words/phrases that can be spoken within a command segment (in this case the second command segment).

When I say :  "SELECT ITEM1,ITEM2,ITEM3...ITEM20"

I need to get the zero based index of the spoken word/phrase in the second command segment.

So if I say "SELECT ITEM2" it will return 1, if I return SELECT ITEM 5 it will return 4, which I would assign into an integer variable "Index", for example.

My goal is to take this sequential number and convert it into a coordinate system in a 4x5 matrix, that corresponds to an on screen grid of options.

So, I will take the Integer division of the index by 4 as the row number, and the modulus of the index as the column number.

I will then multiply the row number and column number by the respective width and height of each tile (all tiles are the same size) to determine coordinates to send to a mouse move operation.

Any suggestions of a way of implementing this without a huge complex IF ELSE THEN statement would be great, as the above would seem the least complex to code and maintain.

Thanks in advance for any insight.

Gary

  • Administrator
  • Hero Member
  • *****
  • Posts: 2824
Re: How to return the index of the spoken word/phrase within a command segment
« Reply #1 on: February 25, 2023, 05:20:21 PM »
VoiceAttack does not store the index of the spoken phrases in a dynamic or multi-phrase command, no.

You can, however, extract the numeric portion of the text from the command into an integer by choosing the 'Set an Integer Value' action and then converting this token (using the 'convert text/token' option):  {TXTNUM:"{CMD}"}  (note the double quotes).  That will stuff the numeric portion of your command into the integer variable that you choose.  From there, you can use the variable for whatever you like.

Side note on what is going on (for those reading along) - If your spoken phrase ({CMD} token) results, for instance,  in 'Select Item 1', the {TXTNUM} token removes everything in the phrase but the '1'.  The resulting '1' is a text value (as are the results of all rendered tokens) and must be converted in order to be used as an integer.  Setting an integer variable's value to the rendered {TXTNUM:"{CMD}"} expression by using 'Convert text/token' will do the conversion for you.


Hope that helps!

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: How to return the index of the spoken word/phrase within a command segment
« Reply #2 on: February 25, 2023, 07:48:09 PM »
I tend to use inline functions for this type of thing.

E.G.
Code: [Select]
Inline C# Function: Find spoken item and calculate corresponding coordinates, wait until execution finishes
Move mouse cursor to screen coordinates by text/token X:{INT:~x}, Y:{INT:~y}
Click left mouse button
where "Find spoken item and calculate corresponding coordinates" contains
Code: [Select]
using System;
using System.Windows.Forms;

public class VAInline
{
string[] items =
{
"Item 1", "Item 2", "Item 3",
"Item 4", "Item 5", "Item 6",
"Item 7", "Item 8", "Item 9",
};

const int itemsPerColumn = 3;
const int startingX = 100; //Leftmost cursor position for the item in column 1, row 1
const int startingY = 200; //Topmost cursor position for the item in column 1, row 1
const int columnOffset = 100; //Distance from the starting point the cursor should move horizontally for each column but the first
const int rowOffset = 200; //Distance from the starting point the cursor should move vertically for row but the first


public void main()
{
if (VA.Command.Action() == "External")
{
Clipboard.SetText("Select [" + String.Join(";", items) + "]"); //The "When I say" contents are configured here
VA.WriteToLog("\"When I say\" contents copied to clipboard", "black");
return;
}

int spokenItemIndex = Array.FindIndex(items, x => x.Equals(VA.Command.Segment(1), StringComparison.CurrentCultureIgnoreCase));

if (spokenItemIndex == -1)
{
VA.WriteToLog("Error: Spoken item could not be found", "red");
return;
}

VA.SetInt("~x", startingX + ((spokenItemIndex % itemsPerColumn) * columnOffset));
VA.SetInt("~y", startingY + ((spokenItemIndex / itemsPerColumn) * rowOffset));
}
}

You can input the names of your items as elements of the "items" array, as shown (I.E. the name of your item, wrapped in double quotes, followed by a comma).
The item definitions don't actually need to be arranged in a grid; you could put them all on one line of you wanted to.

Instead of then manually needing to input those same values in the "When I say" field of the command, you can execute the command from the command list (by right-clicking it and choosing "Execute"), which will copy the appropriately-formatted values to the clipboard, after which you can edit the command and paste them into the "When I say" field



If you'd prefer to input the item names outside of the inline function, this alternate version could be used:
Code: [Select]
Set text [~items] to 'Item 1;Item 2;Item 3;Item 4;Item 5;Item 6;Item 7;Item 8;Item 9'
Inline C# Function: Find spoken item and calculate corresponding coordinates, wait until execution finishes
Move mouse cursor to screen coordinates by text/token X:{INT:~x}, Y:{INT:~y}
Click left mouse button
where "Find spoken item and calculate corresponding coordinates" contains
Code: [Select]
using System;
using System.Windows.Forms;

public class VAInline
{
const int itemsPerColumn = 3;
const int startingX = 100; //Leftmost cursor position for the item in column 1, row 1
const int startingY = 200; //Topmost cursor position for the item in column 1, row 1
const int columnOffset = 100; //Distance from the starting point the cursor should move horizontally for each column but the first
const int rowOffset = 200; //Distance from the starting point the cursor should move vertically for row but the first


public void main()
{
string[] items = VA.GetText("~items").Split(';');

if (VA.Command.Action() == "External")
{
Clipboard.SetText("Select [" + String.Join(";", items) + "]");
VA.WriteToLog("\"When I say\" contents copied to clipboard", "black");
return;
}

int spokenItemIndex = Array.FindIndex(items, x => x.Equals(VA.Command.Segment(1), StringComparison.CurrentCultureIgnoreCase));

if (spokenItemIndex == -1)
{
VA.WriteToLog("Error: Spoken item could not be found", "red");
return;
}

VA.SetInt("~x", startingX + ((spokenItemIndex % itemsPerColumn) * columnOffset));
VA.SetInt("~y", startingY + ((spokenItemIndex / itemsPerColumn) * rowOffset));
}
}

AlanBell68

  • Newbie
  • *
  • Posts: 6
Re: How to return the index of the spoken word/phrase within a command segment
« Reply #3 on: February 26, 2023, 07:57:22 AM »
Thanks for the suggestions. I will have to look into this.
I will need to research inline code before, as this is a new territory.
Thanks again!