Following is documentation and examples for running Engine in your app. Note that the current release (2.12.1) does not support remote configuration of circumstances. In this release, circumstance may only be defined programmatically, then compiled into your app.
Circumstances are the primary element of Engine.
Following are some typical circumstances you might configure Engine to handle:
Circumstances are defined as S-expressions. We’ve chosen this format because it’s:
true. More will be added later.
notcan be nested in one another.
any-factual-placecan only appear within
nearexpressions are implicitly
nearexpression must have at least one sub-expression. The first sub-expression is the pre-filter, which must be either an
any-ofexpression or an
any-ofpredicate must be in the form
(= factual-id "foo"), where the second element of the list is one of
any-ofpredicate must be in the form
(any-of factual-id "foo" "bar"), like
any-ofexpression whose second element is
threshold-metmust have values
The DSL runner returns only a boolean result initially. Another method returns the relevant
Places for an
near expression are returned if the
near is the only filter or is only in an
or. If the
near is in an
and, the places are only returned if the outermost
and succeeds. An
near inside a
not never returns the places.
is-open for a place that doesn’t have an
hours field is false.
The following examples reference Factual Ids, category Ids, and chain Ids.
(at (= category-id 347))
(or (at (= category-id 312)) (at (= category-id 347)))
(at (any-of category-id 312 347))
(and (at (= chain-id "ab4c54c0-d68a-012e-5619-003048cad9da")) (near (= chain-id "e60a5d2d-6e9e-4d3b-bfe4-5cebfc0c3d97")))
(and (at (= chain-id "ab4affd0-d68a-012e-5619-003048cad9da") (not is-open)) (near (= category-id 133) is-open))
(near (= factual-id "d9d3c9e1-983d-438b-8970-ebaddaa71386"))
The default threshold for Engine determining a user is at a place is
"low". It is intended to provide a reasonable
level of confidence that the device is at the place defined in your DSL expression. If you find that the false positive rate for users being at specific places is too high for your use case, you can override the threshold:
(at (= chain-id "ab4c54c0-d68a-012e-5619-003048cad9da") (= threshold-met "high"))
Engine will monitor for the device fulfilling the specified circumstance when the device has either arrived at or departed from a location, and will notify your delegate if the circumstance has been met.
[[FactualEngine sharedEngine] registerCircumstanceNotifierWithId:@"foo" expr:@"(at (= chain-id \"ab4c54c0-d68a-012e-5619-003048cad9da\"))" when:@"arriving" delegate:self];
|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 (either
|delegate||A delegate implementing the FactualCircumstanceDelegate interface.|
Temporarily cease monitoring of a specified circumstance:
[[FactualEngine sharedEngine] disableCircumstanceNotifierWithId:@"my_circumstance"];
|disableCircumstanceNotifierWithId||A unique identifier for the circumstance notifier to be disabled.|
Re-enable monitoring a specified circumstance:
[[FactualEngine sharedEngine] enableCircumstanceNotifierWithId:@"my_circumstance"];
|enableCircumstanceNotifierWithId||A unique identifier for the circumstance notifier to be enabled.|
Permanently cease monitoring for a specified circumstance:
[[FactualEngine sharedEngine] unregisterCircumstanceWithId:@"my_circumstance"];
|unregisterCircumstanceWithId||A unique identifier for the circumstance notifier to be removed.|
In order to handle notification of a circumstance being met, you will need to define a delegate implementing the FactualCircumstanceDelegate interface:
// 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;
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.
You get a list of candidates as follows:
// get a list of place candidates: [[FactualEngine sharedEngine] genPlaceCandidatesWithDelegate: self];
|genPlaceCandidatesWithDelegate||A delegate implementing the FactualDataRequestDelegate interface.|
In order to handle a place candidate list being returned, you will need to define a delegate implementing the FactualCircumstanceDelegate interface:
// 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 an NSDictionary object containing:
For each place, you’ll receive:
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"];
|verifyLocation||Factual Id of the verified location. Note that the Factual ID MUST be present in the result set from the preceding genPlaceCandidatesWithDelegate invocation.|