Skip to content

Releases: soulverteam/SoulverCore

3.0.0

22 Nov 03:39
Compare
Choose a tag to compare

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)

2.7.1

15 Oct 05:39
Compare
Choose a tag to compare

Time & Date Calculations

  • Support for adding timespans with the form hh:mm with more than 24 hours in the hour component
  • Added phrases to get day of month and week of month date components from the current day or a particular date

Bug fixes

  • Fixed an issue with the automatic result conversion mode incorrectly invoking with a single phrase function
  • Fixed an issue affecting stale variable dependencies in rare cases in LineCollection

2.7.0

25 Sep 11:16
Compare
Choose a tag to compare

This version of SoulverCore has been built for Swift 6 with Xcode 16

New Functions

Data Transfer Functions

New function makes it easier to work out how long files will take to download or upload.

  • "time to 3GB at 10 MB/s" (= 300 s)
  • Or specify an explicit unit: "minutes to 35GB at 200MB/s" (= 2.92 min)

Speeding Up Time Functions

New function to speed up time by a multiplier:

  • "1 hour 30 minutes at 1.5x" (= 1 hour)

You can also calculate the time saved:

  • "time saved 1 hour 30 minutes at 1.5x" (= 30 minutes)

Financial Functions

Added a new function for working out how much money you need in the bank to ensure a certain amount of interest:

  • "deposit needed for $42k/year at 7.5%" (= $560k)
  • "savings required for $10k/month @ 5.6% (=$2.143M)

Added additional variants for compounding monthly and quarterly:

  • "interest on $100 after 3 years at 10% compounding monthly"
  • "interest on $100 for 3 years at 10% compounding quarterly"

Percentage functions

New functions to display the percentage change from one number by an amount

  • "3k on 50k" (= 6%)
  • "50 off 150" (= 33%)

Lunar day

  • Get the current lunar day: "lunar day" or "moon day"
  • Or the lunar day on a particular date: "lunar day on March 12, 2025"

Units

  • Added support for unit expressions with a fractional value, like "1 1/2 pounds"
  • Added cubic micrometer & square nanometer units
  • Improved behaviour of certain unit multiplications, where they would not return in the most relevant form: "3 min × 15 mph" now returns "0.75 mi" rather than 1,207 m

Currencies

  • Polygon symbol (formally MATIC) updated to POL
  • Added sub-domination ETH currencies: Wei and Gwei

Conversions

  • Support for automatic conversion of units without explicit value: "usd eur" will be interpreted as "1 usd in eur"
  • More flexible unit conversion for ostensibly incompatible units: "3 mph to minutes" (convert to miles/minute), "10 cubic centimeters to meters" (convert to cubic meters)
  • Support for conversion from & into imperial volume units explicitly, like "1 liter in imperial pints"

Other

General

  • Added power phrase functions like: "3 to the power of 9", "4 raised to 5"
  • Support for min/max functions with percentages
  • Combination and permutation functions now support numerically larger parameters
  • Added additional trigonometry functions that take their parameter in degrees: "asind", "acosd", "atand" and "tand"
  • Added (sample) standard deviation function: "standard deviation of 10, 20, 30 and 40"
    • You can also use "std dev of …" as a shorthand

Time zones

  • Support for "Korea" as an alias of "South Korea"

Bug fixes

  • Fixed a date parsing issue where a number like "1.003.020" was being misinterpreted as a date ("01.03.20")
  • Fixed a lexing issue with feet units that are written with a trailing apostrophe, like 30.334'
  • Fixed an issue with min/max list functions and negative currencies

API

Breaking changes

  • We're working towards only depending on API available in the modern Swift FoundationEssentials & FoundationInternationalization,
  • This version takes the first step in this direction by weaning off uses of NS prefixed classes (NSNumber, NSString, NSRegularExpression etc).
  • For our public API, this change only affects the range property on Token:
    • It is now typed to a similar Token.Range struct, rather NSRange.
    • You can still get an NSRange for a token if needed using token.range.nsRange
  • ECBCurrencyRateProvider now uses swift async/await for rate updates, rather than a closure.

