-- |Types and instances for instances for humans to read.
module Chez.Grater.Readable.Types where

import Chez.Grater.Internal.Prelude

import Chez.Grater.Internal.CI.Orphans ()
import Chez.Grater.Internal.Json (jsonOptions)
import Chez.Grater.Types (Ingredient(..), IngredientName(..), Quantity(..), Unit(..))
import Data.Aeson (FromJSON, ToJSON)
import Data.Aeson.TH (deriveJSON)
import qualified Data.CaseInsensitive as CI

data ReadableFraction = ReadableFraction
  { ReadableFraction -> Int
readableFractionNumerator   :: Int
  , ReadableFraction -> Int
readableFractionDenominator :: Int
  }
  deriving (ReadableFraction -> ReadableFraction -> Bool
(ReadableFraction -> ReadableFraction -> Bool)
-> (ReadableFraction -> ReadableFraction -> Bool)
-> Eq ReadableFraction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReadableFraction -> ReadableFraction -> Bool
$c/= :: ReadableFraction -> ReadableFraction -> Bool
== :: ReadableFraction -> ReadableFraction -> Bool
$c== :: ReadableFraction -> ReadableFraction -> Bool
Eq, Eq ReadableFraction
Eq ReadableFraction
-> (ReadableFraction -> ReadableFraction -> Ordering)
-> (ReadableFraction -> ReadableFraction -> Bool)
-> (ReadableFraction -> ReadableFraction -> Bool)
-> (ReadableFraction -> ReadableFraction -> Bool)
-> (ReadableFraction -> ReadableFraction -> Bool)
-> (ReadableFraction -> ReadableFraction -> ReadableFraction)
-> (ReadableFraction -> ReadableFraction -> ReadableFraction)
-> Ord ReadableFraction
ReadableFraction -> ReadableFraction -> Bool
ReadableFraction -> ReadableFraction -> Ordering
ReadableFraction -> ReadableFraction -> ReadableFraction
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ReadableFraction -> ReadableFraction -> ReadableFraction
$cmin :: ReadableFraction -> ReadableFraction -> ReadableFraction
max :: ReadableFraction -> ReadableFraction -> ReadableFraction
$cmax :: ReadableFraction -> ReadableFraction -> ReadableFraction
>= :: ReadableFraction -> ReadableFraction -> Bool
$c>= :: ReadableFraction -> ReadableFraction -> Bool
> :: ReadableFraction -> ReadableFraction -> Bool
$c> :: ReadableFraction -> ReadableFraction -> Bool
<= :: ReadableFraction -> ReadableFraction -> Bool
$c<= :: ReadableFraction -> ReadableFraction -> Bool
< :: ReadableFraction -> ReadableFraction -> Bool
$c< :: ReadableFraction -> ReadableFraction -> Bool
compare :: ReadableFraction -> ReadableFraction -> Ordering
$ccompare :: ReadableFraction -> ReadableFraction -> Ordering
$cp1Ord :: Eq ReadableFraction
Ord, Int -> ReadableFraction -> ShowS
[ReadableFraction] -> ShowS
ReadableFraction -> String
(Int -> ReadableFraction -> ShowS)
-> (ReadableFraction -> String)
-> ([ReadableFraction] -> ShowS)
-> Show ReadableFraction
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReadableFraction] -> ShowS
$cshowList :: [ReadableFraction] -> ShowS
show :: ReadableFraction -> String
$cshow :: ReadableFraction -> String
showsPrec :: Int -> ReadableFraction -> ShowS
$cshowsPrec :: Int -> ReadableFraction -> ShowS
Show)

