Commit 4839e2a96ce040c7d887d1c7feb30bd9aad713c9

  • avatar
  • Ville Tirronen <ville.tirronen @j…u.fi> (Committer)
  • Mon Aug 20 15:58:10 EEST 2018
  • avatar
  • Ville Tirronen <ville.tirronen @j…u.fi> (Author)
  • Mon Aug 20 15:58:10 EEST 2018
Type-gui, WIP
DerivationChecker/Auxiliaries/src/DCElmGen.hs
(11 / 1)
  
1212import Reason
1313import Explain
1414import SubLanguage
15import qualified Typing
1516import DerivationChecker.API
1617import System.Environment
1718import Data.Text (Text)
2828 , DefineElm (Proxy :: Proxy (Goal Text))
2929 , DefineElm (Proxy :: Proxy (ExplRec))
3030
31 , DefineElm (Proxy :: Proxy Addr)
31 , DefineElm (Proxy :: Proxy Addr) -- For sending concrete, labeled asts over network
3232 , DefineElm (Proxy :: Proxy Part)
3333 , DefineElm (Proxy :: Proxy SerializedFragment)
34
35 , DefineElm (Proxy :: Proxy (TypeElmFlags))
36 , DefineElm (Proxy :: Proxy (Typing.ClientRequest))
37 , DefineElm (Proxy :: Proxy (Typing.ServerReply))
38 , DefineElm (Proxy :: Proxy (Typing.Constraint String))
39 , DefineElm (Proxy :: Proxy (Typing.Target))
40 , DefineElm (Proxy :: Proxy (Typing.SerializedTypeAnnotation String))
41 , DefineElm (Proxy :: Proxy (Typing.DeductionAction String))
42 , DefineElm (Proxy :: Proxy (Typing.TypeDeductionState0))
3443 ]
DerivationChecker/DCService/DCService.cabal
(1 / 1)
  
2121 , http-client
2222 , http-client-tls
2323 , containers
24 , DCServiceAPI
24 , DCServiceAPI , exceptions
2525
2626--
2727--executable Reconstruct
DerivationChecker/DCService/src/Service.hs
(125 / 61)
  