Parsing options

  • Added a DateParsingOptions to EngineFeatureFlags that lets you specify the default time for dates without times (either midday or midnight)

Places

  • Cites, airports and countries now offer a 2-letter ISO country code property

2.6.3

26 Apr 08:20
Compare
Choose a tag to compare

Percentage functions

  • New percentage function: "3 as % with 7, 8 and 9" (= 11.11%)
  • This function gets the percentage of one number of a whole (including the number), a shorthand for "3 as % of (3 + 7 + 8 + 9)".

Future date seeking mode

  • Compound units of time are now supported in date seeking mode (for example "in 1 hour 20 minutes" will return a date 1 hour and 20 minutes from now)

Automatic conversion mode

  • Added a case for nanoseconds to automatically convert into milliseconds

Bug fixes & improvements:

  • Fixed a crash introduced in the previous build when doing certain date interval calculations
  • Fixed a rare issue with fractions potentially being incorrectly formatted
  • Fixed an issue with pitch to hz conversion not enough precision for rounded results in some cases

2.6.2

09 Apr 09:56
Compare
Choose a tag to compare

Improvements

  • Support for rates in lists (like "mean of 0.09615 $/kWh and 0.10965 $/kWh")
  • The base unit for volume units is now cubic meters (rather than liters). This enables SoulverCore to return a result of meters for expressions like "200000 L / 125 m^2"
  • Support for "dec" as a synonym of "decimal"
  • Fixed a hang related to using 0 as in a list with the lcm function
  • Fixed a bug with the future date seeking mode, for dates in the past that had a specified time of day

2.6.1

26 Mar 21:06
Compare
Choose a tag to compare

Places

  • Added new properties country and city on Place. These will return the associated country for a City, and the capital city of a Country. It will also return the associated city with an Airport place
  • Added some additional places: Mauritius, French Guiana, Martinique, La Réunion, & Guadeloupe

Units

  • Support for generic custom units (defined not in terms of an existing unit)
  • Use undefined as your equivalentUnitIdentifier

Linear growth functions

  • Linear growth functions can now omit the starting quantity (it will be assumed to be 0)
  • For instance "time to $100 at $4 every hour" (= 25 hours)

Misc

  • CSS units (em, rem & px) will now always be formatted using a standard US decimal character (.) so they can be immediately pasted into CSS files.
  • Phrases like "days left in 2024" now use round numbers
  • Fixed an issue with a spaceless compound quantity of time not being correctly recognized, like "2hr1min"
  • You can now convert timespans into "months and days"

2.6.0

15 Mar 11:26
Compare
Choose a tag to compare

Currency symbols

  • New CurrencySymbolSettings enum on EngineCustomization
  • Set to .automatic (the default) for the most logical currency symbol settings for the current locale
  • Added "tenges" as a synonym for Kazakhstani Tenges

Bug fixes

  • "tonne" now maps to metric ton, rather than short tons.
  • iso8601 time stamps with sub-second components and negative timezone offsets are now recognized correctly.
  • Fixed an issue with hex/binary/octal numbers not working with log functions
  • Fixed an issue where raising area and volume units to fractional powers would not perform the correct operation
  • Fixed an issued where single letter prefix currency symbols were not parsing correctly (like "R100", used in South Africa)

2.5.0

20 Feb 09:38
Compare
Choose a tag to compare

Calendar Calculations

Timespans

  • Added support for time spans expressed in two units "in minutes and seconds", "in hours and minutes", "in days and hours", "in weeks and days"
  • Support for "as time span" as a synonym for "as timespan"
  • Timespans, rather than single time units, are now used after more operations on single quantities of time
  • For example, "25 min / 12" = (2 min 5 second), "1h20m + 45m" = (2 hours 5 min)
  • We now use fixed time units (weeks, days, minutes, etc), not variable ones (years, months), when "as timespan" is specified for the result

