{-|
Module      : ErrorHandler
Description : Módulo contendo operações de verificação e tratamento de erros do sistema SIGES.
-}
{-# LANGUAGE OverloadedStrings #-}
module Handlers.ErrorHandler where

import qualified Data.Map as Map
import qualified Data.ByteString.Char8 as BS
import qualified Data.Text as T

import Manager
import Handlers.UserHandler
import Handlers.DataHandler
import TUI.OutputScreens


-- | Dada uma determinada tela do sistema e uma resposta, esta função verifica se a resposta foi adequada àquela tela, retornando, em caso positivo, a tela equivalente à resposta, ou em caso negativo, o ErrorLog com a mensagem identificando qualerro existente na resposta.
validScreen :: Screen -> String -> IO (Either ErrorLog Screen)
validScreen :: Screen -> String -> IO (Either String Screen)
validScreen Screen
screen String
answer
    | String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
answer Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
1 = Either String Screen -> IO (Either String Screen)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String Screen
forall a b. a -> Either a b
Left String
"Por favor, digite apenas um caractere.")
    | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Char
charAnswer Char -> Map Char Screen -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.member` Map Char Screen
allScreens = Either String Screen -> IO (Either String Screen)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String Screen
forall a b. a -> Either a b
Left String
"Por favor, digite apenas uma opções acima.")
    | Bool
otherwise = Either String Screen -> IO (Either String Screen)
forall (m :: * -> *) a. Monad m => a -> m a
return (Screen -> Either String Screen
forall a b. b -> Either a b
Right Screen
correctScreen)
    where charAnswer :: Char
charAnswer = Char -> Char
toUpper (Char -> Char) -> Char -> Char
forall a b. (a -> b) -> a -> b
$ String -> Char
forall a. [a] -> a
head String
answer
          allScreens :: Map Char Screen
allScreens = Screen -> Map Char Screen
forall a. Content a => a -> Map Char Screen
nextScreens Screen
screen
          (Just Screen
correctScreen) = Char -> Map Char Screen -> Maybe Screen
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Char
charAnswer Map Char Screen
allScreens

-- | Dada uma String, esta função verificará se esta String é composta unicamente pelo caractere 'R', respondendo com um valor booleano.
singleCharIsR :: String -> Bool
singleCharIsR :: String -> Bool
singleCharIsR String
str
    | String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
str Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
1 = Bool
False
    | Char -> Char
toUpper (String -> Char
forall a. [a] -> a
head String
str) Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'R' = Bool
True
    | Bool
otherwise = Bool
False

-- | Esta função considerará um e-mail, em String, e decidirá se ele é válido e livre ou se é inválido ou se já está em uso, retornando uma mensagem de erro caso o e-mail não seja válido e livre.
checkNewEmail :: String -> IO (Either ErrorLog String)
checkNewEmail :: String -> IO (Either String String)
checkNewEmail String
emailString = do
    Either String String
checkedEmail <- String -> IO (Either String String)
checkEmail String
emailString
    Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (case Either String String
checkedEmail of
                (Right String
"Retornar") -> Either String String
checkedEmail
                (Left String
"Email inválido. Tente novamente.") -> String -> Either String String
forall a b. a -> Either a b
Left String
"Email inválido. Tente novamente."
                (Left String
notRegistered) -> String -> Either String String
forall a b. b -> Either a b
Right String
emailString
                Either String String
_ -> String -> Either String String
forall a b. a -> Either a b
Left String
"Este e-mail já pertence a uma conta no SIGES. Tente novamente.")

-- | Esta função considerará um e-mail, em String, e decidirá se ele é válido e está cadastrado. Caso não seja válido ou não esteja cadastrado, retornará uma mensagem de erro. Caso a função receba como parâmetro uma String composta apenas da letra R, responderá com a String "Retornar".
checkEmail :: String -> IO (Either ErrorLog String)
checkEmail :: String -> IO (Either String String)
checkEmail String
emailString = do
    if String -> Bool
singleCharIsR String
emailString
        then Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. b -> Either a b
Right String
"Retornar")
        else if Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ByteString -> Bool
isValid (String -> ByteString
BS.pack String
emailString)
            then Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. a -> Either a b
Left String
"Email inválido. Tente novamente.")
            else (do
                Bool
checkedUser <- String -> IO Bool
userExists String
emailString
                if Bool
checkedUser
                    then Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. b -> Either a b
Right String
emailString)
                    else Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. a -> Either a b
Left String
"Email não cadastrado. Tente novamente.")
                )

-- | Esta função considerará uma String determinada e decidirá se esta String pode ser usada como senha neste sistema. Em caso negativo, retornará uma mensagem de erro.
checkNewPass :: String -> IO (Either ErrorLog String)
checkNewPass :: String -> IO (Either String String)
checkNewPass String
passwordString
    | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ValidPasswordPolicy -> Password -> Bool
isValidPassword ValidPasswordPolicy
defaultPasswordPolicy_ Password
password = Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. a -> Either a b
Left String
"A senha deve ter mais de 8 caracteres. Tente novamente.")
    | Bool
otherwise = Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. b -> Either a b
Right String
passwordString)
    where password :: Password
password = Text -> Password
mkPassword (Text -> Password) -> Text -> Password
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
passwordString

-- | Esta função considera um e-mail e uma senha, e decide se a senha está correta (caso em que retorna a própria senha) ou não (Caso em que retorna a mensagem de erro correspondente.)
checkPass :: String -> String -> IO (Either ErrorLog String)
checkPass :: String -> String -> IO (Either String String)
checkPass String
emailString String
passwordString = do
    Bool
possiblePassword <- String -> String -> IO Bool
correctPassword String
emailString String
passwordString
    if Bool
possiblePassword
        then Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. b -> Either a b
Right String
passwordString)
        else Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. a -> Either a b
Left String
"Senha incorreta. Tente novamente.")

-- | Esta função considera uma String e decide se ela pode ser considerada como um nome do usuário (apenas letras e espaços são permitidos). Caso a String contenha um nome válido, o próprio nome será retornado. Caso contrário, uma mensagem de erro será retornada.
checkName :: String -> IO (Either ErrorLog String)
checkName :: String -> IO (Either String String)
checkName String
str = do
    if (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\Char
c -> Char -> Bool
isAlpha Char
c Bool -> Bool -> Bool
|| Char -> Bool
isSpace Char
c) String
str
        then Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. b -> Either a b
Right String
str)
        else Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. a -> Either a b
Left String
"Apenas letras são permitidas. Tente novamente.")

-- | Esta função considera uma String e decide se ela representa corretamente uma resposta de Sim ou Não (S ou N). Caso tenha mais de um caractere ou não seja S ou N, retornará uma mensagem de erro. Caso seja válida, a função retornará um Booleano. (True para S e False para N).
yesOrNo :: String -> IO (Either ErrorLog Bool)
yesOrNo :: String -> IO (Either String Bool)
yesOrNo String
str = do
    let firstChar :: Char
firstChar = Char -> Char
toUpper (Char -> Char) -> Char -> Char
forall a b. (a -> b) -> a -> b
$ String -> Char
forall a. [a] -> a
head String
str
    if String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
str Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
1
        then Either String Bool -> IO (Either String Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String Bool
forall a b. a -> Either a b
Left String
"Resposta inválida (apenas S/N). Tente novamente.")
        else Either String Bool -> IO (Either String Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (case Char
firstChar of
                        Char
'S' -> Bool -> Either String Bool
forall a b. b -> Either a b
Right Bool
True
                        Char
'N' -> Bool -> Either String Bool
forall a b. b -> Either a b
Right Bool
False
                        Char
_ -> String -> Either String Bool
forall a b. a -> Either a b
Left String
"Resposta inválida (apenas S/N). Tente novamente.")

-- | Esta função considera uma Sting e decide se ela equivale ao código de uma das salas cadastradas no sistema (Caso em que retornará uma mensagem de erro). Caso contrário, a função retornará em que retornará o próprio código.
checkNewRoomCode :: String -> IO (Either ErrorLog String)
checkNewRoomCode :: String -> IO (Either String String)
checkNewRoomCode String
codeStr = do
    let codeRoom :: String
codeRoom = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper String
codeStr
    Maybe Room
possibleRoom <- String -> IO (Maybe Room)
getRoom String
codeRoom
    if Maybe Room -> Bool
forall a. Maybe a -> Bool
isJust Maybe Room
possibleRoom
        then Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. a -> Either a b
Left String
"Sala já cadastrada. Tente novamente.")
        else Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. b -> Either a b
Right String
codeRoom)

-- | Esta função considera uma Sting e decide se ela equivale ao código de uma das salas cadastradas no sistema (Caso em que retornará o próprio código). Caso contrário, a função retornará uma mensagem de erro.
checkRoomCode :: String -> IO (Either ErrorLog String)
checkRoomCode :: String -> IO (Either String String)
checkRoomCode String
codeStr = do
    let codeRoom :: String
codeRoom = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper String
codeStr
    Maybe Room
possibleRoom <- String -> IO (Maybe Room)
getRoom String
codeRoom
    if Maybe Room -> Bool
forall a. Maybe a -> Bool
isJust Maybe Room
possibleRoom
        then Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. b -> Either a b
Right String
codeRoom)
        else Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. a -> Either a b
Left String
"Sala não cadastrada. Tente novamente.")

-- | Esta função considera uma String, e decidirá se ela equivale a uma data válida. Em caso positivo, retornará o mesmo na forma de uma lista de inteiros. Caso contrário, retornará uma mensagem de erro equivalente ao problema encontrado.
checkDay :: String -> IO (Either ErrorLog [Int])
checkDay :: String -> IO (Either String [Int])
checkDay String
dayStr
    | String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
dayRemovedWs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
10 = Either String [Int] -> IO (Either String [Int])
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String [Int]
forall a b. a -> Either a b
Left String
"Formato inválido (apenas DD-MM-AAAA). Tente novamente.")
    | Int
day Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
31 Bool -> Bool -> Bool
|| Int
day Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = Either String [Int] -> IO (Either String [Int])
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String [Int]
forall a b. a -> Either a b
Left String
"Formato inválido (apenas DD-MM-AAAA). Tente novamente.")
    | Int
month Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
12 Bool -> Bool -> Bool
|| Int
month Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = Either String [Int] -> IO (Either String [Int])
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String [Int]
forall a b. a -> Either a b
Left String
"Formato inválido (apenas DD-MM-AAAA). Tente novamente.")
    | Bool
otherwise = Either String [Int] -> IO (Either String [Int])
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String [Int] -> IO (Either String [Int]))
-> Either String [Int] -> IO (Either String [Int])
forall a b. (a -> b) -> a -> b
$ [Int] -> Either String [Int]
forall a b. b -> Either a b
Right [Int]
dayList
    where dayRemovedWs :: String
dayRemovedWs = (Char -> String -> String) -> String -> String -> String
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\Char
c String
acc -> if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' ' then Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:String
acc else String
acc) String
"" String
dayStr
          dayList :: [Int]
dayList@[Int
day, Int
month, Int
year] = (String -> Int) -> [String] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map String -> Int
forall a. Read a => String -> a
read ([String] -> [Int]) -> [String] -> [Int]
forall a b. (a -> b) -> a -> b
$ String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
"-" String
dayRemovedWs

-- | Esta função considera uma String e decide se ela equivale a um horário. Em caso positivo, retornará o horário em forma de Lista de inteiros. Caso contrário, retornará a mensagem de erro equivalente ao problema encontrado.
checkTime :: String -> IO (Either ErrorLog [Int])
checkTime :: String -> IO (Either String [Int])
checkTime String
timeStr
    | String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
timeRemovedWs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
5 = Either String [Int] -> IO (Either String [Int])
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String [Int]
forall a b. a -> Either a b
Left String
"Formato inválido (apenas HH:MM). Tente novamente.")
    | Int
hours Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
24 Bool -> Bool -> Bool
|| Int
hours Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Either String [Int] -> IO (Either String [Int])
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String [Int]
forall a b. a -> Either a b
Left String
"Formato inválido (apenas HH:MM). Tente novamente.")
    | Int
minutes Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
60 Bool -> Bool -> Bool
|| Int
minutes Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Either String [Int] -> IO (Either String [Int])
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String [Int]
forall a b. a -> Either a b
Left String
"Formato inválido (apenas HH:MM). Tente novamente.")
    | Bool
otherwise = Either String [Int] -> IO (Either String [Int])
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String [Int] -> IO (Either String [Int]))
-> Either String [Int] -> IO (Either String [Int])
forall a b. (a -> b) -> a -> b
$ [Int] -> Either String [Int]
forall a b. b -> Either a b
Right [Int]
timeList
    where timeRemovedWs :: String
timeRemovedWs = (Char -> String -> String) -> String -> String -> String
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\Char
c String
acc -> if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' ' then Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:String
acc else String
acc) String
"" String
timeStr
          timeList :: [Int]
timeList@[Int
hours, Int
minutes] = (String -> Int) -> [String] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map String -> Int
forall a. Read a => String -> a
read ([String] -> [Int]) -> [String] -> [Int]
forall a b. (a -> b) -> a -> b
$ String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
":" String
timeRemovedWs

-- | Esta função considera uma String e decide se ela pode ser usada como descrição para uma reserva de sala. Em caso positivo, retornará a mesma String. Caso contrário, retornará uma mensagem de erro.
checkDescription :: String -> IO (Either ErrorLog String)
checkDescription :: String -> IO (Either String String)
checkDescription String
str = do
    if (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isPrint String
str
        then Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. b -> Either a b
Right String
str)
        else Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String String
forall a b. a -> Either a b
Left String
"Apenas letras são permitidas. Tente novamente.")

-- | Esta função considera uma String e decide se ela representa uma das categorias no sistema. Caso represente, a função retornará a Categoria desejada, e em caso contrário, retornará uma mensagem de erro.
checkCategory :: String -> IO (Either ErrorLog RoomCategory)
checkCategory :: String -> IO (Either String RoomCategory)
checkCategory String
catStr
    | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
catStr = Either String RoomCategory -> IO (Either String RoomCategory)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RoomCategory -> IO (Either String RoomCategory))
-> Either String RoomCategory -> IO (Either String RoomCategory)
forall a b. (a -> b) -> a -> b
$ String -> Either String RoomCategory
forall a b. a -> Either a b
Left String
"Apenas uma das opções acima. Tente novamente"
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'L' = Either String RoomCategory -> IO (Either String RoomCategory)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RoomCategory -> IO (Either String RoomCategory))
-> Either String RoomCategory -> IO (Either String RoomCategory)
forall a b. (a -> b) -> a -> b
$ RoomCategory -> Either String RoomCategory
forall a b. b -> Either a b
Right RoomCategory
Laboratory
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'A' = Either String RoomCategory -> IO (Either String RoomCategory)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RoomCategory -> IO (Either String RoomCategory))
-> Either String RoomCategory -> IO (Either String RoomCategory)
forall a b. (a -> b) -> a -> b
$ RoomCategory -> Either String RoomCategory
forall a b. b -> Either a b
Right RoomCategory
Auditorium
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'S' = Either String RoomCategory -> IO (Either String RoomCategory)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RoomCategory -> IO (Either String RoomCategory))
-> Either String RoomCategory -> IO (Either String RoomCategory)
forall a b. (a -> b) -> a -> b
$ RoomCategory -> Either String RoomCategory
forall a b. b -> Either a b
Right RoomCategory
Classroom
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'E' = Either String RoomCategory -> IO (Either String RoomCategory)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RoomCategory -> IO (Either String RoomCategory))
-> Either String RoomCategory -> IO (Either String RoomCategory)
forall a b. (a -> b) -> a -> b
$ RoomCategory -> Either String RoomCategory
forall a b. b -> Either a b
Right RoomCategory
Office
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'D' = Either String RoomCategory -> IO (Either String RoomCategory)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RoomCategory -> IO (Either String RoomCategory))
-> Either String RoomCategory -> IO (Either String RoomCategory)
forall a b. (a -> b) -> a -> b
$ RoomCategory -> Either String RoomCategory
forall a b. b -> Either a b
Right RoomCategory
Warehouse
    | Bool
otherwise = Either String RoomCategory -> IO (Either String RoomCategory)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RoomCategory -> IO (Either String RoomCategory))
-> Either String RoomCategory -> IO (Either String RoomCategory)
forall a b. (a -> b) -> a -> b
$ String -> Either String RoomCategory
forall a b. a -> Either a b
Left String
"Apenas uma das opções acima. Tente novamente"
    where c :: Char
c = Char -> Char
toUpper (String -> Char
forall a. [a] -> a
head String
catStr)

-- | Esta função considera uma String e decide se ela contém um valor inteiro entre zero e trezentos, caso no qual retornará o inteiro. Em caso contrário, uma mensagem de erro será retornada.
checkNumber :: String -> IO (Either ErrorLog Int)
checkNumber :: String -> IO (Either String Int)
checkNumber String
numStr
    | Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
300 = Either String Int -> IO (Either String Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String Int -> IO (Either String Int))
-> Either String Int -> IO (Either String Int)
forall a b. (a -> b) -> a -> b
$ Int -> Either String Int
forall a b. b -> Either a b
Right Int
num
    | Bool
otherwise = Either String Int -> IO (Either String Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String Int -> IO (Either String Int))
-> Either String Int -> IO (Either String Int)
forall a b. (a -> b) -> a -> b
$ String -> Either String Int
forall a b. a -> Either a b
Left String
"Valor inválido. Tente novamente"
    where num :: Int
num = String -> Int
forall a. Read a => String -> a
read String
numStr

-- | Esta função considera uma String e decide se ela representa um dos tipos de recursos oferecidos pelas salas do sistema. Caso afirmativo, a função retornará o ResourceKind solicitado. Caso contrário, uma mensagem de erro será retornada.
checkResource :: String -> IO (Either ErrorLog ResourceKind)
checkResource :: String -> IO (Either String ResourceKind)
checkResource String
resStr
    | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
resStr = Either String ResourceKind -> IO (Either String ResourceKind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ResourceKind -> IO (Either String ResourceKind))
-> Either String ResourceKind -> IO (Either String ResourceKind)
forall a b. (a -> b) -> a -> b
$ String -> Either String ResourceKind
forall a b. a -> Either a b
Left String
"Apenas uma das opções acima. Tente novamente"
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'P' = Either String ResourceKind -> IO (Either String ResourceKind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ResourceKind -> IO (Either String ResourceKind))
-> Either String ResourceKind -> IO (Either String ResourceKind)
forall a b. (a -> b) -> a -> b
$ ResourceKind -> Either String ResourceKind
forall a b. b -> Either a b
Right ResourceKind
Projector
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'M' = Either String ResourceKind -> IO (Either String ResourceKind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ResourceKind -> IO (Either String ResourceKind))
-> Either String ResourceKind -> IO (Either String ResourceKind)
forall a b. (a -> b) -> a -> b
$ ResourceKind -> Either String ResourceKind
forall a b. b -> Either a b
Right ResourceKind
Microscope
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'B' = Either String ResourceKind -> IO (Either String ResourceKind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ResourceKind -> IO (Either String ResourceKind))
-> Either String ResourceKind -> IO (Either String ResourceKind)
forall a b. (a -> b) -> a -> b
$ ResourceKind -> Either String ResourceKind
forall a b. b -> Either a b
Right ResourceKind
Desk
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'C' = Either String ResourceKind -> IO (Either String ResourceKind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ResourceKind -> IO (Either String ResourceKind))
-> Either String ResourceKind -> IO (Either String ResourceKind)
forall a b. (a -> b) -> a -> b
$ ResourceKind -> Either String ResourceKind
forall a b. b -> Either a b
Right ResourceKind
Computer
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'Q' = Either String ResourceKind -> IO (Either String ResourceKind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ResourceKind -> IO (Either String ResourceKind))
-> Either String ResourceKind -> IO (Either String ResourceKind)
forall a b. (a -> b) -> a -> b
$ ResourceKind -> Either String ResourceKind
forall a b. b -> Either a b
Right ResourceKind
Board
    | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'A' = Either String ResourceKind -> IO (Either String ResourceKind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ResourceKind -> IO (Either String ResourceKind))
-> Either String ResourceKind -> IO (Either String ResourceKind)
forall a b. (a -> b) -> a -> b
$ ResourceKind -> Either String ResourceKind
forall a b. b -> Either a b
Right ResourceKind
AirConditioner
    | Bool
otherwise = Either String ResourceKind -> IO (Either String ResourceKind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String ResourceKind -> IO (Either String ResourceKind))
-> Either String ResourceKind -> IO (Either String ResourceKind)
forall a b. (a -> b) -> a -> b
$ String -> Either String ResourceKind
forall a b. a -> Either a b
Left String
"Apenas uma das opções acima. Tente novamente"
    where c :: Char
c = Char -> Char
toUpper (String -> Char
forall a. [a] -> a
head String
resStr)

-- | Esta função considera uma String e decide se ela equivale a uma das opções (1, 2, 3, ou 4), caso em que retorna a opção como um inteiro. Em caso contrário, retornará uma mensagem de erro.
checkFilter :: String -> IO (Either ErrorLog Int)
checkFilter :: String -> IO (Either String Int)
checkFilter String
filterStr = do
    let filterNum :: Int
filterNum = String -> Int
forall a. Read a => String -> a
read String
filterStr
    if Int
filterNum Int -> [Int] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int
1,Int
2,Int
3,Int
4]
        then Either String Int -> IO (Either String Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String Int -> IO (Either String Int))
-> Either String Int -> IO (Either String Int)
forall a b. (a -> b) -> a -> b
$ Int -> Either String Int
forall a b. b -> Either a b
Right Int
filterNum
        else Either String Int -> IO (Either String Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String Int -> IO (Either String Int))
-> Either String Int -> IO (Either String Int)
forall a b. (a -> b) -> a -> b
$ String -> Either String Int
forall a b. a -> Either a b
Left String
"Valor inválido. Tente novamente"