data ReadableQuantity = ReadableQuantity
  { ReadableQuantity -> Maybe Int
readableQuantityWhole    :: Maybe Int
  , ReadableQuantity -> Maybe ReadableFraction
readableQuantityFraction :: Maybe ReadableFraction
  }
  deriving (ReadableQuantity -> ReadableQuantity -> Bool
(ReadableQuantity -> ReadableQuantity -> Bool)
-> (ReadableQuantity -> ReadableQuantity -> Bool)
-> Eq ReadableQuantity
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReadableQuantity -> ReadableQuantity -> Bool
$c/= :: ReadableQuantity -> ReadableQuantity -> Bool
== :: ReadableQuantity -> ReadableQuantity -> Bool
$c== :: ReadableQuantity -> ReadableQuantity -> Bool
Eq, Eq ReadableQuantity
Eq ReadableQuantity
-> (ReadableQuantity -> ReadableQuantity -> Ordering)
-> (ReadableQuantity -> ReadableQuantity -> Bool)
-> (ReadableQuantity -> ReadableQuantity -> Bool)
-> (ReadableQuantity -> ReadableQuantity -> Bool)
-> (ReadableQuantity -> ReadableQuantity -> Bool)
-> (ReadableQuantity -> ReadableQuantity -> ReadableQuantity)
-> (ReadableQuantity -> ReadableQuantity -> ReadableQuantity)
-> Ord ReadableQuantity
ReadableQuantity -> ReadableQuantity -> Bool
ReadableQuantity -> ReadableQuantity -> Ordering
ReadableQuantity -> ReadableQuantity -> ReadableQuantity
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ReadableQuantity -> ReadableQuantity -> ReadableQuantity
$cmin :: ReadableQuantity -> ReadableQuantity -> ReadableQuantity
max :: ReadableQuantity -> ReadableQuantity -> ReadableQuantity
$cmax :: ReadableQuantity -> ReadableQuantity -> ReadableQuantity
>= :: ReadableQuantity -> ReadableQuantity -> Bool
$c>= :: ReadableQuantity -> ReadableQuantity -> Bool
> :: ReadableQuantity -> ReadableQuantity -> Bool
$c> :: ReadableQuantity -> ReadableQuantity -> Bool
<= :: ReadableQuantity -> ReadableQuantity -> Bool
$c<= :: ReadableQuantity -> ReadableQuantity -> Bool
< :: ReadableQuantity -> ReadableQuantity -> Bool
$c< :: ReadableQuantity -> ReadableQuantity -> Bool
compare :: ReadableQuantity -> ReadableQuantity -> Ordering
$ccompare :: ReadableQuantity -> ReadableQuantity -> Ordering
$cp1Ord :: Eq ReadableQuantity
Ord, Int -> ReadableQuantity -> ShowS
[ReadableQuantity] -> ShowS
ReadableQuantity -> String
(Int -> ReadableQuantity -> ShowS)
-> (ReadableQuantity -> String)
-> ([ReadableQuantity] -> ShowS)
-> Show ReadableQuantity
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReadableQuantity] -> ShowS
$cshowList :: [ReadableQuantity] -> ShowS
show :: ReadableQuantity -> String
$cshow :: ReadableQuantity -> String
showsPrec :: Int -> ReadableQuantity -> ShowS
$cshowsPrec :: Int -> ReadableQuantity -> ShowS
Show)

