{-# LANGUAGE RankNTypes #-}
module Ideas.Encoding.LinkManager
( LinkManager(..), makeLinkManager
, stateToXML
, linkToIndex, linkToExercises, linkToServices, linkToService
, linkToExercise, linkToStrategy, linkToRules, linkToExamples
, linkToDerivations, linkToRule, linkToRandomExample, linkToTestReport
, linkToState, linkToFirsts, linkToApplications, linkToDerivation
, linkToMicrosteps
, escapeInURL
) where
import Data.Maybe
import Ideas.Common.Library
import Ideas.Encoding.Encoder
import Ideas.Encoding.EncoderXML
import Ideas.Encoding.Options
import Ideas.Service.State
import Ideas.Service.Types
import Ideas.Text.HTML
import Ideas.Text.XML
data LinkManager = LinkManager
{ urlForCSS :: String -> String
, urlForImage :: String -> String
, urlForRequest :: String
, urlForIndex :: String
, urlForExercises :: String
, urlForServices :: String
, urlForService :: Service -> String
, urlForExercise :: forall a . Exercise a -> String
, urlForStrategy :: forall a . Exercise a -> String
, urlForRules :: forall a . Exercise a -> String
, urlForConstraints :: forall a . Exercise a -> String
, urlForExamples :: forall a . Exercise a -> String
, urlForDerivations :: forall a . Exercise a -> String
, urlForRule :: forall a . Exercise a -> Rule (Context a) -> String
, urlForTestReport :: forall a . Exercise a -> String
, urlForRandomExample :: forall a . Exercise a -> Difficulty -> String
, urlForState :: forall a . State a -> String
, urlForFirsts :: forall a . State a -> String
, urlForApplications :: forall a . State a -> String
, urlForDerivation :: forall a . State a -> String
, urlForMicrosteps :: forall a . State a -> String
}
linkToIndex :: LinkManager -> HTMLBuilder -> HTMLBuilder
linkToIndex = linkWith urlForIndex
linkToExercises :: LinkManager -> HTMLBuilder -> HTMLBuilder
linkToExercises = linkWith urlForExercises
linkToServices :: LinkManager -> HTMLBuilder -> HTMLBuilder
linkToServices = linkWith urlForServices
linkToService :: LinkManager -> Service -> HTMLBuilder -> HTMLBuilder
linkToService = linkWith . urlForService
linkToExercise :: LinkManager -> Exercise a -> HTMLBuilder -> HTMLBuilder
linkToExercise = linkWith . urlForExercise
linkToStrategy :: LinkManager -> Exercise a -> HTMLBuilder -> HTMLBuilder
linkToStrategy = linkWith . urlForStrategy
linkToRules :: LinkManager -> Exercise a -> HTMLBuilder -> HTMLBuilder
linkToRules = linkWith . urlForRules
linkToExamples :: LinkManager -> Exercise a -> HTMLBuilder -> HTMLBuilder
linkToExamples = linkWith . urlForExamples
linkToDerivations :: LinkManager -> Exercise a -> HTMLBuilder -> HTMLBuilder
linkToDerivations = linkWith . urlForDerivations
linkToRule :: LinkManager -> Exercise a -> Rule (Context a) -> HTMLBuilder -> HTMLBuilder
linkToRule lm = linkWith . urlForRule lm
linkToTestReport :: LinkManager -> Exercise a -> HTMLBuilder -> HTMLBuilder
linkToTestReport = linkWith . urlForTestReport
linkToRandomExample :: LinkManager -> Exercise a -> Difficulty -> HTMLBuilder -> HTMLBuilder
linkToRandomExample lm = linkWith . urlForRandomExample lm
linkToState :: LinkManager -> State a -> HTMLBuilder -> HTMLBuilder
linkToState = linkWith . urlForState
linkToFirsts :: LinkManager -> State a -> HTMLBuilder -> HTMLBuilder
linkToFirsts = linkWith . urlForFirsts
linkToMicrosteps :: LinkManager -> State a -> HTMLBuilder -> HTMLBuilder
linkToMicrosteps = linkWith . urlForMicrosteps
linkToApplications :: LinkManager -> State a -> HTMLBuilder -> HTMLBuilder
linkToApplications = linkWith . urlForApplications
linkToDerivation :: LinkManager -> State a -> HTMLBuilder -> HTMLBuilder
linkToDerivation = linkWith . urlForDerivation
makeLinkManager :: String -> String -> LinkManager
makeLinkManager base cgiBinary = LinkManager
{ urlForRequest = prefix
, urlForCSS = \s -> base ++ "css/" ++ s
, urlForImage = \s -> base ++ "images/" ++ s
, urlForIndex = url $ simpleRequest "index"
, urlForExercises = url $ simpleRequest "exerciselist"
, urlForServices = url $ simpleRequest "servicelist"
, urlForService =
url . makeRequest "serviceinfo" . tag "location" . text
, urlForExercise = url . exerciseRequest "exerciseinfo"
, urlForStrategy = url . exerciseRequest "strategyinfo"
, urlForRules = url . exerciseRequest "rulelist"
, urlForConstraints = url . exerciseRequest "constraintlist"
, urlForTestReport = url . exerciseRequest "testreport"
, urlForExamples = url . exerciseRequest "examples"
, urlForDerivations = url . exerciseRequest "examplederivations"
, urlForRule = \ex r ->
url $ exerciseRequestWith "ruleinfo" ex $
tag "ruleid" $ text r
, urlForRandomExample = \ex d ->
url $ exerciseRequestWith "generate" ex $
"difficulty" .=. show d
, urlForState = url . stateRequest "stateinfo"
, urlForFirsts = url . stateRequest "allfirsts"
, urlForApplications = url . stateRequest "allapplications"
, urlForDerivation = url . stateRequest "derivation"
, urlForMicrosteps = url . stateRequest "microsteps"
}
where
prefix = cgiBinary ++ "?input="
url req = prefix ++ compactXML req
simpleRequest :: String -> XML
simpleRequest s = makeRequest s mempty
makeRequest :: String -> XMLBuilder -> XML
makeRequest s rest = makeXML "request" $
("service" .=. s) <>
("encoding" .=. "html") <>
rest
exerciseRequest :: String -> Exercise a -> XML
exerciseRequest s ex = makeRequest s ("exerciseid" .=. showId ex)
exerciseRequestWith :: String -> Exercise a -> XMLBuilder -> XML
exerciseRequestWith s ex rest =
makeRequest s (("exerciseid" .=. showId ex) <> rest)
stateRequest :: String -> State a -> XML
stateRequest s state =
exerciseRequestWith s (exercise state) (stateToXML state)
stateToXML :: State a -> XMLBuilder
stateToXML st = fromMaybe (error "LinkManager: Invalid state") $
run encodeState (exercise st) optionHtml st
linkWith :: (a -> String) -> a -> HTMLBuilder -> HTMLBuilder
linkWith f = link . escapeInURL . f
escapeInURL :: String -> String
escapeInURL = concatMap f
where
f '+' = "%2B"
f '>' = "%3E"
f '&' = "%26"
f '%' = "%25"
f '#' = "%23"
f ';' = "%3B"
f c = [c]