packages feed

duckling-0.2.0.0: Duckling/AmountOfMoney/Helpers.hs

-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.


{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}

module Duckling.AmountOfMoney.Helpers
  ( currencyOnly
  , valueOnly
  , isSimpleAmountOfMoney
  , isCent
  , isCents
  , isDollarCoin
  , isCurrencyOnly
  , isDime
  , isMoneyWithValue
  , isWithoutCents
  , withCents
  , withInterval
  , withMax
  , withMin
  , withValue
  , mkLatent
  , dollarCoins
  )
  where

import Data.HashMap.Strict (HashMap)
import Data.Maybe (isJust)
import Data.String
import Data.Text (Text)
import Prelude

import Duckling.AmountOfMoney.Types
  ( Currency (..)
  , AmountOfMoneyData (..)
  , amountOfMoneyData'
  )
import Duckling.Numeral.Types (getIntValue, isInteger)
import Duckling.Dimensions.Types
import Duckling.Types hiding (Entity(..))

import qualified Data.HashMap.Strict as HashMap

-- -----------------------------------------------------------------
-- Dollar coin Types

dollarCoins :: HashMap Text Double
dollarCoins = HashMap.fromList
  [ ("nickel", 0.05)
  , ("nickels", 0.05)
  , ("dime", 0.1)
  , ("dimes", 0.1)
  , ("quarter", 0.25)
  , ("quarters", 0.25)
  ]

-- -----------------------------------------------------------------
-- Patterns

isCents :: Predicate
isCents (Token AmountOfMoney AmountOfMoneyData{value = Just _, currency = Cent}) = True
isCents _ = False

isWithoutCents :: Predicate
isWithoutCents (Token AmountOfMoney AmountOfMoneyData{currency = Cent}) = False
isWithoutCents (Token AmountOfMoney AmountOfMoneyData{value = Just v}) = isInteger v
isWithoutCents _ = False

isMoneyWithValue :: Predicate
isMoneyWithValue (Token AmountOfMoney AmountOfMoneyData{value = v1, minValue = v2, maxValue = v3}) =
 any isJust [v1, v2, v3]
isMoneyWithValue _ = False

isCurrencyOnly :: Predicate
isCurrencyOnly (Token AmountOfMoney AmountOfMoneyData
  {value = Nothing, minValue = Nothing, maxValue = Nothing}) = True
isCurrencyOnly _ = False

isDollarCoin :: Predicate
isDollarCoin (Token AmountOfMoney AmountOfMoneyData{value = Just d, currency}) =
  elem d [0.05, 0.1, 0.25] && elem currency [Dollar, AUD, CAD, JMD,
                                             NZD,    SGD, TTD, USD]
isDollarCoin _ = False

isSimpleAmountOfMoney :: Predicate
isSimpleAmountOfMoney (Token AmountOfMoney AmountOfMoneyData
  {value = Just _, minValue = Nothing, maxValue = Nothing}) = True
isSimpleAmountOfMoney _ = False

isDime :: Predicate
isDime (Token AmountOfMoney AmountOfMoneyData
  {value = Just d, currency = Cent}) =
  maybe False (\i -> (i `mod` 10) == 0) $ getIntValue d
isDime _ = False

isCent :: Predicate
isCent (Token AmountOfMoney AmountOfMoneyData
  {value = Just c, currency = Cent}) =
  maybe False (\i -> i >= 0 && i <= 9) $ getIntValue c
isCent _ = False

-- -----------------------------------------------------------------
-- Production

currencyOnly :: Currency -> AmountOfMoneyData
currencyOnly c = amountOfMoneyData'{currency = c}

valueOnly :: Double -> AmountOfMoneyData
valueOnly x = amountOfMoneyData'{value = Just x}

withValue :: Double -> AmountOfMoneyData -> AmountOfMoneyData
withValue x fd = fd {value = Just x}

withCents :: Double -> AmountOfMoneyData -> AmountOfMoneyData
withCents x fd@AmountOfMoneyData {value = Just value} = fd
  {value = Just $ value + x / 100}
withCents x AmountOfMoneyData {value = Nothing} =
  amountOfMoneyData'{value = Just x, currency = Cent}

withInterval :: (Double, Double) -> AmountOfMoneyData -> AmountOfMoneyData
withInterval (from, to) fd = fd
  {minValue = Just from, maxValue = Just to, value = Nothing}

withMin :: Double -> AmountOfMoneyData -> AmountOfMoneyData
withMin x fd = fd {minValue = Just x}

withMax :: Double -> AmountOfMoneyData -> AmountOfMoneyData
withMax x fd = fd {maxValue = Just x}

mkLatent :: AmountOfMoneyData -> AmountOfMoneyData
mkLatent fd = fd {latent = True}