11{-#LANGUAGE OverloadedStrings#-}
22{-#LANGUAGE PartialTypeSignatures#-}
33{-#LANGUAGE DeriveGeneric#-}
4{-#LANGUAGE FlexibleContexts#-}
45{-#GHC_OPTIONS -fno-warn-partial-type-signatures#-}
56module Main where
67import SubLanguage
78import Expr
9import qualified Typing
10import qualified Typing.Rules as Typing
811import DerivationChecker.API
12import Control.Applicative
13import Control.Monad.Catch
914import Servant
1015import Servant.API
1116import Servant.Utils.StaticFiles
17import Control.Exception (SomeException(..), catch)
1218import Servant.Client
1319import qualified Data.Text as T
1420import qualified Data.Text.Lazy as LT
21import qualified Data.Text.Lazy.Encoding as LT
1522import Data.Text (Text)
1623import Network.Wai.Handler.Warp (run)
1724import Data.Proxy
5959
6060
6161server :: HintDB -> BBStore -> Conf -> Server DCAPI
62server hdb blackboard conf = serveDirectoryEmbedded StaticContent.statics:<|> serveCheck :<|> serveTasks :<|> serveHint
63 where
64 serveHint user expr = do
65 liftIO $ writeHintLog "dc_logs/" (case user of
66 LoginManager.Types.Ok u -> Just u
67 LoginManager.Types.Failure -> Nothing)
68 expr
69 case parseEasy expr of
70 Left _ -> return "You have a parse error. Check things like parentheses, indentation etc."
71 Right se -> do
72 case getHint hdb se of
73 Nothing -> return "I can't think of anything... Try adding some parentheses?"
74 Just h -> return h
62server hdb blackboard conf =
63 (-- (serveDirectoryEmbedded StaticContent.statics) (
64 serveDirectoryWebApp "elms/")
65 :<|> serveCheck
66 :<|> serveTypeCheck
67 :<|> serveTypeInitial
68 :<|> serveTasks
69 :<|> serveHint
70 where
71 serveHint user expr = do
72 liftIO $ writeHintLog
73 "dc_logs/"
74 (case user of
75 LoginManager.Types.Ok u -> Just u
76 LoginManager.Types.Failure -> Nothing
77 )
78 expr
79 case parseEasy expr of
80 Left _ ->
81 return
82 "You have a parse error. Check things like parentheses, indentation etc."
83 Right se -> do
84 case getHint hdb se of
85 Nothing ->
86 return "I can't think of anything... Try adding some parentheses?"
87 Just h -> return h
7588
76 serveTasks user taskName = do
77 tf <- liftIO $ Dhall.detailed $ Dhall.input Dhall.auto (tasksAt conf<>"/"<>taskName)
78 pure (taskPage (toElm tf))
89 serveTasks user taskName = do
90 -- This probably needs to change to accomodate two different types of tasks.
91 -- Api can remain the same, but Dhall input will not type check.
92 let fn = tasksAt conf <> "/" <> taskName
93 tf <-
94 liftIO
95 $ Dhall.detailed
96 $ (Left <$> Dhall.input Dhall.auto fn)
97 `Control.Monad.Catch.catch` (\(SomeException _) -> Right <$> Dhall.input Dhall.auto fn)
98 case tf of
99 Left derivation -> pure (taskPage (toElm derivation))
100 Right typing -> liftIO (print (Aeson.encode (typingToElm typing))) >> pure (typingTaskPage (typingToElm typing))
79101
80 serveCheck user taskName step@(Check l r) = do
81 tf <- liftIO . Dhall.detailed . Dhall.input Dhall.auto $ (tasksAt conf<>"/"<> taskName)
82 let (reason,expl) = case loadAll tf l r of
83 Left err -> (GeneralErrorStep err,explain (GeneralErrorStep err))
84 Right loaded -> resolve loaded
85 case user of
86 Failure -> do
87 liftIO $ writeLog "dc_logs" =<< stepLog step reason taskName Nothing
88 return $ addHint "You haven't logged in! Your exercise can't be saved" expl
89 LoginManager.Types.Ok u -> liftIO $  do
90 writeLog "dc_logs" =<< stepLog step reason taskName (Just u)
91 when (isDone expl) $
92 bbAdd u taskName blackboard
93 return expl
94 where
95 loadAll :: TaskFlags -> String -> String -> Either (ErrorMsg String) _
96 loadAll tf l r = do
97 l' <- parseEasy l
98 r' <- parseEasy r
99 fns <- traverse (parseEasyFun . T.unpack) (functions tf)
100 hresolver <- loadHints (hints tf)
101 taskGoal <- loadGoal (goal tf)
102 let resolver = flattenReasons (treeRes (resNamed fns)) <> totalResolver
103 return (l',r',resolver,hresolver,taskGoal)
102 serveTypeCheck user taskName request = do
103 response <- case Typing.serverReply Typing.allRules request of
104 Left e -> throwError err400
105 { errBody = LT.encodeUtf8 $ Typing.prettyPrintTypeConversionError e
106 }
107 Right resp -> pure resp
108 case user of
109 Failure -> do
110 liftIO
111 $ writeTypeLog "dc_logs"
112 =<< typeLog request response taskName Nothing
113 return $ Typing.addHint
114 "You haven't logged in! Your exercise can't be saved"
115 response
116 LoginManager.Types.Ok u -> liftIO $ do
117 writeTypeLog "dc_logs" =<< typeLog request response taskName (Just u)
118 when (undefined) {-isComplete expl-}
119 $ bbAdd u taskName blackboard
120 return response
104121
105 resolve :: _ -> (Reason String, Explanation)
106 resolve (l',r',resolver,hresolver,taskGoal) = -- either (\x -> let c = GeneralErrorStep x in (c,explain mempty c)) id $ do
107 let resolution = fromMaybe (GeneralErrorStep CantResolve)
108 $ resolveChngs resolver l' r'
109 explanation =
110 assignCompletionStatus resolution taskGoal r'
111 . assignHints hresolver resolution l' r'
112 . explain
113 . fmap pr
114 $ resolution
122 serveTypeInitial user taskName = do
123 let fn = tasksAt conf <> "/" <> taskName
124 tf <-
125 liftIO $ Dhall.detailed $ Dhall.input Dhall.auto fn
126 pure $ Typing.initialServerReply (T.unpack $ t_expression tf)
115127
116 in (fmap pr resolution,explanation)
117
118 assignHints :: [(Reason SimpleExpr -> ResolverC SimpleExpr String)] -> Reason SimpleExpr -> SimpleExpr -> SimpleExpr
119 -> _
120 assignHints hintResolvers resolution l r =
121 let hintValues = catMaybes [fmap LT.pack <$> h | hint <- hintResolvers
122 ,let h = resolveChngs (treeRes (hint resolution)) l r]
123 in addHints (mconcat hintValues)
128 serveCheck user taskName step@(Check l r) = do
129 tf <-
130 liftIO
131 . Dhall.detailed
132 . Dhall.input Dhall.auto
133 $ (tasksAt conf <> "/" <> taskName)
134 let (reason, expl) = case loadAll tf l r of
135 Left err -> (GeneralErrorStep err, explain (GeneralErrorStep err))
136 Right loaded -> resolve loaded
137 case user of
138 Failure -> do
139 liftIO $ writeLog "dc_logs" =<< stepLog step reason taskName Nothing
140 return
141 $ addHint "You haven't logged in! Your exercise can't be saved" expl
142 LoginManager.Types.Ok u -> liftIO $ do
143 writeLog "dc_logs" =<< stepLog step reason taskName (Just u)
144 when (isDone expl) $ bbAdd u taskName blackboard
145 return expl
146 where
147 loadAll :: TaskFlags -> String -> String -> Either (ErrorMsg String) _
148 loadAll tf l r = do
149 l' <- parseEasy l
150 r' <- parseEasy r
151 fns <- traverse (parseEasyFun . T.unpack) (functions tf)
152 hresolver <- loadHints (hints tf)
153 taskGoal <- loadGoal (goal tf)
154 let resolver = flattenReasons (treeRes (resNamed fns)) <> totalResolver
155 return (l', r', resolver, hresolver, taskGoal)
124156
125 assignCompletionStatus r goal er
126 | isCorrect r, goal r er = setComplete
127 assignCompletionStatus _ _ _ = id
157 resolve :: _ -> (Reason String, Explanation)
158 resolve (l', r', resolver, hresolver, taskGoal) = -- either (\x -> let c = GeneralErrorStep x in (c,explain mempty c)) id $ do
159 let resolution = fromMaybe (GeneralErrorStep CantResolve)
160 $ resolveChngs resolver l' r'
161 explanation =
162 assignCompletionStatus resolution taskGoal r'
163 . assignHints hresolver resolution l' r'
164 . explain
165 . fmap pr
166 $ resolution
167 in (fmap pr resolution, explanation)
168
169 assignHints
170 :: [(Reason SimpleExpr -> ResolverC SimpleExpr String)]
171 -> Reason SimpleExpr
172 -> SimpleExpr
173 -> SimpleExpr
174 -> (Explanation -> Explanation)
175 assignHints hintResolvers resolution l r =
176 let hintValues = catMaybes
177 [ fmap LT.pack <$> h
178 | hint <- hintResolvers
179 , let h = resolveChngs (treeRes (hint resolution)) l r
180 ]
181 in addHints (mconcat hintValues)
182
183 assignCompletionStatus r goal er | isCorrect r, goal r er = setComplete
184 assignCompletionStatus _ _ _ = id
128185
129186
130187
DerivationChecker/DCService/src/StaticContent.hs
(2 / 0)
  
11{-#LANGUAGE TemplateHaskell#-}
2
23module StaticContent where
34import qualified Data.ByteString as BS
45
99statics =  [
1010 ("TestPage.html" , $(embedFile "../elms/TestPage.html") )
1111 , ("gui.js" , $(embedFile "../elms/gui.js" ) )
12 -- , ("typeGUI.js" , $(embedFile "../elms/typeGUI.js" ) )
1213 , ("style.css" , $(embedFile "../elms/style.css" ) )
1314 ]
DerivationChecker/DCService/src/TaskPage.hs
(11 / 3)
  
66import Data.Text.Lazy.Encoding (decodeUtf8)
77import Data.Monoid
88import Data.Aeson
9import DerivationChecker.API (ElmFlags)
9import DerivationChecker.API (ElmFlags,TypeElmFlags)
1010
1111
1212encodeToText :: ToJSON a => a -> Text
1313encodeToText = toStrict . decodeUtf8 . encode
1414
15typingTaskPage :: TypeElmFlags -> Html ()
16typingTaskPage = taskPageGen "Typing"
17
18
1519taskPage :: ElmFlags -> Html ()
16taskPage elmFlags = html_ $ do
20taskPage = taskPageGen "Main"
21
22taskPageGen :: ToJSON flags => Text -> flags -> Html ()
23taskPageGen elmMain elmFlags = html_ $ do
1724 head_ $ do
1825 meta_ [charset_ "UTF_8"]
1926 link_ [rel_ "stylesheet", href_ "../../static/style.css"]
3030 div_ [id_ "main"] mempty
3131 script_ [type_ "text/javascript",src_ "/new-resources/Login.js"] (return () :: Html ())
3232 script_ [type_ "text/javascript",src_ "../../static/gui.js"] (return () :: Html ())
33 script_ [type_ "text/javascript",src_ "../../static/typeGUI.js"] (return () :: Html ())
3334 script_ $
3435 " var node = document.getElementById('LoginComponent');\n\
3536 \ var app = Elm.StandaloneLogin.embed(node,{loginManager:\"/LoginManager\"});\n\
3939 \ }); "
4040 script_ $
4141 ("var node = document.getElementById('main');\n\
42 \var app = Elm.Main.embed(node,"<>encodeToText elmFlags<>");\n\
42 \var app = Elm."<>elmMain<>".embed(node,"<>encodeToText elmFlags<>");\n\
4343 \" :: Text)
DerivationChecker/DCServiceAPI/src/DerivationChecker/API.hs
(33 / 1)
  
1313import GHC.Generics(Generic)
1414import Elm.Derive
1515import qualified Data.Aeson.Types as A
16import qualified Data.Aeson as A
1617import Servant.API
1718import Servant.HTML.Lucid
1819import Lucid (Html)
2828import qualified Dhall.Core as Dhall
2929import Data.Proxy
3030import LoginManager.Route
31import qualified Typing
3132
3233
3334data CheckStep = Check String String deriving (Generic,Eq,Show)
3435
36data TypeTaskFlags
37 = TTF {t_question :: Text
38 ,t_expression :: Text
39 } deriving (Generic,Eq,Show)
3540
3641data TaskFlags
3742 = TF {question :: Text
4545 ,hints :: [Hint Text]
4646 ,goal :: Goal Text} deriving (Generic,Eq,Show)
4747
48data TypeElmFlags
49 = TEF {typing_question :: Text
50 ,difficulty::Int
51 } deriving (Generic,Eq,Show)
52--instance A.ToJSON TypeElmFlags
53
4854data ElmFlags
4955 = EF {_question :: Text
5056 ,_startingExpression :: Text
5959toElm :: TaskFlags -> ElmFlags
6060toElm tf = EF (question tf) (startingExpression tf)
6161
62typingToElm :: TypeTaskFlags -> TypeElmFlags
63typingToElm tf = TEF (t_question tf) 0
64
6265data Goal a = Rule {rulename :: Text}
6366 | Expression {e :: a}
6467 | Freeform
7373 ,hint::Text} deriving (Generic,Eq,Show,Traversable,Functor,Foldable)
7474
7575instance Dhall.Interpret TaskFlags where
76instance Dhall.Interpret TypeTaskFlags where
7677instance Dhall.Interpret a => Dhall.Interpret (Hint a) where
7778instance Dhall.Interpret a => Dhall.Interpret (Goal a) where
7879
9292deriveBoth defaultOptions ''Goal
9393
9494-- The type handling precursor
95deriveBoth defaultOptions ''TypeElmFlags
96deriveBoth defaultOptions ''Typing.ServerReply
97deriveBoth defaultOptions ''Typing.ClientRequest
98deriveBoth defaultOptions ''Typing.Constraint
99deriveBoth defaultOptions ''Typing.Target
100deriveBoth defaultOptions ''Typing.SerializedTypeAnnotation
101deriveBoth defaultOptions ''Typing.DeductionAction
102deriveBoth defaultOptions ''Typing.TypeDeductionState0
95103deriveBoth defaultOptions ''Addr
96104deriveBoth defaultOptions ''Part
97105deriveBoth defaultOptions ''SerializedFragment
98106
99type DCAPI = "static" :> Raw
107type DCAPI
108 = "static" :> Raw
109
100110 :<|> JYSes :> "tasks" :> Capture "taskname" Text :> "check" :> ReqBody '[JSON] CheckStep :> Post '[JSON] Explanation
111
112 :<|> JYSes :> "tasks" :> Capture "taskname" Text :> "check_type" :> ReqBody '[JSON] Typing.ClientRequest
113 :> Post '[JSON] Typing.ServerReply
114 :<|> JYSes :> "tasks" :> Capture "taskname" Text :> "initial" :> Get '[JSON] Typing.ServerReply
115
101116 :<|> JYSes :> "tasks" :> Capture "taskname" Text :> "page":> Get '[HTML] (Html ())
117
102118 :<|> JYSes :> "hint" :> ReqBody '[JSON] String :> Post '[JSON] Text
103119 -- Should check be a separate service? Might be useful to split that off at some point
DerivationChecker/DCServiceAPI/src/DerivationChecker/LogFile.hs
(28 / 0)
  
1414import Data.ByteString.Lazy as LBS
1515import Control.Exception
1616import DerivationChecker.API
17import qualified Typing
1718
1819data StepLog =
1920 SL {step :: CheckStep
2323 ,loggedAt :: UTCTime
2424 ,muser :: Maybe Text} deriving (Eq,Generic,Show)
2525
26data TypeLog =
27 TL {clientR :: Typing.ClientRequest
28 ,serverReply :: Typing.ServerReply
29 ,tl_task :: Text
30 ,tl_loggedAt :: UTCTime
31 ,tl_muser :: Maybe Text} deriving (Eq,Generic,Show)
32
2633instance Aeson.ToJSON StepLog
2734instance Aeson.FromJSON StepLog
35instance Aeson.ToJSON TypeLog
36instance Aeson.FromJSON TypeLog
2837
2938data HintLog =
3039 HL {hmuser :: Maybe Text
5858stepLog s r t mu = do -- Assumes that taskname is a valid filename. TODO: Do not assume
5959 loggedAt <- getCurrentTime
6060 return $ SL s r t loggedAt mu
61
62typeLog s r t mu = do -- Assumes that taskname is a valid filename. TODO: Still don't assume
63 loggedAt <- getCurrentTime
64 return $ TL s r t loggedAt mu
65
66writeTypeLog :: FilePath -> TypeLog -> IO ()
67writeTypeLog dir sl =
68 let file = dir
69 <> "/" <> (T.unpack (tl_task sl))
70 <> "." <> (if Typing.canProceed (serverReply sl)
71 then "CORRECT"
72 else "WRONG")
73 <> "." <> formatTime defaultTimeLocale "%Y-%m-%d-%H-%M-%S" (tl_loggedAt sl)
74 <> "." <> maybe "anonymous" T.unpack (tl_muser sl)
75 <> ".json"
76 in do
77 createDirectoryIfMissing True dir
78 LBS.writeFile file (Aeson.encode sl)
6179
6280writeLog :: FilePath -> StepLog -> IO ()
6381writeLog dir sl =
DerivationChecker/elms/TypeGUI.elm
(274 / 0)
  
1-- Read more about this program in the official Elm guide:
2-- https://guide.elm-lang.org/architecture/effects/http.html
3
4
5module Typing exposing (..)
6
7import Html exposing (..)
8import Html.Attributes exposing (..)
9import Html.Events exposing (..)
10import Http
11import Json.Decode as Decode
12import Json.Encode as Encode
13import Generated.Types as T
14import String
15import Dict
16import Array exposing (Array)
17import Json.Decode as Json
18import Markdown
19import Dom
20import Task
21
22
23main =
24 Html.programWithFlags
25 { init = init
26 , view = view
27 , update = update
28 , subscriptions = subscriptions
29 }
30
31init : T.TypeElmFlags -> (Model,Cmd Msg)
32init flags =Model {question = flags.typing_question, reply = Nothing, currentSTA = Nothing, currentMessage = Nothing, history = []} ! [getInitialState]
33
34-- MODEL
35
36
37type alias Step =
38 { reason : String
39 , result : String }
40
41
42type Model = Model
43 { question : String
44 , reply : Maybe T.ServerReply
45 , currentSTA : Maybe (T.SerializedTypeAnnotation String)
46 , currentMessage : Maybe String
47 , history : List (Model) -- This might be something slightly lighter...
48 }
49
50
51
52-- UPDATE
53
54
55type Msg
56 =
57 Next
58 | Activate (Maybe T.Addr)
59 | SetSTA (T.SerializedTypeAnnotation String)
60 | Undo
61 | Update (Result Http.Error T.ServerReply)
62 | Nop
63
64
65update : Msg -> Model -> ( Model, Cmd Msg )
66update msg (Model model) =
67 case msg of
68 Next -> case model.currentSTA of
69 Just sta -> case model.reply of
70 Just reply -> Model model ! [ doCheck (makeExprRequest reply sta) ]
71 Nothing -> Model model ! []
72 Nothing -> Model model ! []
73
74 SetSTA sta -> Model {model | currentSTA = Just sta} ! []
75
76 Update (Result.Ok reply) -> if reply.canProceed
77 then let new = {model | reply = Just reply} --, history = Model model::model.history}
78 in Model {new|history=Model new::model.history} ! []
79 else Model {model | currentMessage = Just reply.lastReasons} ! []
80
81 Update (Result.Err httpErr) -> Model model ! []
82
83 Activate maddr -> case maddr of
84 Nothing -> Model {model |currentSTA = Nothing} ![]
85 Just addr -> Model {model | currentSTA = Just (T.STA (addrExprNum addr) (addrToTarget addr) "")} ! []
86
87 Undo -> Model model ! []
88
89 Nop ->
90 Model model ! []
91
92
93setReason s r =
94 { s | reason = r }
95
96
97setResult s r =
98 { s | result = r }
99
100
101doFocus =
102 Task.attempt (always Nop) (Dom.focus "CURINPUT")
103
104-- VIEW
105
106renderModel last editable m = case m.reply of
107 Nothing -> []
108 Just reply -> [div [class "current"]
109 ((if reply.lastReasons /= "" && not last
110 then span [class "reason"] [text ("== {- "++reply.lastReasons++" -}")]
111 else if last then span [class "reason"] [text "== {- ?-}"] else span [class "reason"] [])
112 :: [renderConstraints m.reply, text " ⊢ "
113 ,renderPart (setEditable editable (initialRenderState reply m.currentSTA))
114 (T.Refer (T.Number 0))
115
116 ]++case m.currentMessage of
117 Nothing -> []
118 Just msg -> [div [class "message"] [text msg]]
119 )
120 ]
121
122view : Model -> Html Msg
123view (Model model) =
124 div []
125 ([ Html.p [] [ Markdown.toHtml [class "questionText"] (model.question) ]
126 ]++ List.reverse (List.concatMap (\(Model m1) -> renderModel False False m1) model.history)
127 ++ renderModel True True model)
128
129renderConstraints mc = case mc of
130 Nothing -> span [class "constraints", class "empty"] []
131 Just cs -> if cs.currentConstraints == []
132 then span [class "constraints", class "empty"] []
133 else span [class "constraints"]
134 (List.intersperse (text ",")
135 (List.map (\(T.Constraint class s) -> text (class++" "++s )) cs.currentConstraints))
136
137type AnnotKind = Static (T.SerializedTypeAnnotation String) | Active (T.SerializedTypeAnnotation String) | Blank
138
139renderFragment : RenderState -> T.SerializedFragment -> Html Msg
140renderFragment renderState fragment = case fragment of
141 T.SF addr parts ->
142 let clickEvent = onClickNoPropagate (Activate (Just addr))
143 fragAnnotation = case findAnnotation addr renderState.annotations of
144 Nothing -> exprBox [] Blank
145 Just sta -> exprBox [] (if renderState.underAnnotation then Blank else Static sta)
146 exprBox attrs t = div (class "fragment" :: clickEvent :: attrs)
147 ( case t of
148 Blank ->
149 [span [class "type",class "empty"] []
150 ,span [class "expr"] (List.map (renderPart renderState) parts)]
151 Static (T.STA _ _ ty) ->
152 [span [class "type"] [text ty]
153 ,span [class "expr"] (List.map (renderPart {renderState|underAnnotation=True}) parts)]
154 Active (T.STA n target ty) ->
155 [input [type_ "text",class "type"
156 ,onEnterPress Next
157 ,value ty
158 ,onInput (SetSTA << T.STA n target) ] []
159 ,span [class "expr"] (List.map (renderPart {renderState|underAnnotation=True}) parts)]
160 )
161 in case renderState.currentAnnotation of
162 Nothing -> fragAnnotation
163 Just sta -> if (addr == getAddr sta) && (not renderState.underAnnotation)
164 then if renderState.editable
165 then exprBox [class "activeFragment"] (Active sta)
166 else fragAnnotation
167 else fragAnnotation
168
169
170renderPart renderState p = case p of
171 (T.ConstantPart str) -> span [class "constantPart"] [text str]
172 (T.Refer addr) -> case findFrag addr renderState.fragmentList of
173 Nothing -> text "PROTOCOL ERROR"
174 Just f -> renderFragment renderState f
175
176type alias RenderState = {underAnnotation : Bool
177 ,currentAnnotation : Maybe (T.SerializedTypeAnnotation String)
178 ,fragmentList : List T.SerializedFragment
179 ,annotations : List (T.SerializedTypeAnnotation String)
180 ,editable : Bool}
181
182initialRenderState : T.ServerReply -> Maybe (T.SerializedTypeAnnotation String) -> RenderState
183initialRenderState reply cur = RenderState False cur (reply.currentFragments) (reply.currentTypeAnnotations) True
184setEditable b rs = {rs | editable = b}
185
186findAnnotation : T.Addr -> List (T.SerializedTypeAnnotation a) -> Maybe (T.SerializedTypeAnnotation a)
187findAnnotation addr xs = case xs of
188 [] -> Nothing
189 (sta::xs) -> if addr == getAddr sta then Just sta else findAnnotation addr xs
190
191-- This ought to change into logarithmic version of itself
192findFrag addr frgs = case frgs of
193 [] -> Nothing
194 (T.SF addr1 parts::xs) -> if addr == addr1 then Just (T.SF addr1 parts) else findFrag addr xs
195
196
197
198slackHint = [Markdown.toHtml [] "*Having trouble? Ask in [Slack](https://jyu-fp.slack.com)*"]
199
200
201renderError msg =
202 Html.div [ class "errorMsg" ] [ text msg ]
203
204onClickNoPropagate msg = onWithOptions "click"
205 {stopPropagation = True,preventDefault=False}
206 (Decode.succeed msg)
207
208
209onEnterPress : Msg -> Attribute Msg
210onEnterPress msg =
211 onWithOptions "keypress" {defaultOptions|preventDefault=True}
212 (keyCode |> Json.andThen (\x -> if x==13 then Json.succeed msg else Json.fail "Disregard event"))
213
214
215-- AUXILIARY FUNCTIONS
216
217addrToTarget addr = case addr of
218 T.Number n -> T.Expr
219 T.BinderNOf n bn -> T.Binding bn
220 T.InfixOperatorOf n -> T.InfixOp
221addrExprNum addr = case addr of
222 T.Number n -> n
223 T.BinderNOf n _ -> n
224 T.InfixOperatorOf n -> n
225
226
227makeSTA : T.Addr -> String -> T.SerializedTypeAnnotation String
228makeSTA addr = T.STA (addrExprNum addr) (addrToTarget addr)
229
230getAddr : T.SerializedTypeAnnotation a -> T.Addr
231getAddr sta = case sta of
232 (T.STA n T.Expr _) -> T.Number n
233 (T.STA n (T.Binding m) _) -> T.BinderNOf n m
234 (T.STA n (T.InfixOp) _) -> T.InfixOperatorOf n
235
236
237makeExprRequest : T.ServerReply -> T.SerializedTypeAnnotation String -> T.ClientRequest
238makeExprRequest server sta = T.ClientRequest server.state (T.ModifySub [sta])
239
240-- URG. The system probably can't build T.Constraint by itself, so the API type must change...
241makeCtxRequest : T.ServerReply -> List (T.Constraint String) -> T.ClientRequest
242makeCtxRequest server global = T.ClientRequest server.state (T.SetGlobal global)
243
244
245-- SUBSCRIPTIONS
246
247
248subscriptions : Model -> Sub Msg
249subscriptions model =
250 Sub.none
251
252
253
254--
255--
256--
257---- HTTP
258--
259--
260
261doCheck : T.ClientRequest -> Cmd Msg
262doCheck step =
263 let
264 url =
265 "check_type"
266 in
267 Http.send Update (Http.post url (Http.jsonBody (T.jsonEncClientRequest step)) T.jsonDecServerReply)
268
269getInitialState : Cmd Msg
270getInitialState =
271 let
272 url = "initial"
273 in
274 Http.send Update (Http.get url T.jsonDecServerReply)
DerivationChecker/elms/index.html
(14100 / 0)
  
1<!DOCTYPE HTML>
2<html><head><meta charset="UTF-8"><title>Main</title><style>html,head,body { padding:0; margin:0; }
3body { font-family: calibri, helvetica, arial, sans-serif; }</style><script type="text/javascript">
4(function() {
5'use strict';
6
7function F2(fun)
8{
9 function wrapper(a) { return function(b) { return fun(a,b); }; }
10 wrapper.arity = 2;
11 wrapper.func = fun;
12 return wrapper;
13}
14
15function F3(fun)
16{
17 function wrapper(a) {
18 return function(b) { return function(c) { return fun(a, b, c); }; };
19 }
20 wrapper.arity = 3;
21 wrapper.func = fun;
22 return wrapper;
23}
24
25function F4(fun)
26{
27 function wrapper(a) { return function(b) { return function(c) {
28 return function(d) { return fun(a, b, c, d); }; }; };
29 }
30 wrapper.arity = 4;
31 wrapper.func = fun;
32 return wrapper;
33}
34
35function F5(fun)
36{
37 function wrapper(a) { return function(b) { return function(c) {
38 return function(d) { return function(e) { return fun(a, b, c, d, e); }; }; }; };
39 }
40 wrapper.arity = 5;
41 wrapper.func = fun;
42 return wrapper;
43}
44
45function F6(fun)
46{
47 function wrapper(a) { return function(b) { return function(c) {
48 return function(d) { return function(e) { return function(f) {
49 return fun(a, b, c, d, e, f); }; }; }; }; };
50 }
51 wrapper.arity = 6;
52 wrapper.func = fun;
53 return wrapper;
54}
55
56function F7(fun)
57{
58 function wrapper(a) { return function(b) { return function(c) {
59 return function(d) { return function(e) { return function(f) {
60 return function(g) { return fun(a, b, c, d, e, f, g); }; }; }; }; }; };
61 }
62 wrapper.arity = 7;
63 wrapper.func = fun;
64 return wrapper;
65}
66
67function F8(fun)
68{
69 function wrapper(a) { return function(b) { return function(c) {
70 return function(d) { return function(e) { return function(f) {
71 return function(g) { return function(h) {
72 return fun(a, b, c, d, e, f, g, h); }; }; }; }; }; }; };
73 }
74 wrapper.arity = 8;
75 wrapper.func = fun;
76 return wrapper;
77}
78
79function F9(fun)
80{
81 function wrapper(a) { return function(b) { return function(c) {
82 return function(d) { return function(e) { return function(f) {
83 return function(g) { return function(h) { return function(i) {
84 return fun(a, b, c, d, e, f, g, h, i); }; }; }; }; }; }; }; };
85 }
86 wrapper.arity = 9;
87 wrapper.func = fun;
88 return wrapper;
89}
90
91function A2(fun, a, b)
92{
93 return fun.arity === 2
94 ? fun.func(a, b)
95 : fun(a)(b);
96}
97function A3(fun, a, b, c)
98{
99 return fun.arity === 3
100 ? fun.func(a, b, c)
101 : fun(a)(b)(c);
102}
103function A4(fun, a, b, c, d)
104{
105 return fun.arity === 4
106 ? fun.func(a, b, c, d)
107 : fun(a)(b)(c)(d);
108}
109function A5(fun, a, b, c, d, e)
110{
111 return fun.arity === 5
112 ? fun.func(a, b, c, d, e)
113 : fun(a)(b)(c)(d)(e);
114}
115function A6(fun, a, b, c, d, e, f)
116{
117 return fun.arity === 6
118 ? fun.func(a, b, c, d, e, f)
119 : fun(a)(b)(c)(d)(e)(f);
120}
121function A7(fun, a, b, c, d, e, f, g)
122{
123 return fun.arity === 7
124 ? fun.func(a, b, c, d, e, f, g)
125 : fun(a)(b)(c)(d)(e)(f)(g);
126}
127function A8(fun, a, b, c, d, e, f, g, h)
128{
129 return fun.arity === 8
130 ? fun.func(a, b, c, d, e, f, g, h)
131 : fun(a)(b)(c)(d)(e)(f)(g)(h);
132}
133function A9(fun, a, b, c, d, e, f, g, h, i)
134{
135 return fun.arity === 9
136 ? fun.func(a, b, c, d, e, f, g, h, i)
137 : fun(a)(b)(c)(d)(e)(f)(g)(h)(i);
138}
139//import Native.List //
140
141var _elm_lang$core$Native_Array = function() {
142
143// A RRB-Tree has two distinct data types.
144// Leaf -> "height" is always 0
145// "table" is an array of elements
146// Node -> "height" is always greater than 0
147// "table" is an array of child nodes
148// "lengths" is an array of accumulated lengths of the child nodes
149
150// M is the maximal table size. 32 seems fast. E is the allowed increase
151// of search steps when concatting to find an index. Lower values will
152// decrease balancing, but will increase search steps.
153var M = 32;
154var E = 2;
155
156// An empty array.
157var empty = {
158 ctor: '_Array',
159 height: 0,
160 table: []
161};
162
163
164function get(i, array)
165{
166 if (i < 0 || i >= length(array))
167 {
168 throw new Error(
169 'Index ' + i + ' is out of range. Check the length of ' +
170 'your array first or use getMaybe or getWithDefault.');
171 }
172 return unsafeGet(i, array);
173}
174
175
176function unsafeGet(i, array)
177{
178 for (var x = array.height; x > 0; x--)
179 {
180 var slot = i >> (x * 5);
181 while (array.lengths[slot] <= i)
182 {
183 slot++;
184 }
185 if (slot > 0)
186 {
187 i -= array.lengths[slot - 1];
188 }
189 array = array.table[slot];
190 }
191 return array.table[i];
192}
193
194
195// Sets the value at the index i. Only the nodes leading to i will get
196// copied and updated.
197function set(i, item, array)
198{
199 if (i < 0 || length(array) <= i)
200 {
201 return array;
202 }
203 return unsafeSet(i, item, array);
204}
205
206
207function unsafeSet(i, item, array)
208{
209 array = nodeCopy(array);
210
211 if (array.height === 0)
212 {
213 array.table[i] = item;
214 }
215 else
216 {
217 var slot = getSlot(i, array);
218 if (slot > 0)
219 {
220 i -= array.lengths[slot - 1];
221 }
222 array.table[slot] = unsafeSet(i, item, array.table[slot]);
223 }
224 return array;
225}
226
227
228function initialize(len, f)
229{
230 if (len <= 0)
231 {
232 return empty;
233 }
234 var h = Math.floor( Math.log(len) / Math.log(M) );
235 return initialize_(f, h, 0, len);
236}
237
238function initialize_(f, h, from, to)
239{
240 if (h === 0)
241 {
242 var table = new Array((to - from) % (M + 1));
243 for (var i = 0; i < table.length; i++)
244 {
245 table[i] = f(from + i);
246 }
247 return {
248 ctor: '_Array',
249 height: 0,
250 table: table
251 };
252 }
253
254 var step = Math.pow(M, h);
255 var table = new Array(Math.ceil((to - from) / step));
256 var lengths = new Array(table.length);
257 for (var i = 0; i < table.length; i++)
258 {
259 table[i] = initialize_(f, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to));
260 lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0);
261 }
262 return {
263 ctor: '_Array',
264 height: h,
265 table: table,
266 lengths: lengths
267 };
268}
269
270function fromList(list)
271{
272 if (list.ctor === '[]')
273 {
274 return empty;
275 }
276
277 // Allocate M sized blocks (table) and write list elements to it.
278 var table = new Array(M);
279 var nodes = [];
280 var i = 0;
281
282 while (list.ctor !== '[]')
283 {
284 table[i] = list._0;
285 list = list._1;
286 i++;
287
288 // table is full, so we can push a leaf containing it into the
289 // next node.
290 if (i === M)
291 {
292 var leaf = {
293 ctor: '_Array',
294 height: 0,
295 table: table
296 };
297 fromListPush(leaf, nodes);
298 table = new Array(M);
299 i = 0;
300 }
301 }
302
303 // Maybe there is something left on the table.
304 if (i > 0)
305 {
306 var leaf = {
307 ctor: '_Array',
308 height: 0,
309 table: table.splice(0, i)
310 };
311 fromListPush(leaf, nodes);
312 }
313
314 // Go through all of the nodes and eventually push them into higher nodes.
315 for (var h = 0; h < nodes.length - 1; h++)
316 {
317 if (nodes[h].table.length > 0)
318 {
319 fromListPush(nodes[h], nodes);
320 }
321 }
322
323 var head = nodes[nodes.length - 1];
324 if (head.height > 0 && head.table.length === 1)
325 {
326 return head.table[0];
327 }
328 else
329 {
330 return head;
331 }
332}
333
334// Push a node into a higher node as a child.
335function fromListPush(toPush, nodes)
336{
337 var h = toPush.height;
338
339 // Maybe the node on this height does not exist.
340 if (nodes.length === h)
341 {
342 var node = {
343 ctor: '_Array',
344 height: h + 1,
345 table: [],
346 lengths: []
347 };
348 nodes.push(node);
349 }
350
351 nodes[h].table.push(toPush);
352 var len = length(toPush);
353 if (nodes[h].lengths.length > 0)
354 {
355 len += nodes[h].lengths[nodes[h].lengths.length - 1];
356 }
357 nodes[h].lengths.push(len);
358
359 if (nodes[h].table.length === M)
360 {
361 fromListPush(nodes[h], nodes);
362 nodes[h] = {
363 ctor: '_Array',
364 height: h + 1,
365 table: [],
366 lengths: []
367 };
368 }
369}
370
371// Pushes an item via push_ to the bottom right of a tree.
372function push(item, a)
373{
374 var pushed = push_(item, a);
375 if (pushed !== null)
376 {
377 return pushed;
378 }
379
380 var newTree = create(item, a.height);
381 return siblise(a, newTree);
382}
383
384// Recursively tries to push an item to the bottom-right most
385// tree possible. If there is no space left for the item,
386// null will be returned.
387function push_(item, a)
388{
389 // Handle resursion stop at leaf level.
390 if (a.height === 0)
391 {
392 if (a.table.length < M)
393 {
394 var newA = {
395 ctor: '_Array',
396 height: 0,
397 table: a.table.slice()
398 };
399 newA.table.push(item);
400 return newA;
401 }
402 else
403 {
404 return null;
405 }
406 }
407
408 // Recursively push
409 var pushed = push_(item, botRight(a));
410
411 // There was space in the bottom right tree, so the slot will
412 // be updated.
413 if (pushed !== null)
414 {
415 var newA = nodeCopy(a);
416 newA.table[newA.table.length - 1] = pushed;
417 newA.lengths[newA.lengths.length - 1]++;
418 return newA;
419 }
420
421 // When there was no space left, check if there is space left
422 // for a new slot with a tree which contains only the item
423 // at the bottom.
424 if (a.table.length < M)
425 {
426 var newSlot = create(item, a.height - 1);
427 var newA = nodeCopy(a);
428 newA.table.push(newSlot);
429 newA.lengths.push(newA.lengths[newA.lengths.length - 1] + length(newSlot));
430 return newA;
431 }
432 else
433 {
434 return null;
435 }
436}
437
438// Converts an array into a list of elements.
439function toList(a)
440{
441 return toList_(_elm_lang$core$Native_List.Nil, a);
442}
443
444function toList_(list, a)
445{
446 for (var i = a.table.length - 1; i >= 0; i--)
447 {
448 list =
449 a.height === 0
450 ? _elm_lang$core$Native_List.Cons(a.table[i], list)
451 : toList_(list, a.table[i]);
452 }
453 return list;
454}
455
456// Maps a function over the elements of an array.
457function map(f, a)
458{
459 var newA = {
460 ctor: '_Array',
461 height: a.height,
462 table: new Array(a.table.length)
463 };
464 if (a.height > 0)
465 {
466 newA.lengths = a.lengths;
467 }
468 for (var i = 0; i < a.table.length; i++)
469 {
470 newA.table[i] =
471 a.height === 0
472 ? f(a.table[i])
473 : map(f, a.table[i]);
474 }
475 return newA;
476}
477
478// Maps a function over the elements with their index as first argument.
479function indexedMap(f, a)
480{
481 return indexedMap_(f, a, 0);
482}
483
484function indexedMap_(f, a, from)
485{
486 var newA = {
487 ctor: '_Array',
488 height: a.height,
489 table: new Array(a.table.length)
490 };
491 if (a.height > 0)
492 {
493 newA.lengths = a.lengths;
494 }
495 for (var i = 0; i < a.table.length; i++)
496 {
497 newA.table[i] =
498 a.height === 0
499 ? A2(f, from + i, a.table[i])
500 : indexedMap_(f, a.table[i], i == 0 ? from : from + a.lengths[i - 1]);
501 }
502 return newA;
503}
504
505function foldl(f, b, a)
506{
507 if (a.height === 0)
508 {
509 for (var i = 0; i < a.table.length; i++)
510 {
511 b = A2(f, a.table[i], b);
512 }
513 }
514 else
515 {
516 for (var i = 0; i < a.table.length; i++)
517 {
518 b = foldl(f, b, a.table[i]);
519 }
520 }
521 return b;
522}
523
524function foldr(f, b, a)
525{
526 if (a.height === 0)
527 {
528 for (var i = a.table.length; i--; )
529 {
530 b = A2(f, a.table[i], b);
531 }
532 }
533 else
534 {
535 for (var i = a.table.length; i--; )
536 {
537 b = foldr(f, b, a.table[i]);
538 }
539 }
540 return b;
541}
542
543// TODO: currently, it slices the right, then the left. This can be
544// optimized.
545function slice(from, to, a)
546{
547 if (from < 0)
548 {
549 from += length(a);
550 }
551 if (to < 0)
552 {
553 to += length(a);
554 }
555 return sliceLeft(from, sliceRight(to, a));
556}
557
558function sliceRight(to, a)
559{
560 if (to === length(a))
561 {
562 return a;
563 }
564
565 // Handle leaf level.
566 if (a.height === 0)
567 {
568 var newA = { ctor:'_Array', height:0 };
569 newA.table = a.table.slice(0, to);
570 return newA;
571 }
572
573 // Slice the right recursively.
574 var right = getSlot(to, a);
575 var sliced = sliceRight(to - (right > 0 ? a.lengths[right - 1] : 0), a.table[right]);
576
577 // Maybe the a node is not even needed, as sliced contains the whole slice.
578 if (right === 0)
579 {
580 return sliced;
581 }
582
583 // Create new node.
584 var newA = {
585 ctor: '_Array',
586 height: a.height,
587 table: a.table.slice(0, right),
588 lengths: a.lengths.slice(0, right)
589 };
590 if (sliced.table.length > 0)
591 {
592 newA.table[right] = sliced;
593 newA.lengths[right] = length(sliced) + (right > 0 ? newA.lengths[right - 1] : 0);
594 }
595 return newA;
596}
597
598function sliceLeft(from, a)
599{
600 if (from === 0)
601 {
602 return a;
603 }
604
605 // Handle leaf level.
606 if (a.height === 0)
607 {
608 var newA = { ctor:'_Array', height:0 };
609 newA.table = a.table.slice(from, a.table.length + 1);
610 return newA;
611 }
612
613 // Slice the left recursively.
614 var left = getSlot(from, a);
615 var sliced = sliceLeft(from - (left > 0 ? a.lengths[left - 1] : 0), a.table[left]);
616
617 // Maybe the a node is not even needed, as sliced contains the whole slice.
618 if (left === a.table.length - 1)
619 {
620 return sliced;
621 }
622
623 // Create new node.
624 var newA = {
625 ctor: '_Array',
626 height: a.height,
627 table: a.table.slice(left, a.table.length + 1),
628 lengths: new Array(a.table.length - left)
629 };
630 newA.table[0] = sliced;
631 var len = 0;
632 for (var i = 0; i < newA.table.length; i++)
633 {
634 len += length(newA.table[i]);
635 newA.lengths[i] = len;
636 }
637
638 return newA;
639}
640
641// Appends two trees.
642function append(a,b)
643{
644 if (a.table.length === 0)
645 {
646 return b;
647 }
648 if (b.table.length === 0)
649 {
650 return a;
651 }
652
653 var c = append_(a, b);
654
655 // Check if both nodes can be crunshed together.
656 if (c[0].table.length + c[1].table.length <= M)
657 {
658 if (c[0].table.length === 0)
659 {
660 return c[1];
661 }
662 if (c[1].table.length === 0)
663 {
664 return c[0];
665 }
666
667 // Adjust .table and .lengths
668 c[0].table = c[0].table.concat(c[1].table);
669 if (c[0].height > 0)
670 {
671 var len = length(c[0]);
672 for (var i = 0; i < c[1].lengths.length; i++)
673 {
674 c[1].lengths[i] += len;
675 }
676 c[0].lengths = c[0].lengths.concat(c[1].lengths);
677 }
678
679 return c[0];
680 }
681
682 if (c[0].height > 0)
683 {
684 var toRemove = calcToRemove(a, b);
685 if (toRemove > E)
686 {
687 c = shuffle(c[0], c[1], toRemove);
688 }
689 }
690
691 return siblise(c[0], c[1]);
692}
693
694// Returns an array of two nodes; right and left. One node _may_ be empty.
695function append_(a, b)
696{
697 if (a.height === 0 && b.height === 0)
698 {
699 return [a, b];
700 }
701
702 if (a.height !== 1 || b.height !== 1)
703 {
704 if (a.height === b.height)
705 {
706 a = nodeCopy(a);
707 b = nodeCopy(b);
708 var appended = append_(botRight(a), botLeft(b));
709
710 insertRight(a, appended[1]);
711 insertLeft(b, appended[0]);
712 }
713 else if (a.height > b.height)
714 {
715 a = nodeCopy(a);
716 var appended = append_(botRight(a), b);
717
718 insertRight(a, appended[0]);
719 b = parentise(appended[1], appended[1].height + 1);
720 }
721 else
722 {
723 b = nodeCopy(b);
724 var appended = append_(a, botLeft(b));
725
726 var left = appended[0].table.length === 0 ? 0 : 1;
727 var right = left === 0 ? 1 : 0;
728 insertLeft(b, appended[left]);
729 a = parentise(appended[right], appended[right].height + 1);
730 }
731 }
732
733 // Check if balancing is needed and return based on that.
734 if (a.table.length === 0 || b.table.length === 0)
735 {
736 return [a, b];
737 }
738
739 var toRemove = calcToRemove(a, b);
740 if (toRemove <= E)
741 {
742 return [a, b];
743 }
744 return shuffle(a, b, toRemove);
745}
746
747// Helperfunctions for append_. Replaces a child node at the side of the parent.
748function insertRight(parent, node)
749{
750 var index = parent.table.length - 1;
751 parent.table[index] = node;
752 parent.lengths[index] = length(node);
753 parent.lengths[index] += index > 0 ? parent.lengths[index - 1] : 0;
754}
755
756function insertLeft(parent, node)
757{
758 if (node.table.length > 0)
759 {
760 parent.table[0] = node;
761 parent.lengths[0] = length(node);
762
763 var len = length(parent.table[0]);
764 for (var i = 1; i < parent.lengths.length; i++)
765 {
766 len += length(parent.table[i]);
767 parent.lengths[i] = len;
768 }
769 }
770 else
771 {
772 parent.table.shift();
773 for (var i = 1; i < parent.lengths.length; i++)
774 {
775 parent.lengths[i] = parent.lengths[i] - parent.lengths[0];
776 }
777 parent.lengths.shift();
778 }
779}
780
781// Returns the extra search steps for E. Refer to the paper.
782function calcToRemove(a, b)
783{
784 var subLengths = 0;
785 for (var i = 0; i < a.table.length; i++)
786 {
787 subLengths += a.table[i].table.length;
788 }
789 for (var i = 0; i < b.table.length; i++)
790 {
791 subLengths += b.table[i].table.length;
792 }
793
794 var toRemove = a.table.length + b.table.length;
795 return toRemove - (Math.floor((subLengths - 1) / M) + 1);
796}
797
798// get2, set2 and saveSlot are helpers for accessing elements over two arrays.
799function get2(a, b, index)
800{
801 return index < a.length
802 ? a[index]
803 : b[index - a.length];
804}
805
806function set2(a, b, index, value)
807{
808 if (index < a.length)
809 {
810 a[index] = value;
811 }
812 else
813 {
814 b[index - a.length] = value;
815 }
816}
817
818function saveSlot(a, b, index, slot)
819{
820 set2(a.table, b.table, index, slot);
821
822 var l = (index === 0 || index === a.lengths.length)
823 ? 0
824 : get2(a.lengths, a.lengths, index - 1);
825
826 set2(a.lengths, b.lengths, index, l + length(slot));
827}
828
829// Creates a node or leaf with a given length at their arrays for perfomance.
830// Is only used by shuffle.
831function createNode(h, length)
832{
833 if (length < 0)
834 {
835 length = 0;
836 }
837 var a = {
838 ctor: '_Array',
839 height: h,
840 table: new Array(length)
841 };
842 if (h > 0)
843 {
844 a.lengths = new Array(length);
845 }
846 return a;
847}
848
849// Returns an array of two balanced nodes.
850function shuffle(a, b, toRemove)
851{
852 var newA = createNode(a.height, Math.min(M, a.table.length + b.table.length - toRemove));
853 var newB = createNode(a.height, newA.table.length - (a.table.length + b.table.length - toRemove));
854
855 // Skip the slots with size M. More precise: copy the slot references
856 // to the new node
857 var read = 0;
858 while (get2(a.table, b.table, read).table.length % M === 0)
859 {
860 set2(newA.table, newB.table, read, get2(a.table, b.table, read));
861 set2(newA.lengths, newB.lengths, read, get2(a.lengths, b.lengths, read));
862 read++;
863 }
864
865 // Pulling items from left to right, caching in a slot before writing
866 // it into the new nodes.
867 var write = read;
868 var slot = new createNode(a.height - 1, 0);
869 var from = 0;
870
871 // If the current slot is still containing data, then there will be at
872 // least one more write, so we do not break this loop yet.
873 while (read - write - (slot.table.length > 0 ? 1 : 0) < toRemove)
874 {
875 // Find out the max possible items for copying.
876 var source = get2(a.table, b.table, read);
877 var to = Math.min(M - slot.table.length, source.table.length);
878
879 // Copy and adjust size table.
880 slot.table = slot.table.concat(source.table.slice(from, to));
881 if (slot.height > 0)
882 {
883 var len = slot.lengths.length;
884 for (var i = len; i < len + to - from; i++)
885 {
886 slot.lengths[i] = length(slot.table[i]);
887 slot.lengths[i] += (i > 0 ? slot.lengths[i - 1] : 0);
888 }
889 }
890
891 from += to;
892
893 // Only proceed to next slots[i] if the current one was
894 // fully copied.
895 if (source.table.length <= to)
896 {
897 read++; from = 0;
898 }
899
900 // Only create a new slot if the current one is filled up.
901 if (slot.table.length === M)
902 {
903 saveSlot(newA, newB, write, slot);
904 slot = createNode(a.height - 1, 0);
905 write++;
906 }
907 }
908
909 // Cleanup after the loop. Copy the last slot into the new nodes.
910 if (slot.table.length > 0)
911 {
912 saveSlot(newA, newB, write, slot);
913 write++;
914 }
915
916 // Shift the untouched slots to the left
917 while (read < a.table.length + b.table.length )
918 {
919 saveSlot(newA, newB, write, get2(a.table, b.table, read));
920 read++;
921 write++;
922 }
923
924 return [newA, newB];
925}
926
927// Navigation functions
928function botRight(a)
929{
930 return a.table[a.table.length - 1];
931}
932function botLeft(a)
933{
934 return a.table[0];
935}
936
937// Copies a node for updating. Note that you should not use this if
938// only updating only one of "table" or "lengths" for performance reasons.
939function nodeCopy(a)
940{
941 var newA = {
942 ctor: '_Array',
943 height: a.height,
944 table: a.table.slice()
945 };
946 if (a.height > 0)
947 {
948 newA.lengths = a.lengths.slice();
949 }
950 return newA;
951}
952
953// Returns how many items are in the tree.
954function length(array)
955{
956 if (array.height === 0)
957 {
958 return array.table.length;
959 }
960 else
961 {
962 return array.lengths[array.lengths.length - 1];
963 }
964}
965
966// Calculates in which slot of "table" the item probably is, then
967// find the exact slot via forward searching in "lengths". Returns the index.
968function getSlot(i, a)
969{
970 var slot = i >> (5 * a.height);
971 while (a.lengths[slot] <= i)
972 {
973 slot++;
974 }
975 return slot;
976}
977
978// Recursively creates a tree with a given height containing
979// only the given item.
980function create(item, h)
981{
982 if (h === 0)
983 {
984 return {
985 ctor: '_Array',
986 height: 0,
987 table: [item]
988 };
989 }
990 return {
991 ctor: '_Array',
992 height: h,
993 table: [create(item, h - 1)],
994 lengths: [1]
995 };
996}
997
998// Recursively creates a tree that contains the given tree.
999function parentise(tree, h)
1000{
1001 if (h === tree.height)
1002 {
1003 return tree;
1004 }
1005
1006 return {
1007 ctor: '_Array',
1008 height: h,
1009 table: [parentise(tree, h - 1)],
1010 lengths: [length(tree)]
1011 };
1012}
1013
1014// Emphasizes blood brotherhood beneath two trees.
1015function siblise(a, b)
1016{
1017 return {
1018 ctor: '_Array',
1019 height: a.height + 1,
1020 table: [a, b],
1021 lengths: [length(a), length(a) + length(b)]
1022 };
1023}
1024
1025function toJSArray(a)
1026{
1027 var jsArray = new Array(length(a));
1028 toJSArray_(jsArray, 0, a);
1029 return jsArray;
1030}
1031
1032function toJSArray_(jsArray, i, a)
1033{
1034 for (var t = 0; t < a.table.length; t++)
1035 {
1036 if (a.height === 0)
1037 {
1038 jsArray[i + t] = a.table[t];
1039 }
1040 else
1041 {
1042 var inc = t === 0 ? 0 : a.lengths[t - 1];
1043 toJSArray_(jsArray, i + inc, a.table[t]);
1044 }
1045 }
1046}
1047
1048function fromJSArray(jsArray)
1049{
1050 if (jsArray.length === 0)
1051 {
1052 return empty;
1053 }
1054 var h = Math.floor(Math.log(jsArray.length) / Math.log(M));
1055 return fromJSArray_(jsArray, h, 0, jsArray.length);
1056}
1057
1058function fromJSArray_(jsArray, h, from, to)
1059{
1060 if (h === 0)
1061 {
1062 return {
1063 ctor: '_Array',
1064 height: 0,
1065 table: jsArray.slice(from, to)
1066 };
1067 }
1068
1069 var step = Math.pow(M, h);
1070 var table = new Array(Math.ceil((to - from) / step));
1071 var lengths = new Array(table.length);
1072 for (var i = 0; i < table.length; i++)
1073 {
1074 table[i] = fromJSArray_(jsArray, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to));
1075 lengths[i] = length(table[i]) + (i > 0 ? lengths[i - 1] : 0);
1076 }
1077 return {
1078 ctor: '_Array',
1079 height: h,
1080 table: table,
1081 lengths: lengths
1082 };
1083}
1084
1085return {
1086 empty: empty,
1087 fromList: fromList,
1088 toList: toList,
1089 initialize: F2(initialize),
1090 append: F2(append),
1091 push: F2(push),
1092 slice: F3(slice),
1093 get: F2(get),
1094 set: F3(set),
1095 map: F2(map),
1096 indexedMap: F2(indexedMap),
1097 foldl: F3(foldl),
1098 foldr: F3(foldr),
1099 length: length,
1100
1101 toJSArray: toJSArray,
1102 fromJSArray: fromJSArray
1103};
1104
1105}();//import Native.Utils //
1106
1107var _elm_lang$core$Native_Basics = function() {
1108
1109function div(a, b)
1110{
1111 return (a / b) | 0;
1112}
1113function rem(a, b)
1114{
1115 return a % b;
1116}
1117function mod(a, b)
1118{
1119 if (b === 0)
1120 {
1121 throw new Error('Cannot perform mod 0. Division by zero error.');
1122 }
1123 var r = a % b;
1124 var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r + b) : -mod(-a, -b));
1125
1126 return m === b ? 0 : m;
1127}
1128function logBase(base, n)
1129{
1130 return Math.log(n) / Math.log(base);
1131}
1132function negate(n)
1133{
1134 return -n;
1135}
1136function abs(n)
1137{
1138 return n < 0 ? -n : n;
1139}
1140
1141function min(a, b)
1142{
1143 return _elm_lang$core$Native_Utils.cmp(a, b) < 0 ? a : b;
1144}
1145function max(a, b)
1146{
1147 return _elm_lang$core$Native_Utils.cmp(a, b) > 0 ? a : b;
1148}
1149function clamp(lo, hi, n)
1150{
1151 return _elm_lang$core$Native_Utils.cmp(n, lo) < 0
1152 ? lo
1153 : _elm_lang$core$Native_Utils.cmp(n, hi) > 0
1154 ? hi
1155 : n;
1156}
1157
1158var ord = ['LT', 'EQ', 'GT'];
1159
1160function compare(x, y)
1161{
1162 return { ctor: ord[_elm_lang$core$Native_Utils.cmp(x, y) + 1] };
1163}
1164
1165function xor(a, b)
1166{
1167 return a !== b;
1168}
1169function not(b)
1170{
1171 return !b;
1172}
1173function isInfinite(n)
1174{
1175 return n === Infinity || n === -Infinity;
1176}
1177
1178function truncate(n)
1179{
1180 return n | 0;
1181}
1182
1183function degrees(d)
1184{
1185 return d * Math.PI / 180;
1186}
1187function turns(t)
1188{
1189 return 2 * Math.PI * t;
1190}
1191function fromPolar(point)
1192{
1193 var r = point._0;
1194 var t = point._1;
1195 return _elm_lang$core$Native_Utils.Tuple2(r * Math.cos(t), r * Math.sin(t));
1196}
1197function toPolar(point)
1198{
1199 var x = point._0;
1200 var y = point._1;
1201 return _elm_lang$core$Native_Utils.Tuple2(Math.sqrt(x * x + y * y), Math.atan2(y, x));
1202}
1203
1204return {
1205 div: F2(div),
1206 rem: F2(rem),
1207 mod: F2(mod),
1208
1209 pi: Math.PI,
1210 e: Math.E,
1211 cos: Math.cos,
1212 sin: Math.sin,
1213 tan: Math.tan,
1214 acos: Math.acos,
1215 asin: Math.asin,
1216 atan: Math.atan,
1217 atan2: F2(Math.atan2),
1218
1219 degrees: degrees,
1220 turns: turns,
1221 fromPolar: fromPolar,
1222 toPolar: toPolar,
1223
1224 sqrt: Math.sqrt,
1225 logBase: F2(logBase),
1226 negate: negate,
1227 abs: abs,
1228 min: F2(min),
1229 max: F2(max),
1230 clamp: F3(clamp),
1231 compare: F2(compare),
1232
1233 xor: F2(xor),
1234 not: not,
1235
1236 truncate: truncate,
1237 ceiling: Math.ceil,
1238 floor: Math.floor,
1239 round: Math.round,
1240 toFloat: function(x) { return x; },
1241 isNaN: isNaN,
1242 isInfinite: isInfinite
1243};
1244
1245}();//import //
1246
1247var _elm_lang$core$Native_Utils = function() {
1248
1249// COMPARISONS
1250
1251function eq(x, y)
1252{
1253 var stack = [];
1254 var isEqual = eqHelp(x, y, 0, stack);
1255 var pair;
1256 while (isEqual && (pair = stack.pop()))
1257 {
1258 isEqual = eqHelp(pair.x, pair.y, 0, stack);
1259 }
1260 return isEqual;
1261}
1262
1263
1264function eqHelp(x, y, depth, stack)
1265{
1266 if (depth > 100)
1267 {
1268 stack.push({ x: x, y: y });
1269 return true;
1270 }
1271
1272 if (x === y)
1273 {
1274 return true;
1275 }
1276
1277 if (typeof x !== 'object')
1278 {
1279 if (typeof x === 'function')
1280 {
1281 throw new Error(
1282 'Trying to use `(==)` on functions. There is no way to know if functions are "the same" in the Elm sense.'
1283 + ' Read more about this at http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#=='
1284 + ' which describes why it is this way and what the better version will look like.'
1285 );
1286 }
1287 return false;
1288 }
1289
1290 if (x === null || y === null)
1291 {
1292 return false
1293 }
1294
1295 if (x instanceof Date)
1296 {
1297 return x.getTime() === y.getTime();
1298 }
1299
1300 if (!('ctor' in x))
1301 {
1302 for (var key in x)
1303 {
1304 if (!eqHelp(x[key], y[key], depth + 1, stack))
1305 {
1306 return false;
1307 }
1308 }
1309 return true;
1310 }
1311
1312 // convert Dicts and Sets to lists
1313 if (x.ctor === 'RBNode_elm_builtin' || x.ctor === 'RBEmpty_elm_builtin')
1314 {
1315 x = _elm_lang$core$Dict$toList(x);
1316 y = _elm_lang$core$Dict$toList(y);
1317 }
1318 if (x.ctor === 'Set_elm_builtin')
1319 {
1320 x = _elm_lang$core$Set$toList(x);
1321 y = _elm_lang$core$Set$toList(y);
1322 }
1323
1324 // check if lists are equal without recursion
1325 if (x.ctor === '::')
1326 {
1327 var a = x;
1328 var b = y;
1329 while (a.ctor === '::' && b.ctor === '::')
1330 {
1331 if (!eqHelp(a._0, b._0, depth + 1, stack))
1332 {
1333 return false;
1334 }
1335 a = a._1;
1336 b = b._1;
1337 }
1338 return a.ctor === b.ctor;
1339 }
1340
1341 // check if Arrays are equal
1342 if (x.ctor === '_Array')
1343 {
1344 var xs = _elm_lang$core$Native_Array.toJSArray(x);
1345 var ys = _elm_lang$core$Native_Array.toJSArray(y);
1346 if (xs.length !== ys.length)
1347 {
1348 return false;
1349 }
1350 for (var i = 0; i < xs.length; i++)
1351 {
1352 if (!eqHelp(xs[i], ys[i], depth + 1, stack))
1353 {
1354 return false;
1355 }
1356 }
1357 return true;
1358 }
1359
1360 if (!eqHelp(x.ctor, y.ctor, depth + 1, stack))
1361 {
1362 return false;
1363 }
1364
1365 for (var key in x)
1366 {
1367 if (!eqHelp(x[key], y[key], depth + 1, stack))
1368 {
1369 return false;
1370 }
1371 }
1372 return true;
1373}
1374
1375// Code in Generate/JavaScript.hs, Basics.js, and List.js depends on
1376// the particular integer values assigned to LT, EQ, and GT.
1377
1378var LT = -1, EQ = 0, GT = 1;
1379
1380function cmp(x, y)
1381{
1382 if (typeof x !== 'object')
1383 {
1384 return x === y ? EQ : x < y ? LT : GT;
1385 }
1386
1387 if (x instanceof String)
1388 {
1389 var a = x.valueOf();
1390 var b = y.valueOf();
1391 return a === b ? EQ : a < b ? LT : GT;
1392 }
1393
1394 if (x.ctor === '::' || x.ctor === '[]')
1395 {
1396 while (x.ctor === '::' && y.ctor === '::')
1397 {
1398 var ord = cmp(x._0, y._0);
1399 if (ord !== EQ)
1400 {
1401 return ord;
1402 }
1403 x = x._1;
1404 y = y._1;
1405 }
1406 return x.ctor === y.ctor ? EQ : x.ctor === '[]' ? LT : GT;
1407 }
1408
1409 if (x.ctor.slice(0, 6) === '_Tuple')
1410 {
1411 var ord;
1412 var n = x.ctor.slice(6) - 0;
1413 var err = 'cannot compare tuples with more than 6 elements.';
1414 if (n === 0) return EQ;
1415 if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
1416 if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
1417 if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
1418 if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
1419 if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
1420 if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
1421 if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
1422 return EQ;
1423 }
1424
1425 throw new Error(
1426 'Comparison error: comparison is only defined on ints, '
1427 + 'floats, times, chars, strings, lists of comparable values, '
1428 + 'and tuples of comparable values.'
1429 );
1430}
1431
1432
1433// COMMON VALUES
1434
1435var Tuple0 = {
1436 ctor: '_Tuple0'
1437};
1438
1439function Tuple2(x, y)
1440{
1441 return {
1442 ctor: '_Tuple2',
1443 _0: x,
1444 _1: y
1445 };
1446}
1447
1448function chr(c)
1449{
1450 return new String(c);
1451}
1452
1453
1454// GUID
1455
1456var count = 0;
1457function guid(_)
1458{
1459 return count++;
1460}
1461
1462
1463// RECORDS
1464
1465function update(oldRecord, updatedFields)
1466{
1467 var newRecord = {};
1468
1469 for (var key in oldRecord)
1470 {
1471 newRecord[key] = oldRecord[key];
1472 }
1473
1474 for (var key in updatedFields)
1475 {
1476 newRecord[key] = updatedFields[key];
1477 }
1478
1479 return newRecord;
1480}
1481
1482
1483//// LIST STUFF ////
1484
1485var Nil = { ctor: '[]' };
1486
1487function Cons(hd, tl)
1488{
1489 return {
1490 ctor: '::',
1491 _0: hd,
1492 _1: tl
1493 };
1494}
1495
1496function append(xs, ys)
1497{
1498 // append Strings
1499 if (typeof xs === 'string')
1500 {
1501 return xs + ys;
1502 }
1503
1504 // append Lists
1505 if (xs.ctor === '[]')
1506 {
1507 return ys;
1508 }
1509 var root = Cons(xs._0, Nil);
1510 var curr = root;
1511 xs = xs._1;
1512 while (xs.ctor !== '[]')
1513 {
1514 curr._1 = Cons(xs._0, Nil);
1515 xs = xs._1;
1516 curr = curr._1;
1517 }
1518 curr._1 = ys;
1519 return root;
1520}
1521
1522
1523// CRASHES
1524
1525function crash(moduleName, region)
1526{
1527 return function(message) {
1528 throw new Error(
1529 'Ran into a `Debug.crash` in module `' + moduleName + '` ' + regionToString(region) + '\n'
1530 + 'The message provided by the code author is:\n\n '
1531 + message
1532 );
1533 };
1534}
1535
1536function crashCase(moduleName, region, value)
1537{
1538 return function(message) {
1539 throw new Error(
1540 'Ran into a `Debug.crash` in module `' + moduleName + '`\n\n'
1541 + 'This was caused by the `case` expression ' + regionToString(region) + '.\n'
1542 + 'One of the branches ended with a crash and the following value got through:\n\n ' + toString(value) + '\n\n'
1543 + 'The message provided by the code author is:\n\n '
1544 + message
1545 );
1546 };
1547}
1548
1549function regionToString(region)
1550{
1551 if (region.start.line == region.end.line)
1552 {
1553 return 'on line ' + region.start.line;
1554 }
1555 return 'between lines ' + region.start.line + ' and ' + region.end.line;
1556}
1557
1558
1559// TO STRING
1560
1561function toString(v)
1562{
1563 var type = typeof v;
1564 if (type === 'function')
1565 {
1566 return '<function>';
1567 }
1568
1569 if (type === 'boolean')
1570 {
1571 return v ? 'True' : 'False';
1572 }
1573
1574 if (type === 'number')
1575 {
1576 return v + '';
1577 }
1578
1579 if (v instanceof String)
1580 {
1581 return '\'' + addSlashes(v, true) + '\'';
1582 }
1583
1584 if (type === 'string')
1585 {
1586 return '"' + addSlashes(v, false) + '"';
1587 }
1588
1589 if (v === null)
1590 {
1591 return 'null';
1592 }
1593
1594 if (type === 'object' && 'ctor' in v)
1595 {
1596 var ctorStarter = v.ctor.substring(0, 5);
1597
1598 if (ctorStarter === '_Tupl')
1599 {
1600 var output = [];
1601 for (var k in v)
1602 {
1603 if (k === 'ctor') continue;
1604 output.push(toString(v[k]));
1605 }
1606 return '(' + output.join(',') + ')';
1607 }
1608
1609 if (ctorStarter === '_Task')
1610 {
1611 return '<task>'
1612 }
1613
1614 if (v.ctor === '_Array')
1615 {
1616 var list = _elm_lang$core$Array$toList(v);
1617 return 'Array.fromList ' + toString(list);
1618 }
1619
1620 if (v.ctor === '<decoder>')
1621 {
1622 return '<decoder>';
1623 }
1624
1625 if (v.ctor === '_Process')
1626 {
1627 return '<process:' + v.id + '>';
1628 }
1629
1630 if (v.ctor === '::')
1631 {
1632 var output = '[' + toString(v._0);
1633 v = v._1;
1634 while (v.ctor === '::')
1635 {
1636 output += ',' + toString(v._0);
1637 v = v._1;
1638 }
1639 return output + ']';
1640 }
1641
1642 if (v.ctor === '[]')
1643 {
1644 return '[]';
1645 }
1646
1647 if (v.ctor === 'Set_elm_builtin')
1648 {
1649 return 'Set.fromList ' + toString(_elm_lang$core$Set$toList(v));
1650 }
1651
1652 if (v.ctor === 'RBNode_elm_builtin' || v.ctor === 'RBEmpty_elm_builtin')
1653 {
1654 return 'Dict.fromList ' + toString(_elm_lang$core$Dict$toList(v));
1655 }
1656
1657 var output = '';
1658 for (var i in v)
1659 {
1660 if (i === 'ctor') continue;
1661 var str = toString(v[i]);
1662 var c0 = str[0];
1663 var parenless = c0 === '{' || c0 === '(' || c0 === '<' || c0 === '"' || str.indexOf(' ') < 0;
1664 output += ' ' + (parenless ? str : '(' + str + ')');
1665 }
1666 return v.ctor + output;
1667 }
1668
1669 if (type === 'object')
1670 {
1671 if (v instanceof Date)
1672 {
1673 return '<' + v.toString() + '>';
1674 }
1675
1676 if (v.elm_web_socket)
1677 {
1678 return '<websocket>';
1679 }
1680
1681 var output = [];
1682 for (var k in v)
1683 {
1684 output.push(k + ' = ' + toString(v[k]));
1685 }
1686 if (output.length === 0)
1687 {
1688 return '{}';
1689 }
1690 return '{ ' + output.join(', ') + ' }';
1691 }
1692
1693 return '<internal structure>';
1694}
1695
1696function addSlashes(str, isChar)
1697{
1698 var s = str.replace(/\\/g, '\\\\')
1699 .replace(/\n/g, '\\n')
1700 .replace(/\t/g, '\\t')
1701 .replace(/\r/g, '\\r')
1702 .replace(/\v/g, '\\v')
1703 .replace(/\0/g, '\\0');
1704 if (isChar)
1705 {
1706 return s.replace(/\'/g, '\\\'');
1707 }
1708 else
1709 {
1710 return s.replace(/\"/g, '\\"');
1711 }
1712}
1713
1714
1715return {
1716 eq: eq,
1717 cmp: cmp,
1718 Tuple0: Tuple0,
1719 Tuple2: Tuple2,
1720 chr: chr,
1721 update: update,
1722 guid: guid,
1723
1724 append: F2(append),
1725
1726 crash: crash,
1727 crashCase: crashCase,
1728
1729 toString: toString
1730};
1731
1732}();var _elm_lang$core$Basics$never = function (_p0) {
1733 never:
1734 while (true) {
1735 var _p1 = _p0;
1736 var _v1 = _p1._0;
1737 _p0 = _v1;
1738 continue never;
1739 }
1740};
1741var _elm_lang$core$Basics$uncurry = F2(
1742 function (f, _p2) {
1743 var _p3 = _p2;
1744 return A2(f, _p3._0, _p3._1);
1745 });
1746var _elm_lang$core$Basics$curry = F3(
1747 function (f, a, b) {
1748 return f(
1749 {ctor: '_Tuple2', _0: a, _1: b});
1750 });
1751var _elm_lang$core$Basics$flip = F3(
1752 function (f, b, a) {
1753 return A2(f, a, b);
1754 });
1755var _elm_lang$core$Basics$always = F2(
1756 function (a, _p4) {
1757 return a;
1758 });
1759var _elm_lang$core$Basics$identity = function (x) {
1760 return x;
1761};
1762var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1763_elm_lang$core$Basics_ops['<|'] = F2(
1764 function (f, x) {
1765 return f(x);
1766 });
1767var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1768_elm_lang$core$Basics_ops['|>'] = F2(
1769 function (x, f) {
1770 return f(x);
1771 });
1772var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1773_elm_lang$core$Basics_ops['>>'] = F3(
1774 function (f, g, x) {
1775 return g(
1776 f(x));
1777 });
1778var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1779_elm_lang$core$Basics_ops['<<'] = F3(
1780 function (g, f, x) {
1781 return g(
1782 f(x));
1783 });
1784var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1785_elm_lang$core$Basics_ops['++'] = _elm_lang$core$Native_Utils.append;
1786var _elm_lang$core$Basics$toString = _elm_lang$core$Native_Utils.toString;
1787var _elm_lang$core$Basics$isInfinite = _elm_lang$core$Native_Basics.isInfinite;
1788var _elm_lang$core$Basics$isNaN = _elm_lang$core$Native_Basics.isNaN;
1789var _elm_lang$core$Basics$toFloat = _elm_lang$core$Native_Basics.toFloat;
1790var _elm_lang$core$Basics$ceiling = _elm_lang$core$Native_Basics.ceiling;
1791var _elm_lang$core$Basics$floor = _elm_lang$core$Native_Basics.floor;
1792var _elm_lang$core$Basics$truncate = _elm_lang$core$Native_Basics.truncate;
1793var _elm_lang$core$Basics$round = _elm_lang$core$Native_Basics.round;
1794var _elm_lang$core$Basics$not = _elm_lang$core$Native_Basics.not;
1795var _elm_lang$core$Basics$xor = _elm_lang$core$Native_Basics.xor;
1796var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1797_elm_lang$core$Basics_ops['||'] = _elm_lang$core$Native_Basics.or;
1798var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1799_elm_lang$core$Basics_ops['&&'] = _elm_lang$core$Native_Basics.and;
1800var _elm_lang$core$Basics$max = _elm_lang$core$Native_Basics.max;
1801var _elm_lang$core$Basics$min = _elm_lang$core$Native_Basics.min;
1802var _elm_lang$core$Basics$compare = _elm_lang$core$Native_Basics.compare;
1803var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1804_elm_lang$core$Basics_ops['>='] = _elm_lang$core$Native_Basics.ge;
1805var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1806_elm_lang$core$Basics_ops['<='] = _elm_lang$core$Native_Basics.le;
1807var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1808_elm_lang$core$Basics_ops['>'] = _elm_lang$core$Native_Basics.gt;
1809var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1810_elm_lang$core$Basics_ops['<'] = _elm_lang$core$Native_Basics.lt;
1811var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1812_elm_lang$core$Basics_ops['/='] = _elm_lang$core$Native_Basics.neq;
1813var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1814_elm_lang$core$Basics_ops['=='] = _elm_lang$core$Native_Basics.eq;
1815var _elm_lang$core$Basics$e = _elm_lang$core$Native_Basics.e;
1816var _elm_lang$core$Basics$pi = _elm_lang$core$Native_Basics.pi;
1817var _elm_lang$core$Basics$clamp = _elm_lang$core$Native_Basics.clamp;
1818var _elm_lang$core$Basics$logBase = _elm_lang$core$Native_Basics.logBase;
1819var _elm_lang$core$Basics$abs = _elm_lang$core$Native_Basics.abs;
1820var _elm_lang$core$Basics$negate = _elm_lang$core$Native_Basics.negate;
1821var _elm_lang$core$Basics$sqrt = _elm_lang$core$Native_Basics.sqrt;
1822var _elm_lang$core$Basics$atan2 = _elm_lang$core$Native_Basics.atan2;
1823var _elm_lang$core$Basics$atan = _elm_lang$core$Native_Basics.atan;
1824var _elm_lang$core$Basics$asin = _elm_lang$core$Native_Basics.asin;
1825var _elm_lang$core$Basics$acos = _elm_lang$core$Native_Basics.acos;
1826var _elm_lang$core$Basics$tan = _elm_lang$core$Native_Basics.tan;
1827var _elm_lang$core$Basics$sin = _elm_lang$core$Native_Basics.sin;
1828var _elm_lang$core$Basics$cos = _elm_lang$core$Native_Basics.cos;
1829var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1830_elm_lang$core$Basics_ops['^'] = _elm_lang$core$Native_Basics.exp;
1831var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1832_elm_lang$core$Basics_ops['%'] = _elm_lang$core$Native_Basics.mod;
1833var _elm_lang$core$Basics$rem = _elm_lang$core$Native_Basics.rem;
1834var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1835_elm_lang$core$Basics_ops['//'] = _elm_lang$core$Native_Basics.div;
1836var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1837_elm_lang$core$Basics_ops['/'] = _elm_lang$core$Native_Basics.floatDiv;
1838var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1839_elm_lang$core$Basics_ops['*'] = _elm_lang$core$Native_Basics.mul;
1840var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1841_elm_lang$core$Basics_ops['-'] = _elm_lang$core$Native_Basics.sub;
1842var _elm_lang$core$Basics_ops = _elm_lang$core$Basics_ops || {};
1843_elm_lang$core$Basics_ops['+'] = _elm_lang$core$Native_Basics.add;
1844var _elm_lang$core$Basics$toPolar = _elm_lang$core$Native_Basics.toPolar;
1845var _elm_lang$core$Basics$fromPolar = _elm_lang$core$Native_Basics.fromPolar;
1846var _elm_lang$core$Basics$turns = _elm_lang$core$Native_Basics.turns;
1847var _elm_lang$core$Basics$degrees = _elm_lang$core$Native_Basics.degrees;
1848var _elm_lang$core$Basics$radians = function (t) {
1849 return t;
1850};
1851var _elm_lang$core$Basics$GT = {ctor: 'GT'};
1852var _elm_lang$core$Basics$EQ = {ctor: 'EQ'};
1853var _elm_lang$core$Basics$LT = {ctor: 'LT'};
1854var _elm_lang$core$Basics$JustOneMore = function (a) {
1855 return {ctor: 'JustOneMore', _0: a};
1856};
1857var _elm_lang$core$Maybe$withDefault = F2(
1858 function ($default, maybe) {
1859 var _p0 = maybe;
1860 if (_p0.ctor === 'Just') {
1861 return _p0._0;
1862 } else {
1863 return $default;
1864 }
1865 });
1866var _elm_lang$core$Maybe$Nothing = {ctor: 'Nothing'};
1867var _elm_lang$core$Maybe$andThen = F2(
1868 function (callback, maybeValue) {
1869 var _p1 = maybeValue;
1870 if (_p1.ctor === 'Just') {
1871 return callback(_p1._0);
1872 } else {
1873 return _elm_lang$core$Maybe$Nothing;
1874 }
1875 });
1876var _elm_lang$core$Maybe$Just = function (a) {
1877 return {ctor: 'Just', _0: a};
1878};
1879var _elm_lang$core$Maybe$map = F2(
1880 function (f, maybe) {
1881 var _p2 = maybe;
1882 if (_p2.ctor === 'Just') {
1883 return _elm_lang$core$Maybe$Just(
1884 f(_p2._0));
1885 } else {
1886 return _elm_lang$core$Maybe$Nothing;
1887 }
1888 });
1889var _elm_lang$core$Maybe$map2 = F3(
1890 function (func, ma, mb) {
1891 var _p3 = {ctor: '_Tuple2', _0: ma, _1: mb};
1892 if (((_p3.ctor === '_Tuple2') && (_p3._0.ctor === 'Just')) && (_p3._1.ctor === 'Just')) {
1893 return _elm_lang$core$Maybe$Just(
1894 A2(func, _p3._0._0, _p3._1._0));
1895 } else {
1896 return _elm_lang$core$Maybe$Nothing;
1897 }
1898 });
1899var _elm_lang$core$Maybe$map3 = F4(
1900 function (func, ma, mb, mc) {
1901 var _p4 = {ctor: '_Tuple3', _0: ma, _1: mb, _2: mc};
1902 if ((((_p4.ctor === '_Tuple3') && (_p4._0.ctor === 'Just')) && (_p4._1.ctor === 'Just')) && (_p4._2.ctor === 'Just')) {
1903 return _elm_lang$core$Maybe$Just(
1904 A3(func, _p4._0._0, _p4._1._0, _p4._2._0));
1905 } else {
1906 return _elm_lang$core$Maybe$Nothing;
1907 }
1908 });
1909var _elm_lang$core$Maybe$map4 = F5(
1910 function (func, ma, mb, mc, md) {
1911 var _p5 = {ctor: '_Tuple4', _0: ma, _1: mb, _2: mc, _3: md};
1912 if (((((_p5.ctor === '_Tuple4') && (_p5._0.ctor === 'Just')) && (_p5._1.ctor === 'Just')) && (_p5._2.ctor === 'Just')) && (_p5._3.ctor === 'Just')) {
1913 return _elm_lang$core$Maybe$Just(
1914 A4(func, _p5._0._0, _p5._1._0, _p5._2._0, _p5._3._0));
1915 } else {
1916 return _elm_lang$core$Maybe$Nothing;
1917 }
1918 });
1919var _elm_lang$core$Maybe$map5 = F6(
1920 function (func, ma, mb, mc, md, me) {
1921 var _p6 = {ctor: '_Tuple5', _0: ma, _1: mb, _2: mc, _3: md, _4: me};
1922 if ((((((_p6.ctor === '_Tuple5') && (_p6._0.ctor === 'Just')) && (_p6._1.ctor === 'Just')) && (_p6._2.ctor === 'Just')) && (_p6._3.ctor === 'Just')) && (_p6._4.ctor === 'Just')) {
1923 return _elm_lang$core$Maybe$Just(
1924 A5(func, _p6._0._0, _p6._1._0, _p6._2._0, _p6._3._0, _p6._4._0));
1925 } else {
1926 return _elm_lang$core$Maybe$Nothing;
1927 }
1928 });
1929//import Native.Utils //
1930
1931var _elm_lang$core$Native_List = function() {
1932
1933var Nil = { ctor: '[]' };
1934
1935function Cons(hd, tl)
1936{
1937 return { ctor: '::', _0: hd, _1: tl };
1938}
1939
1940function fromArray(arr)
1941{
1942 var out = Nil;
1943 for (var i = arr.length; i--; )
1944 {
1945 out = Cons(arr[i], out);
1946 }
1947 return out;
1948}
1949
1950function toArray(xs)
1951{
1952 var out = [];
1953 while (xs.ctor !== '[]')
1954 {
1955 out.push(xs._0);
1956 xs = xs._1;
1957 }
1958 return out;
1959}
1960
1961function foldr(f, b, xs)
1962{
1963 var arr = toArray(xs);
1964 var acc = b;
1965 for (var i = arr.length; i--; )
1966 {
1967 acc = A2(f, arr[i], acc);
1968 }
1969 return acc;
1970}
1971
1972function map2(f, xs, ys)
1973{
1974 var arr = [];
1975 while (xs.ctor !== '[]' && ys.ctor !== '[]')
1976 {
1977 arr.push(A2(f, xs._0, ys._0));
1978 xs = xs._1;
1979 ys = ys._1;
1980 }
1981 return fromArray(arr);
1982}
1983
1984function map3(f, xs, ys, zs)
1985{
1986 var arr = [];
1987 while (xs.ctor !== '[]' && ys.ctor !== '[]' && zs.ctor !== '[]')
1988 {
1989 arr.push(A3(f, xs._0, ys._0, zs._0));
1990 xs = xs._1;
1991 ys = ys._1;
1992 zs = zs._1;
1993 }
1994 return fromArray(arr);
1995}
1996
1997function map4(f, ws, xs, ys, zs)
1998{
1999 var arr = [];
2000 while ( ws.ctor !== '[]'
2001 && xs.ctor !== '[]'
2002 && ys.ctor !== '[]'
2003 && zs.ctor !== '[]')
2004 {
2005 arr.push(A4(f, ws._0, xs._0, ys._0, zs._0));
2006 ws = ws._1;
2007 xs = xs._1;
2008 ys = ys._1;
2009 zs = zs._1;
2010 }
2011 return fromArray(arr);
2012}
2013
2014function map5(f, vs, ws, xs, ys, zs)
2015{
2016 var arr = [];
2017 while ( vs.ctor !== '[]'
2018 && ws.ctor !== '[]'
2019 && xs.ctor !== '[]'
2020 && ys.ctor !== '[]'
2021 && zs.ctor !== '[]')
2022 {
2023 arr.push(A5(f, vs._0, ws._0, xs._0, ys._0, zs._0));
2024 vs = vs._1;
2025 ws = ws._1;
2026 xs = xs._1;
2027 ys = ys._1;
2028 zs = zs._1;
2029 }
2030 return fromArray(arr);
2031}
2032
2033function sortBy(f, xs)
2034{
2035 return fromArray(toArray(xs).sort(function(a, b) {
2036 return _elm_lang$core$Native_Utils.cmp(f(a), f(b));
2037 }));
2038}
2039
2040function sortWith(f, xs)
2041{
2042 return fromArray(toArray(xs).sort(function(a, b) {
2043 var ord = f(a)(b).ctor;
2044 return ord === 'EQ' ? 0 : ord === 'LT' ? -1 : 1;
2045 }));
2046}
2047
2048return {
2049 Nil: Nil,
2050 Cons: Cons,
2051 cons: F2(Cons),
2052 toArray: toArray,
2053 fromArray: fromArray,
2054
2055 foldr: F3(foldr),
2056
2057 map2: F3(map2),
2058 map3: F4(map3),
2059 map4: F5(map4),
2060 map5: F6(map5),
2061 sortBy: F2(sortBy),
2062 sortWith: F2(sortWith)
2063};
2064
2065}();var _elm_lang$core$List$sortWith = _elm_lang$core$Native_List.sortWith;
2066var _elm_lang$core$List$sortBy = _elm_lang$core$Native_List.sortBy;
2067var _elm_lang$core$List$sort = function (xs) {
2068 return A2(_elm_lang$core$List$sortBy, _elm_lang$core$Basics$identity, xs);
2069};
2070var _elm_lang$core$List$singleton = function (value) {
2071 return {
2072 ctor: '::',
2073 _0: value,
2074 _1: {ctor: '[]'}
2075 };
2076};
2077var _elm_lang$core$List$drop = F2(
2078 function (n, list) {
2079 drop:
2080 while (true) {
2081 if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) {
2082 return list;
2083 } else {
2084 var _p0 = list;
2085 if (_p0.ctor === '[]') {
2086 return list;
2087 } else {
2088 var _v1 = n - 1,
2089 _v2 = _p0._1;
2090 n = _v1;
2091 list = _v2;
2092 continue drop;
2093 }
2094 }
2095 }
2096 });
2097var _elm_lang$core$List$map5 = _elm_lang$core$Native_List.map5;
2098var _elm_lang$core$List$map4 = _elm_lang$core$Native_List.map4;
2099var _elm_lang$core$List$map3 = _elm_lang$core$Native_List.map3;
2100var _elm_lang$core$List$map2 = _elm_lang$core$Native_List.map2;
2101var _elm_lang$core$List$any = F2(
2102 function (isOkay, list) {
2103 any:
2104 while (true) {
2105 var _p1 = list;
2106 if (_p1.ctor === '[]') {
2107 return false;
2108 } else {
2109 if (isOkay(_p1._0)) {
2110 return true;
2111 } else {
2112 var _v4 = isOkay,
2113 _v5 = _p1._1;
2114 isOkay = _v4;
2115 list = _v5;
2116 continue any;
2117 }
2118 }
2119 }
2120 });
2121var _elm_lang$core$List$all = F2(
2122 function (isOkay, list) {
2123 return !A2(
2124 _elm_lang$core$List$any,
2125 function (_p2) {
2126 return !isOkay(_p2);
2127 },
2128 list);
2129 });
2130var _elm_lang$core$List$foldr = _elm_lang$core$Native_List.foldr;
2131var _elm_lang$core$List$foldl = F3(
2132 function (func, acc, list) {
2133 foldl:
2134 while (true) {
2135 var _p3 = list;
2136 if (_p3.ctor === '[]') {
2137 return acc;
2138 } else {
2139 var _v7 = func,
2140 _v8 = A2(func, _p3._0, acc),
2141 _v9 = _p3._1;
2142 func = _v7;
2143 acc = _v8;
2144 list = _v9;
2145 continue foldl;
2146 }
2147 }
2148 });
2149var _elm_lang$core$List$length = function (xs) {
2150 return A3(
2151 _elm_lang$core$List$foldl,
2152 F2(
2153 function (_p4, i) {
2154 return i + 1;
2155 }),
2156 0,
2157 xs);
2158};
2159var _elm_lang$core$List$sum = function (numbers) {
2160 return A3(
2161 _elm_lang$core$List$foldl,
2162 F2(
2163 function (x, y) {
2164 return x + y;
2165 }),
2166 0,
2167 numbers);
2168};
2169var _elm_lang$core$List$product = function (numbers) {
2170 return A3(
2171 _elm_lang$core$List$foldl,
2172 F2(
2173 function (x, y) {
2174 return x * y;
2175 }),
2176 1,
2177 numbers);
2178};
2179var _elm_lang$core$List$maximum = function (list) {
2180 var _p5 = list;
2181 if (_p5.ctor === '::') {
2182 return _elm_lang$core$Maybe$Just(
2183 A3(_elm_lang$core$List$foldl, _elm_lang$core$Basics$max, _p5._0, _p5._1));
2184 } else {
2185 return _elm_lang$core$Maybe$Nothing;
2186 }
2187};
2188var _elm_lang$core$List$minimum = function (list) {
2189 var _p6 = list;
2190 if (_p6.ctor === '::') {
2191 return _elm_lang$core$Maybe$Just(
2192 A3(_elm_lang$core$List$foldl, _elm_lang$core$Basics$min, _p6._0, _p6._1));
2193 } else {
2194 return _elm_lang$core$Maybe$Nothing;
2195 }
2196};
2197var _elm_lang$core$List$member = F2(
2198 function (x, xs) {
2199 return A2(
2200 _elm_lang$core$List$any,
2201 function (a) {
2202 return _elm_lang$core$Native_Utils.eq(a, x);
2203 },
2204 xs);
2205 });
2206var _elm_lang$core$List$isEmpty = function (xs) {
2207 var _p7 = xs;
2208 if (_p7.ctor === '[]') {
2209 return true;
2210 } else {
2211 return false;
2212 }
2213};
2214var _elm_lang$core$List$tail = function (list) {
2215 var _p8 = list;
2216 if (_p8.ctor === '::') {
2217 return _elm_lang$core$Maybe$Just(_p8._1);
2218 } else {
2219 return _elm_lang$core$Maybe$Nothing;
2220 }
2221};
2222var _elm_lang$core$List$head = function (list) {
2223 var _p9 = list;
2224 if (_p9.ctor === '::') {
2225 return _elm_lang$core$Maybe$Just(_p9._0);
2226 } else {
2227 return _elm_lang$core$Maybe$Nothing;
2228 }
2229};
2230var _elm_lang$core$List_ops = _elm_lang$core$List_ops || {};
2231_elm_lang$core$List_ops['::'] = _elm_lang$core$Native_List.cons;
2232var _elm_lang$core$List$map = F2(
2233 function (f, xs) {
2234 return A3(
2235 _elm_lang$core$List$foldr,
2236 F2(
2237 function (x, acc) {
2238 return {
2239 ctor: '::',
2240 _0: f(x),
2241 _1: acc
2242 };
2243 }),
2244 {ctor: '[]'},
2245 xs);
2246 });
2247var _elm_lang$core$List$filter = F2(
2248 function (pred, xs) {
2249 var conditionalCons = F2(
2250 function (front, back) {
2251 return pred(front) ? {ctor: '::', _0: front, _1: back} : back;
2252 });
2253 return A3(
2254 _elm_lang$core$List$foldr,
2255 conditionalCons,
2256 {ctor: '[]'},
2257 xs);
2258 });
2259var _elm_lang$core$List$maybeCons = F3(
2260 function (f, mx, xs) {
2261 var _p10 = f(mx);
2262 if (_p10.ctor === 'Just') {
2263 return {ctor: '::', _0: _p10._0, _1: xs};
2264 } else {
2265 return xs;
2266 }
2267 });
2268var _elm_lang$core$List$filterMap = F2(
2269 function (f, xs) {
2270 return A3(
2271 _elm_lang$core$List$foldr,
2272 _elm_lang$core$List$maybeCons(f),
2273 {ctor: '[]'},
2274 xs);
2275 });
2276var _elm_lang$core$List$reverse = function (list) {
2277 return A3(
2278 _elm_lang$core$List$foldl,
2279 F2(
2280 function (x, y) {
2281 return {ctor: '::', _0: x, _1: y};
2282 }),
2283 {ctor: '[]'},
2284 list);
2285};
2286var _elm_lang$core$List$scanl = F3(
2287 function (f, b, xs) {
2288 var scan1 = F2(
2289 function (x, accAcc) {
2290 var _p11 = accAcc;
2291 if (_p11.ctor === '::') {
2292 return {
2293 ctor: '::',
2294 _0: A2(f, x, _p11._0),
2295 _1: accAcc
2296 };
2297 } else {
2298 return {ctor: '[]'};
2299 }
2300 });
2301 return _elm_lang$core$List$reverse(
2302 A3(
2303 _elm_lang$core$List$foldl,
2304 scan1,
2305 {
2306 ctor: '::',
2307 _0: b,
2308 _1: {ctor: '[]'}
2309 },
2310 xs));
2311 });
2312var _elm_lang$core$List$append = F2(
2313 function (xs, ys) {
2314 var _p12 = ys;
2315 if (_p12.ctor === '[]') {
2316 return xs;
2317 } else {
2318 return A3(
2319 _elm_lang$core$List$foldr,
2320 F2(
2321 function (x, y) {
2322 return {ctor: '::', _0: x, _1: y};
2323 }),
2324 ys,
2325 xs);
2326 }
2327 });
2328var _elm_lang$core$List$concat = function (lists) {
2329 return A3(
2330 _elm_lang$core$List$foldr,
2331 _elm_lang$core$List$append,
2332 {ctor: '[]'},
2333 lists);
2334};
2335var _elm_lang$core$List$concatMap = F2(
2336 function (f, list) {
2337 return _elm_lang$core$List$concat(
2338 A2(_elm_lang$core$List$map, f, list));
2339 });
2340var _elm_lang$core$List$partition = F2(
2341 function (pred, list) {
2342 var step = F2(
2343 function (x, _p13) {
2344 var _p14 = _p13;
2345 var _p16 = _p14._0;
2346 var _p15 = _p14._1;
2347 return pred(x) ? {
2348 ctor: '_Tuple2',
2349 _0: {ctor: '::', _0: x, _1: _p16},
2350 _1: _p15
2351 } : {
2352 ctor: '_Tuple2',
2353 _0: _p16,
2354 _1: {ctor: '::', _0: x, _1: _p15}
2355 };
2356 });
2357 return A3(
2358 _elm_lang$core$List$foldr,
2359 step,
2360 {
2361 ctor: '_Tuple2',
2362 _0: {ctor: '[]'},
2363 _1: {ctor: '[]'}
2364 },
2365 list);
2366 });
2367var _elm_lang$core$List$unzip = function (pairs) {
2368 var step = F2(
2369 function (_p18, _p17) {
2370 var _p19 = _p18;
2371 var _p20 = _p17;
2372 return {
2373 ctor: '_Tuple2',
2374 _0: {ctor: '::', _0: _p19._0, _1: _p20._0},
2375 _1: {ctor: '::', _0: _p19._1, _1: _p20._1}
2376 };
2377 });
2378 return A3(
2379 _elm_lang$core$List$foldr,
2380 step,
2381 {
2382 ctor: '_Tuple2',
2383 _0: {ctor: '[]'},
2384 _1: {ctor: '[]'}
2385 },
2386 pairs);
2387};
2388var _elm_lang$core$List$intersperse = F2(
2389 function (sep, xs) {
2390 var _p21 = xs;
2391 if (_p21.ctor === '[]') {
2392 return {ctor: '[]'};
2393 } else {
2394 var step = F2(
2395 function (x, rest) {
2396 return {
2397 ctor: '::',
2398 _0: sep,
2399 _1: {ctor: '::', _0: x, _1: rest}
2400 };
2401 });
2402 var spersed = A3(
2403 _elm_lang$core$List$foldr,
2404 step,
2405 {ctor: '[]'},
2406 _p21._1);
2407 return {ctor: '::', _0: _p21._0, _1: spersed};
2408 }
2409 });
2410var _elm_lang$core$List$takeReverse = F3(
2411 function (n, list, taken) {
2412 takeReverse:
2413 while (true) {
2414 if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) {
2415 return taken;
2416 } else {
2417 var _p22 = list;
2418 if (_p22.ctor === '[]') {
2419 return taken;
2420 } else {
2421 var _v23 = n - 1,
2422 _v24 = _p22._1,
2423 _v25 = {ctor: '::', _0: _p22._0, _1: taken};
2424 n = _v23;
2425 list = _v24;
2426 taken = _v25;
2427 continue takeReverse;
2428 }
2429 }
2430 }
2431 });
2432var _elm_lang$core$List$takeTailRec = F2(
2433 function (n, list) {
2434 return _elm_lang$core$List$reverse(
2435 A3(
2436 _elm_lang$core$List$takeReverse,
2437 n,
2438 list,
2439 {ctor: '[]'}));
2440 });
2441var _elm_lang$core$List$takeFast = F3(
2442 function (ctr, n, list) {
2443 if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) {
2444 return {ctor: '[]'};
2445 } else {
2446 var _p23 = {ctor: '_Tuple2', _0: n, _1: list};
2447 _v26_5:
2448 do {
2449 _v26_1:
2450 do {
2451 if (_p23.ctor === '_Tuple2') {
2452 if (_p23._1.ctor === '[]') {
2453 return list;
2454 } else {
2455 if (_p23._1._1.ctor === '::') {
2456 switch (_p23._0) {
2457 case 1:
2458 break _v26_1;
2459 case 2:
2460 return {
2461 ctor: '::',
2462 _0: _p23._1._0,
2463 _1: {
2464 ctor: '::',
2465 _0: _p23._1._1._0,
2466 _1: {ctor: '[]'}
2467 }
2468 };
2469 case 3:
2470 if (_p23._1._1._1.ctor === '::') {
2471 return {
2472 ctor: '::',
2473 _0: _p23._1._0,
2474 _1: {
2475 ctor: '::',
2476 _0: _p23._1._1._0,
2477 _1: {
2478 ctor: '::',
2479 _0: _p23._1._1._1._0,
2480 _1: {ctor: '[]'}
2481 }
2482 }
2483 };
2484 } else {
2485 break _v26_5;
2486 }
2487 default:
2488 if ((_p23._1._1._1.ctor === '::') && (_p23._1._1._1._1.ctor === '::')) {
2489 var _p28 = _p23._1._1._1._0;
2490 var _p27 = _p23._1._1._0;
2491 var _p26 = _p23._1._0;
2492 var _p25 = _p23._1._1._1._1._0;
2493 var _p24 = _p23._1._1._1._1._1;
2494 return (_elm_lang$core$Native_Utils.cmp(ctr, 1000) > 0) ? {
2495 ctor: '::',
2496 _0: _p26,
2497 _1: {
2498 ctor: '::',
2499 _0: _p27,
2500 _1: {
2501 ctor: '::',
2502 _0: _p28,
2503 _1: {
2504 ctor: '::',
2505 _0: _p25,
2506 _1: A2(_elm_lang$core$List$takeTailRec, n - 4, _p24)
2507 }
2508 }
2509 }
2510 } : {
2511 ctor: '::',
2512 _0: _p26,
2513 _1: {
2514 ctor: '::',
2515 _0: _p27,
2516 _1: {
2517 ctor: '::',
2518 _0: _p28,
2519 _1: {
2520 ctor: '::',
2521 _0: _p25,
2522 _1: A3(_elm_lang$core$List$takeFast, ctr + 1, n - 4, _p24)
2523 }
2524 }
2525 }
2526 };
2527 } else {
2528 break _v26_5;
2529 }
2530 }
2531 } else {
2532 if (_p23._0 === 1) {
2533 break _v26_1;
2534 } else {
2535 break _v26_5;
2536 }
2537 }
2538 }
2539 } else {
2540 break _v26_5;
2541 }
2542 } while(false);
2543 return {
2544 ctor: '::',
2545 _0: _p23._1._0,
2546 _1: {ctor: '[]'}
2547 };
2548 } while(false);
2549 return list;
2550 }
2551 });
2552var _elm_lang$core$List$take = F2(
2553 function (n, list) {
2554 return A3(_elm_lang$core$List$takeFast, 0, n, list);
2555 });
2556var _elm_lang$core$List$repeatHelp = F3(
2557 function (result, n, value) {
2558 repeatHelp:
2559 while (true) {
2560 if (_elm_lang$core$Native_Utils.cmp(n, 0) < 1) {
2561 return result;
2562 } else {
2563 var _v27 = {ctor: '::', _0: value, _1: result},
2564 _v28 = n - 1,
2565 _v29 = value;
2566 result = _v27;
2567 n = _v28;
2568 value = _v29;
2569 continue repeatHelp;
2570 }
2571 }
2572 });
2573var _elm_lang$core$List$repeat = F2(
2574 function (n, value) {
2575 return A3(
2576 _elm_lang$core$List$repeatHelp,
2577 {ctor: '[]'},
2578 n,
2579 value);
2580 });
2581var _elm_lang$core$List$rangeHelp = F3(
2582 function (lo, hi, list) {
2583 rangeHelp:
2584 while (true) {
2585 if (_elm_lang$core$Native_Utils.cmp(lo, hi) < 1) {
2586 var _v30 = lo,
2587 _v31 = hi - 1,
2588 _v32 = {ctor: '::', _0: hi, _1: list};
2589 lo = _v30;
2590 hi = _v31;
2591 list = _v32;
2592 continue rangeHelp;
2593 } else {
2594 return list;
2595 }
2596 }
2597 });
2598var _elm_lang$core$List$range = F2(
2599 function (lo, hi) {
2600 return A3(
2601 _elm_lang$core$List$rangeHelp,
2602 lo,
2603 hi,
2604 {ctor: '[]'});
2605 });
2606var _elm_lang$core$List$indexedMap = F2(
2607 function (f, xs) {
2608 return A3(
2609 _elm_lang$core$List$map2,
2610 f,
2611 A2(
2612 _elm_lang$core$List$range,
2613 0,
2614 _elm_lang$core$List$length(xs) - 1),
2615 xs);
2616 });
2617var _elm_lang$core$Array$append = _elm_lang$core$Native_Array.append;
2618var _elm_lang$core$Array$length = _elm_lang$core$Native_Array.length;
2619var _elm_lang$core$Array$isEmpty = function (array) {
2620 return _elm_lang$core$Native_Utils.eq(
2621 _elm_lang$core$Array$length(array),
2622 0);
2623};
2624var _elm_lang$core$Array$slice = _elm_lang$core$Native_Array.slice;
2625var _elm_lang$core$Array$set = _elm_lang$core$Native_Array.set;
2626var _elm_lang$core$Array$get = F2(
2627 function (i, array) {
2628 return ((_elm_lang$core$Native_Utils.cmp(0, i) < 1) && (_elm_lang$core$Native_Utils.cmp(
2629 i,
2630 _elm_lang$core$Native_Array.length(array)) < 0)) ? _elm_lang$core$Maybe$Just(
2631 A2(_elm_lang$core$Native_Array.get, i, array)) : _elm_lang$core$Maybe$Nothing;
2632 });
2633var _elm_lang$core$Array$push = _elm_lang$core$Native_Array.push;
2634var _elm_lang$core$Array$empty = _elm_lang$core$Native_Array.empty;
2635var _elm_lang$core$Array$filter = F2(
2636 function (isOkay, arr) {
2637 var update = F2(
2638 function (x, xs) {
2639 return isOkay(x) ? A2(_elm_lang$core$Native_Array.push, x, xs) : xs;
2640 });
2641 return A3(_elm_lang$core$Native_Array.foldl, update, _elm_lang$core$Native_Array.empty, arr);
2642 });
2643var _elm_lang$core$Array$foldr = _elm_lang$core$Native_Array.foldr;
2644var _elm_lang$core$Array$foldl = _elm_lang$core$Native_Array.foldl;
2645var _elm_lang$core$Array$indexedMap = _elm_lang$core$Native_Array.indexedMap;
2646var _elm_lang$core$Array$map = _elm_lang$core$Native_Array.map;
2647var _elm_lang$core$Array$toIndexedList = function (array) {
2648 return A3(
2649 _elm_lang$core$List$map2,
2650 F2(
2651 function (v0, v1) {
2652 return {ctor: '_Tuple2', _0: v0, _1: v1};
2653 }),
2654 A2(
2655 _elm_lang$core$List$range,
2656 0,
2657 _elm_lang$core$Native_Array.length(array) - 1),
2658 _elm_lang$core$Native_Array.toList(array));
2659};
2660var _elm_lang$core$Array$toList = _elm_lang$core$Native_Array.toList;
2661var _elm_lang$core$Array$fromList = _elm_lang$core$Native_Array.fromList;
2662var _elm_lang$core$Array$initialize = _elm_lang$core$Native_Array.initialize;
2663var _elm_lang$core$Array$repeat = F2(
2664 function (n, e) {
2665 return A2(
2666 _elm_lang$core$Array$initialize,
2667 n,
2668 _elm_lang$core$Basics$always(e));
2669 });
2670var _elm_lang$core$Array$Array = {ctor: 'Array'};
2671//import Native.Utils //
2672
2673var _elm_lang$core$Native_Debug = function() {
2674
2675function log(tag, value)
2676{
2677 var msg = tag + ': ' + _elm_lang$core$Native_Utils.toString(value);
2678 var process = process || {};
2679 if (process.stdout)
2680 {
2681 process.stdout.write(msg);
2682 }
2683 else
2684 {
2685 console.log(msg);
2686 }
2687 return value;
2688}
2689
2690function crash(message)
2691{
2692 throw new Error(message);
2693}
2694
2695return {
2696 crash: crash,
2697 log: F2(log)
2698};
2699
2700}();//import Maybe, Native.List, Native.Utils, Result //
2701
2702var _elm_lang$core$Native_String = function() {
2703
2704function isEmpty(str)
2705{
2706 return str.length === 0;
2707}
2708function cons(chr, str)
2709{
2710 return chr + str;
2711}
2712function uncons(str)
2713{
2714 var hd = str[0];
2715 if (hd)
2716 {
2717 return _elm_lang$core$Maybe$Just(_elm_lang$core$Native_Utils.Tuple2(_elm_lang$core$Native_Utils.chr(hd), str.slice(1)));
2718 }
2719 return _elm_lang$core$Maybe$Nothing;
2720}
2721function append(a, b)
2722{
2723 return a + b;
2724}
2725function concat(strs)
2726{
2727 return _elm_lang$core$Native_List.toArray(strs).join('');
2728}
2729function length(str)
2730{
2731 return str.length;
2732}
2733function map(f, str)
2734{
2735 var out = str.split('');
2736 for (var i = out.length; i--; )
2737 {
2738 out[i] = f(_elm_lang$core$Native_Utils.chr(out[i]));
2739 }
2740 return out.join('');
2741}
2742function filter(pred, str)
2743{
2744 return str.split('').map(_elm_lang$core$Native_Utils.chr).filter(pred).join('');
2745}
2746function reverse(str)
2747{
2748 return str.split('').reverse().join('');
2749}
2750function foldl(f, b, str)
2751{
2752 var len = str.length;
2753 for (var i = 0; i < len; ++i)
2754 {
2755 b = A2(f, _elm_lang$core$Native_Utils.chr(str[i]), b);
2756 }
2757 return b;
2758}
2759function foldr(f, b, str)
2760{
2761 for (var i = str.length; i--; )
2762 {
2763 b = A2(f, _elm_lang$core$Native_Utils.chr(str[i]), b);
2764 }
2765 return b;
2766}
2767function split(sep, str)
2768{
2769 return _elm_lang$core$Native_List.fromArray(str.split(sep));
2770}
2771function join(sep, strs)
2772{
2773 return _elm_lang$core$Native_List.toArray(strs).join(sep);
2774}
2775function repeat(n, str)
2776{
2777 var result = '';
2778 while (n > 0)
2779 {
2780 if (n & 1)
2781 {
2782 result += str;
2783 }
2784 n >>= 1, str += str;
2785 }
2786 return result;
2787}
2788function slice(start, end, str)
2789{
2790 return str.slice(start, end);
2791}
2792function left(n, str)
2793{
2794 return n < 1 ? '' : str.slice(0, n);
2795}
2796function right(n, str)
2797{
2798 return n < 1 ? '' : str.slice(-n);
2799}
2800function dropLeft(n, str)
2801{
2802 return n < 1 ? str : str.slice(n);
2803}
2804function dropRight(n, str)
2805{
2806 return n < 1 ? str : str.slice(0, -n);
2807}
2808function pad(n, chr, str)
2809{
2810 var half = (n - str.length) / 2;
2811 return repeat(Math.ceil(half), chr) + str + repeat(half | 0, chr);
2812}
2813function padRight(n, chr, str)
2814{
2815 return str + repeat(n - str.length, chr);
2816}
2817function padLeft(n, chr, str)
2818{
2819 return repeat(n - str.length, chr) + str;
2820}
2821
2822function trim(str)
2823{
2824 return str.trim();
2825}
2826function trimLeft(str)
2827{
2828 return str.replace(/^\s+/, '');
2829}
2830function trimRight(str)
2831{
2832 return str.replace(/\s+$/, '');
2833}
2834
2835function words(str)
2836{
2837 return _elm_lang$core$Native_List.fromArray(str.trim().split(/\s+/g));
2838}
2839function lines(str)
2840{
2841 return _elm_lang$core$Native_List.fromArray(str.split(/\r\n|\r|\n/g));
2842}
2843
2844function toUpper(str)
2845{
2846 return str.toUpperCase();
2847}
2848function toLower(str)
2849{
2850 return str.toLowerCase();
2851}
2852
2853function any(pred, str)
2854{
2855 for (var i = str.length; i--; )
2856 {
2857 if (pred(_elm_lang$core$Native_Utils.chr(str[i])))
2858 {
2859 return true;
2860 }
2861 }
2862 return false;
2863}
2864function all(pred, str)
2865{
2866 for (var i = str.length; i--; )
2867 {
2868 if (!pred(_elm_lang$core$Native_Utils.chr(str[i])))
2869 {
2870 return false;
2871 }
2872 }
2873 return true;
2874}
2875
2876function contains(sub, str)
2877{
2878 return str.indexOf(sub) > -1;
2879}
2880function startsWith(sub, str)
2881{
2882 return str.indexOf(sub) === 0;
2883}
2884function endsWith(sub, str)
2885{
2886 return str.length >= sub.length &&
2887 str.lastIndexOf(sub) === str.length - sub.length;
2888}
2889function indexes(sub, str)
2890{
2891 var subLen = sub.length;
2892
2893 if (subLen < 1)
2894 {
2895 return _elm_lang$core$Native_List.Nil;
2896 }
2897
2898 var i = 0;
2899 var is = [];
2900
2901 while ((i = str.indexOf(sub, i)) > -1)
2902 {
2903 is.push(i);
2904 i = i + subLen;
2905 }
2906
2907 return _elm_lang$core$Native_List.fromArray(is);
2908}
2909
2910
2911function toInt(s)
2912{
2913 var len = s.length;
2914
2915 // if empty
2916 if (len === 0)
2917 {
2918 return intErr(s);
2919 }
2920
2921 // if hex
2922 var c = s[0];
2923 if (c === '0' && s[1] === 'x')
2924 {
2925 for (var i = 2; i < len; ++i)
2926 {
2927 var c = s[i];
2928 if (('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'))
2929 {
2930 continue;
2931 }
2932 return intErr(s);
2933 }
2934 return _elm_lang$core$Result$Ok(parseInt(s, 16));
2935 }
2936
2937 // is decimal
2938 if (c > '9' || (c < '0' && c !== '-' && c !== '+'))
2939 {
2940 return intErr(s);
2941 }
2942 for (var i = 1; i < len; ++i)
2943 {
2944 var c = s[i];
2945 if (c < '0' || '9' < c)
2946 {
2947 return intErr(s);
2948 }
2949 }
2950
2951 return _elm_lang$core$Result$Ok(parseInt(s, 10));
2952}
2953
2954function intErr(s)
2955{
2956 return _elm_lang$core$Result$Err("could not convert string '" + s + "' to an Int");
2957}
2958
2959
2960function toFloat(s)
2961{
2962 // check if it is a hex, octal, or binary number
2963 if (s.length === 0 || /[\sxbo]/.test(s))
2964 {
2965 return floatErr(s);
2966 }
2967 var n = +s;
2968 // faster isNaN check
2969 return n === n ? _elm_lang$core$Result$Ok(n) : floatErr(s);
2970}
2971
2972function floatErr(s)
2973{
2974 return _elm_lang$core$Result$Err("could not convert string '" + s + "' to a Float");
2975}
2976
2977
2978function toList(str)
2979{
2980 return _elm_lang$core$Native_List.fromArray(str.split('').map(_elm_lang$core$Native_Utils.chr));
2981}
2982function fromList(chars)
2983{
2984 return _elm_lang$core$Native_List.toArray(chars).join('');
2985}
2986
2987return {
2988 isEmpty: isEmpty,
2989 cons: F2(cons),
2990 uncons: uncons,
2991 append: F2(append),
2992 concat: concat,
2993 length: length,
2994 map: F2(map),
2995 filter: F2(filter),
2996 reverse: reverse,
2997 foldl: F3(foldl),
2998 foldr: F3(foldr),
2999
3000 split: F2(split),
3001 join: F2(join),
3002 repeat: F2(repeat),
3003
3004 slice: F3(slice),