Engine Mobile SDK

Following is documentation and examples for accessing Engine in your app. Note that the current release (2.7.0) does not support remote configuration of circumstances. In this release, circumstance may only be defined programmatically, then compiled into your app.


Circumstances

Circumstances are the primary element of Engine.

Following are some typical circumstances you might configure Engine to handle:

  • Any time a user is at a restaurant on a weekend night, in an area they don’t often frequent, and they are near a bar that will be showing live music in an hour.
  • Any time a user is at a coffee shop they’ve never been to, but the user regularly frequents other coffee shops.
  • Any time a user is at a big electronics store that is closed, and is near another one that is open.

Engine provides the following ways for working with circumstances:

Circumstance Notifiers - You can specify a particular circumstance you are interested in and Engine will notify your app delegate when the circumstance occurs. You provide an app delegate for handling the response. Think about this as: let me know if this enters a circumstance I should handle.

Circumstance On-Demand - You can also directly invoke a test to see if a user is within a specified circumstance on-demand. Think about this as: is this user RIGHT NOW in a circumstance that I should handle?


Defining Circumstances

Circumstances are defined as S-expressions. We’ve chosen this format because it’s:

  • Efficient.
  • Flexible.
  • Familiar to most programmers.
  • Platform neutral.
  • Generally easy to read.


Syntax

Currently (release 2.7.0), the following predicates are available:

Predicate Description
= The = predicate must be in the form (= factual-id “a9d73ec3-48be-4829-8173-d6c44e58a424”), where the second element of the list is one of factual-id, category-id, or chain-id.
at Determine if a user is at a place identified by a Factual place Id, a chain Id, or a category Id.
near Determine if a user is near a place identified by a Factual place Id, a chain Id, or a category Id.
is-open Determine if specified place is open or closed.
any-of For specifying multiple ids at once.
and Use this for logically ANDing circumstances requirements.
or Use this for logically ORing circumstances requirements.
not e.g (not is-open).

A couple of notes:

  • at and near can contain multiple expressions, which are ANDed together.
  • The first expression of near must be either an = expression or an or of = expressions.
  • and, or, and not can be nested in each other.
  • at and near expressions cannot appear in other at and near expressions.


Examples

The following examples reference Factual Ids, category Ids, and chain Ids.

IMPORTANT!
A known bug currently is that circumstances for nested categories are not bubbling up. For example, a circumstance for Social > Bars would be coded as: (at (= category-id 312)). However, this circumstance would not be triggered by a place categorized as 313 (Social > Bars > Hotel Lounges). For this release, the direct solution is to or categories together. E.g., (at (or (= category-id 312) (= category-id 313)))


At any restaurant

(at (= category-id 347))
  • 347 is the category Id for Social > Food and Dining > Restaurants


At any restaurant or a bar

(or (at (= category-id 312)) (at (= category-id 347)))
  • 312 is the category Id for Social > Bars
  • 347 is the category Id for Social > Food and Dining > Restaurants


At any restaurant or a bar, using the any-of shorthand

(at (any-of category-id 312 347))


At a Starbucks near a Peet’s Coffee & Tea

(and (at (= chain-id "ab4c54c0-d68a-012e-5619-003048cad9da"))
     (near (= chain-id "e60a5d2d-6e9e-4d3b-bfe4-5cebfc0c3d97")))
  • “ab4c54c0-d68a-012e-5619-003048cad9da” is the chain Id for Starbucks.
  • “e60a5d2d-6e9e-4d3b-bfe4-5cebfc0c3d97” is the chain Id for Peet’s Coffee & Tea.


At a closed Best Buy, near an open electronics store

(and (and (at (= chain-id "ab4affd0-d68a-012e-5619-003048cad9da")) (not is_open))
     (and (near (= category-id 133)) is_open))
  • “ab4affd0-d68a-012e-5619-003048cad9da” is the chain Id for Best Buy
  • 133 is the category Id for Retail > Computers and Electronics


Near the Los Angeles Staples Center

(near (= factual-id "d9d3c9e1-983d-438b-8970-ebaddaa71386"))
  • “d9d3c9e1-983d-438b-8970-ebaddaa71386” is the Factual Id for the Staples Center.


Registering Circumstances

In order to evaluate any of these circumstance expressions, you need to register them against either a notifier or an on-demand responder.

A notifier watches for occurrences of a circumstance passively, and calls to your delegate if the circumstance is seen. On-demand circumstances enable you to evaluate the same circumstances at any time of your choosing (for example, when starting your app).


Circumstance Notifiers

Register a Circumstance Notifier

The following method will create and register a circumstance notifier to monitor for the device being at any Starbucks, upon arrival of a new location:

[[FactualEngine sharedEngine] registerCircumstanceNotifierWithId:@"foo"
                              expr:@"(at (= chain-id \"ab4c54c0-d68a-012e-5619-003048cad9da\"))"
                              when:@"arriving"
                              delegate:self];