newtype ReadableUnit = ReadableUnit { ReadableUnit -> CI Text
unReadableUnit :: CI Text }
  deriving (ReadableUnit -> ReadableUnit -> Bool
(ReadableUnit -> ReadableUnit -> Bool)
-> (ReadableUnit -> ReadableUnit -> Bool) -> Eq ReadableUnit
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReadableUnit -> ReadableUnit -> Bool
$c/= :: ReadableUnit -> ReadableUnit -> Bool
== :: ReadableUnit -> ReadableUnit -> Bool
$c== :: ReadableUnit -> ReadableUnit -> Bool
Eq, Eq ReadableUnit
Eq ReadableUnit
-> (ReadableUnit -> ReadableUnit -> Ordering)
-> (ReadableUnit -> ReadableUnit -> Bool)
-> (ReadableUnit -> ReadableUnit -> Bool)
-> (ReadableUnit -> ReadableUnit -> Bool)
-> (ReadableUnit -> ReadableUnit -> Bool)
-> (ReadableUnit -> ReadableUnit -> ReadableUnit)
-> (ReadableUnit -> ReadableUnit -> ReadableUnit)
-> Ord ReadableUnit
ReadableUnit -> ReadableUnit -> Bool
ReadableUnit -> ReadableUnit -> Ordering
ReadableUnit -> ReadableUnit -> ReadableUnit
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ReadableUnit -> ReadableUnit -> ReadableUnit
$cmin :: ReadableUnit -> ReadableUnit -> ReadableUnit
max :: ReadableUnit -> ReadableUnit -> ReadableUnit
$cmax :: ReadableUnit -> ReadableUnit -> ReadableUnit
>= :: ReadableUnit -> ReadableUnit -> Bool
$c>= :: ReadableUnit -> ReadableUnit -> Bool
> :: ReadableUnit -> ReadableUnit -> Bool
$c> :: ReadableUnit -> ReadableUnit -> Bool
<= :: ReadableUnit -> ReadableUnit -> Bool
$c<= :: ReadableUnit -> ReadableUnit -> Bool
< :: ReadableUnit -> ReadableUnit -> Bool
$c< :: ReadableUnit -> ReadableUnit -> Bool
compare :: ReadableUnit -> ReadableUnit -> Ordering
$ccompare :: ReadableUnit -> ReadableUnit -> Ordering
$cp1Ord :: Eq ReadableUnit
Ord, Int -> ReadableUnit -> ShowS
[ReadableUnit] -> ShowS
ReadableUnit -> String
(Int -> ReadableUnit -> ShowS)
-> (ReadableUnit -> String)
-> ([ReadableUnit] -> ShowS)
-> Show ReadableUnit
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReadableUnit] -> ShowS
$cshowList :: [ReadableUnit] -> ShowS
show :: ReadableUnit -> String
$cshow :: ReadableUnit -> String
showsPrec :: Int -> ReadableUnit -> ShowS
$cshowsPrec :: Int -> ReadableUnit -> ShowS
Show, Value -> Parser [ReadableUnit]
Value -> Parser ReadableUnit
(Value -> Parser ReadableUnit)
-> (Value -> Parser [ReadableUnit]) -> FromJSON ReadableUnit
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [ReadableUnit]
$cparseJSONList :: Value -> Parser [ReadableUnit]
parseJSON :: Value -> Parser ReadableUnit
$cparseJSON :: Value -> Parser ReadableUnit
FromJSON, [ReadableUnit] -> Encoding
[ReadableUnit] -> Value
ReadableUnit -> Encoding
ReadableUnit -> Value
(ReadableUnit -> Value)
-> (ReadableUnit -> Encoding)
-> ([ReadableUnit] -> Value)
-> ([ReadableUnit] -> Encoding)
-> ToJSON ReadableUnit
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [ReadableUnit] -> Encoding
$ctoEncodingList :: [ReadableUnit] -> Encoding
toJSONList :: [ReadableUnit] -> Value
$ctoJSONList :: [ReadableUnit] -> Value
toEncoding :: ReadableUnit -> Encoding
$ctoEncoding :: ReadableUnit -> Encoding
toJSON :: ReadableUnit -> Value
$ctoJSON :: ReadableUnit -> Value
ToJSON)

