1 {-# LANGUAGE OverloadedLists #-}
2 {-# LANGUAGE OverloadedStrings #-}
4 module RecipesSpec where
6 import Data.ByteString.Builder qualified as ByteString.Builder
7 import Data.Char qualified as Char
8 import Data.GenValidity.Map ()
9 import Data.GenValidity.Sequence ()
10 import Data.GenValidity.Set ()
11 import Data.GenValidity.Text ()
12 import Data.List qualified as List
13 import Data.Map.Strict qualified as Map
14 import Data.Ratio (denominator, numerator)
15 import Data.Set qualified as Set
16 import Data.Text qualified as Text
17 import Data.Text.Encoding qualified as Text
18 import Data.Text.Lazy.Encoding qualified as Text.Lazy
19 import Data.Text.Short qualified as ShortText
20 import Data.Validity.Map ()
21 import Data.Validity.Set ()
22 import Data.Validity.Text ()
23 import Graph.DOT qualified as DOT
25 import Language.French qualified as French
26 import Language.Pronunciation (ExampleLiteral (..), Lexeme (..), Rule (..), RuleLexemes, after, before, begining, ending, meaning, occurence, rule, silent, word)
27 import Language.Pronunciation qualified as Pron
28 import Paths_worksheets qualified as Self
29 import Recipes qualified as Recipes
30 import System.Directory qualified as IO
31 import System.FilePath (joinPath, pathSeparator, (<.>), (</>))
32 import System.FilePath.Posix qualified as File
33 import System.IO qualified as IO
35 import Text.Blaze.Html5.Attributes qualified as HA
36 import Utils.Pronunciation qualified as Pron
38 import Wiktionary qualified
39 import Worksheets.Utils.HTML (Html, className, classes, cm, styles, (!))
40 import Worksheets.Utils.HTML qualified as HTML
41 import Worksheets.Utils.IPA qualified as IPA
42 import Worksheets.Utils.Paper qualified as Paper
43 import Worksheets.Utils.Prelude
44 import Worksheets.Utils.SQL qualified as SQL
45 import Prelude (error, even, mod)
47 spec :: HasCallStack => Spec
50 recipeSpec recipeTarteAuCitron
52 recipeSpec recipe@Recipes.Recipe{..} = do
53 let title = recipeName & ShortText.unpack
54 outPath <- goldenPath title "dot"
56 goldenByteStringBuilderFile outPath do
57 return $ Recipes.recipeDOT recipe
59 -- let (blancDœuf, jauneDœuf) = séparerŒuf `app` (œuf & qty 2) `app` (bol & qty 2)
60 -- let beurreCubes = couperEnCubes `app` (beurre & grams 125) `app` (couteau & qty 1)
61 -- let pâteSablée = mélanger
64 { recipeName = "TarteAuCitron"
66 [ "Préchauffer le four" :=
69 [ "four" := 1 & num & Recipes.TermDescr
72 [ "Préchauffer le four 10min à 180°C"
75 [ "four préchauffé" := 1 & num
78 , "Séparer les œufs" :=
81 [ "œuf" := 2 & num & Recipes.TermDescr
82 , "bol" := 2 & num & Recipes.TermDescr
85 [ "Séparer les jaunes des blancs"
88 [ "blanc d'œuf" := 2 & num
89 , "jaune d'œuf" := 2 & num
92 , "Couper le beurre" :=
95 [ "beurre" := 125 & grams & Recipes.TermDescr
96 , "couteau" := 1 & num & Recipes.TermDescr
99 [ "Couper en petits cubes d'1cm de côté"
102 [ "beurre découpé" := 125 & grams
105 , "Faire la pâte sableuse" :=
108 [ "beurre en cubes" :=
110 { termRefName = "Couper le beurre"
111 , termRefPort = Just "beurre découpé"
112 , termRefQuantity = Nothing
114 , "saladier" := 1 & num & Recipes.TermDescr
115 , "doigts" := 10 & num & Recipes.TermDescr
116 , "farine" := 200 & grams & Recipes.TermDescr
119 [ "Mélanger (vite) les ingrédients sableux"
122 [ "pâte sableuse" := ""
125 , "Faire la pâte mousseuse" :=
130 { termRefName = "Séparer les œufs"
131 , termRefPort = Just "jaune d'œuf"
132 , termRefQuantity = Just $ 2 & num
134 , "sucre semoule" := 70 & grams & Recipes.TermDescr
135 , "saladier" := 1 & num & Recipes.TermDescr
136 , "fourchette" := 1 & num & Recipes.TermDescr
137 , "eau" := 2 & tablespoon & Recipes.TermDescr
140 [ "Mélanger les ingrédients mousseux"
143 [ "pâte mousseuse" := ""
146 , "Faire la pâte sablée" :=
149 [ "pâte mousseuse" :=
151 { termRefName = "Faire la pâte mousseuse"
152 , termRefPort = Just "pâte mousseuse"
153 , termRefQuantity = Nothing -- Just $ 1 & num
157 { termRefName = "Faire la pâte sableuse"
158 , termRefPort = Just "pâte sableuse"
159 , termRefQuantity = Nothing -- Just $ 1 & num
163 [ "Incorporer rapidement au couteau les éléments\nsans leur donner de corps"
164 , "Former une boule de pâte sablée avec les paumes"
165 , "Écraser 1 ou 2 fois la boule pour la rendre plus homogène"
168 [ "boule de pâte sablée" := 1 & num
171 , "Cuire le fond de tarte" :=
174 [ "four préchauffé" :=
176 { termRefName = "Préchauffer le four"
177 , termRefPort = Just "four préchauffé"
178 , termRefQuantity = Nothing -- Just $ 1 & num
180 , "boule de pâte sablée" :=
182 { termRefName = "Faire la pâte sablée"
183 , termRefPort = Just "boule de pâte sablée"
184 , termRefQuantity = Nothing -- Just $ 1 & num
188 [ "Foncer la pâte dans le moule"
189 , "(optionnel) Recouvrir la pâte de papier sulfurisé et de haricots sec"
190 , "Cuire la pâte à blanc 20 à 25 minutes"
193 [ "fond de tarte cuit" := 1 & num
196 , "Zester les citrons" :=
199 [ "citron" := 2 & num & Recipes.TermDescr
202 [ "Laver les citrons"
203 , "Râper les citrons"
206 [ "zeste de citron" := 1 & num
207 , "citron lavé" := 2 & num
210 , "Presse les citrons" :=
215 { termRefName = "Zester les citrons"
216 , termRefPort = Just "citron lavé"
217 , termRefQuantity = Just $ 2 & num
219 , "citron" := 2 & num & Recipes.TermDescr
222 [ "Presser les citrons"
225 [ "jus de citron" := 1 & num
228 , "Faire la crème citron" :=
231 [ "zeste de citron" :=
233 { termRefName = "Zester les citrons"
234 , termRefPort = Just "zeste de citron"
235 , termRefQuantity = Nothing -- Just $ 2 & num
239 { termRefName = "Presse les citrons"
240 , termRefPort = Just "jus de citron"
241 , termRefQuantity = Nothing -- Just $ 4 & num
243 , "sucre semoule" := 150 & grams & Recipes.TermDescr
244 , "farine de maïs" := 1 & tablespoon & Recipes.TermDescr
245 , "fouet" := 1 & num & Recipes.TermDescr
246 , "casserole" := 1 & num & Recipes.TermDescr
247 , "gasinière" := 1 & num & Recipes.TermDescr
250 [ "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"
253 [ "crème citron" := 1 & num
256 , "Faire la tarte au citron" :=
259 [ "fond de tarte cuit" :=
261 { termRefName = "Cuire le fond de tarte"
262 , termRefPort = Just "fond de tarte cuit"
263 , termRefQuantity = Just $ 1 & num
267 { termRefName = "Faire la crème citron"
268 , termRefPort = Just "crème citron"
269 , termRefQuantity = Just $ 1 & num
273 [ "Verser sur le fond de tarte cuit"
274 , "Laisser refroidir"
277 [ "tarte au citron" := 1 & num
280 , "Faire la meringue" :=
285 { termRefName = "Séparer les œufs"
286 , termRefPort = Just "blanc d'œuf"
287 , termRefQuantity = Just $ 2 & num
289 , "sucre glace" := 100 & grams & Recipes.TermDescr
290 , "levure chimique" := 0.5 & teaspoon & Recipes.TermDescr
291 , "sel" := 1 & pincée & Recipes.TermDescr
294 [ "Monter les blancs en neige"
295 , "Quand les blancs commencent à être fermes,\najouter le sucre puis la levure"
298 [ "meringue" := 1 & num
301 , "Faire la tarte au citron meringuée" :=
304 [ "tarte au citron" :=
306 { termRefName = "Faire la tarte au citron"
307 , termRefPort = Just "tarte au citron"
308 , termRefQuantity = Just $ 1 & num
312 { termRefName = "Faire la meringue"
313 , termRefPort = Just "meringue"
314 , termRefQuantity = Just $ 1 & num
316 , "four" := 1 & num & Recipes.TermDescr
319 [ "Recouvrir la tarte au citron de meringue"
320 , "Enfourner la tarte jusqu'à ce que la meringue dore"
323 [ "tarte au citron meringuée" := 1 & num
329 grams :: Integer -> Recipes.Quantity
330 grams s = (ShortText.pack (show s) <> "g")
331 centiliters :: Integer -> Recipes.Quantity
332 centiliters s = (ShortText.pack (show s) <> "cl")
333 pincée :: Integer -> Recipes.Quantity
334 pincée s = (ShortText.pack (show s) <> "pincée")
335 tablespoon :: Rational -> Recipes.Quantity
337 | denominator r == 1 = ShortText.pack $ show (numerator r) <> "càs"
338 | otherwise = ShortText.pack $ show (numerator r) <> "/" <> show (denominator r) <> "càs"
339 teaspoon :: Rational -> Recipes.Quantity
341 | denominator r == 1 = ShortText.pack $ show (numerator r) <> "càc"
342 | otherwise = ShortText.pack $ show (numerator r) <> "/" <> show (denominator r) <> "càc"
343 num :: Integer -> Recipes.Quantity
344 num s = (ShortText.pack (show s) <> "×")