parameter description
registerCircumstanceNotifierWithId Provide a unique identifier for this circumstance. You may need this to stop/restart the circumstance. Also, if you have multiple circumstances mapped to the same delegate, you can use this Id to determine which circumstance generated the callback to your delegate.
expr An expression representing the circumstance you are detecting. Expressions are documented above.
when When this circumstance is evaluated (arriving, departing).
delegate Your circumstance handling delegate.


Disable Circumstance Notifier

The following method call will temporarily cease evaluation of the associated circumstance notifier:

[[FactualEngine sharedEngine] disableCircumstanceNotifierWithId:@"my_circumstance"];
parameter description
disableCircumstanceNotifierWithId A unique identifier for the circumstance notifier to be disabled.


Re-enable Circumstance Notifier

The following method call re-enables evaluation of the associated circumstance notifier:

[[FactualEngine sharedEngine] enableCircumstanceNotifierWithId:@"my_circumstance"];
parameter description
enableCircumstanceNotifierWithId A unique identifier for the circumstance notifier to be enabled.

Unregister a Circumstance

The following method call will permanently remove a circumstance from the list of circumstances to be evaluated:

[[FactualEngine sharedEngine] unregisterCircumstanceWithId:@"my_circumstance"];
parameter description
unregisterCircumstanceWithId A unique identifier for the circumstance notifier to be removed.


Circumstance On-Demand

Evaluate a Single Circumstance

The following method will check to see if the user is currently at any Starbucks:

// register the circumstance
[[FactualEngine sharedEngine]
  registerCircumstanceOnDemandWithId:@"my_id"
                                expr:@"(at (= chain-id \"ab4c54c0-d68a-012e-5619-003048cad9da\"))"
                            delegate:myDelegate]

// evaluate it (not that you are referencing the same id)
NSError *anyError;
[[FactualEngine sharedEngine] evaluateCircumstanceWithId:@"my_id"
                                                   error:&anyError];
parameter description
evaluateCircumstanceWithId Id of a circumstance to evaluate immediately.
error If the circumstance specified was not registered prior to the request to evaluate, an error will be returned here.


Evalute All Circumstances

The following method will evaluate all registered on-demand circumstances:

[[FactualEngine sharedEngine] evaluateAllCircumstances];
  • There are no parameters for this method.


Handling Circumstances

In order to handle notification of a circumstance being met, you will need to define a delegate for handling the notification:

// the circumstance was met.
- (void)factualCircumstanceDidOccur:(FactualCircumstance *)circumstance;

// something went wrong
- (void)factualCircumstance:(FactualCircumstance *)circumstance didFailWithError:(NSError *)error;

// some data was generated for debugging purposes.
- (void)factualCircumstance:(FactualCircumstance *)circumstance didReportDebugInfo:(id)debugInfo;


Current Location

Aside from circumstances, Engine enables you to use its on-device places data to generate a list of potential “check-in” candidates at the current location of the device.


Getting the Place Candidates

You get a list of candidates as follows:

// get a list of place candidates:
[[FactualEngine sharedEngine] genPlaceCandidatesWithDelegate: self];
parameter description
genPlaceCandidatesWithDelegate Your app delegate. See above.


Handling Place Candidates

You’ll need to implement a delegate to handle the place attachment candidates:

// the results were returned
- (void)factualDataRequest:(FactualDataRequest *)request didFinishWithData:(id)data;

// an error occurred generating the results.
- (void)factualDataRequest:(FactualDataRequest *)request didFailWithError:(NSError *)error;

The FactualDataRequestDelegate accepts the candidates as a JSON object. The candidate list will contain names, and (when appropriate) Factual Ids. If an activity is listed rather than a place (e.g., “driving”), no meta-data beyond confidence and name will be provided.

Here’s a sample of the candidate list JSON:

{
  "latitude": 33.993088,
  "longitude": -118.442182,
  "candidates":
  [
    {
      "name":"driving"
    },
    {
      "name":"Dunkin' Donuts",
      "place_id": "0294221d-dc0d-4f10-bd09-9bf5920d97d3",
      "chain_id": "2cb519f8-883c-4263-860a-cd83325fbb97",
      "place_category_ids":[339],
      "placerank": 44,
      "is_open":true,
      "distance": 29.279483443232,
      "distance_to": "point",
      "latitude": 33.993074,
      "longitude": -118.442397,
      "threshold_met":"high"
    }
  ]
}


Place Verification

Verifying locations after users have manually indicated their location (e.g., picked a location from a candidate list) can help improve future accuracy of the current location candidates for your app.

If, after presenting the list of place candidates to your end user, the user verifies the location by means of some kind of check-in UI or similar, you can log the verified location as follows:

[[FactualEngine sharedEngine] verifyLocation:@"b8804733-db42-4ac0-8816-fbe2cdd78c96"];
parameter description
verifyLocation Factual Id of the verified location. Note that the Factual ID MUST be present in the result set from the preceding genPlaceCandidatesWithDelegate invocation.