Export des notes sous forme de tableau OrgMode

pull/1/head
Jean-Christophe Jameux 4 years ago
parent d5316f40e2
commit 9afce0fef2
  1. BIN
      elm-stuff/0.19.1/CalculateurDeNotes.elmi
  2. BIN
      elm-stuff/0.19.1/CalculateurDeNotes.elmo
  3. BIN
      elm-stuff/0.19.1/d.dat
  4. BIN
      elm-stuff/0.19.1/i.dat
  5. 2
      elm.json
  6. 805
      src/CalculateurDeNotes.elm
  7. 262
      src/Fraction.elm
  8. 1465
      src/GenerateurDeProblemes.elm
  9. 60
      src/ParserMaths.elm
  10. 45
      src/Test.elm

Binary file not shown.

Binary file not shown.

@ -8,6 +8,7 @@
"direct": { "direct": {
"elm/browser": "1.0.2", "elm/browser": "1.0.2",
"elm/core": "1.0.5", "elm/core": "1.0.5",
"elm/file": "1.0.5",
"elm/html": "1.0.0", "elm/html": "1.0.0",
"elm/parser": "1.1.0", "elm/parser": "1.1.0",
"elm/random": "1.0.0", "elm/random": "1.0.0",
@ -21,7 +22,6 @@
"Janiczek/elm-bidict": "2.0.1", "Janiczek/elm-bidict": "2.0.1",
"andre-dietrich/parser-combinators": "3.2.0", "andre-dietrich/parser-combinators": "3.2.0",
"elm/bytes": "1.0.8", "elm/bytes": "1.0.8",
"elm/file": "1.0.5",
"elm/http": "2.0.0", "elm/http": "2.0.0",
"elm/json": "1.1.3", "elm/json": "1.1.3",
"elm/regex": "1.0.0", "elm/regex": "1.0.0",

@ -1,221 +1,303 @@
module CalculateurDeNotes exposing (..) module CalculateurDeNotes exposing (..)
import Array exposing (..)
import Browser import Browser
import Html exposing (Html)
import Element exposing (..) import Element exposing (..)
import Element.Input as Input import Element.Input as Input
import Set import File.Download
import Array exposing (..) import Html exposing (Html)
import Parser exposing (..) import Parser exposing (..)
import Set
{- {-
-} -}
main = main =
Browser.element Browser.element
{ init = init { init = init
, update = update , update = update
, subscriptions = subscriptions , subscriptions = subscriptions
, view = view , view = view
} }
{- {-
-} -}
type alias Model = type alias Model =
{ bareme : String { bareme : String
, reponsesCorrectes : String , reponsesCorrectes : String
, reponsesEleves : String , reponsesEleves : String
, eleves : Eleves , eleves : Eleves
} }
init : () -> (Model, Cmd Msg)
init : () -> ( Model, Cmd Msg )
init _ = init _ =
( { bareme = "" ( { bareme = ""
, reponsesCorrectes = "" , reponsesCorrectes = ""
, reponsesEleves = "" , reponsesEleves = ""
, eleves = [] , eleves = []
} }
, Cmd.none , Cmd.none
) )
{- {-
-} -}
type Msg type Msg
= NouveauBareme String = NouveauBareme String
| NouvellesReponsesCorrectes String | NouvellesReponsesCorrectes String
| NouvellesReponsesEleves String | NouvellesReponsesEleves String
-- | CalculerNotes | TelechargerNotes
update : Msg -> Model -> ( Model, Cmd Msg ) update : Msg -> Model -> ( Model, Cmd Msg )
update msg model = update msg model =
let let
brms = unsafeRun baremeSujet [] model.bareme brms =
rpnCorrectes = unsafeRun reponsesCorrectes Array.empty model.reponsesCorrectes unsafeRun baremeSujet [] model.bareme
rpnEleves = unsafeRun reponsesEleves [] model.reponsesEleves
in rpnCorrectes =
case msg of unsafeRun reponsesCorrectes Array.empty model.reponsesCorrectes
NouveauBareme nouveauBareme ->
let rpnEleves =
brmss = unsafeRun baremeSujet [] nouveauBareme unsafeRun reponsesEleves [] model.reponsesEleves
in in
( { model case msg of
| bareme = nouveauBareme NouveauBareme nouveauBareme ->
, eleves = notes brmss rpnCorrectes rpnEleves let
} brmss =
, Cmd.none unsafeRun baremeSujet [] nouveauBareme
) in
NouvellesReponsesCorrectes nouvellesReponsesCorrectes -> ( { model
let | bareme = nouveauBareme
rpnCorrectess = unsafeRun reponsesCorrectes Array.empty nouvellesReponsesCorrectes , eleves = notes brmss rpnCorrectes rpnEleves
in }
( { model , Cmd.none
| reponsesCorrectes = nouvellesReponsesCorrectes )
, eleves = notes brms rpnCorrectess rpnEleves
} NouvellesReponsesCorrectes nouvellesReponsesCorrectes ->
, Cmd.none let
) rpnCorrectess =
NouvellesReponsesEleves nouvellesReponsesEleves -> unsafeRun reponsesCorrectes Array.empty nouvellesReponsesCorrectes
let in
rpnElevess = unsafeRun reponsesEleves [] nouvellesReponsesEleves ( { model
in | reponsesCorrectes = nouvellesReponsesCorrectes
( { model , eleves = notes brms rpnCorrectess rpnEleves
| reponsesEleves = nouvellesReponsesEleves }
, eleves = notes brms rpnCorrectes rpnElevess , Cmd.none
} )
, Cmd.none
) NouvellesReponsesEleves nouvellesReponsesEleves ->
let
rpnElevess =
unsafeRun reponsesEleves [] nouvellesReponsesEleves
in
( { model
| reponsesEleves = nouvellesReponsesEleves
, eleves = notes brms rpnCorrectes rpnElevess
}
, Cmd.none
)
TelechargerNotes ->
( model
, File.Download.string "Notes.org" "text/org" <| voirNotesOrg model.eleves
)
unsafeRun prsr defaut texte = unsafeRun prsr defaut texte =
case run prsr texte of case run prsr texte of
Ok x -> x Ok x ->
_ -> defaut x
_ ->
defaut
-- SUBSCRIPTIONS -- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg subscriptions : Model -> Sub Msg
subscriptions model = subscriptions model =
Sub.none Sub.none
{- {-
-} -}
view : Model -> Html Msg view : Model -> Html Msg
view model = view model =
layout [ width fill, height fill ] <| layout [ width fill, height fill ] <|
row [spacing grandEspacement, padding tresGrandEspacement, height fill, width fill, clip, scrollbars] row
[ column [spacing petitEspacement, height fill, width fill, clip, scrollbars] [ spacing grandEspacement
[ Input.multiline [height <| maximum 300 fill, clip, scrollbars] , padding tresGrandEspacement
{ onChange = NouveauBareme , height fill
, label = Input.labelAbove [] <| text "Barème" , width fill
, placeholder = , clip
Just , scrollbars
<| Input.placeholder [] ]
<| text "Entrer le barème sous la forme +3 -1, +2 -1" [ column
, text = model.bareme [ spacing petitEspacement
, spellcheck = False , height fill
} , width fill
, Input.multiline [height <| maximum 300 fill, clip, scrollbars] , clip
{ onChange = NouvellesReponsesCorrectes , scrollbars
, label = Input.labelAbove [] <| text "Réponses correctes" ]
, placeholder = [ Input.multiline [ height <| maximum 300 fill, clip, scrollbars ]
Just { onChange = NouveauBareme
<| Input.placeholder [] , label = Input.labelAbove [] <| text "Barème"
<| text "Entrer les réponses correctes pour chaque sujet" , placeholder =
, text = model.reponsesCorrectes Just <|
, spellcheck = False Input.placeholder [] <|
} text "Entrer le barème sous la forme +3 -1, +2 -1"
, Input.multiline [height <| maximum 300 fill, clip, scrollbars] , text = model.bareme
{ onChange = NouvellesReponsesEleves , spellcheck = False
, label = Input.labelAbove [] <| text "Réponses des élèves" }
, placeholder = , Input.multiline [ height <| maximum 300 fill, clip, scrollbars ]
Just { onChange = NouvellesReponsesCorrectes
<| Input.placeholder [] , label = Input.labelAbove [] <| text "Réponses correctes"
<| text "Entrer les réponses des élèves" , placeholder =
, text = model.reponsesEleves Just <|
, spellcheck = False Input.placeholder [] <|
} text "Entrer les réponses correctes pour chaque sujet"
] , text = model.reponsesCorrectes
, column [spacing petitEspacement, height fill, width fill] , spellcheck = False
[ {-- Input.button [] }
{ onPress = Just CalculerNotes , Input.multiline [ height <| maximum 300 fill, clip, scrollbars ]
, label = text "Calculer les notes" { onChange = NouvellesReponsesEleves
} , label = Input.labelAbove [] <| text "Réponses des élèves"
--} , placeholder =
text Just <|
<| "Moyenne : " ++ String.fromFloat (moyenne model.eleves) Input.placeholder [] <|
++ " Écart type : " ++ String.fromFloat (ecartType model.eleves) text "Entrer les réponses des élèves"
, voirNotes model.eleves , text = model.reponsesEleves
] , spellcheck = False
] }
]
, column [ spacing petitEspacement, height fill, width fill ]
[ text <|
"Moyenne : "
++ String.fromFloat (moyenne model.eleves)
++ " Écart type : "
++ String.fromFloat (ecartType model.eleves)
, Input.button []
{ onPress = Just TelechargerNotes
, label = text "Télécharger le fichier de notes"
}
, voirNotes model.eleves
]
]
voirNotes : Eleves -> Element Msg voirNotes : Eleves -> Element Msg
voirNotes rpnsEleves = voirNotes rpnsEleves =
table [] table []
{ data = rpnsEleves { data = rpnsEleves
, columns = , columns =
[ { header = Element.text "Numéro étudiant" [ { header = Element.text "Numéro étudiant"
, width = fill , width = fill
, view = , view =
\rpns -> \rpns ->
Element.text rpns.numeroEtudiant Element.text rpns.numeroEtudiant
} }
, { header = Element.text "Note" , { header = Element.text "Note"
, width = fill , width = fill
, view = , view =
\rpns -> \rpns ->
case rpns.note of case rpns.note of
Nothing -> Element.text "" Nothing ->
Just nt -> Element.text <| String.fromFloat nt Element.text ""
}
] Just nt ->
} Element.text <| String.fromFloat nt
}
]
}
petitEspacement = 20
grandEspacement = 5*petitEspacement // 4 voirNotesOrg : Eleves -> String
voirNotesOrg rpnsEleves =
let
numero rpns =
rpns.numeroEtudiant
tresGrandEspacement = 25*petitEspacement // 16 voirNote rpns =
case rpns.note of
Nothing ->
""
{- Just nt ->
String.fromFloat nt
ligne rpns =
"|"
++ rpns.numeroEtudiant
-} ++ "|"
++ rpns.nomEtudiant
++ "|"
++ rpns.prenomEtudiant
++ "|"
++ voirNote rpns
++ "|\n"
in
"|Numéro|Nom|Prénom|Note|\n"
++ String.concat (List.map ligne rpnsEleves)
petitEspacement =
20
grandEspacement =
5 * petitEspacement // 4
tresGrandEspacement =
25 * petitEspacement // 16
{-
-}
{-- {--
baremeEtReponses = baremeEtReponses =
succeed (\brm rpn -> BaremeEtReponses brm (List.map (String.split "") rpn)) succeed (\brm rpn -> BaremeEtReponses brm (List.map (String.split "") rpn))
@ -224,220 +306,301 @@ baremeEtReponses =
--} --}
type alias BaremeSujet = List BaremeQuestion type alias BaremeSujet =
List BaremeQuestion
baremeSujet = baremeSujet =
sequence sequence
{ start = "" { start = ""
, separator = "," , separator = ","
, end = "" , end = ""
, spaces = espaces , spaces = espaces
, item = baremeQuestion , item = baremeQuestion
, trailing = Forbidden , trailing = Forbidden
} }
espaces = espaces =
chompWhile <| (==) ' ' chompWhile <| (==) ' '
type alias BaremeQuestion = type alias BaremeQuestion =
{ bonneReponse : Float { bonneReponse : Float
, mauvaiseReponse : Float , mauvaiseReponse : Float
} }
baremeQuestion = baremeQuestion =
succeed BaremeQuestion succeed BaremeQuestion
|= nombre |= nombre
|. spaces |. spaces
|= nombre |= nombre
nombre : Parser Float nombre : Parser Float
nombre = nombre =
oneOf oneOf
[ succeed negate [ succeed negate
|. symbol "-" |. symbol "-"
|= float |= float
, succeed identity , succeed identity
|. symbol "+" |. symbol "+"
|= float |= float
] ]
{- {-
-} -}
type alias ReponsesCorrectes = Array Reponses
type alias ReponsesCorrectes =
Array Reponses
reponsesCorrectes : Parser ReponsesCorrectes reponsesCorrectes : Parser ReponsesCorrectes
reponsesCorrectes = reponsesCorrectes =
succeed Array.fromList succeed Array.fromList
|= sequence |= sequence
{ start = "" { start = ""
, separator = "\n" , separator = "\n"
, end = "" , end = ""
, spaces = espaces , spaces = espaces
, item = reponses , item = reponses
, trailing = Optional , trailing = Optional
} }
type alias Reponses = List String type alias Reponses =
List String
reponses = reponses =
sequence sequence
{ start = "" { start = ""
, separator = "" , separator = ""
, end = "" , end = ""
, spaces = espaces , spaces = espaces
, item = variable , item =
{ start = ( \ x -> x /= '\n' && x /= ';' ) variable
, inner = \_ -> False { start = \x -> x /= '\n' && x /= ';'
, reserved = Set.fromList [] , inner = \_ -> False
} , reserved = Set.fromList []
, trailing = Optional }
} , trailing = Optional
}
type alias Eleves =
List Eleve
type alias Eleves = List Eleve
reponsesEleves : Parser Eleves reponsesEleves : Parser Eleves
reponsesEleves = reponsesEleves =
sequence sequence
{ start = "" { start = ""
, separator = "\n" , separator = "\n"
, end = "" , end = ""
, spaces = espaces , spaces = espaces
, item = reponsesEleve , item = reponsesEleve
, trailing = Optional , trailing = Optional
} }
{- {-
-} -}
type alias Eleve = type alias Eleve =
{ numeroEtudiant : String { numeroEtudiant : String
, numeroSujet : Int , numeroSujet : Int
, reponses : Reponses , nomEtudiant : String
, note : Maybe Float , prenomEtudiant : String
} , reponses : Reponses
, note : Maybe Float
}
reponsesEleve = reponsesEleve =
succeed Eleve succeed Eleve
|= etudiant |= etudiant
|= int |= int
|. champzInteret |= champ
|. champzInteret |= champ
|= reponsesQuizScan |= reponsesQuizScan
|= champzInteret |= champzInteret
etudiant = etudiant =
getChompedString getChompedString <|
<| chompIf Char.isDigit chompIf Char.isDigit
|. chompIf Char.isDigit |. chompIf Char.isDigit
|. chompIf Char.isDigit |. chompIf Char.isDigit
|. chompIf Char.isDigit |. chompIf Char.isDigit
|. chompIf Char.isDigit |. chompIf Char.isDigit
champ =
succeed identity
|. symbol ";"
|= getChompedString (chompWhile ((/=) ';'))
champzInteret = champzInteret =
succeed Nothing succeed Nothing
|. symbol ";" |. symbol ";"
|. chompWhile ( \ x -> x /= '\n' && x /= ';' ) |. chompWhile (\x -> x /= '\n' && x /= ';')
reponsesQuizScan = reponsesQuizScan =
sequence sequence
{ start = ";" { start = ";"
, separator = ";" , separator = ";"
, end = "" , end = ""
, spaces = espaces , spaces = espaces
, item = variable , item =
{ start = ( \ x -> x /= '\n' && x /= ';' ) variable
, inner = \_ -> False { start = \x -> x /= '\n' && x /= ';'
, reserved = Set.fromList [] , inner = \_ -> False
} , reserved = Set.fromList []
, trailing = Mandatory }
} , trailing = Mandatory
}
notes : BaremeSujet -> ReponsesCorrectes -> Eleves -> Eleves notes : BaremeSujet -> ReponsesCorrectes -> Eleves -> Eleves
notes brms rpnCorrectes rpnEleves = notes brms rpnCorrectes rpnEleves =
let let
f rpnEleve = f rpnEleve =
case Array.get (rpnEleve.numeroSujet - 11) rpnCorrectes of case Array.get (rpnEleve.numeroSujet - 11) rpnCorrectes of
Nothing -> rpnEleve Nothing ->
Just bonneRpns -> rpnEleve
{ rpnEleve | note = noteSujet brms bonneRpns rpnEleve.reponses }
in Just bonneRpns ->
List.map f rpnEleves { rpnEleve | note = noteSujet brms bonneRpns rpnEleve.reponses }
in
List.map f rpnEleves
noteSujet : BaremeSujet -> Reponses -> Reponses -> Maybe Float noteSujet : BaremeSujet -> Reponses -> Reponses -> Maybe Float
noteSujet brms bonneRpns rpnsEleve = noteSujet brms bonneRpns rpnsEleve =
case brms of case brms of
[] -> Just 0 [] ->
brm :: brmss -> Just 0
let
bonneRpn = List.head bonneRpns brm :: brmss ->
bonneRpnSuite = List.tail bonneRpns let
rpnEleve = List.head rpnsEleve bonneRpn =
rpnEleveSuite = List.tail rpnsEleve List.head bonneRpns
in
case ( (bonneRpn, bonneRpnSuite), (rpnEleve, rpnEleveSuite) ) of bonneRpnSuite =
( (Just bnRpn, Just bnRpnSuite), (Just rpnElv, Just rpnElvSuite) ) -> List.tail bonneRpns
noteSujet brmss bnRpnSuite rpnElvSuite
|> Maybe.andThen ( Just << (+) ( noteQuestion brm bnRpn rpnElv ) ) rpnEleve =
_ -> Nothing List.head rpnsEleve
rpnEleveSuite =
List.tail rpnsEleve
in
case ( ( bonneRpn, bonneRpnSuite ), ( rpnEleve, rpnEleveSuite ) ) of
( ( Just bnRpn, Just bnRpnSuite ), ( Just rpnElv, Just rpnElvSuite ) ) ->
noteSujet brmss bnRpnSuite rpnElvSuite
|> Maybe.andThen (Just << (+) (noteQuestion brm bnRpn rpnElv))
_ ->
Nothing
noteQuestion brm bonneRpn rpnEleve = noteQuestion brm bonneRpn rpnEleve =
case bonneRpn of case bonneRpn of
"V" -> "V" ->
if rpnEleve == "A" then brm.bonneReponse if rpnEleve == "A" then
else if rpnEleve == "B" then 2*brm.bonneReponse/3 brm.bonneReponse
else if rpnEleve == "C" then brm.mauvaiseReponse/3
else if rpnEleve == "D" then brm.mauvaiseReponse else if rpnEleve == "B" then
else 0 2 * brm.bonneReponse / 3
"F" ->
if rpnEleve == "D" then brm.bonneReponse else if rpnEleve == "C" then
else if rpnEleve == "C" then 2*brm.bonneReponse/3 brm.mauvaiseReponse / 3
else if rpnEleve == "B" then brm.mauvaiseReponse/3
else if rpnEleve == "A" then brm.mauvaiseReponse else if rpnEleve == "D" then
else 0 brm.mauvaiseReponse
_ ->
if bonnerpn == rpneleve then else
brm.bonnereponse 0
else if rpneleve == "-" then
0 "F" ->
else if rpnEleve == "D" then
brm.mauvaisereponse brm.bonneReponse
else if rpnEleve == "C" then
2 * brm.bonneReponse / 3
else if rpnEleve == "B" then
brm.mauvaiseReponse / 3
else if rpnEleve == "A" then
brm.mauvaiseReponse
else
0
_ ->
if bonneRpn == rpnEleve then
brm.bonneReponse
else if rpnEleve == "-" then
0
else
brm.mauvaiseReponse
moyenne elvs = moyenne elvs =
let let
moy nts = List.sum nts / toFloat (List.length nts) moy nts =
in List.sum nts / toFloat (List.length nts)
List.map .note elvs in
|> expurgerNotesManquantes List.map .note elvs
|> moy |> expurgerNotesManquantes
|> moy
ecartType elvs = ecartType elvs =
let let
moy nts = List.sum nts / toFloat (List.length nts) moy nts =
moyCarre = moy << List.map (\x -> x^2) List.sum nts / toFloat (List.length nts)
ecTp nts = sqrt <| moyCarre nts - (moy nts)^2
in moyCarre =
List.map .note elvs moy << List.map (\x -> x ^ 2)
|> expurgerNotesManquantes
|> ecTp ecTp nts =
sqrt <| moyCarre nts - moy nts ^ 2
in
List.map .note elvs
|> expurgerNotesManquantes
|> ecTp
expurgerNotesManquantes nts = expurgerNotesManquantes nts =
case nts of case nts of
[] -> [] [] ->
Nothing :: ntss -> expurgerNotesManquantes ntss []
Just nt :: ntss -> nt :: expurgerNotesManquantes ntss
Nothing :: ntss ->
expurgerNotesManquantes ntss
(Just nt) :: ntss ->
nt :: expurgerNotesManquantes ntss

@ -1,130 +1,206 @@
module Fraction exposing module Fraction exposing
( Fraction ( Erreur
, Resultat , Fraction
, Erreur , Resultat
, frac , add
, num , den
, den , div
, estEntier , estEntier
, opp , exp
, add , frac
, neg , inv
, sub , mul
, mul , neg
, inv , num
, div , opp
, exp , raw
, teX , sub
, raw , teX
) )
import Arithmetic exposing (gcd) import Arithmetic exposing (gcd)
type alias Fraction =
{ num : Int, den : Int }
type alias Fraction = { num : Int, den : Int }
type alias Resultat = Result Erreur Fraction type alias Resultat =
type alias Erreur = String Result Erreur Fraction
type alias Erreur =
String
frac : Int -> Int -> Resultat frac : Int -> Int -> Resultat
frac a b = frac a b =
let let
min = 1 - 2^31 min =
max = 2^31 - 1 1 - 2 ^ 31
in
case b of max =
0 -> Err "Division par zéro." 2 ^ 31 - 1
_ -> in
if a > max || b > max || a < min || b < min then case b of
Err "Certains calculs font intervenir des valeurs trop grandes pour être prises en charge." 0 ->
else Err "Division par zéro."
Ok <| simplifier <| Fraction a b
_ ->
if a > max || b > max || a < min || b < min then
Err "Certains calculs font intervenir des valeurs trop grandes pour être prises en charge."
else
Ok <| simplifier <| Fraction a b
simplifier : Fraction -> Fraction simplifier : Fraction -> Fraction
simplifier a = simplifier a =
let let
pgcd = gcd a.num a.den pgcd =
sgnDuDen = gcd a.num a.den
if a.den < 0 then -1 else 1
in sgnDuDen =
{ a if a.den < 0 then
| num = sgnDuDen*(a.num // pgcd) -1
, den = sgnDuDen*(a.den // pgcd)
} else
1
in
{ a
| num = sgnDuDen * (a.num // pgcd)
, den = sgnDuDen * (a.den // pgcd)
}
num a =
a.num
num a = a.num
den a = a.den den a =
a.den
estEntier a =
a.den == 1
estEntier a = a.den == 1
opp : (Fraction -> Fraction -> Resultat) -> Resultat -> Resultat -> Resultat opp : (Fraction -> Fraction -> Resultat) -> Resultat -> Resultat -> Resultat
opp operation resultat1 resultat2 = opp operation resultat1 resultat2 =
case (resultat1, resultat2) of case ( resultat1, resultat2 ) of
(Ok fraction1, Ok fraction2) -> operation fraction1 fraction2 ( Ok fraction1, Ok fraction2 ) ->
(Err erreur, _) -> Err erreur operation fraction1 fraction2
(_, Err erreur) -> Err erreur
( Err erreur, _ ) ->
Err erreur
( _, Err erreur ) ->
Err erreur
add : Fraction -> Fraction -> Resultat add : Fraction -> Fraction -> Resultat
add a b = add a b =
let let
pgcd = gcd a.den b.den pgcd =
aDenBis = a.den // pgcd gcd a.den b.den
bDenBis = b.den // pgcd
in aDenBis =
frac (a.num*bDenBis + b.num*aDenBis) (a.den*bDenBis) a.den // pgcd
bDenBis =
b.den // pgcd
in
frac (a.num * bDenBis + b.num * aDenBis) (a.den * bDenBis)
neg : Fraction -> Fraction neg : Fraction -> Fraction
neg a = Fraction (-a.num) a.den neg a =
Fraction -a.num a.den
sub : Fraction -> Fraction -> Resultat sub : Fraction -> Fraction -> Resultat
sub a b = add a (neg b) sub a b =
add a (neg b)
mul : Fraction -> Fraction -> Resultat mul : Fraction -> Fraction -> Resultat
mul a b = mul a b =
let let
pgcd = gcd a.num b.den pgcd =
pgcdBis = gcd b.num a.den gcd a.num b.den
aNum = a.num // pgcd
aDen = a.den // pgcdBis pgcdBis =
bNum = b.num // pgcdBis gcd b.num a.den
bDen = b.den // pgcd
in aNum =
frac (aNum*bNum) (aDen*bDen) a.num // pgcd
aDen =
a.den // pgcdBis
bNum =
b.num // pgcdBis
bDen =
b.den // pgcd
in
frac (aNum * bNum) (aDen * bDen)
inv : Fraction -> Resultat inv : Fraction -> Resultat
inv a = inv a =
case a.num of case a.num of
0 -> Err "Division par zéro" 0 ->
_ -> Ok <| Fraction a.den a.num Err "Division par zéro"
_ ->
Ok <| Fraction a.den a.num
div : Fraction -> Fraction -> Resultat div : Fraction -> Fraction -> Resultat
div a b = Result.andThen (mul a) <| inv b div a b =
Result.andThen (mul a) <| inv b
exp : Fraction -> Fraction -> Resultat exp : Fraction -> Fraction -> Resultat
exp a b = exp a b =
let let
sgnDeA = sgnDeA =
if a.num < 0 then -1 else 1 if a.num < 0 then
sgnDeB = -1
if b.num < 0 then -1 else 1
in else
if b.den == 1 && b.num < 0 then 1
frac ((sgnDeA*a.den)^(sgnDeB*b.num)) ((sgnDeA*a.num)^(sgnDeB*b.num))
else if b.den == 1 then sgnDeB =
frac (a.num^b.num) (a.den^b.num) if b.num < 0 then
else -1
Err "Extraction de racine impossible"
else
1
teX a in
= case a.den of if b.den == 1 && b.num < 0 then
1 -> String.fromInt a.num frac ((sgnDeA * a.den) ^ (sgnDeB * b.num)) ((sgnDeA * a.num) ^ (sgnDeB * b.num))
_ ->
if a.num < 0 then else if b.den == 1 then
"-\\frac{" ++ String.fromInt (-a.num) ++ "}{" ++ String.fromInt a.den ++ "}" frac (a.num ^ b.num) (a.den ^ b.num)
else
"\\frac{" ++ String.fromInt a.num ++ "}{" ++ String.fromInt a.den ++ "}" else
Err "Extraction de racine impossible"
raw a = "(" ++ String.fromInt a.num ++ "/" ++ String.fromInt a.den ++ ")"
teX a =
case a.den of
1 ->
String.fromInt a.num
_ ->
if a.num < 0 then
"-\\frac{" ++ String.fromInt -a.num ++ "}{" ++ String.fromInt a.den ++ "}"
else
"\\frac{" ++ String.fromInt a.num ++ "}{" ++ String.fromInt a.den ++ "}"
raw a =
"(" ++ String.fromInt a.num ++ "/" ++ String.fromInt a.den ++ ")"

File diff suppressed because it is too large Load Diff

@ -1,9 +1,9 @@
module ParserMaths exposing (parseMaths, evaluer, evaluerBis, montrerErreurs, expr) module ParserMaths exposing (evaluer, evaluerBis, expr, montrerErreurs, parseMaths)
import Fraction as F exposing (Fraction, Resultat, frac, opp) import Fraction as F exposing (Fraction, Resultat, frac, opp)
import Maybe as M import Maybe as M
import Set
import Parser exposing (..) import Parser exposing (..)
import Set
montrerErreurs : String -> List DeadEnd -> String montrerErreurs : String -> List DeadEnd -> String
@ -11,6 +11,7 @@ montrerErreurs source errs =
case List.head errs of case List.head errs of
Nothing -> Nothing ->
"" ""
Just firstErr -> Just firstErr ->
source source
++ "\n" ++ "\n"
@ -27,16 +28,23 @@ montrerAttendu err =
case err.problem of case err.problem of
ExpectingNumber -> ExpectingNumber ->
"un nombre entier" "un nombre entier"
ExpectingSymbol s -> ExpectingSymbol s ->
"un \"" ++ s ++ "\"" "un \"" ++ s ++ "\""
_ -> _ ->
"une expression" "une expression"
evaluerBis : Expr -> Fraction evaluerBis : Expr -> Fraction
evaluerBis expression = evaluerBis expression =
case evaluer expression of case evaluer expression of
Err _ -> { num = 666, den = 1 } Err _ ->
Ok a -> a { num = 666, den = 1 }
Ok a ->
a
evaluer : Expr -> Resultat evaluer : Expr -> Resultat
evaluer expression = evaluer expression =
@ -68,13 +76,14 @@ evaluer expression =
Poly a_i x -> Poly a_i x ->
Err "Les polynômes ne sont pas encore pris en charge." Err "Les polynômes ne sont pas encore pris en charge."
{-- {--
appliquerAuResultat f a b = appliquerAuResultat f a b =
case (a,b) of case (a,b) of
(Ok aa, Ok bb) -> Ok <| f aa bb (Ok aa, Ok bb) -> Ok <| f aa bb
(Err aa, _) -> Err aa (Err aa, _) -> Err aa
--} --}
{-- {--
type Expr type Expr
= Const Fraction = Const Fraction
@ -92,6 +101,7 @@ type Expr
| Opp Expr | Opp Expr
--} --}
type Expr type Expr
= Add Expr Expr = Add Expr Expr
| Sub Expr Expr | Sub Expr Expr
@ -127,10 +137,13 @@ type Operand
| Operand Operator Expr | Operand Operator Expr
{- {-
En quelque sorte, décurryfie une expression binaire En quelque sorte, décurryfie une expression binaire
binary e_1 (Operand MulOp e_2) == Mul e_1 e_2 binary e_1 (Operand MulOp e_2) == Mul e_1 e_2
-} -}
binary : Expr -> Operand -> Expr binary : Expr -> Operand -> Expr
binary a b = binary a b =
case b of case b of
@ -164,13 +177,16 @@ add =
|= loop [] addHelper |= loop [] addHelper
-- --
foldBinary : Expr -> List Operand -> Expr foldBinary : Expr -> List Operand -> Expr
foldBinary left operands = foldBinary left operands =
List.foldr List.foldr
(\operand expression -> binary expression operand) (\operand expression -> binary expression operand)
left left
operands operands
addHelper : List Operand -> Parser (Step (List Operand) (List Operand)) addHelper : List Operand -> Parser (Step (List Operand) (List Operand))
@ -231,7 +247,8 @@ exp =
primary : Parser Expr primary : Parser Expr
primary = primary =
succeed (\op literal -> succeed
(\op literal ->
case op of case op of
Nothing -> Nothing ->
literal literal
@ -239,16 +256,16 @@ primary =
Just _ -> Just _ ->
Neg literal Neg literal
) )
|= oneOf |= oneOf
[ succeed Just [ succeed Just
|= symbol "-" |= symbol "-"
, succeed Nothing , succeed Nothing
] ]
|= oneOf |= oneOf
[ grouping [ grouping
, poly , poly
, nombre , nombre
] ]
nombre : Parser Expr nombre : Parser Expr
@ -262,6 +279,7 @@ nombre =
, float = Nothing , float = Nothing
} }
poly : Parser Expr poly : Parser Expr
poly = poly =
succeed Poly succeed Poly

@ -1,31 +1,29 @@
module Test exposing (..) module Test exposing (..)
import Browser import Browser
import Html exposing (Html, button, div, text) import Element exposing (..)
import Html.Events exposing (onClick) import Element.Input as Input
import MiniLatex import Html exposing (Html)
--import MiniLatex.Render exposing(MathJaxRenderOption(..))
-- MAIN -- MAIN
main = main =
Browser.sandbox { init = init, update = update, view = view } Browser.sandbox { init = init, update = update, view = view }
texteLaTeX = "Pythagoras says: $a^2 + b^2 = c^2$"
-- MODEL -- MODEL
type alias Model = Int type alias Model =
{ texte : String }
init : Model
init = init =
0 { texte = "" }
@ -33,18 +31,12 @@ init =
type Msg type Msg
= Increment = NouveauTexte String
| Decrement
update : Msg -> Model -> Model update : Msg -> Model -> Model
update msg model = update (NouveauTexte texte) model =
case msg of { texte = texte }
Increment ->
model + 1
Decrement ->
model - 1
@ -53,4 +45,17 @@ update msg model =
view : Model -> Html Msg view : Model -> Html Msg
view model = view model =
MiniLatex.render "" NoDelay texteLaTeX layout [ width fill, height fill ] <|
row []
[ Input.multiline [ height <| maximum 300 fill, clip, scrollbars ]
{ onChange = NouveauTexte
, label = Input.labelAbove [] <| text "Test"
, placeholder =
Just <|
Input.placeholder [] <|
text "Entrer le texte"
, text = String.toUpper model.texte
, spellcheck = False
}
, text model.texte
]

Loading…
Cancel
Save