Format dates using format patterns

  • For example, "March 12, 2023 as EEEE, MMM d, yyyy" (= Sunday, Mar 12, 2023)
  • Or "March 12, 2023 as MM/dd/yy" (= 03/12/23)
  • The pattern language is defined by the Unicode Technical Standard #35
  • Here is a good cheat sheet (RIP Alex Hay)

Timezone codes

  • Added a new TimezoneCodeCorrectionBehavior enum that can be used on an EngineFeatureFlags on an EngineCustomization
  • This includes a new option to only "correct" non-summer timezone codes

Other

  • Add support for dates with the form "13 March 23" (the year is assumed to be the (20)23, and the day 13)
  • Workaround an issue in Foundation's Calendar which sometimes interprets "Feb 29" as an invalid date (even in a leap year)

General

Pounds & ounces

  • New "Pounds & ounces" output format: "87 ounces" will return "5 lb 7 oz"
  • Explicitly convert with "in pounds and ounces" or "in lb oz"

Locales

  • Fixed an issue introduced in 2.4.7 where the . symbol was not being correctly interpreted as a decimal point in locales like French & Russian, in which this symbol is not defined as either a decimal point or thousands separator
  • Support for automatic 3 dp of accuracy in currency results, when used in locales like French and Russian: €12,995 - €1,747 = €11,248 (the result is 11, not 11 thousand)

Other

  • Support for applying SI scalars (k, M, G, etc) to sub-expressions (500)k and line references in LineCollection
  • With the variable declarations feature flag disabled, expressions that include the = symbol will no longer return results

Engine Configuration

EngineFeatureFlags (note: possibly source breaking change)

  • The EngineFeatureFlags object has been tidied up and certain flags removed
  • EngineFeatureFlags had become a bit of a catch-all object over time, with many legacy properties. We felt it was time to make it more friendly for newcomer to the framework, and also more ergonomic for everyone
  • It is unlikely you were using any of the removed feature flags. However, please email us or open a discussion a flag you were depending on is no longer available

Commenting

  • Added a new CommentingOptions object (set the commentingOptions property on LineCollection) to customize which commenting features you want to support in multi-line calculations
  • Calculator no longer supports commenting features (they continue to be available on LineCollection)

2.4.7

31 Jan 03:32
Compare
Choose a tag to compare

Thousands separator as decimal point

  • A new property misplacedThousandsSeparatorBehavior on EngineFeatureFlags and can be set to control how numbers with thousands separators in the wrong position should be handled (allow, disallow or interpretAsDecimalPoint)
  • With the interpretAsDecimalPoint option, Europeans that use , as a decimal separator can now also use . in unambiguous cases (like "1,3 + 1.3 = 2,6")

Number formatting

  • Crypto-currencies no longer round to 2 dp (they're not regular currencies to exhibit this behaviour)
  • Numbers formatted with SI notation now respect the dp property in FormattingPreferences
  • For Europeans, SoulverCore will now automatically show 3 dp of accuracy in results when 3 dp is also used in a currency expression (for example "€12,995 - €1,747 = €11,248"). Note that this result is not eleven thousand

Calendar calculations

  • Support for time interval expressions with year stamps, like today - 1973

Lists

  • Support for subexpressions inside lists, like "max (3+4), 5, 3" (= 7)

Bug fixes

  • Workaround an issue in Foundation where NSDecimalPower() can return incorrect results (like for 0.1^1000)
  • Fixed an issue with future date seeking mode, when inputing unambiguous dates earlier in the year

2.4.6

24 Jan 04:03
Compare
Choose a tag to compare

Timezones

  • Added some missing timezones for some small countries (Brunei, the Maldives, and some others)
  • You can use the "Europe" timezone (like "time in Europe"). We fetch the time in Brussels (often considered the capital of Europe)

Sinh function

  • Fixed an issue with the sinh function incorrectly calling cosh instead
  • Fixed an issue where sinh(10000) could crash SoulverCore