hypothesis for multiple string match

Home Forums OpenEars hypothesis for multiple string match

Viewing 8 posts - 1 through 8 (of 8 total)

  • Author
  • #1019788

    Hello again. First off, I admire your work ethic Halle. I don’t know what your hours of operation are but it would seem you never sleep.

    So, I’ve been working on this one problem for a couple days now and I seem to have hit a wall. If you could point me in the right direction, or even give me a hint, I think I could make it work. It’s probably more of a stackOverflow kind of question but I thought I’d ask here in case OpenEars had some specific method for it.

    Using a pair of words spoken, I would like to identify keyword matches and respond accordingly.

    So, for example someone says “DRINK BEER” that would be different than “SMASH BEER”. A beer happens to be available. Let’s call the appropriate method for the keyword match. I am utilizing a series of property list dictionaries, and attempting to use the dictionary’s key to identify the spoken word. Then taking the valueForKey to launch into a BEER function (I’m about to launch into my own BEER function). I am not opposed to switching the dictionaries to arrays, if that would be better programatically.

    The problem seems to be when I try to use something like rangeOfString with hypothesis and my dictionary, it’s having issues. I assume because of my inexperience in extracting Keys from dictionaries? Is there an easier way to ID when two specific words are uttered using the hypothesis and a plist? AllKeys?

    Using something like the code below, I can get close. It will work with two specific strings, but once I try to tie in my dictionary in different ways as a string it starts crashing on me.

    if ([hypothesis rangeOfString:@"DRINK"].location == NSNotFound && [hypothesis rangeOfString:@"BEER"].location == NSNotFound) { //if the words uttered contain drink and beer is equal to notFound.
            NSLog(@"You didn't say what we thought you would..  let's stop here."); 
        } else { 
            NSLog(@"Ah, you drink the beer. It is cold and refreshing."); 

    I also seem to be okay when using single words, using valueForKey:hypothesis, maybe something along those lines? IDK. Again, now that I write it out, I’m starting to realize this isn’t exactly an OpenEars question, it’s more of a plist question, so I apologize.

    Halle Winkler

    Hi Dave,

    Thank you. Basically, I make a best-effort attempt to answer right as questions come in (if it’s feasible and wouldn’t be rude to someone I was with) so I never have a backlog, which lets me keep the support side pretty well under control. So I’d rather take :10 to answer a question in a laid-back way on a Saturday than start a Monday with a backlog that becomes its own time-management task. I usually find that if I can’t handle that approach because a lot more questions than usual are coming in, that indicates that something important is missing from the docs or tutorial.

    I think I can help you with your question since I do a lot of text munging and matching in OpenEars. Your approach sounds fine to me so I suspect an issue in your plist/dictionary code, can you show some?

    BTW, are you acquainted with the [NSString componentsSeparatedByString] method that returns an NSArray? I use it a lot to work with multiple substrings in combination with fast enumeration. rangeOfString is also fine and I frequently use it, but for what you’re doing you might like to have all the hypotheses dumped right into an ordered array for processing.

    Enjoy your BEER function!


    Thanks! My code is a mess right now, I’ll put together my best effort and then post back. I am learning about componentSeparatedByString now. I was not familiar with that, thanks!


    Okee dokes, hello again. My beer function helped me sleep on it, but I’m still missing something. Here’s some of my code I’m working on.

      objectsInRoom = [playerIsNowAt objectForKey:@"ObjectsInLocation"]; //Bringing objects based on location
    NSLog(@"Here are objects in room - %@", objectsInRoom); //logged below
        //Failed experiments
        //NSArray *objectWords = [objectsInRoom allKeys];
        //NSString *objectString = [NSString stringWithFormat:@"%@",objectWords];
        //NSArray *spokenWords = [hypothesis componentsSeparatedByString:@" "];
        //NSString *spokenString = [NSString stringWithFormat:@"%@",spokenWords];
       //if([hypothesis isEqualToString:@"BEER"]) { //only works if they just say BEER 
        if ([hypothesis rangeOfString:@"BEER"].location != NSNotFound){ // ok but how do i make it search thru allkeys for my dictionary??  maybe the next room has WINE or MIMOSA.
            NSLog(@"HOPE KEPT ALIVE");

    THE LOG :
    Here are objects in room – {
    BEER = Beer;
    PEANUTS = Peanuts;
    READ = Menu;

    So, as you see I can seem to pull single words in using Range, but am stuck on returning a value based on the dictionary.

    Other related code.. in .h
    @property (copy, nonatomic) NSDictionary *objectsInRoom;

    in .m
    @synthesize objectsInRoom; //hm, I think i’m supposed to not synthesize these days and use that underscore thingy?

    I’ve only been coding for a few months, so understanding is appreciated.

    Halle Winkler

    OK, this is how you can use fast enumeration (enumeration means looping through the objects in some container) to search for a match against all your keys:

    NSArray *keyArray = [objectsInRoom allKeys];
    for (NSString *key in keyArray) { 
       if([hypothesis rangeOfString:key].location != NSNotFound) {
            NSLog(@"I found a match in the hypothesis for the key %@ so I'm doing the action for that key and breaking.", key);
          if([key isEqualToString:@"BEER"]) {
             NSLog(@"I found BEER");
             [self doBeerThing];
          } else if([key isEqualToString:@"HAMBURGER"]) {
             NSLog(@"I found HAMBURGER");
             [self doHamburgerThing];
          } else {
             NSLog(@"I don't have an action for the hypothesis that I found.");
          break; // Stop enumerating once we've found something from the keys.
    // Next loop will begin if we get here and there are more keys to check

    There are a few different ways this could be organized for efficiency/clarity. For instance you could skip the first general check for any match and go directly to checking for the specific matches you have in mind, and there are a few different ways you can manage the actual “calling a method having found a specific key” part which I haven’t addressed, but this is a simple and fast approach.


    Sweet nectar of the Gods! Thank you so much, that totally makes sense now.

    I was kind of close with a couple attempts yesterday, I forgot to BREAK out of the For loop. :)


    I ultimately modified your solution to be more generic using some ideas here.

    Thanks again, if you take tips email me a paypal address. You helped me out a bunch with this.

    Halle Winkler

    Super, I think that is a very good way to learn — get some basic pointers and then start iterating it so it fits your requirements until you get a sense of familiarity with the pattern or process.

Viewing 8 posts - 1 through 8 (of 8 total)
  • You must be logged in to reply to this topic.