{-# LANGUAGE OverloadedStrings #-}

-- | This module establishes algorithmic strategies to be used throughout the course.
--
-- Currently, the only use for these strategies consists in evaluating student solutions to translation exercises.
-- The process is as follows:
--
-- 1. First, both the student's response and the model response are normalized using a configurable sentence canonicalizer.
-- 2. Then, the normalized responses are compared using a configurable sentence comparer.
-- 3. If they match, the student's solution is considered correct.
module Study.Courses.English.Grammar.Introduction.Strategies  where

import Core
import Language.Lojban.Core
import Language.Lojban.Canonicalization (extendedSentenceCanonicalizer)
import qualified Data.Text as T

-- | Default sentence comparer throughout the course.
--
-- Decides whether two sentences are equivalent taking into account the following allowances:
--
-- * The descriptors "lo" and "le" are interchangeable.
-- * The generic abstractor "su'u" is exchangeable with the more specific abstractors "nu", "du'u" and "ka".
-- * Tenses are optional, and may be missing from one or both of the sentences (however, if tenses are specified in both sentences, they must match).
--
--     * TODO: this still needs to be implemented
--
-- * Association words ("pe", "ne", "po" and "po'e") are interchangeable.
-- * The quote delimiters "lu\/li'u" and "lo'u/le'u" are interchangeable.
--
--     * Conveniently, it is nonetheless enforced that "lu\/li'u" must only be used around grammatical text, as otherwise the canonicalization fails (due to a parsing failure), and this yields a "mismatch" verdict.
sentenceComparer :: SentenceComparer
sentenceComparer :: SentenceComparer
sentenceComparer Text
x Text
y = ([Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
ys) Bool -> Bool -> Bool
&& (((Text, Text) -> Bool) -> [(Text, Text)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Text, Text) -> Bool
wordComparer ([(Text, Text)] -> Bool) -> [(Text, Text)] -> Bool
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text] -> [(Text, Text)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Text]
xs [Text]
ys) where
    xs :: [Text]
xs = Text -> [Text]
T.words Text
x
    ys :: [Text]
ys = Text -> [Text]
T.words Text
y
    isAssociationWord :: T.Text -> Bool
    isAssociationWord :: Text -> Bool
isAssociationWord Text
x = Text
x Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ Text
"pe", Text
"ne", Text
"po", Text
"po'e" ]
    isNonNameGadri :: a -> Bool
isNonNameGadri a
x = a
x a -> [a] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ a
"lo", a
"le", a
"loi", a
"lei", a
"lo'e", a
"le'e" ]
    wordComparer :: (T.Text, T.Text) -> Bool
    wordComparer :: (Text, Text) -> Bool
wordComparer (Text
x, Text
y) = (SentenceComparer
forall {a}. (Eq a, IsString a) => a -> a -> Bool
wordComparer' Text
x Text
y) Bool -> Bool -> Bool
|| (SentenceComparer
forall {a}. (Eq a, IsString a) => a -> a -> Bool
wordComparer' Text
y Text
x) Bool -> Bool -> Bool
|| (Text -> Bool
isAssociationWord Text
x Bool -> Bool -> Bool
&& Text -> Bool
isAssociationWord Text
y) Bool -> Bool -> Bool
|| (Text -> Bool
forall {a}. (Eq a, IsString a) => a -> Bool
isNonNameGadri Text
x Bool -> Bool -> Bool
&& Text -> Bool
forall {a}. (Eq a, IsString a) => a -> Bool
isNonNameGadri Text
y)
    wordComparer' :: a -> a -> Bool
wordComparer' a
"lu" a
"lo'u" = Bool
True
    wordComparer' a
"li'u" a
"le'u" = Bool
True
    wordComparer' a
"nu" a
"su'u" = Bool
True
    wordComparer' a
"du'u" a
"su'u" = Bool
True
    wordComparer' a
"ka" a
"su'u" = Bool
True
    wordComparer' a
x a
y = a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y

-- | Default sentence canonicalizer throughout the course.
sentenceCanonicalizer :: SentenceCanonicalizer
sentenceCanonicalizer :: SentenceCanonicalizer
sentenceCanonicalizer = SentenceCanonicalizer
extendedSentenceCanonicalizer