2017-03-08 21:33:55 +03:00
|
|
|
-- Copyright (c) 2016-present, Facebook, Inc.
|
|
|
|
-- All rights reserved.
|
|
|
|
--
|
|
|
|
-- This source code is licensed under the BSD-style license found in the
|
2019-05-22 20:36:43 +03:00
|
|
|
-- LICENSE file in the root directory of this source tree.
|
2017-03-08 21:33:55 +03:00
|
|
|
|
|
|
|
|
|
|
|
{-# LANGUAGE DeriveAnyClass #-}
|
|
|
|
{-# LANGUAGE DeriveGeneric #-}
|
|
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
|
|
{-# LANGUAGE NoRebindableSyntax #-}
|
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
|
|
|
|
|
|
module Duckling.Volume.Types where
|
|
|
|
|
|
|
|
import Control.DeepSeq
|
|
|
|
import Data.Aeson
|
|
|
|
import Data.Hashable
|
|
|
|
import Data.Text (Text)
|
|
|
|
import GHC.Generics
|
|
|
|
import Prelude
|
|
|
|
import Duckling.Resolve (Resolve (..))
|
2018-08-24 21:17:30 +03:00
|
|
|
import qualified Data.Text as Text
|
|
|
|
import qualified Data.HashMap.Strict as H
|
2017-03-08 21:33:55 +03:00
|
|
|
|
|
|
|
data Unit
|
|
|
|
= Gallon
|
|
|
|
| Hectolitre
|
|
|
|
| Litre
|
2021-02-02 09:43:09 +03:00
|
|
|
| Centilitre
|
2017-03-08 21:33:55 +03:00
|
|
|
| Millilitre
|
|
|
|
deriving (Eq, Generic, Hashable, Ord, Show, NFData)
|
|
|
|
|
|
|
|
instance ToJSON Unit where
|
|
|
|
toJSON = String . Text.toLower . Text.pack . show
|
|
|
|
|
|
|
|
data VolumeData = VolumeData
|
2018-08-24 21:17:30 +03:00
|
|
|
{ value :: Maybe Double
|
|
|
|
, unit :: Maybe Unit
|
|
|
|
, minValue :: Maybe Double
|
|
|
|
, maxValue :: Maybe Double
|
2017-03-08 21:33:55 +03:00
|
|
|
}
|
|
|
|
deriving (Eq, Generic, Hashable, Ord, Show, NFData)
|
|
|
|
|
|
|
|
instance Resolve VolumeData where
|
|
|
|
type ResolvedValue VolumeData = VolumeValue
|
2018-08-24 21:17:30 +03:00
|
|
|
resolve _ _ VolumeData {value = Just v, unit = Just u} =
|
|
|
|
Just (simple u v, False)
|
|
|
|
resolve _ _ VolumeData {value = Nothing, unit = Just u
|
|
|
|
, minValue = Just from, maxValue = Just to} =
|
|
|
|
Just (between u (from, to), False)
|
|
|
|
resolve _ _ VolumeData {value = Nothing, unit = Just u
|
|
|
|
, minValue = Just v, maxValue = Nothing} =
|
|
|
|
Just (above u v, False)
|
|
|
|
resolve _ _ VolumeData {value = Nothing, unit = Just u
|
|
|
|
, minValue = Nothing, maxValue = Just v} =
|
|
|
|
Just (under u v, False)
|
|
|
|
resolve _ _ _ = Nothing
|
|
|
|
|
|
|
|
data IntervalDirection = Above | Under
|
|
|
|
deriving (Eq, Generic, Hashable, Ord, Show, NFData)
|
2017-03-08 21:33:55 +03:00
|
|
|
|
2018-08-24 21:17:30 +03:00
|
|
|
data SingleValue = SingleValue
|
2017-03-08 21:33:55 +03:00
|
|
|
{ vUnit :: Unit
|
|
|
|
, vValue :: Double
|
|
|
|
}
|
2018-08-24 21:17:30 +03:00
|
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
instance ToJSON SingleValue where
|
|
|
|
toJSON SingleValue {vUnit, vValue} = object
|
|
|
|
[ "value" .= vValue
|
|
|
|
, "unit" .= vUnit
|
|
|
|
]
|
|
|
|
|
|
|
|
data VolumeValue
|
|
|
|
= SimpleValue SingleValue
|
|
|
|
| IntervalValue (SingleValue, SingleValue)
|
|
|
|
| OpenIntervalValue (SingleValue, IntervalDirection)
|
|
|
|
deriving (Show, Eq)
|
2017-03-08 21:33:55 +03:00
|
|
|
|
|
|
|
instance ToJSON VolumeValue where
|
2018-08-24 21:17:30 +03:00
|
|
|
toJSON (SimpleValue value) = case toJSON value of
|
|
|
|
Object o -> Object $ H.insert "type" (toJSON ("value" :: Text)) o
|
|
|
|
_ -> Object H.empty
|
|
|
|
toJSON (IntervalValue (from, to)) = object
|
|
|
|
[ "type" .= ("interval" :: Text)
|
|
|
|
, "from" .= toJSON from
|
|
|
|
, "to" .= toJSON to
|
|
|
|
]
|
|
|
|
toJSON (OpenIntervalValue (from, Above)) = object
|
|
|
|
[ "type" .= ("interval" :: Text)
|
|
|
|
, "from" .= toJSON from
|
2017-03-08 21:33:55 +03:00
|
|
|
]
|
2018-08-24 21:17:30 +03:00
|
|
|
toJSON (OpenIntervalValue (to, Under)) = object
|
|
|
|
[ "type" .= ("interval" :: Text)
|
|
|
|
, "to" .= toJSON to
|
|
|
|
]
|
|
|
|
|
|
|
|
-- -----------------------------------------------------------------
|
|
|
|
-- Value helpers
|
|
|
|
|
|
|
|
simple :: Unit -> Double -> VolumeValue
|
|
|
|
simple u v = SimpleValue $ single u v
|
|
|
|
|
|
|
|
between :: Unit -> (Double, Double) -> VolumeValue
|
|
|
|
between u (from,to) = IntervalValue (single u from, single u to)
|
|
|
|
|
|
|
|
above :: Unit -> Double -> VolumeValue
|
|
|
|
above = openInterval Above
|
|
|
|
|
|
|
|
under :: Unit -> Double -> VolumeValue
|
|
|
|
under = openInterval Under
|
|
|
|
|
|
|
|
openInterval :: IntervalDirection -> Unit -> Double -> VolumeValue
|
|
|
|
openInterval direction u v = OpenIntervalValue (single u v, direction)
|
|
|
|
|
|
|
|
single :: Unit -> Double -> SingleValue
|
|
|
|
single u v = SingleValue {vUnit = u, vValue = v}
|