module Ideas.Encoding.LinkManager
( LinkManager(..)
, dynamicLinks, stateToXML
, staticLinks, linksUp, pathLevel, (</>)
, linkToIndex, linkToExercises, linkToServices, linkToService
, linkToExercise, linkToStrategy, linkToRules, linkToExamples
, linkToDerivations, linkToRule, linkToRandomExample, linkToTestReport
, linkToState, linkToFirsts, linkToApplications, linkToDerivation
, linkToMicrosteps
) where
import Data.Maybe
import Ideas.Common.Library
import Ideas.Encoding.Encoder
import Ideas.Encoding.EncoderXML
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
, isStatic :: Bool
, 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
, 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
dynamicLinks :: String -> LinkManager
dynamicLinks cgiBinary = LinkManager
{ isStatic = False
, urlForRequest = prefix
, urlForCSS = ("http://ideas.cs.uu.nl/css/" ++)
, urlForImage = ("http://ideas.cs.uu.nl/images/" ++)
, 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"
, 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 (simpleOptions (exercise st)) 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]
staticLinks :: LinkManager
staticLinks = LinkManager
{ isStatic = True
, urlForCSS = id
, urlForImage = id
, urlForRequest = ""
,
urlForIndex = "index.html"
, urlForExercises = "exercises.html"
, urlForServices = "services.html"
, urlForService = \srv -> "services" </> idToFilePath srv
, urlForExercise = idToFilePath
, urlForStrategy = idToFilePathWith "-strategy.html"
, urlForRules = idToFilePathWith "-rules.html"
, urlForExamples = idToFilePathWith "-examples.html"
, urlForDerivations = idToFilePathWith "-derivations.html"
, urlForRule = \ex r -> idToFilePathWith ("/" ++ showId r ++ ".html") ex
, urlForTestReport = idToFilePathWith "-testreport.html"
, urlForRandomExample = \_ _ -> ""
, urlForState = const ""
, urlForFirsts = const ""
, urlForApplications = const ""
, urlForDerivation = const ""
, urlForMicrosteps = const ""
}
linksUp :: Int -> LinkManager -> LinkManager
linksUp n lm = lm
{ isStatic = isStatic lm
, urlForIndex = f0 urlForIndex
, urlForExercises = f0 urlForExercises
, urlForServices = f0 urlForServices
, urlForService = f1 urlForService
, urlForExercise = f1 urlForExercise
, urlForStrategy = f1 urlForStrategy
, urlForRules = f1 urlForRules
, urlForExamples = f1 urlForExamples
, urlForDerivations = f1 urlForDerivations
, urlForRule = f2 urlForRule
, urlForRandomExample = f2 urlForRandomExample
, urlForState = f1 urlForState
, urlForFirsts = f1 urlForFirsts
, urlForApplications = f1 urlForApplications
, urlForDerivation = f1 urlForDerivation
, urlForMicrosteps = f1 urlForMicrosteps
}
where
f0 g = pathUp n $ g lm
f1 g = pathUp n . g lm
f2 g x = pathUp n . g lm x
pathUp :: Int -> FilePath -> FilePath
pathUp n file = concat (replicate n "../") ++ file
pathLevel :: FilePath -> Int
pathLevel = length . filter (=='/')
idToFilePath :: HasId a => a -> FilePath
idToFilePath = idToFilePathWith ".html"
idToFilePathWith :: HasId a => String -> a -> FilePath
idToFilePathWith suffix a = foldr (</>) (unqualified a ++ suffix) (qualifiers a)
(</>) :: String -> FilePath -> FilePath
x </> y = x ++ "/" ++ y