data ReadableIngredient = ReadableIngredient
  { ReadableIngredient -> IngredientName
readableIngredientName     :: IngredientName
  , ReadableIngredient -> ReadableQuantity
readableIngredientQuantity :: ReadableQuantity
  , ReadableIngredient -> Maybe ReadableUnit
readableIngredientUnit     :: Maybe ReadableUnit
  }
  deriving (ReadableIngredient -> ReadableIngredient -> Bool
(ReadableIngredient -> ReadableIngredient -> Bool)
-> (ReadableIngredient -> ReadableIngredient -> Bool)
-> Eq ReadableIngredient
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReadableIngredient -> ReadableIngredient -> Bool
$c/= :: ReadableIngredient -> ReadableIngredient -> Bool
== :: ReadableIngredient -> ReadableIngredient -> Bool
$c== :: ReadableIngredient -> ReadableIngredient -> Bool
Eq, Eq ReadableIngredient
Eq ReadableIngredient
-> (ReadableIngredient -> ReadableIngredient -> Ordering)
-> (ReadableIngredient -> ReadableIngredient -> Bool)
-> (ReadableIngredient -> ReadableIngredient -> Bool)
-> (ReadableIngredient -> ReadableIngredient -> Bool)
-> (ReadableIngredient -> ReadableIngredient -> Bool)
-> (ReadableIngredient -> ReadableIngredient -> ReadableIngredient)
-> (ReadableIngredient -> ReadableIngredient -> ReadableIngredient)
-> Ord ReadableIngredient
ReadableIngredient -> ReadableIngredient -> Bool
ReadableIngredient -> ReadableIngredient -> Ordering
ReadableIngredient -> ReadableIngredient -> ReadableIngredient
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ReadableIngredient -> ReadableIngredient -> ReadableIngredient
$cmin :: ReadableIngredient -> ReadableIngredient -> ReadableIngredient
max :: ReadableIngredient -> ReadableIngredient -> ReadableIngredient
$cmax :: ReadableIngredient -> ReadableIngredient -> ReadableIngredient
>= :: ReadableIngredient -> ReadableIngredient -> Bool
$c>= :: ReadableIngredient -> ReadableIngredient -> Bool
> :: ReadableIngredient -> ReadableIngredient -> Bool
$c> :: ReadableIngredient -> ReadableIngredient -> Bool
<= :: ReadableIngredient -> ReadableIngredient -> Bool
$c<= :: ReadableIngredient -> ReadableIngredient -> Bool
< :: ReadableIngredient -> ReadableIngredient -> Bool
$c< :: ReadableIngredient -> ReadableIngredient -> Bool
compare :: ReadableIngredient -> ReadableIngredient -> Ordering
$ccompare :: ReadableIngredient -> ReadableIngredient -> Ordering
$cp1Ord :: Eq ReadableIngredient
Ord, Int -> ReadableIngredient -> ShowS
[ReadableIngredient] -> ShowS
ReadableIngredient -> String
(Int -> ReadableIngredient -> ShowS)
-> (ReadableIngredient -> String)
-> ([ReadableIngredient] -> ShowS)
-> Show ReadableIngredient
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReadableIngredient] -> ShowS
$cshowList :: [ReadableIngredient] -> ShowS
show :: ReadableIngredient -> String
$cshow :: ReadableIngredient -> String
showsPrec :: Int -> ReadableIngredient -> ShowS
$cshowsPrec :: Int -> ReadableIngredient -> ShowS
Show)

deriveJSON (jsonOptions "readableFraction") ''ReadableFraction
deriveJSON (jsonOptions "readableQuantity") ''ReadableQuantity
deriveJSON (jsonOptions "readableIngredient") ''ReadableIngredient

mkReadableQuantity :: Quantity -> ReadableQuantity
mkReadableQuantity :: Quantity -> ReadableQuantity
mkReadableQuantity Quantity
q = case Quantity -> Maybe (Int, Double)
splitQuantity Quantity
q of
  Maybe (Int, Double)
Nothing -> Maybe Int -> Maybe ReadableFraction -> ReadableQuantity
ReadableQuantity Maybe Int
forall a. Maybe a
Nothing Maybe ReadableFraction
forall a. Maybe a
Nothing
  Just (Int
w, Double
d) ->
    case (Int
w Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0, (((Double, Double), (Int, Int)) -> Bool)
-> [((Double, Double), (Int, Int))]
-> Maybe ((Double, Double), (Int, Int))
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (\((Double
lo, Double
hi), (Int, Int)
_) -> Double
lo Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
d Bool -> Bool -> Bool
&& Double
d Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
hi) [((Double, Double), (Int, Int))]
knownQuantities) of
      (Bool
False, Just ((Double, Double)
_, (Int
numerator, Int
denominator))) -> Maybe Int -> Maybe ReadableFraction -> ReadableQuantity
ReadableQuantity (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
w) (ReadableFraction -> Maybe ReadableFraction
forall a. a -> Maybe a
Just (Int -> Int -> ReadableFraction
ReadableFraction Int
numerator Int
denominator))
      (Bool
True, Just ((Double, Double)
_, (Int
numerator, Int
denominator))) -> Maybe Int -> Maybe ReadableFraction -> ReadableQuantity
ReadableQuantity Maybe Int
forall a. Maybe a
Nothing (ReadableFraction -> Maybe ReadableFraction
forall a. a -> Maybe a
Just (Int -> Int -> ReadableFraction
ReadableFraction Int
numerator Int
denominator))
      (Bool
False, Maybe ((Double, Double), (Int, Int))
Nothing) -> Maybe Int -> Maybe ReadableFraction -> ReadableQuantity
ReadableQuantity (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
w) Maybe ReadableFraction
forall a. Maybe a
Nothing
      (Bool
True, Maybe ((Double, Double), (Int, Int))
Nothing) -> Maybe Int -> Maybe ReadableFraction -> ReadableQuantity
ReadableQuantity Maybe Int
forall a. Maybe a
Nothing Maybe ReadableFraction
forall a. Maybe a
Nothing

  where

    quantityPrecision :: Double
    quantityPrecision :: Double
