From 34a0e9cda8770d4784a9bab745f9108669ed5657 Mon Sep 17 00:00:00 2001
From: aqquq <jannik.wurche@student.uni-halle.de>
Date: Wed, 3 Jul 2024 18:06:25 +0200
Subject: [PATCH] =?UTF-8?q?=F0=9F=86=95=20add=20Encoders=20for=20PartialQu?=
 =?UTF-8?q?iz=20and=20sub-types?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/Utils/Api.elm | 180 +++++++++++++++++++++++++++++++++-------------
 1 file changed, 129 insertions(+), 51 deletions(-)

diff --git a/src/Utils/Api.elm b/src/Utils/Api.elm
index 3b3b6b7..b8eb2e5 100644
--- a/src/Utils/Api.elm
+++ b/src/Utils/Api.elm
@@ -1,67 +1,92 @@
 module Utils.Api exposing (..)
 
 import Types exposing (..)
-import Json.Encode exposing (object)
-import Json.Decode as Decode exposing (..)
+import Json.Encode as E exposing (..)
+import Json.Decode as D exposing (..)
+
+encodeNullable : (value -> E.Value) -> Maybe value -> E.Value
+encodeNullable valueEncoder maybeValue =
+    case maybeValue of
+        Just value ->
+            valueEncoder value
+
+        Nothing ->
+            E.null
+
+encodeGraph : Graph -> E.Value
+encodeGraph graph =
+    object 
+        [ ("window", encodeWindow graph.window)
+        , ("functions", E.list encodeMathFunction graph.functions)
+        ]
+
+encodeWindow : Window -> E.Value
+encodeWindow window =
+    object 
+        [ ("xMin", E.int window.xMin)
+        , ("xMax", E.int window.xMax)
+        , ("yMin", E.int window.yMin)
+        , ("yMax", E.int window.yMax)
+        ]
 
-encodeMathFunction : MathFunction -> Json.Encode.Value
+encodeMathFunction : MathFunction -> E.Value
 encodeMathFunction mathFunction =
     case mathFunction of
         Const x ->
-            object [ ( "type", Json.Encode.string "Const" ), ( "value", Json.Encode.float x ) ]
+            object [ ( "type", E.string "Const" ), ( "value", E.float x ) ]
 
         X ->
-            object [ ( "type", Json.Encode.string "X" ) ]
+            object [ ( "type", E.string "X" ) ]
 
         Add f1 f2 ->
