{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} module RecipesSpec where import Data.ByteString.Builder qualified as ByteString.Builder import Data.Char qualified as Char import Data.GenValidity.Map () import Data.GenValidity.Sequence () import Data.GenValidity.Set () import Data.GenValidity.Text () import Data.List qualified as List import Data.Map.Strict qualified as Map import Data.Ratio (denominator, numerator) import Data.Set qualified as Set import Data.Text qualified as Text import Data.Text.Encoding qualified as Text import Data.Text.Lazy.Encoding qualified as Text.Lazy import Data.Text.Short qualified as ShortText import Data.Validity.Map () import Data.Validity.Set () import Data.Validity.Text () import Graph.DOT qualified as DOT import Language import Language.French qualified as French import Language.Pronunciation (ExampleLiteral (..), Lexeme (..), Rule (..), RuleLexemes, after, before, begining, ending, meaning, occurence, rule, silent, word) import Language.Pronunciation qualified as Pron import Paths_worksheets qualified as Self import Recipes qualified as Recipes import System.Directory qualified as IO import System.FilePath (joinPath, pathSeparator, (<.>), ()) import System.FilePath.Posix qualified as File import System.IO qualified as IO import Test.Syd import Text.Blaze.Html5.Attributes qualified as HA import Utils.Pronunciation qualified as Pron import Utils.Tests import Wiktionary qualified import Worksheets.Utils.HTML (Html, className, classes, cm, styles, (!)) import Worksheets.Utils.HTML qualified as HTML import Worksheets.Utils.IPA qualified as IPA import Worksheets.Utils.Paper qualified as Paper import Worksheets.Utils.Prelude import Worksheets.Utils.SQL qualified as SQL import Prelude (error, even, mod) spec :: HasCallStack => Spec spec = do describe "Recipes" do recipeSpec recipeTarteAuCitron recipeSpec recipe@Recipes.Recipe{..} = do let title = recipeName & ShortText.unpack outPath <- goldenPath title "dot" it title do goldenByteStringBuilderFile outPath do return $ Recipes.recipeDOT recipe -- let (blancDœuf, jauneDœuf) = séparerŒuf `app` (œuf & qty 2) `app` (bol & qty 2) -- let beurreCubes = couperEnCubes `app` (beurre & grams 125) `app` (couteau & qty 1) -- let pâteSablée = mélanger recipeTarteAuCitron = Recipes.Recipe { recipeName = "TarteAuCitron" , recipeFunctions = [ "Préchauffer le four" := Recipes.Function { functionInputs = [ "four" := 1 & num & Recipes.TermDescr ] , functionSteps = [ "Préchauffer le four 10min à 180°C" ] , functionOutputs = [ "four préchauffé" := 1 & num ] } , "Séparer les œufs" := Recipes.Function { functionInputs = [ "œuf" := 2 & num & Recipes.TermDescr , "bol" := 2 & num & Recipes.TermDescr ] , functionSteps = [ "Séparer les jaunes des blancs" ] , functionOutputs = [ "blanc d'œuf" := 2 & num , "jaune d'œuf" := 2 & num ] } , "Couper le beurre" := Recipes.Function { functionInputs = [ "beurre" := 125 & grams & Recipes.TermDescr , "couteau" := 1 & num & Recipes.TermDescr ] , functionSteps = [ "Couper en petits cubes d'1cm de côté" ] , functionOutputs = [ "beurre découpé" := 125 & grams ] } , "Faire la pâte sableuse" := Recipes.Function { functionInputs = [ "beurre en cubes" := Recipes.TermRef { termRefName = "Couper le beurre" , termRefPort = Just "beurre découpé" , termRefQuantity = Nothing } , "saladier" := 1 & num & Recipes.TermDescr , "doigts" := 10 & num & Recipes.TermDescr , "farine" := 200 & grams & Recipes.TermDescr ] , functionSteps = [ "Mélanger (vite) les ingrédients sableux" ] , functionOutputs = [ "pâte sableuse" := "" ] } , "Faire la pâte mousseuse" := Recipes.Function { functionInputs = [ "jaune d'œuf" := Recipes.TermRef { termRefName = "Séparer les œufs" , termRefPort = Just "jaune d'œuf" , termRefQuantity = Just $ 2 & num } , "sucre semoule" := 70 & grams & Recipes.TermDescr , "saladier" := 1 & num & Recipes.TermDescr , "fourchette" := 1 & num & Recipes.TermDescr , "eau" := 2 & tablespoon & Recipes.TermDescr ] , functionSteps = [ "Mélanger les ingrédients mousseux" ] , functionOutputs = [ "pâte mousseuse" := "" ] } , "Faire la pâte sablée" := Recipes.Function { functionInputs = [ "pâte mousseuse" := Recipes.TermRef { termRefName = "Faire la pâte mousseuse" , termRefPort = Just "pâte mousseuse" , termRefQuantity = Nothing -- Just $ 1 & num } , "pâte sableuse" := Recipes.TermRef { termRefName = "Faire la pâte sableuse" , termRefPort = Just "pâte sableuse" , termRefQuantity = Nothing -- Just $ 1 & num } ] , functionSteps = [ "Incorporer rapidement au couteau les éléments\nsans leur donner de corps" , "Former une boule de pâte sablée avec les paumes" , "Écraser 1 ou 2 fois la boule pour la rendre plus homogène" ] , functionOutputs = [ "boule de pâte sablée" := 1 & num ] } , "Cuire le fond de tarte" := Recipes.Function { functionInputs = [ "four préchauffé" := Recipes.TermRef { termRefName = "Préchauffer le four" , termRefPort = Just "four préchauffé" , termRefQuantity = Nothing -- Just $ 1 & num } , "boule de pâte sablée" := Recipes.TermRef { termRefName = "Faire la pâte sablée" , termRefPort = Just "boule de pâte sablée" , termRefQuantity = Nothing -- Just $ 1 & num } ] , functionSteps = [ "Foncer la pâte dans le moule" , "(optionnel) Recouvrir la pâte de papier sulfurisé et de haricots sec" , "Cuire la pâte à blanc 20 à 25 minutes" ] , functionOutputs = [ "fond de tarte cuit" := 1 & num ] } , "Zester les citrons" := Recipes.Function { functionInputs = [ "citron" := 2 & num & Recipes.TermDescr ] , functionSteps = [ "Laver les citrons" , "Râper les citrons" ] , functionOutputs = [ "zeste de citron" := 1 & num , "citron lavé" := 2 & num ] } , "Presse les citrons" := Recipes.Function { functionInputs = [ "citron zesté" := Recipes.TermRef { termRefName = "Zester les citrons" , termRefPort = Just "citron lavé" , termRefQuantity = Just $ 2 & num } , "citron" := 2 & num & Recipes.TermDescr ] , functionSteps = [ "Presser les citrons" ] , functionOutputs = [ "jus de citron" := 1 & num ] } , "Faire la crème citron" := Recipes.Function { functionInputs = [ "zeste de citron" := Recipes.TermRef { termRefName = "Zester les citrons" , termRefPort = Just "zeste de citron" , termRefQuantity = Nothing -- Just $ 2 & num } , "jus de citron" := Recipes.TermRef { termRefName = "Presse les citrons" , termRefPort = Just "jus de citron" , termRefQuantity = Nothing -- Just $ 4 & num } , "sucre semoule" := 150 & grams & Recipes.TermDescr , "farine de maïs" := 1 & tablespoon & Recipes.TermDescr , "fouet" := 1 & num & Recipes.TermDescr , "casserole" := 1 & num & Recipes.TermDescr , "gasinière" := 1 & num & Recipes.TermDescr ] , functionSteps = [ "Faire chauffer les ingrédients dans une casserole\nen remuant avec un fouet\nen faisant des cercles et des huits constamment\njusqu'à épaississement de la crème" ] , functionOutputs = [ "crème citron" := 1 & num ] } , "Faire la tarte au citron" := Recipes.Function { functionInputs = [ "fond de tarte cuit" := Recipes.TermRef { termRefName = "Cuire le fond de tarte" , termRefPort = Just "fond de tarte cuit" , termRefQuantity = Just $ 1 & num } , "crème citron" := Recipes.TermRef { termRefName = "Faire la crème citron" , termRefPort = Just "crème citron" , termRefQuantity = Just $ 1 & num } ] , functionSteps = [ "Verser sur le fond de tarte cuit" , "Laisser refroidir" ] , functionOutputs = [ "tarte au citron" := 1 & num ] } , "Faire la meringue" := Recipes.Function { functionInputs = [ "blanc d'œuf" := Recipes.TermRef { termRefName = "Séparer les œufs" , termRefPort = Just "blanc d'œuf" , termRefQuantity = Just $ 2 & num } , "sucre glace" := 100 & grams & Recipes.TermDescr , "levure chimique" := 0.5 & teaspoon & Recipes.TermDescr , "sel" := 1 & pincée & Recipes.TermDescr ] , functionSteps = [ "Monter les blancs en neige" , "Quand les blancs commencent à être fermes,\najouter le sucre puis la levure" ] , functionOutputs = [ "meringue" := 1 & num ] } , "Faire la tarte au citron meringuée" := Recipes.Function { functionInputs = [ "tarte au citron" := Recipes.TermRef { termRefName = "Faire la tarte au citron" , termRefPort = Just "tarte au citron" , termRefQuantity = Just $ 1 & num } , "meringue" := Recipes.TermRef { termRefName = "Faire la meringue" , termRefPort = Just "meringue" , termRefQuantity = Just $ 1 & num } , "four" := 1 & num & Recipes.TermDescr ] , functionSteps = [ "Recouvrir la tarte au citron de meringue" , "Enfourner la tarte jusqu'à ce que la meringue dore" ] , functionOutputs = [ "tarte au citron meringuée" := 1 & num ] } ] } grams :: Integer -> Recipes.Quantity grams s = (ShortText.pack (show s) <> "g") centiliters :: Integer -> Recipes.Quantity centiliters s = (ShortText.pack (show s) <> "cl") pincée :: Integer -> Recipes.Quantity pincée s = (ShortText.pack (show s) <> "pincée") tablespoon :: Rational -> Recipes.Quantity tablespoon r | denominator r == 1 = ShortText.pack $ show (numerator r) <> "càs" | otherwise = ShortText.pack $ show (numerator r) <> "/" <> show (denominator r) <> "càs" teaspoon :: Rational -> Recipes.Quantity teaspoon r | denominator r == 1 = ShortText.pack $ show (numerator r) <> "càc" | otherwise = ShortText.pack $ show (numerator r) <> "/" <> show (denominator r) <> "càc" num :: Integer -> Recipes.Quantity num s = (ShortText.pack (show s) <> "×")