quantityPrecision = Double
0.01

    quarter :: p
quarter = p
0.25
    third :: a
third = a
1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
3
    half :: p
half = p
0.5
    twoThird :: a
twoThird = a
2 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
3
    threeQuarter :: p
threeQuarter = p
0.75

    knownQuantities :: [((Double, Double), (Int, Int))]
    knownQuantities :: [((Double, Double), (Int, Int))]
knownQuantities =
      [ ((Double
forall p. Fractional p => p
quarter Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
quantityPrecision, Double
forall p. Fractional p => p
quarter Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
quantityPrecision), (Int
1, Int
4))
      , ((Double
forall p. Fractional p => p
third Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
quantityPrecision, Double
forall p. Fractional p => p
third Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
quantityPrecision), (Int
1, Int
3))
      , ((Double
forall p. Fractional p => p
half Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
quantityPrecision, Double
forall p. Fractional p => p
half Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
quantityPrecision), (Int
1, Int
2))
      , ((Double
forall p. Fractional p => p
twoThird Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
quantityPrecision, Double
forall p. Fractional p => p
twoThird Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
quantityPrecision), (Int
2, Int
3))
      , ((Double
forall p. Fractional p => p
threeQuarter Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
quantityPrecision, Double
forall p. Fractional p => p
threeQuarter Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
quantityPrecision), (Int
3, Int
4))
      ]

    splitQuantity :: Quantity -> Maybe (Int, Double)
    splitQuantity :: Quantity -> Maybe (Int, Double)
splitQuantity = \case
      Quantity
QuantityMissing -> Maybe (Int, Double)
forall a. Maybe a
Nothing
      Quantity Double
q2 ->
        case Double -> Double
forall a. Num a => a -> a
abs (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round Double
q2 :: Int) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
q2) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
quantityPrecision of
          Bool
True -> (Int, Double) -> Maybe (Int, Double)
forall a. a -> Maybe a
Just (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round Double
q2, Double
0.0)
          Bool
False -> let w :: Int
w = Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate Double
q2 in (Int, Double) -> Maybe (Int, Double)
forall a. a -> Maybe a
Just (Int
w, Double
q2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
w)

showReadableQuantity :: ReadableQuantity -> Maybe Text
showReadableQuantity :: ReadableQuantity -> Maybe Text
showReadableQuantity ReadableQuantity {Maybe Int
Maybe ReadableFraction
readableQuantityFraction :: Maybe ReadableFraction
readableQuantityWhole :: Maybe Int
readableQuantityFraction :: ReadableQuantity -> Maybe ReadableFraction
readableQuantityWhole :: ReadableQuantity -> Maybe Int
..} =
  case (Maybe Int
readableQuantityWhole, Maybe ReadableFraction
readableQuantityFraction) of
    (Maybe Int
Nothing, Maybe ReadableFraction
Nothing) -> Maybe Text
forall a. Maybe a
Nothing
    (Just Int
w, Maybe ReadableFraction
Nothing) -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Int -> Text
forall a. Show a => a -> Text
tshow Int
w
    (Maybe Int
Nothing, Just ReadableFraction {Int
readableFractionDenominator :: Int
readableFractionNumerator :: Int
readableFractionDenominator :: ReadableFraction -> Int
readableFractionNumerator :: ReadableFraction -> Int
..}) -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Int -> Text
forall a. Show a => a -> Text
tshow Int
readableFractionNumerator Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow Int
readableFractionDenominator
    (Just Int
w, Just ReadableFraction {Int
readableFractionDenominator :: Int
readableFractionNumerator :: Int
readableFractionDenominator :: ReadableFraction -> Int
readableFractionNumerator :: ReadableFraction -> Int
..}) -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Int -> Text
forall a. Show a => a -> Text
tshow Int
w Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow Int
readableFractionNumerator Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow Int
readableFractionDenominator