-            object [ ( "type", Json.Encode.string "Add" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
+            object [ ( "type", E.string "Add" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
 
         Sub f1 f2 ->
-            object [ ( "type", Json.Encode.string "Sub" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
+            object [ ( "type", E.string "Sub" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
 
         Mul f1 f2 ->
-            object [ ( "type", Json.Encode.string "Mul" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
+            object [ ( "type", E.string "Mul" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
 
         Div f1 f2 ->
-            object [ ( "type", Json.Encode.string "Div" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
+            object [ ( "type", E.string "Div" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
 
         Pow f1 f2 ->
-            object [ ( "type", Json.Encode.string "Pow" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
+            object [ ( "type", E.string "Pow" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
 
         Log f1 f2 ->
-            object [ ( "type", Json.Encode.string "Log" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
+            object [ ( "type", E.string "Log" ), ( "left", encodeMathFunction f1 ), ( "right", encodeMathFunction f2 ) ]
 
         Ln f ->
-            object [ ( "type", Json.Encode.string "Ln" ), ( "argument", encodeMathFunction f ) ]
+            object [ ( "type", E.string "Ln" ), ( "argument", encodeMathFunction f ) ]
 
         Neg f ->
-            object [ ( "type", Json.Encode.string "Neg" ), ( "argument", encodeMathFunction f ) ]
+            object [ ( "type", E.string "Neg" ), ( "argument", encodeMathFunction f ) ]
 
         Sin f ->
-            object [ ( "type", Json.Encode.string "Sin" ), ( "argument", encodeMathFunction f ) ]
+            object [ ( "type", E.string "Sin" ), ( "argument", encodeMathFunction f ) ]
 
         Cos f ->
-            object [ ( "type", Json.Encode.string "Cos" ), ( "argument", encodeMathFunction f ) ]
+            object [ ( "type", E.string "Cos" ), ( "argument", encodeMathFunction f ) ]
 
         Tan f ->
-            object [ ( "type", Json.Encode.string "Tan" ), ( "argument", encodeMathFunction f ) ]
+            object [ ( "type", E.string "Tan" ), ( "argument", encodeMathFunction f ) ]
 
         Exp f ->
-            object [ ( "type", Json.Encode.string "Exp" ), ( "argument", encodeMathFunction f ) ]
+            object [ ( "type", E.string "Exp" ), ( "argument", encodeMathFunction f ) ]
 
 
 decodeMathFunctionInit : Decoder MathFunction
 decodeMathFunctionInit =
-    field "type" Decode.string |> andThen decodeMathFunction
+    field "type" D.string |> andThen decodeMathFunction
 
 decodeMathFunction : String -> Decoder MathFunction
 decodeMathFunction type_ =
     case type_ of
         "Const" ->
-            field "value" Decode.float |> map Const
+            field "value" D.float |> map Const
 
         "X" ->
-            Decode.succeed X
+            D.succeed X
 
         "Add" ->
             map2 Add (field "left" decodeMathFunctionInit) (field "right" decodeMathFunctionInit)
@@ -100,65 +125,118 @@ decodeMathFunction type_ =
             map Exp (field "argument" decodeMathFunctionInit)
 
         _ ->
-            Decode.fail ("Unknown MathFunction type: " ++ type_)
+            D.fail ("Unknown MathFunction type: " ++ type_)
 
 decodeGraph : Decoder Graph
 decodeGraph = 
     map2 Graph
         (field "window" decodeWindow)
-        (field "functions" (list decodeMathFunctionInit))
+        (field "functions" (D.list decodeMathFunctionInit))
 
 decodeWindow : Decoder Window
 decodeWindow =
     map4 Window
-        (field "xMin" int)
-        (field "yMin" int)
-        (field "xMax" int)
-        (field "yMax" int)
+        (field "xMin" D.int)
+        (field "yMin" D.int)
+        (field "xMax" D.int)
+        (field "yMax" D.int)
 
 partialMCQDecoder : Decoder PartialQuestionType
 partialMCQDecoder =
-    Decode.map2 (\choices correct -> PartialMCQ { choices = choices, correct = correct })
-        (Decode.field "choices" (Decode.list Decode.string))
-        (Decode.field "correct" (Decode.list Decode.string))
+    D.map2 (\choices correct -> PartialMCQ { choices = choices, correct = correct })
+        (D.field "choices" (D.list D.string))
+        (D.field "correct" (D.list D.string))
 
 partialSCQDecoder : Decoder PartialQuestionType
 partialSCQDecoder =
-    Decode.map2 (\choices correct -> PartialSCQ { choices = choices, correct = correct })
-        (Decode.field "choices" (Decode.list Decode.string))
-        (Decode.field "correct" Decode.string)
+    D.map2 (\choices correct -> PartialSCQ { choices = choices, correct = correct })
+        (D.field "choices" (D.list D.string))
+        (D.field "correct" D.string)
 
 partialInputDecoder : Decoder PartialQuestionType
 partialInputDecoder =
-    Decode.map2 (\correct sensitive -> PartialInput { correct = correct, sensitive = sensitive })
-        (Decode.field "correct" (Decode.list Decode.string))
-        (Decode.field "sensitive" Decode.bool)
+    D.map2 (\correct sensitive -> PartialInput { correct = correct, sensitive = sensitive })
+        (D.field "correct" (D.list D.string))
+        (D.field "sensitive" D.bool)
 
 partialQuestionTypeDecoder : Decoder PartialQuestionType
 partialQuestionTypeDecoder =
-    Decode.oneOf
-        [ Decode.field "MCQ" partialMCQDecoder
-        , Decode.field "SCQ" partialSCQDecoder
-        , Decode.field "Input" partialInputDecoder
+    D.oneOf
+        [ D.field "MCQ" partialMCQDecoder
+        , D.field "SCQ" partialSCQDecoder
+        , D.field "Input" partialInputDecoder
         ]
 
 partialQuestionDecoder : Decoder PartialQuestion
 partialQuestionDecoder =
-    Decode.map6 PartialQuestion
-        (Decode.field "task" Decode.string)
-        (Decode.field "hint" (Decode.maybe Decode.string))
-        (Decode.field "explanation" (Decode.maybe Decode.string))
-        (Decode.field "image" (Decode.maybe Decode.string))
-        (Decode.field "graph" (Decode.maybe decodeGraph))
-        (Decode.field "questionType" partialQuestionTypeDecoder)
+    D.map6 PartialQuestion
+        (D.field "task" D.string)
+        (D.field "hint" (D.maybe D.string))
+        (D.field "explanation" (D.maybe D.string))
+        (D.field "image" (D.maybe D.string))
+        (D.field "graph" (D.maybe decodeGraph))
+        (D.field "questionType" partialQuestionTypeDecoder)
 
 partialQuizDecoder : Decoder PartialQuiz
 partialQuizDecoder =
-    Decode.map4 PartialQuiz
-        (Decode.field "id" Decode.string)
-        (Decode.field "name" Decode.string)
-        (Decode.field "duration" (Decode.maybe Decode.int))
-        (Decode.field "questions" (Decode.list partialQuestionDecoder))
+    D.map4 PartialQuiz
+        (D.field "id" D.string)
+        (D.field "name" D.string)
+        (D.field "duration" (D.maybe D.int))
+        (D.field "questions" (D.list partialQuestionDecoder))
+
+partialQuestionTypeEncoder : PartialQuestionType -> E.Value
+partialQuestionTypeEncoder questionType =
+    case questionType of
+        PartialMCQ { choices, correct } ->
+            object
+                [ ( "MCQ", 
+                    object
+                        [ ( "choices", E.list E.string choices )
+                        , ( "correct", E.list E.string correct )
+                        ]
+                  )
+                ]
+
+        PartialSCQ { choices, correct } ->
+            object
+                [ ( "SCQ",
+                    object
+                        [ ( "choices", E.list E.string choices )
+                        , ( "correct", E.string correct )
+                        ]
+                  )
+                ]
+
+        PartialInput { correct, sensitive } ->
+            object
+                [ ( "Input",
+                    object
+                        [ ( "correct", E.list E.string correct )
+                        , ( "sensitive", E.bool sensitive )
+                        ]
+                  )
+                ]
+
+partialQuestionEncoder : PartialQuestion -> E.Value
+partialQuestionEncoder question =
+    object
+        [ ( "task", E.string question.task )
+        , ( "hint", encodeNullable E.string question.hint )
+        , ( "explanation", encodeNullable E.string question.explanation )
+        , ( "image", encodeNullable E.string question.image )
+        , ( "graph", encodeNullable encodeGraph question.graph )
+        , ( "questionType", partialQuestionTypeEncoder question.questionType )
+        ]
+
+partialQuizEncoder : PartialQuiz -> E.Value
+partialQuizEncoder quiz =
+    object
+        [ ( "id", E.string quiz.id )
+        , ( "name", E.string quiz.name )
+        , ( "duration", encodeNullable E.int quiz.duration )
+        , ( "questions", E.list partialQuestionEncoder quiz.questions )
+        ]
 
 transformPartialQuiz : PartialQuiz -> Quiz
 transformPartialQuiz partialQuiz =
-- 
GitLab