Skip to content

3.0.0

Latest
Compare
Choose a tag to compare
@zcohan zcohan released this 22 Nov 03:39

Dynamic place queries

  • A new placeDataProvider property on EngineCustomization supports natural language functions that include places that are dynamically resolved over the internet.

  • Ensure the dynamicPlaceQueries flag is enabled on EngineFeatureFlags to enable this feature (the default is off)

  • Dynamic places are supported in natural language functions, for example:

    • "time in Ubud, Bali"
    • "distance between Bellingen & Nowra"
    • "weather in Assisi, Perugia"
    • "temperature in Narva, Estonia"

A PlaceDataProvider implementation asynchronously geocodes a string query. You can optionally also enable distance calculations between by implementing another function.

protocol PlaceDataProvider {
    
    /// Geocode a given string request
    /// - For example, this might be a place like "Spoleto, Umbria, Italy"
    /// - On Apple platforms, you can use Core Location's `CLGeocoder/geocodeAddressString` class for this
    func placeDataFor(request: String) async throws -> PlaceData?
    
    /// Calculate the distance between two GPS locations
    /// On Apple platforms, you can use Core Location's `CLLocation/distance(from:)` function to calculate this
    /// - This is a synchronous call, because network access is not required to calculate this
    /// - Implement this function to enable "distance from (place) to (place)" style word functions
    /// - Return a unit expression of length (miles or km, up to you)
    func distanceBetween(location1: PlaceData.Coordinates, location2: PlaceData.Coordinates) -> UnitExpression?
    
}

Historical currency conversions

  • The CurrencyRateProvider protocol offers a new function to fetch historical currency rates:
func fetchRateInBackgroundFor(request: CurrencyRateRequest) async -> Decimal?
  • Get the conversion date from the request's new date property and dispatch a query to a web-based data source that supports historical currency conversions (like CurrencyLayer).
  • The synchronous variant rateFor(request: CurrencyRateRequest) -> Decimal? is polled first, to let you return a cached historical rate if available.
  • Ensure the historicalCurrencyQueries flag is enabled on EngineFeatureFlags to enable this feature (the default is off)

Historical weather queries

  • WeatherDataRequest now includes an optional datestamp property.
  • Ensure the historicalWeatherQueries flag is enabled on EngineFeatureFlags to enable this feature (the default is off)

Alternative Result Generator

  • A new AlternativeResultGenerator class can intelligently convert a given CalculationResult into relevant alternative forms
  • For example, a decimal number might be converted into hex, binary and octal, or if below zero, into a fraction, and if above a certain threshold, into scientific notation
  • A unit of time will be converted into a laptime (hh:mm:ss) and timespan (days, hours, minutes, seconds)
  • A date will be converted into ISO8601 format, and a unix timestamp

Date Interval Parsing from String

  • A new dateIntervalFor(_ expression: String) -> DateInterval on Calculator offers intelligent date interval (start and end date) parsing that might be used to power a natural language event scheduling feature

Loading engine content from an external bundle

SoulverCore now supports loading its content files (containing places, units & functions, etc) from an externally located bundle directory. Previous versions always loaded resources included in the framework's resource folder.
To load resources from an external source:

  • First make a resources bundle ResourceBundle(url: URL)? with a URL pointing to your resources bundle.
  • This initializer is failable to ensure that your resources bundle is valid
  • Use the dedicated initializer on EngineCustomization that takes a ResourcesBundle: init(resourcesBundle: ResourceBundle, locale: Locale)

Breaking API changes

In connection with allowing an EngineCustomization to be loaded from an external bundle, we've moved away from all singletons in the framework, including CurrencyList and StaticResources.

  • Functions for getting lists of content primitives (currencies & places) formally provided by these objects are now available on EngineCustomization

Minor features

  • Additional percentage shorthand: "5 of 50" (as a shorthand of "5 as a % of 50")
  • Convert time to decimal: "10:45 to decimal" (= 10.75)
  • Support for interpreting sub-zero numbers like 0.001 as 0,001in an EU locale (with MisplacedThousandsSeparatorBehavior set to interpretAsDecimalPoint)

Bug fixes

  • Fixed a crash when doing fact(99999.999)
  • Fixed a bug with auto converting a conversion in parentheses while using answer auto conversion mode
  • Fixed a bug where you couldn't convert rates of fluid oz/acre into mL/ha (because the first rate was being converted into meters)