mkReadableUnit :: Unit -> Maybe ReadableUnit
mkReadableUnit :: Unit -> Maybe ReadableUnit
mkReadableUnit = \case
  Unit CI Text
x -> ReadableUnit -> Maybe ReadableUnit
forall a. a -> Maybe a
Just (CI Text -> ReadableUnit
ReadableUnit CI Text
x)
  Unit
UnitMissing -> Maybe ReadableUnit
forall a. Maybe a
Nothing

showReadableUnit :: ReadableUnit -> Text
showReadableUnit :: ReadableUnit -> Text
showReadableUnit = CI Text -> Text
forall s. CI s -> s
CI.original (CI Text -> Text)
-> (ReadableUnit -> CI Text) -> ReadableUnit -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReadableUnit -> CI Text
unReadableUnit

mkReadableIngredient :: Ingredient -> ReadableIngredient
mkReadableIngredient :: Ingredient -> ReadableIngredient
mkReadableIngredient Ingredient {Unit
Quantity
IngredientName
ingredientUnit :: Ingredient -> Unit
ingredientQuantity :: Ingredient -> Quantity
ingredientName :: Ingredient -> IngredientName
ingredientUnit :: Unit
ingredientQuantity :: Quantity
ingredientName :: IngredientName
..} =
  ReadableIngredient :: IngredientName
-> ReadableQuantity -> Maybe ReadableUnit -> ReadableIngredient
ReadableIngredient
    { readableIngredientName :: IngredientName
readableIngredientName = IngredientName
ingredientName
    , readableIngredientQuantity :: ReadableQuantity
readableIngredientQuantity = Quantity -> ReadableQuantity
mkReadableQuantity Quantity
ingredientQuantity
    , readableIngredientUnit :: Maybe ReadableUnit
readableIngredientUnit = Unit -> Maybe ReadableUnit
mkReadableUnit Unit
ingredientUnit
    }

showReadableIngredient :: ReadableIngredient -> Text
showReadableIngredient :: ReadableIngredient -> Text
showReadableIngredient ReadableIngredient {Maybe ReadableUnit
IngredientName
ReadableQuantity
readableIngredientUnit :: Maybe ReadableUnit
readableIngredientQuantity :: ReadableQuantity
readableIngredientName :: IngredientName
readableIngredientUnit :: ReadableIngredient -> Maybe ReadableUnit
readableIngredientQuantity :: ReadableIngredient -> ReadableQuantity
readableIngredientName :: ReadableIngredient -> IngredientName
..} =
  case (ReadableQuantity -> Maybe Text
showReadableQuantity ReadableQuantity
readableIngredientQuantity, ReadableUnit -> Text
showReadableUnit (ReadableUnit -> Text) -> Maybe ReadableUnit -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ReadableUnit
readableIngredientUnit) of
    (Maybe Text
Nothing, Maybe Text
Nothing) -> IngredientName -> Text
showIngredientName IngredientName
readableIngredientName
    (Just Text
q, Maybe Text
Nothing) -> Text
q Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> IngredientName -> Text
showIngredientName IngredientName
readableIngredientName
    (Maybe Text
Nothing, Just Text
u) -> Text
u Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> IngredientName -> Text
showIngredientName IngredientName
readableIngredientName
    (Just Text
q, Just Text
u) -> Text
q Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
u Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> IngredientName -> Text
showIngredientName IngredientName
readableIngredientName
  where
    showIngredientName :: IngredientName -> Text
showIngredientName = CI Text -> Text
forall s. CI s -> s
CI.original (CI Text -> Text)
-> (IngredientName -> CI Text) -> IngredientName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IngredientName -> CI Text
unIngredientName