module Chez.Grater.Test.Gen where

import Chez.Grater.Internal.Prelude

import Test.QuickCheck (Gen, arbitrary, elements, oneof)
import qualified Data.CaseInsensitive as CI
import qualified Data.Text as Text

import Chez.Grater.Readable.Types
import Chez.Grater.Types

maybeGen :: Gen a -> Gen (Maybe a)
maybeGen :: Gen a -> Gen (Maybe a)
maybeGen Gen a
gen = [Gen (Maybe a)] -> Gen (Maybe a)
forall a. [Gen a] -> Gen a
oneof
  [ a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> Gen a -> Gen (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
gen
  , Maybe a -> Gen (Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing
  ]

arbitraryAlphaNum :: Gen Char
arbitraryAlphaNum :: Gen Char
arbitraryAlphaNum = [Char] -> Gen Char
forall a. [a] -> Gen a
elements ([Char] -> Gen Char) -> [Char] -> Gen Char
forall a b. (a -> b) -> a -> b
$ [Char
'a'..Char
'z'] [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char
'A'..Char
'Z'] [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char
'0'..Char
'9']

arbitraryAlphaNumStr :: Gen Text
arbitraryAlphaNumStr :: Gen Text
arbitraryAlphaNumStr = do
  Int
n <- Gen Int
forall a. Arbitrary a => Gen a
arbitrary
  [Char] -> Text
Text.pack ([Char] -> Text) -> Gen [Char] -> Gen Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen Char -> Gen [Char]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (Int -> Int
forall a. Num a => a -> a
abs Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
10) Gen Char
arbitraryAlphaNum

arbitraryCi :: Gen (CI Text)
arbitraryCi :: Gen (CI Text)
arbitraryCi = Text -> CI Text
forall s. FoldCase s => s -> CI s
CI.mk (Text -> CI Text) -> Gen Text -> Gen (CI Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Text
arbitraryAlphaNumStr

arbitraryIngredientName :: Gen IngredientName
arbitraryIngredientName :: Gen IngredientName
arbitraryIngredientName = CI Text -> IngredientName
IngredientName (CI Text -> IngredientName) -> Gen (CI Text) -> Gen IngredientName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (CI Text)
arbitraryCi

arbitraryRecipeName :: Gen RecipeName
arbitraryRecipeName :: Gen RecipeName
arbitraryRecipeName = Text -> RecipeName
RecipeName (Text -> RecipeName) -> Gen Text -> Gen RecipeName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Text
arbitraryAlphaNumStr

trunc :: Int -> Double -> Double
trunc :: Int -> Double -> Double
trunc Int
n Double
x = (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t) :: Int)) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
t
  where t :: Double
t = Double
10Double -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Int
n

arbitraryDouble :: Gen Double
arbitraryDouble :: Gen Double
arbitraryDouble = Int -> Double -> Double
trunc Int
5 (Double -> Double) -> (Double -> Double) -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Num a => a -> a
abs (Double -> Double) -> Gen Double -> Gen Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Double
forall a. Arbitrary a => Gen a
arbitrary

arbitraryInt :: Gen Int
arbitraryInt :: Gen Int
arbitraryInt = Int -> Int
forall a. Num a => a -> a
abs (Int -> Int) -> Gen Int -> Gen Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int
forall a. Arbitrary a => Gen a
arbitrary

arbitraryQuantity :: Gen Quantity
arbitraryQuantity :: Gen Quantity
arbitraryQuantity = [Gen Quantity] -> Gen Quantity
forall a. [Gen a] -> Gen a
oneof
  [ Quantity -> Gen Quantity
forall (f :: * -> *) a. Applicative f => a -> f a
pure Quantity
QuantityMissing
  , Double -> Quantity
Quantity (Double -> Quantity) -> Gen Double -> Gen Quantity
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Double
arbitraryDouble
  ]

arbitraryUnit :: Gen Unit
arbitraryUnit :: Gen Unit
arbitraryUnit = [Gen Unit] -> Gen Unit
forall a. [Gen a] -> Gen a
oneof
  [ Unit -> Gen Unit
forall (f :: * -> *) a. Applicative f => a -> f a
pure Unit
UnitMissing
  , CI Text -> Unit
Unit (CI Text -> Unit) -> Gen (CI Text) -> Gen Unit
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (CI Text)
arbitraryCi
  ]

arbitraryIngredient :: Gen Ingredient
arbitraryIngredient :: Gen Ingredient
arbitraryIngredient = IngredientName -> Quantity -> Unit -> Ingredient
Ingredient
  (IngredientName -> Quantity -> Unit -> Ingredient)
-> Gen IngredientName -> Gen (Quantity -> Unit -> Ingredient)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen IngredientName
arbitraryIngredientName
  Gen (Quantity -> Unit -> Ingredient)
-> Gen Quantity -> Gen (Unit -> Ingredient)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Quantity
arbitraryQuantity
  Gen (Unit -> Ingredient) -> Gen Unit -> Gen Ingredient
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Unit
arbitraryUnit

arbitraryStep :: Gen Step
arbitraryStep :: Gen Step
arbitraryStep = Text -> Step
Step
  (Text -> Step) -> Gen Text -> Gen Step
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Text
arbitraryAlphaNumStr

arbitraryReadableFraction :: Gen ReadableFraction
arbitraryReadableFraction :: Gen ReadableFraction
arbitraryReadableFraction = Int -> Int -> ReadableFraction
ReadableFraction
  (Int -> Int -> ReadableFraction)
-> Gen Int -> Gen (Int -> ReadableFraction)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int
arbitraryInt
  Gen (Int -> ReadableFraction) -> Gen Int -> Gen ReadableFraction
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Int -> Int) -> Gen Int -> Gen Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int
arbitraryInt)

arbitraryReadableQuantity :: Gen ReadableQuantity
arbitraryReadableQuantity :: Gen ReadableQuantity
arbitraryReadableQuantity = Maybe Int -> Maybe ReadableFraction -> ReadableQuantity
ReadableQuantity
  (Maybe Int -> Maybe ReadableFraction -> ReadableQuantity)
-> Gen (Maybe Int)
-> Gen (Maybe ReadableFraction -> ReadableQuantity)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int -> Gen (Maybe Int)
forall a. Gen a -> Gen (Maybe a)
maybeGen Gen Int
arbitraryInt
  Gen (Maybe ReadableFraction -> ReadableQuantity)
-> Gen (Maybe ReadableFraction) -> Gen ReadableQuantity
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen ReadableFraction -> Gen (Maybe ReadableFraction)
forall a. Gen a -> Gen (Maybe a)
maybeGen Gen ReadableFraction
arbitraryReadableFraction

arbitraryReadableUnit :: Gen ReadableUnit
arbitraryReadableUnit :: Gen ReadableUnit
arbitraryReadableUnit = CI Text -> ReadableUnit
ReadableUnit (CI Text -> ReadableUnit) -> Gen (CI Text) -> Gen ReadableUnit
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (CI Text)
arbitraryCi