on master help sign in
Delete a whole bunch of old patches
commit9301f5524f4f337e0ceeffc8574080e3a09276fb authorMichael Snoyman <michael@snoyman.com> dateThu 28 Aug 2014, 09:38 (12 years ago) parent1ef4cea
67 files changed+12−18745
patching/patches/BiobaseTurner-0.3.1.1.patch−23 patching/patches/BlogLiterately-diagrams-0.1.4.2.patch−15 patching/patches/ChasingBottoms-1.3.0.7.patch−34 patching/patches/MFlow-0.4.5.4.patch−13157 patching/patches/MusicBrainz-0.2.1.patch−28 patching/patches/Octree-0.5.2.patch−19 patching/patches/Octree-0.5.3.patch−19 patching/patches/arbtt-0.8.1.patch−30 patching/patches/async-2.0.1.5.patch−40 patching/patches/authenticate-oauth-1.4.0.8.patch−147 patching/patches/aws-0.8.6.patch−596 patching/patches/aws-0.9.3.patch+12 patching/patches/bytes-0.14.0.1.patch−25 patching/patches/bzlib-conduit-0.2.1.1.patch−46 patching/patches/cereal-conduit-0.7.2.patch−53 patching/patches/concurrent-extra-0.7.0.6.patch−21 patching/patches/criterion-1.0.0.2.patch−1643 patching/patches/csv-conduit-0.6.2.1.patch−32 patching/patches/diagrams-builder-0.5.0.10.patch−12 patching/patches/diagrams-builder-0.5.0.6.patch−12 patching/patches/diagrams-builder-0.5.0.9.patch−12 patching/patches/diagrams-builder-0.6.patch−27 patching/patches/diagrams-haddock-0.2.2.10.patch−21 patching/patches/distributed-process-0.4.2.patch−96 patching/patches/distributed-process-simplelocalnet-0.2.0.9.patch−21 patching/patches/distributive-0.4.3.patch−11 patching/patches/esqueleto-1.3.8.patch−12 patching/patches/fay-0.19.0.2.patch−12 patching/patches/fb-1.0.1.patch−12 patching/patches/foldl-1.0.2.patch−12 patching/patches/force-layout-0.3.0.5.patch−12 patching/patches/github-0.7.4.patch−23 patching/patches/gitlib-3.0.2.patch−191 patching/patches/gitlib-cmdline-3.0.1.patch−43 patching/patches/gitlib-libgit2-3.0.1.patch−280 patching/patches/gitlib-s3-3.0.2.patch−276 patching/patches/gitlib-test-3.0.1.patch−11 patching/patches/haskell-names-0.3.2.6.patch−12 patching/patches/haskell-packages-0.2.3.3.patch−11 patching/patches/hdaemonize-0.4.5.0.patch−12 patching/patches/heist-0.13.0.6.patch−12 patching/patches/hint-0.4.2.0.patch−21 patching/patches/hoogle-4.2.32.patch−58 patching/patches/hweblib-0.6.1.patch−23 patching/patches/incremental-parser-0.2.3.2.patch−20 patching/patches/network-transport-tests-0.1.0.1.patch−12 patching/patches/primitive-0.5.3.0.patch−62 patching/patches/process-conduit-1.0.0.1.patch−12 patching/patches/process-conduit-1.0.0.2.patch−62 patching/patches/process-conduit-1.1.0.0.patch−21 patching/patches/retry-0.4.patch−12 patching/patches/retry-0.5.patch−19 patching/patches/scientific-0.2.0.1.patch−14 patching/patches/snap-0.13.2.2.patch−12 patching/patches/sqlite-simple-0.4.5.1.patch−12 patching/patches/statistics-0.10.5.2.patch−705 patching/patches/stm-conduit-2.3.0.patch−16 patching/patches/stm-conduit-2.5.1.patch−201 patching/patches/temporary-1.2.0.1.patch−12 patching/patches/temporary-1.2.0.2.patch−39 patching/patches/th-desugar-1.4.2.patch−20 patching/patches/threepenny-gui-0.4.1.0.patch−47 patching/patches/transformers-compat-0.3.3.4.patch−50 patching/patches/uniqueid-0.1.1.patch−100 patching/patches/websockets-0.8.2.0.patch−21 patching/patches/yesod-auth-fb-1.6.1.patch−77 patching/patches/yesod-auth-oauth-1.2.0.patch−26
patching/patches/BiobaseTurner-0.3.1.1.patchdeleted−23
@@ -1,23 +0,0 @@
1−diff -ru orig/Biobase/Turner/Import.hs new/Biobase/Turner/Import.hs
2−--- orig/Biobase/Turner/Import.hs 2014-04-03 10:53:56.310194793 +0300
3−+++ new/Biobase/Turner/Import.hs 2014-04-03 10:53:56.000000000 +0300
4−@@ -37,6 +37,7 @@
5− module Biobase.Turner.Import where
6−
7− import Control.Arrow
8−+import Control.Monad.Trans.Resource (runResourceT)
9− import Data.Array.Repa.Index
10− import Data.ByteString.Char8 as BS
11− import Data.ByteString.Lex.Double
12−diff -ru orig/BiobaseTurner.cabal new/BiobaseTurner.cabal
13−--- orig/BiobaseTurner.cabal 2014-04-03 10:53:56.310194793 +0300
14−+++ new/BiobaseTurner.cabal 2014-04-03 10:53:56.000000000 +0300
15−@@ -35,6 +35,8 @@
16− bytestring >= 0.9 ,
17− bytestring-lexing >= 0.4 ,
18− conduit >= 0.5 ,
19−+ conduit-extra >= 1.0 ,
20−+ resourcet >= 0.4 ,
21− containers >= 0.4 ,
22− filepath >= 1 ,
23− lens >= 3.8 ,
patching/patches/BlogLiterately-diagrams-0.1.4.2.patchdeleted−15
@@ -1,15 +0,0 @@
1−diff -ru orig/BlogLiterately-diagrams.cabal new/BlogLiterately-diagrams.cabal
2−--- orig/BlogLiterately-diagrams.cabal 2014-06-03 16:05:19.882144431 +0300
3−+++ new/BlogLiterately-diagrams.cabal 2014-06-03 16:05:19.000000000 +0300
4−@@ -79,9 +79,9 @@
5− containers,
6− filepath,
7− directory,
8−- diagrams-cairo >= 1.0.1 && < 1.2,
9−+ diagrams-cairo >= 1.0.1 && < 1.3,
10− diagrams-builder >= 0.5 && < 0.6,
11−- diagrams-lib >= 1.0.1 && < 1.2,
12−+ diagrams-lib >= 1.0.1 && < 1.3,
13− BlogLiterately >= 0.6 && < 0.8,
14− pandoc >= 1.9 && < 1.13,
15− safe ==0.3.*
patching/patches/ChasingBottoms-1.3.0.7.patchdeleted−34
@@ -1,34 +0,0 @@
1−diff -ru orig/ChasingBottoms.cabal new/ChasingBottoms.cabal
2−--- orig/ChasingBottoms.cabal 2014-06-10 13:09:03.210534172 +0300
3−+++ new/ChasingBottoms.cabal 2014-06-10 13:09:03.000000000 +0300
4−@@ -121,7 +121,7 @@
5−
6− other-modules: Test.ChasingBottoms.IsType
7−
8−- build-depends: QuickCheck >= 2.1 && < 2.7,
9−+ build-depends: QuickCheck >= 2.1 && < 2.8,
10− mtl >= 1.1 && < 2.2,
11− base >= 4.0 && < 4.8,
12− containers >= 0.3 && < 0.6,
13−@@ -150,7 +150,7 @@
14− Test.ChasingBottoms.TestUtilities.Generators,
15− Test.ChasingBottoms.TimeOut.Tests
16−
17−- build-depends: QuickCheck >= 2.1 && < 2.7,
18−+ build-depends: QuickCheck >= 2.1 && < 2.8,
19− mtl >= 1.1 && < 2.2,
20− base >= 4.0 && < 4.8,
21− containers >= 0.3 && < 0.6,
22−diff -ru orig/Test/ChasingBottoms/ContinuousFunctions.hs new/Test/ChasingBottoms/ContinuousFunctions.hs
23−--- orig/Test/ChasingBottoms/ContinuousFunctions.hs 2014-06-10 13:09:03.202534172 +0300
24−+++ new/Test/ChasingBottoms/ContinuousFunctions.hs 2014-06-10 13:09:03.000000000 +0300
25−@@ -143,7 +143,8 @@
26− , listOf
27− ) where
28−
29−-import Test.QuickCheck hiding ((><), listOf)
30−+import Test.QuickCheck hiding ((><), listOf, infiniteListOf)
31−+import Test.QuickCheck.Gen.Unsafe (promote)
32− import Data.Sequence as Seq
33− import Data.Foldable as Seq (foldr)
34− import Prelude as P hiding (concat)
patching/patches/MFlow-0.4.5.4.patchdeleted−13157
@@ -1,13157 +0,0 @@
1−diff -ru orig/MFlow.cabal new/MFlow.cabal
2−--- orig/MFlow.cabal 2014-06-10 05:51:27.009015855 +0300
3−+++ new/MFlow.cabal 2014-06-10 05:51:25.000000000 +0300
4−@@ -105,10 +105,10 @@
5− extensible-exceptions , base >4.0 && <5,
6− bytestring , containers , RefSerialize , TCache ,
7− stm >2, time, old-time , vector , directory ,
8−- utf8-string , wai , case-insensitive ,
9−+ utf8-string , wai , wai-extra, resourcet, case-insensitive ,
10− http-types , conduit ,conduit-extra, text , parsec , warp ,
11− warp-tls , random , blaze-html , blaze-markup ,
12−- monadloc, clientsession
13−+ monadloc, clientsession, pwstore-fast
14− exposed-modules: MFlow MFlow.Wai.Blaze.Html.All MFlow.Forms
15− MFlow.Forms.Admin MFlow.Cookies MFlow.Wai
16− MFlow.Forms.Blaze.Html MFlow.Forms.Test
17−@@ -128,7 +128,7 @@
18− -- hamlet , shakespeare, monadloc , aws , network , hscolour ,
19− -- persistent-template , persistent-sqlite , persistent ,
20− -- conduit , http-conduit , monad-logger , safecopy ,
21−--- time
22−+-- time, acid-state
23− -- main-is: demos-blaze.hs
24− -- buildable: True
25− -- hs-source-dirs: Demos
26−@@ -142,4 +142,4 @@
27− -- InitialConfig GenerateForm GenerateFormUndo GenerateFormUndoMsg WebService
28− -- LazyLoad
29− -- ghc-options: -iDemos -threaded -rtsopts
30−---
31−+
32−diff -ru orig/Setup.lhs new/Setup.lhs
33−--- orig/Setup.lhs 2014-06-10 05:51:26.953015857 +0300
34−+++ new/Setup.lhs 2014-06-10 05:51:25.000000000 +0300
35−@@ -1,5 +1,5 @@
36−-#! /usr/bin/runghc
37−-
38−-> import Distribution.Simple
39−->
40−-> main = defaultMain
41−+#! /usr/bin/runghc
42−+
43−+> import Distribution.Simple
44−+>
45−+> main = defaultMain
46−diff -ru orig/src/MFlow/Cookies.hs new/src/MFlow/Cookies.hs
47−--- orig/src/MFlow/Cookies.hs 2014-06-10 05:51:26.961015857 +0300
48−+++ new/src/MFlow/Cookies.hs 2014-06-10 05:51:25.000000000 +0300
49−@@ -1,188 +1,188 @@
50−-{-# OPTIONS -XScopedTypeVariables -XOverloadedStrings #-}
51−-
52−-module MFlow.Cookies (
53−- CookieT,
54−- Cookie(..),
55−- contentHtml,
56−- cookieuser,
57−- cookieHeaders,
58−- getCookies,
59−- paranoidEncryptCookie,
60−- paranoidDecryptCookie,
61−- encryptCookie,
62−- decryptCookie
63−- )
64−-where
65−-import Control.Monad(MonadPlus(..), guard, replicateM_, when)
66−-import Data.Char
67−-import Data.Maybe(fromMaybe, fromJust)
68−-import System.IO.Unsafe
69−-import Control.Exception(handle)
70−-import Data.Typeable
71−-import Unsafe.Coerce
72−-import Data.Monoid
73−-import Text.Parsec
74−-import Control.Monad.Identity
75−-import Data.ByteString.Char8 as B
76−-import Web.ClientSession
77−-import System.Environment
78−-
79−---import Debug.Trace
80−---(!>)= flip trace
81−-
82−-contentHtml :: (ByteString, ByteString)
83−-contentHtml= ("Content-Type", "text/html; charset=UTF-8")
84−-
85−-type CookieT = (B.ByteString,B.ByteString,B.ByteString,Maybe B.ByteString)
86−-
87−-data Cookie
88−- = UnEncryptedCookie CookieT
89−- | EncryptedCookie CookieT
90−- | ParanoidCookie CookieT
91−- deriving (Eq, Read, Show)
92−-
93−-cookieuser :: String
94−-cookieuser= "cookieuser"
95−-
96−-getCookies httpreq=
97−- case lookup "Cookie" $ httpreq of
98−- Just str -> splitCookies str :: [(B.ByteString, B.ByteString)]
99−- Nothing -> []
100−-
101−-cookieHeaders cs = Prelude.map (\c-> ( "Set-Cookie", showCookie c)) cs
102−-
103−-showCookie :: Cookie -> B.ByteString
104−-showCookie c@(EncryptedCookie _) = showCookie' $ decryptAndToTuple c
105−-showCookie c@(ParanoidCookie _) = showCookie' $ decryptAndToTuple c
106−-showCookie (UnEncryptedCookie c) = showCookie' c
107−-
108−-showCookie' (n,v,p,me) = n <> "=" <> v <>
109−- ";path=" <> p <>
110−- showMaxAge me
111−-
112−-showMaxAge Nothing = ""
113−-showMaxAge (Just e) = ";Max-age=" <> e
114−-
115−-splitCookies cookies = f cookies []
116−- where
117−- f s r | B.null s = r
118−- f xs0 r =
119−- let
120−- xs = B.dropWhile (==' ') xs0
121−- name = B.takeWhile (/='=') xs
122−- xs1 = B.dropWhile (/='=') xs
123−- xs2 = B.dropWhile (=='=') xs1
124−- val = B.takeWhile (/=';') xs2
125−- xs3 = B.dropWhile (/=';') xs2
126−- xs4 = B.dropWhile (==';') xs3
127−- xs5 = B.dropWhile (==' ') xs4
128−- in f xs5 ((name,val):r)
129−-
130−+{-# OPTIONS -XScopedTypeVariables -XOverloadedStrings #-}
131−+
132−+module MFlow.Cookies (
133−+ CookieT,
134−+ Cookie(..),
135−+ contentHtml,
136−+ cookieuser,
137−+ cookieHeaders,
138−+ getCookies,
139−+ paranoidEncryptCookie,
140−+ paranoidDecryptCookie,
141−+ encryptCookie,
142−+ decryptCookie
143−+ )
144−+where
145−+import Control.Monad(MonadPlus(..), guard, replicateM_, when)
146−+import Data.Char
147−+import Data.Maybe(fromMaybe, fromJust)
148−+import System.IO.Unsafe
149−+import Control.Exception(handle)
150−+import Data.Typeable
151−+import Unsafe.Coerce
152−+import Data.Monoid
153−+import Text.Parsec
154−+import Control.Monad.Identity
155−+import Data.ByteString.Char8 as B
156−+import Web.ClientSession
157−+import System.Environment
158−+
159−+--import Debug.Trace
160−+--(!>)= flip trace
161−+
162−+contentHtml :: (ByteString, ByteString)
163−+contentHtml= ("Content-Type", "text/html; charset=UTF-8")
164−+
165−+type CookieT = (B.ByteString,B.ByteString,B.ByteString,Maybe B.ByteString)
166−+
167−+data Cookie
168−+ = UnEncryptedCookie CookieT
169−+ | EncryptedCookie CookieT
170−+ | ParanoidCookie CookieT
171−+ deriving (Eq, Read, Show)
172−+
173−+cookieuser :: String
174−+cookieuser= "cookieuser"
175−+
176−+getCookies httpreq=
177−+ case lookup "Cookie" $ httpreq of
178−+ Just str -> splitCookies str :: [(B.ByteString, B.ByteString)]
179−+ Nothing -> []
180−+
181−+cookieHeaders cs = Prelude.map (\c-> ( "Set-Cookie", showCookie c)) cs
182−+
183−+showCookie :: Cookie -> B.ByteString
184−+showCookie c@(EncryptedCookie _) = showCookie' $ decryptAndToTuple c
185−+showCookie c@(ParanoidCookie _) = showCookie' $ decryptAndToTuple c
186−+showCookie (UnEncryptedCookie c) = showCookie' c
187−+
188−+showCookie' (n,v,p,me) = n <> "=" <> v <>
189−+ ";path=" <> p <>
190−+ showMaxAge me
191−+
192−+showMaxAge Nothing = ""
193−+showMaxAge (Just e) = ";Max-age=" <> e
194−+
195−+splitCookies cookies = f cookies []
196−+ where
197−+ f s r | B.null s = r
198−+ f xs0 r =
199−+ let
200−+ xs = B.dropWhile (==' ') xs0
201−+ name = B.takeWhile (/='=') xs
202−+ xs1 = B.dropWhile (/='=') xs
203−+ xs2 = B.dropWhile (=='=') xs1
204−+ val = B.takeWhile (/=';') xs2
205−+ xs3 = B.dropWhile (/=';') xs2
206−+ xs4 = B.dropWhile (==';') xs3
207−+ xs5 = B.dropWhile (==' ') xs4
208−+ in f xs5 ((name,val):r)
209−+
210− ----------------------------
211−-
212−---readEnv :: Parser [(String,String)]
213−-readEnv = (do
214−- n <- urlEncoded
215−- string "="
216−- v <- urlEncoded
217−- return (n,v)) `sepBy` (string "&")
218−-
219−-urlEncoded :: Parsec String () String
220−-urlEncoded
221−- = many ( alphaNum `mplus` extra `mplus` safe
222−- `mplus` do{ char '+' ; return ' '}
223−- `mplus` do{ char '%' ; hexadecimal }
224−- )
225−-
226−-
227−---extra :: Parser Char
228−-extra = satisfy (`Prelude.elem` "!*'(),/\"")
229−---
230−---safe :: Parser Char
231−-safe = satisfy (`Prelude.elem` "$-_.")
232−-----
233−---hexadecimal :: Parser HexString
234−-hexadecimal = do d1 <- hexDigit
235−- d2 <- hexDigit
236−- return .chr $ toInt d1* 16 + toInt d2
237−- where toInt d | isDigit d = ord d - ord '0'
238−- toInt d | isHexDigit d = (ord d - ord 'A') + 10
239−- toInt d = error ("hex2int: illegal hex digit " ++ [d])
240−-
241−-
242−-
243−-decryptCookie :: Cookie -> IO Cookie
244−-decryptCookie c@(UnEncryptedCookie _) = return c
245−-decryptCookie (EncryptedCookie c) = decryptCookie' c
246−-decryptCookie (ParanoidCookie c) = paranoidDecryptCookie c
247−-
248−--- Uses 4 seperate keys, corresponding to the 4 seperate fields in the Cookie.
249−-paranoidEncryptCookie :: CookieT -> IO Cookie
250−-paranoidEncryptCookie (a,b,c,d) = do
251−- key1 <- getKey "CookieKey1.key"
252−- key2 <- getKey "CookieKey2.key"
253−- key3 <- getKey "CookieKey3.key"
254−- key4 <- getKey "CookieKey4.key"
255−- iv1 <- randomIV
256−- iv2 <- randomIV
257−- iv3 <- randomIV
258−- iv4 <- randomIV
259−- return $ ParanoidCookie
260−- ( encrypt key1 iv1 a,
261−- encrypt key2 iv2 b,
262−- encrypt key3 iv3 c,
263−- encryptMaybe key4 iv4 d)
264−-
265−-paranoidDecryptCookie :: CookieT -> IO Cookie
266−-paranoidDecryptCookie (a,b,c,d) = do
267−- key1 <- getKey "CookieKey1.key"
268−- key2 <- getKey "CookieKey2.key"
269−- key3 <- getKey "CookieKey3.key"
270−- key4 <- getKey "CookieKey4.key"
271−- return $ UnEncryptedCookie
272−- ( decryptFM key1 a,
273−- decryptFM key2 b,
274−- decryptFM key3 c,
275−- decryptMaybe key4 d)
276−-
277−--- Uses a single key to encrypt all 4 fields.
278−-encryptCookie :: CookieT -> IO Cookie
279−-encryptCookie (a,b,c,d) = do
280−- key <- getKey "CookieKey.key"
281−- iv1 <- randomIV
282−- iv2 <- randomIV
283−- iv3 <- randomIV
284−- iv4 <- randomIV
285−- return $ EncryptedCookie
286−- ( encrypt key iv1 a,
287−- encrypt key iv2 b,
288−- encrypt key iv3 c,
289−- encryptMaybe key iv4 d)
290−-
291−-decryptCookie' :: CookieT -> IO Cookie
292−-decryptCookie' (a,b,c,d) = do
293−- key <- getKey "CookieKey.key"
294−- return $ UnEncryptedCookie
295−- ( decryptFM key a,
296−- decryptFM key b,
297−- decryptFM key c,
298−- decryptMaybe key d)
299−-
300−-encryptMaybe :: Key -> IV -> Maybe ByteString -> Maybe ByteString
301−-encryptMaybe k i (Just s) = Just $ encrypt k i s
302−-encryptMaybe _ _ Nothing = Nothing
303−-
304−-decryptMaybe :: Key -> Maybe ByteString -> Maybe ByteString
305−-decryptMaybe k (Just s) = Just $ fromMaybe "" $ decrypt k s
306−-decryptMaybe _ Nothing = Nothing
307−-
308−-decryptFM :: Key -> ByteString -> ByteString
309−-decryptFM k b = fromMaybe "" $ decrypt k b
310−-
311−-cookieToTuple :: Cookie -> CookieT
312−-cookieToTuple (UnEncryptedCookie c) = c
313−-cookieToTuple (EncryptedCookie c) = c
314−-cookieToTuple (ParanoidCookie c) = c
315−-
316−-decryptAndToTuple :: Cookie -> CookieT
317−-decryptAndToTuple = cookieToTuple . unsafePerformIO . decryptCookie
318−+
319−+--readEnv :: Parser [(String,String)]
320−+readEnv = (do
321−+ n <- urlEncoded
322−+ string "="
323−+ v <- urlEncoded
324−+ return (n,v)) `sepBy` (string "&")
325−+
326−+urlEncoded :: Parsec String () String
327−+urlEncoded
328−+ = many ( alphaNum `mplus` extra `mplus` safe
329−+ `mplus` do{ char '+' ; return ' '}
330−+ `mplus` do{ char '%' ; hexadecimal }
331−+ )
332−+
333−+
334−+--extra :: Parser Char
335−+extra = satisfy (`Prelude.elem` "!*'(),/\"")
336−+--
337−+--safe :: Parser Char
338−+safe = satisfy (`Prelude.elem` "$-_.")
339−+----
340−+--hexadecimal :: Parser HexString
341−+hexadecimal = do d1 <- hexDigit
342−+ d2 <- hexDigit
343−+ return .chr $ toInt d1* 16 + toInt d2
344−+ where toInt d | isDigit d = ord d - ord '0'
345−+ toInt d | isHexDigit d = (ord d - ord 'A') + 10
346−+ toInt d = error ("hex2int: illegal hex digit " ++ [d])
347−+
348−+
349−+
350−+decryptCookie :: Cookie -> IO Cookie
351−+decryptCookie c@(UnEncryptedCookie _) = return c
352−+decryptCookie (EncryptedCookie c) = decryptCookie' c
353−+decryptCookie (ParanoidCookie c) = paranoidDecryptCookie c
354−+
355−+-- Uses 4 seperate keys, corresponding to the 4 seperate fields in the Cookie.
356−+paranoidEncryptCookie :: CookieT -> IO Cookie
357−+paranoidEncryptCookie (a,b,c,d) = do
358−+ key1 <- getKey "CookieKey1.key"
359−+ key2 <- getKey "CookieKey2.key"
360−+ key3 <- getKey "CookieKey3.key"
361−+ key4 <- getKey "CookieKey4.key"
362−+ iv1 <- randomIV
363−+ iv2 <- randomIV
364−+ iv3 <- randomIV
365−+ iv4 <- randomIV
366−+ return $ ParanoidCookie
367−+ ( encrypt key1 iv1 a,
368−+ encrypt key2 iv2 b,
369−+ encrypt key3 iv3 c,
370−+ encryptMaybe key4 iv4 d)
371−+
372−+paranoidDecryptCookie :: CookieT -> IO Cookie
373−+paranoidDecryptCookie (a,b,c,d) = do
374−+ key1 <- getKey "CookieKey1.key"
375−+ key2 <- getKey "CookieKey2.key"
376−+ key3 <- getKey "CookieKey3.key"
377−+ key4 <- getKey "CookieKey4.key"
378−+ return $ UnEncryptedCookie
379−+ ( decryptFM key1 a,
380−+ decryptFM key2 b,
381−+ decryptFM key3 c,
382−+ decryptMaybe key4 d)
383−+
384−+-- Uses a single key to encrypt all 4 fields.
385−+encryptCookie :: CookieT -> IO Cookie
386−+encryptCookie (a,b,c,d) = do
387−+ key <- getKey "CookieKey.key"
388−+ iv1 <- randomIV
389−+ iv2 <- randomIV
390−+ iv3 <- randomIV
391−+ iv4 <- randomIV
392−+ return $ EncryptedCookie
393−+ ( encrypt key iv1 a,
394−+ encrypt key iv2 b,
395−+ encrypt key iv3 c,
396−+ encryptMaybe key iv4 d)
397−+
398−+decryptCookie' :: CookieT -> IO Cookie
399−+decryptCookie' (a,b,c,d) = do
400−+ key <- getKey "CookieKey.key"
401−+ return $ UnEncryptedCookie
402−+ ( decryptFM key a,
403−+ decryptFM key b,
404−+ decryptFM key c,
405−+ decryptMaybe key d)
406−+
407−+encryptMaybe :: Key -> IV -> Maybe ByteString -> Maybe ByteString
408−+encryptMaybe k i (Just s) = Just $ encrypt k i s
409−+encryptMaybe _ _ Nothing = Nothing
410−+
411−+decryptMaybe :: Key -> Maybe ByteString -> Maybe ByteString
412−+decryptMaybe k (Just s) = Just $ fromMaybe "" $ decrypt k s
413−+decryptMaybe _ Nothing = Nothing
414−+
415−+decryptFM :: Key -> ByteString -> ByteString
416−+decryptFM k b = fromMaybe "" $ decrypt k b
417−+
418−+cookieToTuple :: Cookie -> CookieT
419−+cookieToTuple (UnEncryptedCookie c) = c
420−+cookieToTuple (EncryptedCookie c) = c
421−+cookieToTuple (ParanoidCookie c) = c
422−+
423−+decryptAndToTuple :: Cookie -> CookieT
424−+decryptAndToTuple = cookieToTuple . unsafePerformIO . decryptCookie
425−diff -ru orig/src/MFlow/Forms/Admin.hs new/src/MFlow/Forms/Admin.hs
426−--- orig/src/MFlow/Forms/Admin.hs 2014-06-10 05:51:26.985015856 +0300
427−+++ new/src/MFlow/Forms/Admin.hs 2014-06-10 05:51:25.000000000 +0300
428−@@ -1,175 +1,175 @@
429−-{-# OPTIONS
430−- -XScopedTypeVariables
431−-
432−- #-}
433−-module MFlow.Forms.Admin(adminLoop, wait, addAdminWF) where
434−+{-# OPTIONS
435−+ -XScopedTypeVariables
436−+
437−+ #-}
438−+module MFlow.Forms.Admin(adminLoop, wait, addAdminWF) where
439− import MFlow.Forms
440− import MFlow
441−-import MFlow.Forms.Blaze.Html
442−-import Text.Blaze.Html5 hiding (map)
443−-import Control.Applicative
444−-import Control.Workflow
445−-import Control.Monad.Trans
446−-import Data.TCache
447−-import Data.TCache.IndexQuery
448−-import System.Exit
449−-import System.IO
450−-import System.IO.Unsafe
451−-import Data.ByteString.Lazy.Char8 as B (unpack,tail,hGetNonBlocking,append, pack)
452−-import System.IO
453−-import Data.RefSerialize hiding ((<|>))
454−-import Data.Typeable
455−-import Data.Monoid
456−-import Data.Maybe
457−-import Data.Map as M (keys, toList)
458−-import System.Exit
459−-import Control.Exception as E
460−-import Control.Concurrent
461−-import Control.Concurrent.MVar
462−-import GHC.Conc
463−-
464−-
465−-ssyncCache= putStr "sync..." >> syncCache >> putStrLn "done"
466−-
467−--- | A small console interpreter with some commands:
468−---
469−--- [@sync@] Synchronize the cache with persistent storage (see `syncCache`)
470−---
471−--- [@flush@] Flush the cache
472−---
473−--- [@end@] Synchronize and exit
474−---
475−--- [@abort@] Exit. Do not synchronize
476−---
477−--- on exception, for example Control-c, it sync and exits.
478−--- It must be used as the last statement of the main procedure.
479−-adminLoop :: IO ()
480−-adminLoop= do
481−- msgs <- getMessageFlows
482−- putStrLn ""
483−- putStrLn $ "Served:"
484−- mapM putStrLn [ " http://server:port/"++ i | i <- M.keys msgs]
485−- putStrLn ""
486−- putStrLn "Commands: sync, flush, end, abort"
487−- adminLoop1
488−- `E.catch` (\(e:: E.SomeException) ->do
489−- ssyncCache
490−- error $ "\nException: "++ show e)
491−-
492−-adminLoop1= do
493−- putStr ">"; hFlush stdout
494−- op <- getLine
495−- case op of
496−- "sync" -> ssyncCache
497−- "flush" -> atomically flushAll >> putStrLn "flushed cache"
498−- "end" -> ssyncCache >> putStrLn "bye" >> exitWith ExitSuccess
499−- "abort" -> exitWith ExitSuccess
500−- _ -> return()
501−- adminLoop1
502−-
503−--- | execute the process and wait for its finalization.
504−--- then it synchronizes the cache
505−+import MFlow.Forms.Blaze.Html
506−+import Text.Blaze.Html5 hiding (map)
507−+import Control.Applicative
508−+import Control.Workflow
509−+import Control.Monad.Trans
510−+import Data.TCache
511−+import Data.TCache.IndexQuery
512−+import System.Exit
513−+import System.IO
514−+import System.IO.Unsafe
515−+import Data.ByteString.Lazy.Char8 as B (unpack,tail,hGetNonBlocking,append, pack)
516−+import System.IO
517−+import Data.RefSerialize hiding ((<|>))
518−+import Data.Typeable
519−+import Data.Monoid
520−+import Data.Maybe
521−+import Data.Map as M (keys, toList)
522−+import System.Exit
523−+import Control.Exception as E
524−+import Control.Concurrent
525−+import Control.Concurrent.MVar
526−+import GHC.Conc
527−+
528−+
529−+ssyncCache= putStr "sync..." >> syncCache >> putStrLn "done"
530−+
531−+-- | A small console interpreter with some commands:
532−+--
533−+-- [@sync@] Synchronize the cache with persistent storage (see `syncCache`)
534−+--
535−+-- [@flush@] Flush the cache
536−+--
537−+-- [@end@] Synchronize and exit
538−+--
539−+-- [@abort@] Exit. Do not synchronize
540−+--
541−+-- on exception, for example Control-c, it sync and exits.
542−+-- It must be used as the last statement of the main procedure.
543−+adminLoop :: IO ()
544−+adminLoop= do
545−+ msgs <- getMessageFlows
546−+ putStrLn ""
547−+ putStrLn $ "Served:"
548−+ mapM putStrLn [ " http://server:port/"++ i | i <- M.keys msgs]
549−+ putStrLn ""
550−+ putStrLn "Commands: sync, flush, end, abort"
551−+ adminLoop1
552−+ `E.catch` (\(e:: E.SomeException) ->do
553−+ ssyncCache
554−+ error $ "\nException: "++ show e)
555−+
556−+adminLoop1= do
557−+ putStr ">"; hFlush stdout
558−+ op <- getLine
559−+ case op of
560−+ "sync" -> ssyncCache
561−+ "flush" -> atomically flushAll >> putStrLn "flushed cache"
562−+ "end" -> ssyncCache >> putStrLn "bye" >> exitWith ExitSuccess
563−+ "abort" -> exitWith ExitSuccess
564−+ _ -> return()
565−+ adminLoop1
566−+
567−+-- | execute the process and wait for its finalization.
568−+-- then it synchronizes the cache
569− wait f= do
570− putChar '\n'
571− putStrLn "Using configuration: "
572− mapM_ putStrLn [k ++"= "++ show v | (k,v) <- M.toList config]
573−- putChar '\n'
574−- mv <- newEmptyMVar
575−- forkIO (f1 >> putMVar mv True)
576−- putStrLn "wait: ready"
577−+ putChar '\n'
578−+ mv <- newEmptyMVar
579−+ forkIO (f1 >> putMVar mv True)
580−+ putStrLn "wait: ready"
581− takeMVar mv
582−- return ()
583−- `E.catch` (\(e:: E.SomeException) ->do
584−- ssyncCache
585−- error $ "Signal: "++ show e)
586−-
587−- where
588−- f1= do
589−- mv <- newEmptyMVar
590−- n <- getNumProcessors
591−- putStr "Running in "
592−- putStr $ show n
593−- putStrLn " core(s)"
594−- hFlush stdout
595−- f
596−-
597−--- | Install the admin flow in the list of flows handled by `HackMessageFlow`
598−--- this gives access to an administrator page. It is necessary to
599−--- create an admin user with `setAdminUser`.
600−---
601−--- The administration page is reached with the path \"adminserv\"
602−-addAdminWF= addMessageFlows[("adminserv", runFlow $ transientNav adminMFlow)]
603−-
604−-
605−-adminMFlow :: FlowM Html IO ()
606−-adminMFlow= do
607−- let admin = getAdminName
608−- u <- getUser (Just admin) $ p << b << "Please login as Administrator" ++> userLogin
609−- op <- ask $ p <<< wlink "sync" (b << "sync")
610−- <|> p <<< wlink "flush" (b << "flush")
611−- <|> p <<< wlink "errors"(b << "errors")
612−- <|> p <<< wlink "users" (b << "users")
613−- <|> p <<< wlink "end" (b << "end")
614−- <|> wlink "abort" (b << "abort")
615−-
616−- case op of
617−- "users" -> users
618−- "sync" -> liftIO $ syncCache >> print "syncronized cache"
619−- "flush" -> liftIO $ atomically flushAll >> print "flushed cache"
620−-
621−- "errors" -> errors
622−- "end" -> liftIO $ syncCache >> print "bye" >> exitWith(ExitSuccess)
623−- "abort" -> liftIO $ exitWith(ExitSuccess)
624−- _ -> return()
625−- adminMFlow
626−-
627−-
628−-errors= do
629−- size <- liftIO $ hFileSize hlog
630−- if size == 0
631−- then ask $ wlink () (b << "no error log")
632−- else do
633−- liftIO $ hSeek hlog AbsoluteSeek 0
634−- log <- liftIO $ hGetNonBlocking hlog (fromIntegral size)
635−-
636−- let ls :: [[String ]]= runR readp $ pack "[" `append` (B.tail log) `append` pack "]"
637−- let rows= [wlink (Prelude.head e) (b << Prelude.head e) `waction` optionsUser : map (\x ->noWidget <++ fromStr x) (Prelude.tail e) | e <- ls]
638−- showFormList rows 0 10
639−- breturn()
640−-
641−-
642−-
643−-
644−-
645−-
646−-
647−-users= do
648−- users <- liftIO $ atomically $ return . map fst =<< indexOf userName
649−-
650−- showFormList [[wlink u (b << u) `waction` optionsUser ] | u<- users] 0 10
651−-
652−-showFormList
653−- :: [[View Html IO ()]]
654−- -> Int -> Int -> FlowM Html IO b
655−-showFormList ls n l= do
656−- nav <- ask $ updown n l <|> (list **> updown n l)
657−- showFormList ls nav l
658−-
659−- where
660−- list= table <<< firstOf (span1 n l [tr <<< cols e | e <- ls ])
661−-
662−- cols e= firstOf[td <<< c | c <- e]
663−- span1 n l = take l . drop n
664−- updown n l= wlink ( n +l) (b << "up ") <|> wlink ( n -l) (b << "down ") <++ br
665−-
666−-optionsUser us = do
667−- wfs <- liftIO $ return . M.keys =<< getMessageFlows
668−- stats <- let u= undefined
669−- in liftIO $ mapM (\wf -> getWFHistory wf (Token wf us u u u u u u)) wfs
670−- let wfss= filter (isJust . snd) $ zip wfs stats
671−- if null wfss
672−- then ask $ b << " not logs for this user" ++> wlink () (b << "Press here")
673−- else do
674−- wf <- ask $ firstOf [ wlink wf (p << wf) | (wf,_) <- wfss]
675−- ask $ p << unpack (showHistory . fromJust . fromJust $ lookup wf wfss) ++> wlink () (p << "press to menu")
676−-
677−+ return ()
678−+ `E.catch` (\(e:: E.SomeException) ->do
679−+ ssyncCache
680−+ error $ "Signal: "++ show e)
681−+
682−+ where
683−+ f1= do
684−+ mv <- newEmptyMVar
685−+ n <- getNumProcessors
686−+ putStr "Running in "
687−+ putStr $ show n
688−+ putStrLn " core(s)"
689−+ hFlush stdout
690−+ f
691−+
692−+-- | Install the admin flow in the list of flows handled by `HackMessageFlow`
693−+-- this gives access to an administrator page. It is necessary to
694−+-- create an admin user with `setAdminUser`.
695−+--
696−+-- The administration page is reached with the path \"adminserv\"
697−+addAdminWF= addMessageFlows[("adminserv", runFlow $ transientNav adminMFlow)]
698−+
699−+
700−+adminMFlow :: FlowM Html IO ()
701−+adminMFlow= do
702−+ let admin = getAdminName
703−+ u <- getUser (Just admin) $ p << b << "Please login as Administrator" ++> userLogin
704−+ op <- ask $ p <<< wlink "sync" (b << "sync")
705−+ <|> p <<< wlink "flush" (b << "flush")
706−+ <|> p <<< wlink "errors"(b << "errors")
707−+ <|> p <<< wlink "users" (b << "users")
708−+ <|> p <<< wlink "end" (b << "end")
709−+ <|> wlink "abort" (b << "abort")
710−+
711−+ case op of
712−+ "users" -> users
713−+ "sync" -> liftIO $ syncCache >> print "syncronized cache"
714−+ "flush" -> liftIO $ atomically flushAll >> print "flushed cache"
715−+
716−+ "errors" -> errors
717−+ "end" -> liftIO $ syncCache >> print "bye" >> exitWith(ExitSuccess)
718−+ "abort" -> liftIO $ exitWith(ExitSuccess)
719−+ _ -> return()
720−+ adminMFlow
721−+
722−+
723−+errors= do
724−+ size <- liftIO $ hFileSize hlog
725−+ if size == 0
726−+ then ask $ wlink () (b << "no error log")
727−+ else do
728−+ liftIO $ hSeek hlog AbsoluteSeek 0
729−+ log <- liftIO $ hGetNonBlocking hlog (fromIntegral size)
730−+
731−+ let ls :: [[String ]]= runR readp $ pack "[" `append` (B.tail log) `append` pack "]"
732−+ let rows= [wlink (Prelude.head e) (b << Prelude.head e) `waction` optionsUser : map (\x ->noWidget <++ fromStr x) (Prelude.tail e) | e <- ls]
733−+ showFormList rows 0 10
734−+ breturn()
735−+
736−+
737−+
738−+
739−+
740−+
741−+
742−+users= do
743−+ users <- liftIO $ atomically $ return . map fst =<< indexOf userName
744−+
745−+ showFormList [[wlink u (b << u) `waction` optionsUser ] | u<- users] 0 10
746−+
747−+showFormList
748−+ :: [[View Html IO ()]]
749−+ -> Int -> Int -> FlowM Html IO b
750−+showFormList ls n l= do
751−+ nav <- ask $ updown n l <|> (list **> updown n l)
752−+ showFormList ls nav l
753−+
754−+ where
755−+ list= table <<< firstOf (span1 n l [tr <<< cols e | e <- ls ])
756−+
757−+ cols e= firstOf[td <<< c | c <- e]
758−+ span1 n l = take l . drop n
759−+ updown n l= wlink ( n +l) (b << "up ") <|> wlink ( n -l) (b << "down ") <++ br
760−+
761−+optionsUser us = do
762−+ wfs <- liftIO $ return . M.keys =<< getMessageFlows
763−+ stats <- let u= undefined
764−+ in liftIO $ mapM (\wf -> getWFHistory wf (Token wf us u u u u u u)) wfs
765−+ let wfss= filter (isJust . snd) $ zip wfs stats
766−+ if null wfss
767−+ then ask $ b << " not logs for this user" ++> wlink () (b << "Press here")
768−+ else do
769−+ wf <- ask $ firstOf [ wlink wf (p << wf) | (wf,_) <- wfss]
770−+ ask $ p << unpack (showHistory . fromJust . fromJust $ lookup wf wfss) ++> wlink () (p << "press to menu")
771−+
772−diff -ru orig/src/MFlow/Forms/Blaze/Html.hs new/src/MFlow/Forms/Blaze/Html.hs
773−--- orig/src/MFlow/Forms/Blaze/Html.hs 2014-06-10 05:51:26.989015856 +0300
774−+++ new/src/MFlow/Forms/Blaze/Html.hs 2014-06-10 05:51:25.000000000 +0300
775−@@ -58,7 +58,7 @@
776− in if msel then tag ! selected (toValue ("" ::String)) else tag
777−
778−
779−- formAction action form = St.form ! acceptCharset "UTF-8" ! At.action (toValue action) ! method (toValue ("post" :: String)) $ form
780−+ formAction action method1 form = St.form ! acceptCharset "UTF-8" ! At.action (toValue action) ! method (toValue method1) $ form
781−
782− fromStr= toMarkup
783− fromStrNoEncode = preEscapedToMarkup
784−diff -ru orig/src/MFlow/Forms/Internals.hs new/src/MFlow/Forms/Internals.hs
785−--- orig/src/MFlow/Forms/Internals.hs 2014-06-10 05:51:26.981015856 +0300
786−+++ new/src/MFlow/Forms/Internals.hs 2014-06-10 05:51:25.000000000 +0300
787−@@ -1,313 +1,345 @@
788−------------------------------------------------------------------------------
789−---
790−--- Module : MFlow.Forms.Internals
791−--- Copyright :
792−--- License : BSD3
793−---
794−--- Maintainer : agocorona@gmail.com
795−--- Stability : experimental
796−--- Portability :
797−---
798−--- |
799−---
800−------------------------------------------------------------------------------
801−-{-# OPTIONS -XDeriveDataTypeable
802−- -XExistentialQuantification
803−- -XScopedTypeVariables
804−- -XFlexibleInstances
805−- -XUndecidableInstances
806−- -XMultiParamTypeClasses
807−- -XGeneralizedNewtypeDeriving
808−- -XFlexibleContexts
809−- -XOverlappingInstances
810−- -XRecordWildCards
811−-#-}
812−-
813−-module MFlow.Forms.Internals where
814−-import MFlow
815−-import MFlow.Cookies
816−-import Control.Applicative
817−-import Data.Monoid
818−-import Control.Monad.Trans
819−-import Control.Monad.State
820−-import Data.ByteString.Lazy.UTF8 as B hiding (length, foldr, take)
821−-import qualified Data.ByteString.UTF8 as SB
822−-import Data.Typeable
823−-import Data.RefSerialize hiding((<|>))
824−-import Data.TCache
825−-import Data.TCache.Memoization
826−-import Data.TCache.DefaultPersistence
827−-import Data.TCache.Memoization
828−-import Data.Dynamic
829−-import qualified Data.Map as M
830−-import Unsafe.Coerce
831−-import Control.Workflow as WF
832−-import Control.Monad.Identity
833−-import Data.List
834−-import System.IO.Unsafe
835−-import Control.Concurrent.MVar
836−+-----------------------------------------------------------------------------
837−+--
838−+-- Module : MFlow.Forms.Internals
839−+-- Copyright :
840−+-- License : BSD3
841−+--
842−+-- Maintainer : agocorona@gmail.com
843−+-- Stability : experimental
844−+-- Portability :
845−+--
846−+-- |
847−+--
848−+-----------------------------------------------------------------------------
849−+{-# OPTIONS -XDeriveDataTypeable
850−+ -XExistentialQuantification
851−+ -XScopedTypeVariables
852−+ -XFlexibleInstances
853−+ -XUndecidableInstances
854−+ -XMultiParamTypeClasses
855−+ -XGeneralizedNewtypeDeriving
856−+ -XFlexibleContexts
857−+ -XOverlappingInstances
858−+ -XRecordWildCards
859−+#-}
860−+
861−+module MFlow.Forms.Internals where
862−+import MFlow
863−+import MFlow.Cookies
864−+import Control.Applicative
865−+import Data.Monoid
866−+import Control.Monad.Trans
867−+import Control.Monad.State
868−+import Data.ByteString.Lazy.UTF8 as B hiding (length, foldr, take)
869−+import qualified Data.ByteString.UTF8 as SB
870−+import Data.Typeable
871−+import Data.RefSerialize hiding((<|>))
872−+import Data.TCache
873−+import Data.TCache.Memoization
874−+import Data.TCache.DefaultPersistence
875−+import Data.TCache.Memoization
876−+import Data.Dynamic
877−+import qualified Data.Map as M
878−+import Unsafe.Coerce
879−+import Control.Workflow as WF
880−+import Control.Monad.Identity
881−+import Data.List
882−+import System.IO.Unsafe
883−+import Control.Concurrent.MVar
884− import qualified Data.Text as T
885− import Data.Char
886− import Data.List(stripPrefix)
887− import Data.Maybe(isJust)
888− import Control.Concurrent.STM
889− import Data.TCache.Memoization
890−-
891−---
892−----- for traces
893−---
894−-
895−-import Control.Exception as CE
896−-import Control.Concurrent
897−-import Control.Monad.Loc
898−-
899−--- debug
900−---import Debug.Trace
901−---(!>) = flip trace
902−-
903−-
904−-data FailBack a = BackPoint a | NoBack a | GoBack deriving (Show,Typeable)
905−-
906−-
907−-instance (Serialize a) => Serialize (FailBack a ) where
908−- showp (BackPoint x)= insertString (fromString iCanFailBack) >> showp x
909−- showp (NoBack x) = insertString (fromString noFailBack) >> showp x
910−- showp GoBack = insertString (fromString repeatPlease)
911−-
912−- readp = choice [icanFailBackp,repeatPleasep,noFailBackp]
913−- where
914−- noFailBackp = symbol noFailBack >> readp >>= return . NoBack
915−- icanFailBackp = symbol iCanFailBack >> readp >>= return . BackPoint
916−- repeatPleasep = symbol repeatPlease >> return GoBack
917−-
918−-iCanFailBack= "B"
919−-repeatPlease= "G"
920−-noFailBack= "N"
921−-
922−-newtype Sup m a = Sup { runSup :: m (FailBack a ) }
923−-
924−-class MonadState s m => Supervise s m where
925−- supBack :: s -> m () -- called before backtracing. state passed is the previous
926−- supBack = const $ return () -- By default the state passed is the last one
927−-
928−- supervise :: m (FailBack a) -> m (FailBack a)
929−- supervise= id
930−-
931−-
932−-
933−-instance (Supervise s m)=> Monad (Sup m) where
934−- fail _ = Sup . return $ GoBack
935−- return x = Sup . return $ NoBack x
936−- x >>= f = Sup $ loop
937−- where
938−- loop = do
939−- s <- get
940−- v <- supervise $ runSup x -- !> "loop"
941−- case v of
942−- NoBack y -> supervise $ runSup (f y) -- !> "runback"
943−- BackPoint y -> do
944−- z <- supervise $ runSup (f y) -- !> "BACK"
945−- case z of
946−- GoBack -> supBack s >> loop -- !> "BACKTRACKING"
947−- other -> return other
948−- GoBack -> return $ GoBack
949−-
950−-
951−-fromFailBack (NoBack x) = x
952−-fromFailBack (BackPoint x)= x
953−-toFailBack x= NoBack x
954−-
955−-
956−--- | the FlowM monad executes the page navigation. It perform Backtracking when necessary to syncronize
957−--- when the user press the back button or when the user enter an arbitrary URL. The instruction pointer
958−--- is moved to the right position within the procedure to handle the request.
959−---
960−--- However this is transparent to the programmer, who codify in the style of a console application.
961−-newtype FlowM v m a= FlowM {runFlowM :: FlowMM v m a} deriving (Monad,MonadIO,Functor,MonadState(MFlowState v))
962−-flowM= FlowM
963−---runFlowM= runView
964−-
965−-{-# NOINLINE breturn #-}
966−-
967−--- | Use this instead of return to return from a computation with ask statements
968−---
969−--- This way when the user press the back button, the computation will execute back, to
970−--- the returned code, according with the user navigation.
971−-breturn :: (Monad m) => a -> FlowM v m a
972−-breturn = flowM . Sup . return . BackPoint -- !> "breturn"
973−-
974−-
975−-instance (Supervise s m,MonadIO m) => MonadIO (Sup m) where
976−- liftIO f= Sup $ liftIO f >>= \ x -> return $ NoBack x
977−-
978−-instance (Monad m,Functor m) => Functor (Sup m) where
979−- fmap f g= Sup $ do
980−- mr <- runSup g
981−- case mr of
982−- BackPoint x -> return . BackPoint $ f x
983−- NoBack x -> return . NoBack $ f x
984−- GoBack -> return $ GoBack
985−-
986−-
987−-liftSup f = Sup $ f >>= \x -> return $ NoBack x
988−-instance MonadTrans Sup where
989−- lift f = Sup $ f >>= \x -> return $ NoBack x
990−-
991−-
992−-instance (Supervise s m,MonadState s m) => MonadState s (Sup m) where
993−- get= lift get -- !> "get"
994−- put= lift . put
995−-
996−-type WState view m = StateT (MFlowState view) m
997−-type FlowMM view m= Sup (WState view m)
998−-
999−-data FormElm view a = FormElm view (Maybe a) deriving Typeable
1000−-
1001−-instance (Monoid view,Serialize a) => Serialize (FormElm view a) where
1002−- showp (FormElm _ x)= showp x
1003−- readp= readp >>= \x -> return $ FormElm mempty x
1004−-
1005−--- | @View v m a@ is a widget (formlet) with formatting `v` running the monad `m` (usually `IO`) and which return a value of type `a`
1006−---
1007−--- It has 'Applicative', 'Alternative' and 'Monad' instances.
1008−---
1009−--- Things to know about these instances:
1010−---
1011−--- If the View expression does not validate, ask will present the page again.
1012−---
1013−--- /Alternative instance/: Both alternatives are executed. The rest is as usual
1014−---
1015−--- /Monad Instance/:
1016−---
1017−--- The rendering of each statement is added to the previous. If you want to avoid this, use 'wcallback'
1018−---
1019−--- The execution is stopped when the statement has a formlet-widget that does not validate and
1020−--- return an invalid response (So it will present the page again if no other widget in the expression validates).
1021−---
1022−--- The monadic code is executed from the beginning each time the page is presented or refreshed
1023−---
1024−--- use 'pageFlow' if your page has more than one monadic computation with dynamic behaviour
1025−---
1026−--- use 'pageFlow' to identify each subflow branch of a conditional
1027−---
1028−--- For example:
1029−---
1030−--- > pageFlow "myid" $ do
1031−--- > r <- formlet1
1032−--- > liftIO $ ioaction1 r
1033−--- > s <- formlet2
1034−--- > liftIO $ ioaction2 s
1035−--- > case s of
1036−--- > True -> pageFlow "idtrue" $ do ....
1037−--- > False -> paeFlow "idfalse" $ do ...
1038−--- > ...
1039−---
1040−--- Here if @formlet2@ do not validate, @ioaction2@ is not executed. But if @formLet1@ validates and the
1041−--- page is refreshed two times (because @formlet2@ has failed, see above),then @ioaction1@ is executed two times.
1042−--- use 'cachedByKey' if you want to avoid repeated IO executions.
1043−-newtype View v m a = View { runView :: WState v m (FormElm v a)}
1044−-
1045−-
1046−-instance Monad m => Supervise (MFlowState v) (WState v m) where
1047−- supBack st= do -- the previous state is recovered, with the exception of these fields:
1048−- MFlowState{..} <- get
1049−- put st{ mfEnv= mfEnv,mfToken=mfToken
1050−- , mfPath=mfPath
1051−- , mfData=mfData
1052−- , mfTrace= mfTrace
1053−+
1054−+--
1055−+---- for traces
1056−+--
1057−+
1058−+import Control.Exception as CE
1059−+import Control.Concurrent
1060−+import Control.Monad.Loc
1061−+
1062−+-- debug
1063−+import Debug.Trace
1064−+(!>) = flip trace
1065−+
1066−+
1067−+data FailBack a = BackPoint a | NoBack a | GoBack deriving (Show,Typeable)
1068−+
1069−+instance Functor FailBack where
1070−+ fmap f GoBack= GoBack
1071−+ fmap f (BackPoint x)= BackPoint $ f x
1072−+ fmap f (NoBack x)= NoBack $ f x
1073−+
1074−+instance Applicative FailBack where
1075−+ pure x = NoBack x
1076−+ _ <*> GoBack = GoBack
1077−+ GoBack <*> _ = GoBack
1078−+ k <*> x = NoBack $ (fromFailBack k) (fromFailBack x)
1079−+
1080−+instance Alternative FailBack where
1081−+ empty= GoBack
1082−+ GoBack <|> f = f
1083−+ f <|> _ = f
1084−+
1085−+instance (Serialize a) => Serialize (FailBack a ) where
1086−+ showp (BackPoint x)= insertString (fromString iCanFailBack) >> showp x
1087−+ showp (NoBack x) = insertString (fromString noFailBack) >> showp x
1088−+ showp GoBack = insertString (fromString repeatPlease)
1089−+
1090−+ readp = choice [icanFailBackp,repeatPleasep,noFailBackp]
1091−+ where
1092−+ noFailBackp = symbol noFailBack >> readp >>= return . NoBack
1093−+ icanFailBackp = symbol iCanFailBack >> readp >>= return . BackPoint
1094−+ repeatPleasep = symbol repeatPlease >> return GoBack
1095−+
1096−+iCanFailBack= "B"
1097−+repeatPlease= "G"
1098−+noFailBack= "N"
1099−+
1100−+newtype Sup m a = Sup { runSup :: m (FailBack a ) }
1101−+
1102−+class MonadState s m => Supervise s m where
1103−+ supBack :: s -> m () -- called before backtracing. state passed is the previous
1104−+ supBack = const $ return () -- By default the state passed is the last one
1105−+
1106−+ supervise :: m (FailBack a) -> m (FailBack a)
1107−+ supervise= id
1108−+
1109−+
1110−+
1111−+instance (Supervise s m)=> Monad (Sup m) where
1112−+ fail _ = Sup . return $ GoBack
1113−+ return x = Sup . return $ NoBack x
1114−+ x >>= f = Sup $ loop
1115−+ where
1116−+ loop = do
1117−+ s <- get
1118−+ v <- supervise $ runSup x -- !> "loop"
1119−+ case v of
1120−+ NoBack y -> supervise $ runSup (f y) -- !> "runback"
1121−+ BackPoint y -> do
1122−+ z <- supervise $ runSup (f y) -- !> "BACK"
1123−+ case z of
1124−+ GoBack -> supBack s >> loop -- !> "BACKTRACKING"
1125−+ other -> return other
1126−+ GoBack -> return $ GoBack
1127−+
1128−+
1129−+fromFailBack (NoBack x) = x
1130−+fromFailBack (BackPoint x)= x
1131−+toFailBack x= NoBack x
1132−+
1133−+instance (Monad m,Applicative m) => Applicative (Sup m) where
1134−+ pure x = Sup . return $ NoBack x
1135−+ f <*> g= Sup $ do
1136−+ k <- runSup f
1137−+ x <- runSup g
1138−+ return $ k <*> x
1139−+
1140−+instance(Monad m, Applicative m) => Alternative (Sup m) where
1141−+ empty = Sup . return $ GoBack
1142−+ f <|> g= Sup $ do
1143−+ x <- runSup f
1144−+ case x of
1145−+ GoBack -> runSup g !> "GOBACK"
1146−+ _ -> return x
1147−+
1148−+-- | the FlowM monad executes the page navigation. It perform Backtracking when necessary to syncronize
1149−+-- when the user press the back button or when the user enter an arbitrary URL. The instruction pointer
1150−+-- is moved to the right position within the procedure to handle the request.
1151−+--
1152−+-- However this is transparent to the programmer, who codify in the style of a console application.
1153−+newtype FlowM v m a= FlowM {runFlowM :: FlowMM v m a}
1154−+ deriving (Applicative,Alternative,Monad,MonadIO,Functor
1155−+ ,MonadState(MFlowState v))
1156−+
1157−+--runFlowM= runView
1158−+
1159−+{-# NOINLINE breturn #-}
1160−+
1161−+-- | Use this instead of return to return from a computation with ask statements
1162−+--
1163−+-- This way when the user press the back button, the computation will execute back, to
1164−+-- the returned code, according with the user navigation.
1165−+breturn :: (Monad m) => a -> FlowM v m a
1166−+breturn = FlowM . Sup . return . BackPoint -- !> "breturn"
1167−+
1168−+
1169−+instance (Supervise s m,MonadIO m) => MonadIO (Sup m) where
1170−+ liftIO f= Sup $ liftIO f >>= \ x -> return $ NoBack x
1171−+
1172−+instance (Monad m,Functor m) => Functor (Sup m) where
1173−+ fmap f g= Sup $ do
1174−+ mr <- runSup g
1175−+ case mr of
1176−+ BackPoint x -> return . BackPoint $ f x
1177−+ NoBack x -> return . NoBack $ f x
1178−+ GoBack -> return $ GoBack
1179−+
1180−+
1181−+liftSup f = Sup $ f >>= \x -> return $ NoBack x
1182−+instance MonadTrans Sup where
1183−+ lift f = Sup $ f >>= \x -> return $ NoBack x
1184−+
1185−+
1186−+instance (Supervise s m,MonadState s m) => MonadState s (Sup m) where
1187−+ get= lift get -- !> "get"
1188−+ put= lift . put
1189−+
1190−+type WState view m = StateT (MFlowState view) m
1191−+type FlowMM view m= Sup (WState view m)
1192−+
1193−+data FormElm view a = FormElm view (Maybe a) deriving Typeable
1194−+
1195−+instance (Monoid view,Serialize a) => Serialize (FormElm view a) where
1196−+ showp (FormElm _ x)= showp x
1197−+ readp= readp >>= \x -> return $ FormElm mempty x
1198−+
1199−+
1200−+-- | @View v m a@ is a widget (formlet) with formatting `v` running the monad `m` (usually `IO`) and which return a value of type `a`
1201−+--
1202−+-- It has 'Applicative', 'Alternative' and 'Monad' instances.
1203−+--
1204−+-- Things to know about these instances:
1205−+--
1206−+-- If the View expression does not validate, ask will present the page again.
1207−+--
1208−+-- /Alternative instance/: Both alternatives are executed. The rest is as usual
1209−+--
1210−+-- /Monad Instance/:
1211−+--
1212−+-- The rendering of each statement is added to the previous. If you want to avoid this, use 'wcallback'
1213−+--
1214−+-- The execution is stopped when the statement has a formlet-widget that does not validate and
1215−+-- return an invalid response (So it will present the page again if no other widget in the expression validates).
1216−+--
1217−+-- The monadic code is executed from the beginning each time the page is presented or refreshed
1218−+--
1219−+-- use 'pageFlow' if your page has more than one monadic computation with dynamic behaviour
1220−+--
1221−+-- use 'pageFlow' to identify each subflow branch of a conditional
1222−+--
1223−+-- For example:
1224−+--
1225−+-- > pageFlow "myid" $ do
1226−+-- > r <- formlet1
1227−+-- > liftIO $ ioaction1 r
1228−+-- > s <- formlet2
1229−+-- > liftIO $ ioaction2 s
1230−+-- > case s of
1231−+-- > True -> pageFlow "idtrue" $ do ....
1232−+-- > False -> paeFlow "idfalse" $ do ...
1233−+-- > ...
1234−+--
1235−+-- Here if @formlet2@ do not validate, @ioaction2@ is not executed. But if @formLet1@ validates and the
1236−+-- page is refreshed two times (because @formlet2@ has failed, see above),then @ioaction1@ is executed two times.
1237−+-- use 'cachedByKey' if you want to avoid repeated IO executions.
1238−+newtype View v m a = View { runView :: WState v m (FormElm v a)}
1239−+
1240−+
1241−+instance Monad m => Supervise (MFlowState v) (WState v m) where
1242−+ supBack st= do -- the previous state is recovered, with the exception of these fields:
1243−+ MFlowState{..} <- get
1244−+ put st{ mfEnv= mfEnv,mfToken=mfToken
1245−+ , mfPath=mfPath
1246−+ , mfData=mfData
1247−+ , mfTrace= mfTrace
1248− , inSync=False
1249−- , newAsk=False}
1250−-
1251−-
1252−-
1253−-
1254−-instance MonadLoc (FlowM v IO) where
1255−- withLoc loc f = FlowM . Sup $ do
1256−- withLoc loc $ do
1257−- s <- get
1258−- (r,s') <- lift $ do
1259−- rs@(r,s') <- runStateT (runSup (runFlowM f) ) s
1260−- `CE.catch` (handler1 loc s)
1261−- case mfTrace s' of
1262−- [] -> return rs
1263−- trace -> return(r, s'{mfTrace= loc:trace})
1264−- put s'
1265−- return r
1266−-
1267−- where
1268−- handler1 loc s (e :: SomeException)= do
1269−- case CE.fromException e :: Maybe WFErrors of
1270−- Just e -> CE.throw e -- !> ("TROWNF=" ++ show e)
1271−- Nothing ->
1272−- case CE.fromException e :: Maybe AsyncException of
1273−- Just e -> CE.throw e -- !> ("TROWN ASYNCF=" ++ show e)
1274−- Nothing ->
1275−- return (GoBack, s{mfTrace= [show e]})
1276−-
1277−-
1278−---instance (Serialize a,Typeable a, FormInput v) => MonadLoc (FlowM v (Workflow IO)) a where
1279−--- withLoc loc f = FlowM . Sup $
1280−--- withLoc loc $ do
1281−--- s <- get
1282−--- (r,s') <- lift . WF.step $ exec1d "jkkjk" ( runStateT (runSup $ runFlowM f) s) `CMT.catch` (handler1 loc s)
1283−--- put s'
1284−--- return r
1285−---
1286−--- where
1287−--- handler1 loc s (e :: SomeException)=
1288−--- return (GoBack, s{mfTrace= Just ["exception: " ++show e]})
1289−-
1290−-instance FormInput v => MonadLoc (View v IO) where
1291−- withLoc loc f = View $ do
1292−- withLoc loc $ do
1293−- s <- get
1294−- (r,s') <- lift $ do
1295−- rs@(r,s') <- runStateT (runView f) s
1296−- `CE.catch` (handler1 loc s)
1297−- case mfTrace s' of
1298−- [] -> return rs
1299−- trace -> return(r, s'{mfTrace= loc:trace})
1300−- put s'
1301−- return r
1302−-
1303−- where
1304−- handler1 loc s (e :: SomeException)= do
1305−- case CE.fromException e :: Maybe WFErrors of
1306−- Just e -> CE.throw e -- !> ("TROWN=" ++ show e)
1307−- Nothing ->
1308−- case CE.fromException e :: Maybe AsyncException of
1309−- Just e -> CE.throw e -- !> ("TROWN ASYNC=" ++ show e)
1310−- Nothing ->
1311−- return (FormElm mempty Nothing, s{mfTrace= [show e]}) -- !> loc
1312−-
1313−-
1314−-
1315−-
1316−-
1317−-
1318−-
1319−-instance Functor (FormElm view ) where
1320−- fmap f (FormElm form x)= FormElm form (fmap f x)
1321−-
1322−-instance (Monad m,Functor m) => Functor (View view m) where
1323−- fmap f x= View $ fmap (fmap f) $ runView x
1324−-
1325−-
1326−-instance (Monoid view,Functor m, Monad m) => Applicative (View view m) where
1327−- pure a = View . return . FormElm mempty $ Just a
1328−- View f <*> View g= View $
1329−- f >>= \(FormElm form1 k) ->
1330−- g >>= \(FormElm form2 x) ->
1331−- return $ FormElm (form1 `mappend` form2) (k <*> x)
1332−-
1333−-instance (FormInput view,Functor m, Monad m) => Alternative (View view m) where
1334−- empty= View $ return $ FormElm mempty Nothing
1335−+ , newAsk=False}
1336−+
1337−+
1338−+
1339−+
1340−+instance MonadLoc (FlowM v IO) where
1341−+ withLoc loc f = FlowM . Sup $ do
1342−+ withLoc loc $ do
1343−+ s <- get
1344−+ (r,s') <- lift $ do
1345−+ rs@(r,s') <- runStateT (runSup (runFlowM f) ) s
1346−+ `CE.catch` (handler1 loc s)
1347−+ case mfTrace s' of
1348−+ [] -> return rs
1349−+ trace -> return(r, s'{mfTrace= loc:trace})
1350−+ put s'
1351−+ return r
1352−+
1353−+ where
1354−+ handler1 loc s (e :: SomeException)= do
1355−+ case CE.fromException e :: Maybe WFErrors of
1356−+ Just e -> CE.throw e -- !> ("TROWNF=" ++ show e)
1357−+ Nothing ->
1358−+ case CE.fromException e :: Maybe AsyncException of
1359−+ Just e -> CE.throw e -- !> ("TROWN ASYNCF=" ++ show e)
1360−+ Nothing ->
1361−+ return (GoBack, s{mfTrace= [show e]})
1362−+
1363−+
1364−+--instance (Serialize a,Typeable a, FormInput v) => MonadLoc (FlowM v (Workflow IO)) a where
1365−+-- withLoc loc f = FlowM . Sup $
1366−+-- withLoc loc $ do
1367−+-- s <- get
1368−+-- (r,s') <- lift . WF.step $ exec1d "jkkjk" ( runStateT (runSup $ runFlowM f) s) `CMT.catch` (handler1 loc s)
1369−+-- put s'
1370−+-- return r
1371−+--
1372−+-- where
1373−+-- handler1 loc s (e :: SomeException)=
1374−+-- return (GoBack, s{mfTrace= Just ["exception: " ++show e]})
1375−+
1376−+instance FormInput v => MonadLoc (View v IO) where
1377−+ withLoc loc f = View $ do
1378−+ withLoc loc $ do
1379−+ s <- get
1380−+ (r,s') <- lift $ do
1381−+ rs@(r,s') <- runStateT (runView f) s
1382−+ `CE.catch` (handler1 loc s)
1383−+ case mfTrace s' of
1384−+ [] -> return rs
1385−+ trace -> return(r, s'{mfTrace= loc:trace})
1386−+ put s'
1387−+ return r
1388−+
1389−+ where
1390−+ handler1 loc s (e :: SomeException)= do
1391−+ case CE.fromException e :: Maybe WFErrors of
1392−+ Just e -> CE.throw e -- !> ("TROWN=" ++ show e)
1393−+ Nothing ->
1394−+ case CE.fromException e :: Maybe AsyncException of
1395−+ Just e -> CE.throw e -- !> ("TROWN ASYNC=" ++ show e)
1396−+ Nothing ->
1397−+ return (FormElm mempty Nothing, s{mfTrace= [show e]}) -- !> loc
1398−+
1399−+
1400−+
1401−+
1402−+
1403−+
1404−+
1405−+instance Functor (FormElm view ) where
1406−+ fmap f (FormElm form x)= FormElm form (fmap f x)
1407−+
1408−+instance (Monad m,Functor m) => Functor (View view m) where
1409−+ fmap f x= View $ fmap (fmap f) $ runView x
1410−+
1411−+
1412−+instance (Monoid view,Functor m, Monad m) => Applicative (View view m) where
1413−+ pure a = View . return . FormElm mempty $ Just a
1414−+ View f <*> View g= View $
1415−+ f >>= \(FormElm form1 k) ->
1416−+ g >>= \(FormElm form2 x) ->
1417−+ return $ FormElm (form1 `mappend` form2) (k <*> x)
1418−+
1419−+instance (FormInput view,Functor m, Monad m) => Alternative (View view m) where
1420−+ empty= View $ return $ FormElm mempty Nothing
1421− View f <|> View g= View $ do
1422−- path <- gets mfPagePath
1423−+ path <- gets mfPagePath
1424− FormElm form1 k <- f
1425− s1 <- get
1426− let path1 = mfPagePath s1
1427−- put s1{mfPagePath=path}
1428−+ put s1{mfPagePath=path}
1429− FormElm form2 x <- g
1430− s2 <- get
1431− (mix,hasform) <- controlForms s1 s2 form1 form2
1432−@@ -317,259 +349,259 @@
1433− (_,Just _) -> path2
1434− _ -> path
1435− if hasform then put s2{needForm= HasForm,mfPagePath= path3}
1436−- else put s2{mfPagePath=path3}
1437−- return $ FormElm mix (k <|> x)
1438−-
1439−-
1440−-instance (FormInput view, Monad m) => Monad (View view m) where
1441−- View x >>= f = View $ do
1442−- FormElm form1 mk <- x
1443−- case mk of
1444−- Just k -> do
1445−+ else put s2{mfPagePath=path3}
1446−+ return $ FormElm mix (k <|> x)
1447−+
1448−+
1449−+instance (FormInput view, Monad m) => Monad (View view m) where
1450−+ View x >>= f = View $ do
1451−+ FormElm form1 mk <- x
1452−+ case mk of
1453−+ Just k -> do
1454− st'' <- get
1455− let st = st''{ linkMatched = False }
1456−- put st
1457−+ put st
1458− FormElm form2 mk <- runView $ f k
1459− st' <- get
1460− (mix, hasform) <- controlForms st st' form1 form2
1461− when hasform $ put st'{needForm= HasForm}
1462−-
1463−- return $ FormElm mix mk
1464−- Nothing ->
1465−- return $ FormElm form1 Nothing
1466−-
1467−-
1468−-
1469−- return = View . return . FormElm mempty . Just
1470−--- fail msg= View . return $ FormElm [inRed msg] Nothing
1471−-
1472−-
1473−-
1474−-
1475−-instance (FormInput v,Monad m, Functor m, Monoid a) => Monoid (View v m a) where
1476−- mappend x y = mappend <$> x <*> y -- beware that both operands must validate to generate a sum
1477−- mempty= return mempty
1478−-
1479−-
1480−--- | It is a callback in the view monad. The callback rendering substitutes the widget rendering
1481−--- when the latter is validated, without afecting the rendering of other widgets. This allow
1482−--- the simultaneous execution of different behaviours in different widgets in the
1483−--- same page. The inspiration is the callback primitive in the Seaside Web Framework
1484−--- that allows similar functionality (See <http://www.seaside.st>)
1485−---
1486−--- This is the visible difference with 'waction' callbacks, which execute a
1487−--- a flow in the FlowM monad that takes complete control of the navigation, while wactions are
1488−--- executed whithin the same page.
1489−-wcallback
1490−- :: Monad m =>
1491−- View view m a -> (a -> View view m b) -> View view m b
1492−-wcallback (View x) f = View $ do
1493−- FormElm form1 mk <- x
1494−- case mk of
1495−- Just k -> do
1496−- modify $ \st -> st{linkMatched= False, needForm=NoElems}
1497−+
1498−+ return $ FormElm mix mk
1499−+ Nothing ->
1500−+ return $ FormElm form1 Nothing
1501−+
1502−+
1503−+
1504−+ return = View . return . FormElm mempty . Just
1505−+-- fail msg= View . return $ FormElm [inRed msg] Nothing
1506−+
1507−+
1508−+
1509−+
1510−+instance (FormInput v,Monad m, Functor m, Monoid a) => Monoid (View v m a) where
1511−+ mappend x y = mappend <$> x <*> y -- beware that both operands must validate to generate a sum
1512−+ mempty= return mempty
1513−+
1514−+
1515−+-- | It is a callback in the view monad. The callback rendering substitutes the widget rendering
1516−+-- when the latter is validated, without afecting the rendering of other widgets. This allow
1517−+-- the simultaneous execution of different behaviours in different widgets in the
1518−+-- same page. The inspiration is the callback primitive in the Seaside Web Framework
1519−+-- that allows similar functionality (See <http://www.seaside.st>)
1520−+--
1521−+-- This is the visible difference with 'waction' callbacks, which execute a
1522−+-- a flow in the FlowM monad that takes complete control of the navigation, while wactions are
1523−+-- executed whithin the same page.
1524−+wcallback
1525−+ :: Monad m =>
1526−+ View view m a -> (a -> View view m b) -> View view m b
1527−+wcallback (View x) f = View $ do
1528−+ FormElm form1 mk <- x
1529−+ case mk of
1530−+ Just k -> do
1531−+ modify $ \st -> st{linkMatched= False, needForm=NoElems}
1532− runView (f k)
1533−-
1534−- Nothing -> return $ FormElm form1 Nothing
1535−-
1536−-
1537−-
1538−-
1539−-
1540−-
1541−-instance Monoid view => MonadTrans (View view) where
1542−- lift f = View $ (lift f) >>= \x -> return $ FormElm mempty $ Just x
1543−-
1544−-instance MonadTrans (FlowM view) where
1545−- lift f = FlowM $ lift (lift f) -- >>= \x -> return x
1546−-
1547−-instance (FormInput view, Monad m)=> MonadState (MFlowState view) (View view m) where
1548−- get = View $ get >>= \x -> return $ FormElm mempty $ Just x
1549−- put st = View $ put st >>= \x -> return $ FormElm mempty $ Just x
1550−-
1551−---instance (Monad m)=> MonadState (MFlowState view) (FlowM view m) where
1552−--- get = FlowM $ get >>= \x -> return $ FormElm [] $ Just x
1553−--- put st = FlowM $ put st >>= \x -> return $ FormElm [] $ Just x
1554−-
1555−-
1556−-instance (FormInput view,MonadIO m) => MonadIO (View view m) where
1557−- liftIO io= let x= liftIO io in x `seq` lift x -- to force liftIO==unsafePerformIO on the Identity monad
1558−-
1559−--- | Execute the widget in a monad and return the result in another.
1560−-changeMonad :: (Monad m, Executable m1)
1561−- => View v m1 a -> View v m a
1562−-changeMonad w= View . StateT $ \s ->
1563−- let (r,s')= execute $ runStateT ( runView w) s
1564−- in mfSequence s' `seq` return (r,s')
1565−+
1566−+ Nothing -> return $ FormElm form1 Nothing
1567−+
1568−+
1569−+
1570−+
1571−+
1572−+
1573−+instance Monoid view => MonadTrans (View view) where
1574−+ lift f = View $ (lift f) >>= \x -> return $ FormElm mempty $ Just x
1575−+
1576−+instance MonadTrans (FlowM view) where
1577−+ lift f = FlowM $ lift (lift f) -- >>= \x -> return x
1578−+
1579−+instance (FormInput view, Monad m)=> MonadState (MFlowState view) (View view m) where
1580−+ get = View $ get >>= \x -> return $ FormElm mempty $ Just x
1581−+ put st = View $ put st >>= \x -> return $ FormElm mempty $ Just x
1582−+
1583−+--instance (Monad m)=> MonadState (MFlowState view) (FlowM view m) where
1584−+-- get = FlowM $ get >>= \x -> return $ FormElm [] $ Just x
1585−+-- put st = FlowM $ put st >>= \x -> return $ FormElm [] $ Just x
1586−+
1587−+
1588−+instance (FormInput view,MonadIO m) => MonadIO (View view m) where
1589−+ liftIO io= let x= liftIO io in x `seq` lift x -- to force liftIO==unsafePerformIO on the Identity monad
1590−+
1591−+-- | Execute the widget in a monad and return the result in another.
1592−+changeMonad :: (Monad m, Executable m1)
1593−+ => View v m1 a -> View v m a
1594−+changeMonad w= View . StateT $ \s ->
1595−+ let (r,s')= execute $ runStateT ( runView w) s
1596−+ in mfSequence s' `seq` return (r,s')
1597−
1598−
1599−
1600− ----- some combinators ----
1601−-
1602−--- | Join two widgets in the same page
1603−--- the resulting widget, when `ask`ed with it, return a 2 tuple of their validation results
1604−--- if both return Noting, the widget return @Nothing@ (invalid).
1605−---
1606−--- it has a low infix priority: @infixr 2@
1607−---
1608−--- > r <- ask widget1 <+> widget2
1609−--- > case r of (Just x, Nothing) -> ..
1610−-(<+>) , mix :: (Monad m, FormInput view)
1611−- => View view m a
1612−- -> View view m b
1613−- -> View view m (Maybe a, Maybe b)
1614−-mix digest1 digest2= View $ do
1615−+
1616−+-- | Join two widgets in the same page
1617−+-- the resulting widget, when `ask`ed with it, return a 2 tuple of their validation results
1618−+-- if both return Noting, the widget return @Nothing@ (invalid).
1619−+--
1620−+-- it has a low infix priority: @infixr 2@
1621−+--
1622−+-- > r <- ask widget1 <+> widget2
1623−+-- > case r of (Just x, Nothing) -> ..
1624−+(<+>) , mix :: (Monad m, FormInput view)
1625−+ => View view m a
1626−+ -> View view m b
1627−+ -> View view m (Maybe a, Maybe b)
1628−+mix digest1 digest2= View $ do
1629− FormElm f1 mx' <- runView digest1
1630−- s1 <- get
1631−+ s1 <- get
1632− FormElm f2 my' <- runView digest2
1633− s2 <- get
1634− (mix, hasform) <- controlForms s1 s2 f1 f2
1635−- when hasform $ put s2{needForm= HasForm}
1636−- return $ FormElm mix
1637−- $ case (mx',my') of
1638−- (Nothing, Nothing) -> Nothing
1639−- other -> Just other
1640−-
1641−-infixr 2 <+>
1642−-
1643−-(<+>) = mix
1644−-
1645−-
1646−-
1647−--- | The first elem result (even if it is not validated) is discarded, and the secod is returned
1648−--- . This contrast with the applicative operator '*>' which fails the whole validation if
1649−--- the validation of the first elem fails.
1650−---
1651−--- The first element is displayed however, as happens in the case of '*>' .
1652−---
1653−--- Here @w\'s@ are widgets and @r\'s@ are returned values
1654−---
1655−--- @(w1 <* w2)@ will return @Just r1@ only if w1 and w2 are validated
1656−---
1657−--- @(w1 <** w2)@ will return @Just r1@ even if w2 is not validated
1658−---
1659−--- it has a low infix priority: @infixr 1@
1660−-
1661−-(**>) :: (Functor m, Monad m, FormInput view)
1662−- => View view m a -> View view m b -> View view m b
1663−+ when hasform $ put s2{needForm= HasForm}
1664−+ return $ FormElm mix
1665−+ $ case (mx',my') of
1666−+ (Nothing, Nothing) -> Nothing
1667−+ other -> Just other
1668−+
1669−+infixr 2 <+>
1670−+
1671−+(<+>) = mix
1672−+
1673−+
1674−+
1675−+-- | The first elem result (even if it is not validated) is discarded, and the secod is returned
1676−+-- . This contrast with the applicative operator '*>' which fails the whole validation if
1677−+-- the validation of the first elem fails.
1678−+--
1679−+-- The first element is displayed however, as happens in the case of '*>' .
1680−+--
1681−+-- Here @w\'s@ are widgets and @r\'s@ are returned values
1682−+--
1683−+-- @(w1 <* w2)@ will return @Just r1@ only if w1 and w2 are validated
1684−+--
1685−+-- @(w1 <** w2)@ will return @Just r1@ even if w2 is not validated
1686−+--
1687−+-- it has a low infix priority: @infixr 1@
1688−+
1689−+(**>) :: (Functor m, Monad m, FormInput view)
1690−+ => View view m a -> View view m b -> View view m b
1691− --(**>) form1 form2 = valid form1 *> form2
1692− (**>) f g = View $ do
1693− FormElm form1 k <- runView $ valid f
1694−- s1 <- get
1695−+ s1 <- get
1696− FormElm form2 x <- runView g
1697− s2 <- get
1698− (mix,hasform) <- controlForms s1 s2 form1 form2
1699−- when hasform $ put s2{needForm= HasForm}
1700−- return $ FormElm mix (k *> x)
1701−-
1702−-
1703−-
1704−-valid form= View $ do
1705−- FormElm form mx <- runView form
1706−- return $ FormElm form $ Just undefined
1707−-
1708−-infixr 1 **> , <**
1709−-
1710−--- | The second elem result (even if it is not validated) is discarded, and the first is returned
1711−--- . This contrast with the applicative operator '*>' which fails the whole validation if
1712−--- the validation of the second elem fails.
1713−--- The second element is displayed however, as in the case of '<*'.
1714−--- see the `<**` examples
1715−---
1716−--- it has a low infix priority: @infixr 1@
1717−-(<**) :: (Functor m, Monad m, FormInput view) =>
1718−- View view m a -> View view m b -> View view m a
1719−--- (<**) form1 form2 = form1 <* valid form2
1720−+ when hasform $ put s2{needForm= HasForm}
1721−+ return $ FormElm mix (k *> x)
1722−+
1723−+
1724−+
1725−+valid form= View $ do
1726−+ FormElm form mx <- runView form
1727−+ return $ FormElm form $ Just undefined
1728−+
1729−+infixr 1 **> , <**
1730−+
1731−+-- | The second elem result (even if it is not validated) is discarded, and the first is returned
1732−+-- . This contrast with the applicative operator '*>' which fails the whole validation if
1733−+-- the validation of the second elem fails.
1734−+-- The second element is displayed however, as in the case of '<*'.
1735−+-- see the `<**` examples
1736−+--
1737−+-- it has a low infix priority: @infixr 1@
1738−+(<**) :: (Functor m, Monad m, FormInput view) =>
1739−+ View view m a -> View view m b -> View view m a
1740−+-- (<**) form1 form2 = form1 <* valid form2
1741− (<**) f g = View $ do
1742− FormElm form1 k <- runView f
1743−- s1 <- get
1744−+ s1 <- get
1745− FormElm form2 x <- runView $ valid g
1746− s2 <- get
1747− (mix,hasform) <- controlForms s1 s2 form1 form2
1748−- when hasform $ put s2{needForm= HasForm}
1749−- return $ FormElm mix (k <* x)
1750−-
1751−+ when hasform $ put s2{needForm= HasForm}
1752−+ return $ FormElm mix (k <* x)
1753−+
1754−
1755−
1756− -------- Flow control
1757−-
1758−--- | True if the flow is going back (as a result of the back button pressed in the web browser).
1759−--- Usually this check is nos necessary unless conditional code make it necessary
1760−---
1761−--- @menu= do
1762−--- mop <- getGoStraighTo
1763−--- case mop of
1764−--- Just goop -> goop
1765−--- Nothing -> do
1766−--- r \<- `ask` option1 \<|> option2
1767−--- case r of
1768−--- op1 -> setGoStraighTo (Just goop1) >> goop1
1769−--- op2 -> setGoStraighTo (Just goop2) >> goop2@
1770−---
1771−--- This pseudocode below would execute the ask of the menu once. But the user will never have
1772−--- the possibility to see the menu again. To let him choose other option, the code
1773−--- has to be change to
1774−---
1775−--- @menu= do
1776−--- mop <- getGoStraighTo
1777−--- back <- `goingBack`
1778−--- case (mop,back) of
1779−--- (Just goop,False) -> goop
1780−--- _ -> do
1781−--- r \<- `ask` option1 \<|> option2
1782−--- case r of
1783−--- op1 -> setGoStraighTo (Just goop1) >> goop1
1784−--- op2 -> setGoStraighTo (Just goop2) >> goop2@
1785−---
1786−--- However this is very specialized. Normally the back button detection is not necessary.
1787−--- In a persistent flow (with step) even this default entry option would be completely automatic,
1788−--- since the process would restart at the last page visited.
1789−-goingBack :: MonadState (MFlowState view) m => m Bool
1790−-goingBack = do
1791−- st <- get
1792−- return $ not (inSync st) && not (newAsk st)
1793−-
1794−--- | Will prevent the Suprack beyond the point where 'preventGoingBack' is located.
1795−--- If the user press the back button beyond that point, the flow parameter is executed, usually
1796−--- it is an ask statement with a message. If the flow is not going back, it does nothing. It is a cut in Supracking
1797−---
1798−--- It is useful when an undoable transaction has been commited. For example, after a payment.
1799−---
1800−--- This example show a message when the user go back and press again to pay
1801−---
1802−--- > ask $ wlink () << b << "press here to pay 100000 $ "
1803−--- > payIt
1804−--- > preventGoingBack . ask $ b << "You paid 10000 $ one time"
1805−--- > ++> wlink () << b << " Please press here to complete the proccess"
1806−--- > ask $ wlink () << b << "OK, press here to go to the menu or press the back button to verify that you can not pay again"
1807−--- > where
1808−--- > payIt= liftIO $ print "paying"
1809−-
1810−-preventGoingBack
1811−- :: ( Functor m, MonadIO m, FormInput v) => FlowM v m () -> FlowM v m ()
1812−-preventGoingBack msg= do
1813−- back <- goingBack
1814−- if not back then breturn() else do
1815−- breturn() -- will not go back beyond this
1816−- clearEnv
1817−- modify $ \s -> s{newAsk= True}
1818−- msg
1819−-
1820−-
1821−--- | executes the first computation when going forward and the second computation when backtracking.
1822−--- Depending on how the second computation finishes, the flow will resume forward or backward.
1823−-onBacktrack :: Monad m => m a -> FlowM v m a -> FlowM v m a
1824−-onBacktrack doit onback= do
1825−- back <- goingBack
1826−- case back of
1827−- False -> (lift doit) >>= breturn
1828−- True -> onback
1829−-
1830−--- | less powerflul version of `onBacktrack`: The second computation simply undo the effect of
1831−--- the first one, and the flow continues backward ever. It can be used as a rollback mechanism in
1832−--- the context of long running transactions.
1833−-compensate :: Monad m => m a -> m a -> FlowM v m a
1834−-compensate doit undoit= doit `onBacktrack` ( (lift undoit) >> fail "")
1835−+
1836−+-- | True if the flow is going back (as a result of the back button pressed in the web browser).
1837−+-- Usually this check is nos necessary unless conditional code make it necessary
1838−+--
1839−+-- @menu= do
1840−+-- mop <- getGoStraighTo
1841−+-- case mop of
1842−+-- Just goop -> goop
1843−+-- Nothing -> do
1844−+-- r \<- `ask` option1 \<|> option2
1845−+-- case r of
1846−+-- op1 -> setGoStraighTo (Just goop1) >> goop1
1847−+-- op2 -> setGoStraighTo (Just goop2) >> goop2@
1848−+--
1849−+-- This pseudocode below would execute the ask of the menu once. But the user will never have
1850−+-- the possibility to see the menu again. To let him choose other option, the code
1851−+-- has to be change to
1852−+--
1853−+-- @menu= do
1854−+-- mop <- getGoStraighTo
1855−+-- back <- `goingBack`
1856−+-- case (mop,back) of
1857−+-- (Just goop,False) -> goop
1858−+-- _ -> do
1859−+-- r \<- `ask` option1 \<|> option2
1860−+-- case r of
1861−+-- op1 -> setGoStraighTo (Just goop1) >> goop1
1862−+-- op2 -> setGoStraighTo (Just goop2) >> goop2@
1863−+--
1864−+-- However this is very specialized. Normally the back button detection is not necessary.
1865−+-- In a persistent flow (with step) even this default entry option would be completely automatic,
1866−+-- since the process would restart at the last page visited.
1867−+goingBack :: MonadState (MFlowState view) m => m Bool
1868−+goingBack = do
1869−+ st <- get
1870−+ return $ not (inSync st) && not (newAsk st)
1871−+
1872−+-- | Will prevent the Suprack beyond the point where 'preventGoingBack' is located.
1873−+-- If the user press the back button beyond that point, the flow parameter is executed, usually
1874−+-- it is an ask statement with a message. If the flow is not going back, it does nothing. It is a cut in Supracking
1875−+--
1876−+-- It is useful when an undoable transaction has been commited. For example, after a payment.
1877−+--
1878−+-- This example show a message when the user go back and press again to pay
1879−+--
1880−+-- > ask $ wlink () << b << "press here to pay 100000 $ "
1881−+-- > payIt
1882−+-- > preventGoingBack . ask $ b << "You paid 10000 $ one time"
1883−+-- > ++> wlink () << b << " Please press here to complete the proccess"
1884−+-- > ask $ wlink () << b << "OK, press here to go to the menu or press the back button to verify that you can not pay again"
1885−+-- > where
1886−+-- > payIt= liftIO $ print "paying"
1887−+
1888−+preventGoingBack
1889−+ :: ( Functor m, MonadIO m, FormInput v) => FlowM v m () -> FlowM v m ()
1890−+preventGoingBack msg= do
1891−+ back <- goingBack
1892−+ if not back then breturn() else do
1893−+ breturn() -- will not go back beyond this
1894−+ clearEnv
1895−+ modify $ \s -> s{newAsk= True}
1896−+ msg
1897−+
1898−+
1899−+-- | executes the first computation when going forward and the second computation when backtracking.
1900−+-- Depending on how the second computation finishes, the flow will resume forward or backward.
1901−+onBacktrack :: Monad m => m a -> FlowM v m a -> FlowM v m a
1902−+onBacktrack doit onback= do
1903−+ back <- goingBack
1904−+ case back of
1905−+ False -> (lift doit) >>= breturn
1906−+ True -> onback
1907−+
1908−+-- | less powerflul version of `onBacktrack`: The second computation simply undo the effect of
1909−+-- the first one, and the flow continues backward ever. It can be used as a rollback mechanism in
1910−+-- the context of long running transactions.
1911−+compensate :: Monad m => m a -> m a -> FlowM v m a
1912−+compensate doit undoit= doit `onBacktrack` ( (lift undoit) >> fail "")
1913−
1914−
1915− --orElse :: FormInput v => FlowM v IO a -> FlowM v IO a -> FlowM v IO a
1916−@@ -595,91 +627,96 @@
1917− -- case mr of
1918− -- Nothing -> retry
1919− -- Just v -> return v
1920−-
1921−+
1922− type Lang= String
1923−
1924−-needForm1 st= case needForm st of
1925−- HasForm -> False
1926−- HasElems -> True
1927−- NoElems -> False
1928−-
1929−-data NeedForm= HasForm | HasElems | NoElems deriving Show
1930−-
1931−-data MFlowState view= MFlowState{
1932−- mfSequence :: Int,
1933−- mfCached :: Bool,
1934−- newAsk :: Bool,
1935−- inSync :: Bool,
1936−- mfLang :: Lang,
1937−- mfEnv :: Params,
1938−- needForm :: NeedForm,
1939−- mfToken :: Token,
1940−- mfkillTime :: Int,
1941−- mfSessionTime :: Integer,
1942−- mfCookies :: [Cookie],
1943−- mfHttpHeaders :: [(SB.ByteString,SB.ByteString)],
1944−- mfHeader :: view -> view,
1945−- mfDebug :: Bool,
1946−- mfRequirements :: [Requirement],
1947−- mfData :: M.Map TypeRep Void,
1948−- mfAjax :: Maybe (M.Map String Void),
1949−- mfSeqCache :: Int,
1950−- notSyncInAction :: Bool,
1951−-
1952−- -- Link management
1953−+--needForm1 st= case needForm st of
1954−+-- HasForm -> False
1955−+-- HasElems _ -> True
1956−+-- NoElems -> False
1957−+
1958−+
1959−+
1960−+data NeedForm= HasForm | HasElems | NoElems deriving Show
1961−+
1962−+data MFlowState view= MFlowState{
1963−+ mfSequence :: Int,
1964−+ mfCached :: Bool,
1965−+ newAsk :: Bool,
1966−+ inSync :: Bool,
1967−+ mfLang :: Lang,
1968−+ mfEnv :: Params,
1969−+ needForm :: NeedForm,
1970−+ mfFileUpload :: Bool,
1971−+ mfToken :: Token,
1972−+ mfkillTime :: Int,
1973−+ mfSessionTime :: Integer,
1974−+ mfCookies :: [Cookie],
1975−+ mfHttpHeaders :: [(SB.ByteString,SB.ByteString)],
1976−+ mfHeader :: view -> view,
1977−+ mfDebug :: Bool,
1978−+ mfRequirements :: [Requirement],
1979−+ mfInstalledScripts :: [WebRequirement],
1980−+ mfData :: M.Map TypeRep Void,
1981−+ mfAjax :: Maybe (M.Map String Void),
1982−+ mfSeqCache :: Int,
1983−+ notSyncInAction :: Bool,
1984−+
1985−+ -- Link management
1986− mfPath :: [String],
1987−- mfPagePath :: [String],
1988−- mfPrefix :: String,
1989−--- mfPIndex :: Int,
1990−- mfPageFlow :: Bool,
1991−+ mfPagePath :: [String],
1992−+ mfPrefix :: String,
1993−+-- mfPIndex :: Int,
1994−+ mfPageFlow :: Bool,
1995− linkMatched :: Bool,
1996−--- mfPendingPath :: [String],
1997−-
1998−-
1999−- mfAutorefresh :: Bool,
2000−- mfTrace :: [String],
2001−- mfClear :: Bool
2002−- }
2003−- deriving Typeable
2004−-
2005−-type Void = Char
2006−-
2007−-mFlowState0 :: (FormInput view) => MFlowState view
2008−-mFlowState0 = MFlowState 0 False True True "en"
2009−- [] NoElems (error "token of mFlowState0 used")
2010−- 0 0 [] [] stdHeader False [] M.empty Nothing 0 False [] [] "" False False False [] False
2011−-
2012−-
2013−--- | Set user-defined data in the context of the session.
2014−---
2015−--- The data is indexed by type in a map. So the user can insert-retrieve different kinds of data
2016−--- in the session context.
2017−---
2018−--- This example define @addHistory@ and @getHistory@ to maintain a Html log in the session of a Flow:
2019−---
2020−--- > newtype History = History ( Html) deriving Typeable
2021−--- > setHistory html= setSessionData $ History html
2022−--- > getHistory= getSessionData `onNothing` return (History mempty) >>= \(History h) -> return h
2023−--- > addHistory html= do
2024−--- > html' <- getHistory
2025−--- > setHistory $ html' `mappend` html
2026−-
2027−-setSessionData :: (Typeable a,MonadState (MFlowState view) m) => a -> m ()
2028−-setSessionData x=
2029−- modify $ \st -> st{mfData= M.insert (typeOf x ) (unsafeCoerce x) (mfData st)}
2030−-
2031−-delSessionData x=
2032−- modify $ \st -> st{mfData= M.delete (typeOf x ) (mfData st)}
2033−-
2034−--- | Get the session data of the desired type if there is any.
2035−-getSessionData :: (Typeable a, MonadState (MFlowState view) m) => m (Maybe a)
2036−-getSessionData = resp where
2037−- resp= gets mfData >>= \list ->
2038−- case M.lookup ( typeOf $ typeResp resp ) list of
2039−- Just x -> return . Just $ unsafeCoerce x
2040−- Nothing -> return $ Nothing
2041−- typeResp :: m (Maybe x) -> x
2042−- typeResp= undefined
2043−+-- mfPendingPath :: [String],
2044−+
2045−+
2046−+ mfAutorefresh :: Bool,
2047−+ mfTrace :: [String],
2048−+ mfClear :: Bool
2049−+ }
2050−+ deriving Typeable
2051−+
2052−+type Void = Char
2053−+
2054−+mFlowState0 :: (FormInput view) => MFlowState view
2055−+mFlowState0 = MFlowState 0 False True True "en"
2056−+ [] NoElems False (error "token of mFlowState0 used")
2057−+ 0 0 [] [] stdHeader False [] [] M.empty Nothing 0 False
2058−+ [] [] "" False False False [] False
2059−+
2060−+
2061−+-- | Set user-defined data in the context of the session.
2062−+--
2063−+-- The data is indexed by type in a map. So the user can insert-retrieve different kinds of data
2064−+-- in the session context.
2065−+--
2066−+-- This example define @addHistory@ and @getHistory@ to maintain a Html log in the session of a Flow:
2067−+--
2068−+-- > newtype History = History ( Html) deriving Typeable
2069−+-- > setHistory html= setSessionData $ History html
2070−+-- > getHistory= getSessionData `onNothing` return (History mempty) >>= \(History h) -> return h
2071−+-- > addHistory html= do
2072−+-- > html' <- getHistory
2073−+-- > setHistory $ html' `mappend` html
2074−+
2075−+setSessionData :: (Typeable a,MonadState (MFlowState view) m) => a -> m ()
2076−+setSessionData x=
2077−+ modify $ \st -> st{mfData= M.insert (typeOf x ) (unsafeCoerce x) (mfData st)}
2078−+
2079−+delSessionData x=
2080−+ modify $ \st -> st{mfData= M.delete (typeOf x ) (mfData st)}
2081−+
2082−+-- | Get the session data of the desired type if there is any.
2083−+getSessionData :: (Typeable a, MonadState (MFlowState view) m) => m (Maybe a)
2084−+getSessionData = resp where
2085−+ resp= gets mfData >>= \list ->
2086−+ case M.lookup ( typeOf $ typeResp resp ) list of
2087−+ Just x -> return . Just $ unsafeCoerce x
2088−+ Nothing -> return $ Nothing
2089−+ typeResp :: m (Maybe x) -> x
2090−+ typeResp= undefined
2091−
2092− -- | getSessionData specialized for the View monad. if Nothing, the monadic computation
2093− -- does not continue.
2094−@@ -691,554 +728,555 @@
2095− -- | Return the session identifier
2096− getSessionId :: MonadState (MFlowState v) m => m String
2097− getSessionId= gets mfToken >>= return . key
2098−-
2099−--- | Return the user language. Now it is fixed to "en"
2100−-getLang :: MonadState (MFlowState view) m => m String
2101−-getLang= gets mfLang
2102−-
2103−-getToken :: MonadState (MFlowState view) m => m Token
2104−-getToken= gets mfToken
2105−-
2106−-
2107−--- get a parameter form the las received response
2108−-getEnv :: MonadState (MFlowState view) m => m Params
2109−-getEnv = gets mfEnv
2110−-
2111−-stdHeader v = v
2112−-
2113−-
2114−--- | Set the header-footer that will enclose the widgets. It must be provided in the
2115−--- same formatting than them, altrough with normalization to byteStrings any formatting can be used
2116−---
2117−--- This header uses XML trough Haskell Server Pages (<http://hackage.haskell.org/package/hsp>)
2118−---
2119−--- @
2120−--- setHeader $ \c ->
2121−--- \<html\>
2122−--- \<head\>
2123−--- \<title\> my title \</title\>
2124−--- \<meta name= \"Keywords\" content= \"sci-fi\" /\>)
2125−--- \</head\>
2126−--- \<body style= \"margin-left:5%;margin-right:5%\"\>
2127−--- \<% c %\>
2128−--- \</body\>
2129−--- \</html\>
2130−--- @
2131−---
2132−--- This header uses "Text.XHtml"
2133−---
2134−--- @
2135−--- setHeader $ \c ->
2136−--- `thehtml`
2137−--- << (`header`
2138−--- << (`thetitle` << title +++
2139−--- `meta` ! [`name` \"Keywords\",content \"sci-fi\"])) +++
2140−--- `body` ! [`style` \"margin-left:5%;margin-right:5%\"] c
2141−--- @
2142−---
2143−--- This header uses both. It uses byteString tags
2144−---
2145−--- @
2146−--- setHeader $ \c ->
2147−--- `bhtml` [] $
2148−--- `btag` "head" [] $
2149−--- (`toByteString` (thetitle << title) `append`
2150−--- `toByteString` <meta name= \"Keywords\" content= \"sci-fi\" />) `append`
2151−--- `bbody` [(\"style\", \"margin-left:5%;margin-right:5%\")] c
2152−--- @
2153−---
2154−-setHeader :: MonadState (MFlowState view) m => (view -> view) -> m ()
2155−-setHeader header= do
2156−- fs <- get
2157−- put fs{mfHeader= header}
2158−-
2159−-
2160−-
2161−--- | Return the current header
2162−-getHeader :: ( Monad m) => FlowM view m (view -> view)
2163−-getHeader= gets mfHeader
2164−-
2165−--- | Add another header embedded in the previous one
2166−-addHeader new= do
2167−- fhtml <- getHeader
2168−- setHeader $ fhtml . new
2169−-
2170−--- | Set an HTTP cookie
2171−-setCookie :: MonadState (MFlowState view) m
2172−- => String -- ^ name
2173−- -> String -- ^ value
2174−- -> String -- ^ path
2175−- -> Maybe Integer -- ^ Max-Age in seconds. Nothing for a session cookie
2176−- -> m ()
2177−-setCookie n v p me=
2178−- modify $ \st -> st{mfCookies= (UnEncryptedCookie
2179−- ( SB.fromString n,
2180−- SB.fromString v,
2181−- SB.fromString p,
2182−- fmap (SB.fromString . show) me)):mfCookies st }
2183−-
2184−-setParanoidCookie :: MonadState (MFlowState view) m
2185−- => String -- ^ name
2186−- -> String -- ^ value
2187−- -> String -- ^ path
2188−+
2189−+-- | Return the user language. Now it is fixed to "en"
2190−+getLang :: MonadState (MFlowState view) m => m String
2191−+getLang= gets mfLang
2192−+
2193−+getToken :: MonadState (MFlowState view) m => m Token
2194−+getToken= gets mfToken
2195−+
2196−+
2197−+-- get a parameter form the las received response
2198−+getEnv :: MonadState (MFlowState view) m => m Params
2199−+getEnv = gets mfEnv
2200−+
2201−+stdHeader v = v
2202−+
2203−+
2204−+-- | Set the header-footer that will enclose the widgets. It must be provided in the
2205−+-- same formatting than them, altrough with normalization to byteStrings any formatting can be used
2206−+--
2207−+-- This header uses XML trough Haskell Server Pages (<http://hackage.haskell.org/package/hsp>)
2208−+--
2209−+-- @
2210−+-- setHeader $ \c ->
2211−+-- \<html\>
2212−+-- \<head\>
2213−+-- \<title\> my title \</title\>
2214−+-- \<meta name= \"Keywords\" content= \"sci-fi\" /\>)
2215−+-- \</head\>
2216−+-- \<body style= \"margin-left:5%;margin-right:5%\"\>
2217−+-- \<% c %\>
2218−+-- \</body\>
2219−+-- \</html\>
2220−+-- @
2221−+--
2222−+-- This header uses "Text.XHtml"
2223−+--
2224−+-- @
2225−+-- setHeader $ \c ->
2226−+-- `thehtml`
2227−+-- << (`header`
2228−+-- << (`thetitle` << title +++
2229−+-- `meta` ! [`name` \"Keywords\",content \"sci-fi\"])) +++
2230−+-- `body` ! [`style` \"margin-left:5%;margin-right:5%\"] c
2231−+-- @
2232−+--
2233−+-- This header uses both. It uses byteString tags
2234−+--
2235−+-- @
2236−+-- setHeader $ \c ->
2237−+-- `bhtml` [] $
2238−+-- `btag` "head" [] $
2239−+-- (`toByteString` (thetitle << title) `append`
2240−+-- `toByteString` <meta name= \"Keywords\" content= \"sci-fi\" />) `append`
2241−+-- `bbody` [(\"style\", \"margin-left:5%;margin-right:5%\")] c
2242−+-- @
2243−+--
2244−+setHeader :: MonadState (MFlowState view) m => (view -> view) -> m ()
2245−+setHeader header= do
2246−+ fs <- get
2247−+ put fs{mfHeader= header}
2248−+
2249−+
2250−+
2251−+-- | Return the current header
2252−+getHeader :: ( Monad m) => FlowM view m (view -> view)
2253−+getHeader= gets mfHeader
2254−+
2255−+-- | Add another header embedded in the previous one
2256−+addHeader new= do
2257−+ fhtml <- getHeader
2258−+ setHeader $ fhtml . new
2259−+
2260−+-- | Set an HTTP cookie
2261−+setCookie :: MonadState (MFlowState view) m
2262−+ => String -- ^ name
2263−+ -> String -- ^ value
2264−+ -> String -- ^ path
2265−+ -> Maybe Integer -- ^ Max-Age in seconds. Nothing for a session cookie
2266−+ -> m ()
2267−+setCookie n v p me=
2268−+ modify $ \st -> st{mfCookies= (UnEncryptedCookie
2269−+ ( SB.fromString n,
2270−+ SB.fromString v,
2271−+ SB.fromString p,
2272−+ fmap (SB.fromString . show) me)):mfCookies st }
2273−+
2274−+setParanoidCookie :: MonadState (MFlowState view) m
2275−+ => String -- ^ name
2276−+ -> String -- ^ value
2277−+ -> String -- ^ path
2278− -> Maybe Integer -- ^ Max-Age in seconds. Nothing for a session cookie
2279−- -> m ()
2280−-setParanoidCookie n v p me = setEncryptedCookie' n v p me paranoidEncryptCookie
2281−+ -> m ()
2282−+setParanoidCookie n v p me = setEncryptedCookie' n v p me paranoidEncryptCookie
2283−
2284−-setEncryptedCookie :: MonadState (MFlowState view) m
2285−- => String -- ^ name
2286−- -> String -- ^ value
2287−- -> String -- ^ path
2288−+setEncryptedCookie :: MonadState (MFlowState view) m
2289−+ => String -- ^ name
2290−+ -> String -- ^ value
2291−+ -> String -- ^ path
2292− -> Maybe Integer -- ^ Max-Age in seconds. Nothing for a session cookie
2293−- -> m ()
2294−-setEncryptedCookie n v p me = setEncryptedCookie' n v p me encryptCookie
2295−-
2296−-setEncryptedCookie' n v p me encFunc=
2297−- modify $ \st -> st{mfCookies =
2298−- (unsafePerformIO $ encFunc
2299−- ( SB.fromString n,
2300−- SB.fromString v,
2301−- SB.fromString p,
2302−- fmap (SB.fromString . show) me)):mfCookies st }
2303−-
2304−--- | Set an HTTP Response header
2305−-setHttpHeader :: MonadState (MFlowState view) m
2306−- => SB.ByteString -- ^ name
2307−- -> SB.ByteString -- ^ value
2308−- -> m ()
2309−-setHttpHeader n v =
2310−- modify $ \st -> st{mfHttpHeaders = nubBy (\ x y -> fst x == fst y) $ (n,v):mfHttpHeaders st}
2311−-
2312−-
2313−--- | Set
2314−--- 1) the timeout of the flow execution since the last user interaction.
2315−--- Once passed, the flow executes from the begining.
2316−---
2317−--- 2) In persistent flows
2318−--- it set the session state timeout for the flow, that is persistent. If the
2319−--- flow is not persistent, it has no effect.
2320−---
2321−--- As the other state primitives, it can be run in the Flow and in the View monad
2322−---
2323−--- `transient` flows restart anew.
2324−--- persistent flows (that use `step`) restart at the las saved execution point, unless
2325−--- the session time has expired for the user.
2326−-setTimeouts :: ( MonadState (MFlowState v) m) => Int -> Integer -> m ()
2327−-setTimeouts kt st= do
2328−- fs <- get
2329−- put fs{ mfkillTime= kt, mfSessionTime= st}
2330−-
2331−-
2332−-getWFName :: MonadState (MFlowState view) m => m String
2333−-getWFName = do
2334−- fs <- get
2335−- return . twfname $ mfToken fs
2336−-
2337−-getCurrentUser :: MonadState (MFlowState view) m => m String
2338−-getCurrentUser = do
2339−- st<- gets mfToken
2340−- return $ tuser st
2341−-
2342−-type Name= String
2343−-type Type= String
2344−-type Value= String
2345−-type Checked= Bool
2346−-type OnClick= Maybe String
2347−-
2348−-normalize :: (Monad m, FormInput v) => View v m a -> View B.ByteString m a
2349−-normalize f= View . StateT $ \s ->do
2350−- (FormElm fs mx, s') <- runStateT ( runView f) $ unsafeCoerce s
2351−- return (FormElm (toByteString fs ) mx,unsafeCoerce s')
2352−-
2353−-
2354−-
2355−--- | Minimal interface for defining the basic form and link elements. The core of MFlow is agnostic
2356−--- about the rendering package used. Every formatting (either HTML or not) used with MFlow must have an
2357−--- instance of this class.
2358−--- See "MFlow.Forms.Blaze.Html for the instance for blaze-html" "MFlow.Forms.XHtml" for the instance
2359−--- for @Text.XHtml@ and MFlow.Forms.HSP for the instance for Haskell Server Pages.
2360−-class (Monoid view,Typeable view) => FormInput view where
2361−- toByteString :: view -> B.ByteString
2362−- toHttpData :: view -> HttpData
2363−- fromStr :: String -> view
2364−- fromStrNoEncode :: String -> view
2365−- ftag :: String -> view -> view
2366−- inred :: view -> view
2367−- flink :: String -> view -> view
2368−- flink1:: String -> view
2369−- flink1 verb = flink verb (fromStr verb)
2370−- finput :: Name -> Type -> Value -> Checked -> OnClick -> view
2371−- ftextarea :: String -> T.Text -> view
2372−- fselect :: String -> view -> view
2373−- foption :: String -> view -> Bool -> view
2374−- foption1 :: String -> Bool -> view
2375−- foption1 val msel= foption val (fromStr val) msel
2376−- formAction :: String -> view -> view
2377−- attrs :: view -> Attribs -> view
2378−-
2379−-
2380−-
2381−---instance (MonadIO m) => MonadIO (FlowM view m) where
2382−--- liftIO io= let x= liftIO io in x `seq` lift x -- to force liftIO==unsafePerformIO onf the Identity monad
2383−-
2384−---instance Executable (View v m) where
2385−--- execute f = execute $ evalStateT f mFlowState0
2386−-
2387−-
2388−---instance (Monad m, Executable m, Monoid view, FormInput view)
2389−--- => Executable (StateT (MFlowState view) m) where
2390−--- execute f= execute $ evalStateT f mFlowState0
2391−-
2392−--- | Cached widgets operate with widgets in the Identity monad, but they may perform IO using the execute instance
2393−--- of the monad m, which is usually the IO monad. execute basically \"sanctifies\" the use of unsafePerformIO for a transient purpose
2394−--- such is caching. This is defined in "Data.TCache.Memoization". The programmer can create his
2395−--- own instance for his monad.
2396−---
2397−--- With `cachedWidget` it is possible to cache the rendering of a widget as a ByteString (maintaining type safety)
2398−---, permanently or for a certain time. this is very useful for complex widgets that present information. Specially it they must access to databases.
2399−---
2400−--- @
2401−--- import MFlow.Wai.Blaze.Html.All
2402−--- import Some.Time.Library
2403−--- addMessageFlows [(noscript, time)]
2404−--- main= run 80 waiMessageFlow
2405−--- time=do ask $ cachedWidget \"time\" 5
2406−--- $ wlink () b << \"the time is \" ++ show (execute giveTheTime) ++ \" click here\"
2407−--- time
2408−--- @
2409−---
2410−--- this pseudocode would update the time every 5 seconds. The execution of the IO computation
2411−--- giveTheTime must be executed inside the cached widget to avoid unnecesary IO executions.
2412−---
2413−--- NOTE: the rendering of cached widgets are shared by all users
2414−-cachedWidget :: (MonadIO m,Typeable view
2415−- , FormInput view, Typeable a, Executable m )
2416−- => String -- ^ The key of the cached object for the retrieval
2417−- -> Int -- ^ Timeout of the caching. Zero means the whole server run
2418−- -> View view Identity a -- ^ The cached widget, in the Identity monad
2419−- -> View view m a -- ^ The cached result
2420−-cachedWidget key t mf = View . StateT $ \s -> do
2421−- let((FormElm form _), sec)= execute $! cachedByKey key t $ proc mf s{mfCached=True}
2422−- let((FormElm _ mx2), s2) = execute $ runStateT ( runView mf) s{mfSeqCache= sec,mfCached=True}
2423−- let s''= s{inSync = inSync s2
2424−- ,mfRequirements=mfRequirements s2
2425−+ -> m ()
2426−+setEncryptedCookie n v p me = setEncryptedCookie' n v p me encryptCookie
2427−+
2428−+setEncryptedCookie' n v p me encFunc=
2429−+ modify $ \st -> st{mfCookies =
2430−+ (unsafePerformIO $ encFunc
2431−+ ( SB.fromString n,
2432−+ SB.fromString v,
2433−+ SB.fromString p,
2434−+ fmap (SB.fromString . show) me)):mfCookies st }
2435−+
2436−+-- | Set an HTTP Response header
2437−+setHttpHeader :: MonadState (MFlowState view) m
2438−+ => SB.ByteString -- ^ name
2439−+ -> SB.ByteString -- ^ value
2440−+ -> m ()
2441−+setHttpHeader n v =
2442−+ modify $ \st -> st{mfHttpHeaders = nubBy (\ x y -> fst x == fst y) $ (n,v):mfHttpHeaders st}
2443−+
2444−+
2445−+-- | Set
2446−+-- 1) the timeout of the flow execution since the last user interaction.
2447−+-- Once passed, the flow executes from the begining.
2448−+--
2449−+-- 2) In persistent flows
2450−+-- it set the session state timeout for the flow, that is persistent. If the
2451−+-- flow is not persistent, it has no effect.
2452−+--
2453−+-- As the other state primitives, it can be run in the Flow and in the View monad
2454−+--
2455−+-- `transient` flows restart anew.
2456−+-- persistent flows (that use `step`) restart at the las saved execution point, unless
2457−+-- the session time has expired for the user.
2458−+setTimeouts :: ( MonadState (MFlowState v) m) => Int -> Integer -> m ()
2459−+setTimeouts kt st= do
2460−+ fs <- get
2461−+ put fs{ mfkillTime= kt, mfSessionTime= st}
2462−+
2463−+
2464−+getWFName :: MonadState (MFlowState view) m => m String
2465−+getWFName = do
2466−+ fs <- get
2467−+ return . twfname $ mfToken fs
2468−+
2469−+getCurrentUser :: MonadState (MFlowState view) m => m String
2470−+getCurrentUser = do
2471−+ st<- gets mfToken
2472−+ return $ tuser st
2473−+
2474−+type Name= String
2475−+type Type= String
2476−+type Value= String
2477−+type Checked= Bool
2478−+type OnClick= Maybe String
2479−+
2480−+normalize :: (Monad m, FormInput v) => View v m a -> View B.ByteString m a
2481−+normalize f= View . StateT $ \s ->do
2482−+ (FormElm fs mx, s') <- runStateT ( runView f) $ unsafeCoerce s
2483−+ return (FormElm (toByteString fs ) mx,unsafeCoerce s')
2484−+
2485−+
2486−+
2487−+-- | Minimal interface for defining the basic form and link elements. The core of MFlow is agnostic
2488−+-- about the rendering package used. Every formatting (either HTML or not) used with MFlow must have an
2489−+-- instance of this class.
2490−+-- See "MFlow.Forms.Blaze.Html for the instance for blaze-html" "MFlow.Forms.XHtml" for the instance
2491−+-- for @Text.XHtml@ and MFlow.Forms.HSP for the instance for Haskell Server Pages.
2492−+class (Monoid view,Typeable view) => FormInput view where
2493−+ toByteString :: view -> B.ByteString
2494−+ toHttpData :: view -> HttpData
2495−+ fromStr :: String -> view
2496−+ fromStrNoEncode :: String -> view
2497−+ ftag :: String -> view -> view
2498−+ inred :: view -> view
2499−+ flink :: String -> view -> view
2500−+ flink1:: String -> view
2501−+ flink1 verb = flink verb (fromStr verb)
2502−+ finput :: Name -> Type -> Value -> Checked -> OnClick -> view
2503−+ ftextarea :: String -> T.Text -> view
2504−+ fselect :: String -> view -> view
2505−+ foption :: String -> view -> Bool -> view
2506−+ foption1 :: String -> Bool -> view
2507−+ foption1 val msel= foption val (fromStr val) msel
2508−+ formAction :: String -> String -> view -> view
2509−+ attrs :: view -> Attribs -> view
2510−+
2511−+
2512−+
2513−+--instance (MonadIO m) => MonadIO (FlowM view m) where
2514−+-- liftIO io= let x= liftIO io in x `seq` lift x -- to force liftIO==unsafePerformIO onf the Identity monad
2515−+
2516−+--instance Executable (View v m) where
2517−+-- execute f = execute $ evalStateT f mFlowState0
2518−+
2519−+
2520−+--instance (Monad m, Executable m, Monoid view, FormInput view)
2521−+-- => Executable (StateT (MFlowState view) m) where
2522−+-- execute f= execute $ evalStateT f mFlowState0
2523−+
2524−+-- | Cached widgets operate with widgets in the Identity monad, but they may perform IO using the execute instance
2525−+-- of the monad m, which is usually the IO monad. execute basically \"sanctifies\" the use of unsafePerformIO for a transient purpose
2526−+-- such is caching. This is defined in "Data.TCache.Memoization". The programmer can create his
2527−+-- own instance for his monad.
2528−+--
2529−+-- With `cachedWidget` it is possible to cache the rendering of a widget as a ByteString (maintaining type safety)
2530−+--, permanently or for a certain time. this is very useful for complex widgets that present information. Specially it they must access to databases.
2531−+--
2532−+-- @
2533−+-- import MFlow.Wai.Blaze.Html.All
2534−+-- import Some.Time.Library
2535−+-- addMessageFlows [(noscript, time)]
2536−+-- main= run 80 waiMessageFlow
2537−+-- time=do ask $ cachedWidget \"time\" 5
2538−+-- $ wlink () b << \"the time is \" ++ show (execute giveTheTime) ++ \" click here\"
2539−+-- time
2540−+-- @
2541−+--
2542−+-- this pseudocode would update the time every 5 seconds. The execution of the IO computation
2543−+-- giveTheTime must be executed inside the cached widget to avoid unnecesary IO executions.
2544−+--
2545−+-- NOTE: the rendering of cached widgets are shared by all users
2546−+cachedWidget :: (MonadIO m,Typeable view
2547−+ , FormInput view, Typeable a, Executable m )
2548−+ => String -- ^ The key of the cached object for the retrieval
2549−+ -> Int -- ^ Timeout of the caching. Zero means the whole server run
2550−+ -> View view Identity a -- ^ The cached widget, in the Identity monad
2551−+ -> View view m a -- ^ The cached result
2552−+cachedWidget key t mf = View . StateT $ \s -> do
2553−+ let((FormElm form _), sec)= execute $! cachedByKey key t $ proc mf s{mfCached=True}
2554−+ let((FormElm _ mx2), s2) = execute $ runStateT ( runView mf) s{mfSeqCache= sec,mfCached=True}
2555−+ let s''= s{inSync = inSync s2
2556−+ ,mfRequirements=mfRequirements s2
2557− ,mfPath= mfPath s2
2558−- ,mfPagePath= mfPagePath s2
2559−- ,needForm= needForm s2
2560−- ,mfPageFlow= mfPageFlow s2
2561−+ ,mfPagePath= mfPagePath s2
2562−+ ,needForm= needForm s2
2563−+ ,mfPageFlow= mfPageFlow s2
2564− ,mfSeqCache= mfSeqCache s + mfSeqCache s2 - sec}
2565− return $ (mfSeqCache s'') `seq` form `seq` ((FormElm form mx2), s'')
2566−-
2567−- -- !> ("enter: "++show (mfSeqCache s) ++" exit: "++ show ( mfSeqCache s2))
2568−- where
2569−- proc mf s= runStateT (runView mf) s >>= \(r,_) -> mfSeqCache s `seq` return (r,mfSeqCache s )
2570−-
2571−--- | A shorter name for `cachedWidget`
2572−-wcached :: (MonadIO m,Typeable view
2573−- , FormInput view, Typeable a, Executable m )
2574−- => String -- ^ The key of the cached object for the retrieval
2575−- -> Int -- ^ Timeout of the caching. Zero means sessionwide
2576−- -> View view Identity a -- ^ The cached widget, in the Identity monad
2577−- -> View view m a -- ^ The cached result
2578−-wcached= cachedWidget
2579−-
2580−--- | Unlike `cachedWidget`, which cache the rendering but not the user response, @wfreeze@
2581−--- cache also the user response. This is useful for pseudo-widgets which just show information
2582−--- while the controls are in other non freezed widgets. A freezed widget ever return the first user response
2583−--- It is faster than `cachedWidget`.
2584−--- It is not restricted to the Identity monad.
2585−---
2586−--- NOTE: the content of freezed widgets are shared by all users
2587−-wfreeze :: (MonadIO m,Typeable view
2588−- , FormInput view, Typeable a, Executable m )
2589−- => String -- ^ The key of the cached object for the retrieval
2590−- -> Int -- ^ Timeout of the caching. Zero means sessionwide
2591−- -> View view m a -- ^ The cached widget
2592−- -> View view m a -- ^ The cached result
2593−-wfreeze key t mf = View . StateT $ \s -> do
2594−- (FormElm f mx, req,seq,ajax) <- cachedByKey key t $ proc mf s{mfCached=True}
2595−- return ((FormElm f mx), s{mfRequirements=req ,mfSeqCache= seq,mfAjax=ajax})
2596−- where
2597−- proc mf s= do
2598−- (r,s) <- runStateT (runView mf) s
2599−- return (r,mfRequirements s, mfSeqCache s, mfAjax s)
2600−-
2601−-
2602−-
2603−-{- | Execute the Flow, in the @FlowM view m@ monad. It is used as parameter of `hackMessageFlow`
2604−-`waiMessageFlow` or `addMessageFlows`
2605−-
2606−-The flow is executed in a loop. When the flow is finished, it is started again
2607−-
2608−-@main= do
2609−- addMessageFlows [(\"noscript\",transient $ runFlow mainf)]
2610−- forkIO . run 80 $ waiMessageFlow
2611−- adminLoop
2612−-@
2613−--}
2614−-runFlow :: (FormInput view, MonadIO m)
2615−- => FlowM view (Workflow m) () -> Token -> Workflow m ()
2616−-runFlow f t=
2617−- loop (startState t) f t
2618−- where
2619−- loop s f t = do
2620−- (mt,s) <- runFlowOnce2 s f
2621−- let t'= fromFailBack mt
2622−- let t''= t'{tpath=[twfname t']}
2623−- liftIO $ do
2624−- flushRec t''
2625−+
2626−+ -- !> ("enter: "++show (mfSeqCache s) ++" exit: "++ show ( mfSeqCache s2))
2627−+ where
2628−+ proc mf s= runStateT (runView mf) s >>= \(r,_) -> mfSeqCache s `seq` return (r,mfSeqCache s )
2629−+
2630−+-- | A shorter name for `cachedWidget`
2631−+wcached :: (MonadIO m,Typeable view
2632−+ , FormInput view, Typeable a, Executable m )
2633−+ => String -- ^ The key of the cached object for the retrieval
2634−+ -> Int -- ^ Timeout of the caching. Zero means sessionwide
2635−+ -> View view Identity a -- ^ The cached widget, in the Identity monad
2636−+ -> View view m a -- ^ The cached result
2637−+wcached= cachedWidget
2638−+
2639−+-- | Unlike `cachedWidget`, which cache the rendering but not the user response, @wfreeze@
2640−+-- cache also the user response. This is useful for pseudo-widgets which just show information
2641−+-- while the controls are in other non freezed widgets. A freezed widget ever return the first user response
2642−+-- It is faster than `cachedWidget`.
2643−+-- It is not restricted to the Identity monad.
2644−+--
2645−+-- NOTE: the content of freezed widgets are shared by all users
2646−+wfreeze :: (MonadIO m,Typeable view
2647−+ , FormInput view, Typeable a, Executable m )
2648−+ => String -- ^ The key of the cached object for the retrieval
2649−+ -> Int -- ^ Timeout of the caching. Zero means sessionwide
2650−+ -> View view m a -- ^ The cached widget
2651−+ -> View view m a -- ^ The cached result
2652−+wfreeze key t mf = View . StateT $ \s -> do
2653−+ (FormElm f mx, req,seq,ajax) <- cachedByKey key t $ proc mf s{mfCached=True}
2654−+ return ((FormElm f mx), s{mfRequirements=req ,mfSeqCache= seq,mfAjax=ajax})
2655−+ where
2656−+ proc mf s= do
2657−+ (r,s) <- runStateT (runView mf) s
2658−+ return (r,mfRequirements s, mfSeqCache s, mfAjax s)
2659−+
2660−+
2661−+
2662−+{- | Execute the Flow, in the @FlowM view m@ monad. It is used as parameter of `hackMessageFlow`
2663−+`waiMessageFlow` or `addMessageFlows`
2664−+
2665−+The flow is executed in a loop. When the flow is finished, it is started again
2666−+
2667−+@main= do
2668−+ addMessageFlows [(\"noscript\",transient $ runFlow mainf)]
2669−+ forkIO . run 80 $ waiMessageFlow
2670−+ adminLoop
2671−+@
2672−+-}
2673−+runFlow :: (FormInput view, MonadIO m)
2674−+ => FlowM view (Workflow m) () -> Token -> Workflow m ()
2675−+runFlow f t=
2676−+ loop (startState t) f t
2677−+ where
2678−+ loop s f t = do
2679−+ (mt,s) <- runFlowOnce2 s f
2680−+ let t'= fromFailBack mt
2681−+ let t''= t'{tpath=[twfname t']}
2682−+ liftIO $ do
2683−+ flushRec t''
2684− sendToMF t'' t''
2685− let s'= case mfSequence s of
2686− -1 -> s -- !> "end of recovery loop"
2687−- _ -> s{mfPath=[twfname t],mfPagePath=[],mfEnv=[]}
2688−- loop s' f t''{tpath=[]} -- !> "LOOPAGAIN"
2689−-
2690−-inRecovery= -1
2691−-
2692−-runFlowOnce :: (FormInput view, MonadIO m)
2693−- => FlowM view (Workflow m) () -> Token -> Workflow m ()
2694−-runFlowOnce f t= runFlowOnce1 f t >> return ()
2695−-
2696−-runFlowOnce1 f t = runFlowOnce2 (startState t) f
2697−-
2698−+ _ -> s{mfPath=[twfname t],mfPagePath=[],mfEnv=[]}
2699−+ loop s' f t''{tpath=[]} -- !> "LOOPAGAIN"
2700−+
2701−+inRecovery= -1
2702−+
2703−+runFlowOnce :: (FormInput view, MonadIO m)
2704−+ => FlowM view (Workflow m) () -> Token -> Workflow m ()
2705−+runFlowOnce f t= runFlowOnce1 f t >> return ()
2706−+
2707−+runFlowOnce1 f t = runFlowOnce2 (startState t) f
2708−+
2709− startState t= mFlowState0{mfToken=t
2710−- ,mfSequence= inRecovery
2711−- ,mfPath= tpath t
2712−+ ,mfSequence= inRecovery
2713−+ ,mfPath= tpath t
2714− ,mfEnv= tenv t
2715−- ,mfPagePath=[]}
2716−+ ,mfPagePath=[]}
2717−
2718−-runFlowOnce2 s f =
2719−- runStateT (runSup . runFlowM $ do
2720−- backInit
2721−- f
2722−- getToken) s
2723−-
2724−-
2725−- where
2726−- backInit= do
2727−- s <- get -- !> "BackInit"
2728−- case mfTrace s of
2729−+runFlowOnce2 s f =
2730−+ runStateT (runSup . runFlowM $ do
2731−+ backInit
2732−+ f
2733−+ getToken) s
2734−+
2735−+
2736−+ where
2737−+ backInit= do
2738−+ s <- get -- !> "BackInit"
2739−+ case mfTrace s of
2740− [] -> do
2741− let t = mfToken s
2742− back <- goingBack
2743− recover <- lift $ isInRecover
2744−- when (back && not recover) . modify $ \s -> s{ newAsk= True,mfPagePath=[twfname t]}
2745−+ when (back && not recover) . modify $ \s -> s{ newAsk= True,mfPagePath=[twfname t]}
2746− breturn ()
2747−-
2748−- tr -> error $ disp tr
2749−- where
2750−- disp tr= "TRACE (error in the last line):\n\n" ++(concat $ intersperse "\n" tr)
2751−- -- to restart the flow in case of going back before the first page of the flow
2752−+
2753−+ tr -> error $ disp tr
2754−+ where
2755−+ disp tr= "TRACE (error in the last line):\n\n" ++(concat $ intersperse "\n" tr)
2756−+ -- to restart the flow in case of going back before the first page of the flow
2757−
2758− runFlowOnceReturn
2759− :: FormInput v => MFlowState v -> FlowM v m a -> Token -> m (FailBack a, MFlowState v)
2760−-runFlowOnceReturn s f t =
2761−- runStateT (runSup $ runFlowM f) (startState t)
2762−-
2763−-
2764−-
2765−--- | Run a persistent flow inside the current flow. It is identified by the procedure and
2766−--- the string identifier.
2767−--- unlike the normal flows, that run within infinite loops, runFlowIn executes once.
2768−--- In subsequent executions, the flow will get the intermediate responses from te log
2769−+runFlowOnceReturn s f t =
2770−+ runStateT (runSup $ runFlowM f) (startState t)
2771−+
2772−+
2773−+
2774−+-- | Run a persistent flow inside the current flow. It is identified by the procedure and
2775−+-- the string identifier.
2776−+-- unlike the normal flows, that run within infinite loops, runFlowIn executes once.
2777−+-- In subsequent executions, the flow will get the intermediate responses from te log
2778− -- and will return the result without asking again.
2779− -- This is useful for asking once, storing in the log and subsequently retrieving user
2780−--- defined configurations by means of persistent flows with web formularies.
2781−-runFlowIn
2782−- :: (MonadIO m,
2783−- FormInput view)
2784−- => String
2785−- -> FlowM view (Workflow IO) b
2786−- -> FlowM view m b
2787−-runFlowIn wf f= FlowM . Sup $ do
2788−- st <- get
2789−- let t = mfToken st
2790−- (r,st') <- liftIO $ exec1nc wf $ runFlow1 st f t
2791−- put st{mfPath= mfPath st'}
2792−- case r of
2793−- GoBack -> delWF wf ()
2794−- return r
2795−-
2796−- where
2797−- runFlow1 st f t= runStateT (runSup . runFlowM $ f) st
2798−-
2799−-
2800−--- | to unlift a FlowM computation. useful for executing the configuration generated by runFLowIn
2801−--- outside of the web flow (FlowM) monad
2802−-runFlowConf :: (FormInput view, MonadIO m) => FlowM view m a -> m a
2803−-runFlowConf f = do
2804−- q <- liftIO newEmptyMVar -- `debug` (i++w++u)
2805−+-- defined configurations by means of persistent flows with web formularies.
2806−+runFlowIn
2807−+ :: (MonadIO m,
2808−+ FormInput view)
2809−+ => String
2810−+ -> FlowM view (Workflow IO) b
2811−+ -> FlowM view m b
2812−+runFlowIn wf f= FlowM . Sup $ do
2813−+ st <- get
2814−+ let t = mfToken st
2815−+ (r,st') <- liftIO $ exec1nc wf $ runFlow1 st f t
2816−+ put st{mfPath= mfPath st'}
2817−+ case r of
2818−+ GoBack -> delWF wf ()
2819−+ return r
2820−+
2821−+ where
2822−+ runFlow1 st f t= runStateT (runSup . runFlowM $ f) st
2823−+
2824−+
2825−+-- | to unlift a FlowM computation. useful for executing the configuration generated by runFLowIn
2826−+-- outside of the web flow (FlowM) monad
2827−+runFlowConf :: (FormInput view, MonadIO m) => FlowM view m a -> m a
2828−+runFlowConf f = do
2829−+ q <- liftIO newEmptyMVar -- `debug` (i++w++u)
2830− qr <- liftIO newEmptyMVar
2831−- block <- liftIO $ newMVar True
2832−- let t= Token "" "" "" [] [] block q qr
2833−- evalStateT (runSup . runFlowM $ f ) mFlowState0{mfToken=t} >>= return . fromFailBack -- >> return ()
2834−-
2835−+ block <- liftIO $ newMVar True
2836−+ let t= Token "" "" "" [] [] block q qr
2837−+ evalStateT (runSup . runFlowM $ f ) mFlowState0{mfToken=t} >>= return . fromFailBack -- >> return ()
2838−+
2839−
2840− -- | run a transient Flow from the IO monad.
2841− --runNav :: String -> FlowM Html IO () -> IO ()
2842− --runNav ident f= exec1 ident $ runFlowOnce (transientNav f) undefined
2843−-
2844−-
2845−--- | Clears the environment
2846−-clearEnv :: MonadState (MFlowState view) m => m ()
2847−-clearEnv= do
2848−- st <- get
2849−- put st{ mfEnv= []}
2850−-
2851−-
2852−-
2853−-instance (FormInput v,Serialize a)
2854−- => Serialize (a,MFlowState v) where
2855−- showp (x,s)= case mfDebug s of
2856−- False -> showp x
2857−- True -> showp(x, mfEnv s)
2858−- readp= choice[nodebug, debug]
2859−- where
2860−- nodebug= readp >>= \x -> return (x, mFlowState0{mfSequence= inRecovery})
2861−- debug= do
2862−- (x,env) <- readp
2863−- return (x,mFlowState0{mfEnv= env,mfSequence= inRecovery})
2864−-
2865−-
2866−-
2867−--- | stores the result of the flow in a persistent log. When restarted, it get the result
2868−--- from the log and it does not execute it again. When no results are in the log, the computation
2869−--- is executed. It is equivalent to 'Control.Workflow.step' but in the FlowM monad.
2870−-step
2871−- :: (Serialize a,
2872−- Typeable view,
2873−- FormInput view,
2874−- MonadIO m,
2875−- Typeable a) =>
2876−- FlowM view m a
2877−- -> FlowM view (Workflow m) a
2878−-step f= do
2879−- s <- get
2880−- flowM $ Sup $ do
2881−- (r,s') <- lift . WF.step $ runStateT (runSup $ runFlowM f) s
2882−-
2883−- -- when recovery of a workflow, the MFlow state is not considered
2884−- when( mfSequence s' /= inRecovery) $ put s' -- !> (show $ mfSequence s') -- else put s{newAsk=True}
2885−- return r
2886−-
2887−--- | to execute transient flows as if they were persistent
2888−+
2889−+
2890−+-- | Clears the environment
2891−+clearEnv :: MonadState (MFlowState view) m => m ()
2892−+clearEnv= do
2893−+ st <- get
2894−+ put st{ mfEnv= []}
2895−+
2896−+
2897−+
2898−+instance (FormInput v,Serialize a)
2899−+ => Serialize (a,MFlowState v) where
2900−+ showp (x,s)= case mfDebug s of
2901−+ False -> showp x
2902−+ True -> showp(x, mfEnv s)
2903−+ readp= choice[nodebug, debug]
2904−+ where
2905−+ nodebug= readp >>= \x -> return (x, mFlowState0{mfSequence= inRecovery})
2906−+ debug= do
2907−+ (x,env) <- readp
2908−+ return (x,mFlowState0{mfEnv= env,mfSequence= inRecovery})
2909−+
2910−+
2911−+
2912−+-- | stores the result of the flow in a persistent log. When restarted, it get the result
2913−+-- from the log and it does not execute it again. When no results are in the log, the computation
2914−+-- is executed. It is equivalent to 'Control.Workflow.step' but in the FlowM monad.
2915−+step
2916−+ :: (Serialize a,
2917−+ Typeable view,
2918−+ FormInput view,
2919−+ MonadIO m,
2920−+ Typeable a) =>
2921−+ FlowM view m a
2922−+ -> FlowM view (Workflow m) a
2923−+step f= do
2924−+ s <- get
2925−+ FlowM $ Sup $ do
2926−+ (r,s') <- lift . WF.step $ runStateT (runSup $ runFlowM f) s
2927−+
2928−+ -- when recovery of a workflow, the MFlow state is not considered
2929−+ when( mfSequence s' /= inRecovery) $ put s' -- !> (show $ mfSequence s') -- else put s{newAsk=True}
2930−+ return r
2931−+
2932−+-- | to execute transient flows as if they were persistent
2933− -- it can be used instead of step, but it does log nothing.
2934− -- Thus, it is faster and convenient when no session state must be stored beyond the lifespan of
2935−--- the server process.
2936−---
2937−--- > transient $ runFlow f === runFlow $ transientNav f
2938−-transientNav
2939−- :: (Serialize a,
2940−- Typeable view,
2941−- FormInput view,
2942−- Typeable a) =>
2943−- FlowM view IO a
2944−- -> FlowM view (Workflow IO) a
2945−-transientNav f= do
2946−- s <- get
2947−- flowM $ Sup $ do
2948−- (r,s') <- lift . unsafeIOtoWF $ runStateT (runSup $ runFlowM f) s
2949−- put s'
2950−- return r
2951−-
2952−---stepWFRef
2953−--- :: (Serialize a,
2954−--- Typeable view,
2955−--- FormInput view,
2956−--- MonadIO m,
2957−--- Typeable a) =>
2958−--- FlowM view m a
2959−--- -> FlowM view (Workflow m) (WFRef (FailBack a),a)
2960−---stepWFRef f= do
2961−--- s <- get
2962−--- flowM $ Sup $ do
2963−--- (r,s') <- lift . WF.stepWFRef $ runStateT (runSup $ runFlowM f) s
2964−--- -- when recovery of a workflow, the MFlow state is not considered
2965−--- when( mfSequence s' >0) $ put s'
2966−--- return r
2967−-
2968−---step f= do
2969−--- s <- get
2970−--- flowM $ Sup $ do
2971−--- (r,s') <- do
2972−--- (br,s') <- runStateT (runSup $ runFlowM f) s
2973−--- case br of
2974−--- NoBack r -> WF.step $ return r
2975−--- BackPoint r -> WF.step $ return r
2976−--- GoBack -> undoStep
2977−--- -- when recovery of a workflow, the MFlow state is not considered
2978−--- when( mfSequence s' >0) $ put s'
2979−--- return r
2980−-
2981−-
2982−-
2983−---stepDebug
2984−--- :: (Serialize a,
2985−--- Typeable view,
2986−--- FormInput view,
2987−--- Monoid view,
2988−--- MonadIO m,
2989−--- Typeable a) =>
2990−--- FlowM view m a
2991−--- -> FlowM view (Workflow m) a
2992−---stepDebug f= Sup $ do
2993−--- s <- get
2994−--- (r, s') <- lift $ do
2995−--- (r',stat)<- do
2996−--- rec <- isInRecover
2997−--- case rec of
2998−--- True ->do (r', s'') <- getStep 0
2999−--- return (r',s{mfEnv= mfEnv (s'' `asTypeOf`s)})
3000−--- False -> return (undefined,s)
3001−--- (r'', s''') <- WF.stepDebug $ runStateT (runSup f) stat >>= \(r,s)-> return (r, s)
3002−--- return $ (r'' `asTypeOf` r', s''' )
3003−--- put s'
3004−--- return r
3005−-
3006−-
3007−-
3008−-data ParamResult v a= NoParam | NotValidated String v | Validated a deriving (Read, Show)
3009−-
3010−-valToMaybe (Validated x)= Just x
3011−-valToMaybe _= Nothing
3012−-
3013−-isValidated (Validated x)= True
3014−-isValidated _= False
3015−-
3016−-fromValidated (Validated x)= x
3017−-fromValidated NoParam= error $ "fromValidated : NoParam"
3018−-fromValidated (NotValidated s err)= error $ "fromValidated: NotValidated "++ s
3019−-
3020−-
3021−-
3022−-getParam1 :: (Monad m, MonadState (MFlowState v) m, Typeable a, Read a, FormInput v)
3023−- => String -> Params -> m (ParamResult v a)
3024−-getParam1 par req = case lookup par req of
3025−- Just x -> readParam x
3026−- Nothing -> return NoParam
3027−+-- the server process.
3028−+--
3029−+-- > transient $ runFlow f === runFlow $ transientNav f
3030−+transientNav
3031−+ :: (Serialize a,
3032−+ Typeable view,
3033−+ FormInput view,
3034−+ Typeable a) =>
3035−+ FlowM view IO a
3036−+ -> FlowM view (Workflow IO) a
3037−+transientNav f= do
3038−+ s <- get
3039−+ FlowM $ Sup $ do
3040−+ (r,s') <- lift . unsafeIOtoWF $ runStateT (runSup $ runFlowM f) s
3041−+ put s'
3042−+ return r
3043−+
3044−+--stepWFRef
3045−+-- :: (Serialize a,
3046−+-- Typeable view,
3047−+-- FormInput view,
3048−+-- MonadIO m,
3049−+-- Typeable a) =>
3050−+-- FlowM view m a
3051−+-- -> FlowM view (Workflow m) (WFRef (FailBack a),a)
3052−+--stepWFRef f= do
3053−+-- s <- get
3054−+-- flowM $ Sup $ do
3055−+-- (r,s') <- lift . WF.stepWFRef $ runStateT (runSup $ runFlowM f) s
3056−+-- -- when recovery of a workflow, the MFlow state is not considered
3057−+-- when( mfSequence s' >0) $ put s'
3058−+-- return r
3059−+
3060−+--step f= do
3061−+-- s <- get
3062−+-- flowM $ Sup $ do
3063−+-- (r,s') <- do
3064−+-- (br,s') <- runStateT (runSup $ runFlowM f) s
3065−+-- case br of
3066−+-- NoBack r -> WF.step $ return r
3067−+-- BackPoint r -> WF.step $ return r
3068−+-- GoBack -> undoStep
3069−+-- -- when recovery of a workflow, the MFlow state is not considered
3070−+-- when( mfSequence s' >0) $ put s'
3071−+-- return r
3072−+
3073−+
3074−+
3075−+--stepDebug
3076−+-- :: (Serialize a,
3077−+-- Typeable view,
3078−+-- FormInput view,
3079−+-- Monoid view,
3080−+-- MonadIO m,
3081−+-- Typeable a) =>
3082−+-- FlowM view m a
3083−+-- -> FlowM view (Workflow m) a
3084−+--stepDebug f= Sup $ do
3085−+-- s <- get
3086−+-- (r, s') <- lift $ do
3087−+-- (r',stat)<- do
3088−+-- rec <- isInRecover
3089−+-- case rec of
3090−+-- True ->do (r', s'') <- getStep 0
3091−+-- return (r',s{mfEnv= mfEnv (s'' `asTypeOf`s)})
3092−+-- False -> return (undefined,s)
3093−+-- (r'', s''') <- WF.stepDebug $ runStateT (runSup f) stat >>= \(r,s)-> return (r, s)
3094−+-- return $ (r'' `asTypeOf` r', s''' )
3095−+-- put s'
3096−+-- return r
3097−+
3098−+
3099−+
3100−+data ParamResult v a= NoParam | NotValidated String v | Validated a deriving (Read, Show)
3101−+
3102−+valToMaybe (Validated x)= Just x
3103−+valToMaybe _= Nothing
3104−+
3105−+isValidated (Validated x)= True
3106−+isValidated _= False
3107−+
3108−+fromValidated (Validated x)= x
3109−+fromValidated NoParam= error $ "fromValidated : NoParam"
3110−+fromValidated (NotValidated s err)= error $ "fromValidated: NotValidated "++ s
3111−+
3112−+
3113−+
3114−+getParam1 :: (Monad m, MonadState (MFlowState v) m, Typeable a, Read a, FormInput v)
3115−+ => String -> Params -> m (ParamResult v a)
3116−+getParam1 par req = case lookup par req of
3117−+ Just x -> readParam x
3118−+ Nothing -> return NoParam
3119−
3120− -- Read a segment in the REST path. if it does not match with the type requested
3121−--- or if there is no remaining segment, it returns Nothing
3122−+-- or if there is no remaining segment, it returns Nothing
3123− getRestParam :: (Read a, Typeable a, Monad m, Functor m, MonadState (MFlowState v) m, FormInput v)
3124−- => m (Maybe a)
3125−-getRestParam= do
3126−- st <- get
3127−- let lpath = mfPath st
3128−+ => m (Maybe a)
3129−+getRestParam= do
3130−+ st <- get
3131−+ let lpath = mfPath st
3132− if linkMatched st
3133−- then return Nothing
3134−+ then return Nothing
3135− else case stripPrefix (mfPagePath st) lpath of
3136− Nothing -> return Nothing
3137−- Just [] -> return Nothing
3138−- Just xs ->
3139−- case stripPrefix (mfPrefix st) (head xs) of
3140−- Nothing -> return Nothing
3141−- Just name -> do
3142−- r <- fmap valToMaybe $ readParam name
3143−- when (isJust r) $ modify $ \s -> s{inSync= True
3144−- ,linkMatched= True
3145−- ,mfPagePath= mfPagePath s++[name]}
3146−- return r
3147−-
3148−+ Just [] -> return Nothing
3149−+ Just xs -> do
3150−+-- case stripPrefix (mfPrefix st) (head xs) of
3151−+-- Nothing -> return Nothing
3152−+-- Just name ->
3153−+ let name= head xs
3154−+ r <- fmap valToMaybe $ readParam name
3155−+ when (isJust r) $ modify $ \s -> s{inSync= True
3156−+ ,linkMatched= True
3157−+ ,mfPagePath= mfPagePath s++[name]}
3158−+ return r
3159−+
3160−
3161−
3162− -- | return the value of a post or get param in the form ?param=value&param2=value2...
3163−@@ -1246,31 +1284,31 @@
3164− st <- get
3165− r <- getParam1 par $ mfEnv st
3166− return $ valToMaybe r
3167−-
3168−-readParam :: (Monad m, MonadState (MFlowState v) m, Typeable a, Read a, FormInput v)
3169−- => String -> m (ParamResult v a)
3170−-readParam x1 = r
3171−- where
3172−- r= do
3173−- modify $ \s -> s{inSync= True}
3174−- maybeRead x1
3175−-
3176−- getType :: m (ParamResult v a) -> a
3177−- getType= undefined
3178−- x= getType r
3179−- maybeRead str= do
3180−- let typeofx = typeOf x
3181−+
3182−+readParam :: (Monad m, MonadState (MFlowState v) m, Typeable a, Read a, FormInput v)
3183−+ => String -> m (ParamResult v a)
3184−+readParam x1 = r
3185−+ where
3186−+ r= do
3187−+ modify $ \s -> s{inSync= True}
3188−+ maybeRead x1
3189−+
3190−+ getType :: m (ParamResult v a) -> a
3191−+ getType= undefined
3192−+ x= getType r
3193−+ maybeRead str= do
3194−+ let typeofx = typeOf x
3195− if typeofx == typeOf ( undefined :: String) then
3196− return . Validated $ unsafeCoerce str
3197− else if typeofx == typeOf (undefined :: T.Text) then
3198−- return . Validated . unsafeCoerce $ T.pack str
3199−- else case readsPrec 0 $ str of
3200−- [(x,"")] -> return $ Validated x
3201−- _ -> do
3202−- let err= inred . fromStr $ "can't read \"" ++ str ++ "\" as type " ++ show (typeOf x)
3203−- return $ NotValidated str err
3204−-
3205−-
3206−+ return . Validated . unsafeCoerce $ T.pack str
3207−+ else case readsPrec 0 $ str of
3208−+ [(x,"")] -> return $ Validated x
3209−+ _ -> do
3210−+ let err= inred . fromStr $ "can't read \"" ++ str ++ "\" as type " ++ show (typeOf x)
3211−+ return $ NotValidated str err
3212−+
3213−+
3214− ---- Requirements
3215−
3216−
3217−@@ -1278,39 +1316,41 @@
3218− -- Web page or in the server when a widget specifies this. @requires@ is the
3219− -- procedure to be called with the list of requirements.
3220− -- Various widgets in the page can require the same element, MFlow will install it once.
3221−+
3222−+
3223− requires rs =do
3224− st <- get
3225− let l = mfRequirements st
3226−--- let rs'= map Requirement rs \\ l
3227− put st {mfRequirements= l ++ map Requirement rs}
3228−
3229−-
3230−+unfold (JScriptFile f ss)= JScript loadScript:map (\s-> JScriptFile f [s]) ss
3231−+unfold x= [x]
3232−
3233− data Requirement= forall a.(Show a,Typeable a,Requirements a) => Requirement a deriving Typeable
3234−
3235− class Requirements a where
3236−- installRequirements :: (Monad m,FormInput view) => Bool -> [a] -> m view
3237−+ installRequirements :: (MonadState (MFlowState view) m,MonadIO m,FormInput view) => [a] -> m view
3238−
3239− instance Show Requirement where
3240− show (Requirement a)= show a ++ "\n"
3241−
3242−-installAllRequirements :: ( Monad m, FormInput view) => WState view m view
3243−+installAllRequirements :: ( MonadIO m, FormInput view) => WState view m view
3244− installAllRequirements= do
3245− st <- get
3246− let rs = mfRequirements st
3247−- auto = mfAutorefresh st
3248−- installAllRequirements1 auto mempty rs
3249−+ installAllRequirements1 mempty rs
3250−+
3251− where
3252−
3253−- installAllRequirements1 _ v []= return v
3254−- installAllRequirements1 auto v rs= do
3255−+ installAllRequirements1 v []= return v
3256−+ installAllRequirements1 v rs= do
3257− let typehead= case head rs of {Requirement r -> typeOf r}
3258− (rs',rs'')= partition1 typehead rs
3259− v' <- installRequirements2 rs'
3260−- installAllRequirements1 auto (v `mappend` v') rs''
3261−+ installAllRequirements1 (v `mappend` v') rs''
3262− where
3263− installRequirements2 []= return $ fromStrNoEncode ""
3264−- installRequirements2 (Requirement r:rs)= installRequirements auto $ r:unmap rs
3265−+ installRequirements2 (Requirement r:rs)= installRequirements $ r:unmap rs
3266− unmap []=[]
3267− unmap (Requirement r:rs)= unsafeCoerce r:unmap rs
3268− partition1 typehead xs = foldr select ([],[]) xs
3269−@@ -1320,155 +1360,194 @@
3270− in if typer== typehead then ( x:ts,fs)
3271− else (ts, x:fs)
3272−
3273−--- Web requirements ---
3274−-loadjsfile filename lcallbacks=
3275−- let name= addrStr filename in
3276−- "var fileref = document.getElementById('"++name++"');\
3277−- \if (fileref === null){\
3278−+-- Web requirements ---
3279−+loadjsfile filename=
3280−+ let name= addrStr filename
3281−+ in "\n"++name++"=loadScript('"++name++"','"++filename++"');\n"
3282−+
3283−+loadScript ="function loadScript(name, filename){\
3284−+ \var fileref = document.getElementById(name);\
3285−+ \if (fileref === null){\
3286− \fileref=document.createElement('script');\
3287−- \fileref.setAttribute('id','"++name++"');\
3288−- \fileref.setAttribute('type','text/javascript');\
3289−- \fileref.setAttribute('src',\'" ++ filename ++ "\');\
3290−- \document.getElementsByTagName('head')[0].appendChild(fileref);};"
3291−- ++ onload
3292−- where
3293−- onload= case lcallbacks of
3294−- [] -> ""
3295−- cs -> "fileref.onload = function() {"++ (concat $ nub cs)++"};"
3296−-
3297−-
3298−-loadjs content= content
3299−-
3300−-
3301−-loadcssfile filename=
3302−- "var fileref=document.createElement('link');\
3303−- \fileref.setAttribute('rel', 'stylesheet');\
3304−- \fileref.setAttribute('type', 'text/css');\
3305−- \fileref.setAttribute('href', \'"++filename++"\');\
3306−- \document.getElementsByTagName('head')[0].appendChild(fileref);"
3307−-
3308−-
3309−-loadcss content=
3310−- "var fileref=document.createElement('link');\
3311−- \fileref.setAttribute('rel', 'stylesheet');\
3312−- \fileref.setAttribute('type', 'text/css');\
3313−- \fileref.innerText=\""++content++"\";\
3314−- \document.getElementsByTagName('head')[0].appendChild(fileref);"
3315−-
3316−-
3317−-data WebRequirement= JScriptFile
3318−- String
3319−- [String] -- ^ Script URL and the list of scripts to be executed when loaded
3320−- | CSSFile String -- ^ a CSS file URL
3321−- | CSS String -- ^ a String with a CSS description
3322−- | JScript String -- ^ a string with a valid JavaScript
3323−- | ServerProc (String, Flow) -- ^ a server procedure
3324−- deriving(Typeable,Eq,Ord,Show)
3325−-
3326−-instance Eq (String, Flow) where
3327−+ \fileref.setAttribute('id',name);\
3328−+ \fileref.setAttribute('type','text/javascript');\
3329−+ \fileref.setAttribute('src',filename);\
3330−+ \document.getElementsByTagName('head')[0].appendChild(fileref);}\
3331−+ \return fileref};\n\
3332−+ \function addLoadEvent(elem,func) {\
3333−+ \var oldonload = elem.onload;\
3334−+ \if (typeof elem.onload != 'function') {\
3335−+ \elem.onload = func;\
3336−+ \} else {\
3337−+ \elem.onload = function() {\
3338−+ \if (oldonload) {\
3339−+ \oldonload();\
3340−+ \}\
3341−+ \func();\
3342−+ \}\
3343−+ \}\
3344−+ \}"
3345−+
3346−+loadCallback depend script=
3347−+ let varname= addrStr depend in
3348−+ "\naddLoadEvent("++varname++",function(){"++ script++"});"
3349−+
3350−+
3351−+
3352−+
3353−+loadcssfile filename=
3354−+ "var fileref=document.createElement('link');\
3355−+ \fileref.setAttribute('rel', 'stylesheet');\
3356−+ \fileref.setAttribute('type', 'text/css');\
3357−+ \fileref.setAttribute('href', \'"++filename++"\');\
3358−+ \document.getElementsByTagName('head')[0].appendChild(fileref);"
3359−+
3360−+
3361−+loadcss content=
3362−+ "var fileref=document.createElement('link');\
3363−+ \fileref.setAttribute('rel', 'stylesheet');\
3364−+ \fileref.setAttribute('type', 'text/css');\
3365−+ \fileref.innerText=\""++content++"\";\
3366−+ \document.getElementsByTagName('head')[0].appendChild(fileref);"
3367−+
3368−+
3369−+data WebRequirement= JScriptFile
3370−+ String
3371−+ [String] -- ^ Script URL and the list of scripts to be executed when loaded
3372−+ | CSSFile String -- ^ a CSS file URL
3373−+ | CSS String -- ^ a String with a CSS description
3374−+ | JScript String -- ^ a string with a valid JavaScript
3375−+ | ServerProc (String, Flow) -- ^ a server procedure
3376−+ deriving(Typeable,Eq,Ord,Show)
3377−+
3378−+instance Eq (String, Flow) where
3379− (x,_) == (y,_)= x == y
3380−-
3381−-instance Ord (String, Flow) where
3382−- compare(x,_) (y,_)= compare x y
3383−-instance Show (String, Flow) where
3384−- show (x,_)= show x
3385−-
3386−-instance Requirements WebRequirement where
3387−- installRequirements= installWebRequirements
3388−-
3389−-
3390−-
3391−-installWebRequirements :: (Monad m,FormInput view) => Bool -> [WebRequirement] -> m view
3392−-installWebRequirements auto rs= do
3393−- let s = jsRequirements auto $ sort rs
3394−-
3395−- return $ ftag "script" (fromStrNoEncode s)
3396−-
3397−-
3398−-jsRequirements _ []= ""
3399−-
3400−-jsRequirements False (r@(JScriptFile f c) : r'@(JScriptFile f' c'):rs)
3401−- | f==f' = jsRequirements False $ JScriptFile f (nub $ c++c'):rs
3402−- | otherwise= strRequirement r ++ jsRequirements False (r':rs)
3403−-
3404−-jsRequirements True (r@(JScriptFile f c) : r'@(JScriptFile f' c'):rs)
3405−- | f==f' = concatMap strRequirement(map JScript $ nub (c' ++ c)) ++ jsRequirements True rs
3406−- | otherwise= strRequirement r ++ jsRequirements True (r':rs)
3407−-
3408−-
3409−-
3410−-
3411−-jsRequirements auto (r:r':rs)
3412−- | r== r' = jsRequirements auto $ r:rs
3413−- | otherwise= strRequirement r ++ jsRequirements auto (r':rs)
3414−-
3415−-jsRequirements auto (r:rs)= strRequirement r++jsRequirements auto rs
3416−-
3417−-strRequirement (CSSFile s') = loadcssfile s'
3418−-strRequirement (CSS s') = loadcss s'
3419−-strRequirement (JScriptFile s' call) = loadjsfile s' call
3420−-strRequirement (JScript s') = loadjs s'
3421−-strRequirement (ServerProc f)= (unsafePerformIO $! addMessageFlows [f]) `seq` ""
3422−-
3423−-
3424−-
3425−-
3426−-
3427−---- AJAX ----
3428−-ajaxScript=
3429−- "function loadXMLObj()" ++
3430−- "{" ++
3431−- "var xmlhttp;" ++
3432−- "if (window.XMLHttpRequest)" ++
3433−- "{"++
3434−- " xmlhttp=new XMLHttpRequest();" ++
3435−- " }" ++
3436−- "else" ++
3437−- "{"++
3438−- " xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');" ++
3439−- " }" ++
3440−- "return xmlhttp" ++
3441−- "};" ++
3442−-
3443−- " xmlhttp= loadXMLObj();" ++
3444−- " noparam= '';"++
3445−- ""++
3446−- "function doServer (servproc,param,param2){" ++
3447−- " xmlhttp.open('GET',servproc+'?ajax='+param+'&val='+param2,true);" ++
3448−- " xmlhttp.send();};" ++
3449−- ""++
3450−- "xmlhttp.onreadystatechange=function()" ++
3451−- " {" ++
3452−- " if (xmlhttp.readyState== 4 && xmlhttp.status==200)" ++
3453−- " {" ++
3454−- " eval(xmlhttp.responseText);" ++
3455−- " }" ++
3456−- " };" ++
3457−- ""
3458−-
3459−-formPrefix st form anchored= do
3460−+
3461−+instance Ord (String, Flow) where
3462−+ compare(x,_) (y,_)= compare x y
3463−+instance Show (String, Flow) where
3464−+ show (x,_)= show x
3465−+
3466−+instance Requirements WebRequirement where
3467−+ installRequirements= installWebRequirements
3468−+
3469−+
3470−+
3471−+installWebRequirements
3472−+ :: (MonadState(MFlowState view) m,MonadIO m,FormInput view) => [WebRequirement] -> m view
3473−+installWebRequirements rs= do
3474−+ installed <- gets mfInstalledScripts
3475−+ let rs'= (nub rs) \\ installed
3476−+
3477−+ strs <- mapM strRequirement rs' -- !>( "OLD="++show installed) !> ("new="++show rs')
3478−+ case null strs of
3479−+ True -> return mempty
3480−+ False -> return . ftag "script" . fromStrNoEncode $ concat strs
3481−+
3482−+
3483−+strRequirement r=do
3484−+ r1 <- strRequirement' r
3485−+ modify $ \st -> st{mfInstalledScripts= mfInstalledScripts st ++ [r]}
3486−+ return r1
3487−+
3488−+strRequirement' (CSSFile scr) = return $ loadcssfile scr
3489−+strRequirement' (CSS scr) = return $ loadcss scr
3490−+strRequirement' (JScriptFile file scripts) = do
3491−+ installed <- gets mfInstalledScripts
3492−+ let hasLoadScript (JScriptFile _ _)= True
3493−+ hasLoadScript _= False
3494−+ inst2= dropWhile (not . hasLoadScript) installed
3495−+ hasSameFile file (JScriptFile fil _)= if file== fil then True else False
3496−+ hasSameFile _ _= False
3497−+ case (inst2,find (hasSameFile file) inst2) of
3498−+ ([],_) ->
3499−+ -- no script file has been loaded previously
3500−+ return $ loadScript <> loadjsfile file <> concatMap(loadCallback file) scripts
3501−+ (_,Just _) -> do
3502−+ -- This script file has been already loaded or demanded for load
3503−+ autorefresh <- gets mfAutorefresh
3504−+ case autorefresh of
3505−+ -- demanded for load, not loaded
3506−+ False -> return $ concatMap(loadCallback file) scripts
3507−+ -- already loaded
3508−+ True -> return $ concat scripts
3509−+ -- other script file has been loaded or demanded load, so loadScript is already installed
3510−+ _ -> return $ loadjsfile file <> concatMap(loadCallback file) scripts
3511−+
3512−+
3513−+strRequirement' (JScript scr) = return scr
3514−+strRequirement' (ServerProc f)= do
3515−+ liftIO $ addMessageFlows [f]
3516−+ return ""
3517−+
3518−+
3519−+
3520−+
3521−+
3522−+--- AJAX ----
3523−+ajaxScript=
3524−+ "function loadXMLObj()" ++
3525−+ "{" ++
3526−+ "var xmlhttp;" ++
3527−+ "if (window.XMLHttpRequest)" ++
3528−+ "{"++
3529−+ " xmlhttp=new XMLHttpRequest();" ++
3530−+ " }" ++
3531−+ "else" ++
3532−+ "{"++
3533−+ " xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');" ++
3534−+ " }" ++
3535−+ "return xmlhttp" ++
3536−+ "};" ++
3537−+
3538−+ " xmlhttp= loadXMLObj();" ++
3539−+ " noparam= '';"++
3540−+ ""++
3541−+ "function doServer (servproc,param,param2){" ++
3542−+ " xmlhttp.open('GET',servproc+'?ajax='+param+'&val='+param2,true);" ++
3543−+ " xmlhttp.send();};" ++
3544−+ ""++
3545−+ "xmlhttp.onreadystatechange=function()" ++
3546−+ " {" ++
3547−+ " if (xmlhttp.readyState== 4 && xmlhttp.status==200)" ++
3548−+ " {" ++
3549−+ " eval(xmlhttp.responseText);" ++
3550−+ " }" ++
3551−+ " };" ++
3552−+ ""
3553−+
3554−+formPrefix st form anchored= do
3555− let verb = twfname $ mfToken st
3556−- path = currentPath st
3557−- (anchor,anchorf)
3558−- <- case anchored of
3559−- True -> do
3560−- anchor <- genNewId
3561−- return ('#':anchor, (ftag "a") mempty `attrs` [("name",anchor)])
3562−- False -> return (mempty,mempty)
3563−- return $ formAction (path ++ anchor ) $ anchorf <> form -- !> anchor
3564−-
3565−--- | insert a form tag if the widget has form input fields. If not, it does nothing
3566−-insertForm w=View $ do
3567−- FormElm forms mx <- runView w
3568−- st <- get
3569−- cont <- case needForm1 st of
3570−- True -> do
3571−- frm <- formPrefix st forms False
3572−- put st{needForm= HasForm}
3573−- return frm
3574−- _ -> return forms
3575−-
3576−- return $ FormElm cont mx
3577−+ path = currentPath st
3578−+ hasfile= mfFileUpload st
3579−+ attr= case hasfile of
3580−+ True -> [("enctype","multipart/form-data")]
3581−+ False -> []
3582−+ (anchor,anchorf)
3583−+ <- case anchored of
3584−+ True -> do
3585−+ anchor <- genNewId
3586−+ return ('#':anchor, (ftag "a") mempty `attrs` [("name",anchor)])
3587−+ False -> return (mempty,mempty)
3588−+ return $ formAction (path ++ anchor ) "POST" ( anchorf <> form ) `attrs` attr
3589−+
3590−+
3591−+
3592−+
3593−+
3594−+
3595−+-- | insert a form tag if the widget has form input fields. If not, it does nothing
3596−+insertForm w=View $ do
3597−+ FormElm forms mx <- runView w
3598−+ st <- get
3599−+ cont <- case needForm st of
3600−+ HasElems -> do
3601−+ frm <- formPrefix st forms False
3602−+ put st{needForm= HasForm}
3603−+ return frm
3604−+ _ -> return forms
3605−+
3606−+ return $ FormElm cont mx
3607−
3608− -- isert a form tag if necessary when two pieces of HTML have to mix as a result of >>= >> <|> or <+> operators
3609− controlForms :: (FormInput v, MonadState (MFlowState v) m)
3610−@@ -1481,40 +1560,40 @@
3611− v1' <- formPrefix s1 v1 True
3612− return (v1' <> v2 , True)
3613−
3614−- _ -> return (v1 <> v2, False)
3615−-
3616−-currentPath st= concat ['/':v| v <- mfPagePath st ]
3617−-
3618−--- | Generate a new string. Useful for creating tag identifiers and other attributes.
3619−---
3620−--- if the page is refreshed, the identifiers generated are the same.
3621−-genNewId :: MonadState (MFlowState view) m => m String
3622−-genNewId= do
3623−- st <- get
3624−- case mfCached st of
3625−- False -> do
3626−- let n= mfSequence st
3627−- prefseq= mfPrefix st
3628−- put $ st{mfSequence= n+1}
3629−-
3630−- return $ 'p':show n++prefseq
3631−- True -> do
3632−- let n = mfSeqCache st
3633−- put $ st{mfSeqCache=n+1}
3634−- return $ 'c' : (show n)
3635−-
3636−--- | get the next ideitifier that will be created by genNewId
3637−-getNextId :: MonadState (MFlowState view) m => m String
3638−-getNextId= do
3639−- st <- get
3640−- case mfCached st of
3641−- False -> do
3642−- let n= mfSequence st
3643−- prefseq= mfPrefix st
3644−- return $ 'p':show n++prefseq
3645−- True -> do
3646−- let n = mfSeqCache st
3647−- return $ 'c' : (show n)
3648−+ _ -> return (v1 <> v2, False)
3649−+
3650−+currentPath st= concat ['/':v| v <- mfPagePath st ]
3651−+
3652−+-- | Generate a new string. Useful for creating tag identifiers and other attributes.
3653−+--
3654−+-- if the page is refreshed, the identifiers generated are the same.
3655−+genNewId :: MonadState (MFlowState view) m => m String
3656−+genNewId= do
3657−+ st <- get
3658−+ case mfCached st of
3659−+ False -> do
3660−+ let n= mfSequence st
3661−+ prefseq= mfPrefix st
3662−+ put $ st{mfSequence= n+1}
3663−+
3664−+ return $ 'p':show n++prefseq
3665−+ True -> do
3666−+ let n = mfSeqCache st
3667−+ put $ st{mfSeqCache=n+1}
3668−+ return $ 'c' : (show n)
3669−+
3670−+-- | get the next ideitifier that will be created by genNewId
3671−+getNextId :: MonadState (MFlowState view) m => m String
3672−+getNextId= do
3673−+ st <- get
3674−+ case mfCached st of
3675−+ False -> do
3676−+ let n= mfSequence st
3677−+ prefseq= mfPrefix st
3678−+ return $ 'p':show n++prefseq
3679−+ True -> do
3680−+ let n = mfSeqCache st
3681−+ return $ 'c' : (show n)
3682−+
3683−
3684−
3685−-
3686−diff -ru orig/src/MFlow/Forms/Test.hs new/src/MFlow/Forms/Test.hs
3687−--- orig/src/MFlow/Forms/Test.hs 2014-06-10 05:51:26.977015856 +0300
3688−+++ new/src/MFlow/Forms/Test.hs 2014-06-10 05:51:25.000000000 +0300
3689−@@ -1,404 +1,404 @@
3690−------------------------------------------------------------------------------
3691−---
3692−--- Module : MFlow.Forms.Test
3693−--- Copyright :
3694−--- License : BSD3
3695−---
3696−--- Maintainer : agocorona@gmail.com
3697−--- Stability : experimental
3698−--- Portability :
3699−---
3700−--- |
3701−---
3702−------------------------------------------------------------------------------
3703−-{-# OPTIONS
3704−- -XOverlappingInstances
3705−- -XFlexibleInstances
3706−- -XUndecidableInstances
3707−- -XPatternGuards
3708−- -XRecordWildCards
3709−- #-}
3710−-
3711−-module MFlow.Forms.Test (Generate(..),runTest,runTest1,inject, ask, askt, userWidget, getUser, getUserSimple, verify) where
3712−-import MFlow.Forms hiding(ask,askt,getUser,userWidget,getUserSimple)
3713−-import qualified MFlow.Forms (ask)
3714−-import MFlow.Forms.Internals
3715−-import MFlow.Forms(FormInput(..))
3716−-import MFlow.Forms.Admin
3717−-import Control.Workflow as WF
3718−-import Control.Concurrent
3719−-import Control.Monad
3720−-import MFlow
3721−-import qualified Data.Map as M
3722−-import Control.Monad.Trans
3723−-import System.IO.Unsafe
3724−-import System.Random
3725−-import Data.Char(chr, ord)
3726−-import Data.List
3727−-import Data.Typeable
3728−-import qualified Data.ByteString.Lazy.Char8 as B
3729−-import Control.Concurrent.MVar
3730−-import Data.TCache.Memoization
3731−-import Control.Monad.State
3732−-import Data.Monoid
3733−-import Data.Maybe
3734−-import Data.IORef
3735−-import MFlow.Cookies(cookieuser)
3736−-
3737−-import Data.Dynamic
3738−-import Data.TCache.Memoization
3739−-
3740−-
3741−-
3742−-class Generate a where
3743−- generate :: IO a
3744−-
3745−-instance Generate a => Generate (Maybe a) where
3746−- generate= do
3747−- b <- randomRIO(0,1 :: Int)
3748−- case b of 0 -> generate >>= return . Just ; _ -> return Nothing
3749−-
3750−-instance Generate String where
3751−- generate= replicateM 5 $ randomRIO ('a','z')
3752−-
3753−-instance Generate Int where
3754−- generate= randomRIO(1,1000)
3755−-
3756−-instance Generate Integer where
3757−- generate= randomRIO(1,1000)
3758−-
3759−-
3760−-instance (Generate a, Generate b) => Generate (a,b) where
3761−- generate= fmap (,) generate `ap` generate
3762−-
3763−-
3764−-instance (Generate a, Generate b) => Generate (Maybe a,Maybe b) where
3765−- generate= do
3766−- r <- generate
3767−- case r of
3768−- (Nothing,Nothing) -> generate
3769−- other -> return other
3770−-
3771−-
3772−-instance (Bounded a, Enum a) => Generate a where
3773−- generate= mx
3774−- where
3775−- mx= do
3776−- let x= typeOfIO mx
3777−- n <- randomRIO ( fromEnum $ minBound `asTypeOf` x
3778−- , fromEnum $ maxBound `asTypeOf` x)
3779−- return $ toEnum n
3780−- where
3781−- typeOfIO :: IO a -> a
3782−- typeOfIO = undefined
3783−-
3784−--- | run a list of flows with a number of simultaneous threads
3785−-runTest :: [(Int, Flow)] -> IO ()
3786−-runTest ps= do
3787−- mapM_ (forkIO . run1) ps
3788−- putStrLn $ "started " ++ (show . sum . fst $ unzip ps) ++ " threads"
3789−-
3790−- where
3791−- run1 (nusers, proc) = replicateM_ nusers $ runTest1 proc
3792−-
3793−-runTest1 f = do
3794−- atomicModifyIORef testNumber (\n -> (n+1,n+1))
3795−- name <- generate
3796−- x <- generate
3797−- y <- generate
3798−+-----------------------------------------------------------------------------
3799−+--
3800−+-- Module : MFlow.Forms.Test
3801−+-- Copyright :
3802−+-- License : BSD3
3803−+--
3804−+-- Maintainer : agocorona@gmail.com
3805−+-- Stability : experimental
3806−+-- Portability :
3807−+--
3808−+-- |
3809−+--
3810−+-----------------------------------------------------------------------------
3811−+{-# OPTIONS
3812−+ -XOverlappingInstances
3813−+ -XFlexibleInstances
3814−+ -XUndecidableInstances
3815−+ -XPatternGuards
3816−+ -XRecordWildCards
3817−+ #-}
3818−+
3819−+module MFlow.Forms.Test (Generate(..),runTest,runTest1,inject, ask, askt, userWidget, getUser, getUserSimple, verify) where
3820−+import MFlow.Forms hiding(ask,askt,getUser,userWidget,getUserSimple)
3821−+import qualified MFlow.Forms (ask)
3822−+import MFlow.Forms.Internals
3823−+import MFlow.Forms(FormInput(..))
3824−+import MFlow.Forms.Admin
3825−+import Control.Workflow as WF
3826−+import Control.Concurrent
3827−+import Control.Monad
3828−+import MFlow
3829−+import qualified Data.Map as M
3830−+import Control.Monad.Trans
3831−+import System.IO.Unsafe
3832−+import System.Random
3833−+import Data.Char(chr, ord)
3834−+import Data.List
3835−+import Data.Typeable
3836−+import qualified Data.ByteString.Lazy.Char8 as B
3837−+import Control.Concurrent.MVar
3838−+import Data.TCache.Memoization
3839−+import Control.Monad.State
3840−+import Data.Monoid
3841−+import Data.Maybe
3842−+import Data.IORef
3843−+import MFlow.Cookies(cookieuser)
3844−+
3845−+import Data.Dynamic
3846−+import Data.TCache.Memoization
3847−+
3848−+
3849−+
3850−+class Generate a where
3851−+ generate :: IO a
3852−+
3853−+instance Generate a => Generate (Maybe a) where
3854−+ generate= do
3855−+ b <- randomRIO(0,1 :: Int)
3856−+ case b of 0 -> generate >>= return . Just ; _ -> return Nothing
3857−+
3858−+instance Generate String where
3859−+ generate= replicateM 5 $ randomRIO ('a','z')
3860−+
3861−+instance Generate Int where
3862−+ generate= randomRIO(1,1000)
3863−+
3864−+instance Generate Integer where
3865−+ generate= randomRIO(1,1000)
3866−+
3867−+
3868−+instance (Generate a, Generate b) => Generate (a,b) where
3869−+ generate= fmap (,) generate `ap` generate
3870−+
3871−+
3872−+instance (Generate a, Generate b) => Generate (Maybe a,Maybe b) where
3873−+ generate= do
3874−+ r <- generate
3875−+ case r of
3876−+ (Nothing,Nothing) -> generate
3877−+ other -> return other
3878−+
3879−+
3880−+instance (Bounded a, Enum a) => Generate a where
3881−+ generate= mx
3882−+ where
3883−+ mx= do
3884−+ let x= typeOfIO mx
3885−+ n <- randomRIO ( fromEnum $ minBound `asTypeOf` x
3886−+ , fromEnum $ maxBound `asTypeOf` x)
3887−+ return $ toEnum n
3888−+ where
3889−+ typeOfIO :: IO a -> a
3890−+ typeOfIO = undefined
3891−+
3892−+-- | run a list of flows with a number of simultaneous threads
3893−+runTest :: [(Int, Flow)] -> IO ()
3894−+runTest ps= do
3895−+ mapM_ (forkIO . run1) ps
3896−+ putStrLn $ "started " ++ (show . sum . fst $ unzip ps) ++ " threads"
3897−+
3898−+ where
3899−+ run1 (nusers, proc) = replicateM_ nusers $ runTest1 proc
3900−+
3901−+runTest1 f = do
3902−+ atomicModifyIORef testNumber (\n -> (n+1,n+1))
3903−+ name <- generate
3904−+ x <- generate
3905−+ y <- generate
3906− z <- generate
3907−-
3908−- let t = Token x y z [] [] undefined undefined undefined
3909−- WF.start name f t
3910−-
3911−-testNumber= unsafePerformIO $ newIORef 0
3912−-
3913−-getTestNumber :: MonadIO m => m Int
3914−-getTestNumber= liftIO $ readIORef testNumber
3915−-
3916−--- | inject substitutes an expression by other. It may be used to override
3917−--- ask interaction with the user. It should bee used infix for greater readability:
3918−---
3919−--- > ask something `inject` const someother
3920−---
3921−--- The parameter passed is the test number
3922−--- if the flow has not been executed by runTest, inject return the original
3923−-inject :: MonadIO m => m b -> (Int -> b) -> m b
3924−-inject exp v= do
3925−- n <- getTestNumber
3926−- if n== 0 then exp else exp `seq` return $ v n
3927−-
3928−--- | a simulated ask that generate simulated user input of the type expected.
3929−---
3930−--- It forces the web page rendering, since it is monadic and can contain
3931−--- side effects and load effects to be tested.
3932−---
3933−--- it is a substitute of 'ask' from "MFlow.Forms" for testing purposes.
3934−-
3935−--- execute 'runText' to initiate threads under different load conditions.
3936−-ask :: (Generate a, MonadIO m, Functor m, FormInput v,Typeable v) => View v m a -> FlowM v m a
3937−-ask w = do
3938−- FormElm forms mx <- FlowM . lift $ runView w
3939−- r <- liftIO generate
3940−- let n= B.length $ toByteString forms
3941−- breturn $ n `seq` mx `seq` r
3942−--- let u= undefined
3943−--- liftIO $ runStateT (runView mf) s
3944−--- bool <- liftIO generate
3945−--- case bool of
3946−--- False -> fail ""
3947−--- True -> do
3948−--- b <- liftIO generate
3949−--- r <- liftIO generate
3950−--- case (b,r) of
3951−--- (True,x) -> breturn x
3952−--- _ -> ask w
3953−-
3954−-
3955−--- | instead of generating a result like `ask`, the result is given as the first parameter
3956−--- so it does not need a Generate instance.
3957−---
3958−--- It forces the web page rendering, since it is monadic so it can contain
3959−--- side effects and load effects to be tested.
3960−-askt :: (MonadIO m, FormInput v) => (Int -> a) -> View v m a -> FlowM v m a
3961−-askt v w = do
3962−- FormElm forms mx <- FlowM . lift $ runView w
3963−- n <- getTestNumber
3964−- let l= B.length $ toByteString forms
3965−- breturn $ l `seq` mx `seq` v n
3966−-
3967−---mvtestopts :: MVar (M.Map String (Int,Dynamic))
3968−---mvtestopts = unsafePerformIO $ newMVar M.empty
3969−-
3970−---asktn :: (Typeable a,MonadIO m) => [a] -> View v m a -> FlowM v m a
3971−---asktn xs w= do
3972−--- v <- liftIO $ do
3973−--- let k = addrStr xs
3974−--- opts <- takeMVar mvtestopts
3975−--- let r = M.lookup k opts
3976−--- case r of
3977−--- Nothing -> do
3978−--- putMVar mvtestopts $ M.singleton k (0,toDyn xs)
3979−--- return $ head xs
3980−--- Just (i,d) -> do
3981−--- putMVar mvtestopts $ M.insert k (i+1,d) opts
3982−--- return $ (fromMaybe (error err1) $ fromDynamic d) !! i
3983−---
3984−--- askt v w
3985−---
3986−--- where
3987−--- err1= "MFlow.Forms.Test: asktn: fromDynamic error"
3988−-
3989−-
3990−--- | verify a property. if not true, throw the error message.
3991−---
3992−--- It is intended to be used in a infix notation, on the right of the code,
3993−--- in order to separate the code assertions from the application code and make clearly
3994−--- visible them as a form of documentation.
3995−--- separated from it:
3996−---
3997−--- > liftIO $ print (x :: Int) `verify` (return $ x > 10, "x < = 10")
3998−---
3999−--- the expression is monadic to allow for complex verifications that may involve IO actions
4000−-verifyM :: Monad m => m b -> (m Bool, String) -> m b
4001−-verifyM f (mprop, msg)= do
4002−- prop <- mprop
4003−- case prop of
4004−- True -> f
4005−- False -> error msg
4006−-
4007−--- | a pure version of verifyM
4008−-verify :: a -> (Bool, String) -> a
4009−-verify f (prop, msg)= do
4010−- case prop of
4011−- True -> f
4012−- False -> error msg
4013−-
4014−-
4015−---
4016−---match form=do
4017−--- marches <- readIORef matches
4018−--- return $ head map (m s) matches
4019−--- where
4020−--- m s (ms,ps) = case and $ map (flip isInfixOf $ s) ms of
4021−--- True -> Just ps
4022−--- False -> Nothing
4023−---
4024−---composeParams (Gen ps) form= zip (getParams form) ps
4025−--- where
4026−--- getParams form=
4027−--- let search name form
4028−--- | null form = mempty
4029−--- | isPrefix name form = drop (length name) form
4030−--- | otherwise= search name $ tail form
4031−---
4032−--- par s= takeWhile(/='\"') . dropWhile (/='\"') . tail . dropWhile (/='=') $ s
4033−--- getPar= par $ search "name"
4034−--- in getPar form
4035−---
4036−-
4037−-waction :: (Functor m, MonadIO m,Generate a, FormInput view)
4038−- => View view m a
4039−- -> (a -> FlowM view m b)
4040−- -> View view m b
4041−-waction w f= do
4042−- x <- liftIO generate
4043−- MFlow.Forms.waction (return x) f
4044−-
4045−-userWidget :: ( MonadIO m, Functor m
4046−- , FormInput view)
4047−- => Maybe String
4048−- -> View view m (Maybe (String,String), Maybe String)
4049−- -> View view m String
4050−-userWidget muser formuser= do
4051−- user <- getCurrentUser
4052−- if muser== Just user then return user
4053−- else if isJust muser then do
4054−- let user= fromJust muser
4055−- login user >> return user
4056−- else liftIO generate >>= \u -> login u >> return u
4057−-
4058−- where
4059−- login uname= do
4060−- st <- get
4061−- let t = mfToken st
4062−- t'= t{tuser= uname}
4063−- put st{mfToken= t'}
4064−- return ()
4065−-
4066−-getUserSimple :: ( MonadIO m, FormInput view, Typeable view
4067−- , Functor m)
4068−- => FlowM view m String
4069−-getUserSimple= getUser Nothing userFormLine
4070−-
4071−-
4072−-getUser :: ( FormInput view, Typeable view
4073−- , Functor m,MonadIO m)
4074−- => Maybe String
4075−- -> View view m (Maybe (String,String), Maybe String)
4076−- -> FlowM view m String
4077−-getUser mu form= ask $ userWidget mu form
4078−-
4079−---wmodify
4080−--- :: (Functor m, MonadIO m, FormInput v, Generate (Maybe a)) =>
4081−--- View v m a1
4082−--- -> ([v] -> Maybe a -> WState v m ([v], Maybe b))
4083−--- -> View v m b
4084−---wmodify formt act = do
4085−--- x <- liftIO generate
4086−--- formt `MFlow.Forms.wmodify` (\ f _-> return (f,x)) `MFlow.Forms.wmodify` act
4087−-
4088−-{-
4089−-type Var= String
4090−-data Test= Test{tflink:: [(Var,String)]
4091−- ,selectOptions :: [(Var,[String])]
4092−- ,tfinput :: [(Var, String)]
4093−- ,tftextarea :: [(Var, String)]
4094−- }
4095−- deriving(Read,Show)
4096−-
4097−-type TestM = Test -> Test
4098−-
4099−-instance Monoid TestM where
4100−- mempty= id
4101−- mappend= (.)
4102−-
4103−-instance FormInput TestM where
4104−- ftag = const id
4105−- inred = const id
4106−- fromStr = const id
4107−- flink var _= let(n,v)=break (=='=') var in \t ->t{tflink= (n,tail v):tflink t}
4108−- finput n _ v _ _ = \t -> t{tfinput = (n,v):tfinput t}
4109−- ftextarea n v= \t -> t{tftextarea = (n,v):tftextarea t}
4110−- fselect n _= \t -> t{selectOptions=(n,[]):selectOptions t}
4111−- foption o _ _= \t ->
4112−- let (n,opts)= head $ selectOptions t
4113−- in t{selectOptions=(n,o:opts):tail (selectOptions t)}
4114−- formAction _ _= id
4115−- addAttributes _ _= id
4116−-
4117−-generateGenerate Test{..}= do
4118−- b <- generate
4119−- case b of
4120−- True -> genLink
4121−- False -> genForm
4122−-
4123−- where
4124−- genForm= do
4125−- -- one on every generate is incomplete
4126−- n <- randomRIO(0,10) :: IO Int
4127−- case n of
4128−- 0 -> do
4129−- genInput
4130−-
4131−- _ -> do
4132−- r1 <- genInput
4133−- r2 <- genSelect
4134−- r3 <- genTextArea
4135−- return $ r1++r2++r3
4136−- genLink= do
4137−- let n = length tflink
4138−- if n == 0 then genForm
4139−- else do
4140−- r <- randomRIO(0,n )
4141−- return [tflink !! r]
4142−-
4143−- genSelect=do
4144−- let n = length selectOptions
4145−- if n== 0
4146−- then return []
4147−- else mapM gen selectOptions
4148−- where
4149−- gen(s,os)= do
4150−- let m = length os
4151−- j <- randomRIO(0,m)
4152−- return (s, os !! j)
4153−-
4154−- genInput= do
4155−- let n = length tftextarea
4156−- if n==0
4157−- then return []
4158−- else mapM gen tfinput
4159−- where gen(n,_)= do
4160−- str <- generate
4161−- return $ (n,str)
4162−-
4163−- genTextArea= do
4164−- let n = length tfinput
4165−- if n==0
4166−- then return []
4167−- else mapM gen tftextarea
4168−- where
4169−- gen(n,_)= do
4170−- str <- generate
4171−- return $ (n,str)
4172−-
4173−-pwf= "pwf"
4174−-ind= "ind"
4175−-instance Processable Params where
4176−- pwfname = fromMaybe noScript . lookup pwf
4177−- puser= fromMaybe anonymous . lookup cookieuser
4178−- pind = fromMaybe "0" . lookup ind
4179−- getParams = id
4180−-
4181−-
4182−-
4183−-runTest nusers = do
4184−- wfs <- getMessageFlows
4185−- replicateM nusers $ gen wfs
4186−- where
4187−- gen wfs = do
4188−- u <- generate
4189−- mapM (genTraffic u) $ M.toList wfs
4190−-
4191−- genTraffic u (n,_)= forkIO $ iterategenerates [(pwf,n),(cookieuser,u)] []
4192−-
4193−- iterategenerates ident msg= iterate [] msg
4194−- where
4195−- iterate cs msg= do
4196−- (HttpData ps cooks test,_) <- msgScheduler $ ident ++ cs++ msg
4197−- let cs'= cs++ map (\(a,b,c,d)-> (a,b)) cooks
4198−- resp <- generateGenerate . read $ B.unpack test
4199−- iterate cs' resp
4200−-
4201−- -}
4202−+
4203−+ let t = Token x y z [] [] undefined undefined undefined
4204−+ WF.start name f t
4205−+
4206−+testNumber= unsafePerformIO $ newIORef 0
4207−+
4208−+getTestNumber :: MonadIO m => m Int
4209−+getTestNumber= liftIO $ readIORef testNumber
4210−+
4211−+-- | inject substitutes an expression by other. It may be used to override
4212−+-- ask interaction with the user. It should bee used infix for greater readability:
4213−+--
4214−+-- > ask something `inject` const someother
4215−+--
4216−+-- The parameter passed is the test number
4217−+-- if the flow has not been executed by runTest, inject return the original
4218−+inject :: MonadIO m => m b -> (Int -> b) -> m b
4219−+inject exp v= do
4220−+ n <- getTestNumber
4221−+ if n== 0 then exp else exp `seq` return $ v n
4222−+
4223−+-- | a simulated ask that generate simulated user input of the type expected.
4224−+--
4225−+-- It forces the web page rendering, since it is monadic and can contain
4226−+-- side effects and load effects to be tested.
4227−+--
4228−+-- it is a substitute of 'ask' from "MFlow.Forms" for testing purposes.
4229−+
4230−+-- execute 'runText' to initiate threads under different load conditions.
4231−+ask :: (Generate a, MonadIO m, Functor m, FormInput v,Typeable v) => View v m a -> FlowM v m a
4232−+ask w = do
4233−+ FormElm forms mx <- FlowM . lift $ runView w
4234−+ r <- liftIO generate
4235−+ let n= B.length $ toByteString forms
4236−+ breturn $ n `seq` mx `seq` r
4237−+-- let u= undefined
4238−+-- liftIO $ runStateT (runView mf) s
4239−+-- bool <- liftIO generate
4240−+-- case bool of
4241−+-- False -> fail ""
4242−+-- True -> do
4243−+-- b <- liftIO generate
4244−+-- r <- liftIO generate
4245−+-- case (b,r) of
4246−+-- (True,x) -> breturn x
4247−+-- _ -> ask w
4248−+
4249−+
4250−+-- | instead of generating a result like `ask`, the result is given as the first parameter
4251−+-- so it does not need a Generate instance.
4252−+--
4253−+-- It forces the web page rendering, since it is monadic so it can contain
4254−+-- side effects and load effects to be tested.
4255−+askt :: (MonadIO m, FormInput v) => (Int -> a) -> View v m a -> FlowM v m a
4256−+askt v w = do
4257−+ FormElm forms mx <- FlowM . lift $ runView w
4258−+ n <- getTestNumber
4259−+ let l= B.length $ toByteString forms
4260−+ breturn $ l `seq` mx `seq` v n
4261−+
4262−+--mvtestopts :: MVar (M.Map String (Int,Dynamic))
4263−+--mvtestopts = unsafePerformIO $ newMVar M.empty
4264−+
4265−+--asktn :: (Typeable a,MonadIO m) => [a] -> View v m a -> FlowM v m a
4266−+--asktn xs w= do
4267−+-- v <- liftIO $ do
4268−+-- let k = addrStr xs
4269−+-- opts <- takeMVar mvtestopts
4270−+-- let r = M.lookup k opts
4271−+-- case r of
4272−+-- Nothing -> do
4273−+-- putMVar mvtestopts $ M.singleton k (0,toDyn xs)
4274−+-- return $ head xs
4275−+-- Just (i,d) -> do
4276−+-- putMVar mvtestopts $ M.insert k (i+1,d) opts
4277−+-- return $ (fromMaybe (error err1) $ fromDynamic d) !! i
4278−+--
4279−+-- askt v w
4280−+--
4281−+-- where
4282−+-- err1= "MFlow.Forms.Test: asktn: fromDynamic error"
4283−+
4284−+
4285−+-- | verify a property. if not true, throw the error message.
4286−+--
4287−+-- It is intended to be used in a infix notation, on the right of the code,
4288−+-- in order to separate the code assertions from the application code and make clearly
4289−+-- visible them as a form of documentation.
4290−+-- separated from it:
4291−+--
4292−+-- > liftIO $ print (x :: Int) `verify` (return $ x > 10, "x < = 10")
4293−+--
4294−+-- the expression is monadic to allow for complex verifications that may involve IO actions
4295−+verifyM :: Monad m => m b -> (m Bool, String) -> m b
4296−+verifyM f (mprop, msg)= do
4297−+ prop <- mprop
4298−+ case prop of
4299−+ True -> f
4300−+ False -> error msg
4301−+
4302−+-- | a pure version of verifyM
4303−+verify :: a -> (Bool, String) -> a
4304−+verify f (prop, msg)= do
4305−+ case prop of
4306−+ True -> f
4307−+ False -> error msg
4308−+
4309−+
4310−+--
4311−+--match form=do
4312−+-- marches <- readIORef matches
4313−+-- return $ head map (m s) matches
4314−+-- where
4315−+-- m s (ms,ps) = case and $ map (flip isInfixOf $ s) ms of
4316−+-- True -> Just ps
4317−+-- False -> Nothing
4318−+--
4319−+--composeParams (Gen ps) form= zip (getParams form) ps
4320−+-- where
4321−+-- getParams form=
4322−+-- let search name form
4323−+-- | null form = mempty
4324−+-- | isPrefix name form = drop (length name) form
4325−+-- | otherwise= search name $ tail form
4326−+--
4327−+-- par s= takeWhile(/='\"') . dropWhile (/='\"') . tail . dropWhile (/='=') $ s
4328−+-- getPar= par $ search "name"
4329−+-- in getPar form
4330−+--
4331−+
4332−+waction :: (Functor m, MonadIO m,Generate a, FormInput view)
4333−+ => View view m a
4334−+ -> (a -> FlowM view m b)
4335−+ -> View view m b
4336−+waction w f= do
4337−+ x <- liftIO generate
4338−+ MFlow.Forms.waction (return x) f
4339−+
4340−+userWidget :: ( MonadIO m, Functor m
4341−+ , FormInput view)
4342−+ => Maybe String
4343−+ -> View view m (Maybe (String,String), Maybe String)
4344−+ -> View view m String
4345−+userWidget muser formuser= do
4346−+ user <- getCurrentUser
4347−+ if muser== Just user then return user
4348−+ else if isJust muser then do
4349−+ let user= fromJust muser
4350−+ login user >> return user
4351−+ else liftIO generate >>= \u -> login u >> return u
4352−+
4353−+ where
4354−+ login uname= do
4355−+ st <- get
4356−+ let t = mfToken st
4357−+ t'= t{tuser= uname}
4358−+ put st{mfToken= t'}
4359−+ return ()
4360−+
4361−+getUserSimple :: ( MonadIO m, FormInput view, Typeable view
4362−+ , Functor m)
4363−+ => FlowM view m String
4364−+getUserSimple= getUser Nothing userFormLine
4365−+
4366−+
4367−+getUser :: ( FormInput view, Typeable view
4368−+ , Functor m,MonadIO m)
4369−+ => Maybe String
4370−+ -> View view m (Maybe (String,String), Maybe String)
4371−+ -> FlowM view m String
4372−+getUser mu form= ask $ userWidget mu form
4373−+
4374−+--wmodify
4375−+-- :: (Functor m, MonadIO m, FormInput v, Generate (Maybe a)) =>
4376−+-- View v m a1
4377−+-- -> ([v] -> Maybe a -> WState v m ([v], Maybe b))
4378−+-- -> View v m b
4379−+--wmodify formt act = do
4380−+-- x <- liftIO generate
4381−+-- formt `MFlow.Forms.wmodify` (\ f _-> return (f,x)) `MFlow.Forms.wmodify` act
4382−+
4383−+{-
4384−+type Var= String
4385−+data Test= Test{tflink:: [(Var,String)]
4386−+ ,selectOptions :: [(Var,[String])]
4387−+ ,tfinput :: [(Var, String)]
4388−+ ,tftextarea :: [(Var, String)]
4389−+ }
4390−+ deriving(Read,Show)
4391−+
4392−+type TestM = Test -> Test
4393−+
4394−+instance Monoid TestM where
4395−+ mempty= id
4396−+ mappend= (.)
4397−+
4398−+instance FormInput TestM where
4399−+ ftag = const id
4400−+ inred = const id
4401−+ fromStr = const id
4402−+ flink var _= let(n,v)=break (=='=') var in \t ->t{tflink= (n,tail v):tflink t}
4403−+ finput n _ v _ _ = \t -> t{tfinput = (n,v):tfinput t}
4404−+ ftextarea n v= \t -> t{tftextarea = (n,v):tftextarea t}
4405−+ fselect n _= \t -> t{selectOptions=(n,[]):selectOptions t}
4406−+ foption o _ _= \t ->
4407−+ let (n,opts)= head $ selectOptions t
4408−+ in t{selectOptions=(n,o:opts):tail (selectOptions t)}
4409−+ formAction _ _= id
4410−+ addAttributes _ _= id
4411−+
4412−+generateGenerate Test{..}= do
4413−+ b <- generate
4414−+ case b of
4415−+ True -> genLink
4416−+ False -> genForm
4417−+
4418−+ where
4419−+ genForm= do
4420−+ -- one on every generate is incomplete
4421−+ n <- randomRIO(0,10) :: IO Int
4422−+ case n of
4423−+ 0 -> do
4424−+ genInput
4425−+
4426−+ _ -> do
4427−+ r1 <- genInput
4428−+ r2 <- genSelect
4429−+ r3 <- genTextArea
4430−+ return $ r1++r2++r3
4431−+ genLink= do
4432−+ let n = length tflink
4433−+ if n == 0 then genForm
4434−+ else do
4435−+ r <- randomRIO(0,n )
4436−+ return [tflink !! r]
4437−+
4438−+ genSelect=do
4439−+ let n = length selectOptions
4440−+ if n== 0
4441−+ then return []
4442−+ else mapM gen selectOptions
4443−+ where
4444−+ gen(s,os)= do
4445−+ let m = length os
4446−+ j <- randomRIO(0,m)
4447−+ return (s, os !! j)
4448−+
4449−+ genInput= do
4450−+ let n = length tftextarea
4451−+ if n==0
4452−+ then return []
4453−+ else mapM gen tfinput
4454−+ where gen(n,_)= do
4455−+ str <- generate
4456−+ return $ (n,str)
4457−+
4458−+ genTextArea= do
4459−+ let n = length tfinput
4460−+ if n==0
4461−+ then return []
4462−+ else mapM gen tftextarea
4463−+ where
4464−+ gen(n,_)= do
4465−+ str <- generate
4466−+ return $ (n,str)
4467−+
4468−+pwf= "pwf"
4469−+ind= "ind"
4470−+instance Processable Params where
4471−+ pwfname = fromMaybe noScript . lookup pwf
4472−+ puser= fromMaybe anonymous . lookup cookieuser
4473−+ pind = fromMaybe "0" . lookup ind
4474−+ getParams = id
4475−+
4476−+
4477−+
4478−+runTest nusers = do
4479−+ wfs <- getMessageFlows
4480−+ replicateM nusers $ gen wfs
4481−+ where
4482−+ gen wfs = do
4483−+ u <- generate
4484−+ mapM (genTraffic u) $ M.toList wfs
4485−+
4486−+ genTraffic u (n,_)= forkIO $ iterategenerates [(pwf,n),(cookieuser,u)] []
4487−+
4488−+ iterategenerates ident msg= iterate [] msg
4489−+ where
4490−+ iterate cs msg= do
4491−+ (HttpData ps cooks test,_) <- msgScheduler $ ident ++ cs++ msg
4492−+ let cs'= cs++ map (\(a,b,c,d)-> (a,b)) cooks
4493−+ resp <- generateGenerate . read $ B.unpack test
4494−+ iterate cs' resp
4495−+
4496−+ -}
4497−diff -ru orig/src/MFlow/Forms/Widgets.hs new/src/MFlow/Forms/Widgets.hs
4498−--- orig/src/MFlow/Forms/Widgets.hs 2014-06-10 05:51:26.977015856 +0300
4499−+++ new/src/MFlow/Forms/Widgets.hs 2014-06-10 05:51:25.000000000 +0300
4500−@@ -1,114 +1,114 @@
4501−-
4502−-{- |
4503−-Some dynamic widgets, widgets that dynamically edit content in other widgets,
4504−-widgets for templating, content management and multilanguage. And some primitives
4505−-to create other active widgets.
4506−--}
4507−+
4508−+{- |
4509−+Some dynamic widgets, widgets that dynamically edit content in other widgets,
4510−+widgets for templating, content management and multilanguage. And some primitives
4511−+to create other active widgets.
4512−+-}
4513− -- {-# OPTIONS -F -pgmF cpphs #-}
4514−-{-# OPTIONS -cpp -pgmPcpphs -optP--cpp #-}
4515−-{-# LANGUAGE UndecidableInstances,ExistentialQuantification
4516−- , FlexibleInstances, OverlappingInstances, FlexibleContexts
4517−+{-# OPTIONS -cpp -pgmPcpphs -optP--cpp #-}
4518−+{-# LANGUAGE UndecidableInstances,ExistentialQuantification
4519−+ , FlexibleInstances, OverlappingInstances, FlexibleContexts
4520− , OverloadedStrings, DeriveDataTypeable , ScopedTypeVariables
4521−- , StandaloneDeriving #-}
4522−-
4523−-
4524−-
4525−-
4526−-module MFlow.Forms.Widgets (
4527−--- * Ajax refreshing of widgets
4528−-autoRefresh, noAutoRefresh, appendUpdate, prependUpdate, push, UpdateMethod(..), lazy
4529−-
4530−--- * JQueryUi widgets
4531−-,datePicker, getSpinner, wautocomplete, wdialog,
4532−-
4533−--- * User Management
4534−-userFormOrName,maybeLogout, wlogin,
4535−-
4536−--- * Active widgets
4537−-wEditList,wautocompleteList
4538−-, wautocompleteEdit,
4539−-
4540−--- * Editing widgets
4541−-delEdited, getEdited, setEdited, prependWidget,appendWidget,setWidget
4542−-
4543−--- * Content Management
4544−-,tField, tFieldEd, htmlEdit, edTemplate, dField, template, witerate,tfieldKey
4545−-
4546−--- * Multilanguage
4547−-,mFieldEd, mField
4548−-
4549−--- * utility
4550−-,insertForm, readtField, writetField
4551−-
4552−-
4553−-) where
4554−-import MFlow
4555−-import MFlow.Forms
4556−-import MFlow.Forms.Internals
4557−-import Data.Monoid
4558−+ , StandaloneDeriving #-}
4559−+
4560−+
4561−+
4562−+
4563−+module MFlow.Forms.Widgets (
4564−+-- * Ajax refreshing of widgets
4565−+autoRefresh, noAutoRefresh, appendUpdate, prependUpdate, push, UpdateMethod(..), lazy
4566−+
4567−+-- * JQueryUi widgets
4568−+,datePicker, getSpinner, wautocomplete, wdialog,
4569−+
4570−+-- * User Management
4571−+userFormOrName,maybeLogout, wlogin,
4572−+
4573−+-- * Active widgets
4574−+wEditList,wautocompleteList
4575−+, wautocompleteEdit,
4576−+
4577−+-- * Editing widgets
4578−+delEdited, getEdited, setEdited, prependWidget,appendWidget,setWidget
4579−+
4580−+-- * Content Management
4581−+,tField, tFieldEd, htmlEdit, edTemplate, dField, template, witerate,tfieldKey
4582−+
4583−+-- * Multilanguage
4584−+,mFieldEd, mField
4585−+
4586−+-- * utility
4587−+,insertForm, readtField, writetField
4588−+
4589−+
4590−+) where
4591−+import MFlow
4592−+import MFlow.Forms
4593−+import MFlow.Forms.Internals
4594−+import Data.Monoid
4595− import Data.ByteString.Lazy.UTF8 as B hiding (length,span)
4596−-import Data.ByteString.Lazy.Char8 (unpack)
4597−-import Control.Monad.Trans
4598−-import Data.Typeable
4599−-import Data.List
4600−-import System.IO.Unsafe
4601−-
4602−-import Control.Monad.State
4603−-import Data.TCache
4604−-import Data.TCache.Defs
4605−-import Data.TCache.Memoization
4606−-import Data.RefSerialize hiding ((<|>))
4607−-import qualified Data.Map as M
4608−-import Data.IORef
4609−-import MFlow.Cookies
4610−-import Data.Maybe
4611−-import Data.Char
4612−-import Control.Monad.Identity
4613−-import Control.Workflow(killWF)
4614−-import Unsafe.Coerce
4615−-import Control.Exception
4616−+import Data.ByteString.Lazy.Char8 (unpack)
4617−+import Control.Monad.Trans
4618−+import Data.Typeable
4619−+import Data.List
4620−+import System.IO.Unsafe
4621−+
4622−+import Control.Monad.State
4623−+import Data.TCache
4624−+import Data.TCache.Defs
4625−+import Data.TCache.Memoization
4626−+import Data.RefSerialize hiding ((<|>))
4627−+import qualified Data.Map as M
4628−+import Data.IORef
4629−+import MFlow.Cookies
4630−+import Data.Maybe
4631−+import Data.Char
4632−+import Control.Monad.Identity
4633−+import Control.Workflow(killWF)
4634−+import Unsafe.Coerce
4635−+import Control.Exception
4636− import MFlow.Forms.Cache
4637−-
4638−-
4639−-
4640−---jqueryScript= "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
4641−---jqueryScript1="//code.jquery.com/jquery-1.9.1.js"
4642−---
4643−---jqueryCSS1= "//code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css"
4644−---jqueryCSS= "//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"
4645−---
4646−---jqueryUI1= "//code.jquery.com/ui/1.9.1/jquery-ui.js"
4647−---jqueryUI= "//code.jquery.com/ui/1.10.3/jquery-ui.js"
4648−-
4649−-jqueryScript= getConfig "cjqueryScript" "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
4650−-jqueryCSS= getConfig "cjqueryCSS" "//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"
4651−-jqueryUI= getConfig "cjqueryUI" "//code.jquery.com/ui/1.10.3/jquery-ui.js"
4652−-nicEditUrl= getConfig "cnicEditUrl" "//js.nicedit.com/nicEdit-latest.js"
4653−-------- User Management ------
4654−-
4655−--- | Present a user form if not logged in. Otherwise, the user name and a logout link is presented.
4656−--- The paremeters and the behaviour are the same as 'userWidget'.
4657−--- Only the display is different
4658−-userFormOrName mode wid= userWidget mode wid `wmodify` f <** maybeLogout
4659−- where
4660−- f _ justu@(Just u) = return ([fromStr u], justu) -- !> "input"
4661−- f felem Nothing = do
4662−- us <- getCurrentUser -- getEnv cookieuser
4663−- if us == anonymous
4664−- then return (felem, Nothing)
4665−- else return([fromStr us], Just us)
4666−-
4667−--- | Display a logout link if the user is logged. Nothing otherwise
4668−-maybeLogout :: (MonadIO m,Functor m,FormInput v) => View v m ()
4669−-maybeLogout= do
4670−- us <- getCurrentUser
4671−- if us/= anonymous
4672−- then do
4673−- cmd <- ajax $ const $ return "window.location=='/'" --refresh
4674−- fromStr " " ++> ((wlink () (fromStr "logout")) <![("onclick",cmd "''")]) `waction` const logout
4675−+
4676−+
4677−+
4678−+--jqueryScript= "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
4679−+--jqueryScript1="//code.jquery.com/jquery-1.9.1.js"
4680−+--
4681−+--jqueryCSS1= "//code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css"
4682−+--jqueryCSS= "//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"
4683−+--
4684−+--jqueryUI1= "//code.jquery.com/ui/1.9.1/jquery-ui.js"
4685−+--jqueryUI= "//code.jquery.com/ui/1.10.3/jquery-ui.js"
4686−+
4687−+jqueryScript= getConfig "cjqueryScript" "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
4688−+jqueryCSS= getConfig "cjqueryCSS" "//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"
4689−+jqueryUI= getConfig "cjqueryUI" "//code.jquery.com/ui/1.10.3/jquery-ui.js"
4690−+nicEditUrl= getConfig "cnicEditUrl" "//js.nicedit.com/nicEdit-latest.js"
4691−+------- User Management ------
4692−+
4693−+-- | Present a user form if not logged in. Otherwise, the user name and a logout link is presented.
4694−+-- The paremeters and the behaviour are the same as 'userWidget'.
4695−+-- Only the display is different
4696−+userFormOrName mode wid= userWidget mode wid `wmodify` f <** maybeLogout
4697−+ where
4698−+ f _ justu@(Just u) = return ([fromStr u], justu) -- !> "input"
4699−+ f felem Nothing = do
4700−+ us <- getCurrentUser -- getEnv cookieuser
4701−+ if us == anonymous
4702−+ then return (felem, Nothing)
4703−+ else return([fromStr us], Just us)
4704−+
4705−+-- | Display a logout link if the user is logged. Nothing otherwise
4706−+maybeLogout :: (MonadIO m,Functor m,FormInput v) => View v m ()
4707−+maybeLogout= do
4708−+ us <- getCurrentUser
4709−+ if us/= anonymous
4710−+ then do
4711−+ cmd <- ajax $ const $ return "window.location=='/'" --refresh
4712−+ fromStr " " ++> ((wlink () (fromStr "logout")) <![("onclick",cmd "''")]) `waction` const logout
4713− else noWidget
4714−
4715−-
4716−+
4717− data Medit view m a = Medit (M.Map B.ByteString [(String,View view m a)])
4718−
4719− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
4720−@@ -129,46 +129,46 @@
4721− ta :: Medit v m a -> a
4722− ta= undefined
4723−
4724−-#endif
4725−-
4726−--- | If not logged, it present a page flow which askm for the user name, then the password if not logged
4727−---
4728−--- If logged, it present the user name and a link to logout
4729−---
4730−--- normally to be used with autoRefresh and pageFlow when used with other widgets.
4731−-wlogin :: (MonadIO m,Functor m,FormInput v) => View v m ()
4732−-wlogin= do
4733−- username <- getCurrentUser
4734−- if username /= anonymous
4735−+#endif
4736−+
4737−+-- | If not logged, it present a page flow which askm for the user name, then the password if not logged
4738−+--
4739−+-- If logged, it present the user name and a link to logout
4740−+--
4741−+-- normally to be used with autoRefresh and pageFlow when used with other widgets.
4742−+wlogin :: (MonadIO m,Functor m,FormInput v) => View v m ()
4743−+wlogin= wform $ do
4744−+ username <- getCurrentUser
4745−+ if username /= anonymous
4746− then do
4747− private; noCache;noStore
4748−- return username
4749−- else do
4750−+ return username
4751−+ else do
4752− name <- getString Nothing <! hint "login name"
4753− <! size (9 :: Int)
4754−- <++ ftag "br" mempty
4755−+ <++ ftag "br" mempty
4756− pass <- getPassword <! hint "password"
4757−- <! size 9
4758−- <++ ftag "br" mempty
4759−- <** submitButton "login"
4760−- val <- userValidate (name,pass)
4761−- case val of
4762−- Just msg -> notValid msg
4763−- Nothing -> login name >> (return name)
4764−-
4765−- `wcallback` (\name -> ftag "b" (fromStr $ "logged as " ++ name++ " ")
4766−- ++> pageFlow "logout" (submitButton "logout")) -- wlink ("logout" :: String) (ftag "b" $ fromStr " logout"))
4767−- `wcallback` const (logout >> wlogin)
4768−-
4769−-focus = [("onload","this.focus()")]
4770−-hint s= [("placeholder",s)]
4771−-size n= [("size",show n)]
4772−-
4773−-getEdited1 id= do
4774−- Medit stored <- getSessionData `onNothing` return (Medit M.empty)
4775−- return $ fromMaybe [] $ M.lookup id stored
4776−-
4777−--- | Return the list of edited widgets (added by the active widgets) for a given identifier
4778−+ <! size 9
4779−+ <++ ftag "br" mempty
4780−+ <** submitButton "login"
4781−+ val <- userValidate (name,pass)
4782−+ case val of
4783−+ Just msg -> notValid msg
4784−+ Nothing -> login name >> (return name)
4785−+
4786−+ `wcallback` (\name -> ftag "b" (fromStr $ "logged as " ++ name++ " ")
4787−+ ++> pageFlow "logout" (submitButton "logout")) -- wlink ("logout" :: String) (ftag "b" $ fromStr " logout"))
4788−+ `wcallback` const (logout >> wlogin)
4789−+
4790−+focus = [("onload","this.focus()")]
4791−+hint s= [("placeholder",s)]
4792−+size n= [("size",show n)]
4793−+
4794−+getEdited1 id= do
4795−+ Medit stored <- getSessionData `onNothing` return (Medit M.empty)
4796−+ return $ fromMaybe [] $ M.lookup id stored
4797−+
4798−+-- | Return the list of edited widgets (added by the active widgets) for a given identifier
4799− getEdited
4800−
4801− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
4802−@@ -181,15 +181,15 @@
4803−
4804− #endif
4805−
4806−- B.ByteString -> m [View v m1 a]
4807−+ B.ByteString -> m [View v m1 a]
4808−+
4809−+getEdited id= do
4810−+ r <- getEdited1 id
4811−+ let (_,ws)= unzip r
4812−+ return ws
4813−
4814−-getEdited id= do
4815−- r <- getEdited1 id
4816−- let (_,ws)= unzip r
4817−- return ws
4818−-
4819−--- | Deletes the list of edited widgets for a certain identifier and with the type of the witness widget parameter
4820−-delEdited
4821−+-- | Deletes the list of edited widgets for a certain identifier and with the type of the witness widget parameter
4822−+delEdited
4823− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
4824− :: (Typeable v, Typeable a, MonadIO m, Typeable m1,
4825− #else
4826−@@ -197,312 +197,312 @@
4827− #endif
4828− MonadState (MFlowState view) m)
4829− => B.ByteString -- ^ identifier
4830−- -> [View v m1 a] -> m () -- ^ withess
4831−-delEdited id witness=do
4832−- Medit stored <- getSessionData `onNothing` return (Medit (M.empty))
4833−- let (ks, ws)= unzip $ fromMaybe [] $ M.lookup id stored
4834−-
4835−- return $ ws `asTypeOf` witness
4836−- liftIO $ mapM flushCached ks
4837−- let stored'= M.delete id stored
4838−- setSessionData . Medit $ stored'
4839−-
4840−-
4841−-
4842−--- setEdited id ([] `asTypeOf` (zip (repeat "") witness))
4843−-
4844−-setEdited id ws= do
4845−- Medit stored <- getSessionData `onNothing` return (Medit (M.empty))
4846−- let stored'= M.insert id ws stored
4847−- setSessionData . Medit $ stored'
4848−-
4849−-
4850−-addEdited id w= do
4851−- ws <- getEdited1 id
4852−- setEdited id (w:ws)
4853−-
4854−+ -> [View v m1 a] -> m () -- ^ withess
4855−+delEdited id witness=do
4856−+ Medit stored <- getSessionData `onNothing` return (Medit (M.empty))
4857−+ let (ks, ws)= unzip $ fromMaybe [] $ M.lookup id stored
4858−+
4859−+ return $ ws `asTypeOf` witness
4860−+ liftIO $ mapM flushCached ks
4861−+ let stored'= M.delete id stored
4862−+ setSessionData . Medit $ stored'
4863−+
4864−+
4865−+
4866−+-- setEdited id ([] `asTypeOf` (zip (repeat "") witness))
4867−+
4868−+setEdited id ws= do
4869−+ Medit stored <- getSessionData `onNothing` return (Medit (M.empty))
4870−+ let stored'= M.insert id ws stored
4871−+ setSessionData . Medit $ stored'
4872−+
4873−+
4874−+addEdited id w= do
4875−+ ws <- getEdited1 id
4876−+ setEdited id (w:ws)
4877−+
4878− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
4879− modifyWidget :: (MonadIO m,Executable m,Typeable a,FormInput v, Typeable Identity, Typeable m)
4880−-#else
4881−-modifyWidget :: (MonadIO m,Executable m,Typeable a,FormInput v)
4882−+#else
4883−+modifyWidget :: (MonadIO m,Executable m,Typeable a,FormInput v)
4884− #endif
4885−- => B.ByteString -> B.ByteString -> View v Identity a -> View v m B.ByteString
4886−-modifyWidget selector modifier w = View $ do
4887−- ws <- getEdited selector
4888−- let n = length (ws `asTypeOf` [w])
4889−- let key= "widget"++ show selector ++ show n ++ show (typeOf $ typ w)
4890−- let cw = wcached key 0 w
4891−- addEdited selector (key,cw)
4892−- FormElm form _ <- runView cw
4893−- let elem= toByteString form
4894−- return . FormElm mempty . Just $ selector <> "." <> modifier <>"('" <> elem <> "');"
4895−- where
4896−- typ :: View v Identity a -> a
4897−- typ = undefined
4898−-
4899−--- | Return the javascript to be executed on the browser to prepend a widget to the location
4900−--- identified by the selector (the bytestring parameter), The selector must have the form of a jquery expression
4901−--- . It stores the added widgets in the edited list, that is accessed with 'getEdited'
4902−---
4903−--- The resulting string can be executed in the browser. 'ajax' will return the code to
4904−--- execute the complete ajax roundtrip. This code returned by ajax must be in an eventhabdler.
4905−---
4906−--- This example will insert a widget in the div when the element with identifier
4907−--- /clickelem/ is clicked. when the form is sbmitted, the widget values are returned
4908−--- and the list of edited widgets are deleted.
4909−---
4910−--- > id1<- genNewId
4911−--- > let sel= "$('#" <> fromString id1 <> "')"
4912−--- > callAjax <- ajax . const $ prependWidget sel wn
4913−--- > let installevents= "$(document).ready(function(){\
4914−--- > \$('#clickelem').click(function(){"++callAjax "''"++"});})"
4915−--- >
4916−--- > requires [JScriptFile jqueryScript [installevents] ]
4917−--- > ws <- getEdited sel
4918−--- > r <- (div <<< manyOf ws) <! [("id",id1)]
4919−--- > delEdited sel ws'
4920−--- > return r
4921−-
4922−+ => B.ByteString -> B.ByteString -> View v Identity a -> View v m B.ByteString
4923−+modifyWidget selector modifier w = View $ do
4924−+ ws <- getEdited selector
4925−+ let n = length (ws `asTypeOf` [w])
4926−+ let key= "widget"++ show selector ++ show n ++ show (typeOf $ typ w)
4927−+ let cw = wcached key 0 w
4928−+ addEdited selector (key,cw)
4929−+ FormElm form _ <- runView cw
4930−+ let elem= toByteString form
4931−+ return . FormElm mempty . Just $ selector <> "." <> modifier <>"('" <> elem <> "');"
4932−+ where
4933−+ typ :: View v Identity a -> a
4934−+ typ = undefined
4935−+
4936−+-- | Return the javascript to be executed on the browser to prepend a widget to the location
4937−+-- identified by the selector (the bytestring parameter), The selector must have the form of a jquery expression
4938−+-- . It stores the added widgets in the edited list, that is accessed with 'getEdited'
4939−+--
4940−+-- The resulting string can be executed in the browser. 'ajax' will return the code to
4941−+-- execute the complete ajax roundtrip. This code returned by ajax must be in an eventhabdler.
4942−+--
4943−+-- This example will insert a widget in the div when the element with identifier
4944−+-- /clickelem/ is clicked. when the form is sbmitted, the widget values are returned
4945−+-- and the list of edited widgets are deleted.
4946−+--
4947−+-- > id1<- genNewId
4948−+-- > let sel= "$('#" <> fromString id1 <> "')"
4949−+-- > callAjax <- ajax . const $ prependWidget sel wn
4950−+-- > let installevents= "$(document).ready(function(){\
4951−+-- > \$('#clickelem').click(function(){"++callAjax "''"++"});})"
4952−+-- >
4953−+-- > requires [JScriptFile jqueryScript [installevents] ]
4954−+-- > ws <- getEdited sel
4955−+-- > r <- (div <<< manyOf ws) <! [("id",id1)]
4956−+-- > delEdited sel ws'
4957−+-- > return r
4958−+
4959− prependWidget
4960− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
4961− :: (Typeable a, MonadIO m, Executable m, FormInput v, Typeable Identity, Typeable m)
4962−-#else
4963−+#else
4964− :: (Typeable a, MonadIO m, Executable m, FormInput v)
4965−-#endif
4966−- => B.ByteString -- ^ jquery selector
4967−- -> View v Identity a -- ^ widget to prepend
4968−- -> View v m B.ByteString -- ^ string returned with the jquery string to be executed in the browser
4969−-prependWidget sel w= modifyWidget sel "prepend" w
4970−-
4971−--- | Like 'prependWidget' but append the widget instead of prepend.
4972−-appendWidget
4973−+#endif
4974−+ => B.ByteString -- ^ jquery selector
4975−+ -> View v Identity a -- ^ widget to prepend
4976−+ -> View v m B.ByteString -- ^ string returned with the jquery string to be executed in the browser
4977−+prependWidget sel w= modifyWidget sel "prepend" w
4978−+
4979−+-- | Like 'prependWidget' but append the widget instead of prepend.
4980−+appendWidget
4981− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
4982− :: (Typeable a, MonadIO m, Executable m, FormInput v, Typeable Identity, Typeable m) =>
4983− #else
4984− :: (Typeable a, MonadIO m, Executable m, FormInput v) =>
4985− #endif
4986−- B.ByteString -> View v Identity a -> View v m B.ByteString
4987−-appendWidget sel w= modifyWidget sel "append" w
4988−-
4989−--- | L ike 'prependWidget' but set the entire content of the selector instead of prepending an element
4990−-setWidget
4991−+ B.ByteString -> View v Identity a -> View v m B.ByteString
4992−+appendWidget sel w= modifyWidget sel "append" w
4993−+
4994−+-- | L ike 'prependWidget' but set the entire content of the selector instead of prepending an element
4995−+setWidget
4996− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
4997− :: (Typeable a, MonadIO m, Executable m, FormInput v, Typeable m, Typeable Identity) =>
4998− #else
4999− :: (Typeable a, MonadIO m, Executable m, FormInput v) =>
5000−-#endif
5001−- B.ByteString -> View v Identity a -> View v m B.ByteString
5002−-setWidget sel w= modifyWidget sel "html" w
5003−-
5004−-
5005−--- | Inside a tag, it add and delete widgets of the same type. When the form is submitted
5006−--- or a wlink is pressed, this widget return the list of validated widgets.
5007−--- the event for adding a new widget is attached , as a click event to the element of the page with the identifier /wEditListAdd/
5008−--- that the user will choose.
5009−---
5010−--- This example add or delete editable text boxes, with two initial boxes with
5011−--- /hi/, /how are you/ as values. Tt uses blaze-html:
5012−---
5013−--- > r <- ask $ addLink
5014−--- > ++> br
5015−--- > ++> (El.div `wEditList` getString1 $ ["hi", "how are you"]) "addid"
5016−--- > <++ br
5017−--- > <** submitButton "send"
5018−--- >
5019−--- > ask $ p << (show r ++ " returned")
5020−--- > ++> wlink () (p << text " back to menu")
5021−--- > mainmenu
5022−--- > where
5023−--- > addLink = a ! At.id "addid"
5024−--- > ! href "#"
5025−--- > $ text "add"
5026−--- > delBox = input ! type_ "checkbox"
5027−--- > ! checked ""
5028−--- > ! onclick "this.parentNode.parentNode.removeChild(this.parentNode)"
5029−--- > getString1 mx= El.div <<< delBox ++> getString mx <++ br
5030−-
5031−-wEditList :: (Typeable a,Read a
5032−+#endif
5033−+ B.ByteString -> View v Identity a -> View v m B.ByteString
5034−+setWidget sel w= modifyWidget sel "html" w
5035−+
5036−+
5037−+-- | Inside a tag, it add and delete widgets of the same type. When the form is submitted
5038−+-- or a wlink is pressed, this widget return the list of validated widgets.
5039−+-- the event for adding a new widget is attached , as a click event to the element of the page with the identifier /wEditListAdd/
5040−+-- that the user will choose.
5041−+--
5042−+-- This example add or delete editable text boxes, with two initial boxes with
5043−+-- /hi/, /how are you/ as values. Tt uses blaze-html:
5044−+--
5045−+-- > r <- ask $ addLink
5046−+-- > ++> br
5047−+-- > ++> (El.div `wEditList` getString1 $ ["hi", "how are you"]) "addid"
5048−+-- > <++ br
5049−+-- > <** submitButton "send"
5050−+-- >
5051−+-- > ask $ p << (show r ++ " returned")
5052−+-- > ++> wlink () (p << text " back to menu")
5053−+-- > mainmenu
5054−+-- > where
5055−+-- > addLink = a ! At.id "addid"
5056−+-- > ! href "#"
5057−+-- > $ text "add"
5058−+-- > delBox = input ! type_ "checkbox"
5059−+-- > ! checked ""
5060−+-- > ! onclick "this.parentNode.parentNode.removeChild(this.parentNode)"
5061−+-- > getString1 mx= El.div <<< delBox ++> getString mx <++ br
5062−+
5063−+wEditList :: (Typeable a,Read a
5064− ,FormInput view
5065− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
5066− ,Functor m,MonadIO m, Executable m, Typeable m, Typeable Identity)
5067−-#else
5068−+#else
5069− ,Functor m,MonadIO m, Executable m)
5070−-#endif
5071−- => (view ->view) -- ^ The holder tag
5072−- -> (Maybe String -> View view Identity a) -- ^ the contained widget, initialized by a string
5073−- -> [String] -- ^ The initial list of values.
5074−- -> String -- ^ The id of the button or link that will create a new list element when clicked
5075−- -> View view m [a]
5076−-wEditList holderview w xs addId = do
5077−- let ws= map (w . Just) xs
5078−- wn= w Nothing
5079−- id1<- genNewId
5080−- let sel= "$('#" <> fromString id1 <> "')"
5081−- callAjax <- ajax . const $ prependWidget sel wn
5082−- let installevents= "$(document).ready(function(){$('#"++addId++"').click(function(){"++callAjax "''"++"});})"
5083−-
5084−- requires [JScriptFile jqueryScript [installevents] ]
5085−-
5086−- ws' <- getEdited sel
5087−-
5088−- r <- (holderview <<< (allOf $ ws' ++ map changeMonad ws)) <! [("id",id1)]
5089−- delEdited sel ws'
5090−- return r
5091−-
5092−-
5093−-
5094−-
5095−--- | Present the JQuery autocompletion list, from a procedure defined by the programmer, to a text box.
5096−-wautocomplete
5097−- :: (Show a, MonadIO m, FormInput v)
5098−- => Maybe String -- ^ Initial value
5099−- -> (String -> IO a) -- ^ Autocompletion procedure: will receive a prefix and return a list of strings
5100−- -> View v m String
5101−-wautocomplete mv autocomplete = do
5102−- text1 <- genNewId
5103−- ajaxc <- ajax $ \u -> do
5104−- r <- liftIO $ autocomplete u
5105−- return $ jaddtoautocomp text1 r
5106−-
5107−-
5108−- requires [JScriptFile jqueryScript [] -- [events]
5109−- ,CSSFile jqueryCSS
5110−- ,JScriptFile jqueryUI []]
5111−-
5112−-
5113−- getString mv <! [("type", "text")
5114−- ,("id", text1)
5115−- ,("oninput", ajaxc $ "$('#"++text1++"').attr('value')" )
5116−- ,("autocomplete", "off")]
5117−-
5118−-
5119−- where
5120−- jaddtoautocomp text1 us= "$('#"<>fromString text1<>"').autocomplete({ source: " <> fromString( show us) <> " });"
5121−-
5122−-
5123−--- | Produces a text box. It gives a autocompletion list to the textbox. When return
5124−--- is pressed in the textbox, the box content is used to create a widget of a kind defined
5125−--- by the user, which will be situated above of the textbox. When submitted, the result is the content
5126−--- of the created widgets (the validated ones).
5127−---
5128−--- 'wautocompleteList' is an specialization of this widget, where
5129−--- the widget parameter is fixed, with a checkbox that delete the eleement when unselected
5130−--- . This fixed widget is as such (using generic 'FormElem' class tags):
5131−---
5132−--- > ftag "div" <<< ftag "input" mempty
5133−--- > `attrs` [("type","checkbox")
5134−--- > ,("checked","")
5135−--- > ,("onclick","this.parentNode.parentNode.removeChild(this.parentNode)")]
5136−--- > ++> ftag "span" (fromStr $ fromJust x )
5137−--- > ++> whidden( fromJust x)
5138−-wautocompleteEdit
5139−+#endif
5140−+ => (view ->view) -- ^ The holder tag
5141−+ -> (Maybe String -> View view Identity a) -- ^ the contained widget, initialized by a string
5142−+ -> [String] -- ^ The initial list of values.
5143−+ -> String -- ^ The id of the button or link that will create a new list element when clicked
5144−+ -> View view m [a]
5145−+wEditList holderview w xs addId = do
5146−+ let ws= map (w . Just) xs
5147−+ wn= w Nothing
5148−+ id1<- genNewId
5149−+ let sel= "$('#" <> fromString id1 <> "')"
5150−+ callAjax <- ajax . const $ prependWidget sel wn
5151−+ let installevents= "$(document).ready(function(){$('#"++addId++"').click(function(){"++callAjax "''"++"});})"
5152−+
5153−+ requires [JScriptFile jqueryScript [installevents] ]
5154−+
5155−+ ws' <- getEdited sel
5156−+
5157−+ r <- (holderview <<< (allOf $ ws' ++ map changeMonad ws)) <! [("id",id1)]
5158−+ delEdited sel ws'
5159−+ return r
5160−+
5161−+
5162−+
5163−+
5164−+-- | Present the JQuery autocompletion list, from a procedure defined by the programmer, to a text box.
5165−+wautocomplete
5166−+ :: (Show a, MonadIO m, FormInput v)
5167−+ => Maybe String -- ^ Initial value
5168−+ -> (String -> IO a) -- ^ Autocompletion procedure: will receive a prefix and return a list of strings
5169−+ -> View v m String
5170−+wautocomplete mv autocomplete = do
5171−+ text1 <- genNewId
5172−+ ajaxc <- ajax $ \u -> do
5173−+ r <- liftIO $ autocomplete u
5174−+ return $ jaddtoautocomp text1 r
5175−+
5176−+
5177−+ requires [JScriptFile jqueryScript [] -- [events]
5178−+ ,CSSFile jqueryCSS
5179−+ ,JScriptFile jqueryUI []]
5180−+
5181−+
5182−+ getString mv <! [("type", "text")
5183−+ ,("id", text1)
5184−+ ,("oninput", ajaxc $ "$('#"++text1++"').attr('value')" )
5185−+ ,("autocomplete", "off")]
5186−+
5187−+
5188−+ where
5189−+ jaddtoautocomp text1 us= "$('#"<>fromString text1<>"').autocomplete({ source: " <> fromString( show us) <> " });"
5190−+
5191−+
5192−+-- | Produces a text box. It gives a autocompletion list to the textbox. When return
5193−+-- is pressed in the textbox, the box content is used to create a widget of a kind defined
5194−+-- by the user, which will be situated above of the textbox. When submitted, the result is the content
5195−+-- of the created widgets (the validated ones).
5196−+--
5197−+-- 'wautocompleteList' is an specialization of this widget, where
5198−+-- the widget parameter is fixed, with a checkbox that delete the eleement when unselected
5199−+-- . This fixed widget is as such (using generic 'FormElem' class tags):
5200−+--
5201−+-- > ftag "div" <<< ftag "input" mempty
5202−+-- > `attrs` [("type","checkbox")
5203−+-- > ,("checked","")
5204−+-- > ,("onclick","this.parentNode.parentNode.removeChild(this.parentNode)")]
5205−+-- > ++> ftag "span" (fromStr $ fromJust x )
5206−+-- > ++> whidden( fromJust x)
5207−+wautocompleteEdit
5208− :: (Typeable a, MonadIO m,Functor m, Executable m
5209− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
5210− , FormInput v, Typeable m, Typeable Identity)
5211−-#else
5212−+#else
5213− , FormInput v)
5214−-#endif
5215−- => String -- ^ the initial text of the box
5216−- -> (String -> IO [String]) -- ^ the autocompletion procedure: receives a prefix, return a list of options.
5217−- -> (Maybe String -> View v Identity a) -- ^ the widget to add, initialized with the string entered in the box
5218−- -> [String] -- ^ initial set of values
5219−- -> View v m [a] -- ^ resulting widget
5220−-wautocompleteEdit phold autocomplete elem values= do
5221−- id1 <- genNewId
5222−- let textx= id1++"text"
5223−- let sel= "$('#" <> fromString id1 <> "')"
5224−- ajaxc <- ajax $ \(c:u) ->
5225−- case c of
5226−- 'f' -> prependWidget sel (elem $ Just u)
5227−- _ -> do
5228−- r <- liftIO $ autocomplete u
5229−- return $ jaddtoautocomp textx r
5230−-
5231−-
5232−- requires [JScriptFile jqueryScript [events textx ajaxc]
5233−- ,CSSFile jqueryCSS
5234−- ,JScriptFile jqueryUI []]
5235−-
5236−- ws' <- getEdited sel
5237−-
5238−- r<- (ftag "div" mempty `attrs` [("id", id1)]
5239−- ++> allOf (ws' ++ (map (changeMonad . elem . Just) values)))
5240−- <++ ftag "input" mempty
5241−- `attrs` [("type", "text")
5242−- ,("id", textx)
5243−- ,("placeholder", phold)
5244−- ,("oninput", ajaxc $ "'n'+$('#"++textx++"').val()" )
5245−- ,("autocomplete", "off")]
5246−- delEdited sel ws'
5247−- return r
5248−- where
5249−- events textx ajaxc=
5250−- "$(document).ready(function(){ \
5251−- \$('#"++textx++"').keydown(function(){ \
5252−- \if(event.keyCode == 13){ \
5253−- \var v= $('#"++textx++"').val(); \
5254−- \if(event.preventDefault) event.preventDefault();\
5255−- \else if(event.returnValue) event.returnValue = false;" ++
5256−- ajaxc "'f'+v"++";"++
5257−- " $('#"++textx++"').val('');\
5258−- \}\
5259−- \});\
5260−- \});"
5261−-
5262−- jaddtoautocomp textx us= "$('#"<>fromString textx<>"').autocomplete({ source: " <> fromString( show us) <> " });"
5263−+#endif
5264−+ => String -- ^ the initial text of the box
5265−+ -> (String -> IO [String]) -- ^ the autocompletion procedure: receives a prefix, return a list of options.
5266−+ -> (Maybe String -> View v Identity a) -- ^ the widget to add, initialized with the string entered in the box
5267−+ -> [String] -- ^ initial set of values
5268−+ -> View v m [a] -- ^ resulting widget
5269−+wautocompleteEdit phold autocomplete elem values= do
5270−+ id1 <- genNewId
5271−+ let textx= id1++"text"
5272−+ let sel= "$('#" <> fromString id1 <> "')"
5273−+ ajaxc <- ajax $ \(c:u) ->
5274−+ case c of
5275−+ 'f' -> prependWidget sel (elem $ Just u)
5276−+ _ -> do
5277−+ r <- liftIO $ autocomplete u
5278−+ return $ jaddtoautocomp textx r
5279−+
5280−+
5281−+ requires [JScriptFile jqueryScript [events textx ajaxc]
5282−+ ,CSSFile jqueryCSS
5283−+ ,JScriptFile jqueryUI []]
5284−+
5285−+ ws' <- getEdited sel
5286−+
5287−+ r<- (ftag "div" mempty `attrs` [("id", id1)]
5288−+ ++> allOf (ws' ++ (map (changeMonad . elem . Just) values)))
5289−+ <++ ftag "input" mempty
5290−+ `attrs` [("type", "text")
5291−+ ,("id", textx)
5292−+ ,("placeholder", phold)
5293−+ ,("oninput", ajaxc $ "'n'+$('#"++textx++"').val()" )
5294−+ ,("autocomplete", "off")]
5295−+ delEdited sel ws'
5296−+ return r
5297−+ where
5298−+ events textx ajaxc=
5299−+ "$(document).ready(function(){ \
5300−+ \$('#"++textx++"').keydown(function(){ \
5301−+ \if(event.keyCode == 13){ \
5302−+ \var v= $('#"++textx++"').val(); \
5303−+ \if(event.preventDefault) event.preventDefault();\
5304−+ \else if(event.returnValue) event.returnValue = false;" ++
5305−+ ajaxc "'f'+v"++";"++
5306−+ " $('#"++textx++"').val('');\
5307−+ \}\
5308−+ \});\
5309−+ \});"
5310−+
5311−+ jaddtoautocomp textx us= "$('#"<>fromString textx<>"').autocomplete({ source: " <> fromString( show us) <> " });"
5312−
5313−
5314− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
5315− deriving instance Typeable Identity
5316− #endif
5317−-
5318−--- | A specialization of 'wutocompleteEdit' which make appear each chosen option with
5319−--- a checkbox that deletes the element when uncheched. The result, when submitted, is the list of selected elements.
5320−+
5321−+-- | A specialization of 'wutocompleteEdit' which make appear each chosen option with
5322−+-- a checkbox that deletes the element when uncheched. The result, when submitted, is the list of selected elements.
5323− wautocompleteList
5324− #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 707)
5325− :: (Functor m, MonadIO m, Executable m, FormInput v, Typeable m, Typeable Identity) =>
5326−-#else
5327−+#else
5328− :: (Functor m, MonadIO m, Executable m, FormInput v) =>
5329−-#endif
5330−- String -> (String -> IO [String]) -> [String] -> View v m [String]
5331−-wautocompleteList phold serverproc values=
5332−- wautocompleteEdit phold serverproc wrender1 values
5333−- where
5334−- wrender1 x= ftag "div" <<< ftag "input" mempty
5335−- `attrs` [("type","checkbox")
5336−- ,("checked","")
5337−- ,("onclick","this.parentNode.parentNode.removeChild(this.parentNode)")]
5338−- ++> ftag "span" (fromStr $ fromJust x )
5339−- ++> whidden( fromJust x)
5340−-
5341−-------- Templating and localization ---------
5342−-
5343−-data TField = TField {tfieldKey :: Key, tfieldContent :: B.ByteString} deriving (Read, Show,Typeable)
5344−-
5345−-instance Indexable TField where
5346−- key (TField k _)= k
5347−- defPath _= "texts/"
5348−-
5349−-
5350−-instance Serializable TField where
5351−- serialize (TField k content) = content
5352−- deserialKey k content= TField k content -- applyDeserializers [des1,des2] k bs
5353−-
5354−-
5355−- setPersist = \_ -> Just filePersist
5356−-
5357−-
5358−-
5359−-writetField k s= atomically $ writeDBRef (getDBRef k) $ TField k $ toByteString s
5360−-
5361−-
5362−-readtField text k= atomically $ do
5363−- let ref = getDBRef k
5364−- mr <- readDBRef ref
5365−- case mr of
5366−- Just (TField k v) -> if v /= mempty then return $ fromStrNoEncode $ toString v else return text
5367−- Nothing -> return text
5368−-
5369−+#endif
5370−+ String -> (String -> IO [String]) -> [String] -> View v m [String]
5371−+wautocompleteList phold serverproc values=
5372−+ wautocompleteEdit phold serverproc wrender1 values
5373−+ where
5374−+ wrender1 x= ftag "div" <<< ftag "input" mempty
5375−+ `attrs` [("type","checkbox")
5376−+ ,("checked","")
5377−+ ,("onclick","this.parentNode.parentNode.removeChild(this.parentNode)")]
5378−+ ++> ftag "span" (fromStr $ fromJust x )
5379−+ ++> whidden( fromJust x)
5380−+
5381−+------- Templating and localization ---------
5382−+
5383−+data TField = TField {tfieldKey :: Key, tfieldContent :: B.ByteString} deriving (Read, Show,Typeable)
5384−+
5385−+instance Indexable TField where
5386−+ key (TField k _)= k
5387−+ defPath _= "texts/"
5388−+
5389−+
5390−+instance Serializable TField where
5391−+ serialize (TField k content) = content
5392−+ deserialKey k content= TField k content -- applyDeserializers [des1,des2] k bs
5393−+
5394−+
5395−+ setPersist = \_ -> Just filePersist
5396−+
5397−+
5398−+
5399−+writetField k s= atomically $ writeDBRef (getDBRef k) $ TField k $ toByteString s
5400−+
5401−+
5402−+readtField text k= atomically $ do
5403−+ let ref = getDBRef k
5404−+ mr <- readDBRef ref
5405−+ case mr of
5406−+ Just (TField k v) -> if v /= mempty then return $ fromStrNoEncode $ toString v else return text
5407−+ Nothing -> return text
5408−+
5409− -- | Creates a rich text editor aroun a text field or a text area widget.
5410− -- This code:
5411− --
5412−@@ -512,221 +512,224 @@
5413− -- > <** submitButton "enter"
5414− --
5415− -- Creates a rich text area with bold and italic buttons. The buttons are the ones alled
5416−--- in the nicEdit editor.
5417−-htmlEdit :: (Monad m, FormInput v) => [String] -> UserStr -> View v m a -> View v m a
5418−-htmlEdit buttons jsuser w = do
5419−- id <- genNewId
5420−-
5421−- let installHtmlField=
5422−- "\nfunction installHtmlField(muser,cookieuser,name,buttons){\
5423−- \if(muser== '' || document.cookie.search(cookieuser+'='+muser) != -1)\
5424−- \bkLib.onDomLoaded(function() {\
5425−- \var myNicEditor = new nicEditor({buttonList : buttons});\
5426−- \myNicEditor.panelInstance(name);\
5427−- \})};\n"
5428−- install= "installHtmlField('"++jsuser++"','"++cookieuser++"','"++id++"',"++show buttons++");\n"
5429−-
5430−- requires [JScriptFile nicEditUrl [installHtmlField,install]]
5431−- w <! [("id",id)]
5432−-
5433−-
5434−-
5435−-
5436−--- | A widget that display the content of an html, But if the user has edition privileges,
5437−--- it permits to edit it in place. So the editor could see the final appearance
5438−--- of what he writes.
5439−---
5440−--- When the user click the save, the content is saved and
5441−--- identified by the key. Then, from now on, all the users will see the saved
5442−--- content instead of the code content.
5443−---
5444−--- The content is saved in a file by default (/texts/ in this versions), but there is
5445−--- a configurable version (`tFieldGen`). The content of the element and the formatting
5446−--- is cached in memory, so the display is, theoretically, very fast.
5447−---
5448−-
5449−-tFieldEd
5450−- :: (Functor m, MonadIO m, Executable m,
5451−- FormInput v) =>
5452−- UserStr -> Key -> v -> View v m ()
5453−-tFieldEd muser k text= wfreeze k 0 $ do
5454−- content <- liftIO $ readtField text k
5455−- nam <- genNewId
5456−- let ipanel= nam++"panel"
5457−- name= nam++"-"++k
5458−- install= "\ninstallEditField('"++muser++"','"++cookieuser++"','"++name++"','"++ipanel++"');\n"
5459−- getTexts :: (Token -> IO ())
5460−- getTexts token = do
5461−- let (k,s):_ = tenv token
5462−- liftIO $ do
5463−- writetField k $ (fromStrNoEncode s `asTypeOf` text)
5464−- flushCached k
5465−- sendFlush token $ HttpData [] [] ""
5466−- return()
5467−-
5468−- requires [JScriptFile nicEditUrl [install]
5469−- ,JScript ajaxSendText
5470−- ,JScript installEditField
5471−--- ,JScriptFile jqueryScript []
5472−- ,ServerProc ("_texts", transient getTexts)]
5473−+-- in the nicEdit editor.
5474−+htmlEdit :: (Monad m, FormInput v) => [String] -> UserStr -> View v m a -> View v m a
5475−+htmlEdit buttons jsuser w = do
5476−+ id <- genNewId
5477−+
5478−+ let installHtmlField=
5479−+ "\nfunction installHtmlField(muser,cookieuser,name,buttons){\
5480−+ \if(muser== '' || document.cookie.search(cookieuser+'='+muser) != -1)\
5481−+ \bkLib.onDomLoaded(function() {\
5482−+ \var myNicEditor = new nicEditor({buttonList : buttons});\
5483−+ \myNicEditor.panelInstance(name);\
5484−+ \})};\n"
5485−+ install= "installHtmlField('"++jsuser++"','"++cookieuser++"','"++id++"',"++show buttons++");\n"
5486−+
5487−+ requires [JScript installHtmlField ,JScriptFile nicEditUrl [install]]
5488−+ w <! [("id",id)]
5489−+
5490−+
5491−+
5492−+
5493−+-- | A widget that display the content of an html, But if the user has edition privileges,
5494−+-- it permits to edit it in place. So the editor could see the final appearance
5495−+-- of what he writes.
5496−+--
5497−+-- When the user click the save, the content is saved and
5498−+-- identified by the key. Then, from now on, all the users will see the saved
5499−+-- content instead of the code content.
5500−+--
5501−+-- The content is saved in a file by default (/texts/ in this versions), but there is
5502−+-- a configurable version (`tFieldGen`). The content of the element and the formatting
5503−+-- is cached in memory, so the display is, theoretically, very fast.
5504−+--
5505−+
5506−+tFieldEd
5507−+ :: (Functor m, MonadIO m, Executable m,
5508−+ FormInput v) =>
5509−+ UserStr -> Key -> v -> View v m ()
5510−+tFieldEd muser k text= wfreeze k 0 $ do
5511−+ content <- liftIO $ readtField text k
5512−+ nam <- genNewId
5513−+ let ipanel= nam++"panel"
5514−+ name= nam++"-"++k
5515−+ install= "installEditField('"++muser++"','"++cookieuser++"','"++name++"','"++ipanel++"');\n"
5516−+ getTexts :: (Token -> IO ())
5517−+ getTexts token = do
5518−+ let (k,s):_ = tenv token
5519−+ liftIO $ do
5520−+ writetField k $ (fromStrNoEncode s `asTypeOf` text)
5521−+ flushCached k
5522−+ sendFlush token $ HttpData [] [] ""
5523−+ return()
5524−+
5525−+ requires [JScriptFile nicEditUrl [install]
5526−+ ,JScript ajaxSendText
5527−+ ,JScript installEditField
5528−+ ,ServerProc ("_texts", transient getTexts)]
5529−
5530− us <- getCurrentUser
5531− when(us== muser) noCache
5532−-
5533−- (ftag "div" mempty `attrs` [("id",ipanel)]) ++>
5534−- notValid (ftag "span" content `attrs` [("id", name)])
5535−-
5536−-
5537−-
5538−-installEditField=
5539−- "\nfunction installEditField(muser,cookieuser,name,ipanel){\
5540−- \if(muser== '' || document.cookie.search(cookieuser+'='+muser) != -1)\
5541−- \bkLib.onDomLoaded(function() {\
5542−- \var myNicEditor = new nicEditor({fullPanel : true, onSave : function(content, id, instance) {\
5543−- \ajaxSendText(id,content);\
5544−- \myNicEditor.removeInstance(name);\
5545−- \myNicEditor.removePanel(ipanel);\
5546−- \}});\
5547−- \myNicEditor.addInstance(name);\
5548−- \myNicEditor.setPanel(ipanel);\
5549−- \})};\n"
5550−-
5551−-ajaxSendText = "\nfunction ajaxSendText(id,content){\
5552−- \var arr= id.split('-');\
5553−- \var k= arr[1];\
5554−- \$.ajax({\
5555−- \type: 'POST',\
5556−- \url: '/_texts',\
5557−- \data: k + '='+ encodeURIComponent(content),\
5558−- \success: function (resp) {},\
5559−- \error: function (xhr, status, error) {\
5560−- \var msg = $('<div>' + xhr + '</div>');\
5561−- \id1.html(msg);\
5562−- \}\
5563−- \});\
5564−- \return false;\
5565−- \};\n"
5566−-
5567−--- | a text field. Read the cached field value and present it without edition.
5568−-tField :: (MonadIO m,Functor m, Executable m, FormInput v)
5569−- => Key
5570−- -> View v m ()
5571−-tField k = wfreeze k 0 $ do
5572−- content <- liftIO $ readtField (fromStrNoEncode "not found") k
5573−- notValid content
5574−-
5575−--- | A multilanguage version of tFieldEd. For a field with @key@ it add a suffix with the
5576−--- two characters of the language used.
5577−-mFieldEd muser k content= do
5578−- lang <- getLang
5579−- tFieldEd muser (k ++ ('-':lang)) content
5580−-
5581−-
5582−-
5583−--- | A multilanguage version of tField
5584−-mField k= do
5585−- lang <- getLang
5586−- tField $ k ++ ('-':lang)
5587−-
5588−-newtype IteratedId= IteratedId String deriving Typeable
5589−-
5590−--- | Permits to iterate the presentation of data and//or input fields and widgets within
5591−--- a web page that does not change. The placeholders are created with dField. Both are widget
5592−--- modifiers: The latter gets a widget and create a placeholder in the page that is updated
5593−--- via ajax. The content of the update is the rendering of the widget at each iteration.
5594−--- The former gets a wider widget which contains dField elements and permit the iteration.
5595−--- Whenever a link or a form within the witerate widget is activated, the result is the
5596−--- placeholders filled with the new html content. This content can be data, a input field,
5597−--- a link or a widget. No navigation happens.
5598−---
5599−--- This permits even faster updates than autoRefresh. since the latter refresh the whole
5600−--- widget and it does not permits modifications of the layout at runtime.
5601−---
5602−--- When edTemplate or template is used on top of witerate, the result is editable at runtime,
5603−--- and the span placeholders generated, that are updated via ajax can be relocated within
5604−--- the layout of the template.
5605−---
5606−--- Additionally, contrary to some javascript frameworks, the pages generated with this
5607−--- mechanism are searchable by web crawlers.
5608−-
5609−-witerate
5610−- :: (MonadIO m, Functor m, FormInput v) =>
5611−- View v m a -> View v m a
5612−-witerate w= do
5613−- name <- genNewId
5614−- setSessionData $ IteratedId name
5615−- st <- get
5616−- let t= mfkillTime st
5617−- let installAutoEval=
5618−- "$(document).ready(function(){\
5619−- \autoEvalLink('"++name++"',0);\
5620−- \autoEvalForm('"++name++"');\
5621−- \})\n"
5622−+
5623−+ (ftag "div" mempty `attrs` [("id",ipanel)]) ++>
5624−+ notValid (ftag "span" content `attrs` [("id", name)])
5625−+
5626−+
5627−+
5628−+installEditField=
5629−+ "\nfunction installEditField(muser,cookieuser,name,ipanel){\
5630−+ \if(muser== '' || document.cookie.search(cookieuser+'='+muser) != -1){\
5631−+ \var myNicEditor = new nicEditor({fullPanel : true, onSave : function(content, id, instance) {\
5632−+ \ajaxSendText(id,content);\
5633−+ \myNicEditor.removeInstance(name);\
5634−+ \myNicEditor.removePanel(ipanel);\
5635−+ \}});\
5636−+ \myNicEditor.addInstance(name);\
5637−+ \myNicEditor.setPanel(ipanel);\
5638−+ \}};\n"
5639−+
5640−+ajaxSendText = "\nfunction ajaxSendText(id,content){\
5641−+ \var arr= id.split('-');\
5642−+ \var k= arr[1];\
5643−+ \$.ajax({\
5644−+ \type: 'POST',\
5645−+ \url: '/_texts',\
5646−+ \data: k + '='+ encodeURIComponent(content),\
5647−+ \success: function (resp) {},\
5648−+ \error: function (xhr, status, error) {\
5649−+ \var msg = $('<div>' + xhr + '</div>');\
5650−+ \id1.html(msg);\
5651−+ \}\
5652−+ \});\
5653−+ \return false;\
5654−+ \};\n"
5655−+
5656−+-- | a text field. Read the cached field value and present it without edition.
5657−+tField :: (MonadIO m,Functor m, Executable m, FormInput v)
5658−+ => Key
5659−+ -> View v m ()
5660−+tField k = wfreeze k 0 $ do
5661−+ content <- liftIO $ readtField (fromStrNoEncode "not found") k
5662−+ notValid content
5663−+
5664−+-- | A multilanguage version of tFieldEd. For a field with @key@ it add a suffix with the
5665−+-- two characters of the language used.
5666−+mFieldEd muser k content= do
5667−+ lang <- getLang
5668−+ tFieldEd muser (k ++ ('-':lang)) content
5669−+
5670−+
5671−+
5672−+-- | A multilanguage version of tField
5673−+mField k= do
5674−+ lang <- getLang
5675−+ tField $ k ++ ('-':lang)
5676−+
5677−+data IteratedId = IteratedId String String deriving (Typeable, Show)
5678−+
5679−+-- | Permits to iterate the presentation of data and//or input fields and widgets within
5680−+-- a web page that does not change. The placeholders are created with dField. Both are widget
5681−+-- modifiers: The latter gets a widget and create a placeholder in the page that is updated
5682−+-- via ajax. The content of the update is the rendering of the widget at each iteration.
5683−+-- The former gets a wider widget which contains dField elements and permit the iteration.
5684−+-- Whenever a link or a form within the witerate widget is activated, the result is the
5685−+-- placeholders filled with the new html content. This content can be data, a input field,
5686−+-- a link or a widget. No navigation happens.
5687−+--
5688−+-- This permits even faster updates than autoRefresh. since the latter refresh the whole
5689−+-- widget and it does not permits modifications of the layout at runtime.
5690−+--
5691−+-- When edTemplate or template is used on top of witerate, the result is editable at runtime,
5692−+-- and the span placeholders generated, that are updated via ajax can be relocated within
5693−+-- the layout of the template.
5694−+--
5695−+-- Additionally, contrary to some javascript frameworks, the pages generated with this
5696−+-- mechanism are searchable by web crawlers.
5697−+
5698−+witerate
5699−+ :: (MonadIO m, Functor m, FormInput v) =>
5700−+ View v m a -> View v m a
5701−+witerate w= do
5702−+ name <- genNewId
5703−+ setSessionData $ IteratedId name mempty
5704−+ st <- get
5705−+ let t= mfkillTime st
5706−+ let installAutoEval=
5707−+ "$(document).ready(function(){\
5708−+ \autoEvalLink('"++name++"',0);\
5709−+ \autoEvalForm('"++name++"');\
5710−+ \})\n"
5711− let r = lookup ("auto"++name) $ mfEnv st
5712− w'= w `wcallback` (const $ do
5713−+ setSessionData $ IteratedId name mempty
5714− modify $ \s -> s{mfPagePath=mfPagePath st
5715− ,mfSequence= mfSequence st
5716−- ,mfRequirements= if r== Nothing then mfRequirements s else []
5717− ,mfHttpHeaders=[]}
5718−- w)
5719−-
5720−- ret <- case r of
5721−- Nothing -> do
5722−- requires [JScript autoEvalLink
5723−- ,JScript autoEvalForm
5724−- ,JScript $ timeoutscript t
5725−+ w)
5726−+
5727−+ ret <- case r of
5728−+ Nothing -> do
5729−+ requires [JScript autoEvalLink
5730−+ ,JScript autoEvalForm
5731−+ ,JScript $ timeoutscript t
5732− ,JScriptFile jqueryScript [installAutoEval]
5733−- ,JScript setId]
5734−-
5735−- (ftag "div" <<< w') <! [("id",name)]
5736−-
5737−- Just sind -> View $ do
5738−- let t= mfToken st
5739−- modify $ \s -> s{mfRequirements=[],mfHttpHeaders=[]} -- !> "just"
5740−- resetCachePolicy
5741−- FormElm _ mr <- runView w'
5742−- setCachePolicy
5743−- reqs <- return . map ( \(Requirement r) -> unsafeCoerce r) =<< gets mfRequirements
5744−- let js = jsRequirements True reqs
5745−-
5746−- st' <- get
5747−- liftIO . sendFlush t $ HttpData
5748−- (mfHttpHeaders st')
5749−- (mfCookies st') (fromString js)
5750−- put st'{mfAutorefresh=True, inSync=True}
5751−- return $ FormElm mempty Nothing
5752−-
5753−- delSessionData $ IteratedId name
5754−+ ,JScript setId]
5755−+
5756−+ (ftag "div" <<< w') <! [("id",name)]
5757−+
5758−+ Just sind -> refresh $ View $ do
5759−+ FormElm _ mr <- runView w'
5760−+ IteratedId _ render <- getSessionData `onNothing` return (IteratedId name mempty)
5761−+ return $ FormElm (fromStrNoEncode render) mr
5762−+
5763−+-- View $ do
5764−+-- let t= mfToken st
5765−+-- modify $ \s -> s{mfRequirements=[],mfHttpHeaders=[]} -- !> "just"
5766−+-- resetCachePolicy
5767−+-- FormElm _ mr <- runView w'
5768−+-- setCachePolicy
5769−+--
5770−+-- reqs <- installAllRequirements
5771−+--
5772−+-- st' <- get
5773−+-- liftIO . sendFlush t $ HttpData
5774−+-- (mfHttpHeaders st')
5775−+-- (mfCookies st') (toByteString reqs)
5776−+-- put st'{mfAutorefresh=True, inSync=True}
5777−+-- return $ FormElm mempty Nothing
5778−+
5779−+ delSessionData $ IteratedId name mempty
5780− return ret
5781−
5782−
5783−-
5784−-autoEvalLink = "\nfunction autoEvalLink(id,ind){\
5785−- \var id1= $('#'+id);\
5786−+
5787−+autoEvalLink = "\nfunction autoEvalLink(id,ind){\
5788−+ \var id1= $('#'+id);\
5789− \var ida= $('#'+id+' a[class!=\"_noAutoRefresh\"]');\
5790−- \ida.off('click');\
5791−- \ida.click(function () {\
5792−- \if (hadtimeout == true) return true;\
5793−- \var pdata = $(this).attr('data-value');\
5794−- \var actionurl = $(this).attr('href');\
5795−- \var dialogOpts = {\
5796−+ \ida.off('click');\
5797−+ \ida.click(function () {\
5798−+ \if (hadtimeout == true) return true;\
5799−+ \var pdata = $(this).attr('data-value');\
5800−+ \var actionurl = $(this).attr('href');\
5801−+ \var dialogOpts = {\
5802− \type: 'GET',\
5803−- \url: actionurl+'?auto'+id+'='+ind,\
5804−- \data: pdata,\
5805−- \success: function (resp) {\
5806−+ \url: actionurl+'?auto'+id+'='+ind,\
5807−+ \data: pdata,\
5808−+ \success: function (resp) {\
5809− \eval(resp);\
5810− \autoEvalLink(id,ind);\
5811−- \autoEvalForm(id);\
5812−- \},\
5813−- \error: function (xhr, status, error) {\
5814−- \var msg = $('<div>' + xhr + '</div>');\
5815−- \id1.html(msg);\
5816−- \}\
5817−- \};\
5818−- \$.ajax(dialogOpts);\
5819−- \return false;\
5820−- \});\
5821−- \}\n"
5822−+ \autoEvalForm(id);\
5823−+ \},\
5824−+ \error: function (xhr, status, error) {\
5825−+ \var msg = $('<div>' + xhr + '</div>');\
5826−+ \id1.html(msg);\
5827−+ \}\
5828−+ \};\
5829−+ \$.ajax(dialogOpts);\
5830−+ \return false;\
5831−+ \});\
5832−+ \}\n"
5833−
5834− autoEvalForm = "\nfunction autoEvalForm(id) {\
5835− \var buttons= $('#'+id+' input[type=\"submit\"]');\
5836−@@ -736,12 +739,12 @@
5837− \if ($(this).attr('class') != '_noAutoRefresh'){\
5838− \event.preventDefault();\
5839− \if (hadtimeout == true) return true;\
5840−- \var $form = $(this).closest('form');\
5841−+ \var $form = $(this).closest('form');\
5842− \var url = $form.attr('action');\
5843− \pdata = 'auto'+id+'=true&'+this.name+'='+this.value+'&'+$form.serialize();\
5844− \postForm(id,url,pdata);\
5845− \return false;\
5846−- \}else {\
5847−+ \}else {\
5848− \noajax= true;\
5849− \return true;\
5850− \}\
5851−@@ -751,7 +754,7 @@
5852− \idform.submit(function(event) {\
5853− \if(noajax) {noajax=false; return true;}\
5854− \event.preventDefault();\
5855−- \var $form = $(this);\
5856−+ \var $form = $(this);\
5857− \var url = $form.attr('action');\
5858− \var pdata = 'auto'+id+'=true&' + $form.serialize();\
5859− \postForm(id,url,pdata);\
5860−@@ -759,290 +762,291 @@
5861− \}\
5862− \function postForm(id,url,pdata){\
5863− \var id1= $('#'+id);\
5864−- \$.ajax({\
5865−- \type: 'POST',\
5866−- \url: url,\
5867−- \data: 'auto'+id+'=true&'+this.name+'='+this.value+'&'+pdata,\
5868−- \success: function (resp) {\
5869−+ \$.ajax({\
5870−+ \type: 'POST',\
5871−+ \url: url,\
5872−+ \data: 'auto'+id+'=true&'+this.name+'='+this.value+'&'+pdata,\
5873−+ \success: function (resp) {\
5874− \eval(resp);\
5875− \autoEvalLink(id,0);\
5876−- \autoEvalForm(id);\
5877−+ \autoEvalForm(id);\
5878− \},\
5879−- \error: function (xhr, status, error) {\
5880−- \var msg = $('<div>' + xhr + '</div>');\
5881−- \id1.html(msg);\
5882−+ \error: function (xhr, status, error) {\
5883−+ \var msg = $('<div>' + xhr + '</div>');\
5884−+ \id1.html(msg);\
5885− \}\
5886−- \});\
5887−+ \});\
5888− \}"
5889−
5890−-
5891−-
5892−-setId= "function setId(id,v){document.getElementById(id).innerHTML= v;};\n"
5893−-
5894−--- | Present a widget via AJAX if it is within a 'witerate' context. In the first iteration it present the
5895−--- widget surrounded by a placeholder. subsequent iterations will send just the javascript code
5896−--- necessary for the refreshing of the placeholder.
5897−-dField
5898−- :: (Monad m, FormInput view) =>
5899−- View view m b -> View view m b
5900−-dField w= View $ do
5901−- id <- genNewId
5902−- FormElm render mx <- runView w
5903−- st <- get
5904−- let env = mfEnv st
5905−-
5906−- IteratedId name <- getSessionData `onNothing` return (IteratedId noid)
5907−- let r = lookup ("auto"++name) env
5908−+
5909−+
5910−+setId= "function setId(id,v){document.getElementById(id).innerHTML= v;};\n"
5911−+
5912−+-- | Present a widget via AJAX if it is within a 'witerate' context. In the first iteration it present the
5913−+-- widget surrounded by a placeholder. subsequent iterations will send just the javascript code
5914−+-- necessary for the refreshing of the placeholder.
5915−+dField
5916−+ :: (Monad m, FormInput view) =>
5917−+ View view m b -> View view m b
5918−+dField w= View $ do
5919−+ id <- genNewId
5920−+ FormElm render mx <- runView w
5921−+ st <- get
5922−+ let env = mfEnv st
5923−+
5924−+ IteratedId name scripts <- getSessionData `onNothing` return (IteratedId noid mempty)
5925−+ let r = lookup ("auto"++name) env
5926− if r == Nothing || (name == noid && newAsk st== True)
5927−- then do
5928−--- requires [JScriptFile jqueryScript ["$(document).ready(function() {setId('"++id++"','" ++ toString (toByteString render)++"')});\n"]]
5929−- return $ FormElm((ftag "span" render) `attrs` [("id",id)]) mx
5930−- else do
5931−- requires [JScript $ "setId('"++id++"','" ++ toString (toByteString $ render)++"');\n"]
5932−- return $ FormElm mempty mx
5933−-
5934−-noid= "noid"
5935−-
5936−+ then return $ FormElm((ftag "span" render) `attrs` [("id",id)]) mx
5937−+ else do
5938−+ setSessionData $ IteratedId name $ scripts <> "setId('"++id++"','" ++ toString (toByteString $ render)++"');"
5939−+ return $ FormElm mempty mx
5940−+
5941−+noid= "noid"
5942−+
5943−
5944− -- | permits the edition of the rendering of a widget at run time. Once saved, the new rendering
5945− -- becomes the new rendering of the widget for all the users. You must keep the active elements of the
5946− -- template
5947− --
5948− -- the first parameter is the user that has permissions for edition. the second is a key that
5949−--- identifies the template.
5950−-edTemplate
5951−- :: (MonadIO m, FormInput v, Typeable a) =>
5952−- UserStr -> Key -> View v m a -> View v m a
5953−-edTemplate muser k w= View $ do
5954−- nam <- genNewId
5955−-
5956−- let ipanel= nam++"panel"
5957−- name= nam++"-"++k
5958−- install= "installEditField('"++muser++"','"++cookieuser++"','"++name++"','"++ipanel++"');\n"
5959−-
5960−-
5961−- requires [JScriptFile nicEditUrl [install]
5962−- ,JScript ajaxSendText
5963−- ,JScript installEditField
5964−- ,JScriptFile jqueryScript []
5965−- ,ServerProc ("_texts", transient getTexts)]
5966−+-- identifies the template.
5967−+edTemplate
5968−+ :: (MonadIO m, FormInput v, Typeable a) =>
5969−+ UserStr -> Key -> View v m a -> View v m a
5970−+edTemplate muser k w= View $ do
5971−+ nam <- genNewId
5972−+
5973−+ let ipanel= nam++"panel"
5974−+ name= nam++"-"++k
5975−+ install= "installEditField('"++muser++"','"++cookieuser++"','"++name++"','"++ipanel++"');\n"
5976−+
5977−+
5978−+ requires [JScript installEditField
5979−+ ,JScriptFile nicEditUrl [install]
5980−+ ,JScript ajaxSendText
5981−+ ,JScriptFile jqueryScript []
5982−+ ,ServerProc ("_texts", transient getTexts)]
5983− us <- getCurrentUser
5984−- when(us== muser) noCache
5985−- FormElm text mx <- runView w
5986−- content <- liftIO $ readtField text k
5987−-
5988−- return $ FormElm (ftag "div" mempty `attrs` [("id",ipanel)] <>
5989−- ftag "span" content `attrs` [("id", name)])
5990−- mx
5991−- where
5992−- getTexts :: (Token -> IO ())
5993−- getTexts token= do
5994−- let (k,s):_ = tenv token
5995−- liftIO $ do
5996−- writetField k $ (fromStrNoEncode s `asTypeOf` viewFormat w)
5997−- flushCached k
5998−- sendFlush token $ HttpData [] [] ""
5999−- return()
6000−-
6001−- viewFormat :: View v m a -> v
6002−- viewFormat= undefined -- is a type function
6003−-
6004−+ when(us== muser) noCache
6005−+ FormElm text mx <- runView w
6006−+ content <- liftIO $ readtField text k
6007−+
6008−+ return $ FormElm (ftag "div" mempty `attrs` [("id",ipanel)] <>
6009−+ ftag "span" content `attrs` [("id", name)])
6010−+ mx
6011−+ where
6012−+ getTexts :: Token -> IO () -- low level server process
6013−+ getTexts token= do
6014−+ let (k,s):_ = tenv token
6015−+ liftIO $ do
6016−+ writetField k $ (fromStrNoEncode s `asTypeOf` viewFormat w)
6017−+ flushCached k
6018−+ sendFlush token $ HttpData [] [] "" --empty response
6019−+
6020−+ return()
6021−+
6022−+
6023−+ viewFormat :: View v m a -> v
6024−+ viewFormat= undefined -- is a type function
6025−+
6026− -- | Does the same than template but without the edition facility
6027−-template
6028−- :: (MonadIO m, FormInput v, Typeable a) =>
6029−- Key -> View v m a -> View v m a
6030−-template k w= View $ do
6031−- FormElm text mx <- runView w
6032−- let content= unsafePerformIO $ readtField text k
6033−- return $ FormElm content mx
6034−-
6035−-
6036−-
6037−-------------------- JQuery widgets -------------------
6038−--- | present the JQuery datepicker calendar to choose a date.
6039−--- The second parameter is the configuration. Use \"()\" by default.
6040−--- See http://jqueryui.com/datepicker/
6041−-datePicker :: (Monad m, FormInput v) => String -> Maybe String -> View v m (Int,Int,Int)
6042−-datePicker conf jd= do
6043−- id <- genNewId
6044−- let setit= "$(document).ready(function() {\
6045−- \$( '#"++id++"' ).datepicker "++ conf ++";\
6046−- \});"
6047−-
6048−- requires
6049−- [CSSFile jqueryCSS
6050−- ,JScriptFile jqueryScript []
6051−- ,JScriptFile jqueryUI [setit]]
6052−-
6053−- s <- getString jd <! [("id",id)]
6054−- let (month,r) = span (/='/') s
6055−- let (day,r2)= span(/='/') $ tail r
6056−- return (read day,read month, read $ tail r2)
6057−-
6058−--- | present a jQuery dialog with a widget. When a button is pressed it return the result.
6059−--- The first parameter is the configuration. To make it modal, use \"({modal: true})\" see <http://jqueryui.com/dialog/> for
6060−--- the available configurations.
6061−---
6062−--- The enclosed widget will be wrapped within a form tag if the user do not encloses it using wform.f
6063−-wdialog :: (Monad m, FormInput v) => String -> String -> View v m a -> View v m a
6064−-wdialog conf title w= do
6065−- id <- genNewId
6066−- let setit= "$(document).ready(function() {\
6067−- \$('#"++id++"').dialog "++ conf ++";\
6068−- \var idform= $('#"++id++" form');\
6069−- \idform.submit(function(){$(this).dialog(\"close\")})\
6070−- \});"
6071−-
6072−- modify $ \st -> st{needForm= HasForm}
6073−- requires
6074−- [CSSFile jqueryCSS
6075−- ,JScriptFile jqueryScript []
6076−- ,JScriptFile jqueryUI [setit]]
6077−-
6078−- (ftag "div" <<< insertForm w) <! [("id",id),("title", title)]
6079−-
6080−-
6081−-
6082−-
6083−-
6084−--- | Capture the form or link submissions and send them via jQuery AJAX.
6085−--- The response is the new presentation of the widget, that is updated. No new page is generated
6086−--- but the functionality is equivalent. Only the activated widget rendering is updated
6087−--- in the client, so a widget with autoRefresh can be used in heavyweight pages.
6088−--- If AJAX/JavaScript are not available, the widget is refreshed normally, via a new page.
6089−---
6090−--- autoRefresh encloses the widget in a form tag if it includes form elements.
6091−---
6092−--- If there are more than one autoRefresh, they must be enclosed within 'pageFlow' elements
6093−-autoRefresh
6094−- :: (MonadIO m,
6095−- FormInput v)
6096−- => View v m a
6097−- -> View v m a
6098−-autoRefresh = update "html"
6099−-
6100−--- | In some cases, it is neccessary that a link or form inside a 'autoRefresh' or 'update' block
6101−--- should not be autorefreshed, since it produces side effects in the rest of the page that
6102−--- affect to the rendering of the whole. If you like to refresh the whole page, simply add
6103−--- noAutoRefresh attribute to the widget to force the refresh of the whole page when it is activated.
6104−---
6105−--- That behaviour is common at the last sentence of the 'autoRefresh' block.
6106−---
6107−--- This is a cascade menu example.
6108−---
6109−--- > r <- page $ autoRefresh $ ul <<< do
6110−--- > li <<< wlink OptionA << "option A"
6111−--- > ul <<< li <<< (wlink OptionA1 << "Option A1" <! noAutoRefresh)
6112−--- > <|> li <<< (wlink OptionA2 << "Option A2" <! noAutoRefresh)
6113−--- > <|>...
6114−--- > maybe other content
6115−--- >
6116−--- > case r of
6117−--- > OptionA1 -> pageA1
6118−--- > OptionA2 -> pageA2
6119−---
6120−--- when @option A@ is clicked, the two sub-options appear with autorefresh. Only the two
6121−--- lines are returned by the server using AJAX. but when Option A1-2 is pressed we want to
6122−--- present other pages, so we add the noAutorefresh attribute.
6123−---
6124−--- NOTE: the noAutoRefresh attribute should be added to the <a/> or <form/> tags.
6125−-noAutoRefresh= [("class","_noAutoRefresh")]
6126−-
6127−--- | does the same than `autoRefresh` but append the result of each request to the bottom of the widget
6128−---
6129−--- all the comments and remarks of `autoRefresh` apply here
6130−-appendUpdate :: (MonadIO m,
6131−- FormInput v)
6132−- => View v m a
6133−- -> View v m a
6134−-appendUpdate= update "append"
6135−-
6136−--- | does the same than `autoRefresh` but prepend the result of each request before the current widget content
6137−---
6138−--- all the comments and remarks of `autoRefresh` apply here
6139−-prependUpdate :: (MonadIO m,
6140−- FormInput v)
6141−- => View v m a
6142−- -> View v m a
6143−-prependUpdate= update "prepend"
6144−-
6145−-update :: (MonadIO m, FormInput v)
6146−- => B.ByteString
6147−- -> View v m a
6148−- -> View v m a
6149−-update method w= do
6150−- id <- genNewId
6151−+template
6152−+ :: (MonadIO m, FormInput v, Typeable a) =>
6153−+ Key -> View v m a -> View v m a
6154−+template k w= View $ do
6155−+ FormElm text mx <- runView w
6156−+ let content= unsafePerformIO $ readtField text k
6157−+ return $ FormElm content mx
6158−+
6159−+
6160−+
6161−+------------------- JQuery widgets -------------------
6162−+-- | present the JQuery datepicker calendar to choose a date.
6163−+-- The second parameter is the configuration. Use \"()\" by default.
6164−+-- See http://jqueryui.com/datepicker/
6165−+datePicker :: (Monad m, FormInput v) => String -> Maybe String -> View v m (Int,Int,Int)
6166−+datePicker conf jd= do
6167−+ id <- genNewId
6168−+ let setit= "$(document).ready(function() {\
6169−+ \$( '#"++id++"' ).datepicker "++ conf ++";\
6170−+ \});"
6171−+
6172−+ requires
6173−+ [CSSFile jqueryCSS
6174−+ ,JScriptFile jqueryScript []
6175−+ ,JScriptFile jqueryUI [setit]]
6176−+
6177−+ s <- getString jd <! [("id",id)]
6178−+ let (month,r) = span (/='/') s
6179−+ let (day,r2)= span(/='/') $ tail r
6180−+ return (read day,read month, read $ tail r2)
6181−+
6182−+-- | present a jQuery dialog with a widget. When a button is pressed it return the result.
6183−+-- The first parameter is the configuration. To make it modal, use \"({modal: true})\" see <http://jqueryui.com/dialog/> for
6184−+-- the available configurations.
6185−+--
6186−+-- The enclosed widget will be wrapped within a form tag if the user do not encloses it using wform.f
6187−+wdialog :: (Monad m, FormInput v) => String -> String -> View v m a -> View v m a
6188−+wdialog conf title w= do
6189−+ id <- genNewId
6190−+ let setit= "$(document).ready(function() {\
6191−+ \$('#"++id++"').dialog "++ conf ++";\
6192−+ \var idform= $('#"++id++" form');\
6193−+ \idform.submit(function(){$(this).dialog(\"close\")})\
6194−+ \});"
6195−+
6196−+ modify $ \st -> st{needForm= HasForm}
6197−+ requires
6198−+ [CSSFile jqueryCSS
6199−+ ,JScriptFile jqueryScript []
6200−+ ,JScriptFile jqueryUI [setit]]
6201−+
6202−+ (ftag "div" <<< insertForm w) <! [("id",id),("title", title)]
6203−+
6204−+
6205−+
6206−+
6207−+
6208−+-- | Capture the form or link submissions and send them via jQuery AJAX.
6209−+-- The response is the new presentation of the widget, that is updated. No new page is generated
6210−+-- but the functionality is equivalent. Only the activated widget rendering is updated
6211−+-- in the client, so a widget with autoRefresh can be used in heavyweight pages.
6212−+-- If AJAX/JavaScript are not available, the widget is refreshed normally, via a new page.
6213−+--
6214−+-- autoRefresh encloses the widget in a form tag if it includes form elements.
6215−+--
6216−+-- If there are more than one autoRefresh, they must be enclosed within 'pageFlow' elements
6217−+autoRefresh
6218−+ :: (MonadIO m,
6219−+ FormInput v)
6220−+ => View v m a
6221−+ -> View v m a
6222−+autoRefresh = update "html"
6223−+
6224−+-- | In some cases, it is neccessary that a link or form inside a 'autoRefresh' or 'update' block
6225−+-- should not be autorefreshed, since it produces side effects in the rest of the page that
6226−+-- affect to the rendering of the whole. If you like to refresh the whole page, simply add
6227−+-- noAutoRefresh attribute to the widget to force the refresh of the whole page when it is activated.
6228−+--
6229−+-- That behaviour is common at the last sentence of the 'autoRefresh' block.
6230−+--
6231−+-- This is a cascade menu example.
6232−+--
6233−+-- > r <- page $ autoRefresh $ ul <<< do
6234−+-- > li <<< wlink OptionA << "option A"
6235−+-- > ul <<< li <<< (wlink OptionA1 << "Option A1" <! noAutoRefresh)
6236−+-- > <|> li <<< (wlink OptionA2 << "Option A2" <! noAutoRefresh)
6237−+-- > <|>...
6238−+-- > maybe other content
6239−+-- >
6240−+-- > case r of
6241−+-- > OptionA1 -> pageA1
6242−+-- > OptionA2 -> pageA2
6243−+--
6244−+-- when @option A@ is clicked, the two sub-options appear with autorefresh. Only the two
6245−+-- lines are returned by the server using AJAX. but when Option A1-2 is pressed we want to
6246−+-- present other pages, so we add the noAutorefresh attribute.
6247−+--
6248−+-- NOTE: the noAutoRefresh attribute should be added to the <a/> or <form/> tags.
6249−+noAutoRefresh= [("class","_noAutoRefresh")]
6250−+
6251−+-- | does the same than `autoRefresh` but append the result of each request to the bottom of the widget
6252−+--
6253−+-- all the comments and remarks of `autoRefresh` apply here
6254−+appendUpdate :: (MonadIO m,
6255−+ FormInput v)
6256−+ => View v m a
6257−+ -> View v m a
6258−+appendUpdate= update "append"
6259−+
6260−+-- | does the same than `autoRefresh` but prepend the result of each request before the current widget content
6261−+--
6262−+-- all the comments and remarks of `autoRefresh` apply here
6263−+prependUpdate :: (MonadIO m,
6264−+ FormInput v)
6265−+ => View v m a
6266−+ -> View v m a
6267−+prependUpdate= update "prepend"
6268−+
6269−+update :: (MonadIO m, FormInput v)
6270−+ => String
6271−+ -> View v m a
6272−+ -> View v m a
6273−+update method w= do
6274−+ id <- genNewId
6275− st <- get
6276−-
6277−- let t = mfkillTime st -1
6278−-
6279−- installscript=
6280−- "$(document).ready(function(){\
6281−- \ajaxGetLink('"++id++"');\
6282−- \ajaxPostForm('"++id++"');\
6283−+
6284−+ let t = mfkillTime st -1
6285−+
6286−+ installscript=
6287−+ "$(document).ready(function(){\
6288−+ \ajaxGetLink('"++id++"');\
6289−+ \ajaxPostForm('"++id++"');\
6290− \});"
6291− st <- get
6292− let insync = inSync st
6293−- let env= mfEnv st
6294−- let r= lookup ("auto"++id) env
6295−+ let env= mfEnv st
6296−+ let r= lookup ("auto"++id) env
6297− if r == Nothing
6298−- then do
6299−- requires [JScript $ timeoutscript t
6300−- ,JScript ajaxGetLink
6301−- ,JScript ajaxPostForm
6302−- ,JScriptFile jqueryScript [installscript]]
6303−- (ftag "div" <<< insertForm w) <! [("id",id)]
6304−-
6305−- else View $ do
6306−- let t= mfToken st -- !> "JUST"
6307−- modify $ \s -> s{mfHttpHeaders=[]} -- !> "just"
6308−- resetCachePolicy
6309−- FormElm form mr <- runView $ insertForm w
6310−- setCachePolicy
6311−- st' <- get
6312−- let HttpData ctype c s= toHttpData $ method <> " " <> toByteString form
6313−-
6314−- (liftIO . sendFlush t $ HttpData (ctype ++
6315−- mfHttpHeaders st') (mfCookies st' ++ c) s)
6316−- put st'{mfAutorefresh=True,newAsk=True}
6317−-
6318−- return $ FormElm mempty Nothing
6319−-
6320−- where
6321−- -- | adapted from http://www.codeproject.com/Articles/341151/Simple-AJAX-POST-Form-and-AJAX-Fetch-Link-to-Modal
6322−+ then do
6323−+ requires [JScript $ timeoutscript t
6324−+ ,JScript ajaxGetLink
6325−+ ,JScript ajaxPostForm
6326−+ ,JScriptFile jqueryScript [installscript]]
6327−+ (ftag "div" <<< insertForm w) <! [("id",id)]
6328−+
6329−+ else refresh $ fromStr (method <> " ") ++> insertForm w
6330−+-- View $ do
6331−+-- let t= mfToken st -- !> "JUST"
6332−+-- modify $ \s -> s{mfHttpHeaders=[]} -- !> "just"
6333−+-- resetCachePolicy
6334−+-- FormElm form mr <- runView $ insertForm w
6335−+-- setCachePolicy
6336−+-- st' <- get
6337−+-- let HttpData ctype c s= toHttpData $ method <> " " <> toByteString form
6338−+--
6339−+-- (liftIO . sendFlush t $ HttpData (ctype ++
6340−+-- mfHttpHeaders st') (mfCookies st' ++ c) s)
6341−+-- put st'{mfAutorefresh=True,newAsk=True}
6342−+--
6343−+-- return $ FormElm mempty Nothing
6344−+
6345−+ where
6346−+ -- | adapted from http://www.codeproject.com/Articles/341151/Simple-AJAX-POST-Form-and-AJAX-Fetch-Link-to-Modal
6347− -- \url: actionurl+'?bustcache='+ new Date().getTime()+'&auto'+id+'=true',\n\
6348− ajaxGetLink = "\nfunction ajaxGetLink(id){\
6349−- \var id1= $('#'+id);\
6350−+ \var id1= $('#'+id);\
6351− \var ida= $('#'+id+' a[class!=\"_noAutoRefresh\"]');\
6352−- \ida.off('click');\
6353−- \ida.click(function () {\
6354−- \if (hadtimeout == true) return true;\
6355−- \var pdata = $(this).attr('data-value');\
6356−- \var actionurl = $(this).attr('href');\
6357−- \var dialogOpts = {\
6358−+ \ida.off('click');\
6359−+ \ida.click(function () {\
6360−+ \if (hadtimeout == true) return true;\
6361−+ \var pdata = $(this).attr('data-value');\
6362−+ \var actionurl = $(this).attr('href');\
6363−+ \var dialogOpts = {\
6364− \type: 'GET',\
6365−- \url: actionurl+'?auto'+id+'=true',\
6366−- \data: pdata,\
6367−- \success: function (resp) {\
6368−- \var ind= resp.indexOf(' ');\
6369−- \var dat= resp.substr(ind);\
6370−- \var method= resp.substr(0,ind);\
6371−- \if(method== 'html')id1.html(dat);\
6372−- \else if (method == 'append') id1.append(dat);\
6373−+ \url: actionurl+'?auto'+id+'=true',\
6374−+ \data: pdata,\
6375−+ \success: function (resp) {\
6376−+ \var ind= resp.indexOf(' ');\
6377−+ \var dat= resp.substr(ind);\
6378−+ \var method= resp.substr(0,ind);\
6379−+ \if(method== 'html')id1.html(dat);\
6380−+ \else if (method == 'append') id1.append(dat);\
6381− \else if (method == 'prepend') id1.prepend(dat);\
6382−- \else $(':root').html(resp);\
6383−+ \else $(':root').html(resp);\
6384− \ajaxGetLink(id);\
6385−- \ajaxPostForm(id);\
6386−- \},\
6387−- \error: function (xhr, status, error) {\
6388−- \var msg = $('<div>' + xhr + '</div>');\
6389−- \id1.html(msg);\
6390−- \}\
6391−- \};\
6392−- \$.ajax(dialogOpts);\
6393−- \return false;\
6394−- \});\
6395−- \}\n"
6396−+ \ajaxPostForm(id);\
6397−+ \},\
6398−+ \error: function (xhr, status, error) {\
6399−+ \var msg = $('<div>' + xhr + '</div>');\
6400−+ \id1.html(msg);\
6401−+ \}\
6402−+ \};\
6403−+ \$.ajax(dialogOpts);\
6404−+ \return false;\
6405−+ \});\
6406−+ \}\n"
6407−
6408− ajaxPostForm = "\nfunction ajaxPostForm(id) {\
6409− \var buttons= $('#'+id+' input[type=\"submit\"]');\
6410−@@ -1051,13 +1055,13 @@
6411− \buttons.click(function(event) {\
6412− \if ($(this).attr('class') != '_noAutoRefresh'){\
6413− \event.preventDefault();\
6414−- \if (hadtimeout == true) return true;\
6415−- \var $form = $(this).closest('form');\
6416−+ \if (hadtimeout == true) return true;\
6417−+ \var $form = $(this).closest('form');\
6418− \var url = $form.attr('action');\
6419− \pdata = 'auto'+id+'=true&'+this.name+'='+this.value+'&'+$form.serialize();\
6420− \postForm(id,url,pdata);\
6421− \return false;\
6422−- \}else {\
6423−+ \}else {\
6424− \noajax= true;\
6425− \return true;\
6426− \}\
6427−@@ -1067,197 +1071,197 @@
6428− \idform.submit(function(event) {\
6429− \if(noajax) {noajax=false; return true;}\
6430− \event.preventDefault();\
6431−- \var $form = $(this);\
6432−+ \var $form = $(this);\
6433− \var url = $form.attr('action');\
6434− \var pdata = 'auto'+id+'=true&' + $form.serialize();\
6435− \postForm(id,url,pdata);\
6436− \return false;})\
6437− \}\
6438− \function postForm(id,url,pdata){\
6439−- \var id1= $('#'+id);\
6440−- \$.ajax({\
6441−- \type: 'POST',\
6442−- \url: url,\
6443−- \data: pdata,\
6444−- \success: function (resp) {\
6445−- \var ind= resp.indexOf(' ');\
6446−- \var dat = resp.substr(ind);\
6447−- \var method= resp.substr(0,ind);\
6448−- \if(method== 'html')id1.html(dat);\
6449−- \else if (method == 'append') id1.append(dat);\
6450−+ \var id1= $('#'+id);\
6451−+ \$.ajax({\
6452−+ \type: 'POST',\
6453−+ \url: url,\
6454−+ \data: pdata,\
6455−+ \success: function (resp) {\
6456−+ \var ind= resp.indexOf(' ');\
6457−+ \var dat = resp.substr(ind);\
6458−+ \var method= resp.substr(0,ind);\
6459−+ \if(method== 'html')id1.html(dat);\
6460−+ \else if (method == 'append') id1.append(dat);\
6461− \else if (method == 'prepend') id1.prepend(dat);\
6462− \else $(':root').html(resp);\
6463−- \ajaxGetLink(id);\
6464−- \ajaxPostForm(id);\
6465−- \},\
6466−- \error: function (xhr, status, error) {\
6467−- \var msg = $('<div>' + xhr + '</div>');\
6468−- \id1.html(msg);\
6469−- \}\
6470−- \});\
6471−- \};"
6472−-
6473−-
6474−-
6475−-
6476−-timeoutscript t=
6477−- "\nvar hadtimeout=false;\
6478−- \if("++show t++" > 0)setTimeout(function() {hadtimeout=true; }, "++show (t*1000)++");\n"
6479−-
6480−-
6481−-data UpdateMethod= Append | Prepend | Html deriving Show
6482−-
6483−--- | continously execute a widget and update the content.
6484−--- The update method specify how the update is done. 'Html' means a substitution of content.
6485−--- The second parameter is the delay for the next retry in case of disconnection, in milliseconds.
6486−---
6487−--- It can be used to show data updates in the server. The widget is executed in a different process than
6488−--- the one of the rest of the page.
6489−--- Updates in the session context are not seen by the push widget. It has his own context.
6490−--- To communicate with te widget, use DBRef's or TVar and the
6491−--- STM semantics for waiting updates using 'retry'.
6492−---
6493−--- Widgets in a push can have links and forms, but since they are asunchonous, they can not
6494−--- return inputs. but they can modify the server state.
6495−--- push ever return an invalid response to the calling widget, so it never
6496−--- triggers the advance of the navigation.
6497−---
6498−---
6499−--- This example is a counter increased each second:
6500−---
6501−--- > pushIncrease= do
6502−--- > tv <- liftIO $ newTVarIO 0
6503−--- > page $ push 0 Html $ do
6504−--- > n <- atomic $ readTVar tv
6505−--- > atomic $ writeTVar tv $ n + 1
6506−--- > liftIO $ threadDelay 1000000
6507−--- > b << (show n) ++> noWidget
6508−---
6509−---
6510−--- This other simulates a console output that echoes what is entered in a text box
6511−--- below. It has two widgets: a push output in append mode and a text box input.
6512−--- The communication uses a TVar. The push widget wait for updates in the TVar.
6513−--- because the second widget uses autoRefresh, all happens in the same page.
6514−---
6515−--- It is recommended to add a timeout to the push widget, like in the example:
6516−---
6517−--- > pushSample= do
6518−--- > tv <- liftIO $ newTVarIO $ Just "init"
6519−--- > page $ push Append 1000 (disp tv) <** input tv
6520−--- >
6521−--- > where
6522−--- > disp tv= do
6523−--- > setTimeouts 100 0
6524−--- > line <- tget tv
6525−--- > p << line ++> noWidget
6526−--- >
6527−--- > input tv= autoRefresh $ do
6528−--- > line <- getString Nothing <** submitButton "Enter"
6529−--- > tput tv line
6530−--- >
6531−--- > tput tv x = atomic $ writeTVar tv ( Just x) !> "WRITE"
6532−--- >
6533−--- > tget tv= atomic $ do
6534−--- > mr <- readTVar tv
6535−--- > case mr of
6536−--- > Nothing -> retry
6537−--- > Just r -> do
6538−--- > writeTVar tv Nothing
6539−--- > return r
6540−-
6541−-push :: FormInput v
6542−- => UpdateMethod
6543−- -> Int
6544−- -> View v IO ()
6545−- -> View v IO ()
6546−-push method' wait w= push' . map toLower $ show method'
6547−- where
6548−- push' method= do
6549−- id <- genNewId
6550−- st <- get
6551−- let token= mfToken st
6552−-
6553−- procname= "_push" ++ tind token ++ id
6554−- installscript=
6555−- "$(document).ready(function(){\n"
6556−- ++ "ajaxPush('"++id++"',"++show wait++");"
6557−- ++ "})\n"
6558−-
6559−- new <- gets newAsk
6560−-
6561−- when new $ do
6562−- killWF procname token{twfname= procname}
6563−- let proc=runFlow . transientNav . ask $ w'
6564−- requires [ServerProc (procname, proc),
6565−- JScript $ ajaxPush procname,
6566−- JScriptFile jqueryScript [installscript]]
6567−-
6568−- (ftag "div" <<< noWidget) <! [("id",id)]
6569−- <++ ftag "div" mempty `attrs` [("id",id++"status")]
6570−-
6571−- where
6572−- w' = do
6573−- modify $ \s -> s{inSync= True,newAsk=True}
6574−- w
6575−-
6576−-
6577−-
6578−- ajaxPush procname=" function ajaxPush(id,waititime){\
6579−- \var cnt=0; \
6580−- \var id1= $('#'+id);\
6581−- \var idstatus= $('#'+id+'status');\
6582−- \var ida= $('#'+id+' a');\
6583−- \var actionurl='/"++procname++"';\
6584−- \var dialogOpts = {\
6585−- \cache: false,\
6586−- \type: 'GET',\
6587−- \url: actionurl,\
6588−- \data: '',\
6589−- \success: function (resp) {\
6590−- \idstatus.html('')\
6591−- \cnt=0;\
6592−- \id1."++method++"(resp);\
6593−- \ajaxPush1();\
6594−- \},\
6595−- \error: function (xhr, status, error) {\
6596−- \cnt= cnt + 1;\
6597−- \if (false) \
6598−- \idstatus.html('no more retries');\
6599−- \else {\
6600−- \idstatus.html('waiting');\
6601−- \setTimeout(function() { idstatus.html('retrying');ajaxPush1(); }, waititime);\
6602−- \}\
6603−- \}\
6604−- \};\
6605−- \function ajaxPush1(){\
6606−- \$.ajax(dialogOpts);\
6607−- \return false;\
6608−- \}\
6609−- \ajaxPush1();\
6610−- \}"
6611−-
6612−-
6613−-
6614−-
6615−--- | show the jQuery spinner widget. the first parameter is the configuration . Use \"()\" by default.
6616−--- See http://jqueryui.com/spinner
6617−-getSpinner
6618−- :: (MonadIO m, Read a,Show a, Typeable a, FormInput view) =>
6619−- String -> Maybe a -> View view m a
6620−-getSpinner conf mv= do
6621−- id <- genNewId
6622−- let setit= "$(document).ready(function() {\
6623−- \var spinner = $( '#"++id++"' ).spinner "++conf++";\
6624−- \spinner.spinner( \"enable\" );\
6625−- \});"
6626−- requires
6627−- [CSSFile jqueryCSS
6628−- ,JScriptFile jqueryScript []
6629−- ,JScriptFile jqueryUI [setit]]
6630−-
6631−- getTextBox mv <! [("id",id)]
6632−+ \ajaxGetLink(id);\
6633−+ \ajaxPostForm(id);\
6634−+ \},\
6635−+ \error: function (xhr, status, error) {\
6636−+ \var msg = $('<div>' + xhr + '</div>');\
6637−+ \id1.html(msg);\
6638−+ \}\
6639−+ \});\
6640−+ \};"
6641−+
6642−+
6643−+
6644−+
6645−+timeoutscript t=
6646−+ "\nvar hadtimeout=false;\
6647−+ \if("++show t++" > 0)setTimeout(function() {hadtimeout=true; }, "++show (t*1000)++");\n"
6648−+
6649−+
6650−+data UpdateMethod= Append | Prepend | Html deriving Show
6651−+
6652−+-- | continously execute a widget and update the content.
6653−+-- The update method specify how the update is done. 'Html' means a substitution of content.
6654−+-- The second parameter is the delay for the next retry in case of disconnection, in milliseconds.
6655−+--
6656−+-- It can be used to show data updates in the server. The widget is executed in a different process than
6657−+-- the one of the rest of the page.
6658−+-- Updates in the session context are not seen by the push widget. It has his own context.
6659−+-- To communicate with te widget, use DBRef's or TVar and the
6660−+-- STM semantics for waiting updates using 'retry'.
6661−+--
6662−+-- Widgets in a push can have links and forms, but since they are asunchonous, they can not
6663−+-- return inputs. but they can modify the server state.
6664−+-- push ever return an invalid response to the calling widget, so it never
6665−+-- triggers the advance of the navigation.
6666−+--
6667−+--
6668−+-- This example is a counter increased each second:
6669−+--
6670−+-- > pushIncrease= do
6671−+-- > tv <- liftIO $ newTVarIO 0
6672−+-- > page $ push 0 Html $ do
6673−+-- > n <- atomic $ readTVar tv
6674−+-- > atomic $ writeTVar tv $ n + 1
6675−+-- > liftIO $ threadDelay 1000000
6676−+-- > b << (show n) ++> noWidget
6677−+--
6678−+--
6679−+-- This other simulates a console output that echoes what is entered in a text box
6680−+-- below. It has two widgets: a push output in append mode and a text box input.
6681−+-- The communication uses a TVar. The push widget wait for updates in the TVar.
6682−+-- because the second widget uses autoRefresh, all happens in the same page.
6683−+--
6684−+-- It is recommended to add a timeout to the push widget, like in the example:
6685−+--
6686−+-- > pushSample= do
6687−+-- > tv <- liftIO $ newTVarIO $ Just "init"
6688−+-- > page $ push Append 1000 (disp tv) <** input tv
6689−+-- >
6690−+-- > where
6691−+-- > disp tv= do
6692−+-- > setTimeouts 100 0
6693−+-- > line <- tget tv
6694−+-- > p << line ++> noWidget
6695−+-- >
6696−+-- > input tv= autoRefresh $ do
6697−+-- > line <- getString Nothing <** submitButton "Enter"
6698−+-- > tput tv line
6699−+-- >
6700−+-- > tput tv x = atomic $ writeTVar tv ( Just x) !> "WRITE"
6701−+-- >
6702−+-- > tget tv= atomic $ do
6703−+-- > mr <- readTVar tv
6704−+-- > case mr of
6705−+-- > Nothing -> retry
6706−+-- > Just r -> do
6707−+-- > writeTVar tv Nothing
6708−+-- > return r
6709−+
6710−+push :: FormInput v
6711−+ => UpdateMethod
6712−+ -> Int
6713−+ -> View v IO ()
6714−+ -> View v IO ()
6715−+push method' wait w= push' . map toLower $ show method'
6716−+ where
6717−+ push' method= do
6718−+ id <- genNewId
6719−+ st <- get
6720−+ let token= mfToken st
6721−+
6722−+ procname= "_push" ++ tind token ++ id
6723−+ installscript=
6724−+ "$(document).ready(function(){\n"
6725−+ ++ "ajaxPush('"++id++"',"++show wait++");"
6726−+ ++ "})\n"
6727−+
6728−+ new <- gets newAsk
6729−+
6730−+ when new $ do
6731−+ killWF procname token{twfname= procname}
6732−+ let proc=runFlow . transientNav . ask $ w'
6733−+ requires [ServerProc (procname, proc),
6734−+ JScript $ ajaxPush procname,
6735−+ JScriptFile jqueryScript [installscript]]
6736−+
6737−+ (ftag "div" <<< noWidget) <! [("id",id)]
6738−+ <++ ftag "div" mempty `attrs` [("id",id++"status")]
6739−+
6740−+ where
6741−+ w' = do
6742−+ modify $ \s -> s{inSync= True,newAsk=True}
6743−+ w
6744−+
6745−+
6746−+
6747−+ ajaxPush procname=" function ajaxPush(id,waititime){\
6748−+ \var cnt=0; \
6749−+ \var id1= $('#'+id);\
6750−+ \var idstatus= $('#'+id+'status');\
6751−+ \var ida= $('#'+id+' a');\
6752−+ \var actionurl='/"++procname++"';\
6753−+ \var dialogOpts = {\
6754−+ \cache: false,\
6755−+ \type: 'GET',\
6756−+ \url: actionurl,\
6757−+ \data: '',\
6758−+ \success: function (resp) {\
6759−+ \idstatus.html('');\
6760−+ \cnt=0;\
6761−+ \id1."++method++"(resp);\
6762−+ \ajaxPush1();\
6763−+ \},\
6764−+ \error: function (xhr, status, error) {\
6765−+ \cnt= cnt + 1;\
6766−+ \if (false) \
6767−+ \idstatus.html('no more retries');\
6768−+ \else {\
6769−+ \idstatus.html('waiting');\
6770−+ \setTimeout(function() { idstatus.html('retrying');ajaxPush1(); }, waititime);\
6771−+ \}\
6772−+ \}\
6773−+ \};\
6774−+ \function ajaxPush1(){\
6775−+ \$.ajax(dialogOpts);\
6776−+ \return false;\
6777−+ \}\
6778−+ \ajaxPush1();\
6779−+ \}"
6780−+
6781−+
6782−+
6783−+
6784−+-- | show the jQuery spinner widget. the first parameter is the configuration . Use \"()\" by default.
6785−+-- See http://jqueryui.com/spinner
6786−+getSpinner
6787−+ :: (MonadIO m, Read a,Show a, Typeable a, FormInput view) =>
6788−+ String -> Maybe a -> View view m a
6789−+getSpinner conf mv= do
6790−+ id <- genNewId
6791−+ let setit= "$(document).ready(function() {\
6792−+ \var spinner = $( '#"++id++"' ).spinner "++conf++";\
6793−+ \spinner.spinner( \"enable\" );\
6794−+ \});"
6795−+ requires
6796−+ [CSSFile jqueryCSS
6797−+ ,JScriptFile jqueryScript []
6798−+ ,JScriptFile jqueryUI [setit]]
6799−+
6800−+ getTextBox mv <! [("id",id)]
6801−+
6802−
6803−-
6804−
6805− -- | takes as argument a widget and delay the load until it is visible. The renderring to
6806− -- be shown during the load is the specified in the first parameter. The resulting lazy
6807−@@ -1277,50 +1281,31 @@
6808− --
6809− -- lazy temprendering $ img ! href imageurl ++> noWidget
6810− lazy :: (FormInput v,Functor m,MonadIO m) => v -> View v m a -> View v m a
6811−-lazy v w= do
6812−- id <- genNewId
6813−+lazy v w= do
6814−+ id <- genNewId
6815− st <- get
6816− let path = currentPath st
6817−- env = mfEnv st
6818−- r= lookup ("auto"++id) env
6819−- t = mfkillTime st -1
6820−+ env = mfEnv st
6821−+ r= lookup ("auto"++id) env
6822−+ t = mfkillTime st -1
6823− installscript = "$(document).ready(function(){\
6824− \function lazyexec(){lazy('"++id++"','"++ path ++"',lazyexec)};\
6825− \$(window).one('scroll',lazyexec);\
6826− \$(window).trigger('scroll');\
6827− \});"
6828−
6829−--- installscript2= "$(window).one('scroll',function(){\
6830−--- \function lazyexec(){lazy('"++id++"','"++ path ++"',lazyexec)};\
6831−--- \lazyexec()});"
6832−-
6833−-
6834−- if r == Nothing then View $ do
6835−- requires [JScript lazyScript
6836−+ if r == Nothing then View $ do
6837−+ requires [JScript lazyScript
6838− ,JScriptFile jqueryScript [installscript,scrollposition]]
6839−- FormElm rendering mx <- runView w
6840−+ reqs <- gets mfRequirements
6841−+ FormElm _ mx <- runView w
6842−+ modify $ \st-> st{mfRequirements= reqs} --ignore requirements
6843− return $ FormElm (ftag "div" v `attrs` [("id",id)]) mx
6844−-
6845−- else View $ do
6846−- resetCachePolicy
6847−- st' <- get
6848−- FormElm form mx <- runView w
6849−- setCachePolicy
6850−- let t= mfToken st'
6851−- reqs <- installAllRequirements
6852−- let HttpData ctype c s= toHttpData $ toByteString form
6853−- liftIO . sendFlush t $ HttpData (ctype ++
6854−- mfHttpHeaders st') (mfCookies st' ++ c)
6855−- $ toByteString reqs <> s -- !> (unpack $ toByteString reqs)
6856−- put st'{mfAutorefresh=True,inSync= True}
6857−-
6858−- return $ FormElm mempty mx
6859−-
6860−+
6861−+ else refresh w
6862−
6863− where
6864−
6865−-
6866−-
6867− scrollposition= "$.fn.scrollposition= function(){\
6868− \var pos= $(this).position();\
6869− \if (typeof(pos)==='undefined') {return 1;}\
6870−@@ -1339,24 +1324,37 @@
6871− \lastCall = now;\
6872− \if(id1.scrollposition() > 0){\
6873− \$(window).one('scroll',f);}\
6874−- \else{\
6875−- \var dialogOpts = {\
6876−+ \else{\
6877−+ \var dialogOpts = {\
6878− \type: 'GET',\
6879−- \url: actionurl+'?auto'+id+'=true',\
6880−- \success: function (resp) {\
6881−+ \url: actionurl+'?auto'+id+'=true',\
6882−+ \success: function (resp) {\
6883− \id1.html(resp);\
6884−- \$(window).trigger('scroll');\
6885−+ \$(window).trigger('scroll');\
6886− \},\
6887−- \error: function (xhr, status, error) {\
6888−- \var msg = $('<div>' + xhr + '</div>');\
6889−+ \error: function (xhr, status, error) {\
6890−+ \var msg = $('<div>' + xhr + '</div>');\
6891− \id1.html(msg);\
6892−- \}\
6893−- \};\
6894−- \$.ajax(dialogOpts);\
6895−+ \}\
6896−+ \};\
6897−+ \$.ajax(dialogOpts);\
6898− \}}};"
6899−
6900−+refresh w= View $ do
6901−+ resetCachePolicy
6902−+ modify $ \st -> st{mfAutorefresh=True,inSync= True}
6903−+ FormElm form mx <- runView w -- !> show (mfInstalledScripts st')
6904−+ setCachePolicy
6905−+ st' <- get
6906−+ let t= mfToken st'
6907−+ reqs <- installAllRequirements
6908−+ let HttpData ctype c s= toHttpData $ toByteString form
6909−+ liftIO . sendFlush t $ HttpData (ctype ++
6910−+ mfHttpHeaders st') (mfCookies st' ++ c)
6911−+ $ s <> toByteString reqs
6912−+ return $ FormElm mempty mx
6913−
6914−-waitAndExecute= "function waitAndExecute(sym,f) {\
6915−- \if (eval(sym)) {f();}\
6916−- \else {setTimeout(function() {waitAndExecute(sym,f)}, 50);}\
6917−- \}\n"
6918−+--waitAndExecute= "function waitAndExecute(sym,f) {\
6919−+-- \if (eval(sym)) {f();}\
6920−+-- \else {setTimeout(function() {waitAndExecute(sym,f)}, 50);}\
6921−+-- \}\n"
6922−diff -ru orig/src/MFlow/Forms/XHtml.hs new/src/MFlow/Forms/XHtml.hs
6923−--- orig/src/MFlow/Forms/XHtml.hs 2014-06-10 05:51:26.973015856 +0300
6924−+++ new/src/MFlow/Forms/XHtml.hs 2014-06-10 05:51:25.000000000 +0300
6925−@@ -1,66 +1,66 @@
6926−------------------------------------------------------------------------------
6927−---
6928−--- Module : Control.MessageFlow.Forms.XHtml
6929−--- Copyright : Alberto Gónez Corona
6930−--- License : BSD3
6931−---
6932−--- Maintainer : agocorona@gmail.com
6933−--- Stability : experimental
6934−---
6935−------------------------------------------------------------------------------
6936−-{- | Instances of `FormInput` for the 'Text.XHtml' module of the xhtml package
6937−--}
6938−-
6939−-{-# OPTIONS -XMultiParamTypeClasses
6940−- -XFlexibleInstances
6941−- -XUndecidableInstances
6942−- -XTypeSynonymInstances
6943−- -XFlexibleContexts
6944−- -XTypeOperators
6945−- #-}
6946−-
6947−-
6948−-module MFlow.Forms.XHtml where
6949−-
6950−-import MFlow (HttpData(..))
6951−-import MFlow.Forms
6952−-import MFlow.Cookies(contentHtml)
6953−-import Data.ByteString.Lazy.Char8(pack,unpack)
6954−-import qualified Data.Text as T
6955−-import Text.XHtml.Strict as X
6956−-import Control.Monad.Trans
6957−-import Data.Typeable
6958−-
6959−-instance Monad m => ADDATTRS (View Html m a) where
6960−- widget ! atrs= widget `wmodify` \fs mx -> return ((head fs ! atrs:tail fs), mx)
6961−-
6962−-
6963−-
6964−-instance FormInput Html where
6965−- toByteString = pack. showHtmlFragment
6966−- toHttpData = HttpData [contentHtml] [] . toByteString
6967−- ftag t= tag t
6968−- inred = X.bold ![X.thestyle "color:red"]
6969−- finput n t v f c= X.input ! ([thetype t ,name n, value v] ++ if f then [checked] else []
6970−- ++ case c of Just s ->[strAttr "onclick" s]; _ -> [] )
6971−- ftextarea name text= X.textarea ! [X.name name] << T.unpack text
6972−-
6973−- fselect name list = select ![ X.name name] << list
6974−- foption name v msel= X.option ! ([value name] ++ selected msel) << v
6975−- where
6976−- selected msel = if msel then [X.selected] else []
6977−-
6978−- attrs tag attrs = tag ! (map (\(n,v) -> strAttr n v) attrs)
6979−-
6980−-
6981−-
6982−- formAction action form = X.form ! [X.action action, method "post"] << form
6983−- fromStr = stringToHtml
6984−- fromStrNoEncode= primHtml
6985−-
6986−- flink v str = toHtml $ hotlink ( v) << str
6987−-
6988−-instance Typeable Html where
6989−- typeOf = \_ -> mkTyConApp (mkTyCon3 "xhtml" "Text.XHtml.Strict" "Html") []
6990−-
6991−-
6992−+-----------------------------------------------------------------------------
6993−+--
6994−+-- Module : Control.MessageFlow.Forms.XHtml
6995−+-- Copyright : Alberto Gónez Corona
6996−+-- License : BSD3
6997−+--
6998−+-- Maintainer : agocorona@gmail.com
6999−+-- Stability : experimental
7000−+--
7001−+-----------------------------------------------------------------------------
7002−+{- | Instances of `FormInput` for the 'Text.XHtml' module of the xhtml package
7003−+-}
7004−+
7005−+{-# OPTIONS -XMultiParamTypeClasses
7006−+ -XFlexibleInstances
7007−+ -XUndecidableInstances
7008−+ -XTypeSynonymInstances
7009−+ -XFlexibleContexts
7010−+ -XTypeOperators
7011−+ #-}
7012−+
7013−+
7014−+module MFlow.Forms.XHtml where
7015−+
7016−+import MFlow (HttpData(..))
7017−+import MFlow.Forms
7018−+import MFlow.Cookies(contentHtml)
7019−+import Data.ByteString.Lazy.Char8(pack,unpack)
7020−+import qualified Data.Text as T
7021−+import Text.XHtml.Strict as X
7022−+import Control.Monad.Trans
7023−+import Data.Typeable
7024−+
7025−+instance Monad m => ADDATTRS (View Html m a) where
7026−+ widget ! atrs= widget `wmodify` \fs mx -> return ((head fs ! atrs:tail fs), mx)
7027−+
7028−+
7029−+
7030−+instance FormInput Html where
7031−+ toByteString = pack. showHtmlFragment
7032−+ toHttpData = HttpData [contentHtml] [] . toByteString
7033−+ ftag t= tag t
7034−+ inred = X.bold ![X.thestyle "color:red"]
7035−+ finput n t v f c= X.input ! ([thetype t ,name n, value v] ++ if f then [checked] else []
7036−+ ++ case c of Just s ->[strAttr "onclick" s]; _ -> [] )
7037−+ ftextarea name text= X.textarea ! [X.name name] << T.unpack text
7038−+
7039−+ fselect name list = select ![ X.name name] << list
7040−+ foption name v msel= X.option ! ([value name] ++ selected msel) << v
7041−+ where
7042−+ selected msel = if msel then [X.selected] else []
7043−+
7044−+ attrs tag attrs = tag ! (map (\(n,v) -> strAttr n v) attrs)
7045−+
7046−+
7047−+
7048−+ formAction action form = X.form ! [X.action action, method "post"] << form
7049−+ fromStr = stringToHtml
7050−+ fromStrNoEncode= primHtml
7051−+
7052−+ flink v str = toHtml $ hotlink ( v) << str
7053−+
7054−+instance Typeable Html where
7055−+ typeOf = \_ -> mkTyConApp (mkTyCon3 "xhtml" "Text.XHtml.Strict" "Html") []
7056−+
7057−+
7058−diff -ru orig/src/MFlow/Forms.hs new/src/MFlow/Forms.hs
7059−--- orig/src/MFlow/Forms.hs 2014-06-10 05:51:26.961015857 +0300
7060−+++ new/src/MFlow/Forms.hs 2014-06-10 05:51:25.000000000 +0300
7061−@@ -1,1039 +1,1047 @@
7062−-{-# OPTIONS -XDeriveDataTypeable
7063−- -XUndecidableInstances
7064−- -XExistentialQuantification
7065−- -XMultiParamTypeClasses
7066−- -XTypeSynonymInstances
7067−- -XFlexibleInstances
7068−- -XScopedTypeVariables
7069−- -XFunctionalDependencies
7070−- -XFlexibleContexts
7071−- -XRecordWildCards
7072−- -XIncoherentInstances
7073−- -XTypeFamilies
7074−- -XTypeOperators
7075−- -XOverloadedStrings
7076−- -XTemplateHaskell
7077−- -XNoMonomorphismRestriction
7078−-
7079−-#-}
7080−-
7081−-{- |
7082−-MFlow run stateful server processes. This version is the first stateful web framework
7083−-that is as RESTful as a web framework can be.
7084−-
7085−-The routes are expressed as normal, monadic haskell code in the FlowM monad. Local links
7086−-point to alternative routes within this monadic computation just like a textual menu
7087−-in a console application. Any GET page is directly reachable by means of a RESTful URL.
7088−-
7089−-At any moment the flow can respond to the back button or to any RESTful path that the user may paste in the navigation bar.
7090−-If the procedure is waiting for another different page, the FlowM monad backtrack until the path partially match
7091−-. From this position the execution goes forward until the rest of the path match. This way the
7092−-statelessness is optional. However, it is possible to store a session state, which may backtrack or
7093−-not when the navigation goes back and forth. It is upto the programmer.
7094−-
7095−-
7096−-All the flow of requests and responses are coded by the programmer in a single procedure.
7097−-Allthoug single request-response flows are possible. Therefore, the code is
7098−-more understandable. It is not continuation based. It uses a log for thread state persistence and backtracking for
7099−-handling the back button. Back button state syncronization is supported out-of-the-box
7100−-
7101−-The MFlow architecture is scalable, since the state is serializable and small
7102−-
7103−-The processes are stopped and restarted by the
7104−-application server on demand, including the execution state (if the Wokflow monad is used).
7105−-Therefore session management is automatic. State consistence and transactions are given by the TCache package.
7106−-
7107−-The processes interact trough widgets, that are an extension of formlets with
7108−-additional applicative combinators, formatting, link management, callbacks, modifiers, caching,
7109−-byteString conversion and AJAX. All is coded in pure haskell.
7110−-
7111−-The interfaces and communications are abstract, but there are bindings for blaze-html, HSP, Text.XHtml and byteString
7112−-, Hack and WAI but it can be extended to non Web based architectures.
7113−-
7114−-Bindings for hack, and hsp >= 0.8, are not compiled by Hackage, and do not appear, but are included in the package files.
7115−-To use them, add then to the exported modules and execute cabal install
7116−-
7117−-It is designed for applications that can be run with no deployment with runghc in order
7118−-to speed up the development process. see <http://haskell-web.blogspot.com.es/2013/05/a-web-application-in-tweet.html>
7119−-
7120−-This module implement stateful processes (flows) that are optionally persistent.
7121−-This means that they automatically store and recover his execution state. They are executed by the MFlow app server.
7122−-defined in the "MFlow" module.
7123−-
7124−-These processses interact with the user trough user interfaces made of widgets (see below) that return back statically typed responses to
7125−-the calling process. Because flows are stateful, not request-response, the code is more understandable, because
7126−-all the flow of request and responses is coded by the programmer in a single procedure in the FlowM monad. Allthoug
7127−-single request-response flows and callbacks are possible.
7128−-
7129−-This module is abstract with respect to the formatting (here referred with the type variable @view@) . For an
7130−-instantiation for "Text.XHtml" import "MFlow.Forms.XHtml", "MFlow.Hack.XHtml.All" or "MFlow.Wai.XHtml.All" .
7131−-To use Haskell Server Pages import "MFlow.Forms.HSP". However the functionalities are documented here.
7132−-
7133−-`ask` is the only method for user interaction. It run in the @MFlow view m@ monad, with @m@ the monad chosen by the user, usually IO.
7134−-It send user interfaces (in the @View view m@ monad) and return statically
7135−-typed responses. The user interface definitions are based on a extension of
7136−-formLets (<http://www.haskell.org/haskellwiki/Formlets>) with the addition of caching, links, formatting, attributes,
7137−- extra combinators, callbaks and modifiers.
7138−-The interaction with the user is stateful. In the same computation there may be many
7139−-request-response interactions, in the same way than in the case of a console applications.
7140−-
7141−-* APPLICATION SERVER
7142−-
7143−-Therefore, session and state management is simple and transparent: it is in the haskell
7144−-structures in the scope of the computation. `transient` (normal) procedures have no persistent session state
7145−-and `stateless` procedures accept a single request and return a single response.
7146−-
7147−-`MFlow.Forms.step` is a lifting monad transformer that permit persistent server procedures that
7148−-remember the execution state even after system shutdowns by using the package workflow (<http://hackage.haskell.org/package/Workflow>) internally.
7149−-This state management is transparent. There is no programer interface for session management.
7150−-
7151−-The programmer set the process timeout and the session timeout with `setTimeouts`.
7152−-If the procedure has been stopped due to the process timeout or due to a system shutdowm,
7153−-the procedure restart in the last state when a request for this procedure arrives
7154−-(if the procedure uses the `step` monad transformer)
7155−-
7156−-* WIDGETS
7157−-
7158−-The correctness of the web responses is assured by the use of formLets.
7159−-But unlike formLets in its current form, it permits the definition of widgets.
7160−-/A widget is a combination of formLets and links within its own formatting template/, all in
7161−-the same definition in the same source file, in plain declarative Haskell style.
7162−-
7163−-The formatting is abstract. It has to implement the 'FormInput' class.
7164−-There are instances for Text.XHtml ("MFlow.Forms.XHtml"), Haskell Server Pages ("MFlow.Forms.HSP")
7165−-and ByteString. So widgets
7166−-can use any formatting that is instance of `FormInput`.
7167−-It is possible to use more than one format in the same widget.
7168−-
7169−-Links defined with `wlink` are treated the same way than forms. They are type safe and return values
7170−- to the same flow of execution.
7171−-It is posssible to combine links and forms in the same widget by using applicative combinators but also
7172−-additional applicative combinators like \<+> !*> , |*|. Widgets are also monoids, so they can
7173−-be combined as such.
7174−-
7175−-* NEW IN THIS RELEASE
7176−-
7177−-[@Runtime templates@] 'template', 'edTemplate', 'witerate' and 'dField' permit the edition of
7178−-the widget content at runtime, and the management of placeholders with input fields and data fields
7179−-within the template with no navigation in the client, little bandwidth usage and little server load. Enven less
7180−-than using 'autoRefresh'.
7181−-
7182−-* IN PREVIOUS RELEASES
7183−-
7184−-{@AutoRefresh@] Using `autoRefresh`, Dynamic widgets can refresh themselves with new information without forcing a refresh of the whole page
7185−-
7186−-[@Push@] With `push` a widget can push new content to the browser when something in the server happens
7187−-
7188−-[@Error traces@] using the monadloc package, now each runtime error (in a monadic statement) has a complete execution trace.
7189−-
7190−-
7191−-[@RESTful URLs@] Now each page is directly reachable by means of a intuitive, RESTful url, whose path is composed by the sucession
7192−-of links clicked to reach such page and such point in the procedure. Just what you would expect.
7193−-
7194−-[@Page flows@] each widget-formlet can have its own independent behaviour within the page. They can
7195−-refresh independently trough AJAX by means of 'autoRefresh'. Additionally, 'pageFlow' initiates the page flow mode or a
7196−-subpage flow by adding a well know indetifier prefix for links and form parameters.
7197−-
7198−-[@Modal Dialogs@] 'wdialog' present a widget within a modal or non modal jQuery dialog. while a monadic
7199−-widget-formlet can add different form elements depending on the user responses, 'wcallback' can
7200−-substitute the widget by other. (See 'Demos/demos.blaze.hs' for some examples)
7201−-
7202−-[@JQuery widgets@] with MFlow interface: 'getSpinner', 'datePicker', 'wdialog'
7203−-
7204−-[@WAI interface@] Now MFlow works with Snap and other WAI developments. Include "MFlow.Wai" or "MFlow.Wai.Blaze.Html.All" to use it.
7205−-
7206−-[@blaze-html support@] see <http://hackage.haskell.org/package/blaze-html> import "MFlow.Forms.Blaze.Html" or "MFlow.Wai.Blaze.Html.All" to use Blaze-Html
7207−-
7208−-[@AJAX@] Now an ajax procedures (defined with 'ajax' can perform many interactions with the browser widgets, instead
7209−-of a single request-response (see 'ajaxSend').
7210−-
7211−-[@Active widgets@] "MFlow.Forms.Widgets" contains active widgets that interact with the
7212−-server via Ajax and dynamically control other widgets: 'wEditList', 'autocomplete' 'autocompleteEdit' and others.
7213−-
7214−-[@Requirements@] a widget can specify javaScript files, JavasScript online scipts, CSS files, online CSS and server processes
7215−- and any other instance of the 'Requrement' class. See 'requires' and 'WebRequirements'
7216−-
7217−-[@content-management@] for templating and online edition of the content template. See 'tFieldEd' 'tFieldGen' and 'tField'
7218−-
7219−-[@multilanguage@] see 'mField' and 'mFieldEd'
7220−-
7221−-[@URLs to internal states@] if the web navigation is trough GET forms or links,
7222−- an URL can express a direct path to the n-th step of a flow, So this URL can be shared with other users.
7223−-Just like in the case of an ordinary stateless application.
7224−-
7225−-
7226−-[@Back Button@] This is probably the first implementation in any language where the navigation
7227−-can be expressed procedurally and still it works well with the back button, thanks
7228−-to monad magic. (See <http://haskell-web.blogspot.com.es/2012/03//failback-monad.html>)
7229−-
7230−-
7231−-[@Cached widgets@] with `cachedWidget` it is possible to cache the rendering of a widget as a ByteString (maintaining type safety)
7232−-, the caching can be permanent or for a certain time. this is very useful for complex widgets that present information. Specially if
7233−-the widget content comes from a database and it is shared by all users.
7234−-
7235−-
7236−-[@Callbacks@] `waction` add a callback to a widget. It is executed when its input is validated.
7237−-The callback may initate a flow of interactions with the user or simply executes an internal computation.
7238−-Callbacks are necessary for the creation of abstract container
7239−-widgets that may not know the behaviour of its content. with callbacks, the widget manages its content as black boxes.
7240−-
7241−-
7242−-[@Modifiers@] `wmodify` change the visualization and result returned by the widget. For example it may hide a
7243−-login form and substitute it by the username if already logged.
7244−-
7245−-Example:
7246−-
7247−-@ ask $ wform userloginform \``validate`\` valdateProc \``waction`\` loginProc \``wmodify`\` hideIfLogged@
7248−-
7249−-
7250−-[@attributes for formLet elements@] to add atributes to widgets. See the '<!' opèrator
7251−-
7252−-
7253−-[@ByteString normalization and hetereogeneous formatting@] For caching the rendering of widgets at the
7254−- ByteString level, and to permit many formatring styles
7255−-in the same page, there are operators that combine different formats which are converted to ByteStrings.
7256−-For example the header and footer may be coded in XML, while the formlets may be formatted using Text.XHtml.
7257−-
7258−-[@File Server@] With file caching. See "MFlow.FileServer"
7259−-
7260−-
7261−--}
7262−-
7263−-module MFlow.Forms(
7264−-
7265−--- * Basic definitions
7266−--- FormLet(..),
7267−-FlowM, View(..), FormElm(..), FormInput(..)
7268−-
7269−--- * Users
7270−-, Auth(..), userRegister, setAuthMethod, userValidate, isLogged, setAdminUser, getAdminName
7271−-,getCurrentUser,getUserSimple, getUser, userFormLine, userLogin,logout, paranoidLogout
7272−-,encryptedLogout, userWidget, paranoidUserWidget, encryptedUserWidget, login, paranoidLogin, encryptedLogin,
7273−-userName,
7274−--- * User interaction
7275−-ask, page, askt, clearEnv, wstateless, pageFlow,
7276−--- * formLets
7277−--- | They usually produce the HTML form elements (depending on the FormInput instance used)
7278−--- It is possible to modify their attributes with the `<!` operator.
7279−--- They are combined with applicative ombinators and some additional ones
7280−--- formatting can be added with the formatting combinators.
7281−--- modifiers change their presentation and behaviour
7282−-getString,getInt,getInteger, getTextBox
7283−-,getMultilineText,getBool,getSelect, setOption,setSelectedOption, getPassword,
7284−-getRadio, setRadio, setRadioActive, wlabel, getCheckBoxes, genCheckBoxes, setCheckBox,
7285−-submitButton,resetButton, whidden, wlink, absLink, getKeyValueParam,
7286−+{-# OPTIONS -XDeriveDataTypeable
7287−+ -XUndecidableInstances
7288−+ -XExistentialQuantification
7289−+ -XMultiParamTypeClasses
7290−+ -XTypeSynonymInstances
7291−+ -XFlexibleInstances
7292−+ -XScopedTypeVariables
7293−+ -XFunctionalDependencies
7294−+ -XFlexibleContexts
7295−+ -XRecordWildCards
7296−+ -XIncoherentInstances
7297−+ -XTypeFamilies
7298−+ -XTypeOperators
7299−+ -XOverloadedStrings
7300−+ -XTemplateHaskell
7301−+ -XNoMonomorphismRestriction
7302−+
7303−+#-}
7304−+
7305−+{- |
7306−+MFlow run stateful server processes. This version is the first stateful web framework
7307−+that is as RESTful as a web framework can be.
7308−+
7309−+The routes are expressed as normal, monadic haskell code in the FlowM monad. Local links
7310−+point to alternative routes within this monadic computation just like a textual menu
7311−+in a console application. Any GET page is directly reachable by means of a RESTful URL.
7312−+
7313−+At any moment the flow can respond to the back button or to any RESTful path that the user may paste in the navigation bar.
7314−+If the procedure is waiting for another different page, the FlowM monad backtrack until the path partially match
7315−+. From this position the execution goes forward until the rest of the path match. This way the
7316−+statelessness is optional. However, it is possible to store a session state, which may backtrack or
7317−+not when the navigation goes back and forth. It is upto the programmer.
7318−+
7319−+
7320−+All the flow of requests and responses are coded by the programmer in a single procedure.
7321−+Allthoug single request-response flows are possible. Therefore, the code is
7322−+more understandable. It is not continuation based. It uses a log for thread state persistence and backtracking for
7323−+handling the back button. Back button state syncronization is supported out-of-the-box
7324−+
7325−+The MFlow architecture is scalable, since the state is serializable and small
7326−+
7327−+The processes are stopped and restarted by the
7328−+application server on demand, including the execution state (if the Wokflow monad is used).
7329−+Therefore session management is automatic. State consistence and transactions are given by the TCache package.
7330−+
7331−+The processes interact trough widgets, that are an extension of formlets with
7332−+additional applicative combinators, formatting, link management, callbacks, modifiers, caching,
7333−+byteString conversion and AJAX. All is coded in pure haskell.
7334−+
7335−+The interfaces and communications are abstract, but there are bindings for blaze-html, HSP, Text.XHtml and byteString
7336−+, Hack and WAI but it can be extended to non Web based architectures.
7337−+
7338−+Bindings for hack, and hsp >= 0.8, are not compiled by Hackage, and do not appear, but are included in the package files.
7339−+To use them, add then to the exported modules and execute cabal install
7340−+
7341−+It is designed for applications that can be run with no deployment with runghc in order
7342−+to speed up the development process. see <http://haskell-web.blogspot.com.es/2013/05/a-web-application-in-tweet.html>
7343−+
7344−+This module implement stateful processes (flows) that are optionally persistent.
7345−+This means that they automatically store and recover his execution state. They are executed by the MFlow app server.
7346−+defined in the "MFlow" module.
7347−+
7348−+These processses interact with the user trough user interfaces made of widgets (see below) that return back statically typed responses to
7349−+the calling process. Because flows are stateful, not request-response, the code is more understandable, because
7350−+all the flow of request and responses is coded by the programmer in a single procedure in the FlowM monad. Allthoug
7351−+single request-response flows and callbacks are possible.
7352−+
7353−+This module is abstract with respect to the formatting (here referred with the type variable @view@) . For an
7354−+instantiation for "Text.XHtml" import "MFlow.Forms.XHtml", "MFlow.Hack.XHtml.All" or "MFlow.Wai.XHtml.All" .
7355−+To use Haskell Server Pages import "MFlow.Forms.HSP". However the functionalities are documented here.
7356−+
7357−+`ask` is the only method for user interaction. It run in the @MFlow view m@ monad, with @m@ the monad chosen by the user, usually IO.
7358−+It send user interfaces (in the @View view m@ monad) and return statically
7359−+typed responses. The user interface definitions are based on a extension of
7360−+formLets (<http://www.haskell.org/haskellwiki/Formlets>) with the addition of caching, links, formatting, attributes,
7361−+ extra combinators, callbaks and modifiers.
7362−+The interaction with the user is stateful. In the same computation there may be many
7363−+request-response interactions, in the same way than in the case of a console applications.
7364−+
7365−+* APPLICATION SERVER
7366−+
7367−+Therefore, session and state management is simple and transparent: it is in the haskell
7368−+structures in the scope of the computation. `transient` (normal) procedures have no persistent session state
7369−+and `stateless` procedures accept a single request and return a single response.
7370−+
7371−+`MFlow.Forms.step` is a lifting monad transformer that permit persistent server procedures that
7372−+remember the execution state even after system shutdowns by using the package workflow (<http://hackage.haskell.org/package/Workflow>) internally.
7373−+This state management is transparent. There is no programer interface for session management.
7374−+
7375−+The programmer set the process timeout and the session timeout with `setTimeouts`.
7376−+If the procedure has been stopped due to the process timeout or due to a system shutdowm,
7377−+the procedure restart in the last state when a request for this procedure arrives
7378−+(if the procedure uses the `step` monad transformer)
7379−+
7380−+* WIDGETS
7381−+
7382−+The correctness of the web responses is assured by the use of formLets.
7383−+But unlike formLets in its current form, it permits the definition of widgets.
7384−+/A widget is a combination of formLets and links within its own formatting template/, all in
7385−+the same definition in the same source file, in plain declarative Haskell style.
7386−+
7387−+The formatting is abstract. It has to implement the 'FormInput' class.
7388−+There are instances for Text.XHtml ("MFlow.Forms.XHtml"), Haskell Server Pages ("MFlow.Forms.HSP")
7389−+and ByteString. So widgets
7390−+can use any formatting that is instance of `FormInput`.
7391−+It is possible to use more than one format in the same widget.
7392−+
7393−+Links defined with `wlink` are treated the same way than forms. They are type safe and return values
7394−+ to the same flow of execution.
7395−+It is posssible to combine links and forms in the same widget by using applicative combinators but also
7396−+additional applicative combinators like \<+> !*> , |*|. Widgets are also monoids, so they can
7397−+be combined as such.
7398−+
7399−+* NEW IN THIS RELEASE
7400−+
7401−+[@Runtime templates@] 'template', 'edTemplate', 'witerate' and 'dField' permit the edition of
7402−+the widget content at runtime, and the management of placeholders with input fields and data fields
7403−+within the template with no navigation in the client, little bandwidth usage and little server load. Enven less
7404−+than using 'autoRefresh'.
7405−+
7406−+* IN PREVIOUS RELEASES
7407−+
7408−+{@AutoRefresh@] Using `autoRefresh`, Dynamic widgets can refresh themselves with new information without forcing a refresh of the whole page
7409−+
7410−+[@Push@] With `push` a widget can push new content to the browser when something in the server happens
7411−+
7412−+[@Error traces@] using the monadloc package, now each runtime error (in a monadic statement) has a complete execution trace.
7413−+
7414−+
7415−+[@RESTful URLs@] Now each page is directly reachable by means of a intuitive, RESTful url, whose path is composed by the sucession
7416−+of links clicked to reach such page and such point in the procedure. Just what you would expect.
7417−+
7418−+[@Page flows@] each widget-formlet can have its own independent behaviour within the page. They can
7419−+refresh independently trough AJAX by means of 'autoRefresh'. Additionally, 'pageFlow' initiates the page flow mode or a
7420−+subpage flow by adding a well know indetifier prefix for links and form parameters.
7421−+
7422−+[@Modal Dialogs@] 'wdialog' present a widget within a modal or non modal jQuery dialog. while a monadic
7423−+widget-formlet can add different form elements depending on the user responses, 'wcallback' can
7424−+substitute the widget by other. (See 'Demos/demos.blaze.hs' for some examples)
7425−+
7426−+[@JQuery widgets@] with MFlow interface: 'getSpinner', 'datePicker', 'wdialog'
7427−+
7428−+[@WAI interface@] Now MFlow works with Snap and other WAI developments. Include "MFlow.Wai" or "MFlow.Wai.Blaze.Html.All" to use it.
7429−+
7430−+[@blaze-html support@] see <http://hackage.haskell.org/package/blaze-html> import "MFlow.Forms.Blaze.Html" or "MFlow.Wai.Blaze.Html.All" to use Blaze-Html
7431−+
7432−+[@AJAX@] Now an ajax procedures (defined with 'ajax' can perform many interactions with the browser widgets, instead
7433−+of a single request-response (see 'ajaxSend').
7434−+
7435−+[@Active widgets@] "MFlow.Forms.Widgets" contains active widgets that interact with the
7436−+server via Ajax and dynamically control other widgets: 'wEditList', 'autocomplete' 'autocompleteEdit' and others.
7437−+
7438−+[@Requirements@] a widget can specify javaScript files, JavasScript online scipts, CSS files, online CSS and server processes
7439−+ and any other instance of the 'Requrement' class. See 'requires' and 'WebRequirements'
7440−+
7441−+[@content-management@] for templating and online edition of the content template. See 'tFieldEd' 'tFieldGen' and 'tField'
7442−+
7443−+[@multilanguage@] see 'mField' and 'mFieldEd'
7444−+
7445−+[@URLs to internal states@] if the web navigation is trough GET forms or links,
7446−+ an URL can express a direct path to the n-th step of a flow, So this URL can be shared with other users.
7447−+Just like in the case of an ordinary stateless application.
7448−+
7449−+
7450−+[@Back Button@] This is probably the first implementation in any language where the navigation
7451−+can be expressed procedurally and still it works well with the back button, thanks
7452−+to monad magic. (See <http://haskell-web.blogspot.com.es/2012/03//failback-monad.html>)
7453−+
7454−+
7455−+[@Cached widgets@] with `cachedWidget` it is possible to cache the rendering of a widget as a ByteString (maintaining type safety)
7456−+, the caching can be permanent or for a certain time. this is very useful for complex widgets that present information. Specially if
7457−+the widget content comes from a database and it is shared by all users.
7458−+
7459−+
7460−+[@Callbacks@] `waction` add a callback to a widget. It is executed when its input is validated.
7461−+The callback may initate a flow of interactions with the user or simply executes an internal computation.
7462−+Callbacks are necessary for the creation of abstract container
7463−+widgets that may not know the behaviour of its content. with callbacks, the widget manages its content as black boxes.
7464−+
7465−+
7466−+[@Modifiers@] `wmodify` change the visualization and result returned by the widget. For example it may hide a
7467−+login form and substitute it by the username if already logged.
7468−+
7469−+Example:
7470−+
7471−+@ ask $ wform userloginform \``validate`\` valdateProc \``waction`\` loginProc \``wmodify`\` hideIfLogged@
7472−+
7473−+
7474−+[@attributes for formLet elements@] to add atributes to widgets. See the '<!' opèrator
7475−+
7476−+
7477−+[@ByteString normalization and hetereogeneous formatting@] For caching the rendering of widgets at the
7478−+ ByteString level, and to permit many formatring styles
7479−+in the same page, there are operators that combine different formats which are converted to ByteStrings.
7480−+For example the header and footer may be coded in XML, while the formlets may be formatted using Text.XHtml.
7481−+
7482−+[@File Server@] With file caching. See "MFlow.FileServer"
7483−+
7484−+
7485−+-}
7486−+
7487−+module MFlow.Forms(
7488−+
7489−+-- * Basic definitions
7490−+-- FormLet(..),
7491−+FlowM, View(..), FormElm(..), FormInput(..)
7492−+
7493−+-- * Users
7494−+, Auth(..), userRegister, setAuthMethod, userValidate, isLogged, setAdminUser, getAdminName
7495−+,getCurrentUser,getUserSimple, getUser, userFormLine, userLogin,logout, paranoidLogout
7496−+,encryptedLogout, userWidget, paranoidUserWidget, encryptedUserWidget, login, paranoidLogin, encryptedLogin,
7497−+userName,
7498−+-- * User interaction
7499−+ask, page, askt, clearEnv, wstateless, pageFlow,
7500−+-- * formLets
7501−+-- | They usually produce the HTML form elements (depending on the FormInput instance used)
7502−+-- It is possible to modify their attributes with the `<!` operator.
7503−+-- They are combined with applicative ombinators and some additional ones
7504−+-- formatting can be added with the formatting combinators.
7505−+-- modifiers change their presentation and behaviour
7506−+getString,getInt,getInteger, getTextBox
7507−+,getMultilineText,getBool,getSelect, setOption,setSelectedOption, getPassword,
7508−+getRadio, setRadio, setRadioActive, wlabel, getCheckBoxes, genCheckBoxes, setCheckBox,
7509−+submitButton,resetButton, whidden, wlink, absLink, getKeyValueParam, fileUpload,
7510− getRestParam, returning, wform, firstOf, manyOf, allOf, wraw, wrender, notValid
7511−--- * FormLet modifiers
7512−-,validate, noWidget, stop, waction, wcallback, wmodify,
7513−-
7514−--- * Caching widgets
7515−-cachedWidget, wcached, wfreeze,
7516−-
7517−--- * Widget combinators
7518−-(<+>),(|*>),(|+|), (**>),(<**),(<|>),(<*),(<$>),(<*>),(>:>)
7519−-
7520−----- * Normalized (convert to ByteString) widget combinators
7521−----- | These dot operators are indentical to the non dot operators, with the addition of the conversion of the arguments to lazy byteStrings
7522−-----
7523−----- The purpose is to combine heterogeneous formats into byteString-formatted widgets that
7524−----- can be cached with `cachedWidget`
7525−---,(.<+>.), (.|*>.), (.|+|.), (.**>.),(.<**.), (.<|>.),
7526−-
7527−--- * Formatting combinators
7528−-,(<<<),(++>),(<++),(<!)
7529−-
7530−----- * Normalized (convert to ByteString) formatting combinators
7531−----- | Some combinators that convert the formatting of their arguments to lazy byteString
7532−-----(.<<.),(.<++.),(.++>.)
7533−-
7534−--- * ByteString tags
7535−-,btag,bhtml,bbody
7536−-
7537−--- * Normalization
7538−-,flatten, normalize
7539−-
7540−--- * Running the flow monad
7541−-,runFlow, transientNav, runFlowOnce, runFlowIn
7542−-,runFlowConf,MFlow.Forms.Internals.step
7543−--- * controlling backtracking
7544−-,goingBack,returnIfForward, breturn, preventGoingBack, compensate, onBacktrack, retry
7545−-
7546−+-- * FormLet modifiers
7547−+,validate, noWidget, stop, waction, wcallback, wmodify,
7548−+
7549−+-- * Caching widgets
7550−+cachedWidget, wcached, wfreeze,
7551−+
7552−+-- * Widget combinators
7553−+(<+>),(|*>),(|+|), (**>),(<**),(<|>),(<*),(<$>),(<*>),(>:>)
7554−+
7555−+---- * Normalized (convert to ByteString) widget combinators
7556−+---- | These dot operators are indentical to the non dot operators, with the addition of the conversion of the arguments to lazy byteStrings
7557−+----
7558−+---- The purpose is to combine heterogeneous formats into byteString-formatted widgets that
7559−+---- can be cached with `cachedWidget`
7560−+--,(.<+>.), (.|*>.), (.|+|.), (.**>.),(.<**.), (.<|>.),
7561−+
7562−+-- * Formatting combinators
7563−+,(<<<),(++>),(<++),(<!)
7564−+
7565−+---- * Normalized (convert to ByteString) formatting combinators
7566−+---- | Some combinators that convert the formatting of their arguments to lazy byteString
7567−+----(.<<.),(.<++.),(.++>.)
7568−+
7569−+-- * ByteString tags
7570−+,btag,bhtml,bbody
7571−+
7572−+-- * Normalization
7573−+,flatten, normalize
7574−+
7575−+-- * Running the flow monad
7576−+,runFlow, transientNav, runFlowOnce, runFlowIn
7577−+,runFlowConf,MFlow.Forms.Internals.step
7578−+-- * controlling backtracking
7579−+,goingBack,returnIfForward, breturn, preventGoingBack, compensate, onBacktrack, retry
7580−+
7581− -- * Setting parameters
7582−-,setHttpHeader
7583−-,setHeader
7584−-,addHeader
7585−-,getHeader
7586−-,setSessionData
7587−+,setHttpHeader
7588−+,setHeader
7589−+,addHeader
7590−+,getHeader
7591−+,setSessionData
7592− ,getSessionData
7593−-,getSData
7594−-,delSessionData
7595−-,setTimeouts
7596−-
7597−--- * Cookies
7598−-,setCookie
7599−-,setParanoidCookie
7600−-,setEncryptedCookie
7601−--- * Ajax
7602−-,ajax
7603−-,ajaxSend
7604−-,ajaxSend_
7605−--- * Requirements
7606−-,Requirements(..)
7607−-,WebRequirement(..)
7608−-,requires
7609−+,getSData
7610−+,delSessionData
7611−+,setTimeouts
7612−+
7613−+-- * Cookies
7614−+,setCookie
7615−+,setParanoidCookie
7616−+,setEncryptedCookie
7617−+-- * Ajax
7618−+,ajax
7619−+,ajaxSend
7620−+,ajaxSend_
7621−+-- * Requirements
7622−+,Requirements(..)
7623−+,WebRequirement(..)
7624−+,requires
7625− -- * Utility
7626−-,getSessionId
7627−-,getLang
7628−-,genNewId
7629−-,getNextId
7630−-,changeMonad
7631−-,FailBack
7632−-,fromFailBack
7633−-,toFailBack
7634−-
7635−-)
7636−-where
7637−-
7638−-import Data.RefSerialize hiding ((<|>),empty)
7639−-import Data.TCache
7640−-import Data.TCache.Memoization
7641−-import MFlow
7642−-import MFlow.Forms.Internals
7643−-import MFlow.Cookies
7644−+,getSessionId
7645−+,getLang
7646−+,genNewId
7647−+,getNextId
7648−+,changeMonad
7649−+,FailBack
7650−+,fromFailBack
7651−+,toFailBack
7652−+
7653−+)
7654−+where
7655−+
7656−+import Data.RefSerialize hiding ((<|>),empty)
7657−+import Data.TCache
7658−+import Data.TCache.Memoization
7659−+import MFlow
7660−+import MFlow.Forms.Internals
7661−+import MFlow.Cookies
7662− import Data.ByteString.Lazy.Char8 as B(ByteString,cons,append,empty,fromChunks,unpack)
7663− import Data.ByteString.Lazy.UTF8 hiding (length, take)
7664−-import qualified Data.String as S
7665−-import qualified Data.Text as T
7666−-import Data.Text.Encoding
7667−-import Data.List
7668−---import qualified Data.CaseInsensitive as CI
7669−-import Data.Typeable
7670−-import Data.Monoid
7671−-import Control.Monad.State.Strict
7672−-import Data.Maybe
7673−-import Control.Applicative
7674−-import Control.Exception
7675−-import Control.Concurrent
7676−-import Control.Workflow as WF
7677−-import Control.Monad.Identity
7678−-import Unsafe.Coerce
7679−-import Data.List(intersperse)
7680−-import Data.IORef
7681−-import qualified Data.Map as M
7682−-import System.IO.Unsafe
7683−-import Data.Char(isNumber,toLower)
7684−-import Network.HTTP.Types.Header
7685−-import MFlow.Forms.Cache
7686−-
7687−--- | Validates a form or widget result against a validating procedure
7688−---
7689−--- @getOdd= getInt Nothing `validate` (\x -> return $ if mod x 2==0 then Nothing else Just "only odd numbers, please")@
7690−-validate
7691−- :: (FormInput view, Monad m) =>
7692−- View view m a
7693−- -> (a -> WState view m (Maybe view))
7694−- -> View view m a
7695−-validate formt val= View $ do
7696−- FormElm form mx <- runView formt
7697−- case mx of
7698−- Just x -> do
7699−- me <- val x
7700−- modify (\s -> s{inSync= True})
7701−- case me of
7702−- Just str ->
7703−- return $ FormElm ( form <> inred str) Nothing
7704−- Nothing -> return $ FormElm form mx
7705−- _ -> return $ FormElm form mx
7706−-
7707−--- | Actions are callbacks that are executed when a widget is validated.
7708−--- A action may be a complete flow in the flowM monad. It takes complete control of the navigation
7709−--- while it is executed. At the end it return the result to the caller and display the original
7710−--- calling page.
7711−--- It is useful when the widget is inside widget containers that may treat it as a black box.
7712−---
7713−--- It returns a result that can be significative or, else, be ignored with '<**' and '**>'.
7714−--- An action may or may not initiate his own dialog with the user via `ask`
7715−-waction
7716−- :: (FormInput view, Monad m)
7717−- => View view m a
7718−- -> (a -> FlowM view m b)
7719−- -> View view m b
7720−-waction f ac = do
7721−- x <- f
7722−- s <- get
7723−- let env = mfEnv s
7724−- let seq = mfSequence s
7725−- put s{mfSequence=mfSequence s+ 100,mfEnv=[],newAsk=True}
7726−- r <- flowToView $ ac x
7727−- modify $ \s-> s{mfSequence= seq, mfEnv= env}
7728−- return r
7729−- where
7730−- flowToView x=
7731−- View $ do
7732−- r <- runSup $ runFlowM x
7733−- case r of
7734−- NoBack x ->
7735−- return (FormElm mempty $ Just x)
7736−- BackPoint x->
7737−- return (FormElm mempty $ Just x)
7738−- GoBack-> do
7739−- modify $ \s ->s{notSyncInAction= True}
7740−- return (FormElm mempty Nothing)
7741−-
7742−--- | change the rendering and the return value of a page. This is superseeded by page flows.
7743−-wmodify :: (Monad m, FormInput v)
7744−- => View v m a
7745−- -> (v -> Maybe a -> WState v m (v, Maybe b))
7746−- -> View v m b
7747−-wmodify formt act = View $ do
7748−- FormElm f mx <- runView formt
7749−- (f',mx') <- act f mx
7750−- return $ FormElm f' mx'
7751−-
7752−--- | Display a text box and return a non empty String
7753−-getString :: (FormInput view,Monad m) =>
7754−- Maybe String -> View view m String
7755−-getString ms = getTextBox ms
7756−- `validate`
7757−- \s -> if null s then return (Just $ fromStr "")
7758−- else return Nothing
7759−-
7760−--- | Display a text box and return an Integer (if the value entered is not an Integer, fails the validation)
7761−-getInteger :: (FormInput view, MonadIO m) =>
7762−- Maybe Integer -> View view m Integer
7763−-getInteger = getTextBox
7764−-
7765−--- | Display a text box and return a Int (if the value entered is not an Int, fails the validation)
7766−-getInt :: (FormInput view, MonadIO m) =>
7767−- Maybe Int -> View view m Int
7768−-getInt = getTextBox
7769−-
7770−--- | Display a password box
7771−-getPassword :: (FormInput view,
7772−- Monad m) =>
7773−- View view m String
7774−-getPassword = getParam Nothing "password" Nothing
7775−-
7776−-newtype Radio a= Radio a
7777−-
7778−--- | Implement a radio button that perform a submit when pressed.
7779−--- the parameter is the name of the radio group
7780−-setRadioActive :: (FormInput view, MonadIO m,
7781−- Read a, Typeable a, Eq a, Show a) =>
7782−- a -> String -> View view m (Radio a)
7783−-setRadioActive v n = View $ do
7784−- st <- get
7785−- put st{needForm= HasElems}
7786−- let env = mfEnv st
7787−- mn <- getParam1 n env
7788−- let str = if typeOf v == typeOf(undefined :: String)
7789−- then unsafeCoerce v else show v
7790−- return $ FormElm (finput n "radio" str
7791−- ( isValidated mn && v== fromValidated mn) (Just "this.form.submit()"))
7792−- (fmap Radio $ valToMaybe mn)
7793−-
7794−-
7795−--- | Implement a radio button
7796−--- the parameter is the name of the radio group
7797−-setRadio :: (FormInput view, MonadIO m,
7798−- Read a, Typeable a, Eq a, Show a) =>
7799−- a -> String -> View view m (Radio a)
7800−-setRadio v n= View $ do
7801−- st <- get
7802−- put st{needForm= HasElems}
7803−- let env = mfEnv st
7804−- mn <- getParam1 n env
7805−- let str = if typeOf v == typeOf(undefined :: String)
7806−- then unsafeCoerce v else show v
7807−- return $ FormElm (finput n "radio" str
7808−- ( isValidated mn && v== fromValidated mn) Nothing)
7809−- (fmap Radio $ valToMaybe mn)
7810−-
7811−--- | encloses a set of Radio boxes. Return the option selected
7812−-getRadio
7813−- :: (Monad m, Functor m, FormInput view) =>
7814−- [String -> View view m (Radio a)] -> View view m a
7815−-getRadio rs= do
7816−- id <- genNewId
7817−- Radio r <- firstOf $ map (\r -> r id) rs
7818−- return r
7819−-
7820−-data CheckBoxes = CheckBoxes [String]
7821−-
7822−-instance Monoid CheckBoxes where
7823−- mappend (CheckBoxes xs) (CheckBoxes ys)= CheckBoxes $ xs ++ ys
7824−- mempty= CheckBoxes []
7825−-
7826−---instance (Monad m, Functor m) => Monoid (View v m CheckBoxes) where
7827−--- mappend x y= mappend <$> x <*> y
7828−--- mempty= return (CheckBoxes [])
7829−-
7830−-
7831−--- | Display a text box and return the value entered if it is readable( Otherwise, fail the validation)
7832−-setCheckBox :: (FormInput view, MonadIO m) =>
7833−- Bool -> String -> View view m CheckBoxes
7834−-setCheckBox checked v= View $ do
7835−- n <- genNewId
7836−- st <- get
7837−- put st{needForm= HasElems}
7838−- let env = mfEnv st
7839−- strs= map snd $ filter ((==) n . fst) env
7840−- mn= if null strs then Nothing else Just $ head strs
7841−- val = inSync st
7842−- let ret= case val of -- !> show val of
7843−- True -> Just $ CheckBoxes strs -- !> show strs
7844−- False -> Nothing
7845−- return $ FormElm
7846−- ( finput n "checkbox" v
7847−- ( checked || (isJust mn && v== fromJust mn)) Nothing)
7848−- ret
7849−-
7850−--- | Read the checkboxes dinamically created by JavaScript within the view parameter
7851−--- see for example `selectAutocomplete` in "MFlow.Forms.Widgets"
7852−-genCheckBoxes :: (Monad m, FormInput view) => view -> View view m CheckBoxes
7853−-genCheckBoxes v= View $ do
7854−- n <- genNewId
7855−- st <- get
7856−- put st{needForm= HasElems}
7857−- let env = mfEnv st
7858−- strs= map snd $ filter ((==) n . fst) env
7859−- mn= if null strs then Nothing else Just $ head strs
7860−-
7861−- val <- gets inSync
7862−- let ret= case val of
7863−- True -> Just $ CheckBoxes strs
7864−- False -> Nothing
7865−- return $ FormElm (ftag "span" v `attrs`[("id",n)]) ret
7866−-
7867−-whidden :: (Monad m, FormInput v,Read a, Show a, Typeable a) => a -> View v m a
7868−-whidden x= View $ do
7869−- n <- genNewId
7870−- env <- gets mfEnv
7871−- let showx= case cast x of
7872−- Just x' -> x'
7873−- Nothing -> show x
7874−- r <- getParam1 n env
7875−- return . FormElm (finput n "hidden" showx False Nothing) $ valToMaybe r
7876−-
7877−-getCheckBoxes :: (FormInput view, Monad m)=> View view m CheckBoxes -> View view m [String]
7878−-getCheckBoxes boxes = View $ do
7879−- n <- genNewId
7880−- st <- get
7881−- let env = mfEnv st
7882−- let form= finput n "hidden" "" False Nothing
7883−- mr <- getParam1 n env
7884−-
7885−- let env = mfEnv st
7886−- modify $ \st -> st{needForm= HasElems}
7887−- FormElm form2 mr2 <- runView boxes
7888−- return $ FormElm (form <> form2) $
7889−- case (mr `asTypeOf` Validated ("" :: String),mr2) of
7890−- (NoParam,_) -> Nothing
7891−- (Validated _,Nothing) -> Just []
7892−- (Validated _, Just (CheckBoxes rs)) -> Just rs
7893−-
7894−-
7895−-
7896−-
7897−-
7898−-getTextBox
7899−- :: (FormInput view,
7900−- Monad m,
7901−- Typeable a,
7902−- Show a,
7903−- Read a) =>
7904−- Maybe a -> View view m a
7905−-getTextBox ms = getParam Nothing "text" ms
7906−-
7907−-
7908−-getParam
7909−- :: (FormInput view,
7910−- Monad m,
7911−- Typeable a,
7912−- Show a,
7913−- Read a) =>
7914−- Maybe String -> String -> Maybe a -> View view m a
7915−-getParam look type1 mvalue = View $ do
7916−- tolook <- case look of
7917−- Nothing -> genNewId
7918−- Just n -> return n
7919−- let nvalue x = case x of
7920−- Nothing -> ""
7921−- Just v ->
7922−- case cast v of
7923−- Just v' -> v'
7924−- Nothing -> show v
7925−- st <- get
7926−- let env = mfEnv st
7927−- put st{needForm= HasElems}
7928−- r <- getParam1 tolook env
7929−- case r of
7930−- Validated x -> return $ FormElm (finput tolook type1 (nvalue $ Just x) False Nothing) $ Just x
7931−- NotValidated s err -> return $ FormElm (finput tolook type1 s False Nothing <> err) $ Nothing
7932−- NoParam -> return $ FormElm (finput tolook type1 (nvalue mvalue) False Nothing) $ Nothing
7933−-
7934−-
7935−-
7936−---getCurrentName :: MonadState (MFlowState view) m => m String
7937−---getCurrentName= do
7938−--- st <- get
7939−--- let parm = mfSequence st
7940−--- return $ "p"++show parm
7941−-
7942−-
7943−--- | Display a multiline text box and return its content
7944−-getMultilineText :: (FormInput view
7945−- , Monad m)
7946−- => T.Text
7947−- -> View view m T.Text
7948−-getMultilineText nvalue = View $ do
7949−- tolook <- genNewId
7950−- env <- gets mfEnv
7951−- r <- getParam1 tolook env
7952−- case r of
7953−- Validated x -> return $ FormElm (ftextarea tolook x) $ Just x
7954−- NotValidated s err -> return $ FormElm (ftextarea tolook (T.pack s)) Nothing
7955−- NoParam -> return $ FormElm (ftextarea tolook nvalue) Nothing
7956−-
7957−-
7958−---instance (MonadIO m, Functor m, FormInput view) => FormLet Bool m view where
7959−--- digest mv = getBool b "True" "False"
7960−--- where
7961−--- b= case mv of
7962−--- Nothing -> Nothing
7963−--- Just bool -> Just $ case bool of
7964−--- True -> "True"
7965−--- False -> "False"
7966−-
7967−--- | Display a dropdown box with the two values (second (true) and third parameter(false))
7968−--- . With the value of the first parameter selected.
7969−-getBool :: (FormInput view,
7970−- Monad m, Functor m) =>
7971−- Bool -> String -> String -> View view m Bool
7972−-getBool mv truestr falsestr= do
7973−- r <- getSelect $ setOption truestr (fromStr truestr) <! (if mv then [("selected","true")] else [])
7974−- <|> setOption falsestr(fromStr falsestr) <! if not mv then [("selected","true")] else []
7975−- if r == truestr then return True else return False
7976−-
7977−-
7978−-
7979−--- | Display a dropdown box with the options in the first parameter is optionally selected
7980−--- . It returns the selected option.
7981−-getSelect :: (FormInput view,
7982−- Monad m,Typeable a, Read a) =>
7983−- View view m (MFOption a) -> View view m a
7984−-getSelect opts = View $ do
7985−- tolook <- genNewId
7986−- st <- get
7987−- let env = mfEnv st
7988−- put st{needForm= HasElems}
7989−- r <- getParam1 tolook env
7990−- setSessionData $ fmap MFOption $ valToMaybe r
7991−- FormElm form mr <- (runView opts)
7992−-
7993−- return $ FormElm (fselect tolook form) $ valToMaybe r
7994−-
7995−-
7996−-newtype MFOption a= MFOption a deriving Typeable
7997−-
7998−-instance (FormInput view,Monad m, Functor m) => Monoid (View view m (MFOption a)) where
7999−- mappend = (<|>)
8000−- mempty = Control.Applicative.empty
8001−-
8002−--- | Set the option for getSelect. Options are concatenated with `<|>`
8003−-setOption
8004−- :: (Monad m, Show a, Eq a, Typeable a, FormInput view) =>
8005−- a -> view -> View view m (MFOption a)
8006−-setOption n v = do
8007−- mo <- getSessionData
8008−- case mo of
8009−- Nothing -> setOption1 n v False
8010−- Just Nothing -> setOption1 n v False
8011−- Just (Just (MFOption o)) -> setOption1 n v $ n == o
8012−-
8013−--- | Set the selected option for getSelect. Options are concatenated with `<|>`
8014−-setSelectedOption
8015−- :: (Monad m, Show a, Eq a, Typeable a, FormInput view) =>
8016−- a -> view -> View view m (MFOption a)
8017−-setSelectedOption n v= do
8018−- mo <- getSessionData
8019−- case mo of
8020−- Nothing -> setOption1 n v True
8021−- Just Nothing -> setOption1 n v True
8022−- Just (Just o) -> setOption1 n v $ n == o
8023−-
8024−-
8025−-setOption1 :: (FormInput view,
8026−- Monad m, Typeable a, Eq a, Show a) =>
8027−- a -> view -> Bool -> View view m (MFOption a)
8028−-setOption1 nam val check= View $ do
8029−- st <- get
8030−- let env = mfEnv st
8031−- put st{needForm= HasElems}
8032−- let n = if typeOf nam == typeOf(undefined :: String)
8033−- then unsafeCoerce nam
8034−- else show nam
8035−-
8036−- return . FormElm (foption n val check) . Just $ MFOption nam
8037−-
8038−---fileUpload :: (FormInput view,
8039−--- Monad m) =>
8040−--- View view m T.Text
8041−---fileUpload= getParam Nothing "file" Nothing
8042−-
8043−-
8044−--- | Enclose Widgets within some formating.
8045−--- @view@ is intended to be instantiated to a particular format
8046−---
8047−--- NOTE: It has a infix priority : @infixr 5@ less than the one of @++>@ and @<++@ of the operators, so use parentheses when appropriate,
8048−--- unless the we want to enclose all the widgets in the right side.
8049−--- Most of the type errors in the DSL are due to the low priority of this operator.
8050−---
8051−--- This is a widget, which is a table with some links. it returns an Int
8052−---
8053−--- > import MFlow.Forms.Blaze.Html
8054−--- >
8055−--- > tableLinks :: View Html Int
8056−--- > table ! At.style "border:1;width:20%;margin-left:auto;margin-right:auto"
8057−--- > <<< caption << text "choose an item"
8058−--- > ++> thead << tr << ( th << b << text "item" <> th << b << text "times chosen")
8059−--- > ++> (tbody
8060−--- > <<< tr ! rowspan "2" << td << linkHome
8061−--- > ++> (tr <<< td <<< wlink IPhone (b << text "iphone") <++ td << ( b << text (fromString $ show ( cart V.! 0)))
8062−--- > <|> tr <<< td <<< wlink IPod (b << text "ipad") <++ td << ( b << text (fromString $ show ( cart V.! 1)))
8063−--- > <|> tr <<< td <<< wlink IPad (b << text "ipod") <++ td << ( b << text (fromString $ show ( cart V.! 2))))
8064−--- > )
8065−-(<<<) :: (Monad m, Monoid view)
8066−- => (view ->view)
8067−- -> View view m a
8068−- -> View view m a
8069−-(<<<) v form= View $ do
8070−- FormElm f mx <- runView form
8071−- return $ FormElm (v f) mx
8072−-
8073−-
8074−-infixr 5 <<<
8075−-
8076−-
8077−-
8078−-
8079−-
8080−-
8081−--- | Append formatting code to a widget
8082−---
8083−--- @ getString "hi" <++ H1 << "hi there"@
8084−---
8085−--- It has a infix prority: @infixr 6@ higuer that '<<<' and most other operators
8086−-(<++) :: (Monad m, Monoid v)
8087−- => View v m a
8088−- -> v
8089−- -> View v m a
8090−-(<++) form v= View $ do
8091−- FormElm f mx <- runView form
8092−- return $ FormElm ( f <> v) mx
8093−-
8094−-infixr 6 ++>
8095−-infixr 6 <++
8096−--- | Prepend formatting code to a widget
8097−---
8098−--- @bold << "enter name" ++> getString Nothing @
8099−---
8100−--- It has a infix prority: @infixr 6@ higuer that '<<<' and most other operators
8101−-(++>) :: (Monad m, Monoid view)
8102−- => view -> View view m a -> View view m a
8103−-html ++> w = -- (html <>) <<< digest
8104−- View $ do
8105−- FormElm f mx <- runView w
8106−- return $ FormElm (html <> f) mx
8107−-
8108−-
8109−-
8110−--- | Add attributes to the topmost tag of a widget
8111−---
8112−--- it has a fixity @infix 8@
8113−-infixl 8 <!
8114−-widget <! attribs= View $ do
8115−- FormElm fs mx <- runView widget
8116−- return $ FormElm (fs `attrs` attribs) mx -- (head fs `attrs` attribs:tail fs) mx
8117−--- case fs of
8118−--- [hfs] -> return $ FormElm [hfs `attrs` attribs] mx
8119−--- _ -> error $ "operator <! : malformed widget: "++ concatMap (unpack. toByteString) fs
8120−-
8121−-
8122−--- | Is an example of login\/register validation form needed by 'userWidget'. In this case
8123−--- the form field appears in a single line. it shows, in sequence, entries for the username,
8124−--- password, a button for loging, a entry to repeat password necesary for registering
8125−--- and a button for registering.
8126−--- The user can build its own user login\/validation forms by modifying this example
8127−---
8128−--- @ userFormLine=
8129−--- (User \<\$\> getString (Just \"enter user\") \<\*\> getPassword \<\+\> submitButton \"login\")
8130−--- \<\+\> fromStr \" password again\" \+\> getPassword \<\* submitButton \"register\"
8131−--- @
8132−-userFormLine :: (FormInput view, Functor m, Monad m)
8133−- => View view m (Maybe (UserStr,PasswdStr), Maybe PasswdStr)
8134−-userFormLine=
8135−- ((,) <$> getString (Just "enter user") <! [("size","5")]
8136−- <*> getPassword <! [("size","5")]
8137−- <** submitButton "login")
8138−- <+> (fromStr " password again" ++> getPassword <! [("size","5")]
8139−- <** submitButton "register")
8140−-
8141−--- | Example of user\/password form (no validation) to be used with 'userWidget'
8142−-userLogin :: (FormInput view, Functor m, Monad m)
8143−- => View view m (Maybe (UserStr,PasswdStr), Maybe String)
8144−-userLogin=
8145−- ((,) <$> fromStr "Enter User: " ++> getString Nothing <! [("size","4")]
8146−- <*> fromStr " Enter Pass: " ++> getPassword <! [("size","4")]
8147−- <** submitButton "login")
8148−- <+> (noWidget
8149−- <* noWidget)
8150−-
8151−-
8152−-
8153−--- | Empty widget that does not validate. May be used as \"empty boxes\" inside larger widgets.
8154−---
8155−--- It returns a non valid value.
8156−-noWidget :: (FormInput view,
8157−- Monad m, Functor m) =>
8158−- View view m a
8159−-noWidget= Control.Applicative.empty
8160−+import qualified Data.String as S
8161−+import qualified Data.Text as T
8162−+import Data.Text.Encoding
8163−+import Data.List
8164−+--import qualified Data.CaseInsensitive as CI
8165−+import Data.Typeable
8166−+import Data.Monoid
8167−+import Control.Monad.State.Strict
8168−+import Data.Maybe
8169−+import Control.Applicative
8170−+import Control.Exception
8171−+import Control.Concurrent
8172−+import Control.Workflow as WF
8173−+import Control.Monad.Identity
8174−+import Unsafe.Coerce
8175−+import Data.List(intersperse)
8176−+import Data.IORef
8177−+import qualified Data.Map as M
8178−+import System.IO.Unsafe
8179−+import Data.Char(isNumber,toLower)
8180−+import Network.HTTP.Types.Header
8181−+import MFlow.Forms.Cache
8182−+
8183−+-- | Validates a form or widget result against a validating procedure
8184−+--
8185−+-- @getOdd= getInt Nothing `validate` (\x -> return $ if mod x 2==0 then Nothing else Just "only odd numbers, please")@
8186−+validate
8187−+ :: (FormInput view, Monad m) =>
8188−+ View view m a
8189−+ -> (a -> WState view m (Maybe view))
8190−+ -> View view m a
8191−+validate formt val= View $ do
8192−+ FormElm form mx <- runView formt
8193−+ case mx of
8194−+ Just x -> do
8195−+ me <- val x
8196−+ modify (\s -> s{inSync= True})
8197−+ case me of
8198−+ Just str ->
8199−+ return $ FormElm ( form <> inred str) Nothing
8200−+ Nothing -> return $ FormElm form mx
8201−+ _ -> return $ FormElm form mx
8202−+
8203−+-- | Actions are callbacks that are executed when a widget is validated.
8204−+-- A action may be a complete flow in the flowM monad. It takes complete control of the navigation
8205−+-- while it is executed. At the end it return the result to the caller and display the original
8206−+-- calling page.
8207−+-- It is useful when the widget is inside widget containers that may treat it as a black box.
8208−+--
8209−+-- It returns a result that can be significative or, else, be ignored with '<**' and '**>'.
8210−+-- An action may or may not initiate his own dialog with the user via `ask`
8211−+waction
8212−+ :: (FormInput view, Monad m)
8213−+ => View view m a
8214−+ -> (a -> FlowM view m b)
8215−+ -> View view m b
8216−+waction f ac = do
8217−+ x <- f
8218−+ s <- get
8219−+ let env = mfEnv s
8220−+ let seq = mfSequence s
8221−+ put s{mfSequence=mfSequence s+ 100,mfEnv=[],newAsk=True}
8222−+ r <- flowToView $ ac x
8223−+ modify $ \s-> s{mfSequence= seq, mfEnv= env}
8224−+ return r
8225−+ where
8226−+ flowToView x=
8227−+ View $ do
8228−+ r <- runSup $ runFlowM x
8229−+ case r of
8230−+ NoBack x ->
8231−+ return (FormElm mempty $ Just x)
8232−+ BackPoint x->
8233−+ return (FormElm mempty $ Just x)
8234−+ GoBack-> do
8235−+ modify $ \s ->s{notSyncInAction= True}
8236−+ return (FormElm mempty Nothing)
8237−+
8238−+-- | change the rendering and the return value of a page. This is superseeded by page flows.
8239−+wmodify :: (Monad m, FormInput v)
8240−+ => View v m a
8241−+ -> (v -> Maybe a -> WState v m (v, Maybe b))
8242−+ -> View v m b
8243−+wmodify formt act = View $ do
8244−+ FormElm f mx <- runView formt
8245−+ (f',mx') <- act f mx
8246−+ return $ FormElm f' mx'
8247−+
8248−+-- | Display a text box and return a non empty String
8249−+getString :: (FormInput view,Monad m) =>
8250−+ Maybe String -> View view m String
8251−+getString ms = getTextBox ms
8252−+ `validate`
8253−+ \s -> if null s then return (Just $ fromStr "")
8254−+ else return Nothing
8255−+
8256−+-- | Display a text box and return an Integer (if the value entered is not an Integer, fails the validation)
8257−+getInteger :: (FormInput view, MonadIO m) =>
8258−+ Maybe Integer -> View view m Integer
8259−+getInteger = getTextBox
8260−+
8261−+-- | Display a text box and return a Int (if the value entered is not an Int, fails the validation)
8262−+getInt :: (FormInput view, MonadIO m) =>
8263−+ Maybe Int -> View view m Int
8264−+getInt = getTextBox
8265−+
8266−+-- | Display a password box
8267−+getPassword :: (FormInput view,
8268−+ Monad m) =>
8269−+ View view m String
8270−+getPassword = getParam Nothing "password" Nothing
8271−+
8272−+newtype Radio a= Radio a
8273−+
8274−+-- | Implement a radio button that perform a submit when pressed.
8275−+-- the parameter is the name of the radio group
8276−+setRadioActive :: (FormInput view, MonadIO m,
8277−+ Read a, Typeable a, Eq a, Show a) =>
8278−+ a -> String -> View view m (Radio a)
8279−+setRadioActive v n = View $ do
8280−+ st <- get
8281−+ put st{needForm= HasElems }
8282−+ let env = mfEnv st
8283−+ mn <- getParam1 n env
8284−+ let str = if typeOf v == typeOf(undefined :: String)
8285−+ then unsafeCoerce v else show v
8286−+ return $ FormElm (finput n "radio" str
8287−+ ( isValidated mn && v== fromValidated mn) (Just "this.form.submit()"))
8288−+ (fmap Radio $ valToMaybe mn)
8289−+
8290−+
8291−+-- | Implement a radio button
8292−+-- the parameter is the name of the radio group
8293−+setRadio :: (FormInput view, MonadIO m,
8294−+ Read a, Typeable a, Eq a, Show a) =>
8295−+ a -> String -> View view m (Radio a)
8296−+setRadio v n= View $ do
8297−+ st <- get
8298−+ put st{needForm= HasElems}
8299−+ let env = mfEnv st
8300−+ mn <- getParam1 n env
8301−+ let str = if typeOf v == typeOf(undefined :: String)
8302−+ then unsafeCoerce v else show v
8303−+ return $ FormElm (finput n "radio" str
8304−+ ( isValidated mn && v== fromValidated mn) Nothing)
8305−+ (fmap Radio $ valToMaybe mn)
8306−+
8307−+-- | encloses a set of Radio boxes. Return the option selected
8308−+getRadio
8309−+ :: (Monad m, Functor m, FormInput view) =>
8310−+ [String -> View view m (Radio a)] -> View view m a
8311−+getRadio rs= do
8312−+ id <- genNewId
8313−+ Radio r <- firstOf $ map (\r -> r id) rs
8314−+ return r
8315−+
8316−+data CheckBoxes = CheckBoxes [String]
8317−+
8318−+instance Monoid CheckBoxes where
8319−+ mappend (CheckBoxes xs) (CheckBoxes ys)= CheckBoxes $ xs ++ ys
8320−+ mempty= CheckBoxes []
8321−+
8322−+--instance (Monad m, Functor m) => Monoid (View v m CheckBoxes) where
8323−+-- mappend x y= mappend <$> x <*> y
8324−+-- mempty= return (CheckBoxes [])
8325−+
8326−+
8327−+-- | Display a text box and return the value entered if it is readable( Otherwise, fail the validation)
8328−+setCheckBox :: (FormInput view, MonadIO m) =>
8329−+ Bool -> String -> View view m CheckBoxes
8330−+setCheckBox checked v= View $ do
8331−+ n <- genNewId
8332−+ st <- get
8333−+ put st{needForm= HasElems}
8334−+ let env = mfEnv st
8335−+ strs= map snd $ filter ((==) n . fst) env
8336−+ mn= if null strs then Nothing else Just $ head strs
8337−+ val = inSync st
8338−+ let ret= case val of -- !> show val of
8339−+ True -> Just $ CheckBoxes strs -- !> show strs
8340−+ False -> Nothing
8341−+ return $ FormElm
8342−+ ( finput n "checkbox" v
8343−+ ( checked || (isJust mn && v== fromJust mn)) Nothing)
8344−+ ret
8345−+
8346−+-- | Read the checkboxes dinamically created by JavaScript within the view parameter
8347−+-- see for example `selectAutocomplete` in "MFlow.Forms.Widgets"
8348−+genCheckBoxes :: (Monad m, FormInput view) => view -> View view m CheckBoxes
8349−+genCheckBoxes v= View $ do
8350−+ n <- genNewId
8351−+ st <- get
8352−+ put st{needForm= HasElems}
8353−+ let env = mfEnv st
8354−+ strs= map snd $ filter ((==) n . fst) env
8355−+ mn= if null strs then Nothing else Just $ head strs
8356−+
8357−+ val <- gets inSync
8358−+ let ret= case val of
8359−+ True -> Just $ CheckBoxes strs
8360−+ False -> Nothing
8361−+ return $ FormElm (ftag "span" v `attrs`[("id",n)]) ret
8362−+
8363−+whidden :: (Monad m, FormInput v,Read a, Show a, Typeable a) => a -> View v m a
8364−+whidden x= View $ do
8365−+ n <- genNewId
8366−+ env <- gets mfEnv
8367−+ let showx= case cast x of
8368−+ Just x' -> x'
8369−+ Nothing -> show x
8370−+ r <- getParam1 n env
8371−+ return . FormElm (finput n "hidden" showx False Nothing) $ valToMaybe r
8372−+
8373−+getCheckBoxes :: (FormInput view, Monad m)=> View view m CheckBoxes -> View view m [String]
8374−+getCheckBoxes boxes = View $ do
8375−+ n <- genNewId
8376−+ st <- get
8377−+ let env = mfEnv st
8378−+ let form= finput n "hidden" "" False Nothing
8379−+ mr <- getParam1 n env
8380−+
8381−+ let env = mfEnv st
8382−+ modify $ \st -> st{needForm= HasElems}
8383−+ FormElm form2 mr2 <- runView boxes
8384−+ return $ FormElm (form <> form2) $
8385−+ case (mr `asTypeOf` Validated ("" :: String),mr2) of
8386−+ (NoParam,_) -> Nothing
8387−+ (Validated _,Nothing) -> Just []
8388−+ (Validated _, Just (CheckBoxes rs)) -> Just rs
8389−+
8390−+
8391−+
8392−+
8393−+
8394−+getTextBox
8395−+ :: (FormInput view,
8396−+ Monad m,
8397−+ Typeable a,
8398−+ Show a,
8399−+ Read a) =>
8400−+ Maybe a -> View view m a
8401−+getTextBox ms = getParam Nothing "text" ms
8402−+
8403−+
8404−+getParam
8405−+ :: (FormInput view,
8406−+ Monad m,
8407−+ Typeable a,
8408−+ Show a,
8409−+ Read a) =>
8410−+ Maybe String -> String -> Maybe a -> View view m a
8411−+getParam look type1 mvalue = View $ do
8412−+ tolook <- case look of
8413−+ Nothing -> genNewId
8414−+ Just n -> return n
8415−+ let nvalue x = case x of
8416−+ Nothing -> ""
8417−+ Just v ->
8418−+ case cast v of
8419−+ Just v' -> v'
8420−+ Nothing -> show v
8421−+ st <- get
8422−+ let env = mfEnv st
8423−+ put st{needForm= HasElems}
8424−+ r <- getParam1 tolook env
8425−+ case r of
8426−+ Validated x -> return $ FormElm (finput tolook type1 (nvalue $ Just x) False Nothing) $ Just x
8427−+ NotValidated s err -> return $ FormElm (finput tolook type1 s False Nothing <> err) $ Nothing
8428−+ NoParam -> return $ FormElm (finput tolook type1 (nvalue mvalue) False Nothing) $ Nothing
8429−+
8430−+
8431−+
8432−+--getCurrentName :: MonadState (MFlowState view) m => m String
8433−+--getCurrentName= do
8434−+-- st <- get
8435−+-- let parm = mfSequence st
8436−+-- return $ "p"++show parm
8437−+
8438−+
8439−+-- | Display a multiline text box and return its content
8440−+getMultilineText :: (FormInput view
8441−+ , Monad m)
8442−+ => T.Text
8443−+ -> View view m T.Text
8444−+getMultilineText nvalue = View $ do
8445−+ tolook <- genNewId
8446−+ env <- gets mfEnv
8447−+ r <- getParam1 tolook env
8448−+ case r of
8449−+ Validated x -> return $ FormElm (ftextarea tolook x) $ Just x
8450−+ NotValidated s err -> return $ FormElm (ftextarea tolook (T.pack s)) Nothing
8451−+ NoParam -> return $ FormElm (ftextarea tolook nvalue) Nothing
8452−+
8453−+
8454−+--instance (MonadIO m, Functor m, FormInput view) => FormLet Bool m view where
8455−+-- digest mv = getBool b "True" "False"
8456−+-- where
8457−+-- b= case mv of
8458−+-- Nothing -> Nothing
8459−+-- Just bool -> Just $ case bool of
8460−+-- True -> "True"
8461−+-- False -> "False"
8462−+
8463−+-- | Display a dropdown box with the two values (second (true) and third parameter(false))
8464−+-- . With the value of the first parameter selected.
8465−+getBool :: (FormInput view,
8466−+ Monad m, Functor m) =>
8467−+ Bool -> String -> String -> View view m Bool
8468−+getBool mv truestr falsestr= do
8469−+ r <- getSelect $ setOption truestr (fromStr truestr) <! (if mv then [("selected","true")] else [])
8470−+ <|> setOption falsestr(fromStr falsestr) <! if not mv then [("selected","true")] else []
8471−+ if r == truestr then return True else return False
8472−+
8473−+
8474−+
8475−+-- | Display a dropdown box with the options in the first parameter is optionally selected
8476−+-- . It returns the selected option.
8477−+getSelect :: (FormInput view,
8478−+ Monad m,Typeable a, Read a) =>
8479−+ View view m (MFOption a) -> View view m a
8480−+getSelect opts = View $ do
8481−+ tolook <- genNewId
8482−+ st <- get
8483−+ let env = mfEnv st
8484−+ put st{needForm= HasElems}
8485−+ r <- getParam1 tolook env
8486−+ setSessionData $ fmap MFOption $ valToMaybe r
8487−+ FormElm form mr <- (runView opts)
8488−+
8489−+ return $ FormElm (fselect tolook form) $ valToMaybe r
8490−+
8491−+
8492−+newtype MFOption a= MFOption a deriving Typeable
8493−+
8494−+instance (FormInput view,Monad m, Functor m) => Monoid (View view m (MFOption a)) where
8495−+ mappend = (<|>)
8496−+ mempty = Control.Applicative.empty
8497−+
8498−+-- | Set the option for getSelect. Options are concatenated with `<|>`
8499−+setOption
8500−+ :: (Monad m, Show a, Eq a, Typeable a, FormInput view) =>
8501−+ a -> view -> View view m (MFOption a)
8502−+setOption n v = do
8503−+ mo <- getSessionData
8504−+ case mo of
8505−+ Nothing -> setOption1 n v False
8506−+ Just Nothing -> setOption1 n v False
8507−+ Just (Just (MFOption o)) -> setOption1 n v $ n == o
8508−+
8509−+-- | Set the selected option for getSelect. Options are concatenated with `<|>`
8510−+setSelectedOption
8511−+ :: (Monad m, Show a, Eq a, Typeable a, FormInput view) =>
8512−+ a -> view -> View view m (MFOption a)
8513−+setSelectedOption n v= do
8514−+ mo <- getSessionData
8515−+ case mo of
8516−+ Nothing -> setOption1 n v True
8517−+ Just Nothing -> setOption1 n v True
8518−+ Just (Just o) -> setOption1 n v $ n == o
8519−+
8520−+
8521−+setOption1 :: (FormInput view,
8522−+ Monad m, Typeable a, Eq a, Show a) =>
8523−+ a -> view -> Bool -> View view m (MFOption a)
8524−+setOption1 nam val check= View $ do
8525−+ st <- get
8526−+ let env = mfEnv st
8527−+ put st{needForm= HasElems}
8528−+ let n = if typeOf nam == typeOf(undefined :: String)
8529−+ then unsafeCoerce nam
8530−+ else show nam
8531−+
8532−+ return . FormElm (foption n val check) . Just $ MFOption nam
8533−+
8534−+-- | upload a file to a temporary file in the server
8535−+--
8536−+-- The user can move, rename it etc.
8537−+fileUpload :: (FormInput view,
8538−+ Monad m,Functor m) =>
8539−+ View view m (String
8540−+ ,String
8541−+ ,String
8542−+ ) -- ^ ( original file, file type, temporal uploaded)
8543−+fileUpload=
8544−+ getParam Nothing "file" Nothing <** modify ( \st -> st{mfFileUpload = True})
8545−+
8546−+
8547−+
8548−+-- | Enclose Widgets within some formating.
8549−+-- @view@ is intended to be instantiated to a particular format
8550−+--
8551−+-- NOTE: It has a infix priority : @infixr 5@ less than the one of @++>@ and @<++@ of the operators, so use parentheses when appropriate,
8552−+-- unless the we want to enclose all the widgets in the right side.
8553−+-- Most of the type errors in the DSL are due to the low priority of this operator.
8554−+--
8555−+-- This is a widget, which is a table with some links. it returns an Int
8556−+--
8557−+-- > import MFlow.Forms.Blaze.Html
8558−+-- >
8559−+-- > tableLinks :: View Html Int
8560−+-- > table ! At.style "border:1;width:20%;margin-left:auto;margin-right:auto"
8561−+-- > <<< caption << text "choose an item"
8562−+-- > ++> thead << tr << ( th << b << text "item" <> th << b << text "times chosen")
8563−+-- > ++> (tbody
8564−+-- > <<< tr ! rowspan "2" << td << linkHome
8565−+-- > ++> (tr <<< td <<< wlink IPhone (b << text "iphone") <++ td << ( b << text (fromString $ show ( cart V.! 0)))
8566−+-- > <|> tr <<< td <<< wlink IPod (b << text "ipad") <++ td << ( b << text (fromString $ show ( cart V.! 1)))
8567−+-- > <|> tr <<< td <<< wlink IPad (b << text "ipod") <++ td << ( b << text (fromString $ show ( cart V.! 2))))
8568−+-- > )
8569−+(<<<) :: (Monad m, Monoid view)
8570−+ => (view ->view)
8571−+ -> View view m a
8572−+ -> View view m a
8573−+(<<<) v form= View $ do
8574−+ FormElm f mx <- runView form
8575−+ return $ FormElm (v f) mx
8576−+
8577−+
8578−+infixr 5 <<<
8579−+
8580−+
8581−+
8582−+
8583−+
8584−+
8585−+-- | Append formatting code to a widget
8586−+--
8587−+-- @ getString "hi" '<++' H1 '<<' "hi there"@
8588−+--
8589−+-- It has a infix prority: @infixr 6@ higher than '<<<' and most other operators.
8590−+(<++) :: (Monad m, Monoid v)
8591−+ => View v m a
8592−+ -> v
8593−+ -> View v m a
8594−+(<++) form v= View $ do
8595−+ FormElm f mx <- runView form
8596−+ return $ FormElm ( f <> v) mx
8597−+
8598−+infixr 6 ++>
8599−+infixr 6 <++
8600−+-- | Prepend formatting code to a widget
8601−+--
8602−+-- @bold '<<' "enter name" '++>' 'getString' 'Nothing' @
8603−+--
8604−+-- It has a infix prority: @infixr 6@ higher than '<<<' and most other operators
8605−+(++>) :: (Monad m, Monoid view)
8606−+ => view -> View view m a -> View view m a
8607−+html ++> w = -- (html <>) <<< digest
8608−+ View $ do
8609−+ FormElm f mx <- runView w
8610−+ return $ FormElm (html <> f) mx
8611−+
8612−+
8613−+
8614−+-- | Add attributes to the topmost tag of a widget
8615−+--
8616−+-- It has a fixity @infix 8@
8617−+infixl 8 <!
8618−+widget <! attribs= View $ do
8619−+ FormElm fs mx <- runView widget
8620−+ return $ FormElm (fs `attrs` attribs) mx -- (head fs `attrs` attribs:tail fs) mx
8621−+-- case fs of
8622−+-- [hfs] -> return $ FormElm [hfs `attrs` attribs] mx
8623−+-- _ -> error $ "operator <! : malformed widget: "++ concatMap (unpack. toByteString) fs
8624−+
8625−+
8626−+-- | Is an example of login\/register validation form needed by 'userWidget'. In this case
8627−+-- the form field appears in a single line. it shows, in sequence, entries for the username,
8628−+-- password, a button for loging, a entry to repeat password necesary for registering
8629−+-- and a button for registering.
8630−+-- The user can build its own user login\/validation forms by modifying this example
8631−+--
8632−+-- @ userFormLine=
8633−+-- (User \<\$\> getString (Just \"enter user\") \<\*\> getPassword \<\+\> submitButton \"login\")
8634−+-- \<\+\> fromStr \" password again\" \+\> getPassword \<\* submitButton \"register\"
8635−+-- @
8636−+userFormLine :: (FormInput view, Functor m, Monad m)
8637−+ => View view m (Maybe (UserStr,PasswdStr), Maybe PasswdStr)
8638−+userFormLine=
8639−+ ((,) <$> getString (Just "enter user") <! [("size","5")]
8640−+ <*> getPassword <! [("size","5")]
8641−+ <** submitButton "login")
8642−+ <+> (fromStr " password again" ++> getPassword <! [("size","5")]
8643−+ <** submitButton "register")
8644−+
8645−+-- | Example of user\/password form (no validation) to be used with 'userWidget'
8646−+userLogin :: (FormInput view, Functor m, Monad m)
8647−+ => View view m (Maybe (UserStr,PasswdStr), Maybe String)
8648−+userLogin=
8649−+ ((,) <$> fromStr "Enter User: " ++> getString Nothing <! [("size","4")]
8650−+ <*> fromStr " Enter Pass: " ++> getPassword <! [("size","4")]
8651−+ <** submitButton "login")
8652−+ <+> (noWidget
8653−+ <* noWidget)
8654−+
8655−+
8656−+
8657−+-- | Empty widget that does not validate. May be used as \"empty boxes\" inside larger widgets.
8658−+--
8659−+-- It returns a non valid value.
8660−+noWidget :: (FormInput view,
8661−+ Monad m, Functor m) =>
8662−+ View view m a
8663−+noWidget= Control.Applicative.empty
8664−
8665− -- | a sinonym of noWidget that can be used in a monadic expression in the View monad does not continue
8666−-stop :: (FormInput view,
8667−- Monad m, Functor m) =>
8668−+stop :: (FormInput view,
8669−+ Monad m, Functor m) =>
8670− View view m a
8671− stop= Control.Applicative.empty
8672−-
8673−--- | Render a Show-able value and return it
8674−-wrender
8675−- :: (Monad m, Functor m, Show a, FormInput view) =>
8676−- a -> View view m a
8677−-wrender x = (fromStr $ show x) ++> return x
8678−-
8679−--- | Render raw view formatting. It is useful for displaying information.
8680−-wraw :: Monad m => view -> View view m ()
8681−-wraw x= View . return . FormElm x $ Just ()
8682−-
8683−--- To display some rendering and return a no valid value
8684−-notValid :: Monad m => view -> View view m a
8685−-notValid x= View . return $ FormElm x Nothing
8686−-
8687−--- | Wether the user is logged or is anonymous
8688−-isLogged :: MonadState (MFlowState v) m => m Bool
8689−-isLogged= do
8690−- rus <- return . tuser =<< gets mfToken
8691−- return . not $ rus == anonymous
8692−-
8693−--- | return the result if going forward
8694−---
8695−--- If the process is backtraking, it does not validate,
8696−--- in order to continue the backtracking
8697−-returnIfForward :: (Monad m, FormInput view,Functor m) => b -> View view m b
8698−-returnIfForward x = do
8699−- back <- goingBack
8700−- if back then noWidget else return x
8701−-
8702−--- | forces backtracking if the widget validates, because a previous page handle this widget response
8703−--- . This is useful for recurrent cached widgets or `absLink`s that are present in multiple pages. For example
8704−--- in the case of menus or common options. The active elements of this widget must be cached with no timeout.
8705−-retry :: Monad m => View v m a -> View v m ()
8706−-retry w = View $ do
8707−- FormElm v mx <- runView w
8708−- when (isJust mx) $ modify $ \st -> st{inSync = False}
8709−- return $ FormElm v Nothing
8710−-
8711−--- | It creates a widget for user login\/registering. If a user name is specified
8712−--- in the first parameter, it is forced to login\/password as this specific user.
8713−--- If this user was already logged, the widget return the user without asking.
8714−--- If the user press the register button, the new user-password is registered and the
8715−--- user logged.
8716−-
8717−-userWidget :: ( MonadIO m, Functor m
8718−- , FormInput view)
8719−- => Maybe String
8720−- -> View view m (Maybe (UserStr,PasswdStr), Maybe String)
8721−- -> View view m String
8722−-userWidget muser formuser = userWidget' muser formuser login1
8723−-
8724−--- | Uses 4 different keys to encrypt the 4 parts of a MFlow cookie.
8725−-
8726−-paranoidUserWidget muser formuser = userWidget' muser formuser paranoidLogin1
8727−-
8728−--- | Uses a single key to encrypt the MFlow cookie.
8729−-
8730−-encryptedUserWidget muser formuser = userWidget' muser formuser encryptedLogin1
8731−-
8732−-userWidget' muser formuser login1Func = do
8733−- user <- getCurrentUser
8734−- if muser== Just user || isNothing muser && user/= anonymous
8735−- then returnIfForward user
8736−- else formuser `validate` val muser `wcallback` login1Func
8737−- where
8738−- val _ (Nothing,_) = return . Just $ fromStr "Plese fill in the user/passwd to login, or user/passwd/passwd to register"
8739−-
8740−- val mu (Just us, Nothing)=
8741−- if isNothing mu || isJust mu && fromJust mu == fst us
8742−- then userValidate us
8743−- else return . Just $ fromStr "This user has no permissions for this task"
8744−-
8745−- val mu (Just us, Just p)=
8746−- if isNothing mu || isJust mu && fromJust mu == fst us
8747−- then if Data.List.length p > 0 && snd us== p
8748−- then return Nothing
8749−- else return . Just $ fromStr "The passwords do not match"
8750−- else return . Just $ fromStr "wrong user for the operation"
8751−-
8752−--- val _ _ = return . Just $ fromStr "Please fill in the fields for login or register"
8753−-
8754−-login1
8755−- :: (MonadIO m, MonadState (MFlowState view) m) =>
8756−- (Maybe (UserStr, PasswdStr), Maybe t) -> m UserStr
8757−-login1 uname = login1' uname login
8758−-
8759−-paranoidLogin1 uname = login1' uname paranoidLogin
8760−-
8761−-encryptedLogin1 uname = login1' uname encryptedLogin
8762−-
8763−-login1' (Just (uname,_), Nothing) loginFunc= loginFunc uname >> return uname
8764−-login1' (Just us@(u,p), Just _) loginFunc= do -- register button pressed
8765−- userRegister u p
8766−- loginFunc u
8767−- return u
8768−-
8769−--- | change the user
8770−---
8771−--- It is supposed that the user has been validated
8772−-
8773−-login uname = login' uname setCookie
8774−-
8775−-paranoidLogin uname = login' uname setParanoidCookie
8776−-
8777−-encryptedLogin uname = login' uname setEncryptedCookie
8778−-
8779−-login'
8780−- :: (Num a1, S.IsString a, MonadIO m,
8781−- MonadState (MFlowState view) m) =>
8782−- String -> (String -> String -> a -> Maybe a1 -> m ()) -> m ()
8783−-login' uname setCookieFunc = do
8784−- back <- goingBack
8785−- if back then return () else do
8786−- st <- get
8787−- let t = mfToken st
8788−- u = tuser t
8789−- when (u /= uname) $ do
8790−- let t'= t{tuser= uname}
8791−- -- moveState (twfname t) t t'
8792−- put st{mfToken= t'}
8793−- liftIO $ deleteTokenInList t
8794−- liftIO $ addTokenToList t'
8795−- setCookieFunc cookieuser uname "/" (Just $ 365*24*60*60)
8796−-
8797−-logout = logout' setCookie
8798−-
8799−-paranoidLogout = logout' setParanoidCookie
8800−-
8801−-encryptedLogout = logout' setEncryptedCookie
8802−-
8803−-
8804−--- | logout. The user is reset to the `anonymous` user
8805−-logout'
8806−- :: (Num a1,S.IsString a, MonadIO m,
8807−- MonadState (MFlowState view) m) =>
8808−- (String -> [Char] -> a -> Maybe a1 -> m ()) -> m ()
8809−+
8810−+-- | Render a Show-able value and return it
8811−+wrender
8812−+ :: (Monad m, Functor m, Show a, FormInput view) =>
8813−+ a -> View view m a
8814−+wrender x = (fromStr $ show x) ++> return x
8815−+
8816−+-- | Render raw view formatting. It is useful for displaying information.
8817−+wraw :: Monad m => view -> View view m ()
8818−+wraw x= View . return . FormElm x $ Just ()
8819−+
8820−+-- To display some rendering and return a no valid value
8821−+notValid :: Monad m => view -> View view m a
8822−+notValid x= View . return $ FormElm x Nothing
8823−+
8824−+-- | Wether the user is logged or is anonymous
8825−+isLogged :: MonadState (MFlowState v) m => m Bool
8826−+isLogged= do
8827−+ rus <- return . tuser =<< gets mfToken
8828−+ return . not $ rus == anonymous
8829−+
8830−+-- | return the result if going forward
8831−+--
8832−+-- If the process is backtraking, it does not validate,
8833−+-- in order to continue the backtracking
8834−+returnIfForward :: (Monad m, FormInput view,Functor m) => b -> View view m b
8835−+returnIfForward x = do
8836−+ back <- goingBack
8837−+ if back then noWidget else return x
8838−+
8839−+-- | forces backtracking if the widget validates, because a previous page handle this widget response
8840−+-- . This is useful for recurrent cached widgets or `absLink`s that are present in multiple pages. For example
8841−+-- in the case of menus or common options. The active elements of this widget must be cached with no timeout.
8842−+retry :: Monad m => View v m a -> View v m ()
8843−+retry w = View $ do
8844−+ FormElm v mx <- runView w
8845−+ when (isJust mx) $ modify $ \st -> st{inSync = False}
8846−+ return $ FormElm v Nothing
8847−+
8848−+-- | It creates a widget for user login\/registering. If a user name is specified
8849−+-- in the first parameter, it is forced to login\/password as this specific user.
8850−+-- If this user was already logged, the widget return the user without asking.
8851−+-- If the user press the register button, the new user-password is registered and the
8852−+-- user logged.
8853−+
8854−+userWidget :: ( MonadIO m, Functor m
8855−+ , FormInput view)
8856−+ => Maybe String
8857−+ -> View view m (Maybe (UserStr,PasswdStr), Maybe String)
8858−+ -> View view m String
8859−+userWidget muser formuser = userWidget' muser formuser login1
8860−+
8861−+-- | Uses 4 different keys to encrypt the 4 parts of a MFlow cookie.
8862−+
8863−+paranoidUserWidget muser formuser = userWidget' muser formuser paranoidLogin1
8864−+
8865−+-- | Uses a single key to encrypt the MFlow cookie.
8866−+
8867−+encryptedUserWidget muser formuser = userWidget' muser formuser encryptedLogin1
8868−+
8869−+userWidget' muser formuser login1Func = do
8870−+ user <- getCurrentUser
8871−+ if muser== Just user || isNothing muser && user/= anonymous
8872−+ then returnIfForward user
8873−+ else formuser `validate` val muser `wcallback` login1Func
8874−+ where
8875−+ val _ (Nothing,_) = return . Just $ fromStr "Plese fill in the user/passwd to login, or user/passwd/passwd to register"
8876−+
8877−+ val mu (Just us, Nothing)=
8878−+ if isNothing mu || isJust mu && fromJust mu == fst us
8879−+ then userValidate us
8880−+ else return . Just $ fromStr "This user has no permissions for this task"
8881−+
8882−+ val mu (Just us, Just p)=
8883−+ if isNothing mu || isJust mu && fromJust mu == fst us
8884−+ then if Data.List.length p > 0 && snd us== p
8885−+ then return Nothing
8886−+ else return . Just $ fromStr "The passwords do not match"
8887−+ else return . Just $ fromStr "wrong user for the operation"
8888−+
8889−+-- val _ _ = return . Just $ fromStr "Please fill in the fields for login or register"
8890−+
8891−+login1
8892−+ :: (MonadIO m, MonadState (MFlowState view) m) =>
8893−+ (Maybe (UserStr, PasswdStr), Maybe t) -> m UserStr
8894−+login1 uname = login1' uname login
8895−+
8896−+paranoidLogin1 uname = login1' uname paranoidLogin
8897−+
8898−+encryptedLogin1 uname = login1' uname encryptedLogin
8899−+
8900−+login1' (Just (uname,_), Nothing) loginFunc= loginFunc uname >> return uname
8901−+login1' (Just us@(u,p), Just _) loginFunc= do -- register button pressed
8902−+ userRegister u p
8903−+ loginFunc u
8904−+ return u
8905−+
8906−+-- | change the user
8907−+--
8908−+-- It is supposed that the user has been validated
8909−+
8910−+login uname = login' uname setCookie
8911−+
8912−+paranoidLogin uname = login' uname setParanoidCookie
8913−+
8914−+encryptedLogin uname = login' uname setEncryptedCookie
8915−+
8916−+login'
8917−+ :: (Num a1, S.IsString a, MonadIO m,
8918−+ MonadState (MFlowState view) m) =>
8919−+ String -> (String -> String -> a -> Maybe a1 -> m ()) -> m ()
8920−+login' uname setCookieFunc = do
8921−+ back <- goingBack
8922−+ if back then return () else do
8923−+ st <- get
8924−+ let t = mfToken st
8925−+ u = tuser t
8926−+ when (u /= uname) $ do
8927−+ let t'= t{tuser= uname}
8928−+ -- moveState (twfname t) t t'
8929−+ put st{mfToken= t'}
8930−+ liftIO $ deleteTokenInList t
8931−+ liftIO $ addTokenToList t'
8932−+ setCookieFunc cookieuser uname "/" (Just $ 365*24*60*60)
8933−+
8934−+logout = logout' setCookie
8935−+
8936−+paranoidLogout = logout' setParanoidCookie
8937−+
8938−+encryptedLogout = logout' setEncryptedCookie
8939−+
8940−+
8941−+-- | logout. The user is reset to the `anonymous` user
8942−+logout'
8943−+ :: (Num a1,S.IsString a, MonadIO m,
8944−+ MonadState (MFlowState view) m) =>
8945−+ (String -> [Char] -> a -> Maybe a1 -> m ()) -> m ()
8946− logout' setCookieFunc = do
8947−- public
8948−- back <- goingBack
8949−- if back then return () else do
8950−- st <- get
8951−- let t = mfToken st
8952−- t'= t{tuser= anonymous}
8953−- when (tuser t /= anonymous) $ do
8954−--- moveState (twfname t) t t'
8955−- put st{mfToken= t'}
8956−--- liftIO $ deleteTokenInList t
8957−- liftIO $ addTokenToList t'
8958−- setCookieFunc cookieuser anonymous "/" (Just $ -1000)
8959−-
8960−--- | If not logged, perform login. otherwise return the user
8961−---
8962−--- @getUserSimple= getUser Nothing userFormLine@
8963−-getUserSimple :: ( FormInput view, Typeable view)
8964−- => FlowM view IO String
8965−-getUserSimple= getUser Nothing userFormLine
8966−-
8967−--- | Very basic user authentication. The user is stored in a cookie.
8968−--- it looks for the cookie. If no cookie, it ask to the user for a `userRegister`ed
8969−--- user-password combination.
8970−--- The user-password combination is only asked if the user has not logged already
8971−--- otherwise, the stored username is returned.
8972−---
8973−--- @getUser mu form= ask $ userWidget mu form@
8974−-getUser :: ( FormInput view, Typeable view)
8975−- => Maybe String
8976−- -> View view IO (Maybe (UserStr,PasswdStr), Maybe String)
8977−- -> FlowM view IO String
8978−-getUser mu form= ask $ userWidget mu form
8979−-
8980−--- | Authentication against `userRegister`ed users.
8981−--- to be used with `validate`
8982−-userValidate :: (FormInput view,MonadIO m) => (UserStr,PasswdStr) -> m (Maybe view)
8983−-userValidate (u,p) = liftIO $ do
8984−- Auth _ val <- getAuthMethod
8985−- val u p >>= return . fmap fromStr
8986−-
8987−-
8988−-
8989−--- | for compatibility with the same procedure in 'MFLow.Forms.Test.askt'.
8990−--- This is the non testing version
8991−---
8992−--- > askt v w= ask w
8993−---
8994−--- hide one or the other
8995−-askt :: FormInput v => (Int -> a) -> View v IO a -> FlowM v IO a
8996−-askt v w = ask w
8997−-
8998−-
8999−--- | It is the way to interact with the user.
9000−--- It takes a widget and return the input result. If the widget is not validated (return @Nothing@)
9001−--- , the page is presented again
9002−---
9003−--- If the environment or the URL has the parameters being looked at, maybe as a result of a previous interaction,
9004−--- it will not ask to the user and return the result.
9005−--- To force asking in any case, add an `clearEnv` statement before.
9006−--- It also handles ajax requests
9007−---
9008−--- 'ask' also synchronizes the execution of the flow with the user page navigation by
9009−-
9010−--- * Backtracking (invoking previous 'ask' staement in the flow) when detecting mismatches between
9011−--- get and post parameters and what is expected by the widgets
9012−--- until a total or partial match is found.
9013−---
9014−--- * Advancing in the flow by matching a single requests with one or more sucessive ask statements
9015−---
9016−--- Backtracking and advancing can occur in a single request, so the flow in any state can reach any
9017−--- other state in the flow if the request has the required parameters.
9018−-ask :: (FormInput view) =>
9019−- View view IO a -> FlowM view IO a
9020−+ public
9021−+ back <- goingBack
9022−+ if back then return () else do
9023−+ st <- get
9024−+ let t = mfToken st
9025−+ t'= t{tuser= anonymous}
9026−+ when (tuser t /= anonymous) $ do
9027−+-- moveState (twfname t) t t'
9028−+ put st{mfToken= t'}
9029−+-- liftIO $ deleteTokenInList t
9030−+ liftIO $ addTokenToList t'
9031−+ setCookieFunc cookieuser anonymous "/" (Just $ -1000)
9032−+
9033−+-- | If not logged, perform login. otherwise return the user
9034−+--
9035−+-- @getUserSimple= getUser Nothing userFormLine@
9036−+getUserSimple :: ( FormInput view, Typeable view)
9037−+ => FlowM view IO String
9038−+getUserSimple= getUser Nothing userFormLine
9039−+
9040−+-- | Very basic user authentication. The user is stored in a cookie.
9041−+-- it looks for the cookie. If no cookie, it ask to the user for a `userRegister`ed
9042−+-- user-password combination.
9043−+-- The user-password combination is only asked if the user has not logged already
9044−+-- otherwise, the stored username is returned.
9045−+--
9046−+-- @getUser mu form= ask $ userWidget mu form@
9047−+getUser :: ( FormInput view, Typeable view)
9048−+ => Maybe String
9049−+ -> View view IO (Maybe (UserStr,PasswdStr), Maybe String)
9050−+ -> FlowM view IO String
9051−+getUser mu form= ask $ userWidget mu form
9052−+
9053−+-- | Authentication against `userRegister`ed users.
9054−+-- to be used with `validate`
9055−+userValidate :: (FormInput view,MonadIO m) => (UserStr,PasswdStr) -> m (Maybe view)
9056−+userValidate (u,p) = liftIO $ do
9057−+ Auth _ val <- getAuthMethod
9058−+ val u p >>= return . fmap fromStr
9059−+
9060−+
9061−+
9062−+-- | for compatibility with the same procedure in 'MFLow.Forms.Test.askt'.
9063−+-- This is the non testing version
9064−+--
9065−+-- > askt v w= ask w
9066−+--
9067−+-- hide one or the other
9068−+askt :: FormInput v => (Int -> a) -> View v IO a -> FlowM v IO a
9069−+askt v w = ask w
9070−+
9071−+
9072−+-- | It is the way to interact with the user.
9073−+-- It takes a widget and return the input result. If the widget is not validated (return @Nothing@)
9074−+-- , the page is presented again
9075−+--
9076−+-- If the environment or the URL has the parameters being looked at, maybe as a result of a previous interaction,
9077−+-- it will not ask to the user and return the result.
9078−+-- To force asking in any case, add an `clearEnv` statement before.
9079−+-- It also handles ajax requests
9080−+--
9081−+-- 'ask' also synchronizes the execution of the flow with the user page navigation by
9082−+
9083−+-- * Backtracking (invoking previous 'ask' staement in the flow) when detecting mismatches between
9084−+-- get and post parameters and what is expected by the widgets
9085−+-- until a total or partial match is found.
9086−+--
9087−+-- * Advancing in the flow by matching a single requests with one or more sucessive ask statements
9088−+--
9089−+-- Backtracking and advancing can occur in a single request, so the flow in any state can reach any
9090−+-- other state in the flow if the request has the required parameters.
9091−+ask :: (FormInput view) =>
9092−+ View view IO a -> FlowM view IO a
9093− ask w = do
9094−- resetCachePolicy
9095−+ resetCachePolicy
9096− st1 <- get >>= \s -> return s{mfSequence=
9097− let seq= mfSequence s in
9098− if seq ==inRecovery then 0 else seq
9099−- ,mfHttpHeaders =[],mfAutorefresh= False }
9100−- if not . null $ mfTrace st1 then fail "" else do
9101−- -- AJAX
9102−- let env= mfEnv st1
9103−- mv1= lookup "ajax" env
9104−- majax1= mfAjax st1
9105−-
9106−- case (majax1,mv1,M.lookup (fromJust mv1)(fromJust majax1), lookup "val" env) of
9107−- (Just ajaxl,Just v1,Just f, Just v2) -> do
9108−- FlowM . lift $ (unsafeCoerce f) v2
9109−- FlowM $ lift nextMessage
9110−- ask w
9111−- -- END AJAX
9112−-
9113−+ ,mfHttpHeaders =[],mfAutorefresh= False }
9114−+ if not . null $ mfTrace st1 then fail "" else do
9115−+ -- AJAX
9116−+ let env= mfEnv st1
9117−+ mv1= lookup "ajax" env
9118−+ majax1= mfAjax st1
9119−+
9120−+ case (majax1,mv1,M.lookup (fromJust mv1)(fromJust majax1), lookup "val" env) of
9121−+ (Just ajaxl,Just v1,Just f, Just v2) -> do
9122−+ FlowM . lift $ (unsafeCoerce f) v2
9123−+ FlowM $ lift nextMessage
9124−+ ask w
9125−+ -- END AJAX
9126−+
9127− _ -> do
9128−
9129− -- mfPagePath : contains the REST path of the page.
9130−@@ -1044,252 +1052,250 @@
9131− -- if exist and it is not prefix of the current path being navigated to, backtrack
9132− else if not $ pagepath `isPrefixOf` mfPath st1 then fail "" -- !> ("pagepath fail with "++ show (mfPath st1))
9133− else do
9134−-
9135−- let st= st1{needForm= NoElems, inSync= False, mfRequirements= [], linkMatched= False}
9136−- put st
9137−- FormElm forms mx <- FlowM . lift $ runView w
9138−- setCachePolicy
9139−- st' <- get
9140−- if notSyncInAction st' then put st'{notSyncInAction=False}>> ask w
9141−-
9142−- else
9143−- case mx of
9144−- Just x -> do
9145−- put st'{newAsk= True, mfEnv=[]}
9146−- breturn x -- !> ("BRETURN "++ show (mfPagePath st') )
9147−-
9148−- Nothing ->
9149−- if not (inSync st') && not (newAsk st')
9150−- -- !> ("insync="++show (inSync st'))
9151−- -- !> ("newask="++show (newAsk st'))
9152−- then fail "" -- !> "FAIL sync"
9153−- else if mfAutorefresh st' then do
9154−- resetState st st' -- !> ("EN AUTOREFRESH" ++ show [ mfPagePath st,mfPath st,mfPagePath st'])
9155−+
9156−+ let st= st1{needForm= NoElems, inSync= False, linkMatched= False
9157−+ ,mfRequirements= []
9158−+ ,mfInstalledScripts= if newAsk st1 then [] else mfInstalledScripts st1}
9159−+ put st
9160−+ FormElm forms mx <- FlowM . lift $ runView w
9161−+ setCachePolicy
9162−+ st' <- get
9163−+ if notSyncInAction st' then put st'{notSyncInAction=False}>> ask w
9164−+
9165−+ else
9166−+ case mx of
9167−+ Just x -> do
9168−+ put st'{newAsk= True, mfEnv=[]}
9169−+ breturn x -- !> ("BRETURN "++ show (mfPagePath st') )
9170−+
9171−+ Nothing ->
9172−+ if not (inSync st') && not (newAsk st')
9173−+ -- !> ("insync="++show (inSync st'))
9174−+ -- !> ("newask="++show (newAsk st'))
9175−+ then fail "" -- !> "FAIL sync"
9176−+ else if mfAutorefresh st' then do
9177−+ resetState st st' -- !> ("EN AUTOREFRESH" ++ show [ mfPagePath st,mfPath st,mfPagePath st'])
9178− -- modify $ \st -> st{mfPagePath=mfPagePath st'} !> "REPEAT"
9179−- FlowM $ lift nextMessage
9180−- ask w
9181−- else do
9182−+ FlowM $ lift nextMessage
9183−+ ask w
9184−+ else do
9185− reqs <- FlowM $ lift installAllRequirements -- !> "REPEAT"
9186−-
9187−- let header= mfHeader st'
9188−- t= mfToken st'
9189−- cont <- case (needForm1 st') of
9190−- True -> do
9191−- frm <- formPrefix st' forms False -- !> ("formPrefix="++ show(mfPagePath st'))
9192−- return . header $ reqs <> frm
9193−- _ -> return . header $ reqs <> forms
9194−-
9195−- let HttpData ctype c s= toHttpData cont
9196−- liftIO . sendFlush t $ HttpData (ctype ++ mfHttpHeaders st') (mfCookies st' ++ c) s
9197−-
9198−-
9199−- resetState st st'
9200−+ st' <- get
9201−+ let header= mfHeader st'
9202−+ t= mfToken st'
9203−+ cont <- case (needForm st') of
9204−+ HasElems -> do
9205−+ frm <- formPrefix st' forms False -- !> ("formPrefix="++ show(mfPagePath st'))
9206−+ return . header $ reqs <> frm
9207−+ _ -> return . header $ reqs <> forms
9208−+
9209−+ let HttpData ctype c s= toHttpData cont
9210−+ liftIO . sendFlush t $ HttpData (ctype ++ mfHttpHeaders st') (mfCookies st' ++ c) s
9211−+
9212−+ resetState st st'
9213− FlowM $ lift nextMessage -- !> "NEXTMESSAGE"
9214−- ask w
9215−- where
9216−- resetState st st'=
9217−- put st{mfCookies=[]
9218−- -- ,mfHttpHeaders=[]
9219−- ,newAsk= False
9220−- ,mfToken= mfToken st'
9221−- ,mfPageFlow= mfPageFlow st'
9222−- ,mfAjax= mfAjax st'
9223−--- ,mfSeqCache= mfSeqCache st'
9224−- ,mfData= mfData st' }
9225−-
9226−-
9227−--- | A synonym of ask.
9228−---
9229−--- Maybe more appropiate for pages with long interactions with the user
9230−--- while the result has little importance.
9231−-page
9232−- :: (FormInput view) =>
9233−- View view IO a -> FlowM view IO a
9234−-page= ask
9235−-
9236−-nextMessage :: MonadIO m => WState view m ()
9237−-nextMessage = do
9238−- st <- get
9239−- let t= mfToken st
9240−- t1= mfkillTime st
9241−- t2= mfSessionTime st
9242−- msg <- liftIO ( receiveReqTimeout t1 t2 t)
9243−- let req= getParams msg
9244−- env= updateParams inPageFlow (mfEnv st) req -- !> ("PAGEFLOW="++ show inPageFlow)
9245−- npath= pwfPath msg
9246−- path= mfPath st
9247−- inPageFlow= mfPagePath st `isPrefixOf` npath
9248−-
9249−- put st{ mfPath= npath
9250−-
9251−-
9252−- , mfPageFlow= inPageFlow
9253−-
9254−- , mfEnv= env }
9255−-
9256−-
9257−- where
9258−-
9259−- comparePaths _ n [] xs= n
9260−- comparePaths o n _ [] = o
9261−- comparePaths o n (v:path) (v': npath) | v== v' = comparePaths o (n+1)path npath
9262−- | otherwise= n
9263−-
9264−- updateParams :: Bool -> Params -> Params -> Params
9265−- updateParams False _ req= req
9266−- updateParams True env req=
9267−- let params= takeWhile isparam env
9268−- fs= fst $ head req
9269−- parms= (case findIndex (\p -> fst p == fs) params of
9270−- Nothing -> params
9271−- Just i -> Data.List.take i params)
9272−- ++ req
9273−- in parms
9274−--- !> "IN PAGE FLOW" !> ("parms=" ++ show parms )
9275−--- !> ("env=" ++ show env)
9276−--- !> ("req=" ++ show req)
9277−-
9278−-
9279−-
9280−-isparam ('p': r:_,_)= isNumber r
9281−-isparam ('c': r:_,_)= isNumber r
9282−-isparam _= False
9283−-
9284−--- | Creates a stateless flow (see `stateless`) whose behaviour is defined as a widget. It is a
9285−--- higuer level form of the latter
9286−-wstateless
9287−- :: (Typeable view, FormInput view) =>
9288−- View view IO () -> Flow
9289−-wstateless w = runFlow . transientNav . ask $ w **> (stop `asTypeOf` w)
9290−-
9291−-
9292−-
9293−-
9294−-
9295−-
9296−--- | Wrap a widget with form element within a form-action element.
9297−--- Usually this is not necessary since this wrapping is done automatically by the @Wiew@ monad, unless
9298−--- there are more than one form in the page.
9299−-wform :: (Monad m, FormInput view)
9300−- => View view m b -> View view m b
9301−-wform x = View $ do
9302−- FormElm form mr <- (runView $ x )
9303−- st <- get
9304−- form1 <- formPrefix st form True
9305−- put st{needForm=HasForm}
9306−- return $ FormElm form1 mr
9307−-
9308−-
9309−-
9310−-
9311−-resetButton :: (FormInput view, Monad m) => String -> View view m ()
9312−+ ask w
9313−+ where
9314−+ resetState st st'=
9315−+ put st{mfCookies=[]
9316−+ ,mfInstalledScripts= mfInstalledScripts st'
9317−+ ,newAsk= False
9318−+ ,mfToken= mfToken st'
9319−+ ,mfPageFlow= mfPageFlow st'
9320−+ ,mfAjax= mfAjax st'
9321−+ ,mfData= mfData st' }
9322−+
9323−+
9324−+-- | A synonym of ask.
9325−+--
9326−+-- Maybe more appropiate for pages with long interactions with the user
9327−+-- while the result has little importance.
9328−+page
9329−+ :: (FormInput view) =>
9330−+ View view IO a -> FlowM view IO a
9331−+page= ask
9332−+
9333−+nextMessage :: MonadIO m => WState view m ()
9334−+nextMessage = do
9335−+ st <- get
9336−+ let t= mfToken st
9337−+ t1= mfkillTime st
9338−+ t2= mfSessionTime st
9339−+ msg <- liftIO ( receiveReqTimeout t1 t2 t)
9340−+ let req= getParams msg
9341−+ env= updateParams inPageFlow (mfEnv st) req -- !> ("PAGEFLOW="++ show inPageFlow)
9342−+ npath= pwfPath msg
9343−+ path= mfPath st
9344−+ inPageFlow= mfPagePath st `isPrefixOf` npath
9345−+
9346−+ put st{ mfPath= npath
9347−+ , mfPageFlow= inPageFlow
9348−+ , mfEnv= env }
9349−+
9350−+ where
9351−+
9352−+-- comparePaths _ n [] xs= n
9353−+-- comparePaths o n _ [] = o
9354−+-- comparePaths o n (v:path) (v': npath) | v== v' = comparePaths o (n+1)path npath
9355−+-- | otherwise= n
9356−+
9357−+ updateParams :: Bool -> Params -> Params -> Params
9358−+ updateParams False _ req= req
9359−+ updateParams True env req=
9360−+ let params= takeWhile isparam req -- env
9361−+ fs= fst $ head req
9362−+ parms= (case findIndex (\p -> fst p == fs) params of
9363−+ Nothing -> params
9364−+ Just i -> Data.List.take i params)
9365−+ ++ req
9366−+ in parms
9367−+-- !> "IN PAGE FLOW" !> ("parms=" ++ show parms )
9368−+-- !> ("env=" ++ show env)
9369−+-- !> ("req=" ++ show req)
9370−+
9371−+
9372−+
9373−+isparam ('p': r:_,_)= isNumber r
9374−+isparam ('c': r:_,_)= isNumber r
9375−+isparam _= False
9376−+
9377−+-- | Creates a stateless flow (see `stateless`) whose behaviour is defined as a widget. It is a
9378−+-- higuer level form of the latter
9379−+wstateless
9380−+ :: (Typeable view, FormInput view) =>
9381−+ View view IO () -> Flow
9382−+wstateless w = runFlow . transientNav . ask $ w **> (stop `asTypeOf` w)
9383−+
9384−+
9385−+
9386−+
9387−+
9388−+
9389−+-- | Wrap a widget with form element within a form-action element.
9390−+-- Usually this is not necessary since this wrapping is done automatically by the @Wiew@ monad, unless
9391−+-- there are more than one form in the page.
9392−+wform :: (Monad m, FormInput view)
9393−+ => View view m b -> View view m b
9394−+wform= insertForm
9395−+--wform x = View $ do
9396−+-- FormElm form mr <- (runView $ x )
9397−+-- st <- get
9398−+-- form1 <- formPrefix st form True
9399−+-- put st{needForm=HasForm}
9400−+-- return $ FormElm form1 mr
9401−+
9402−+
9403−+
9404−+
9405−+resetButton :: (FormInput view, Monad m) => String -> View view m ()
9406− resetButton label= View $ return $ FormElm (finput "reset" "reset" label False Nothing)
9407−- $ Just ()
9408−-
9409−-submitButton :: (FormInput view, Monad m) => String -> View view m String
9410−-submitButton label= getParam Nothing "submit" $ Just label
9411−-
9412−-newtype AjaxSessionId= AjaxSessionId String deriving Typeable
9413−-
9414−--- | Install the server code and return the client code for an AJAX interaction.
9415−--- It is very lightweight, It does no t need jQuery.
9416−---
9417−--- This example increases the value of a text box each time the box is clicked
9418−---
9419−--- > ask $ do
9420−--- > let elemval= "document.getElementById('text1').value"
9421−--- > ajaxc <- ajax $ \n -> return $ elemval <> "='" <> B.pack(show(read n +1)) <> "'"
9422−--- > b << text "click the box"
9423−--- > ++> getInt (Just 0) <! [("id","text1"),("onclick", ajaxc elemval)]
9424−-ajax :: (MonadIO m, FormInput v)
9425−- => (String -> View v m ByteString) -- ^ user defined procedure, executed in the server.Receives the value of the javascript expression and must return another javascript expression that will be executed in the web browser
9426−- -> View v m (String -> String) -- ^ returns a function that accept a javascript expression and return a javascript event handler expression that invokes the ajax server procedure
9427−-ajax f = do
9428−- requires[JScript ajaxScript]
9429−- t <- gets mfToken
9430−- id <- genNewId
9431−- installServerControl id $ \x-> do
9432−- setSessionData $ AjaxSessionId id
9433−- r <- f x
9434−- liftIO $ sendFlush t (HttpData [("Content-Type", "text/plain")][] r )
9435−- return ()
9436−-
9437−-installServerControl :: (FormInput v,MonadIO m) => String -> (String -> View v m ()) -> View v m (String -> String)
9438−-installServerControl id f= do
9439−- t <- gets mfToken
9440−- st <- get
9441−- let ajxl = fromMaybe M.empty $ mfAjax st
9442−- let ajxl'= M.insert id (unsafeCoerce f ) ajxl
9443−- put st{mfAjax=Just ajxl'}
9444−- return $ \param -> "doServer("++"'" ++ twfname t ++"','"++id++"',"++ param++")"
9445−-
9446−--- | Send the javascript expression, generated by the procedure parameter as a ByteString, execute it in the browser and the result is returned back
9447−---
9448−--- The @ajaxSend@ invocation must be inside a ajax procedure or else a /No ajax session set/ error will be produced
9449−-ajaxSend
9450−- :: (Read a,Monoid v, MonadIO m) => View v m ByteString -> View v m a
9451−-ajaxSend cmd= View $ do
9452−- AjaxSessionId id <- getSessionData `onNothing` error "no AjaxSessionId set"
9453−- env <- getEnv
9454−- t <- getToken
9455−- case (lookup "ajax" $ env, lookup "val" env) of
9456−- (Nothing,_) -> return $ FormElm mempty Nothing
9457−- (Just id, Just _) -> do
9458−- FormElm __ (Just str) <- runView cmd
9459−- liftIO $ sendFlush t $ HttpData [("Content-Type", "text/plain")][] $ str <> readEvalLoop t id "''"
9460−- nextMessage
9461−- env <- getEnv
9462−- case (lookup "ajax" $ env,lookup "val" env) of
9463−- (Nothing,_) -> return $ FormElm mempty Nothing
9464−- (Just id, Just v2) -> do
9465−- return $ FormElm mempty . Just $ read v2
9466−- where
9467−- readEvalLoop t id v = "doServer('"<> fromString (twfname t)<>"','"<> fromString id<>"',"<>v<>");" :: ByteString
9468−-
9469−--- | Like @ajaxSend@ but the result is ignored
9470−-ajaxSend_
9471−- :: (MonadIO m, Monoid v) => View v m ByteString -> View v m ()
9472−-ajaxSend_ = ajaxSend
9473−-
9474−-wlabel
9475−- :: (Monad m, FormInput view) => view -> View view m a -> View view m a
9476−-wlabel str w = do
9477−- id <- genNewId
9478−- ftag "label" str `attrs` [("for",id)] ++> w <! [("id",id)]
9479−-
9480−-
9481−+ $ Just ()
9482−+
9483−+submitButton :: (FormInput view, Monad m) => String -> View view m String
9484−+submitButton label= getParam Nothing "submit" $ Just label
9485−+
9486−+newtype AjaxSessionId= AjaxSessionId String deriving Typeable
9487−+
9488−+-- | Install the server code and return the client code for an AJAX interaction.
9489−+-- It is very lightweight, It does no t need jQuery.
9490−+--
9491−+-- This example increases the value of a text box each time the box is clicked
9492−+--
9493−+-- > ask $ do
9494−+-- > let elemval= "document.getElementById('text1').value"
9495−+-- > ajaxc <- ajax $ \n -> return $ elemval <> "='" <> B.pack(show(read n +1)) <> "'"
9496−+-- > b << text "click the box"
9497−+-- > ++> getInt (Just 0) <! [("id","text1"),("onclick", ajaxc elemval)]
9498−+ajax :: (MonadIO m, FormInput v)
9499−+ => (String -> View v m ByteString) -- ^ user defined procedure, executed in the server.Receives the value of the javascript expression and must return another javascript expression that will be executed in the web browser
9500−+ -> View v m (String -> String) -- ^ returns a function that accept a javascript expression and return a javascript event handler expression that invokes the ajax server procedure
9501−+ajax f = do
9502−+ requires[JScript ajaxScript]
9503−+ t <- gets mfToken
9504−+ id <- genNewId
9505−+ installServerControl id $ \x-> do
9506−+ setSessionData $ AjaxSessionId id
9507−+ r <- f x
9508−+ liftIO $ sendFlush t (HttpData [("Content-Type", "text/plain")][] r )
9509−+ return ()
9510−+
9511−+installServerControl :: (FormInput v,MonadIO m) => String -> (String -> View v m ()) -> View v m (String -> String)
9512−+installServerControl id f= do
9513−+ t <- gets mfToken
9514−+ st <- get
9515−+ let ajxl = fromMaybe M.empty $ mfAjax st
9516−+ let ajxl'= M.insert id (unsafeCoerce f ) ajxl
9517−+ put st{mfAjax=Just ajxl'}
9518−+ return $ \param -> "doServer("++"'" ++ twfname t ++"','"++id++"',"++ param++")"
9519−+
9520−+-- | Send the javascript expression, generated by the procedure parameter as a ByteString, execute it in the browser and the result is returned back
9521−+--
9522−+-- The @ajaxSend@ invocation must be inside a ajax procedure or else a /No ajax session set/ error will be produced
9523−+ajaxSend
9524−+ :: (Read a,Monoid v, MonadIO m) => View v m ByteString -> View v m a
9525−+ajaxSend cmd= View $ do
9526−+ AjaxSessionId id <- getSessionData `onNothing` error "no AjaxSessionId set"
9527−+ env <- getEnv
9528−+ t <- getToken
9529−+ case (lookup "ajax" $ env, lookup "val" env) of
9530−+ (Nothing,_) -> return $ FormElm mempty Nothing
9531−+ (Just id, Just _) -> do
9532−+ FormElm __ (Just str) <- runView cmd
9533−+ liftIO $ sendFlush t $ HttpData [("Content-Type", "text/plain")][] $ str <> readEvalLoop t id "''"
9534−+ nextMessage
9535−+ env <- getEnv
9536−+ case (lookup "ajax" $ env,lookup "val" env) of
9537−+ (Nothing,_) -> return $ FormElm mempty Nothing
9538−+ (Just id, Just v2) -> do
9539−+ return $ FormElm mempty . Just $ read v2
9540−+ where
9541−+ readEvalLoop t id v = "doServer('"<> fromString (twfname t)<>"','"<> fromString id<>"',"<>v<>");" :: ByteString
9542−+
9543−+-- | Like @ajaxSend@ but the result is ignored
9544−+ajaxSend_
9545−+ :: (MonadIO m, Monoid v) => View v m ByteString -> View v m ()
9546−+ajaxSend_ = ajaxSend
9547−+
9548−+wlabel
9549−+ :: (Monad m, FormInput view) => view -> View view m a -> View view m a
9550−+wlabel str w = do
9551−+ id <- genNewId
9552−+ ftag "label" str `attrs` [("for",id)] ++> w <! [("id",id)]
9553−+
9554−+
9555− -- | Creates a link to a the next step within the flow.
9556− -- A link can be composed with other widget elements.
9557− -- It can not be broken by its own definition.
9558−--- It points to the page that created it.
9559−-wlink :: (Typeable a, Show a, MonadIO m, FormInput view)
9560−- => a -> view -> View view m a
9561−-wlink x v= View $ do
9562−- verb <- getWFName
9563−+-- It points to the page that created it.
9564−+wlink :: (Typeable a, Show a, MonadIO m, FormInput view)
9565−+ => a -> view -> View view m a
9566−+wlink x v= View $ do
9567−+ verb <- getWFName
9568− st <- get
9569−-
9570−- let name = mfPrefix st ++ (map toLower $ if typeOf x== typeOf(undefined :: String)
9571−- then unsafeCoerce x
9572−- else show x)
9573−+
9574−+ let name = --mfPrefix st ++
9575−+ (map toLower $ if typeOf x== typeOf(undefined :: String)
9576−+ then unsafeCoerce x
9577−+ else show x)
9578− lpath = mfPath st
9579−- newPath= mfPagePath st ++ [name]
9580−-
9581−- r <- if linkMatched st then return Nothing -- only a link match per page or monadic sentence in page
9582−- else
9583−- case newPath `isPrefixOf` lpath of
9584−- True -> do
9585−- modify $ \s -> s{inSync= True
9586−+ newPath= mfPagePath st ++ [name]
9587−+
9588−+ r <- if linkMatched st then return Nothing -- only a link match per page or monadic sentence in page
9589−+ else
9590−+ case newPath `isPrefixOf` lpath of
9591−+ True -> do
9592−+ modify $ \s -> s{inSync= True
9593− ,linkMatched= True
9594−- ,mfPagePath= newPath }
9595−-
9596−+ ,mfPagePath= newPath }
9597−+
9598− return $ Just x
9599−--- !> (name ++ "<-" ++ "link path=" ++show newPath)
9600−+-- !> (name ++ "<-" ++ "link path=" ++show newPath)
9601− False -> return Nothing
9602− -- !> ( "NOT MATCHED "++name++" link path= "++show newPath
9603−--- ++ "path="++ show lpath)
9604−+-- ++ "path="++ show lpath)
9605−
9606−- let path= concat ['/':v| v <- newPath ]
9607−- return $ FormElm (flink path v) r
9608−+ let path= concat ['/':v| v <- newPath ]
9609−+ return $ FormElm (flink path v) r
9610−
9611− -- Creates an absolute link. While a `wlink` path depend on the page where it is located and
9612− -- ever points to the code of the page that had it inserted, an absLink point to the first page
9613−@@ -1313,299 +1319,300 @@
9614− -- > p << "third statement" ++> (absLink "here" << p << "will present the first statement alone")
9615− -- > p << "fourth statement" ++> wlink () << p << "will not reach here"
9616− --absLink x = wcached (show x) 0 . wlink x
9617−-absLink x v= View $ do
9618−- verb <- getWFName
9619−+absLink x v= View $ do
9620−+ verb <- getWFName
9621− st <- get
9622−-
9623−- let name = mfPrefix st ++ (map toLower $ if typeOf x== typeOf(undefined :: String)
9624−- then unsafeCoerce x
9625−- else show x)
9626−+
9627−+ let name = -- mfPrefix st
9628−+ (map toLower $ if typeOf x== typeOf(undefined :: String)
9629−+ then unsafeCoerce x
9630−+ else show x)
9631−
9632− lpath = mfPath st
9633−- newPath= mfPagePath st ++ [name]
9634−- r <- if linkMatched st then return Nothing -- only a link match per page or monadic sentence in page
9635−- else
9636−- case newPath `isPrefixOf` lpath of
9637−- True -> do
9638−- modify $ \s -> s{inSync= True
9639−+ newPath= mfPagePath st ++ [name]
9640−+ r <- if linkMatched st then return Nothing -- only a link match per page or monadic sentence in page
9641−+ else
9642−+ case newPath `isPrefixOf` lpath of
9643−+ True -> do
9644−+ modify $ \s -> s{inSync= True
9645− ,linkMatched= True
9646−- ,mfPagePath= newPath }
9647−-
9648−- return $ Just x -- !> (name ++ "<- abs" ++ "lpath=" ++show lpath)
9649−- False -> return Nothing -- !> ( "NOT MATCHED "++name++" LP= "++show lpath)
9650−-
9651−- path <- liftIO $ cachedByKey (show x) 0 . return $ currentPath st ++ ('/':name)
9652−-
9653−- return $ FormElm (flink path v) r -- !> name
9654−-
9655−-
9656−-
9657−--- | When some user interface return some response to the server, but it is not produced by
9658−--- a form or a link, but for example by an script, @returning@ convert this code into a
9659−--- widget.
9660−---
9661−--- At runtime the parameter is read from the environment and validated.
9662−---
9663−--- . The parameter is the visualization code, that accept a serialization function that generate
9664−--- the server invocation string, used by the visualization to return the value by means
9665−--- of an script, usually.
9666−-returning :: (Typeable a, Read a, Show a,Monad m, FormInput view)
9667−- => ((a->String) ->view) -> View view m a
9668−-returning expr=View $ do
9669−- verb <- getWFName
9670−- name <- genNewId
9671−- env <- gets mfEnv
9672−- let string x=
9673−- let showx= case cast x of
9674−- Just x' -> x'
9675−- _ -> show x
9676−- in (verb ++ "?" ++ name ++ "=" ++ showx)
9677−- toSend= expr string
9678−- r <- getParam1 name env
9679−- return $ FormElm toSend $ valToMaybe r
9680−-
9681−-
9682−-
9683−-
9684−-
9685−---instance (Widget a b m view, Monoid view) => Widget [a] b m view where
9686−--- widget xs = View $ do
9687−--- forms <- mapM(\x -> (runView $ widget x )) xs
9688−--- let vs = concatMap (\(FormElm v _) -> v) forms
9689−--- res = filter isJust $ map (\(FormElm _ r) -> r) forms
9690−--- res1= if null res then Nothing else head res
9691−--- return $ FormElm [mconcat vs] res1
9692−-
9693−--- | Concat a list of widgets of the same type, return a the first validated result
9694−-firstOf :: (FormInput view, Monad m, Functor m)=> [View view m a] -> View view m a
9695−+ ,mfPagePath= newPath }
9696−+
9697−+ return $ Just x -- !> (name ++ "<- abs" ++ "lpath=" ++show lpath)
9698−+ False -> return Nothing -- !> ( "NOT MATCHED "++name++" LP= "++show lpath)
9699−+
9700−+ path <- liftIO $ cachedByKey (show x) 0 . return $ currentPath st ++ ('/':name)
9701−+
9702−+ return $ FormElm (flink path v) r -- !> name
9703−+
9704−+
9705−+
9706−+-- | When some user interface return some response to the server, but it is not produced by
9707−+-- a form or a link, but for example by an script, @returning@ convert this code into a
9708−+-- widget.
9709−+--
9710−+-- At runtime the parameter is read from the environment and validated.
9711−+--
9712−+-- . The parameter is the visualization code, that accept a serialization function that generate
9713−+-- the server invocation string, used by the visualization to return the value by means
9714−+-- of an script, usually.
9715−+returning :: (Typeable a, Read a, Show a,Monad m, FormInput view)
9716−+ => ((a->String) ->view) -> View view m a
9717−+returning expr=View $ do
9718−+ verb <- getWFName
9719−+ name <- genNewId
9720−+ env <- gets mfEnv
9721−+ let string x=
9722−+ let showx= case cast x of
9723−+ Just x' -> x'
9724−+ _ -> show x
9725−+ in (verb ++ "?" ++ name ++ "=" ++ showx)
9726−+ toSend= expr string
9727−+ r <- getParam1 name env
9728−+ return $ FormElm toSend $ valToMaybe r
9729−+
9730−+
9731−+
9732−+
9733−+
9734−+--instance (Widget a b m view, Monoid view) => Widget [a] b m view where
9735−+-- widget xs = View $ do
9736−+-- forms <- mapM(\x -> (runView $ widget x )) xs
9737−+-- let vs = concatMap (\(FormElm v _) -> v) forms
9738−+-- res = filter isJust $ map (\(FormElm _ r) -> r) forms
9739−+-- res1= if null res then Nothing else head res
9740−+-- return $ FormElm [mconcat vs] res1
9741−+
9742−+-- | Concat a list of widgets of the same type, return a the first validated result
9743−+firstOf :: (FormInput view, Monad m, Functor m)=> [View view m a] -> View view m a
9744− firstOf xs= foldl' (<|>) noWidget xs
9745−--- View $ do
9746−--- forms <- mapM runView xs
9747−--- let vs = concatMap (\(FormElm v _) -> [mconcat v]) forms
9748−--- res = filter isJust $ map (\(FormElm _ r) -> r) forms
9749−--- res1= if null res then Nothing else head res
9750−--- return $ FormElm vs res1
9751−-
9752−--- | from a list of widgets, it return the validated ones.
9753−-manyOf :: (FormInput view, MonadIO m, Functor m)=> [View view m a] -> View view m [a]
9754−-manyOf xs= whidden () *> (View $ do
9755−- forms <- mapM runView xs
9756−- let vs = mconcat $ map (\(FormElm v _) -> v) forms
9757−- res1= catMaybes $ map (\(FormElm _ r) -> r) forms
9758−- return . FormElm vs $ Just res1)
9759−+-- View $ do
9760−+-- forms <- mapM runView xs
9761−+-- let vs = concatMap (\(FormElm v _) -> [mconcat v]) forms
9762−+-- res = filter isJust $ map (\(FormElm _ r) -> r) forms
9763−+-- res1= if null res then Nothing else head res
9764−+-- return $ FormElm vs res1
9765−+
9766−+-- | from a list of widgets, it return the validated ones.
9767−+manyOf :: (FormInput view, MonadIO m, Functor m)=> [View view m a] -> View view m [a]
9768−+manyOf xs= whidden () *> (View $ do
9769−+ forms <- mapM runView xs
9770−+ let vs = mconcat $ map (\(FormElm v _) -> v) forms
9771−+ res1= catMaybes $ map (\(FormElm _ r) -> r) forms
9772−+ return . FormElm vs $ Just res1)
9773−
9774− -- | like manyOf, but does not validate if one or more of the widgets does not validate
9775− allOf xs= manyOf xs `validate` \rs ->
9776− if length rs== length xs
9777− then return Nothing
9778− else return $ Just mempty
9779−-
9780−-(>:>) :: (Monad m, Monoid v) => View v m a -> View v m [a] -> View v m [a]
9781−-(>:>) w ws = View $ do
9782−- FormElm fs mxs <- runView $ ws
9783−- FormElm f1 mx <- runView w
9784−- return $ FormElm (f1 <> fs)
9785−- $ case( mx,mxs) of
9786−- (Just x, Just xs) -> Just $ x:xs
9787−- (Nothing, mxs) -> mxs
9788−- (Just x, _) -> Just [x]
9789−-
9790−--- | Intersperse a widget in a list of widgets. the results is a 2-tuple of both types.
9791−---
9792−--- it has a infix priority @infixr 5@
9793−-(|*>) :: (MonadIO m, Functor m, FormInput view)
9794−- => View view m r
9795−- -> [View view m r']
9796−- -> View view m (Maybe r,Maybe r')
9797−-(|*>) x xs= View $ do
9798−- fs <- mapM runView xs
9799−- FormElm fx rx <- runView x
9800−+
9801−+(>:>) :: (Monad m, Monoid v) => View v m a -> View v m [a] -> View v m [a]
9802−+(>:>) w ws = View $ do
9803−+ FormElm fs mxs <- runView $ ws
9804−+ FormElm f1 mx <- runView w
9805−+ return $ FormElm (f1 <> fs)
9806−+ $ case( mx,mxs) of
9807−+ (Just x, Just xs) -> Just $ x:xs
9808−+ (Nothing, mxs) -> mxs
9809−+ (Just x, _) -> Just [x]
9810−+
9811−+-- | Intersperse a widget in a list of widgets. the results is a 2-tuple of both types.
9812−+--
9813−+-- it has a infix priority @infixr 5@
9814−+(|*>) :: (MonadIO m, Functor m, FormInput view)
9815−+ => View view m r
9816−+ -> [View view m r']
9817−+ -> View view m (Maybe r,Maybe r')
9818−+(|*>) x xs= View $ do
9819−+ fs <- mapM runView xs
9820−+ FormElm fx rx <- runView x
9821− let (fxs, rxss) = unzip $ map (\(FormElm v r) -> (v,r)) fs
9822− rs= filter isJust rxss
9823−- rxs= if null rs then Nothing else head rs
9824−- return $ FormElm (fx <> mconcat (intersperse fx fxs) <> fx)
9825−- $ case (rx,rxs) of
9826−- (Nothing, Nothing) -> Nothing
9827−- other -> Just other
9828−-
9829−-
9830−-
9831−-infixr 5 |*>
9832−-
9833−--- | Put a widget before and after other. Useful for navigation links in a page that appears at toAdd
9834−--- and at the bottom of a page.
9835−-
9836−--- It has a low infix priority: @infixr 1@
9837−-(|+|) :: (Functor m, FormInput view, MonadIO m)
9838−- => View view m r
9839−- -> View view m r'
9840−- -> View view m (Maybe r, Maybe r')
9841−-(|+|) w w'= w |*> [w']
9842−-
9843−-infixr 1 |+|
9844−-
9845−-
9846−--- | Flatten a binary tree of tuples of Maybe results produced by the \<+> operator
9847−--- into a single tuple with the same elements in the same order.
9848−--- This is useful for easing matching. For example:
9849−---
9850−--- @ res \<- ask $ wlink1 \<+> wlink2 wform \<+> wlink3 \<+> wlink4@
9851−---
9852−--- @res@ has type:
9853−---
9854−--- @Maybe (Maybe (Maybe (Maybe (Maybe a,Maybe b),Maybe c),Maybe d),Maybe e)@
9855−---
9856−--- but @flatten res@ has type:
9857−---
9858−--- @ (Maybe a, Maybe b, Maybe c, Maybe d, Maybe e)@
9859−-
9860−-flatten :: Flatten (Maybe tree) list => tree -> list
9861−-flatten res= doflat $ Just res
9862−-
9863−-class Flatten tree list where
9864−- doflat :: tree -> list
9865−-
9866−-
9867−-type Tuple2 a b= Maybe (Maybe a, Maybe b)
9868−-type Tuple3 a b c= Maybe ( (Tuple2 a b), Maybe c)
9869−-type Tuple4 a b c d= Maybe ( (Tuple3 a b c), Maybe d)
9870−-type Tuple5 a b c d e= Maybe ( (Tuple4 a b c d), Maybe e)
9871−-type Tuple6 a b c d e f= Maybe ( (Tuple5 a b c d e), Maybe f)
9872−-
9873−-instance Flatten (Tuple2 a b) (Maybe a, Maybe b) where
9874−- doflat (Just(ma,mb))= (ma,mb)
9875−- doflat Nothing= (Nothing,Nothing)
9876−-
9877−-instance Flatten (Tuple3 a b c) (Maybe a, Maybe b,Maybe c) where
9878−- doflat (Just(mx,mc))= let(ma,mb)= doflat mx in (ma,mb,mc)
9879−- doflat Nothing= (Nothing,Nothing,Nothing)
9880−-
9881−-instance Flatten (Tuple4 a b c d) (Maybe a, Maybe b,Maybe c,Maybe d) where
9882−- doflat (Just(mx,mc))= let(ma,mb,md)= doflat mx in (ma,mb,md,mc)
9883−- doflat Nothing= (Nothing,Nothing,Nothing,Nothing)
9884−-
9885−-instance Flatten (Tuple5 a b c d e) (Maybe a, Maybe b,Maybe c,Maybe d,Maybe e) where
9886−- doflat (Just(mx,mc))= let(ma,mb,md,me)= doflat mx in (ma,mb,md,me,mc)
9887−- doflat Nothing= (Nothing,Nothing,Nothing,Nothing,Nothing)
9888−-
9889−-instance Flatten (Tuple6 a b c d e f) (Maybe a, Maybe b,Maybe c,Maybe d,Maybe e,Maybe f) where
9890−- doflat (Just(mx,mc))= let(ma,mb,md,me,mf)= doflat mx in (ma,mb,md,me,mf,mc)
9891−- doflat Nothing= (Nothing,Nothing,Nothing,Nothing,Nothing,Nothing)
9892−-
9893−---infixr 7 .<<.
9894−----- | > (.<<.) w x = w $ toByteString x
9895−---(.<<.) :: (FormInput view) => (ByteString -> ByteString) -> view -> ByteString
9896−---(.<<.) w x = w ( toByteString x)
9897−---
9898−----- | > (.<+>.) x y = normalize x <+> normalize y
9899−---(.<+>.)
9900−--- :: (Monad m, FormInput v, FormInput v1) =>
9901−--- View v m a -> View v1 m b -> View ByteString m (Maybe a, Maybe b)
9902−---(.<+>.) x y = normalize x <+> normalize y
9903−---
9904−----- | > (.|*>.) x y = normalize x |*> map normalize y
9905−---(.|*>.)
9906−--- :: (Functor m, MonadIO m, FormInput v, FormInput v1) =>
9907−--- View v m r
9908−--- -> [View v1 m r'] -> View ByteString m (Maybe r, Maybe r')
9909−---(.|*>.) x y = normalize x |*> map normalize y
9910−---
9911−----- | > (.|+|.) x y = normalize x |+| normalize y
9912−---(.|+|.)
9913−--- :: (Functor m, MonadIO m, FormInput v, FormInput v1) =>
9914−--- View v m r -> View v1 m r' -> View ByteString m (Maybe r, Maybe r')
9915−---(.|+|.) x y = normalize x |+| normalize y
9916−---
9917−----- | > (.**>.) x y = normalize x **> normalize y
9918−---(.**>.)
9919−--- :: (Monad m, Functor m, FormInput v, FormInput v1) =>
9920−--- View v m a -> View v1 m b -> View ByteString m b
9921−---(.**>.) x y = normalize x **> normalize y
9922−---
9923−----- | > (.<**.) x y = normalize x <** normalize y
9924−---(.<**.)
9925−--- :: (Monad m, Functor m, FormInput v, FormInput v1) =>
9926−--- View v m a -> View v1 m b -> View ByteString m a
9927−---(.<**.) x y = normalize x <** normalize y
9928−---
9929−----- | > (.<|>.) x y= normalize x <|> normalize y
9930−---(.<|>.)
9931−--- :: (Monad m, Functor m, FormInput v, FormInput v1) =>
9932−--- View v m a -> View v1 m a -> View ByteString m a
9933−---(.<|>.) x y= normalize x <|> normalize y
9934−---
9935−----- | > (.<++.) x v= normalize x <++ toByteString v
9936−---(.<++.) :: (Monad m, FormInput v, FormInput v') => View v m a -> v' -> View ByteString m a
9937−---(.<++.) x v= normalize x <++ toByteString v
9938−---
9939−----- | > (.++>.) v x= toByteString v ++> normalize x
9940−---(.++>.) :: (Monad m, FormInput v, FormInput v') => v -> View v' m a -> View ByteString m a
9941−---(.++>.) v x= toByteString v ++> normalize x
9942−-
9943−-
9944−-instance FormInput ByteString where
9945−- toByteString= id
9946−- toHttpData = HttpData [contentHtml ] []
9947−- ftag x= btag x []
9948−- inred = btag "b" [("style", "color:red")]
9949−- finput n t v f c= btag "input" ([("type", t) ,("name", n),("value", v)] ++ if f then [("checked","true")] else []
9950−- ++ case c of Just s ->[( "onclick", s)]; _ -> [] ) ""
9951−- ftextarea name text= btag "textarea" [("name", name)] $ fromChunks [encodeUtf8 text]
9952−-
9953−- fselect name options= btag "select" [("name", name)] options
9954−-
9955−- foption value content msel= btag "option" ([("value", value)] ++ selected msel) content
9956−- where
9957−- selected msel = if msel then [("selected","true")] else []
9958−-
9959−- attrs = addAttrs
9960−-
9961−-
9962−- formAction action form = btag "form" [("action", action),("method", "post")] form
9963−- fromStr = fromString
9964−- fromStrNoEncode= fromString
9965−-
9966−- flink v str = btag "a" [("href", v)] str
9967−-
9968−------- page Flows ----
9969−-
9970−--- | Prepares the state for a page flow. It add a prefix to every form element or link identifier for the formlets and also
9971−--- keep the state of the links clicked and form imput entered within the widget.
9972−--- If the computation within the widget has branches @if@ @case@ etc, each branch must have its pageFlow with a distinct identifier.
9973−--- See <http://haskell-web.blogspot.com.es/2013/06/the-promising-land-of-monadic-formlets.html>
9974−-pageFlow
9975−- :: (Monad m, Functor m, FormInput view) =>
9976−- String -> View view m a -> View view m a
9977−-pageFlow str widget=do
9978−- s <- get
9979−-
9980−- if mfPageFlow s == False
9981−- then do
9982−- put s{mfPrefix= str ++ mfPrefix s
9983−- ,mfSequence=0
9984−+ rxs= if null rs then Nothing else head rs
9985−+ return $ FormElm (fx <> mconcat (intersperse fx fxs) <> fx)
9986−+ $ case (rx,rxs) of
9987−+ (Nothing, Nothing) -> Nothing
9988−+ other -> Just other
9989−+
9990−+
9991−+
9992−+infixr 5 |*>
9993−+
9994−+-- | Put a widget before and after other. Useful for navigation links in a page that appears at toAdd
9995−+-- and at the bottom of a page.
9996−+
9997−+-- It has a low infix priority: @infixr 1@
9998−+(|+|) :: (Functor m, FormInput view, MonadIO m)
9999−+ => View view m r
10000−+ -> View view m r'
10001−+ -> View view m (Maybe r, Maybe r')
10002−+(|+|) w w'= w |*> [w']
10003−+
10004−+infixr 1 |+|
10005−+
10006−+
10007−+-- | Flatten a binary tree of tuples of Maybe results produced by the \<+> operator
10008−+-- into a single tuple with the same elements in the same order.
10009−+-- This is useful for easing matching. For example:
10010−+--
10011−+-- @ res \<- ask $ wlink1 \<+> wlink2 wform \<+> wlink3 \<+> wlink4@
10012−+--
10013−+-- @res@ has type:
10014−+--
10015−+-- @Maybe (Maybe (Maybe (Maybe (Maybe a,Maybe b),Maybe c),Maybe d),Maybe e)@
10016−+--
10017−+-- but @flatten res@ has type:
10018−+--
10019−+-- @ (Maybe a, Maybe b, Maybe c, Maybe d, Maybe e)@
10020−+
10021−+flatten :: Flatten (Maybe tree) list => tree -> list
10022−+flatten res= doflat $ Just res
10023−+
10024−+class Flatten tree list where
10025−+ doflat :: tree -> list
10026−+
10027−+
10028−+type Tuple2 a b= Maybe (Maybe a, Maybe b)
10029−+type Tuple3 a b c= Maybe ( (Tuple2 a b), Maybe c)
10030−+type Tuple4 a b c d= Maybe ( (Tuple3 a b c), Maybe d)
10031−+type Tuple5 a b c d e= Maybe ( (Tuple4 a b c d), Maybe e)
10032−+type Tuple6 a b c d e f= Maybe ( (Tuple5 a b c d e), Maybe f)
10033−+
10034−+instance Flatten (Tuple2 a b) (Maybe a, Maybe b) where
10035−+ doflat (Just(ma,mb))= (ma,mb)
10036−+ doflat Nothing= (Nothing,Nothing)
10037−+
10038−+instance Flatten (Tuple3 a b c) (Maybe a, Maybe b,Maybe c) where
10039−+ doflat (Just(mx,mc))= let(ma,mb)= doflat mx in (ma,mb,mc)
10040−+ doflat Nothing= (Nothing,Nothing,Nothing)
10041−+
10042−+instance Flatten (Tuple4 a b c d) (Maybe a, Maybe b,Maybe c,Maybe d) where
10043−+ doflat (Just(mx,mc))= let(ma,mb,md)= doflat mx in (ma,mb,md,mc)
10044−+ doflat Nothing= (Nothing,Nothing,Nothing,Nothing)
10045−+
10046−+instance Flatten (Tuple5 a b c d e) (Maybe a, Maybe b,Maybe c,Maybe d,Maybe e) where
10047−+ doflat (Just(mx,mc))= let(ma,mb,md,me)= doflat mx in (ma,mb,md,me,mc)
10048−+ doflat Nothing= (Nothing,Nothing,Nothing,Nothing,Nothing)
10049−+
10050−+instance Flatten (Tuple6 a b c d e f) (Maybe a, Maybe b,Maybe c,Maybe d,Maybe e,Maybe f) where
10051−+ doflat (Just(mx,mc))= let(ma,mb,md,me,mf)= doflat mx in (ma,mb,md,me,mf,mc)
10052−+ doflat Nothing= (Nothing,Nothing,Nothing,Nothing,Nothing,Nothing)
10053−+
10054−+--infixr 7 .<<.
10055−+---- | > (.<<.) w x = w $ toByteString x
10056−+--(.<<.) :: (FormInput view) => (ByteString -> ByteString) -> view -> ByteString
10057−+--(.<<.) w x = w ( toByteString x)
10058−+--
10059−+---- | > (.<+>.) x y = normalize x <+> normalize y
10060−+--(.<+>.)
10061−+-- :: (Monad m, FormInput v, FormInput v1) =>
10062−+-- View v m a -> View v1 m b -> View ByteString m (Maybe a, Maybe b)
10063−+--(.<+>.) x y = normalize x <+> normalize y
10064−+--
10065−+---- | > (.|*>.) x y = normalize x |*> map normalize y
10066−+--(.|*>.)
10067−+-- :: (Functor m, MonadIO m, FormInput v, FormInput v1) =>
10068−+-- View v m r
10069−+-- -> [View v1 m r'] -> View ByteString m (Maybe r, Maybe r')
10070−+--(.|*>.) x y = normalize x |*> map normalize y
10071−+--
10072−+---- | > (.|+|.) x y = normalize x |+| normalize y
10073−+--(.|+|.)
10074−+-- :: (Functor m, MonadIO m, FormInput v, FormInput v1) =>
10075−+-- View v m r -> View v1 m r' -> View ByteString m (Maybe r, Maybe r')
10076−+--(.|+|.) x y = normalize x |+| normalize y
10077−+--
10078−+---- | > (.**>.) x y = normalize x **> normalize y
10079−+--(.**>.)
10080−+-- :: (Monad m, Functor m, FormInput v, FormInput v1) =>
10081−+-- View v m a -> View v1 m b -> View ByteString m b
10082−+--(.**>.) x y = normalize x **> normalize y
10083−+--
10084−+---- | > (.<**.) x y = normalize x <** normalize y
10085−+--(.<**.)
10086−+-- :: (Monad m, Functor m, FormInput v, FormInput v1) =>
10087−+-- View v m a -> View v1 m b -> View ByteString m a
10088−+--(.<**.) x y = normalize x <** normalize y
10089−+--
10090−+---- | > (.<|>.) x y= normalize x <|> normalize y
10091−+--(.<|>.)
10092−+-- :: (Monad m, Functor m, FormInput v, FormInput v1) =>
10093−+-- View v m a -> View v1 m a -> View ByteString m a
10094−+--(.<|>.) x y= normalize x <|> normalize y
10095−+--
10096−+---- | > (.<++.) x v= normalize x <++ toByteString v
10097−+--(.<++.) :: (Monad m, FormInput v, FormInput v') => View v m a -> v' -> View ByteString m a
10098−+--(.<++.) x v= normalize x <++ toByteString v
10099−+--
10100−+---- | > (.++>.) v x= toByteString v ++> normalize x
10101−+--(.++>.) :: (Monad m, FormInput v, FormInput v') => v -> View v' m a -> View ByteString m a
10102−+--(.++>.) v x= toByteString v ++> normalize x
10103−+
10104−+
10105−+instance FormInput ByteString where
10106−+ toByteString= id
10107−+ toHttpData = HttpData [contentHtml ] []
10108−+ ftag x= btag x []
10109−+ inred = btag "b" [("style", "color:red")]
10110−+ finput n t v f c= btag "input" ([("type", t) ,("name", n),("value", v)] ++ if f then [("checked","true")] else []
10111−+ ++ case c of Just s ->[( "onclick", s)]; _ -> [] ) ""
10112−+ ftextarea name text= btag "textarea" [("name", name)] $ fromChunks [encodeUtf8 text]
10113−+
10114−+ fselect name options= btag "select" [("name", name)] options
10115−+
10116−+ foption value content msel= btag "option" ([("value", value)] ++ selected msel) content
10117−+ where
10118−+ selected msel = if msel then [("selected","true")] else []
10119−+
10120−+ attrs = addAttrs
10121−+
10122−+
10123−+ formAction action method form = btag "form" [("action", action),("method", method)] form
10124−+ fromStr = fromString
10125−+ fromStrNoEncode= fromString
10126−+
10127−+ flink v str = btag "a" [("href", v)] str
10128−+
10129−+------ page Flows ----
10130−+
10131−+-- | Prepares the state for a page flow. It add a prefix to every form element or link identifier for the formlets and also
10132−+-- keep the state of the links clicked and form imput entered within the widget.
10133−+-- If the computation within the widget has branches @if@ @case@ etc, each branch must have its pageFlow with a distinct identifier.
10134−+-- See <http://haskell-web.blogspot.com.es/2013/06/the-promising-land-of-monadic-formlets.html>
10135−+pageFlow
10136−+ :: (Monad m, Functor m, FormInput view) =>
10137−+ String -> View view m a -> View view m a
10138−+pageFlow str widget=do
10139−+ s <- get
10140−+
10141−+ if mfPageFlow s == False
10142−+ then do
10143−+ put s{mfPrefix= str ++ mfPrefix s
10144−+ ,mfSequence=0
10145− ,mfPageFlow= True
10146−- } -- !> ("PARENT pageflow. prefix="++ str)
10147−-
10148−- r<- widget <** (modify (\s' -> s'{mfSequence= mfSequence s
10149−+ } -- !> ("PARENT pageflow. prefix="++ str)
10150−+
10151−+ r<- widget <** (modify (\s' -> s'{mfSequence= mfSequence s
10152− ,mfPrefix= mfPrefix s
10153−- }))
10154−+ }))
10155− modify (\s -> s{mfPageFlow=False} )
10156−- return r -- !> ("END PARENT pageflow. prefix="++ str))
10157−-
10158−-
10159−- else do
10160−- put s{mfPrefix= str++ mfPrefix s,mfSequence=0} -- !> ("PARENT pageflow. prefix="++ str) -- !> ("CHILD pageflow. prefix="++ str)
10161−-
10162−- widget <** (modify (\s' -> s'{mfSequence= mfSequence s
10163−- ,mfPrefix= mfPrefix s}))
10164−- -- !> ("END CHILD pageflow. prefix="++ str))
10165−-
10166−-
10167−-
10168−---acum map []= map
10169−---acum map (x:xs) =
10170−--- let map' = case M.lookup x map of
10171−--- Nothing -> M.insert x 1 map
10172−--- Just n -> M.insert x (n+1) map
10173−--- in acum map' xs
10174−-
10175−+ return r -- !> ("END PARENT pageflow. prefix="++ str))
10176−+
10177−+
10178−+ else do
10179−+ put s{mfPrefix= str++ mfPrefix s,mfSequence=0} -- !> ("PARENT pageflow. prefix="++ str) -- !> ("CHILD pageflow. prefix="++ str)
10180−+
10181−+ widget <** (modify (\s' -> s'{mfSequence= mfSequence s
10182−+ ,mfPrefix= mfPrefix s}))
10183−+ -- !> ("END CHILD pageflow. prefix="++ str))
10184−+
10185−+
10186−+
10187−+--acum map []= map
10188−+--acum map (x:xs) =
10189−+-- let map' = case M.lookup x map of
10190−+-- Nothing -> M.insert x 1 map
10191−+-- Just n -> M.insert x (n+1) map
10192−+-- in acum map' xs
10193−+
10194−diff -ru orig/src/MFlow/Hack/Response.hs new/src/MFlow/Hack/Response.hs
10195−--- orig/src/MFlow/Hack/Response.hs 2014-06-10 05:51:26.969015857 +0300
10196−+++ new/src/MFlow/Hack/Response.hs 2014-06-10 05:51:25.000000000 +0300
10197−@@ -1,13 +1,13 @@
10198− {-# OPTIONS -XExistentialQuantification -XTypeSynonymInstances
10199−- -XFlexibleInstances -XDeriveDataTypeable -XOverloadedStrings #-}
10200−-module MFlow.Hack.Response where
10201−-
10202−+ -XFlexibleInstances -XDeriveDataTypeable -XOverloadedStrings #-}
10203−+module MFlow.Hack.Response where
10204−+
10205− import Hack
10206−-import MFlow.Cookies
10207−+import MFlow.Cookies
10208− import Data.ByteString.Lazy.Char8 as B
10209−
10210−-import MFlow
10211−-import Data.Typeable
10212−+import MFlow
10213−+import Data.Typeable
10214− import Data.Monoid
10215− import System.IO.Unsafe
10216− import Data.Map as M
10217−@@ -18,9 +18,9 @@
10218− --(!>)= flip trace
10219−
10220−
10221−-
10222−-class ToResponse a where
10223−- toResponse :: a -> Response
10224−+
10225−+class ToResponse a where
10226−+ toResponse :: a -> Response
10227−
10228−
10229−
10230−@@ -31,28 +31,28 @@
10231− mappend (TResp x) (TResp y)=
10232− case cast y of
10233− Just y' -> TResp $ mappend x y'
10234−- Nothing -> error $ "fragment of type " ++ show ( typeOf y) ++ " after fragment of type " ++ show ( typeOf x)
10235−-
10236−+ Nothing -> error $ "fragment of type " ++ show ( typeOf y) ++ " after fragment of type " ++ show ( typeOf x)
10237−+
10238−
10239− instance ToResponse TResp where
10240−- toResponse (TResp x)= toResponse x
10241−+ toResponse (TResp x)= toResponse x
10242− toResponse (TRespR r)= toResponse r
10243−-
10244−-instance ToResponse Response where
10245−- toResponse = id
10246−-
10247−-instance ToResponse ByteString where
10248−- toResponse x= Response{status=200, headers=[contentHtml {-,("Content-Length",show $ B.length x) -}], body= x}
10249−-
10250−-instance ToResponse String where
10251−+
10252−+instance ToResponse Response where
10253−+ toResponse = id
10254−+
10255−+instance ToResponse ByteString where
10256−+ toResponse x= Response{status=200, headers=[contentHtml {-,("Content-Length",show $ B.length x) -}], body= x}
10257−+
10258−+instance ToResponse String where
10259− toResponse x= Response{status=200, headers=[contentHtml{-,("Content-Length",show $ B.length x) -}], body= B.pack x}
10260−
10261− instance ToResponse HttpData where
10262− toResponse (HttpData hs cookies x)= (toResponse x) {headers= hs++ cookieHeaders cookies}
10263−- toResponse (Error NotFound str)= Response{status=404, headers=[], body= getNotFoundResponse str}
10264−-
10265−-instance Typeable Env where
10266−- typeOf = \_-> mkTyConApp (mkTyCon3 "hack-handler-simpleserver" "Hack" "Env") []
10267−-
10268−---instance Typeable Response where
10269−--- typeOf = \_-> mkTyConApp (mkTyCon "Hack.Response")[]
10270−+ toResponse (Error NotFound str)= Response{status=404, headers=[], body= getNotFoundResponse str}
10271−+
10272−+instance Typeable Env where
10273−+ typeOf = \_-> mkTyConApp (mkTyCon3 "hack-handler-simpleserver" "Hack" "Env") []
10274−+
10275−+--instance Typeable Response where
10276−+-- typeOf = \_-> mkTyConApp (mkTyCon "Hack.Response")[]
10277−diff -ru orig/src/MFlow/Hack/XHtml.hs new/src/MFlow/Hack/XHtml.hs
10278−--- orig/src/MFlow/Hack/XHtml.hs 2014-06-10 05:51:26.969015857 +0300
10279−+++ new/src/MFlow/Hack/XHtml.hs 2014-06-10 05:51:25.000000000 +0300
10280−@@ -27,14 +27,14 @@
10281− import Text.XHtml
10282− import Data.Typeable
10283− import Data.ByteString.Lazy.Char8 as B(pack,unpack, length, ByteString)
10284−-
10285−-instance ToResponse Html where
10286−+
10287−+instance ToResponse Html where
10288− toResponse x= Response{ status=200, headers=[]
10289−- , Hack.body= pack $ showHtml x}
10290−+ , Hack.body= pack $ showHtml x}
10291− --
10292−---instance Typeable Html where
10293−--- typeOf = \_ -> mkTyConApp (mkTyCon "Text.XHtml.Strict.Html") []
10294−+--instance Typeable Html where
10295−+-- typeOf = \_ -> mkTyConApp (mkTyCon "Text.XHtml.Strict.Html") []
10296− --
10297−---instance ConvertTo Html TResp where
10298−+--instance ConvertTo Html TResp where
10299− -- convert = TResp
10300−
10301−diff -ru orig/src/MFlow/Hack.hs new/src/MFlow/Hack.hs
10302−--- orig/src/MFlow/Hack.hs 2014-06-10 05:51:26.957015857 +0300
10303−+++ new/src/MFlow/Hack.hs 2014-06-10 05:51:25.000000000 +0300
10304−@@ -8,33 +8,33 @@
10305−
10306− see <http://hackage.haskell.org/package/hack>
10307− -}
10308−-
10309−+
10310− module MFlow.Hack(
10311− module MFlow.Cookies
10312− ,module MFlow
10313− ,hackMessageFlow)
10314− where
10315−-
10316−-import Data.Typeable
10317−-import Hack
10318−-
10319−-import Control.Concurrent.MVar(modifyMVar_, readMVar)
10320−-import Control.Monad(when)
10321−-
10322−-
10323−-import Data.ByteString.Lazy.Char8 as B(pack, unpack, length, ByteString)
10324−-import Control.Concurrent(ThreadId(..))
10325−-import System.IO.Unsafe
10326−+
10327−+import Data.Typeable
10328−+import Hack
10329−+
10330−+import Control.Concurrent.MVar(modifyMVar_, readMVar)
10331−+import Control.Monad(when)
10332−+
10333−+
10334−+import Data.ByteString.Lazy.Char8 as B(pack, unpack, length, ByteString)
10335−+import Control.Concurrent(ThreadId(..))
10336−+import System.IO.Unsafe
10337− import Control.Concurrent.MVar
10338−-import Control.Concurrent
10339−-import Control.Exception
10340−+import Control.Concurrent
10341−+import Control.Exception
10342− import qualified Data.Map as M
10343−-import Data.Maybe
10344−+import Data.Maybe
10345− import Data.TCache
10346−-import Data.TCache.DefaultPersistence
10347−-import Control.Workflow hiding (Indexable(..))
10348−-
10349−-import MFlow
10350−+import Data.TCache.DefaultPersistence
10351−+import Control.Workflow hiding (Indexable(..))
10352−+
10353−+import MFlow
10354− import MFlow.Cookies
10355−
10356− import MFlow.Hack.Response
10357−@@ -46,13 +46,13 @@
10358−
10359−
10360− flow= "flow"
10361−-
10362−-instance Processable Env where
10363−- pwfname env= if null sc then noScript else sc
10364−- where
10365−+
10366−+instance Processable Env where
10367−+ pwfname env= if null sc then noScript else sc
10368−+ where
10369− sc= tail $ pathInfo env
10370−- puser env = fromMaybe anonymous $ lookup cookieuser $ http env
10371−-
10372−+ puser env = fromMaybe anonymous $ lookup cookieuser $ http env
10373−+
10374− pind env= fromMaybe (error ": No FlowID") $ lookup flow $ http env
10375− getParams= http
10376− -- getServer env= serverName env
10377−@@ -60,38 +60,38 @@
10378− -- getPort env= serverPort env
10379−
10380−
10381−-
10382−----------------------------------------------
10383−-
10384−-
10385−-
10386−---
10387−---instance ConvertTo String TResp where
10388−--- convert = TResp . pack
10389−+
10390−+---------------------------------------------
10391−+
10392−+
10393−+
10394− --
10395−---instance ConvertTo ByteString TResp where
10396−+--instance ConvertTo String TResp where
10397−+-- convert = TResp . pack
10398−+--
10399−+--instance ConvertTo ByteString TResp where
10400− -- convert = TResp
10401− --
10402−---
10403−---instance ConvertTo Error TResp where
10404−+--
10405−+--instance ConvertTo Error TResp where
10406− -- convert (Error e)= TResp . pack $ errorResponse e
10407− --
10408− --instance ToResponse v =>ConvertTo (HttpData v) TResp where
10409−--- convert= TRespR
10410−+-- convert= TRespR
10411−+
10412−+
10413−+--webScheduler :: Env
10414−+-- -> ProcList
10415−+-- -> IO (TResp, ThreadId)
10416−+--webScheduler = msgScheduler
10417−+
10418−+--theDir= unsafePerformIO getCurrentDirectory
10419−+
10420−+wFMiddleware :: (Env -> Bool) -> (Env-> IO Response) -> (Env -> IO Response)
10421−+wFMiddleware filter f = \ env -> if filter env then hackMessageFlow env else f env -- !> "new message"
10422−
10423−-
10424−---webScheduler :: Env
10425−--- -> ProcList
10426−--- -> IO (TResp, ThreadId)
10427−---webScheduler = msgScheduler
10428−-
10429−---theDir= unsafePerformIO getCurrentDirectory
10430−-
10431−-wFMiddleware :: (Env -> Bool) -> (Env-> IO Response) -> (Env -> IO Response)
10432−-wFMiddleware filter f = \ env -> if filter env then hackMessageFlow env else f env -- !> "new message"
10433−-
10434− -- | An instance of the abstract "MFlow" scheduler to the Hack interface
10435−--- it accept the list of processes being scheduled and return a hack handler
10436−+-- it accept the list of processes being scheduled and return a hack handler
10437− --
10438− -- Example:
10439− --
10440−@@ -107,112 +107,112 @@
10441− -- concat [ "http:\/\/server\/"++ i ++ "\n" | (i,_) \<- msgs]
10442− -- @
10443− --hackMessageFlow :: [(String, (Token -> Workflow IO ()))]
10444−--- -> (Env -> IO Response)
10445−---hackMessageFlow messageFlows =
10446−--- unsafePerformIO (addMessageFlows messageFlows) `seq`
10447−--- hackWorkflow -- wFMiddleware f other
10448−+-- -> (Env -> IO Response)
10449−+--hackMessageFlow messageFlows =
10450−+-- unsafePerformIO (addMessageFlows messageFlows) `seq`
10451−+-- hackWorkflow -- wFMiddleware f other
10452− -- where
10453− -- f env = unsafePerformIO $ do
10454− -- paths <- getMessageFlows >>=
10455− -- return (pwfname env `elem` paths)
10456−
10457−--- other= (\env -> defaultResponse $ "options: " ++ opts)
10458−+-- other= (\env -> defaultResponse $ "options: " ++ opts)
10459− -- (paths,_)= unzip messageFlows
10460− -- opts= concatMap (\s -> "<a href=\""++ s ++"\">"++s ++"</a>, ") paths
10461−-
10462−-
10463−-splitPath ""= ("","","")
10464−-splitPath str=
10465−- let
10466−- strr= reverse str
10467−- (ext, rest)= span (/= '.') strr
10468−- (mod, path)= span(/='/') $ tail rest
10469−- in (tail $ reverse path, reverse mod, reverse ext)
10470−-
10471−-
10472−-
10473−-hackMessageFlow :: Env -> IO Response
10474−-hackMessageFlow req1= do
10475−- let httpreq1= http req1
10476−- let cookies= {-# SCC "getCookies" #-} getCookies httpreq1
10477−-
10478−- (flowval , retcookies) <- case lookup ( flow) cookies of
10479−- Just fl -> return (fl, [])
10480−- Nothing -> do
10481−- fl <- newFlow
10482−+
10483−+
10484−+splitPath ""= ("","","")
10485−+splitPath str=
10486−+ let
10487−+ strr= reverse str
10488−+ (ext, rest)= span (/= '.') strr
10489−+ (mod, path)= span(/='/') $ tail rest
10490−+ in (tail $ reverse path, reverse mod, reverse ext)
10491−+
10492−+
10493−+
10494−+hackMessageFlow :: Env -> IO Response
10495−+hackMessageFlow req1= do
10496−+ let httpreq1= http req1
10497−+ let cookies= {-# SCC "getCookies" #-} getCookies httpreq1
10498−+
10499−+ (flowval , retcookies) <- case lookup ( flow) cookies of
10500−+ Just fl -> return (fl, [])
10501−+ Nothing -> do
10502−+ fl <- newFlow
10503− return ( fl, [( flow, fl, "/",(Just $ show $ 365*24*60*60))])
10504−-
10505−-{- for state persistence in cookies
10506−- putStateCookie req1 cookies
10507−- let retcookies= case getStateCookie req1 of
10508−- Nothing -> retcookies1
10509−- Just ck -> ck:retcookies1
10510−--}
10511−-
10512−- let input=
10513−- case ( requestMethod req1, lookup "Content-Type" httpreq1 ) of
10514−- (POST,Just "application/x-www-form-urlencoded") -> urlDecode . unpack $ hackInput req1
10515−- (GET, _) -> urlDecode . queryString $ req1
10516−- _ -> []
10517−-
10518−- let req = case retcookies of
10519−- [] -> req1{http= (input ++ cookies) ++ http req1} -- !> "REQ"
10520−- _ -> req1{http=(flow, flowval): ( input ++ cookies ) ++ http req1} -- !> "REQ"
10521−-
10522−-
10523−+
10524−+{- for state persistence in cookies
10525−+ putStateCookie req1 cookies
10526−+ let retcookies= case getStateCookie req1 of
10527−+ Nothing -> retcookies1
10528−+ Just ck -> ck:retcookies1
10529−+-}
10530−+
10531−+ let input=
10532−+ case ( requestMethod req1, lookup "Content-Type" httpreq1 ) of
10533−+ (POST,Just "application/x-www-form-urlencoded") -> urlDecode . unpack $ hackInput req1
10534−+ (GET, _) -> urlDecode . queryString $ req1
10535−+ _ -> []
10536−+
10537−+ let req = case retcookies of
10538−+ [] -> req1{http= (input ++ cookies) ++ http req1} -- !> "REQ"
10539−+ _ -> req1{http=(flow, flowval): ( input ++ cookies ) ++ http req1} -- !> "REQ"
10540−+
10541−+
10542− (resp',th) <- msgScheduler req
10543−-
10544−
10545−- let resp''= toResponse resp'
10546−+
10547−+ let resp''= toResponse resp'
10548− let headers1= case retcookies of [] -> headers resp''; _ -> (cookieHeaders retcookies)
10549−- let resp = resp''{status=200, headers= headers1 {-,("Content-Length",show $ B.length x) -}}
10550−-
10551−+ let resp = resp''{status=200, headers= headers1 {-,("Content-Length",show $ B.length x) -}}
10552−+
10553− return resp
10554−
10555−-
10556−-------persistent state in cookies (not tested)
10557−-
10558−-tvresources :: MVar (Maybe ( M.Map string string))
10559−-tvresources= unsafePerformIO $ newMVar Nothing
10560−-statCookieName= "stat"
10561−-
10562−-putStateCookie req cookies=
10563−- case lookup statCookieName cookies of
10564−- Nothing -> return ()
10565−- Just (statCookieName, str , "/", _) -> modifyMVar_ tvresources $
10566−- \mmap -> case mmap of
10567−- Just map -> return $ Just $ M.insert (keyResource req) str map
10568−- Nothing -> return $ Just $ M.fromList [((keyResource req), str) ]
10569−-
10570−-getStateCookie req= do
10571−- mr<- readMVar tvresources
10572−- case mr of
10573−- Nothing -> return Nothing
10574−- Just map -> case M.lookup (keyResource req) map of
10575−- Nothing -> return Nothing
10576−- Just str -> do
10577−- swapMVar tvresources Nothing
10578−- return $ Just (statCookieName, str , "/")
10579−-
10580−-{-
10581−-persistInCookies= setPersist PersistStat{readStat=readResource, writeStat=writeResource, deleteStat=deleteResource}
10582−- where
10583−- writeResource stat= modifyMVar_ tvresources $ \mmap ->
10584−- case mmap of
10585−- Just map-> return $ Just $ M.insert (keyResource stat) (serialize stat) map
10586−- Nothing -> return $ Just $ M.fromList [((keyResource stat), (serialize stat)) ]
10587−- readResource stat= do
10588−- mstr <- withMVar tvresources $ \mmap ->
10589−- case mmap of
10590−- Just map -> return $ M.lookup (keyResource stat) map
10591−- Nothing -> return Nothing
10592−- case mstr of
10593−- Nothing -> return Nothing
10594−- Just str -> return $ deserialize str
10595−-
10596−- deleteResource stat= modifyMVar_ tvresources $ \mmap->
10597−- case mmap of
10598−- Just map -> return $ Just $ M.delete (keyResource stat) map
10599−- Nothing -> return $ Nothing
10600−+
10601−+------persistent state in cookies (not tested)
10602−+
10603−+tvresources :: MVar (Maybe ( M.Map string string))
10604−+tvresources= unsafePerformIO $ newMVar Nothing
10605−+statCookieName= "stat"
10606−+
10607−+putStateCookie req cookies=
10608−+ case lookup statCookieName cookies of
10609−+ Nothing -> return ()
10610−+ Just (statCookieName, str , "/", _) -> modifyMVar_ tvresources $
10611−+ \mmap -> case mmap of
10612−+ Just map -> return $ Just $ M.insert (keyResource req) str map
10613−+ Nothing -> return $ Just $ M.fromList [((keyResource req), str) ]
10614−+
10615−+getStateCookie req= do
10616−+ mr<- readMVar tvresources
10617−+ case mr of
10618−+ Nothing -> return Nothing
10619−+ Just map -> case M.lookup (keyResource req) map of
10620−+ Nothing -> return Nothing
10621−+ Just str -> do
10622−+ swapMVar tvresources Nothing
10623−+ return $ Just (statCookieName, str , "/")
10624−+
10625−+{-
10626−+persistInCookies= setPersist PersistStat{readStat=readResource, writeStat=writeResource, deleteStat=deleteResource}
10627−+ where
10628−+ writeResource stat= modifyMVar_ tvresources $ \mmap ->
10629−+ case mmap of
10630−+ Just map-> return $ Just $ M.insert (keyResource stat) (serialize stat) map
10631−+ Nothing -> return $ Just $ M.fromList [((keyResource stat), (serialize stat)) ]
10632−+ readResource stat= do
10633−+ mstr <- withMVar tvresources $ \mmap ->
10634−+ case mmap of
10635−+ Just map -> return $ M.lookup (keyResource stat) map
10636−+ Nothing -> return Nothing
10637−+ case mstr of
10638−+ Nothing -> return Nothing
10639−+ Just str -> return $ deserialize str
10640−+
10641−+ deleteResource stat= modifyMVar_ tvresources $ \mmap->
10642−+ case mmap of
10643−+ Just map -> return $ Just $ M.delete (keyResource stat) map
10644−+ Nothing -> return $ Nothing
10645−
10646− -}
10647−diff -ru orig/src/MFlow/Wai/Blaze/Html/All.hs new/src/MFlow/Wai/Blaze/Html/All.hs
10648−--- orig/src/MFlow/Wai/Blaze/Html/All.hs 2014-06-10 05:51:26.969015857 +0300
10649−+++ new/src/MFlow/Wai/Blaze/Html/All.hs 2014-06-10 05:51:25.000000000 +0300
10650−@@ -1,97 +1,99 @@
10651−-----------------------------------------------------------------------------
10652−---
10653−--- Module : MFlow.Wai.Blaze.Html.All
10654−--- Copyright :
10655−--- License : BSD3
10656−---
10657−--- Maintainer : agocorona@gmail.com
10658−--- Stability : experimental
10659−--- Portability :
10660−---
10661−--- |
10662−---
10663−------------------------------------------------------------------------------
10664−-
10665−-module MFlow.Wai.Blaze.Html.All (
10666−- module Data.TCache
10667−-,module MFlow
10668−-,module MFlow.Forms
10669−-,module MFlow.Forms.Widgets
10670−-,module MFlow.Forms.Blaze.Html
10671−-,module MFlow.Forms.Admin
10672−-,module Control.Applicative
10673−-,module Text.Blaze.Html5
10674−-,module Text.Blaze.Html5.Attributes
10675−-,module Control.Monad.IO.Class
10676−-,module MFlow.Forms.WebApi
10677−-,module MFlow.Forms.Cache
10678−-,runNavigation
10679−-,runSecureNavigation
10680−-) where
10681−-
10682−-import MFlow
10683−-import MFlow.Wai
10684−-import MFlow.Forms
10685−-import MFlow.Forms.Widgets
10686−-import MFlow.Forms.Admin
10687−-import MFlow.Forms.Blaze.Html
10688−-import MFlow.Forms.WebApi
10689−-import MFlow.Forms.Cache
10690−-import Text.Blaze.Html5 hiding (map)
10691−-import Text.Blaze.Html5.Attributes hiding (label,span,style,cite,title,summary,step,form)
10692−-import Network.Wai
10693−-import Network.Wai.Handler.Warp hiding (getPort) --(run,defaultSettings,Settings ,setPort)
10694−-import Data.TCache
10695−-import Text.Blaze.Internal(text)
10696−-
10697−-import Control.Workflow (Workflow, unsafeIOtoWF)
10698−-
10699−-
10700−-import Control.Applicative
10701−-import Control.Monad(when, unless)
10702−-import Control.Monad.IO.Class
10703−-import System.Environment
10704−-import Data.Maybe(fromMaybe)
10705−-import Data.Char(isNumber)
10706−-import Network.Wai.Handler.WarpTLS as TLS
10707−-
10708−--- | The port is read from the first exectution parameter.
10709−--- If no parameter, it is read from the PORT environment variable.
10710−--- if this does not exist, the port 80 is used.
10711−-getPort= do
10712−- args <- getArgs
10713−- port <- case args of
10714−- port:xs -> return port
10715−- _ -> do
10716−- env <- getEnvironment
10717−- return $ fromMaybe "80" $ lookup "PORT" env
10718−- let porti= if and $ map isNumber port then fromIntegral $ read port
10719−- else 80
10720−- putStr "using port "
10721−- print porti
10722−- return porti
10723−-
10724−--- | run a persistent flow. It uses `getPort` to get the port
10725−--- The first parameter is the first element in the URL path.
10726−--- It also set the home page
10727−-runNavigation :: String -> FlowM Html (Workflow IO) () -> IO ()
10728−-runNavigation n f= do
10729−- unless (null n) $ setNoScript n
10730−- addMessageFlows[(n, runFlow f)]
10731−- porti <- getPort
10732−- wait $ run porti waiMessageFlow
10733−- --runSettings defaultSettings{settingsTimeout = 20, settingsPort= porti} waiMessageFlow
10734−-
10735−--- | Exactly the same as runNavigation, but with TLS added.
10736−--- Expects certificate.pem and key.pem in project directory.
10737−-
10738−-runSecureNavigation = runSecureNavigation' TLS.defaultTlsSettings defaultSettings
10739−-
10740−-runSecureNavigation' :: TLSSettings -> Settings -> String -> FlowM Html (Workflow IO) () -> IO ()
10741−-runSecureNavigation' t s n f = do
10742−- unless (null n) $ setNoScript n
10743−- addMessageFlows[(n, runFlow f)]
10744−- porti <- getPort
10745−--- let s' = setPort porti s
10746−+----------------------------------------------------------------------------
10747−+--
10748−+-- Module : MFlow.Wai.Blaze.Html.All
10749−+-- Copyright :
10750−+-- License : BSD3
10751−+--
10752−+-- Maintainer : agocorona@gmail.com
10753−+-- Stability : experimental
10754−+-- Portability :
10755−+--
10756−+-- |
10757−+--
10758−+-----------------------------------------------------------------------------
10759−+
10760−+module MFlow.Wai.Blaze.Html.All (
10761−+ module Data.TCache
10762−+,module MFlow
10763−+,module MFlow.Forms
10764−+,module MFlow.Forms.Widgets
10765−+,module MFlow.Forms.Blaze.Html
10766−+,module MFlow.Forms.Admin
10767−+,module Control.Applicative
10768−+,module Text.Blaze.Html5
10769−+,module Text.Blaze.Html5.Attributes
10770−+,module Control.Monad.IO.Class
10771−+,module MFlow.Forms.WebApi
10772−+,module MFlow.Forms.Cache
10773−+,runNavigation
10774−+,runSecureNavigation
10775−+,runSecureNavigation'
10776−+) where
10777−+
10778−+import MFlow
10779−+import MFlow.Wai
10780−+import MFlow.Forms
10781−+import MFlow.Forms.Widgets
10782−+import MFlow.Forms.Admin
10783−+import MFlow.Forms.Blaze.Html
10784−+import MFlow.Forms.WebApi
10785−+import MFlow.Forms.Cache
10786−+import Text.Blaze.Html5 hiding (map)
10787−+import Text.Blaze.Html5.Attributes hiding (label,span,style,cite,title,summary,step,form)
10788−+import Network.Wai
10789−+import Network.Wai.Handler.Warp --(run,defaultSettings,Settings ,setPort)
10790−+import Data.TCache
10791−+import Text.Blaze.Internal(text)
10792−+
10793−+import Control.Workflow (Workflow, unsafeIOtoWF)
10794−+
10795−+
10796−+import Control.Applicative
10797−+import Control.Monad(when, unless)
10798−+import Control.Monad.IO.Class
10799−+import System.Environment
10800−+import Data.Maybe(fromMaybe)
10801−+import Data.Char(isNumber)
10802−+import Network.Wai.Handler.WarpTLS as TLS
10803−+
10804−+
10805−+getPortW= do
10806−+ args <- getArgs
10807−+ port <- case args of
10808−+ port:xs -> return port
10809−+ _ -> do
10810−+ env <- getEnvironment
10811−+ return $ fromMaybe "80" $ lookup "PORT" env
10812−+ let porti= if and $ map isNumber port then fromIntegral $ read port
10813−+ else 80
10814−+ putStr "using port "
10815−+ print porti
10816−+ return porti
10817−+
10818−+-- | run a persistent flow. It uses `getPortW` to get the port
10819−+-- The first parameter is the first element in the URL path.
10820−+-- It also set the home page
10821−+-- The port is read from the first parameter passed to the executable.
10822−+-- If no parameter, it is read from the PORT environment variable.
10823−+-- if this does not exist, the port 80 is used.
10824−+runNavigation :: String -> FlowM Html (Workflow IO) () -> IO ()
10825−+runNavigation n f= do
10826−+ unless (null n) $ setNoScript n
10827−+ addMessageFlows[(n, runFlow f)]
10828−+ porti <- getPortW
10829−+ wait $ run porti waiMessageFlow
10830−+ --runSettings defaultSettings{settingsTimeout = 20, settingsPort= porti} waiMessageFlow
10831−+
10832−+-- | Exactly the same as runNavigation, but with TLS added.
10833−+-- Expects certificate.pem and key.pem in project directory.
10834−+
10835−+runSecureNavigation = runSecureNavigation' TLS.defaultTlsSettings defaultSettings
10836−+
10837−+runSecureNavigation' :: TLSSettings -> Settings -> String -> FlowM Html (Workflow IO) () -> IO ()
10838−+runSecureNavigation' t s n f = do
10839−+ unless (null n) $ setNoScript n
10840−+ addMessageFlows[(n, runFlow f)]
10841−+ porti <- getPortW
10842−+-- let s' = setPort porti s
10843− -- wait $ TLS.runTLS t s' waiMessageFlow
10844−- wait $ TLS.runTLS t s{settingsPort = porti} waiMessageFlow
10845−+ wait $ TLS.runTLS t s{settingsPort = porti} waiMessageFlow
10846−diff -ru orig/src/MFlow/Wai/Response.hs new/src/MFlow/Wai/Response.hs
10847−--- orig/src/MFlow/Wai/Response.hs 2014-06-10 05:51:26.965015857 +0300
10848−+++ new/src/MFlow/Wai/Response.hs 2014-06-10 05:51:25.000000000 +0300
10849−@@ -1,62 +1,62 @@
10850−-{-# OPTIONS -XExistentialQuantification -XTypeSynonymInstances
10851−- -XFlexibleInstances -XDeriveDataTypeable -XOverloadedStrings #-}
10852−-module MFlow.Wai.Response where
10853−-
10854−-import Network.Wai
10855−-import MFlow.Cookies
10856−-
10857−-import Data.ByteString.Lazy.UTF8
10858−-import MFlow
10859−-import Data.Typeable
10860−-import Data.Monoid
10861−-import System.IO.Unsafe
10862−-import Data.Map as M
10863−-import Data.CaseInsensitive
10864−-import Network.HTTP.Types
10865−-import Control.Workflow(WFErrors(..))
10866−---import Data.String
10867−---import Debug.Trace
10868−---
10869−---(!>)= flip trace
10870−-
10871−-
10872−-
10873−-class ToResponse a where
10874−- toResponse :: a -> Response
10875−-
10876−-
10877−-
10878−-data TResp = TRempty | forall a.ToResponse a=>TRespR a | forall a.(Typeable a, ToResponse a, Monoid a) => TResp a deriving Typeable
10879−-
10880−-instance Monoid TResp where
10881−- mempty = TRempty
10882−- mappend (TResp x) (TResp y)=
10883−- case cast y of
10884−- Just y' -> TResp $ mappend x y'
10885−- Nothing -> error $ "fragment of type " ++ show ( typeOf y) ++ " after fragment of type " ++ show ( typeOf x)
10886−-
10887−-
10888−-mkParams = Prelude.map mkparam
10889−-mkparam (x,y)= (mk x, y)
10890−-
10891−-instance ToResponse TResp where
10892−- toResponse (TResp x)= toResponse x
10893−- toResponse (TRespR r)= toResponse r
10894−-
10895−-instance ToResponse Response where
10896−- toResponse = id
10897−-
10898−-instance ToResponse ByteString where
10899−- toResponse x= responseLBS status200 [mkparam contentHtml] x
10900−-
10901−-instance ToResponse String where
10902−- toResponse x= responseLBS status200 [mkparam contentHtml] $ fromString x
10903−-
10904−-instance ToResponse HttpData where
10905−- toResponse (HttpData hs cookies x)= responseLBS status200 (mkParams ( hs <> cookieHeaders cookies)) x
10906−- toResponse (Error str)= responseLBS status404 [("Content-Type", "text/html")] str
10907−-
10908−--- toResponse $ error "FATAL ERROR: HttpData errors should not reach here: MFlow.Forms.Response.hs "
10909−-
10910−-
10911−-
10912−+{-# OPTIONS -XExistentialQuantification -XTypeSynonymInstances
10913−+ -XFlexibleInstances -XDeriveDataTypeable -XOverloadedStrings #-}
10914−+module MFlow.Wai.Response where
10915−+
10916−+import Network.Wai
10917−+import MFlow.Cookies
10918−+
10919−+import Data.ByteString.Lazy.UTF8
10920−+import MFlow
10921−+import Data.Typeable
10922−+import Data.Monoid
10923−+import System.IO.Unsafe
10924−+import Data.Map as M
10925−+import Data.CaseInsensitive
10926−+import Network.HTTP.Types
10927−+import Control.Workflow(WFErrors(..))
10928−+--import Data.String
10929−+--import Debug.Trace
10930−+--
10931−+--(!>)= flip trace
10932−+
10933−+
10934−+
10935−+class ToResponse a where
10936−+ toResponse :: a -> Response
10937−+
10938−+
10939−+
10940−+data TResp = TRempty | forall a.ToResponse a=>TRespR a | forall a.(Typeable a, ToResponse a, Monoid a) => TResp a deriving Typeable
10941−+
10942−+instance Monoid TResp where
10943−+ mempty = TRempty
10944−+ mappend (TResp x) (TResp y)=
10945−+ case cast y of
10946−+ Just y' -> TResp $ mappend x y'
10947−+ Nothing -> error $ "fragment of type " ++ show ( typeOf y) ++ " after fragment of type " ++ show ( typeOf x)
10948−+
10949−+
10950−+mkParams = Prelude.map mkparam
10951−+mkparam (x,y)= (mk x, y)
10952−+
10953−+instance ToResponse TResp where
10954−+ toResponse (TResp x)= toResponse x
10955−+ toResponse (TRespR r)= toResponse r
10956−+
10957−+instance ToResponse Response where
10958−+ toResponse = id
10959−+
10960−+instance ToResponse ByteString where
10961−+ toResponse x= responseLBS status200 [mkparam contentHtml] x
10962−+
10963−+instance ToResponse String where
10964−+ toResponse x= responseLBS status200 [mkparam contentHtml] $ fromString x
10965−+
10966−+instance ToResponse HttpData where
10967−+ toResponse (HttpData hs cookies x)= responseLBS status200 (mkParams ( hs <> cookieHeaders cookies)) x
10968−+ toResponse (Error str)= responseLBS status404 [("Content-Type", "text/html")] str
10969−+
10970−+-- toResponse $ error "FATAL ERROR: HttpData errors should not reach here: MFlow.Forms.Response.hs "
10971−+
10972−+
10973−+
10974−diff -ru orig/src/MFlow/Wai.hs new/src/MFlow/Wai.hs
10975−--- orig/src/MFlow/Wai.hs 2014-06-10 05:51:26.957015857 +0300
10976−+++ new/src/MFlow/Wai.hs 2014-06-10 05:51:25.000000000 +0300
10977−@@ -1,184 +1,209 @@
10978−-{-# LANGUAGE UndecidableInstances
10979−- , CPP
10980−- , TypeSynonymInstances
10981−- , MultiParamTypeClasses
10982−- , DeriveDataTypeable
10983−- , FlexibleInstances
10984−- , OverloadedStrings #-}
10985−-
10986−-module MFlow.Wai(
10987−- module MFlow.Cookies
10988−- ,module MFlow
10989−- ,waiMessageFlow)
10990−-where
10991−-
10992−-import Data.Typeable
10993−-import Network.Wai
10994−-
10995−-import Control.Concurrent.MVar(modifyMVar_, readMVar)
10996−-import Control.Monad(when)
10997−-
10998−-
10999−-import qualified Data.ByteString.Lazy.Char8 as B(empty,pack, unpack, length, ByteString,tail)
11000−-import Data.ByteString.Lazy(fromChunks)
11001−+{-# LANGUAGE UndecidableInstances
11002−+ , CPP
11003−+ , TypeSynonymInstances
11004−+ , MultiParamTypeClasses
11005−+ , DeriveDataTypeable
11006−+ , FlexibleInstances
11007−+ , OverloadedStrings #-}
11008−+
11009−+module MFlow.Wai(
11010−+ module MFlow.Cookies
11011−+ ,module MFlow
11012−+ ,waiMessageFlow)
11013−+where
11014−+
11015−+import Data.Typeable
11016−+import Network.Wai
11017−+
11018−+import Control.Concurrent.MVar(modifyMVar_, readMVar)
11019−+import Control.Monad(when)
11020−+
11021−+
11022−+import qualified Data.ByteString.Lazy.Char8 as B(empty,pack, unpack, length, ByteString,tail)
11023−+import Data.ByteString.Lazy(fromChunks)
11024− import Data.ByteString.UTF8 hiding (span)
11025−-import qualified Data.ByteString as SB hiding (pack, unpack)
11026−-import Control.Concurrent(ThreadId(..))
11027−-import System.IO.Unsafe
11028−-import Control.Concurrent.MVar
11029−-import Control.Concurrent
11030−-import Control.Monad.Trans
11031−-import Control.Exception
11032−-import qualified Data.Map as M
11033−-import Data.Maybe
11034−-import Data.TCache
11035−-import Data.TCache.DefaultPersistence
11036−-import Control.Workflow hiding (Indexable(..))
11037−-
11038−-import MFlow
11039−-import MFlow.Cookies
11040−-import Data.Monoid
11041−-import MFlow.Wai.Response
11042−-import Network.Wai
11043−-import Network.HTTP.Types -- hiding (urlDecode)
11044−-import Data.Conduit
11045−-import Data.Conduit.Lazy
11046−-import qualified Data.Conduit.List as CList
11047−-import Data.CaseInsensitive
11048−-import System.Time
11049−-import qualified Data.Text as T
11050−-
11051−-
11052−---import Debug.Trace
11053−---(!>) = flip trace
11054−-
11055−-flow= "flow"
11056−-
11057−-instance Processable Request where
11058−- pwfPath env= if Prelude.null sc then [noScript] else Prelude.map T.unpack sc
11059−- where
11060−- sc= let p= pathInfo env
11061−- p'= reverse p
11062−- in case p' of
11063−- [] -> []
11064−- p' -> if T.null $ head p' then reverse(tail p') else p
11065−-
11066−-
11067−- puser env = fromMaybe anonymous $ fmap toString $ lookup ( mk $ fromString cookieuser) $ requestHeaders env
11068−-
11069−- pind env= fromMaybe (error ": No FlowID") $ fmap toString $ lookup (mk flow) $ requestHeaders env
11070−- getParams= mkParams1 . requestHeaders
11071−- where
11072−- mkParams1 = Prelude.map mkParam1
11073−- mkParam1 ( x,y)= (toString $ original x, toString y)
11074−-
11075−--- getServer env= serverName env
11076−--- getPath env= pathInfo env
11077−--- getPort env= serverPort env
11078−-
11079−-
11080−-splitPath ""= ("","","")
11081−-splitPath str=
11082−- let
11083−- strr= reverse str
11084−- (ext, rest)= span (/= '.') strr
11085−- (mod, path)= span(/='/') $ tail rest
11086−- in (tail $ reverse path, reverse mod, reverse ext)
11087−-
11088−-
11089−-waiMessageFlow :: Application
11090−-waiMessageFlow req1= do
11091−- let httpreq1= requestHeaders req1
11092−-
11093−- let cookies = getCookies httpreq1
11094−-
11095−- (flowval , retcookies) <- case lookup flow cookies of
11096−- Just fl -> return (fl, [])
11097−- Nothing -> do
11098−- fl <- liftIO $ newFlow
11099−- return (fl, [UnEncryptedCookie (flow, fl, "/",Nothing):: Cookie])
11100−-
11101−-{- for state persistence in cookies
11102−- putStateCookie req1 cookies
11103−- let retcookies= case getStateCookie req1 of
11104−- Nothing -> retcookies1
11105−- Just ck -> ck:retcookies1
11106−--}
11107−-
11108−- input <- case parseMethod $ requestMethod req1 of
11109−- Right POST -> do
11110−-
11111−- inp <- liftIO $ requestBody req1 $$ CList.consume
11112−-
11113−- return . parseSimpleQuery $ SB.concat inp
11114−-
11115−-
11116−-
11117−- Right GET ->
11118−- return . Prelude.map (\(x,y) -> (x,fromMaybe "" y)) $ queryString req1
11119−-
11120−-
11121−- let req = case retcookies of
11122−- [] -> req1{requestHeaders= mkParams (input ++ cookies) ++ requestHeaders req1} -- !> "REQ"
11123−- _ -> req1{requestHeaders= mkParams ((flow, flowval): input ++ cookies) ++ requestHeaders req1} -- !> "REQ"
11124−-
11125−-
11126−- (resp',th) <- liftIO $ msgScheduler req -- !> (show $ requestHeaders req)
11127−-
11128−- let resp= case (resp',retcookies) of
11129−- (_,[]) -> resp'
11130−- (error@(Error _),_) -> error
11131−- (HttpData hs co str,_) -> HttpData hs (co++ retcookies) str
11132−-
11133−- return $ toResponse resp
11134−-
11135−-
11136−-------persistent state in cookies (not tested)
11137−-
11138−-tvresources :: MVar (Maybe ( M.Map string string))
11139−-tvresources= unsafePerformIO $ newMVar Nothing
11140−-statCookieName= "stat"
11141−-
11142−-putStateCookie req cookies=
11143−- case lookup statCookieName cookies of
11144−- Nothing -> return ()
11145−- Just (statCookieName, str , "/", _) -> modifyMVar_ tvresources $
11146−- \mmap -> case mmap of
11147−- Just map -> return $ Just $ M.insert (keyResource req) str map
11148−- Nothing -> return $ Just $ M.fromList [((keyResource req), str) ]
11149−-
11150−-getStateCookie req= do
11151−- mr<- readMVar tvresources
11152−- case mr of
11153−- Nothing -> return Nothing
11154−- Just map -> case M.lookup (keyResource req) map of
11155−- Nothing -> return Nothing
11156−- Just str -> do
11157−- swapMVar tvresources Nothing
11158−- return $ Just (statCookieName, str , "/")
11159−-
11160−-
11161−-
11162−-
11163−-{-
11164−-persistInCookies= setPersist PersistStat{readStat=readResource, writeStat=writeResource, deleteStat=deleteResource}
11165−- where
11166−- writeResource stat= modifyMVar_ tvresources $ \mmap ->
11167−- case mmap of
11168−- Just map-> return $ Just $ M.insert (keyResource stat) (serialize stat) map
11169−- Nothing -> return $ Just $ M.fromList [((keyResource stat), (serialize stat)) ]
11170−- readResource stat= do
11171−- mstr <- withMVar tvresources $ \mmap ->
11172−- case mmap of
11173−- Just map -> return $ M.lookup (keyResource stat) map
11174−- Nothing -> return Nothing
11175−- case mstr of
11176−- Nothing -> return Nothing
11177−- Just str -> return $ deserialize str
11178−-
11179−- deleteResource stat= modifyMVar_ tvresources $ \mmap->
11180−- case mmap of
11181−- Just map -> return $ Just $ M.delete (keyResource stat) map
11182−- Nothing -> return $ Nothing
11183−-
11184−--}
11185−+import qualified Data.ByteString.Char8 as SB -- hiding (pack, unpack)
11186−+import Control.Concurrent(ThreadId(..))
11187−+import System.IO.Unsafe
11188−+import Control.Concurrent.MVar
11189−+import Control.Concurrent
11190−+import Control.Monad.Trans
11191−+import Control.Exception
11192−+import qualified Data.Map as M
11193−+import Data.Maybe
11194−+import Data.TCache
11195−+import Data.TCache.DefaultPersistence
11196−+import Control.Workflow hiding (Indexable(..))
11197−+
11198−+import MFlow
11199−+import MFlow.Cookies
11200−+import Data.Monoid
11201−+import MFlow.Wai.Response
11202−+import Network.Wai
11203−+import Network.Wai.Parse
11204−+import qualified Data.Conduit.Binary as CB
11205−+import Control.Monad.Trans.Resource
11206−+import Network.HTTP.Types
11207−+import Data.Conduit
11208−+import Data.Conduit.Lazy
11209−+import qualified Data.Conduit.List as CList
11210−+import Data.CaseInsensitive
11211−+import System.Time
11212−+import System.Directory
11213−+import System.IO
11214−+import qualified Data.Text as T
11215−+
11216−+
11217−+import Debug.Trace
11218−+(!>) = flip trace
11219−+
11220−+flow= "flow"
11221−+
11222−+instance Processable Request where
11223−+ pwfPath env= if Prelude.null sc then [noScript] else Prelude.map T.unpack sc
11224−+ where
11225−+ sc= let p= pathInfo env
11226−+ p'= reverse p
11227−+ in case p' of
11228−+ [] -> []
11229−+ p' -> if T.null $ head p' then reverse(tail p') else p
11230−+
11231−+
11232−+ puser env = fromMaybe anonymous $ fmap toString $ lookup ( mk $ fromString cookieuser) $ requestHeaders env
11233−+
11234−+ pind env= fromMaybe (error ": No FlowID") $ fmap toString $ lookup (mk flow) $ requestHeaders env
11235−+ getParams= mkParams1 . requestHeaders
11236−+ where
11237−+ mkParams1 = Prelude.map mkParam1
11238−+ mkParam1 ( x,y)= (toString $ original x, toString y)
11239−+
11240−+toApp :: (Request -> IO Response) -> Application
11241−+#if MIN_VERSION_wai(3, 0, 0)
11242−+toApp f req sendResponse = f req >>= sendResponse
11243−+#else
11244−+toApp = id
11245−+#endif
11246−+
11247−+waiMessageFlow :: Application
11248−+waiMessageFlow = toApp $ \req1 -> do
11249−+ let httpreq1= requestHeaders req1
11250−+
11251−+ let cookies = getCookies httpreq1
11252−+
11253−+ (flowval , retcookies) <- case lookup flow cookies of
11254−+ Just fl -> return (fl, [])
11255−+ Nothing -> do
11256−+ fl <- liftIO $ newFlow
11257−+ return (fl, [UnEncryptedCookie (flow, fl, "/",Nothing):: Cookie])
11258−+
11259−+{- for state persistence in cookies
11260−+ putStateCookie req1 cookies
11261−+ let retcookies= case getStateCookie req1 of
11262−+ Nothing -> retcookies1
11263−+ Just ck -> ck:retcookies1
11264−+-}
11265−+
11266−+ (params,files) <- case parseMethod $ requestMethod req1 of
11267−+ Right GET -> do
11268−+ return (Prelude.map (\(x,y) -> (x,fromMaybe "" y)) $ queryString req1,[])
11269−+
11270−+ Right POST -> do
11271−+
11272−+ case getRequestBodyType req1 of
11273−+ Nothing -> error $ "getRequestBodyType: "
11274−+ Just rbt ->
11275−+ runResourceT $ withInternalState $ \state -> liftIO $ do
11276−+ let backend file info= do
11277−+ (key, (fp, h)) <- flip runInternalState state $ allocate (do
11278−+ tempDir <- getTemporaryDirectory
11279−+ openBinaryTempFile tempDir "upload.tmp") (\(_, h) -> hClose h)
11280−+ CB.sinkHandle h
11281−+ lift $ release key
11282−+ return fp
11283−+#if MIN_VERSION_wai(3, 0, 0)
11284−+ let backend' file info getBS = do
11285−+ let src = do
11286−+ bs <- liftIO getBS
11287−+ when (not $ SB.null bs) $ do
11288−+ Data.Conduit.yield bs
11289−+ src
11290−+ src $$ backend file info
11291−+ sinkRequestBody backend' rbt (requestBody req1)
11292−+#else
11293−+ requestBody req1 $$ sinkRequestBody backend rbt
11294−+#endif
11295−+
11296−+-- let fileparams= Prelude.map (\(param,FileInfo filename contentype content)
11297−+-- -> (param, SB.pack content )) files
11298−+-- let fileparams= Prelude.map (\(param,fileinfo)
11299−+-- -> (param, fileinfo )) files
11300−+-- return $ fileparams++ params
11301−+ let filesp= Prelude.map (\(param,FileInfo filename contentype tempfile)
11302−+ -> (mk param, fromString $ show(filename,contentype,tempfile) )) files
11303−+-- let filesp= Prelude.map (\(a,b) -> ( mk a, fromString $ show b)) files
11304−+
11305−+
11306−+ let req = case retcookies of
11307−+ [] -> req1{requestHeaders= filesp ++ mkParams (params ++ cookies) ++ requestHeaders req1}
11308−+ _ -> req1{requestHeaders= filesp ++ mkParams ((flow, flowval): params ++ cookies) ++ requestHeaders req1}
11309−+
11310−+
11311−+ (resp',th) <- liftIO $ msgScheduler req -- !> (show $ requestHeaders req)
11312−+
11313−+ let resp= case (resp',retcookies) of
11314−+ (_,[]) -> resp'
11315−+ (error@(Error _),_) -> error
11316−+ (HttpData hs co str,_) -> HttpData hs (co++ retcookies) str
11317−+
11318−+ return $ toResponse resp
11319−+
11320−+
11321−+------persistent state in cookies (not tested)
11322−+
11323−+tvresources :: MVar (Maybe ( M.Map string string))
11324−+tvresources= unsafePerformIO $ newMVar Nothing
11325−+statCookieName= "stat"
11326−+
11327−+putStateCookie req cookies=
11328−+ case lookup statCookieName cookies of
11329−+ Nothing -> return ()
11330−+ Just (statCookieName, str , "/", _) -> modifyMVar_ tvresources $
11331−+ \mmap -> case mmap of
11332−+ Just map -> return $ Just $ M.insert (keyResource req) str map
11333−+ Nothing -> return $ Just $ M.fromList [((keyResource req), str) ]
11334−+
11335−+getStateCookie req= do
11336−+ mr<- readMVar tvresources
11337−+ case mr of
11338−+ Nothing -> return Nothing
11339−+ Just map -> case M.lookup (keyResource req) map of
11340−+ Nothing -> return Nothing
11341−+ Just str -> do
11342−+ swapMVar tvresources Nothing
11343−+ return $ Just (statCookieName, str , "/")
11344−+
11345−+
11346−+
11347−+
11348−+{-
11349−+persistInCookies= setPersist PersistStat{readStat=readResource, writeStat=writeResource, deleteStat=deleteResource}
11350−+ where
11351−+ writeResource stat= modifyMVar_ tvresources $ \mmap ->
11352−+ case mmap of
11353−+ Just map-> return $ Just $ M.insert (keyResource stat) (serialize stat) map
11354−+ Nothing -> return $ Just $ M.fromList [((keyResource stat), (serialize stat)) ]
11355−+ readResource stat= do
11356−+ mstr <- withMVar tvresources $ \mmap ->
11357−+ case mmap of
11358−+ Just map -> return $ M.lookup (keyResource stat) map
11359−+ Nothing -> return Nothing
11360−+ case mstr of
11361−+ Nothing -> return Nothing
11362−+ Just str -> return $ deserialize str
11363−+
11364−+ deleteResource stat= modifyMVar_ tvresources $ \mmap->
11365−+ case mmap of
11366−+ Just map -> return $ Just $ M.delete (keyResource stat) map
11367−+ Nothing -> return $ Nothing
11368−+
11369−+-}
11370−diff -ru orig/src/MFlow.hs new/src/MFlow.hs
11371−--- orig/src/MFlow.hs 2014-06-10 05:51:26.957015857 +0300
11372−+++ new/src/MFlow.hs 2014-06-10 05:51:25.000000000 +0300
11373−@@ -1,545 +1,550 @@
11374−-{- | Non monadic low level primitives that implement the MFlow application server.
11375−-See "MFlow.Form" for the higher level interface that you may use.
11376−-
11377−-it implements an scheduler of 'Processable' messages that are served according with
11378−-the source identification and the verb invoked.
11379−-The scheduler executed the appropriate workflow (using the workflow package).
11380−-The workflow will send additional messages to the source and wait for the responses.
11381−-The diaglog is identified by a 'Token', which is associated to the flow.
11382−-. The computation state is optionally logged. On timeout, the process is killed. When invoked again,
11383−-the execution state is recovered as if no interruption took place.
11384−-
11385−-There is no asumption about message codification, so instantiations
11386−-of this scheduler for different infrastructures is possible,
11387−-including non-Web based ones as long as they support or emulate cookies.
11388−-
11389−-"MFlow.Hack" is an instantiation for the Hack interface in a Web context.
11390−-
11391−-"MFlow.Wai" is a instantiation for the WAI interface.
11392−-
11393−-"MFlow.Forms" implements a monadic type safe interface with composabe widgets and and applicative
11394−-combinator as well as an higher comunication interface.
11395−-
11396−-"MFlow.Forms.XHtml" is an instantiation for the Text.XHtml format
11397−-
11398−-"MFlow.Forms.Blaze.Html" is an instantaiation for blaze-html
11399−-
11400−-"MFlow.Forms.HSP" is an instantiation for the Haskell Server Pages format
11401−-
11402−-There are some @*.All@ packages that contain a mix of these instantiations.
11403−-For exmaple, "MFlow.Wai.Blaze.Html.All" includes most of all necessary for using MFlow with
11404−-Wai <http://hackage.haskell.org/package/wai> and
11405−-Blaze-html <http://hackage.haskell.org/package/blaze-html>
11406−-
11407−-
11408−-In order to manage resources, there are primitives that kill the process and its state after a timeout.
11409−-
11410−-All these details are hidden in the monad of "MFlow.Forms" that provides an higher level interface.
11411−-
11412−-Fragment based streaming: 'sendFragment' are provided only at this level.
11413−-
11414−-'stateless' and 'transient' server processeses are also possible. the first are request-response
11415−- . `transient` processes do not persist after timeout, so they restart anew after a timeout or a crash.
11416−-
11417−--}
11418−-
11419−-
11420−-{-# LANGUAGE DeriveDataTypeable, UndecidableInstances
11421−- ,ExistentialQuantification
11422−- ,MultiParamTypeClasses
11423−- ,FunctionalDependencies
11424−- ,TypeSynonymInstances
11425−- ,FlexibleInstances
11426−- ,FlexibleContexts
11427−- ,RecordWildCards
11428−- ,OverloadedStrings
11429−- ,ScopedTypeVariables
11430−-
11431−- #-}
11432−-module MFlow (
11433−-Flow, Params, HttpData(..),Processable(..)
11434−-, Token(..), ProcList
11435−--- * low level comunication primitives. Use `ask` instead
11436−-,flushRec, flushResponse, receive, receiveReq, receiveReqTimeout, send, sendFlush, sendFragment
11437−-, sendEndFragment, sendToMF
11438−--- * Flow configuration
11439−-,setNoScript,addMessageFlows,getMessageFlows,delMessageFlow, transient, stateless,anonymous
11440−-,noScript,hlog, setNotFoundResponse,getNotFoundResponse,
11441−--- * ByteString tags
11442−--- | very basic but efficient bytestring tag formatting
11443−-btag, bhtml, bbody,Attribs, addAttrs
11444−--- * user
11445−-, userRegister, setAdminUser, getAdminName, Auth(..),getAuthMethod, setAuthMethod
11446−+{- | Non monadic low level primitives that implement the MFlow application server.
11447−+See "MFlow.Form" for the higher level interface that you may use.
11448−+
11449−+it implements an scheduler of 'Processable' messages that are served according with
11450−+the source identification and the verb invoked.
11451−+The scheduler executed the appropriate workflow (using the workflow package).
11452−+The workflow will send additional messages to the source and wait for the responses.
11453−+The diaglog is identified by a 'Token', which is associated to the flow.
11454−+. The computation state is optionally logged. On timeout, the process is killed. When invoked again,
11455−+the execution state is recovered as if no interruption took place.
11456−+
11457−+There is no asumption about message codification, so instantiations
11458−+of this scheduler for different infrastructures is possible,
11459−+including non-Web based ones as long as they support or emulate cookies.
11460−+
11461−+"MFlow.Hack" is an instantiation for the Hack interface in a Web context.
11462−+
11463−+"MFlow.Wai" is a instantiation for the WAI interface.
11464−+
11465−+"MFlow.Forms" implements a monadic type safe interface with composabe widgets and and applicative
11466−+combinator as well as an higher comunication interface.
11467−+
11468−+"MFlow.Forms.XHtml" is an instantiation for the Text.XHtml format
11469−+
11470−+"MFlow.Forms.Blaze.Html" is an instantaiation for blaze-html
11471−+
11472−+"MFlow.Forms.HSP" is an instantiation for the Haskell Server Pages format
11473−+
11474−+There are some @*.All@ packages that contain a mix of these instantiations.
11475−+For exmaple, "MFlow.Wai.Blaze.Html.All" includes most of all necessary for using MFlow with
11476−+Wai <http://hackage.haskell.org/package/wai> and
11477−+Blaze-html <http://hackage.haskell.org/package/blaze-html>
11478−+
11479−+
11480−+In order to manage resources, there are primitives that kill the process and its state after a timeout.
11481−+
11482−+All these details are hidden in the monad of "MFlow.Forms" that provides an higher level interface.
11483−+
11484−+Fragment based streaming: 'sendFragment' are provided only at this level.
11485−+
11486−+'stateless' and 'transient' server processeses are also possible. the first are request-response
11487−+ . `transient` processes do not persist after timeout, so they restart anew after a timeout or a crash.
11488−+
11489−+-}
11490−+
11491−+
11492−+{-# LANGUAGE DeriveDataTypeable, UndecidableInstances
11493−+ ,ExistentialQuantification
11494−+ ,MultiParamTypeClasses
11495−+ ,FunctionalDependencies
11496−+ ,TypeSynonymInstances
11497−+ ,FlexibleInstances
11498−+ ,FlexibleContexts
11499−+ ,RecordWildCards
11500−+ ,OverloadedStrings
11501−+ ,ScopedTypeVariables
11502−+ ,BangPatterns
11503−+ #-}
11504−+module MFlow (
11505−+Flow, Params, HttpData(..),Processable(..)
11506−+, Token(..), ProcList
11507−+-- * low level comunication primitives. Use `ask` instead
11508−+,flushRec, flushResponse, receive, receiveReq, receiveReqTimeout, send, sendFlush, sendFragment
11509−+, sendEndFragment, sendToMF
11510−+-- * Flow configuration
11511−+,setNoScript,addMessageFlows,getMessageFlows,delMessageFlow, transient, stateless,anonymous
11512−+,noScript,hlog, setNotFoundResponse,getNotFoundResponse,
11513−+-- * ByteString tags
11514−+-- | very basic but efficient bytestring tag formatting
11515−+btag, bhtml, bbody,Attribs, addAttrs
11516−+-- * user
11517−+, userRegister, setAdminUser, getAdminName, Auth(..),getAuthMethod, setAuthMethod
11518− -- * static files
11519− -- * config
11520−-,config, getConfig
11521−-,setFilesPath
11522−--- * internal use
11523−-,addTokenToList,deleteTokenInList, msgScheduler,serveFile,newFlow
11524−-,UserStr,PasswdStr, User(..),eUser
11525−-
11526−-)
11527−-where
11528−-import Control.Concurrent.MVar
11529−-import Data.IORef
11530−-import GHC.Conc(unsafeIOToSTM)
11531−-import Data.Typeable
11532−-import Data.Maybe(isJust, isNothing, fromMaybe, fromJust)
11533−-import Data.Char(isSeparator)
11534−-import Data.List(isPrefixOf,isSuffixOf,isInfixOf, elem , span, (\\),intersperse)
11535−-import Control.Monad(when)
11536−-
11537−-import Data.Monoid
11538−-import Control.Concurrent(forkIO,threadDelay,killThread, myThreadId, ThreadId)
11539−-import Data.Char(toLower)
11540−-
11541−-import Unsafe.Coerce
11542−-import System.IO.Unsafe
11543−-import Data.TCache
11544−-import Data.TCache.DefaultPersistence hiding(Indexable(..))
11545−-import Data.TCache.Memoization
11546−-import qualified Data.ByteString.Lazy.Char8 as B (head, readFile,ByteString, concat,pack, unpack,empty,append,cons,fromChunks)
11547−-import Data.ByteString.Lazy.Internal (ByteString(Chunk))
11548−-import qualified Data.ByteString.Char8 as SB
11549−-import qualified Data.Map as M
11550−-import System.IO
11551−-import System.Time
11552−-import Control.Workflow
11553−-import MFlow.Cookies
11554−-import Control.Monad.Trans
11555−-import qualified Control.Exception as CE
11556−-import Data.RefSerialize hiding (empty)
11557−-import qualified Data.Text as T
11558−-import System.Posix.Internals
11559−-import Control.Exception
11560−---import Debug.Trace
11561−---(!>) = flip trace
11562−-
11563−-
11564−--- | a Token identifies a flow that handle messages. The scheduler compose a Token with every `Processable`
11565−--- message that arrives and send the mesage to the appropriate flow.
11566−-data Token = Token{twfname,tuser, tind :: String , tpath :: [String], tenv:: Params, tblock:: MVar Bool, tsendq :: MVar Req, trecq :: MVar Resp} deriving Typeable
11567−-
11568−-instance Indexable Token where
11569−- key (Token w u i _ _ _ _ _ )= i
11570−--- if u== anonymous then u ++ i -- ++ "@" ++ w
11571−--- else u -- ++ "@" ++ w
11572−-
11573−-instance Show Token where
11574−- show t = "Token " ++ key t
11575−-
11576−-instance Read Token where
11577−- readsPrec _ ('T':'o':'k':'e': 'n':' ':str1)
11578−- | anonymous `isPrefixOf` str1= [(Token w anonymous i [] [] (newVar True) (newVar 0) (newVar 0), tail str2)]
11579−- | otherwise = [(Token w ui "0" [] [] (newVar True) (newVar 0) (newVar 0), tail str2)]
11580−-
11581−- where
11582−-
11583−- (ui,str')= span(/='@') str1
11584−- i = drop (length anonymous) ui
11585−- (w,str2) = span (not . isSeparator) $ tail str'
11586−- newVar _= unsafePerformIO $ newEmptyMVar
11587−-
11588−-
11589−- readsPrec _ str= error $ "parse error in Token read from: "++ str
11590−-
11591−-instance Serializable Token where
11592−- serialize = B.pack . show
11593−- deserialize= read . B.unpack
11594−- setPersist = \_ -> Just filePersist
11595−-
11596−-iorefqmap= unsafePerformIO . newMVar $ M.empty
11597−-
11598−-addTokenToList t@Token{..} =
11599−- modifyMVar_ iorefqmap $ \ map ->
11600−- return $ M.insert ( tind ++ twfname ++ tuser ) t map
11601−-
11602−-deleteTokenInList t@Token{..} =
11603−- modifyMVar_ iorefqmap $ \ map ->
11604−- return $ M.delete (tind ++ twfname ++ tuser) map
11605−-
11606−-getToken msg= do
11607−- qmap <- readMVar iorefqmap
11608−- let u= puser msg ; w= pwfname msg ; i=pind msg; ppath=pwfPath msg;penv= getParams msg
11609−- let mqs = M.lookup ( i ++ w ++ u) qmap
11610−- case mqs of
11611−- Nothing -> do
11612−- q <- newEmptyMVar -- `debug` (i++w++u)
11613−+,config,getConfig
11614−+,setFilesPath
11615−+-- * internal use
11616−+,addTokenToList,deleteTokenInList, msgScheduler,serveFile,newFlow
11617−+,UserStr,PasswdStr, User(..),eUser
11618−+
11619−+)
11620−+where
11621−+import Control.Concurrent.MVar
11622−+import Data.IORef
11623−+import GHC.Conc(unsafeIOToSTM)
11624−+import Data.Typeable
11625−+import Data.Maybe(isJust, isNothing, fromMaybe, fromJust)
11626−+import Data.Char(isSeparator)
11627−+import Data.List(isPrefixOf,isSuffixOf,isInfixOf, elem , span, (\\),intersperse)
11628−+import Control.Monad(when)
11629−+
11630−+import Data.Monoid
11631−+import Control.Concurrent(forkIO,threadDelay,killThread, myThreadId, ThreadId)
11632−+import Data.Char(toLower)
11633−+
11634−+import Unsafe.Coerce
11635−+import System.IO.Unsafe
11636−+import Data.TCache
11637−+import Data.TCache.DefaultPersistence hiding(Indexable(..))
11638−+import Data.TCache.Memoization
11639−+import qualified Data.ByteString.Lazy.Char8 as B (head, readFile,ByteString, concat,pack, unpack,empty,append,cons,fromChunks)
11640−+import Data.ByteString.Lazy.Internal (ByteString(Chunk))
11641−+import qualified Data.ByteString.Char8 as SB
11642−+import qualified Data.Map as M
11643−+import System.IO
11644−+import System.Time
11645−+import Control.Workflow
11646−+import MFlow.Cookies
11647−+import Control.Monad.Trans
11648−+import qualified Control.Exception as CE
11649−+import Data.RefSerialize hiding (empty)
11650−+import qualified Data.Text as T
11651−+import System.Posix.Internals
11652−+import Control.Exception
11653−+import Crypto.PasswordStore
11654−+
11655−+
11656−+--import Debug.Trace
11657−+--(!>) = flip trace
11658−+
11659−+
11660−+-- | a Token identifies a flow that handle messages. The scheduler compose a Token with every `Processable`
11661−+-- message that arrives and send the mesage to the appropriate flow.
11662−+data Token = Token{twfname,tuser, tind :: String , tpath :: [String], tenv:: Params, tblock:: MVar Bool, tsendq :: MVar Req, trecq :: MVar Resp} deriving Typeable
11663−+
11664−+instance Indexable Token where
11665−+ key (Token w u i _ _ _ _ _ )= i
11666−+-- if u== anonymous then u ++ i -- ++ "@" ++ w
11667−+-- else u -- ++ "@" ++ w
11668−+
11669−+instance Show Token where
11670−+ show t = "Token " ++ key t
11671−+
11672−+instance Read Token where
11673−+ readsPrec _ ('T':'o':'k':'e': 'n':' ':str1)
11674−+ | anonymous `isPrefixOf` str1= [(Token w anonymous i [] [] (newVar True) (newVar 0) (newVar 0), tail str2)]
11675−+ | otherwise = [(Token w ui "0" [] [] (newVar True) (newVar 0) (newVar 0), tail str2)]
11676−+
11677−+ where
11678−+
11679−+ (ui,str')= span(/='@') str1
11680−+ i = drop (length anonymous) ui
11681−+ (w,str2) = span (not . isSeparator) $ tail str'
11682−+ newVar _= unsafePerformIO $ newEmptyMVar
11683−+
11684−+
11685−+ readsPrec _ str= error $ "parse error in Token read from: "++ str
11686−+
11687−+instance Serializable Token where
11688−+ serialize = B.pack . show
11689−+ deserialize= read . B.unpack
11690−+ setPersist = \_ -> Just filePersist
11691−+
11692−+iorefqmap= unsafePerformIO . newMVar $ M.empty
11693−+
11694−+addTokenToList t@Token{..} =
11695−+ modifyMVar_ iorefqmap $ \ map ->
11696−+ return $ M.insert ( tind ++ twfname ++ tuser ) t map
11697−+
11698−+deleteTokenInList t@Token{..} =
11699−+ modifyMVar_ iorefqmap $ \ map ->
11700−+ return $ M.delete (tind ++ twfname ++ tuser) map
11701−+
11702−+getToken msg= do
11703−+ qmap <- readMVar iorefqmap
11704−+ let u= puser msg ; w= pwfname msg ; i=pind msg; ppath=pwfPath msg;penv= getParams msg
11705−+ let mqs = M.lookup ( i ++ w ++ u) qmap
11706−+ case mqs of
11707−+ Nothing -> do
11708−+ q <- newEmptyMVar -- `debug` (i++w++u)
11709− qr <- newEmptyMVar
11710−- pblock <- newMVar True
11711−- let token= Token w u i ppath penv pblock q qr
11712−- addTokenToList token
11713−- return token
11714−-
11715−- Just token -> return token{tpath= ppath, tenv= penv}
11716−-
11717−-
11718−-type Flow= (Token -> Workflow IO ())
11719−-
11720−-data HttpData = HttpData [(SB.ByteString,SB.ByteString)] [Cookie] ByteString | Error ByteString deriving (Typeable, Show)
11721−-
11722−-
11723−-instance Monoid HttpData where
11724−- mempty= HttpData [] [] B.empty
11725−- mappend (HttpData h c s) (HttpData h' c' s')= HttpData (h++h') (c++ c') $ mappend s s'
11726−-
11727−--- | List of (wfname, workflow) pairs, to be scheduled depending on the message's pwfname
11728−-type ProcList = WorkflowList IO Token ()
11729−-
11730−-
11731−-data Req = forall a.( Processable a, Typeable a)=> Req a deriving Typeable
11732−-
11733−-type Params = [(String,String)]
11734−-
11735−-class Processable a where
11736−- pwfname :: a -> String
11737−- pwfname s= Prelude.head $ pwfPath s
11738−- pwfPath :: a -> [String]
11739−- puser :: a -> String
11740−- pind :: a -> String
11741−- getParams :: a -> Params
11742−-
11743−-instance Processable Token where
11744−- pwfname = twfname
11745−- pwfPath = tpath
11746−- puser = tuser
11747−- pind = tind
11748−- getParams = tenv
11749−-
11750−-instance Processable Req where
11751−- pwfname (Req x)= pwfname x
11752−- pwfPath (Req x)= pwfPath x
11753−- puser (Req x)= puser x
11754−- pind (Req x)= pind x
11755−- getParams (Req x)= getParams x
11756−--- getServer (Req x)= getServer x
11757−--- getPort (Req x)= getPort x
11758−-
11759−-data Resp = Fragm HttpData
11760−- | EndFragm HttpData
11761−- | Resp HttpData
11762−-
11763−-
11764−-
11765−-
11766−--- | The anonymous user
11767−-anonymous= "anon#"
11768−-
11769−--- | It is the path of the root flow
11770−+ pblock <- newMVar True
11771−+ let token= Token w u i ppath penv pblock q qr
11772−+ addTokenToList token
11773−+ return token
11774−+
11775−+ Just token -> return token{tpath= ppath, tenv= penv}
11776−+
11777−+
11778−+type Flow= (Token -> Workflow IO ())
11779−+
11780−+data HttpData = HttpData [(SB.ByteString,SB.ByteString)] [Cookie] ByteString | Error ByteString deriving (Typeable, Show)
11781−+
11782−+
11783−+instance Monoid HttpData where
11784−+ mempty= HttpData [] [] B.empty
11785−+ mappend (HttpData h c s) (HttpData h' c' s')= HttpData (h++h') (c++ c') $ mappend s s'
11786−+
11787−+-- | List of (wfname, workflow) pairs, to be scheduled depending on the message's pwfname
11788−+type ProcList = WorkflowList IO Token ()
11789−+
11790−+
11791−+data Req = forall a.( Processable a, Typeable a)=> Req a deriving Typeable
11792−+
11793−+type Params = [(String,String)]
11794−+
11795−+class Processable a where
11796−+ pwfname :: a -> String
11797−+ pwfname s= Prelude.head $ pwfPath s
11798−+ pwfPath :: a -> [String]
11799−+ puser :: a -> String
11800−+ pind :: a -> String
11801−+ getParams :: a -> Params
11802−+
11803−+instance Processable Token where
11804−+ pwfname = twfname
11805−+ pwfPath = tpath
11806−+ puser = tuser
11807−+ pind = tind
11808−+ getParams = tenv
11809−+
11810−+instance Processable Req where
11811−+ pwfname (Req x)= pwfname x
11812−+ pwfPath (Req x)= pwfPath x
11813−+ puser (Req x)= puser x
11814−+ pind (Req x)= pind x
11815−+ getParams (Req x)= getParams x
11816−+-- getServer (Req x)= getServer x
11817−+-- getPort (Req x)= getPort x
11818−+
11819−+data Resp = Fragm HttpData
11820−+ | EndFragm HttpData
11821−+ | Resp HttpData
11822−+
11823−+
11824−+
11825−+
11826−+-- | The anonymous user
11827−+anonymous= "anon#"
11828−+
11829−+-- | It is the path of the root flow
11830− noScriptRef= unsafePerformIO $ newIORef "noscript"
11831−-
11832−-noScript= unsafePerformIO $ readIORef noScriptRef
11833−+
11834−+noScript= unsafePerformIO $ readIORef noScriptRef
11835−
11836− -- | set the flow to be executed when the URL has no path. The home page.
11837− --
11838− -- By default it is "noscript".
11839− -- Although it is changed by `runNavigation` to his own flow name.
11840−-setNoScript scr= writeIORef noScriptRef scr
11841−-
11842−-{-
11843−-instance (Monad m, Show a) => Traceable (Workflow m a) where
11844−- debugf iox str = do
11845−- x <- iox
11846−- return $ debug x (str++" => Workflow "++ show x)
11847−--}
11848−--- | send a complete response
11849−---send :: Token -> HttpData -> IO()
11850−-send t@(Token _ _ _ _ _ _ _ qresp) msg= do
11851−- ( putMVar qresp . Resp $ msg ) -- !> ("<<<<< send "++ show t)
11852−-
11853−-sendFlush t msg= flushRec t >> send t msg -- !> "sendFlush "
11854−-
11855−--- | send a response fragment. Useful for streaming. the last packet must be sent trough 'send'
11856−-sendFragment :: Token -> HttpData -> IO()
11857−-sendFragment (Token _ _ _ _ _ _ _ qresp) msg= putMVar qresp . Fragm $ msg
11858−-
11859−-{-# DEPRECATED sendEndFragment "use \"send\" to end a fragmented response instead" #-}
11860−-sendEndFragment :: Token -> HttpData -> IO()
11861−-sendEndFragment (Token _ _ _ _ _ _ _ qresp) msg= putMVar qresp $ EndFragm msg
11862−-
11863−---emptyReceive (Token queue _ _)= emptyQueue queue
11864−-receive :: Typeable a => Token -> IO a
11865−-receive t= receiveReq t >>= return . fromReq
11866−-
11867−-flushResponse t@(Token _ _ _ _ _ _ _ qresp)= tryTakeMVar qresp
11868−-
11869−-
11870−-flushRec t@(Token _ _ _ _ _ _ queue _)= tryTakeMVar queue -- !> "flushRec"
11871−-
11872−-receiveReq :: Token -> IO Req
11873−+setNoScript scr= writeIORef noScriptRef scr
11874−+
11875−+{-
11876−+instance (Monad m, Show a) => Traceable (Workflow m a) where
11877−+ debugf iox str = do
11878−+ x <- iox
11879−+ return $ debug x (str++" => Workflow "++ show x)
11880−+-}
11881−+-- | send a complete response
11882−+--send :: Token -> HttpData -> IO()
11883−+send t@(Token _ _ _ _ _ _ _ qresp) msg= do
11884−+ ( putMVar qresp . Resp $ msg ) -- !> ("<<<<< send "++ show t)
11885−+
11886−+sendFlush t msg= flushRec t >> send t msg -- !> "sendFlush "
11887−+
11888−+-- | send a response fragment. Useful for streaming. the last packet must be sent trough 'send'
11889−+sendFragment :: Token -> HttpData -> IO()
11890−+sendFragment (Token _ _ _ _ _ _ _ qresp) msg= putMVar qresp . Fragm $ msg
11891−+
11892−+{-# DEPRECATED sendEndFragment "use \"send\" to end a fragmented response instead" #-}
11893−+sendEndFragment :: Token -> HttpData -> IO()
11894−+sendEndFragment (Token _ _ _ _ _ _ _ qresp) msg= putMVar qresp $ EndFragm msg
11895−+
11896−+--emptyReceive (Token queue _ _)= emptyQueue queue
11897−+receive :: Typeable a => Token -> IO a
11898−+receive t= receiveReq t >>= return . fromReq
11899−+
11900−+flushResponse t@(Token _ _ _ _ _ _ _ qresp)= tryTakeMVar qresp
11901−+
11902−+
11903−+flushRec t@(Token _ _ _ _ _ _ queue _)= tryTakeMVar queue -- !> "flushRec"
11904−+
11905−+receiveReq :: Token -> IO Req
11906− receiveReq t@(Token _ _ _ _ _ _ queue _)= do
11907− r <- readMVar queue -- !> (">>>>>> receiveReq ")
11908−- return r -- !> "receiveReq >>>>"
11909−-
11910−-fromReq :: Typeable a => Req -> a
11911−-fromReq (Req x) = x' where
11912−- x'= case cast x of
11913−- Nothing -> error $ "receive: received type: "++ show (typeOf x) ++ " does not match the desired type:" ++ show (typeOf x')
11914−- Just y -> y
11915−-
11916−-
11917−-receiveReqTimeout :: Int
11918−- -> Integer
11919−- -> Token
11920−- -> IO Req
11921−-receiveReqTimeout 0 0 t= receiveReq t
11922−-receiveReqTimeout time time2 t=
11923−- let id= keyWF (twfname t) t in withKillTimeout id time time2 (receiveReq t)
11924−-
11925−-
11926−-delMsgHistory t = do
11927−- let statKey= keyWF (twfname t) t -- !> "wf" --let qnme= keyWF wfname t
11928−- delWFHistory1 statKey -- `debug` "delWFHistory"
11929−-
11930−-
11931−-
11932−--- | executes a simple request-response computation that receive the params and return a response
11933−---
11934−--- It is used with `addMessageFlows`
11935−---
11936−--- There is a higuer level version @wstateless@ in "MFLow.Forms"
11937−-stateless :: (Params -> IO HttpData) -> Flow
11938−-stateless f = transient proc
11939−- where
11940−- proc t@(Token _ _ _ _ _ _ queue qresp) = loop t queue qresp
11941−- loop t queue qresp=do
11942−- req <- takeMVar queue -- !> (">>>>>> stateless " ++ thread t)
11943−- resp <- f (getParams req)
11944−- (putMVar qresp $ Resp resp ) -- !> ("<<<<<< stateless " ++thread t)
11945−- loop t queue qresp -- !> ("enviado stateless " ++ thread t)
11946−-
11947−-
11948−-
11949−--- | Executes a monadic computation that send and receive messages, but does
11950−--- not store its state in permanent storage. The process once stopped, will restart anew
11951−---
11952−----- It is used with `addMessageFlows` `hackMessageFlow` or `waiMessageFlow`
11953−-transient :: (Token -> IO ()) -> Flow
11954−-transient f= unsafeIOtoWF . f -- WF(\s -> f t>>= \x-> return (s, x) )
11955−-
11956−-
11957−-_messageFlows :: MVar (WorkflowList IO Token ()) -- MVar (M.Map String (Token -> Workflow IO ()))
11958−-_messageFlows= unsafePerformIO $ newMVar emptyFList
11959−- where
11960−- emptyFList= M.empty :: WorkflowList IO Token ()
11961−-
11962−--- | add a list of flows to be scheduled. Each entry in the list is a pair @(path, flow)@
11963−-addMessageFlows wfs= modifyMVar_ _messageFlows(\ms -> return $ M.union (M.fromList $ map flt wfs)ms)
11964−- where flt ("",f)= (noScript,f)
11965−- flt e= e
11966−-
11967−--- | return the list of the scheduler
11968−-getMessageFlows = readMVar _messageFlows
11969−-
11970−-delMessageFlow wfname= modifyMVar_ _messageFlows (\ms -> return $ M.delete wfname ms)
11971−-
11972−-
11973−-sendToMF Token{..} msg= putMVar tsendq (Req msg) -- !> "sendToMF"
11974−-
11975−---recFromMF :: (Typeable a, Typeable c, Processable a) => Token -> a -> IO c
11976−-recFromMF t@Token{..} = do
11977−- m <- takeMVar trecq -- !> "recFromMF <<<<<< "
11978−- case m of
11979−- Resp r -> return r -- !> "<<<<<< recFromMF"
11980−- Fragm r -> do
11981−- result <- getStream r
11982−- return result
11983−-
11984−- where
11985−- getStream r = do
11986−- mr <- takeMVar trecq
11987−- case mr of
11988−- Fragm h -> do
11989−- rest <- unsafeInterleaveIO $ getStream h
11990−- let result= mappend r rest
11991−- return result
11992−- EndFragm h -> do
11993−- let result= mappend r h
11994−- return result
11995−-
11996−- Resp h -> do
11997−- let result= mappend r h
11998−- return result
11999−-
12000−-
12001−-
12002−-
12003−--- | The scheduler creates a Token with every `Processable`
12004−--- message that arrives and send the mesage to the appropriate flow, then wait for the response
12005−--- and return it.
12006−---
12007−--- It is the core of the application server. "MFLow.Wai" and "MFlow.Hack" use it
12008−-msgScheduler
12009−- :: (Typeable a,Processable a)
12010−- => a -> IO (HttpData, ThreadId)
12011−-msgScheduler x = do
12012−+ return r -- !> "receiveReq >>>>"
12013−+
12014−+fromReq :: Typeable a => Req -> a
12015−+fromReq (Req x) = x' where
12016−+ x'= case cast x of
12017−+ Nothing -> error $ "receive: received type: "++ show (typeOf x) ++ " does not match the desired type:" ++ show (typeOf x')
12018−+ Just y -> y
12019−+
12020−+
12021−+receiveReqTimeout :: Int
12022−+ -> Integer
12023−+ -> Token
12024−+ -> IO Req
12025−+receiveReqTimeout 0 0 t= receiveReq t
12026−+receiveReqTimeout time time2 t=
12027−+ let id= keyWF (twfname t) t in withKillTimeout id time time2 (receiveReq t)
12028−+
12029−+
12030−+delMsgHistory t = do
12031−+ let statKey= keyWF (twfname t) t -- !> "wf" --let qnme= keyWF wfname t
12032−+ delWFHistory1 statKey -- `debug` "delWFHistory"
12033−+
12034−+
12035−+
12036−+-- | executes a simple request-response computation that receive the params and return a response
12037−+--
12038−+-- It is used with `addMessageFlows`
12039−+--
12040−+-- There is a higuer level version @wstateless@ in "MFLow.Forms"
12041−+stateless :: (Params -> IO HttpData) -> Flow
12042−+stateless f = transient proc
12043−+ where
12044−+ proc t@(Token _ _ _ _ _ _ queue qresp) = loop t queue qresp
12045−+ loop t queue qresp=do
12046−+ req <- takeMVar queue -- !> (">>>>>> stateless " ++ thread t)
12047−+ resp <- f (getParams req)
12048−+ (putMVar qresp $ Resp resp ) -- !> ("<<<<<< stateless " ++thread t)
12049−+ loop t queue qresp -- !> ("enviado stateless " ++ thread t)
12050−+
12051−+
12052−+
12053−+-- | Executes a monadic computation that send and receive messages, but does
12054−+-- not store its state in permanent storage. The process once stopped, will restart anew
12055−+--
12056−+---- It is used with `addMessageFlows` `hackMessageFlow` or `waiMessageFlow`
12057−+transient :: (Token -> IO ()) -> Flow
12058−+transient f= unsafeIOtoWF . f -- WF(\s -> f t>>= \x-> return (s, x) )
12059−+
12060−+
12061−+_messageFlows :: MVar (WorkflowList IO Token ()) -- MVar (M.Map String (Token -> Workflow IO ()))
12062−+_messageFlows= unsafePerformIO $ newMVar emptyFList
12063−+ where
12064−+ emptyFList= M.empty :: WorkflowList IO Token ()
12065−+
12066−+-- | add a list of flows to be scheduled. Each entry in the list is a pair @(path, flow)@
12067−+addMessageFlows wfs= modifyMVar_ _messageFlows(\ms -> return $ M.union (M.fromList $ map flt wfs)ms)
12068−+ where flt ("",f)= (noScript,f)
12069−+ flt e= e
12070−+
12071−+-- | return the list of the scheduler
12072−+getMessageFlows = readMVar _messageFlows
12073−+
12074−+delMessageFlow wfname= modifyMVar_ _messageFlows (\ms -> return $ M.delete wfname ms)
12075−+
12076−+
12077−+sendToMF Token{..} msg= putMVar tsendq (Req msg) -- !> "sendToMF"
12078−+
12079−+--recFromMF :: (Typeable a, Typeable c, Processable a) => Token -> a -> IO c
12080−+recFromMF t@Token{..} = do
12081−+ m <- takeMVar trecq -- !> "recFromMF <<<<<< "
12082−+ case m of
12083−+ Resp r -> return r -- !> "<<<<<< recFromMF"
12084−+ Fragm r -> do
12085−+ result <- getStream r
12086−+ return result
12087−+
12088−+ where
12089−+ getStream r = do
12090−+ mr <- takeMVar trecq
12091−+ case mr of
12092−+ Fragm h -> do
12093−+ rest <- unsafeInterleaveIO $ getStream h
12094−+ let result= mappend r rest
12095−+ return result
12096−+ EndFragm h -> do
12097−+ let result= mappend r h
12098−+ return result
12099−+
12100−+ Resp h -> do
12101−+ let result= mappend r h
12102−+ return result
12103−+
12104−+
12105−+
12106−+
12107−+-- | The scheduler creates a Token with every `Processable`
12108−+-- message that arrives and send the mesage to the appropriate flow, then wait for the response
12109−+-- and return it.
12110−+--
12111−+-- It is the core of the application server. "MFLow.Wai" and "MFlow.Hack" use it
12112−+msgScheduler
12113−+ :: (Typeable a,Processable a)
12114−+ => a -> IO (HttpData, ThreadId)
12115−+msgScheduler x = do
12116− token <- getToken x
12117−- th <- myThreadId
12118−+ th <- myThreadId
12119− let wfname = takeWhile (/='/') $ pwfname x
12120−- criticalSection (tblock token) $ do
12121−- sendToMF token x -- !> show th
12122−- th <- startMessageFlow wfname token
12123−- r <- recFromMF token
12124−- return (r,th) -- !> let HttpData _ _ r1=r in B.unpack r1
12125−+ criticalSection (tblock token) $ do
12126−+ sendToMF token x -- !> show th
12127−+ th <- startMessageFlow wfname token
12128−+ r <- recFromMF token
12129−+ return (r,th) -- !> let HttpData _ _ r1=r in B.unpack r1
12130− where
12131−- criticalSection mv f= bracket
12132−- (takeMVar mv)
12133−- (putMVar mv)
12134−+ criticalSection mv f= bracket
12135−+ (takeMVar mv)
12136−+ (putMVar mv)
12137− $ const $ f
12138−-
12139−- --start the flow if not started yet
12140−- startMessageFlow wfname token =
12141−- forkIO $ do
12142−- wfs <- getMessageFlows
12143−- r <- startWF wfname token wfs -- !>( "init wf " ++ wfname)
12144−- case r of
12145−- Left NotFound -> do
12146−- (sendFlush token =<< serveFile (pwfname x))
12147−+
12148−+ --start the flow if not started yet
12149−+ startMessageFlow wfname token =
12150−+ forkIO $ do
12151−+ wfs <- getMessageFlows
12152−+ r <- startWF wfname token wfs -- !>( "init wf " ++ wfname)
12153−+ case r of
12154−+ Left NotFound -> do
12155−+ (sendFlush token =<< serveFile (pwfname x))
12156− `CE.catch` \(e:: CE.SomeException) -> do
12157−- showError wfname token (show e)
12158−--- sendFlush token (Error NotFound $ "Not found: " <> pack wfname)
12159−- deleteTokenInList token
12160−-
12161−- Left AlreadyRunning -> return () -- !> ("already Running " ++ wfname)
12162−-
12163−- Left Timeout -> do
12164−- hFlush stdout -- !> ("TIMEOUT in msgScheduler" ++ (show $ unsafePerformIO myThreadId))
12165−- deleteTokenInList token
12166−-
12167−- Left (WFException e)-> do
12168−- showError wfname token e
12169−- moveState wfname token token{tind= "error/"++tuser token}
12170−- deleteTokenInList token -- !> "DELETETOKEN"
12171−-
12172−-
12173−- Right _ -> delMsgHistory token >> return () -- !> ("finished " ++ wfname)
12174−-
12175−-
12176−-
12177−-showError wfname token@Token{..} e= do
12178−- t <- return . calendarTimeToString =<< toCalendarTime =<< getClockTime
12179−- let msg= errorMessage t e tuser (Prelude.concat $ intersperse "/" tpath) tenv
12180−- logError msg
12181−- fresp <- getNotFoundResponse
12182−- let admin= getAdminName
12183−- sendFlush token . Error $ fresp (tuser== admin) $ Prelude.concat[ "<br/>"++ s | s <- lines msg]
12184−-
12185−-
12186−-errorMessage t e u path env=
12187−- "\n---------------------ERROR-------------------------\
12188−- \\nTIME=" ++ t ++"\n\n" ++
12189−- e++
12190−- "\n\nUSER= " ++ u ++
12191−- "\n\nPATH= " ++ path ++
12192−- "\n\nREQUEST:\n\n" ++
12193−- show env
12194−-
12195−-line= unsafePerformIO $ newMVar ()
12196−-
12197−-logError err= do
12198−- takeMVar line
12199−- putStrLn err
12200−- hSeek hlog SeekFromEnd 0
12201−- hPutStrLn hlog err
12202−- hFlush hlog
12203−- putMVar line ()
12204−-
12205−-logFileName= "errlog"
12206−-
12207−-
12208−-
12209−--- | The handler of the error log
12210−-hlog= unsafePerformIO $ openFile logFileName ReadWriteMode
12211−-
12212−------- USER MANAGEMENT -------
12213−-
12214−-data Auth = Auth{
12215−- uregister :: UserStr -> PasswdStr -> (IO (Maybe String)),
12216−- uvalidate :: UserStr -> PasswdStr -> (IO (Maybe String))}
12217−-
12218−-_authMethod= unsafePerformIO $ newIORef $ Auth tCacheRegister tCacheValidate
12219−-
12220−--- | set an authentication method
12221−-setAuthMethod auth= writeIORef _authMethod auth
12222−-
12223−-getAuthMethod = readIORef _authMethod
12224−-
12225−-
12226−-data User= User
12227−- { userName :: String
12228−- , upassword :: String
12229−- } deriving (Read, Show, Typeable)
12230−-
12231−-
12232−-eUser= User (error1 "username") (error1 "password")
12233−-
12234−-error1 s= error $ s ++ " undefined"
12235−-
12236−-userPrefix= "user/"
12237−-instance Indexable User where
12238−- key User{userName= user}= keyUserName user
12239−-
12240−--- | Return the key name of an user
12241−-keyUserName n= userPrefix++n
12242−-
12243−-instance Serializable User where
12244−- serialize= B.pack . show
12245−- deserialize= read . B.unpack
12246−- setPersist = \_ -> Just filePersist
12247−-
12248−--- | Register an user/password
12249−-tCacheRegister :: String -> String -> IO (Maybe String)
12250−-tCacheRegister user password = atomically $ do
12251−- withSTMResources [newuser] doit
12252−- where
12253−- newuser= User user password
12254−- doit [Just (User _ _)] = resources{toReturn= Just "user already exist"}
12255−- doit [Nothing] = resources{toAdd= [newuser],toReturn= Nothing}
12256−-
12257−-tCacheValidate :: UserStr -> PasswdStr -> IO (Maybe String)
12258−-tCacheValidate u p =
12259−- let user= eUser{userName=u}
12260−- in atomically
12261−- $ withSTMResources [user]
12262−- $ \ mu -> case mu of
12263−- [Nothing] -> resources{toReturn= err }
12264−- [Just (User _ pass )] -> resources{toReturn=
12265−- case pass==p of
12266−- True -> Nothing
12267−- False -> err
12268−- }
12269−-
12270−- where
12271−- err= Just "Username or password invalid"
12272−-
12273−-userRegister u p= liftIO $ do
12274−- Auth reg _ <- getAuthMethod :: IO Auth
12275−- reg u p
12276−-
12277−-
12278−-newtype Config= Config1 (M.Map String String) deriving (Read,Show,Typeable)
12279−-
12280−---defConfig= Config1 $ M.fromList
12281−--- [("cadmin","admin")
12282−--- ,("cjqueryScript","//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js")
12283−--- ,("cjqueryCSS","//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css")
12284−--- ,("cjqueryUI","//code.jquery.com/ui/1.10.3/jquery-ui.js")
12285−--- ,("cnicEditUrl","//js.nicedit.com/nicEdit-latest.js")]
12286−-
12287−+ showError wfname token (show e)
12288−+-- sendFlush token (Error NotFound $ "Not found: " <> pack wfname)
12289−+ deleteTokenInList token
12290−+
12291−+ Left AlreadyRunning -> return () -- !> ("already Running " ++ wfname)
12292−+
12293−+ Left Timeout -> do
12294−+ hFlush stdout -- !> ("TIMEOUT in msgScheduler" ++ (show $ unsafePerformIO myThreadId))
12295−+ deleteTokenInList token
12296−+
12297−+ Left (WFException e)-> do
12298−+ showError wfname token e
12299−+ moveState wfname token token{tind= "error/"++tuser token}
12300−+ deleteTokenInList token -- !> "DELETETOKEN"
12301−+
12302−+
12303−+ Right _ -> delMsgHistory token >> return () -- !> ("finished " ++ wfname)
12304−+
12305−+
12306−+
12307−+showError wfname token@Token{..} e= do
12308−+ t <- return . calendarTimeToString =<< toCalendarTime =<< getClockTime
12309−+ let msg= errorMessage t e tuser (Prelude.concat $ intersperse "/" tpath) tenv
12310−+ logError msg
12311−+ fresp <- getNotFoundResponse
12312−+ let admin= getAdminName
12313−+ sendFlush token . Error $ fresp (tuser== admin) $ Prelude.concat[ "<br/>"++ s | s <- lines msg]
12314−+
12315−+
12316−+errorMessage t e u path env=
12317−+ "\n---------------------ERROR-------------------------\
12318−+ \\nTIME=" ++ t ++"\n\n" ++
12319−+ e++
12320−+ "\n\nUSER= " ++ u ++
12321−+ "\n\nPATH= " ++ path ++
12322−+ "\n\nREQUEST:\n\n" ++
12323−+ show env
12324−+
12325−+line= unsafePerformIO $ newMVar ()
12326−+
12327−+logError err= do
12328−+ takeMVar line
12329−+ putStrLn err
12330−+ hSeek hlog SeekFromEnd 0
12331−+ hPutStrLn hlog err
12332−+ hFlush hlog
12333−+ putMVar line ()
12334−+
12335−+logFileName= "errlog"
12336−+
12337−+
12338−+
12339−+-- | The handler of the error log
12340−+hlog= unsafePerformIO $ openFile logFileName ReadWriteMode
12341−+
12342−+------ USER MANAGEMENT -------
12343−+
12344−+data Auth = Auth{
12345−+ uregister :: UserStr -> PasswdStr -> (IO (Maybe String)),
12346−+ uvalidate :: UserStr -> PasswdStr -> (IO (Maybe String))}
12347−+
12348−+_authMethod= unsafePerformIO $ newIORef $ Auth tCacheRegister tCacheValidate
12349−+
12350−+-- | set an authentication method. That includes the registration and validation calls.
12351−+-- both return Nothing if sucessful. Otherwise they return a text mesage explaining the failure
12352−+setAuthMethod auth= writeIORef _authMethod auth
12353−+
12354−+getAuthMethod = readIORef _authMethod
12355−+
12356−+
12357−+data User= User
12358−+ { userName :: String
12359−+ , upassword :: String
12360−+ } deriving (Read, Show, Typeable)
12361−+
12362−+
12363−+eUser= User (error1 "username") (error1 "password")
12364−+
12365−+error1 s= error $ s ++ " undefined"
12366−+
12367−+userPrefix= "user/"
12368−+instance Indexable User where
12369−+ key User{userName= user}= keyUserName user
12370−+
12371−+-- | Return the key name of an user
12372−+keyUserName n= userPrefix++n
12373−+
12374−+instance Serializable User where
12375−+ serialize= B.pack . show
12376−+ deserialize= read . B.unpack
12377−+ setPersist = \_ -> Just filePersist
12378−+
12379−+-- | Register an user/password
12380−+tCacheRegister :: String -> String -> IO (Maybe String)
12381−+tCacheRegister user password= tCacheRegister' 14 user password
12382−+
12383−+tCacheRegister' strength user password= do
12384−+ salted_password <- makePassword (SB.pack password) strength
12385−+ atomically $ do
12386−+ let newuser = User user (SB.unpack salted_password)
12387−+ withSTMResources [newuser] $ doit newuser
12388−+ where
12389−+ doit newuser [Just (User _ _)] = resources{toReturn= Just "user already exist"}
12390−+ doit newuser [Nothing] = resources{toAdd= [newuser],toReturn= Nothing}
12391−+
12392−+
12393−+-- withSTMResources [newuser] doit
12394−+-- where
12395−+-- newuser= User user password
12396−+-- doit [Just (User _ _)] = resources{toReturn= Just "user already exist"}
12397−+-- doit [Nothing] = resources{toAdd= [newuser],toReturn= Nothing}
12398−+
12399−+tCacheValidate :: UserStr -> PasswdStr -> IO (Maybe String)
12400−+tCacheValidate u p =
12401−+ let user= eUser{userName=u}
12402−+ in atomically
12403−+ $ withSTMResources [user]
12404−+ $ \ mu -> case mu of
12405−+ [Nothing] -> resources{toReturn= err }
12406−+ [Just u@(User _ pass )] -> resources{toReturn =
12407−+ case verifyPassword (SB.pack p) (SB.pack pass)
12408−+ || pass== p of -- for backward compatibility for unhashed passwords
12409−+ True -> Nothing
12410−+ False -> err
12411−+ }
12412−+ where
12413−+ err= Just "Username or password invalid"
12414−+
12415−+-- | register an user with the auth Method
12416−+userRegister :: MonadIO m => UserStr -> PasswdStr -> m (Maybe String)
12417−+userRegister !u !p= liftIO $ do
12418−+ Auth reg _ <- getAuthMethod :: IO Auth
12419−+ reg u p
12420−+
12421−+
12422−+newtype Config= Config1 (M.Map String String) deriving (Read,Show,Typeable)
12423−+
12424−+
12425− data Config0 = Config{cadmin :: UserStr -- ^ Administrator name
12426− ,cjqueryScript :: String -- ^ URL of jquery
12427− ,cjqueryCSS :: String -- ^ URL of jqueryCSS
12428− ,cjqueryUI :: String -- ^ URL of jqueryUI
12429− ,cnicEditUrl :: String -- ^ URL of the nicEdit editor
12430− }
12431−- deriving (Read, Show, Typeable)
12432−+ deriving (Read, Show, Typeable)
12433−
12434−---defConfig0= Config "admin" "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
12435−--- "//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"
12436−--- "//code.jquery.com/ui/1.10.3/jquery-ui.js"
12437−--- "//js.nicedit.com/nicEdit-latest.js"
12438−---
12439−---writeDefConfig0= writeFile "sal" $ show defConfig0
12440−
12441− change :: Config0 -> Config
12442− change Config{..} = Config1 $ M.fromList
12443−@@ -558,370 +563,366 @@
12444−
12445− readOld :: ByteString -> Config
12446− readOld s= (change . read . B.unpack $ s)
12447−-
12448−-keyConfig= "mflow.config"
12449−+
12450−+keyConfig= "mflow.config"
12451− instance Indexable Config where key _= keyConfig
12452−
12453−-rconf :: DBRef Config
12454−-rconf= getDBRef keyConfig
12455−-
12456−-instance Serializable Config where
12457−- serialize = B.pack . show
12458−+rconf :: DBRef Config
12459−+rconf= getDBRef keyConfig
12460−+
12461−+instance Serializable Config where
12462−+ serialize (Config1 c)= B.pack $ "Config1 (fromList[\n" <> (concat . intersperse ",\n" $ map show (M.toList c)) <> "])"
12463− deserialize s = unsafePerformIO $ (return $! read $! B.unpack s)
12464−- `CE.catch` \(e :: SomeException) -> return (readOld s)
12465−- setPersist = \_ -> Just filePersist
12466−+ `CE.catch` \(e :: SomeException) -> return (readOld s)
12467−+ setPersist = \_ -> Just filePersist
12468−
12469− -- | read a config variable from the config file \"mflow.config\". if it is not set, uses the second parameter and
12470− -- add it to the configuration list, so next time the administrator can change it in the configuration file
12471−-getConfig k v= case M.lookup k config of
12472−+getConfig k v= case M.lookup k config of
12473− Nothing -> unsafePerformIO $ setConfig k v >> return v
12474− Just s -> s
12475−
12476− -- | set an user-defined config variable
12477−-setConfig k v= atomically $ do
12478−- Config1 conf <- readConfig
12479−- writeDBRef rconf $ Config1 $ M.insert k v conf
12480−+setConfig k v= atomically $ do
12481−+ Config1 conf <- readConfig
12482−+ writeDBRef rconf $ Config1 $ M.insert k v conf
12483−
12484−
12485− -- user ---
12486−-
12487−-type UserStr= String
12488−-type PasswdStr= String
12489−+
12490−+type UserStr= String
12491−+type PasswdStr= String
12492−
12493−
12494− -- | set the Administrator user and password.
12495− -- It must be defined in Main , before any configuration parameter is read, before the execution
12496−--- of any flow
12497−-setAdminUser :: MonadIO m => UserStr -> PasswdStr -> m ()
12498−-setAdminUser user password= liftIO $ do
12499−+-- of any flow
12500−+setAdminUser :: MonadIO m => UserStr -> PasswdStr -> m ()
12501−+setAdminUser user password= liftIO $ do
12502− userRegister user password
12503− setConfig "cadmin" user
12504−--- atomically $ do
12505−--- Config1 conf <- readConfig
12506−--- writeDBRef rconf $ Config1 $ M.insert "cadmin" user conf
12507−-
12508−-
12509−-
12510−-getAdminName= getConfig "cadmin" "admin"
12511−-
12512−-
12513−---------------- ERROR RESPONSES --------
12514−-
12515−-defNotFoundResponse isAdmin msg= fresp $
12516−- case isAdmin of
12517−- True -> B.pack msg
12518−- _ -> "The administrator has been notified"
12519−- where
12520−- fresp msg=
12521−- "<html><h4>Error 404: Page not found or error ocurred</h4> <p style=\"font-family:courier\">" <> msg <>"</p>" <>
12522−- "<br/>" <> opts <> "<br/><a href=\"/\" >press here to go home</a></html>"
12523−-
12524−-
12525−- paths= Prelude.map B.pack . M.keys $ unsafePerformIO getMessageFlows
12526−- opts= "options: " <> B.concat (Prelude.map (\s ->
12527−- "<a href=\"/"<> s <>"\">"<> s <>"</a>, ") $ filter (\s -> B.head s /= '_') paths)
12528−-
12529−-notFoundResponse= unsafePerformIO $ newIORef defNotFoundResponse
12530−-
12531−--- | set the 404 "not found" response.
12532−---
12533−--- The parameter is as follows:
12534−--- (Bool Either if the user is Administrator or not
12535−--- -> String The error string
12536−--- -> HttpData) The response. See `defNotFoundResponse` code for an example
12537−-
12538−-setNotFoundResponse ::
12539−- (Bool
12540−- -> String
12541−- -> ByteString)
12542−- -> IO ()
12543−-
12544−-setNotFoundResponse f= liftIO $ writeIORef notFoundResponse f
12545−-getNotFoundResponse= liftIO $ readIORef notFoundResponse
12546−-
12547−---------------- BASIC BYTESTRING TAGS -------------------
12548−-
12549−-
12550−-type Attribs= [(String,String)]
12551−--- | Writes a XML tag in a ByteString. It is the most basic form of formatting. For
12552−--- more sophisticated formatting , use "MFlow.Forms.XHtml" or "MFlow.Forms.HSP".
12553−-btag :: String -> Attribs -> ByteString -> ByteString
12554−-btag t rs v= "<" <> pt <> attrs rs <> ">" <> v <> "</" <> pt <> ">"
12555−- where
12556−- pt= B.pack t
12557−- attrs []= B.empty
12558−- attrs rs= B.pack $ concatMap(\(n,v) -> (' ' : n) ++ "=\"" ++ v++ "\"" ) rs
12559−-
12560−--- |
12561−--- > bhtml ats v= btag "html" ats v
12562−-bhtml :: Attribs -> ByteString -> ByteString
12563−-bhtml ats v= btag "html" ats v
12564−-
12565−-
12566−--- |
12567−--- > bbody ats v= btag "body" ats v
12568−-bbody :: Attribs -> ByteString -> ByteString
12569−-bbody ats v= btag "body" ats v
12570−-
12571−-addAttrs :: ByteString -> Attribs -> ByteString
12572−-addAttrs (Chunk "<" (Chunk tag rest)) rs=
12573−- Chunk "<"(Chunk tag (B.pack $ concatMap(\(n,v) -> (' ' : n) ++ "=" ++ v ) rs)) <> rest
12574−-
12575−-addAttrs other _ = error $ "addAttrs: byteString is not a tag: " ++ show other
12576−-
12577−-
12578−-------------------- FILE SERVER -----------
12579−-
12580−--- | Set the path of the files in the web server. The links to the files are relative to it.
12581−--- The files are cached (memoized) according with the "Data.TCache" policies in the program space. This avoid the blocking of
12582−--- the efficient GHC threads by frequent IO calls.So it enhances the performance
12583−--- in the context of heavy concurrence.
12584−--- It uses 'Data.TCache.Memoization'.
12585−--- The caching-uncaching follows the `setPersist` criteria
12586−-setFilesPath :: MonadIO m => String -> m ()
12587−-setFilesPath path= liftIO $ writeIORef rfilesPath path
12588−-
12589−-rfilesPath= unsafePerformIO $ newIORef "files/"
12590−-
12591−-serveFile path'= do
12592−- when(let hpath= Prelude.head path' in hpath == '/' || hpath =='\\') $ error noperm
12593−- when(not(".." `isSuffixOf` path') && ".." `isInfixOf` path') $ error noperm
12594−- filesPath <- readIORef rfilesPath
12595−- let path= filesPath ++ path'
12596−- mr <- cachedByKey path 0 $ (B.readFile path >>= return . Just) `CE.catch` ioerr (return Nothing)
12597−- case mr of
12598−- Nothing -> error "not found" -- return $ HttpData [setMime "text/plain"] [] $ pack $ "not accessible"
12599−- Just r ->
12600−- let ext = reverse . takeWhile (/='.') $ reverse path
12601−- mmime= lookup (map toLower ext) mimeTable
12602−- mime = case mmime of Just m -> m ;Nothing -> "application/octet-stream"
12603−-
12604−- in return $ HttpData [setMime mime, ("Cache-Control", "max-age=360000")] [] r
12605−- where
12606−- noperm= "no permissions"
12607−- ioerr x= \(e :: CE.IOException) -> x
12608−- setMime x= ("Content-Type",x)
12609−-
12610−---------------------- FLOW ID GENERATOR ------------
12611−-
12612−-data NFlow= NFlow !Integer deriving (Read, Show, Typeable)
12613−-
12614−-
12615−-
12616−-instance Indexable NFlow where
12617−- key _= "Flow"
12618−-
12619−-instance Serializable NFlow where
12620−- serialize= B.pack . show
12621−- deserialize= read . B.unpack
12622−- setPersist = \_ -> Just filePersist
12623−-
12624−-rflow= getDBRef . key $ NFlow undefined
12625−-
12626−-newFlow= do
12627−- TOD t _ <- getClockTime
12628−- atomically $ do
12629−- NFlow n <- readDBRef rflow `onNothing` return (NFlow 0)
12630−- writeDBRef rflow . NFlow $ n+1
12631−- return . SB.pack . show $ t + n
12632−-
12633−-
12634−-mimeTable=[
12635−- ("html", "text/html"),
12636−- ("htm", "text/html"),
12637−- ("txt", "text/plain"),
12638−- ("hs", "text/plain"),
12639−- ("lhs", "text/plain"),
12640−- ("jpeg", "image/jpeg"),
12641−- ("pdf", "application/pdf"),
12642−- ("js", "application/x-javascript"),
12643−- ("gif", "image/gif"),
12644−- ("bmp", "image/bmp"),
12645−- ("ico", "image/x-icon"),
12646−- ("doc", "application/msword"),
12647−- ("jpg", "image/jpeg"),
12648−- ("eps", "application/postscript"),
12649−- ("zip", "application/zip"),
12650−- ("exe", "application/octet-stream"),
12651−- ("tif", "image/tiff"),
12652−- ("tiff", "image/tiff"),
12653−- ("mov", "video/quicktime"),
12654−- ("movie", "video/x-sgi-movie"),
12655−- ("mp2", "video/mpeg"),
12656−- ("mp3", "audio/mpeg"),
12657−- ("mpa", "video/mpeg"),
12658−- ("mpe", "video/mpeg"),
12659−- ("mpeg", "video/mpeg"),
12660−- ("mpg", "video/mpeg"),
12661−- ("mpp", "application/vnd.ms-project"),
12662−- ("323", "text/h323"),
12663−- ("*", "application/octet-stream"),
12664−- ("acx", "application/internet-property-stream"),
12665−- ("ai", "application/postscript"),
12666−- ("aif", "audio/x-aiff"),
12667−- ("aifc", "audio/x-aiff"),
12668−- ("aiff", "audio/x-aiff"),
12669−- ("asf", "video/x-ms-asf"),
12670−- ("asr", "video/x-ms-asf"),
12671−- ("asx", "video/x-ms-asf"),
12672−- ("au", "audio/basic"),
12673−- ("avi", "video/x-msvideo"),
12674−- ("axs", "application/olescript"),
12675−- ("bas", "text/plain"),
12676−- ("bcpio", "application/x-bcpio"),
12677−- ("bin", "application/octet-stream"),
12678−- ("c", "text/plain"),
12679−- ("cat", "application/vnd.ms-pkiseccat"),
12680−- ("cdf", "application/x-cdf"),
12681−- ("cdf", "application/x-netcdf"),
12682−- ("cer", "application/x-x509-ca-cert"),
12683−- ("class", "application/octet-stream"),
12684−- ("clp", "application/x-msclip"),
12685−- ("cmx", "image/x-cmx"),
12686−- ("cod", "image/cis-cod"),
12687−- ("cpio", "application/x-cpio"),
12688−- ("crd", "application/x-mscardfile"),
12689−- ("crl", "application/pkix-crl"),
12690−- ("crt", "application/x-x509-ca-cert"),
12691−- ("csh", "application/x-csh"),
12692−- ("css", "text/css"),
12693−- ("dcr", "application/x-director"),
12694−- ("der", "application/x-x509-ca-cert"),
12695−- ("dir", "application/x-director"),
12696−- ("dll", "application/x-msdownload"),
12697−- ("dms", "application/octet-stream"),
12698−- ("dot", "application/msword"),
12699−- ("dvi", "application/x-dvi"),
12700−- ("dxr", "application/x-director"),
12701−- ("eps", "application/postscript"),
12702−- ("etx", "text/x-setext"),
12703−- ("evy", "application/envoy"),
12704−- ("fif", "application/fractals"),
12705−- ("flr", "x-world/x-vrml"),
12706−- ("gtar", "application/x-gtar"),
12707−- ("gz", "application/x-gzip"),
12708−- ("h", "text/plain"),
12709−- ("hdf", "application/x-hdf"),
12710−- ("hlp", "application/winhlp"),
12711−- ("hqx", "application/mac-binhex40"),
12712−- ("hta", "application/hta"),
12713−- ("htc", "text/x-component"),
12714−- ("htt", "text/webviewhtml"),
12715−- ("ief", "image/ief"),
12716−- ("iii", "application/x-iphone"),
12717−- ("ins", "application/x-internet-signup"),
12718−- ("isp", "application/x-internet-signup"),
12719−- ("jfif", "image/pipeg"),
12720−- ("jpe", "image/jpeg"),
12721−- ("latex", "application/x-latex"),
12722−- ("lha", "application/octet-stream"),
12723−- ("lsf", "video/x-la-asf"),
12724−- ("lsx", "video/x-la-asf"),
12725−- ("lzh", "application/octet-stream"),
12726−- ("m13", "application/x-msmediaview"),
12727−- ("m14", "application/x-msmediaview"),
12728−- ("m3u", "audio/x-mpegurl"),
12729−- ("man", "application/x-troff-man"),
12730−- ("mdb", "application/x-msaccess"),
12731−- ("me", "application/x-troff-me"),
12732−- ("mht", "message/rfc822"),
12733−- ("mhtml", "message/rfc822"),
12734−- ("mid", "audio/mid"),
12735−- ("mny", "application/x-msmoney"),
12736−- ("mpv2", "video/mpeg"),
12737−- ("ms", "application/x-troff-ms"),
12738−- ("msg", "application/vnd.ms-outlook"),
12739−- ("mvb", "application/x-msmediaview"),
12740−- ("nc", "application/x-netcdf"),
12741−- ("nws", "message/rfc822"),
12742−- ("oda", "application/oda"),
12743−- ("p10", "application/pkcs10"),
12744−- ("p12", "application/x-pkcs12"),
12745−- ("p7b", "application/x-pkcs7-certificates"),
12746−- ("p7c", "application/x-pkcs7-mime"),
12747−- ("p7m", "application/x-pkcs7-mime"),
12748−- ("p7r", "application/x-pkcs7-certreqresp"),
12749−- ("p7s", "application/x-pkcs7-signature"),
12750−- ("png", "image/png"),
12751−- ("pbm", "image/x-portable-bitmap"),
12752−- ("pfx", "application/x-pkcs12"),
12753−- ("pgm", "image/x-portable-graymap"),
12754−- ("pko", "application/ynd.ms-pkipko"),
12755−- ("pma", "application/x-perfmon"),
12756−- ("pmc", "application/x-perfmon"),
12757−- ("pml", "application/x-perfmon"),
12758−- ("pmr", "application/x-perfmon"),
12759−- ("pmw", "application/x-perfmon"),
12760−- ("pnm", "image/x-portable-anymap"),
12761−- ("pot", "application/vnd.ms-powerpoint"),
12762−- ("ppm", "image/x-portable-pixmap"),
12763−- ("pps", "application/vnd.ms-powerpoint"),
12764−- ("ppt", "application/vnd.ms-powerpoint"),
12765−- ("prf", "application/pics-rules"),
12766−- ("ps", "application/postscript"),
12767−- ("pub", "application/x-mspublisher"),
12768−- ("qt", "video/quicktime"),
12769−- ("ra", "audio/x-pn-realaudio"),
12770−- ("ram", "audio/x-pn-realaudio"),
12771−- ("ras", "image/x-cmu-raster"),
12772−- ("rgb", "image/x-rgb"),
12773−- ("rmi", "audio/mid"),
12774−- ("roff", "application/x-troff"),
12775−- ("rtf", "application/rtf"),
12776−- ("rtx", "text/richtext"),
12777−- ("scd", "application/x-msschedule"),
12778−- ("sct", "text/scriptlet"),
12779−- ("setpay", "application/set-payment-initiation"),
12780−- ("setreg", "application/set-registration-initiation"),
12781−- ("sh", "application/x-sh"),
12782−- ("shar", "application/x-shar"),
12783−- ("sit", "application/x-stuffit"),
12784−- ("snd", "audio/basic"),
12785−- ("spc", "application/x-pkcs7-certificates"),
12786−- ("spl", "application/futuresplash"),
12787−- ("src", "application/x-wais-source"),
12788−- ("sst", "application/vnd.ms-pkicertstore"),
12789−- ("stl", "application/vnd.ms-pkistl"),
12790−- ("stm", "text/html"),
12791−- ("sv4cpio", "application/x-sv4cpio"),
12792−- ("sv4crc", "application/x-sv4crc"),
12793−- ("svg", "image/svg+xml"),
12794−- ("swf", "application/x-shockwave-flash"),
12795−- ("t", "application/x-troff"),
12796−- ("tar", "application/x-tar"),
12797−- ("tcl", "application/x-tcl"),
12798−- ("tex", "application/x-tex"),
12799−- ("texi", "application/x-texinfo"),
12800−- ("texinfo", "application/x-texinfo"),
12801−- ("tgz", "application/x-compressed"),
12802−- ("tr", "application/x-troff"),
12803−- ("trm", "application/x-msterminal"),
12804−- ("tsv", "text/tab-separated-values"),
12805−- ("uls", "text/iuls"),
12806−- ("ustar", "application/x-ustar"),
12807−- ("vcf", "text/x-vcard"),
12808−- ("vrml", "x-world/x-vrml"),
12809−- ("wav", "audio/x-wav"),
12810−- ("wcm", "application/vnd.ms-works"),
12811−- ("wdb", "application/vnd.ms-works"),
12812−- ("wks", "application/vnd.ms-works"),
12813−- ("wmf", "application/x-msmetafile"),
12814−- ("wps", "application/vnd.ms-works"),
12815−- ("wri", "application/x-mswrite"),
12816−- ("wrl", "x-world/x-vrml"),
12817−- ("wrz", "x-world/x-vrml"),
12818−- ("xaf", "x-world/x-vrml"),
12819−- ("xbm", "image/x-xbitmap"),
12820−- ("xla", "application/vnd.ms-excel"),
12821−- ("xlc", "application/vnd.ms-excel"),
12822−- ("xlm", "application/vnd.ms-excel"),
12823−- ("xls", "application/vnd.ms-excel"),
12824−- ("xlt", "application/vnd.ms-excel"),
12825−- ("xlw", "application/vnd.ms-excel"),
12826−- ("xof", "x-world/x-vrml"),
12827−- ("xpm", "image/x-xpixmap"),
12828−- ("xwd", "image/x-xwindowdump"),
12829−- ("z", "application/x-compress")
12830−-
12831−- ]
12832−-
12833−+
12834−+
12835−+getAdminName= getConfig "cadmin" "admin"
12836−+
12837−+
12838−+--------------- ERROR RESPONSES --------
12839−+
12840−+defNotFoundResponse isAdmin msg= fresp $
12841−+ case isAdmin of
12842−+ True -> B.pack msg
12843−+ _ -> "The administrator has been notified"
12844−+ where
12845−+ fresp msg=
12846−+ "<html><h4>Error 404: Page not found or error ocurred</h4> <p style=\"font-family:courier\">" <> msg <>"</p>" <>
12847−+ "<br/>" <> opts <> "<br/><a href=\"/\" >press here to go home</a></html>"
12848−+
12849−+
12850−+ paths= Prelude.map B.pack . M.keys $ unsafePerformIO getMessageFlows
12851−+ opts= "options: " <> B.concat (Prelude.map (\s ->
12852−+ "<a href=\"/"<> s <>"\">"<> s <>"</a>, ") $ filter (\s -> B.head s /= '_') paths)
12853−+
12854−+notFoundResponse= unsafePerformIO $ newIORef defNotFoundResponse
12855−+
12856−+-- | set the 404 "not found" response.
12857−+--
12858−+-- The parameter is as follows:
12859−+-- (Bool Either if the user is Administrator or not
12860−+-- -> String The error string
12861−+-- -> HttpData) The response. See `defNotFoundResponse` code for an example
12862−+
12863−+setNotFoundResponse ::
12864−+ (Bool
12865−+ -> String
12866−+ -> ByteString)
12867−+ -> IO ()
12868−+
12869−+setNotFoundResponse f= liftIO $ writeIORef notFoundResponse f
12870−+getNotFoundResponse= liftIO $ readIORef notFoundResponse
12871−+
12872−+--------------- BASIC BYTESTRING TAGS -------------------
12873−+
12874−+
12875−+type Attribs= [(String,String)]
12876−+-- | Writes a XML tag in a ByteString. It is the most basic form of formatting. For
12877−+-- more sophisticated formatting , use "MFlow.Forms.XHtml" or "MFlow.Forms.HSP".
12878−+btag :: String -> Attribs -> ByteString -> ByteString
12879−+btag t rs v= "<" <> pt <> attrs rs <> ">" <> v <> "</" <> pt <> ">"
12880−+ where
12881−+ pt= B.pack t
12882−+ attrs []= B.empty
12883−+ attrs rs= B.pack $ concatMap(\(n,v) -> (' ' : n) ++ "=\"" ++ v++ "\"" ) rs
12884−+
12885−+-- |
12886−+-- > bhtml ats v= btag "html" ats v
12887−+bhtml :: Attribs -> ByteString -> ByteString
12888−+bhtml ats v= btag "html" ats v
12889−+
12890−+
12891−+-- |
12892−+-- > bbody ats v= btag "body" ats v
12893−+bbody :: Attribs -> ByteString -> ByteString
12894−+bbody ats v= btag "body" ats v
12895−+
12896−+addAttrs :: ByteString -> Attribs -> ByteString
12897−+addAttrs (Chunk "<" (Chunk tag rest)) rs=
12898−+ Chunk "<"(Chunk tag (B.pack $ concatMap(\(n,v) -> (' ' : n) ++ "=" ++ v ) rs)) <> rest
12899−+
12900−+addAttrs other _ = error $ "addAttrs: byteString is not a tag: " ++ show other
12901−+
12902−+
12903−+------------------- FILE SERVER -----------
12904−+
12905−+-- | Set the path of the files in the web server. The links to the files are relative to it.
12906−+-- The files are cached (memoized) according with the "Data.TCache" policies in the program space. This avoid the blocking of
12907−+-- the efficient GHC threads by frequent IO calls.So it enhances the performance
12908−+-- in the context of heavy concurrence.
12909−+-- It uses 'Data.TCache.Memoization'.
12910−+-- The caching-uncaching follows the `setPersist` criteria
12911−+setFilesPath :: MonadIO m => String -> m ()
12912−+setFilesPath !path= liftIO $ writeIORef rfilesPath path
12913−+
12914−+rfilesPath= unsafePerformIO $ newIORef "files/"
12915−+
12916−+serveFile path'= do
12917−+ when(let hpath= Prelude.head path' in hpath == '/' || hpath =='\\') $ error noperm
12918−+ when(not(".." `isSuffixOf` path') && ".." `isInfixOf` path') $ error noperm
12919−+ filesPath <- readIORef rfilesPath
12920−+ let path= filesPath ++ path'
12921−+ mr <- cachedByKey path 0 $ (B.readFile path >>= return . Just) `CE.catch` ioerr (return Nothing)
12922−+ case mr of
12923−+ Nothing -> error "not found" -- return $ HttpData [setMime "text/plain"] [] $ pack $ "not accessible"
12924−+ Just r ->
12925−+ let ext = reverse . takeWhile (/='.') $ reverse path
12926−+ mmime= lookup (map toLower ext) mimeTable
12927−+ mime = case mmime of Just m -> m ;Nothing -> "application/octet-stream"
12928−+
12929−+ in return $ HttpData [setMime mime, ("Cache-Control", "max-age=360000")] [] r
12930−+ where
12931−+ noperm= "no permissions"
12932−+ ioerr x= \(e :: CE.IOException) -> x
12933−+ setMime x= ("Content-Type",x)
12934−+
12935−+--------------------- FLOW ID GENERATOR ------------
12936−+
12937−+data NFlow= NFlow !Integer deriving (Read, Show, Typeable)
12938−+
12939−+
12940−+
12941−+instance Indexable NFlow where
12942−+ key _= "Flow"
12943−+
12944−+instance Serializable NFlow where
12945−+ serialize= B.pack . show
12946−+ deserialize= read . B.unpack
12947−+ setPersist = \_ -> Just filePersist
12948−+
12949−+rflow= getDBRef . key $ NFlow undefined
12950−+
12951−+newFlow= do
12952−+ TOD t _ <- getClockTime
12953−+ atomically $ do
12954−+ NFlow n <- readDBRef rflow `onNothing` return (NFlow 0)
12955−+ writeDBRef rflow . NFlow $ n+1
12956−+ return . SB.pack . show $ t + n
12957−+
12958−+
12959−+mimeTable=[
12960−+ ("html", "text/html"),
12961−+ ("htm", "text/html"),
12962−+ ("txt", "text/plain"),
12963−+ ("hs", "text/plain"),
12964−+ ("lhs", "text/plain"),
12965−+ ("jpeg", "image/jpeg"),
12966−+ ("pdf", "application/pdf"),
12967−+ ("js", "application/x-javascript"),
12968−+ ("gif", "image/gif"),
12969−+ ("bmp", "image/bmp"),
12970−+ ("ico", "image/x-icon"),
12971−+ ("doc", "application/msword"),
12972−+ ("jpg", "image/jpeg"),
12973−+ ("eps", "application/postscript"),
12974−+ ("zip", "application/zip"),
12975−+ ("exe", "application/octet-stream"),
12976−+ ("tif", "image/tiff"),
12977−+ ("tiff", "image/tiff"),
12978−+ ("mov", "video/quicktime"),
12979−+ ("movie", "video/x-sgi-movie"),
12980−+ ("mp2", "video/mpeg"),
12981−+ ("mp3", "audio/mpeg"),
12982−+ ("mpa", "video/mpeg"),
12983−+ ("mpe", "video/mpeg"),
12984−+ ("mpeg", "video/mpeg"),
12985−+ ("mpg", "video/mpeg"),
12986−+ ("mpp", "application/vnd.ms-project"),
12987−+ ("323", "text/h323"),
12988−+ ("*", "application/octet-stream"),
12989−+ ("acx", "application/internet-property-stream"),
12990−+ ("ai", "application/postscript"),
12991−+ ("aif", "audio/x-aiff"),
12992−+ ("aifc", "audio/x-aiff"),
12993−+ ("aiff", "audio/x-aiff"),
12994−+ ("asf", "video/x-ms-asf"),
12995−+ ("asr", "video/x-ms-asf"),
12996−+ ("asx", "video/x-ms-asf"),
12997−+ ("au", "audio/basic"),
12998−+ ("avi", "video/x-msvideo"),
12999−+ ("axs", "application/olescript"),
13000−+ ("bas", "text/plain"),
13001−+ ("bcpio", "application/x-bcpio"),
13002−+ ("bin", "application/octet-stream"),
13003−+ ("c", "text/plain"),
13004−+ ("cat", "application/vnd.ms-pkiseccat"),
13005−+ ("cdf", "application/x-cdf"),
13006−+ ("cdf", "application/x-netcdf"),
13007−+ ("cer", "application/x-x509-ca-cert"),
13008−+ ("class", "application/octet-stream"),
13009−+ ("clp", "application/x-msclip"),
13010−+ ("cmx", "image/x-cmx"),
13011−+ ("cod", "image/cis-cod"),
13012−+ ("cpio", "application/x-cpio"),
13013−+ ("crd", "application/x-mscardfile"),
13014−+ ("crl", "application/pkix-crl"),
13015−+ ("crt", "application/x-x509-ca-cert"),
13016−+ ("csh", "application/x-csh"),
13017−+ ("css", "text/css"),
13018−+ ("dcr", "application/x-director"),
13019−+ ("der", "application/x-x509-ca-cert"),
13020−+ ("dir", "application/x-director"),
13021−+ ("dll", "application/x-msdownload"),
13022−+ ("dms", "application/octet-stream"),
13023−+ ("dot", "application/msword"),
13024−+ ("dvi", "application/x-dvi"),
13025−+ ("dxr", "application/x-director"),
13026−+ ("eps", "application/postscript"),
13027−+ ("etx", "text/x-setext"),
13028−+ ("evy", "application/envoy"),
13029−+ ("fif", "application/fractals"),
13030−+ ("flr", "x-world/x-vrml"),
13031−+ ("gtar", "application/x-gtar"),
13032−+ ("gz", "application/x-gzip"),
13033−+ ("h", "text/plain"),
13034−+ ("hdf", "application/x-hdf"),
13035−+ ("hlp", "application/winhlp"),
13036−+ ("hqx", "application/mac-binhex40"),
13037−+ ("hta", "application/hta"),
13038−+ ("htc", "text/x-component"),
13039−+ ("htt", "text/webviewhtml"),
13040−+ ("ief", "image/ief"),
13041−+ ("iii", "application/x-iphone"),
13042−+ ("ins", "application/x-internet-signup"),
13043−+ ("isp", "application/x-internet-signup"),
13044−+ ("jfif", "image/pipeg"),
13045−+ ("jpe", "image/jpeg"),
13046−+ ("latex", "application/x-latex"),
13047−+ ("lha", "application/octet-stream"),
13048−+ ("lsf", "video/x-la-asf"),
13049−+ ("lsx", "video/x-la-asf"),
13050−+ ("lzh", "application/octet-stream"),
13051−+ ("m13", "application/x-msmediaview"),
13052−+ ("m14", "application/x-msmediaview"),
13053−+ ("m3u", "audio/x-mpegurl"),
13054−+ ("man", "application/x-troff-man"),
13055−+ ("mdb", "application/x-msaccess"),
13056−+ ("me", "application/x-troff-me"),
13057−+ ("mht", "message/rfc822"),
13058−+ ("mhtml", "message/rfc822"),
13059−+ ("mid", "audio/mid"),
13060−+ ("mny", "application/x-msmoney"),
13061−+ ("mpv2", "video/mpeg"),
13062−+ ("ms", "application/x-troff-ms"),
13063−+ ("msg", "application/vnd.ms-outlook"),
13064−+ ("mvb", "application/x-msmediaview"),
13065−+ ("nc", "application/x-netcdf"),
13066−+ ("nws", "message/rfc822"),
13067−+ ("oda", "application/oda"),
13068−+ ("p10", "application/pkcs10"),
13069−+ ("p12", "application/x-pkcs12"),
13070−+ ("p7b", "application/x-pkcs7-certificates"),
13071−+ ("p7c", "application/x-pkcs7-mime"),
13072−+ ("p7m", "application/x-pkcs7-mime"),
13073−+ ("p7r", "application/x-pkcs7-certreqresp"),
13074−+ ("p7s", "application/x-pkcs7-signature"),
13075−+ ("png", "image/png"),
13076−+ ("pbm", "image/x-portable-bitmap"),
13077−+ ("pfx", "application/x-pkcs12"),
13078−+ ("pgm", "image/x-portable-graymap"),
13079−+ ("pko", "application/ynd.ms-pkipko"),
13080−+ ("pma", "application/x-perfmon"),
13081−+ ("pmc", "application/x-perfmon"),
13082−+ ("pml", "application/x-perfmon"),
13083−+ ("pmr", "application/x-perfmon"),
13084−+ ("pmw", "application/x-perfmon"),
13085−+ ("pnm", "image/x-portable-anymap"),
13086−+ ("pot", "application/vnd.ms-powerpoint"),
13087−+ ("ppm", "image/x-portable-pixmap"),
13088−+ ("pps", "application/vnd.ms-powerpoint"),
13089−+ ("ppt", "application/vnd.ms-powerpoint"),
13090−+ ("prf", "application/pics-rules"),
13091−+ ("ps", "application/postscript"),
13092−+ ("pub", "application/x-mspublisher"),
13093−+ ("qt", "video/quicktime"),
13094−+ ("ra", "audio/x-pn-realaudio"),
13095−+ ("ram", "audio/x-pn-realaudio"),
13096−+ ("ras", "image/x-cmu-raster"),
13097−+ ("rgb", "image/x-rgb"),
13098−+ ("rmi", "audio/mid"),
13099−+ ("roff", "application/x-troff"),
13100−+ ("rtf", "application/rtf"),
13101−+ ("rtx", "text/richtext"),
13102−+ ("scd", "application/x-msschedule"),
13103−+ ("sct", "text/scriptlet"),
13104−+ ("setpay", "application/set-payment-initiation"),
13105−+ ("setreg", "application/set-registration-initiation"),
13106−+ ("sh", "application/x-sh"),
13107−+ ("shar", "application/x-shar"),
13108−+ ("sit", "application/x-stuffit"),
13109−+ ("snd", "audio/basic"),
13110−+ ("spc", "application/x-pkcs7-certificates"),
13111−+ ("spl", "application/futuresplash"),
13112−+ ("src", "application/x-wais-source"),
13113−+ ("sst", "application/vnd.ms-pkicertstore"),
13114−+ ("stl", "application/vnd.ms-pkistl"),
13115−+ ("stm", "text/html"),
13116−+ ("sv4cpio", "application/x-sv4cpio"),
13117−+ ("sv4crc", "application/x-sv4crc"),
13118−+ ("svg", "image/svg+xml"),
13119−+ ("swf", "application/x-shockwave-flash"),
13120−+ ("t", "application/x-troff"),
13121−+ ("tar", "application/x-tar"),
13122−+ ("tcl", "application/x-tcl"),
13123−+ ("tex", "application/x-tex"),
13124−+ ("texi", "application/x-texinfo"),
13125−+ ("texinfo", "application/x-texinfo"),
13126−+ ("tgz", "application/x-compressed"),
13127−+ ("tr", "application/x-troff"),
13128−+ ("trm", "application/x-msterminal"),
13129−+ ("tsv", "text/tab-separated-values"),
13130−+ ("uls", "text/iuls"),
13131−+ ("ustar", "application/x-ustar"),
13132−+ ("vcf", "text/x-vcard"),
13133−+ ("vrml", "x-world/x-vrml"),
13134−+ ("wav", "audio/x-wav"),
13135−+ ("wcm", "application/vnd.ms-works"),
13136−+ ("wdb", "application/vnd.ms-works"),
13137−+ ("wks", "application/vnd.ms-works"),
13138−+ ("wmf", "application/x-msmetafile"),
13139−+ ("wps", "application/vnd.ms-works"),
13140−+ ("wri", "application/x-mswrite"),
13141−+ ("wrl", "x-world/x-vrml"),
13142−+ ("wrz", "x-world/x-vrml"),
13143−+ ("xaf", "x-world/x-vrml"),
13144−+ ("xbm", "image/x-xbitmap"),
13145−+ ("xla", "application/vnd.ms-excel"),
13146−+ ("xlc", "application/vnd.ms-excel"),
13147−+ ("xlm", "application/vnd.ms-excel"),
13148−+ ("xls", "application/vnd.ms-excel"),
13149−+ ("xlt", "application/vnd.ms-excel"),
13150−+ ("xlw", "application/vnd.ms-excel"),
13151−+ ("xof", "x-world/x-vrml"),
13152−+ ("xpm", "image/x-xpixmap"),
13153−+ ("xwd", "image/x-xwindowdump"),
13154−+ ("z", "application/x-compress")
13155−+
13156−+ ]
13157−+
patching/patches/MusicBrainz-0.2.1.patchdeleted−28
@@ -1,28 +0,0 @@
1−diff -ru orig/MusicBrainz.cabal new/MusicBrainz.cabal
2−--- orig/MusicBrainz.cabal 2014-06-30 16:08:08.987902131 +0300
3−+++ new/MusicBrainz.cabal 2014-06-30 16:08:08.000000000 +0300
4−@@ -23,8 +23,10 @@
5− , monad-control ==0.3.*
6− , bytestring
7− , conduit >= 1.0.0
8−+ , conduit-extra >= 1.0.0
9− , text
10− , time
11−+ , resourcet
12− , vector >=0.9
13− , xml-types ==0.3.*
14− , http-conduit >= 1.8.8
15−diff -ru orig/Network/Protocol/MusicBrainz/XML2/WebService.hs new/Network/Protocol/MusicBrainz/XML2/WebService.hs
16−--- orig/Network/Protocol/MusicBrainz/XML2/WebService.hs 2014-06-30 16:08:08.987902131 +0300
17−+++ new/Network/Protocol/MusicBrainz/XML2/WebService.hs 2014-06-30 16:08:08.000000000 +0300
18−@@ -11,8 +11,9 @@
19− import Control.Applicative (liftA2, (<|>))
20− import Control.Monad.IO.Class (MonadIO)
21− import Control.Monad.Trans.Control (MonadBaseControl)
22−+import Control.Monad.Trans.Resource (MonadThrow, runResourceT)
23− import qualified Data.ByteString.Lazy as BL
24−-import Data.Conduit (Consumer, ($=), ($$), MonadThrow, runResourceT)
25−+import Data.Conduit (Consumer, ($=), ($$))
26− import Data.Conduit.Binary (sourceLbs)
27− import Data.List (intercalate)
28− import Data.Maybe (fromMaybe)
patching/patches/Octree-0.5.2.patchdeleted−19
@@ -1,19 +0,0 @@
1−diff -ru orig/Octree.cabal new/Octree.cabal
2−--- orig/Octree.cabal 2014-04-17 19:22:31.263672240 +0300
3−+++ new/Octree.cabal 2014-04-17 19:22:31.000000000 +0300
4−@@ -32,13 +32,13 @@
5−
6− Test-suite test_Octree
7− Type: exitcode-stdio-1.0
8−- Build-depends: base>=4.0 && < 4.7, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0
9−+ Build-depends: base>=4.0 && < 4.8, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0
10− Main-is: tests/test_Octree.hs
11−
12− Test-suite readme
13− type: exitcode-stdio-1.0
14− -- We have a symlink: README.lhs -> README.md
15− main-is: README.lhs
16−- Build-depends: base>=4.0 && < 4.7, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0, markdown-unlit
17−+ Build-depends: base>=4.0 && < 4.8, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0, markdown-unlit
18− ghc-options: -pgmL markdown-unlit
19−
patching/patches/Octree-0.5.3.patchdeleted−19
@@ -1,19 +0,0 @@
1−diff -ru orig/Octree.cabal new/Octree.cabal
2−--- orig/Octree.cabal 2014-05-01 18:10:50.650819156 +0300
3−+++ new/Octree.cabal 2014-05-01 18:10:50.000000000 +0300
4−@@ -33,13 +33,13 @@
5−
6− Test-suite test_Octree
7− Type: exitcode-stdio-1.0
8−- Build-depends: base>=4.0 && < 4.7, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0
9−+ Build-depends: base>=4.0 && < 4.8, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0
10− Main-is: tests/test_Octree.hs
11−
12− Test-suite readme
13− type: exitcode-stdio-1.0
14− -- We have a symlink: README.lhs -> README.md
15− main-is: README.lhs
16−- Build-depends: base>=4.0 && < 4.7, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0, markdown-unlit
17−+ Build-depends: base>=4.0 && < 4.8, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0, markdown-unlit
18− ghc-options: -pgmL markdown-unlit
19−
patching/patches/arbtt-0.8.1.patchdeleted−30
@@ -1,30 +0,0 @@
1−diff -ruN orig/arbtt.cabal new/arbtt.cabal
2−--- orig/arbtt.cabal 2014-08-10 08:32:58.666725004 +0300
3−+++ new/arbtt.cabal 2014-08-10 08:32:58.000000000 +0300
4−@@ -35,7 +35,7 @@
5− build-depends:
6− base == 4.5.* || == 4.6.* || == 4.7.*,
7− filepath, directory, transformers, time >= 1.4, utf8-string,
8−- aeson == 0.6.* || == 0.7.*,
9−+ aeson,
10− array == 0.4.* || == 0.5.*,
11− binary >= 0.5,
12− bytestring, deepseq, strict, old-locale
13−@@ -82,7 +82,7 @@
14− binary >= 0.5,
15− deepseq, bytestring, utf8-string, time >= 1.4, strict,
16− transformers, unix, directory, filepath,
17−- aeson == 0.6.* || == 0.7.*,
18−+ aeson,
19− array == 0.4.* || == 0.5.*,
20− terminal-progress-bar, bytestring-progress
21− other-modules:
22−@@ -112,7 +112,7 @@
23− base == 4.5.* || == 4.6.* || == 4.7.*,
24− parsec == 3.*,
25− containers == 0.5.*,
26−- aeson == 0.6.* || == 0.7.*,
27−+ aeson,
28− array == 0.4.* || == 0.5.*,
29− binary >= 0.5,
30− deepseq, bytestring, utf8-string, time >= 1.4, strict,
patching/patches/async-2.0.1.5.patchdeleted−40
@@ -1,40 +0,0 @@
1−diff -ruN orig/Control/Concurrent/Async.hs new/Control/Concurrent/Async.hs
2−--- orig/Control/Concurrent/Async.hs 2014-08-11 12:23:17.688591763 +0300
3−+++ new/Control/Concurrent/Async.hs 2014-08-11 12:23:17.000000000 +0300
4−@@ -246,7 +246,10 @@
5− --
6− {-# INLINE waitCatch #-}
7− waitCatch :: Async a -> IO (Either SomeException a)
8−-waitCatch = atomically . waitCatchSTM
9−+waitCatch = tryAgain . atomically . waitCatchSTM
10−+ where
11−+ -- See: https://github.com/simonmar/async/issues/14
12−+ tryAgain f = f `catch` \BlockedIndefinitelyOnSTM -> f
13−
14− -- | Check whether an 'Async' has completed yet. If it has not
15− -- completed yet, then the result is @Nothing@, otherwise the result
16−diff -ruN orig/test/test-async.hs new/test/test-async.hs
17−--- orig/test/test-async.hs 2014-08-11 12:23:17.688591763 +0300
18−+++ new/test/test-async.hs 2014-08-11 12:23:17.000000000 +0300
19−@@ -29,6 +29,7 @@
20− testCase "async_cancel" async_cancel
21− , testCase "async_poll" async_poll
22− , testCase "async_poll2" async_poll2
23−+ , testCase "withasync_waitCatch_blocked" withasync_waitCatch_blocked
24− ]
25−
26− value = 42 :: Int
27−@@ -104,3 +105,13 @@
28− when (isNothing r) $ assertFailure ""
29− r <- poll a -- poll twice, just to check we don't deadlock
30− when (isNothing r) $ assertFailure ""
31−+
32−+withasync_waitCatch_blocked :: Assertion
33−+withasync_waitCatch_blocked = do
34−+ r <- withAsync (newEmptyMVar >>= takeMVar) waitCatch
35−+ case r of
36−+ Left e ->
37−+ case fromException e of
38−+ Just BlockedIndefinitelyOnMVar -> return ()
39−+ Nothing -> assertFailure $ show e
40−+ Right () -> assertFailure ""
patching/patches/authenticate-oauth-1.4.0.8.patchdeleted−147
@@ -1,147 +0,0 @@
1−diff -ru orig/authenticate-oauth.cabal new/authenticate-oauth.cabal
2−--- orig/authenticate-oauth.cabal 2014-02-21 07:19:28.878548521 +0200
3−+++ new/authenticate-oauth.cabal 2014-02-21 07:19:28.000000000 +0200
4−@@ -19,7 +19,7 @@
5− , transformers >= 0.1 && < 0.4
6− , bytestring >= 0.9
7− , crypto-pubkey-types >= 0.1 && < 0.5
8−- , RSA >= 1.2 && < 1.3
9−+ , RSA >= 1.2 && < 2.1
10− , time
11− , data-default
12− , base64-bytestring >= 0.1 && < 1.1
13−diff -ru orig/Web/Authenticate/OAuth.hs new/Web/Authenticate/OAuth.hs
14−--- orig/Web/Authenticate/OAuth.hs 2014-02-21 07:19:28.874548521 +0200
15−+++ new/Web/Authenticate/OAuth.hs 2014-02-21 07:19:28.000000000 +0200
16−@@ -1,5 +1,5 @@
17−-{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, MultiParamTypeClasses #-}
18−-{-# LANGUAGE OverloadedStrings, StandaloneDeriving #-}
19−+{-# LANGUAGE DeriveDataTypeable, OverloadedStrings, StandaloneDeriving, FlexibleContexts #-}
20−+{-# LANGUAGE CPP #-}
21− {-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
22− module Web.Authenticate.OAuth
23− ( -- * Data types
24−@@ -15,48 +15,50 @@
25− authorizeUrl, authorizeUrl', getAccessToken, getTemporaryCredential,
26− getTokenCredential, getTemporaryCredentialWithScope,
27− getAccessTokenProxy, getTemporaryCredentialProxy,
28−- getTokenCredentialProxy,
29−+ getTokenCredentialProxy,
30− getAccessToken', getTemporaryCredential',
31− -- * Utility Methods
32− paramEncode, addScope, addMaybeProxy
33− ) where
34−-import Blaze.ByteString.Builder (toByteString, Builder)
35−-import Codec.Crypto.RSA (ha_SHA1, rsassa_pkcs1_v1_5_sign)
36−-import Control.Exception
37−-import Control.Monad
38−-import Control.Monad.IO.Class (MonadIO, liftIO)
39−-import Control.Monad.Trans.Control
40−-import Control.Monad.Trans.Resource
41−-import Crypto.Types.PubKey.RSA (PrivateKey (..), PublicKey (..))
42−-import Data.ByteString.Base64
43−-import qualified Data.ByteString.Char8 as BS
44−-import qualified Data.ByteString.Lazy.Char8 as BSL
45−-import Data.Char
46−-import Data.Conduit (Source, ($$), ($=))
47−-import Data.Conduit.Blaze (builderToByteString)
48−-import qualified Data.Conduit.List as CL
49−-import Data.Default
50−-import Data.Digest.Pure.SHA
51−-import qualified Data.IORef as I
52−-import Data.List (sortBy)
53−-import Data.Maybe
54−-import Data.Time
55−-import Network.HTTP.Conduit
56−-import Network.HTTP.Types (SimpleQuery, parseSimpleQuery)
57−-import Network.HTTP.Types (Header)
58−-import Network.HTTP.Types (renderSimpleQuery, status200)
59−-import Numeric
60−-import System.Random
61−-#if MIN_VERSION_base(4,7,0)
62−-import Data.Data hiding (Proxy (..))
63−-#else
64−+import Network.HTTP.Conduit
65− import Data.Data
66−+import qualified Data.ByteString.Char8 as BS
67−+import qualified Data.ByteString.Lazy.Char8 as BSL
68−+import Data.Maybe
69−+import Network.HTTP.Types (parseSimpleQuery, SimpleQuery)
70−+import Control.Exception
71−+import Control.Monad
72−+import Data.List (sortBy)
73−+import System.Random
74−+import Data.Char
75−+import Data.Digest.Pure.SHA
76−+import Data.ByteString.Base64
77−+import Data.Time
78−+import Numeric
79−+#if MIN_VERSION_RSA(2, 0, 0)
80−+import Codec.Crypto.RSA (rsassa_pkcs1_v1_5_sign, hashSHA1)
81−+#else
82−+import Codec.Crypto.RSA (rsassa_pkcs1_v1_5_sign, ha_SHA1)
83− #endif
84−+import Crypto.Types.PubKey.RSA (PrivateKey(..), PublicKey(..))
85−+import Network.HTTP.Types (Header)
86−+import Blaze.ByteString.Builder (toByteString)
87−+import Control.Monad.IO.Class (MonadIO)
88−+import Network.HTTP.Types (renderSimpleQuery, status200)
89−+import Data.Conduit (($$), ($=), Source)
90−+import qualified Data.Conduit.List as CL
91−+import Data.Conduit.Blaze (builderToByteString)
92−+import Blaze.ByteString.Builder (Builder)
93−+import Control.Monad.IO.Class (liftIO)
94−+import Control.Monad.Trans.Control
95−+import Control.Monad.Trans.Resource
96−+import Data.Default
97−+import qualified Data.IORef as I
98−
99− -- | Data type for OAuth client (consumer).
100−---
101−--- The constructor for this data type is not exposed.
102−--- Instead, you should use the 'def' method or 'newOAuth' function to retrieve a default instance,
103−+--
104−+-- The constructor for this data type is not exposed.
105−+-- Instead, you should use the 'def' method or 'newOAuth' function to retrieve a default instance,
106− -- and then use the records below to make modifications.
107− -- This approach allows us to add configuration options without breaking backwards compatibility.
108− data OAuth = OAuth { oauthServerName :: String -- ^ Service name (default: @\"\"@)
109−@@ -71,7 +73,7 @@
110− , oauthAuthorizeUri :: String
111− -- ^ Uri to authorize (default: @\"\"@).
112− -- You MUST specify if you use 'authorizeUrl' or 'authorizeZUrl'';
113−- -- otherwise you can just leave this empty.
114−+ -- otherwise you can just leave this empty.
115− , oauthSignatureMethod :: SignMethod
116− -- ^ Signature Method (default: 'HMACSHA1')
117− , oauthConsumerKey :: BS.ByteString
118−@@ -188,7 +190,7 @@
119− getTemporaryCredential' hook oa manager = do
120− let req = fromJust $ parseUrl $ oauthRequestUri oa
121− crd = maybe id (insert "oauth_callback") (oauthCallback oa) $ emptyCredential
122−- req' <- signOAuth oa crd $ hook (req { method = "POST" })
123−+ req' <- signOAuth oa crd $ hook (req { method = "POST" })
124− rsp <- httpLbs req' manager
125− if responseStatus rsp == status200
126− then do
127−@@ -211,7 +213,7 @@
128− -> String -- ^ URL to authorize
129− authorizeUrl' f oa cr = oauthAuthorizeUri oa ++ BS.unpack (renderSimpleQuery True queries)
130− where fixed = ("oauth_token", token cr):f oa cr
131−- queries =
132−+ queries =
133− case oauthCallback oa of
134− Nothing -> fixed
135− Just callback -> ("oauth_callback", callback):fixed
136−@@ -346,7 +348,11 @@
137− PLAINTEXT ->
138− return $ BS.intercalate "&" $ map paramEncode [oauthConsumerSecret oa, tokenSecret tok]
139− RSASHA1 pr ->
140−+#if MIN_VERSION_RSA(2, 0, 0)
141−+ liftM (encode . toStrict . rsassa_pkcs1_v1_5_sign hashSHA1 pr) (getBaseString tok req)
142−+#else
143− liftM (encode . toStrict . rsassa_pkcs1_v1_5_sign ha_SHA1 pr) (getBaseString tok req)
144−+#endif
145−
146− #if MIN_VERSION_http_conduit(2, 0, 0)
147− addAuthHeader :: BS.ByteString -> Credential -> Request -> Request
patching/patches/aws-0.8.6.patchdeleted−596
@@ -1,596 +0,0 @@
1−diff -ru orig/Aws/Aws.hs new/Aws/Aws.hs
2−--- orig/Aws/Aws.hs 2014-04-04 10:18:25.108401067 +0300
3−+++ new/Aws/Aws.hs 2014-04-04 10:18:24.000000000 +0300
4−@@ -33,7 +33,6 @@
5− import Control.Monad.IO.Class
6− import Control.Monad.Trans
7− import Control.Monad.Trans.Resource
8−-import Data.Attempt (Attempt(Success, Failure))
9− import qualified Data.ByteString as B
10− import qualified Data.CaseInsensitive as CI
11− import qualified Data.Conduit as C
12−@@ -185,11 +184,8 @@
13− unsafeAws cfg scfg manager request = do
14− metadataRef <- liftIO $ newIORef mempty
15−
16−- let catchAll :: ResourceT IO a -> ResourceT IO (Attempt a)
17−- catchAll = E.handle (return . failure') . fmap Success
18−-
19−- failure' :: E.SomeException -> Attempt a
20−- failure' = Failure
21−+ let catchAll :: ResourceT IO a -> ResourceT IO (Either E.SomeException a)
22−+ catchAll = E.handle (return . Left) . fmap Right
23−
24− resp <- catchAll $
25− unsafeAwsRef cfg scfg manager metadataRef request
26−@@ -268,8 +264,8 @@
27− where go request = do resp <- lift $ aws cfg scfg manager request
28− C.yield resp
29− case responseResult resp of
30−- Failure _ -> return ()
31−- Success x ->
32−+ Left _ -> return ()
33−+ Right x ->
34− case nextIteratedRequest request x of
35− Nothing -> return ()
36− Just nextRequest -> go nextRequest
37−diff -ru orig/Aws/Core.hs new/Aws/Core.hs
38−--- orig/Aws/Core.hs 2014-04-04 10:18:25.108401067 +0300
39−+++ new/Aws/Core.hs 2014-04-04 10:18:24.000000000 +0300
40−@@ -89,13 +89,12 @@
41− import Control.Applicative
42− import Control.Arrow
43− import qualified Control.Exception as E
44−-import qualified Control.Failure as F
45− import Control.Monad
46− import Control.Monad.IO.Class
47−+import Control.Monad.Trans.Resource (ResourceT, MonadThrow (throwM))
48− import qualified Crypto.Classes as Crypto
49− import qualified Crypto.HMAC as HMAC
50− import Crypto.Hash.CryptoAPI (MD5, SHA1, SHA256, hash')
51−-import Data.Attempt (Attempt(..), FromAttempt(..))
52− import Data.ByteString (ByteString)
53− import qualified Data.ByteString as B
54− import qualified Data.ByteString.Base16 as Base16
55−@@ -104,7 +103,7 @@
56− import qualified Data.ByteString.Lazy as L
57− import qualified Data.ByteString.UTF8 as BU
58− import Data.Char
59−-import Data.Conduit (ResourceT, ($$+-))
60−+import Data.Conduit (($$+-))
61− import qualified Data.Conduit as C
62− import qualified Data.Conduit.List as CL
63− import Data.Default (def)
64−@@ -137,12 +136,12 @@
65− --
66− -- Response forms a Writer-like monad.
67− data Response m a = Response { responseMetadata :: m
68−- , responseResult :: Attempt a }
69−+ , responseResult :: Either E.SomeException a }
70− deriving (Show, Functor)
71−
72− -- | Read a response result (if it's a success response, fail otherwise).
73−-readResponse :: FromAttempt f => Response m a -> f a
74−-readResponse = fromAttempt . responseResult
75−+readResponse :: MonadThrow n => Response m a -> n a
76−+readResponse = either throwM return . responseResult
77−
78− -- | Read a response result (if it's a success response, fail otherwise). In MonadIO.
79− readResponseIO :: MonadIO io => Response m a -> io a
80−@@ -159,13 +158,13 @@
81− --multiResponse :: Monoid m => Response m a -> Response [m] a ->
82−
83− instance Monoid m => Monad (Response m) where
84−- return x = Response mempty (Success x)
85−- Response m1 (Failure e) >>= _ = Response m1 (Failure e)
86−- Response m1 (Success x) >>= f = let Response m2 y = f x
87−+ return x = Response mempty (Right x)
88−+ Response m1 (Left e) >>= _ = Response m1 (Left e)
89−+ Response m1 (Right x) >>= f = let Response m2 y = f x
90− in Response (m1 `mappend` m2) y -- currently using First-semantics, Last SHOULD work too
91−
92−-instance (Monoid m, E.Exception e) => F.Failure e (Response m) where
93−- failure e = Response mempty (F.failure e)
94−+instance Monoid m => MonadThrow (Response m) where
95−+ throwM e = Response mempty (throwM e)
96−
97− -- | Add metadata to an 'IORef' (using 'mappend').
98− tellMetadataRef :: Monoid m => IORef m -> m -> IO ()
99−@@ -696,24 +695,24 @@
100− elCont name = laxElement name &/ content &| T.unpack
101−
102− -- | Extract the first element from a parser result list, and throw an 'XmlException' if the list is empty.
103−-force :: F.Failure XmlException m => String -> [a] -> m a
104−+force :: MonadThrow m => String -> [a] -> m a
105− force = Cu.force . XmlException
106−
107− -- | Extract the first element from a monadic parser result list, and throw an 'XmlException' if the list is empty.
108−-forceM :: F.Failure XmlException m => String -> [m a] -> m a
109−+forceM :: MonadThrow m => String -> [m a] -> m a
110− forceM = Cu.forceM . XmlException
111−
112− -- | Read an integer from a 'T.Text', throwing an 'XmlException' on failure.
113−-textReadInt :: (F.Failure XmlException m, Num a) => T.Text -> m a
114−+textReadInt :: (MonadThrow m, Num a) => T.Text -> m a
115− textReadInt s = case reads $ T.unpack s of
116− [(n,"")] -> return $ fromInteger n
117−- _ -> F.failure $ XmlException "Invalid Integer"
118−+ _ -> throwM $ XmlException "Invalid Integer"
119−
120− -- | Read an integer from a 'String', throwing an 'XmlException' on failure.
121−-readInt :: (F.Failure XmlException m, Num a) => String -> m a
122−+readInt :: (MonadThrow m, Num a) => String -> m a
123− readInt s = case reads s of
124− [(n,"")] -> return $ fromInteger n
125−- _ -> F.failure $ XmlException "Invalid Integer"
126−+ _ -> throwM $ XmlException "Invalid Integer"
127−
128− -- | Create a complete 'HTTPResponseConsumer' from a simple function that takes a 'Cu.Cursor' to XML in the response
129− -- body.
130−@@ -731,5 +730,5 @@
131− let Response metadata x = parse cursor
132− liftIO $ tellMetadataRef metadataRef metadata
133− case x of
134−- Failure err -> liftIO $ C.monadThrow err
135−- Success v -> return v
136−+ Left err -> liftIO $ throwM err
137−+ Right v -> return v
138−diff -ru orig/Aws/DynamoDb/Core.hs new/Aws/DynamoDb/Core.hs
139−--- orig/Aws/DynamoDb/Core.hs 2014-04-04 10:18:25.108401067 +0300
140−+++ new/Aws/DynamoDb/Core.hs 2014-04-04 10:18:24.000000000 +0300
141−@@ -2,6 +2,7 @@
142−
143− import Aws.Core
144− import qualified Control.Exception as C
145−+import Control.Monad.Trans.Resource (throwM)
146− import Crypto.Hash.CryptoAPI (SHA256, hash)
147− import qualified Data.Aeson as A
148− import qualified Data.ByteString as B
149−@@ -125,5 +126,5 @@
150− (HTTP.Status{HTTP.statusCode=200}) -> do
151− case A.fromJSON val of
152− A.Success a -> return a
153−- A.Error err -> monadThrow $ DyError (HTTP.responseStatus resp) "" err
154−- _ -> monadThrow $ DyError (HTTP.responseStatus resp) "" (show val)
155−+ A.Error err -> throwM $ DyError (HTTP.responseStatus resp) "" err
156−+ _ -> throwM $ DyError (HTTP.responseStatus resp) "" (show val)
157−diff -ru orig/Aws/Ec2/InstanceMetadata.hs new/Aws/Ec2/InstanceMetadata.hs
158−--- orig/Aws/Ec2/InstanceMetadata.hs 2014-04-04 10:18:25.112401067 +0300
159−+++ new/Aws/Ec2/InstanceMetadata.hs 2014-04-04 10:18:24.000000000 +0300
160−@@ -2,7 +2,7 @@
161−
162− import Control.Applicative
163− import Control.Exception
164−-import Control.Failure
165−+import Control.Monad.Trans.Resource (throwM)
166− import qualified Data.ByteString.Lazy as L
167− import qualified Data.ByteString.Lazy.Char8 as B8
168− import Data.ByteString.Lazy.UTF8 as BU
169−@@ -25,7 +25,7 @@
170− getInstanceMetadataFirst :: HTTP.Manager -> String -> IO L.ByteString
171− getInstanceMetadataFirst mgr p = do listing <- getInstanceMetadataListing mgr p
172− case listing of
173−- [] -> failure (MetadataNotFound p)
174−+ [] -> throwM (MetadataNotFound p)
175− (x:_) -> getInstanceMetadata mgr p x
176−
177− getInstanceMetadataOrFirst :: HTTP.Manager -> String -> Maybe String -> IO L.ByteString
178−diff -ru orig/Aws/Iam/Core.hs new/Aws/Iam/Core.hs
179−--- orig/Aws/Iam/Core.hs 2014-04-04 10:18:25.112401067 +0300
180−+++ new/Aws/Iam/Core.hs 2014-04-04 10:18:24.000000000 +0300
181−@@ -19,8 +19,8 @@
182− import qualified Blaze.ByteString.Builder as Blaze
183− import qualified Blaze.ByteString.Builder.Char8 as Blaze8
184− import Control.Exception (Exception)
185−-import qualified Control.Failure as F
186− import Control.Monad
187−+import Control.Monad.Trans.Resource (MonadThrow, throwM)
188− import Data.ByteString (ByteString)
189− import Data.IORef
190− import Data.List (intersperse, sort)
191−@@ -152,13 +152,13 @@
192− fromError cursor = do
193− errCode <- force "Missing Error Code" $ cursor $// elContent "Code"
194− errMsg <- force "Missing Error Message" $ cursor $// elContent "Message"
195−- F.failure $ IamError (HTTP.responseStatus resp) errCode errMsg
196−+ throwM $ IamError (HTTP.responseStatus resp) errCode errMsg
197−
198− -- | Parses IAM @DateTime@ data type.
199−-parseDateTime :: (F.Failure XmlException m) => String -> m UTCTime
200−+parseDateTime :: MonadThrow m => String -> m UTCTime
201− parseDateTime x
202− = case parseTime defaultTimeLocale iso8601UtcDate x of
203−- Nothing -> F.failure $ XmlException $ "Invalid DateTime: " ++ x
204−+ Nothing -> throwM $ XmlException $ "Invalid DateTime: " ++ x
205− Just dt -> return dt
206−
207− -- | The IAM @User@ data type.
208−@@ -180,7 +180,7 @@
209− deriving (Eq, Ord, Show, Typeable)
210−
211− -- | Parses the IAM @User@ data type.
212−-parseUser :: (F.Failure XmlException m) => Cu.Cursor -> m User
213−+parseUser :: MonadThrow m => Cu.Cursor -> m User
214− parseUser cursor = do
215− userArn <- attr "Arn"
216− userCreateDate <- attr "CreateDate" >>= parseDateTime . Text.unpack
217−diff -ru orig/Aws/Iam/Internal.hs new/Aws/Iam/Internal.hs
218−--- orig/Aws/Iam/Internal.hs 2014-04-04 10:18:25.112401067 +0300
219−+++ new/Aws/Iam/Internal.hs 2014-04-04 10:18:24.000000000 +0300
220−@@ -15,8 +15,8 @@
221− import Aws.Iam.Core
222− import Control.Applicative
223− import Control.Arrow (second)
224−-import qualified Control.Failure as F
225− import Control.Monad
226−+import Control.Monad.Trans.Resource (MonadThrow)
227− import Data.ByteString (ByteString)
228− import Data.Maybe
229− import Data.Monoid ((<>))
230−@@ -62,7 +62,7 @@
231− -- | Reads and returns the @IsTruncated@ and @Marker@ attributes present in
232− -- all IAM data pagination responses.
233− markedIterResponse
234−- :: F.Failure XmlException m
235−+ :: MonadThrow m
236− => Cu.Cursor
237− -> m (Bool, Maybe Text)
238− markedIterResponse cursor = do
239−diff -ru orig/Aws/S3/Commands/CopyObject.hs new/Aws/S3/Commands/CopyObject.hs
240−--- orig/Aws/S3/Commands/CopyObject.hs 2014-04-04 10:18:25.112401067 +0300
241−+++ new/Aws/S3/Commands/CopyObject.hs 2014-04-04 10:18:24.000000000 +0300
242−@@ -5,7 +5,7 @@
243− import Aws.S3.Core
244− import Control.Applicative
245− import Control.Arrow (second)
246−-import Control.Failure
247−+import Control.Monad.Trans.Resource (throwM)
248− import qualified Data.CaseInsensitive as CI
249− import Data.Maybe
250− import qualified Data.Text as T
251−@@ -93,7 +93,7 @@
252− return $ CopyObjectResponse vid lastMod etag
253− where parse el = do
254− let parseHttpDate' x = case parseTime defaultTimeLocale iso8601UtcDate x of
255−- Nothing -> failure $ XmlException ("Invalid Last-Modified " ++ x)
256−+ Nothing -> throwM $ XmlException ("Invalid Last-Modified " ++ x)
257− Just y -> return y
258− lastMod <- forceM "Missing Last-Modified" $ el $/ elContent "LastModified" &| (parseHttpDate' . T.unpack)
259− etag <- force "Missing ETag" $ el $/ elContent "ETag"
260−diff -ru orig/Aws/S3/Core.hs new/Aws/S3/Core.hs
261−--- orig/Aws/S3/Core.hs 2014-04-04 10:18:25.112401067 +0300
262−+++ new/Aws/S3/Core.hs 2014-04-04 10:18:24.000000000 +0300
263−@@ -5,8 +5,8 @@
264− import Control.Arrow ((***))
265− import Control.Monad
266− import Control.Monad.IO.Class
267−+import Control.Monad.Trans.Resource (MonadThrow, throwM)
268− import Crypto.Hash.CryptoAPI (MD5)
269−-import Data.Attempt (Attempt(..))
270− import Data.Conduit (($$+-))
271− import Data.Function
272− import Data.IORef
273−@@ -20,12 +20,10 @@
274− import qualified Blaze.ByteString.Builder as Blaze
275− import qualified Blaze.ByteString.Builder.Char8 as Blaze8
276− import qualified Control.Exception as C
277−-import qualified Control.Failure as F
278− import qualified Data.ByteString as B
279− import qualified Data.ByteString.Char8 as B8
280− import qualified Data.ByteString.Base64 as Base64
281− import qualified Data.CaseInsensitive as CI
282−-import qualified Data.Conduit as C
283− import qualified Data.Serialize as Serialize
284− import qualified Data.Text as T
285− import qualified Data.Text.Encoding as T
286−@@ -248,10 +246,10 @@
287− = do doc <- HTTP.responseBody resp $$+- XML.sinkDoc XML.def
288− let cursor = Cu.fromDocument doc
289− liftIO $ case parseError cursor of
290−- Success err -> C.monadThrow err
291−- Failure otherErr -> C.monadThrow otherErr
292−+ Right err -> throwM err
293−+ Left otherErr -> throwM otherErr
294− where
295−- parseError :: Cu.Cursor -> Attempt S3Error
296−+ parseError :: Cu.Cursor -> Either C.SomeException S3Error
297− parseError root = do code <- force "Missing error Code" $ root $/ elContent "Code"
298− message <- force "Missing error Message" $ root $/ elContent "Message"
299− let resource = listToMaybe $ root $/ elContent "Resource"
300−@@ -279,7 +277,7 @@
301− }
302− deriving (Show)
303−
304−-parseUserInfo :: F.Failure XmlException m => Cu.Cursor -> m UserInfo
305−+parseUserInfo :: MonadThrow m => Cu.Cursor -> m UserInfo
306− parseUserInfo el = do id_ <- force "Missing user ID" $ el $/ elContent "ID"
307− displayName <- force "Missing user DisplayName" $ el $/ elContent "DisplayName"
308− return UserInfo { userId = id_, userDisplayName = displayName }
309−@@ -308,10 +306,10 @@
310− | ReducedRedundancy
311− deriving (Show)
312−
313−-parseStorageClass :: F.Failure XmlException m => T.Text -> m StorageClass
314−+parseStorageClass :: MonadThrow m => T.Text -> m StorageClass
315− parseStorageClass "STANDARD" = return Standard
316− parseStorageClass "REDUCED_REDUNDANCY" = return ReducedRedundancy
317−-parseStorageClass s = F.failure . XmlException $ "Invalid Storage Class: " ++ T.unpack s
318−+parseStorageClass s = throwM . XmlException $ "Invalid Storage Class: " ++ T.unpack s
319−
320− writeStorageClass :: StorageClass -> T.Text
321− writeStorageClass Standard = "STANDARD"
322−@@ -321,9 +319,9 @@
323− = AES256
324− deriving (Show)
325−
326−-parseServerSideEncryption :: F.Failure XmlException m => T.Text -> m ServerSideEncryption
327−+parseServerSideEncryption :: MonadThrow m => T.Text -> m ServerSideEncryption
328− parseServerSideEncryption "AES256" = return AES256
329−-parseServerSideEncryption s = F.failure . XmlException $ "Invalid Server Side Encryption: " ++ T.unpack s
330−+parseServerSideEncryption s = throwM . XmlException $ "Invalid Server Side Encryption: " ++ T.unpack s
331−
332− writeServerSideEncryption :: ServerSideEncryption -> T.Text
333− writeServerSideEncryption AES256 = "AES256"
334−@@ -358,11 +356,11 @@
335− }
336− deriving (Show)
337−
338−-parseObjectInfo :: F.Failure XmlException m => Cu.Cursor -> m ObjectInfo
339−+parseObjectInfo :: MonadThrow m => Cu.Cursor -> m ObjectInfo
340− parseObjectInfo el
341− = do key <- force "Missing object Key" $ el $/ elContent "Key"
342− let time s = case parseTime defaultTimeLocale "%Y-%m-%dT%H:%M:%S%QZ" $ T.unpack s of
343−- Nothing -> F.failure $ XmlException "Invalid time"
344−+ Nothing -> throwM $ XmlException "Invalid time"
345− Just v -> return v
346− lastModified <- forceM "Missing object LastModified" $ el $/ elContent "LastModified" &| time
347− eTag <- force "Missing object ETag" $ el $/ elContent "ETag"
348−@@ -392,7 +390,7 @@
349− }
350− deriving (Show)
351−
352−-parseObjectMetadata :: F.Failure HeaderException m => HTTP.ResponseHeaders -> m ObjectMetadata
353−+parseObjectMetadata :: MonadThrow m => HTTP.ResponseHeaders -> m ObjectMetadata
354− parseObjectMetadata h = ObjectMetadata
355− `liftM` deleteMarker
356− `ap` etag
357−@@ -406,15 +404,15 @@
358− Nothing -> return False
359− Just "true" -> return True
360− Just "false" -> return False
361−- Just x -> F.failure $ HeaderException ("Invalid x-amz-delete-marker " ++ x)
362−+ Just x -> throwM $ HeaderException ("Invalid x-amz-delete-marker " ++ x)
363− etag = case T.decodeUtf8 `fmap` lookup "ETag" h of
364− Just x -> return x
365−- Nothing -> F.failure $ HeaderException "ETag missing"
366−+ Nothing -> throwM $ HeaderException "ETag missing"
367− lastModified = case B8.unpack `fmap` lookup "Last-Modified" h of
368− Just ts -> case parseHttpDate ts of
369− Just t -> return t
370−- Nothing -> F.failure $ HeaderException ("Invalid Last-Modified: " ++ ts)
371−- Nothing -> F.failure $ HeaderException "Last-Modified missing"
372−+ Nothing -> throwM $ HeaderException ("Invalid Last-Modified: " ++ ts)
373−+ Nothing -> throwM $ HeaderException "Last-Modified missing"
374− versionId = T.decodeUtf8 `fmap` lookup "x-amz-version-id" h
375− -- expiration = return undefined
376− userMetadata = flip mapMaybe ht $
377−diff -ru orig/Aws/Ses/Core.hs new/Aws/Ses/Core.hs
378−--- orig/Aws/Ses/Core.hs 2014-04-04 10:18:25.112401067 +0300
379−+++ new/Aws/Ses/Core.hs 2014-04-04 10:18:24.000000000 +0300
380−@@ -22,8 +22,8 @@
381− import qualified Blaze.ByteString.Builder as Blaze
382− import qualified Blaze.ByteString.Builder.Char8 as Blaze8
383− import qualified Control.Exception as C
384−-import qualified Control.Failure as F
385− import Control.Monad (mplus)
386−+import Control.Monad.Trans.Resource (throwM)
387− import qualified Data.ByteString as B
388− import qualified Data.ByteString.Base64 as B64
389− import Data.ByteString.Char8 ({-IsString-})
390−@@ -128,7 +128,7 @@
391− fromError cursor = do
392− errCode <- force "Missing Error Code" $ cursor $// elContent "Code"
393− errMessage <- force "Missing Error Message" $ cursor $// elContent "Message"
394−- F.failure $ SesError (HTTP.responseStatus resp) errCode errMessage
395−+ throwM $ SesError (HTTP.responseStatus resp) errCode errMessage
396−
397− class SesAsQuery a where
398− -- | Write a data type as a list of query parameters.
399−diff -ru orig/Aws/SimpleDb/Core.hs new/Aws/SimpleDb/Core.hs
400−--- orig/Aws/SimpleDb/Core.hs 2014-04-04 10:18:25.116401067 +0300
401−+++ new/Aws/SimpleDb/Core.hs 2014-04-04 10:18:24.000000000 +0300
402−@@ -4,8 +4,8 @@
403− import qualified Blaze.ByteString.Builder as Blaze
404− import qualified Blaze.ByteString.Builder.Char8 as Blaze8
405− import qualified Control.Exception as C
406−-import qualified Control.Failure as F
407− import Control.Monad
408−+import Control.Monad.Trans.Resource (MonadThrow, throwM)
409− import qualified Data.ByteString as B
410− import qualified Data.ByteString.Base64 as Base64
411− import Data.IORef
412−@@ -149,16 +149,16 @@
413− (err:_) -> fromError err
414− fromError cursor = do errCode <- force "Missing Error Code" $ cursor $// elCont "Code"
415− errMessage <- force "Missing Error Message" $ cursor $// elCont "Message"
416−- F.failure $ SdbError (HTTP.responseStatus resp) errCode errMessage
417−+ throwM $ SdbError (HTTP.responseStatus resp) errCode errMessage
418−
419− class SdbFromResponse a where
420− sdbFromResponse :: Cu.Cursor -> Response SdbMetadata a
421−
422−-sdbCheckResponseType :: F.Failure XmlException m => a -> T.Text -> Cu.Cursor -> m a
423−+sdbCheckResponseType :: MonadThrow m => a -> T.Text -> Cu.Cursor -> m a
424− sdbCheckResponseType a n c = do _ <- force ("Expected response type " ++ T.unpack n) (Cu.laxElement n c)
425− return a
426−
427−-decodeBase64 :: F.Failure XmlException m => Cu.Cursor -> m T.Text
428−+decodeBase64 :: MonadThrow m => Cu.Cursor -> m T.Text
429− decodeBase64 cursor =
430− let encoded = T.concat $ cursor $/ Cu.content
431− encoding = listToMaybe $ cursor $| Cu.laxAttribute "encoding" &| T.toCaseFold
432−@@ -166,15 +166,15 @@
433− case encoding of
434− Nothing -> return encoded
435− Just "base64" -> case Base64.decode . T.encodeUtf8 $ encoded of
436−- Left msg -> F.failure $ XmlException ("Invalid Base64 data: " ++ msg)
437−+ Left msg -> throwM $ XmlException ("Invalid Base64 data: " ++ msg)
438− Right x -> return $ T.decodeUtf8 x
439−- Just actual -> F.failure $ XmlException ("Unrecognized encoding " ++ T.unpack actual)
440−+ Just actual -> throwM $ XmlException ("Unrecognized encoding " ++ T.unpack actual)
441−
442− data Attribute a
443− = ForAttribute { attributeName :: T.Text, attributeData :: a }
444− deriving (Show)
445−
446−-readAttribute :: F.Failure XmlException m => Cu.Cursor -> m (Attribute T.Text)
447−+readAttribute :: MonadThrow m => Cu.Cursor -> m (Attribute T.Text)
448− readAttribute cursor = do
449− name <- forceM "Missing Name" $ cursor $/ Cu.laxElement "Name" &| decodeBase64
450− value <- forceM "Missing Value" $ cursor $/ Cu.laxElement "Value" &| decodeBase64
451−@@ -225,7 +225,7 @@
452− = Item { itemName :: T.Text, itemData :: a }
453− deriving (Show)
454−
455−-readItem :: F.Failure XmlException m => Cu.Cursor -> m (Item [Attribute T.Text])
456−+readItem :: MonadThrow m => Cu.Cursor -> m (Item [Attribute T.Text])
457− readItem cursor = do
458− name <- force "Missing Name" <=< sequence $ cursor $/ Cu.laxElement "Name" &| decodeBase64
459− attributes <- sequence $ cursor $/ Cu.laxElement "Attribute" &| readAttribute
460−diff -ru orig/Aws/Sqs/Commands/Message.hs new/Aws/Sqs/Commands/Message.hs
461−--- orig/Aws/Sqs/Commands/Message.hs 2014-04-04 10:18:25.116401067 +0300
462−+++ new/Aws/Sqs/Commands/Message.hs 2014-04-04 10:18:24.000000000 +0300
463−@@ -4,9 +4,9 @@
464− import Aws.Core
465− import Aws.Sqs.Core
466− import Control.Applicative
467−+import Control.Monad.Trans.Resource (MonadThrow)
468− import Data.Maybe
469− import Text.XML.Cursor (($/), ($//), (&/), (&|))
470−-import qualified Control.Failure as F
471− import qualified Data.ByteString.Char8 as B
472− import qualified Data.Text as T
473− import qualified Data.Text.Encoding as TE
474−@@ -98,7 +98,7 @@
475− }
476− deriving (Show)
477−
478−-readMessageAttribute :: F.Failure XmlException m => Cu.Cursor -> m (MessageAttribute,T.Text)
479−+readMessageAttribute :: MonadThrow m => Cu.Cursor -> m (MessageAttribute,T.Text)
480− readMessageAttribute cursor = do
481− name <- force "Missing Name" $ cursor $/ Cu.laxElement "Name" &/ Cu.content
482− value <- force "Missing Value" $ cursor $/ Cu.laxElement "Value" &/ Cu.content
483−diff -ru orig/Aws/Sqs/Core.hs new/Aws/Sqs/Core.hs
484−--- orig/Aws/Sqs/Core.hs 2014-04-04 10:18:25.116401067 +0300
485−+++ new/Aws/Sqs/Core.hs 2014-04-04 10:18:24.000000000 +0300
486−@@ -5,14 +5,12 @@
487− import qualified Blaze.ByteString.Builder as Blaze
488− import qualified Blaze.ByteString.Builder.Char8 as Blaze8
489− import qualified Control.Exception as C
490−-import qualified Control.Failure as F
491− import Control.Monad
492− import Control.Monad.IO.Class
493−-import Data.Attempt (Attempt(..))
494−+import Control.Monad.Trans.Resource (MonadThrow, throwM)
495− import qualified Data.ByteString as B
496− import qualified Data.ByteString.Char8 as BC
497− import Data.Conduit (($$+-))
498−-import qualified Data.Conduit as C
499− import Data.IORef
500− import Data.List
501− import Data.Maybe
502−@@ -234,10 +232,10 @@
503− = do doc <- HTTP.responseBody resp $$+- XML.sinkDoc XML.def
504− let cursor = Cu.fromDocument doc
505− liftIO $ case parseError cursor of
506−- Success err -> C.monadThrow err
507−- Failure otherErr -> C.monadThrow otherErr
508−+ Right err -> throwM err
509−+ Left otherErr -> throwM otherErr
510− where
511−- parseError :: Cu.Cursor -> Attempt SqsError
512−+ parseError :: Cu.Cursor -> Either C.SomeException SqsError
513− parseError root = do cursor <- force "Missing Error" $ root $/ Cu.laxElement "Error"
514− code <- force "Missing error Code" $ cursor $/ elContent "Code"
515− message <- force "Missing error Message" $ cursor $/ elContent "Message"
516−@@ -291,7 +289,7 @@
517− | PermissionGetQueueAttributes
518− deriving (Show, Enum, Eq)
519−
520−-parseQueueAttribute :: F.Failure XmlException m => T.Text -> m QueueAttribute
521−+parseQueueAttribute :: MonadThrow m => T.Text -> m QueueAttribute
522− parseQueueAttribute "ApproximateNumberOfMessages" = return ApproximateNumberOfMessages
523− parseQueueAttribute "ApproximateNumberOfMessagesNotVisible" = return ApproximateNumberOfMessagesNotVisible
524− parseQueueAttribute "VisibilityTimeout" = return VisibilityTimeout
525−@@ -301,7 +299,7 @@
526− parseQueueAttribute "MaximumMessageSize" = return MaximumMessageSize
527− parseQueueAttribute "MessageRetentionPeriod" = return MessageRetentionPeriod
528− parseQueueAttribute "QueueArn" = return QueueArn
529−-parseQueueAttribute x = F.failure $ XmlException ( "Invalid Attribute Name. " ++ show x)
530−+parseQueueAttribute x = throwM $ XmlException ( "Invalid Attribute Name. " ++ show x)
531−
532− printQueueAttribute :: QueueAttribute -> T.Text
533− printQueueAttribute QueueAll = "All"
534−@@ -315,12 +313,12 @@
535− printQueueAttribute MessageRetentionPeriod = "MessageRetentionPeriod"
536− printQueueAttribute QueueArn = "QueueArn"
537−
538−-parseMessageAttribute :: F.Failure XmlException m => T.Text -> m MessageAttribute
539−+parseMessageAttribute :: MonadThrow m => T.Text -> m MessageAttribute
540− parseMessageAttribute "SenderId" = return SenderId
541− parseMessageAttribute "SentTimestamp" = return SentTimestamp
542− parseMessageAttribute "ApproximateReceiveCount" = return ApproximateReceiveCount
543− parseMessageAttribute "ApproximateFirstReceiveTimestamp" = return ApproximateFirstReceiveTimestamp
544−-parseMessageAttribute x = F.failure $ XmlException ( "Invalid Attribute Name. " ++ show x)
545−+parseMessageAttribute x = throwM $ XmlException ( "Invalid Attribute Name. " ++ show x)
546−
547− printMessageAttribute :: MessageAttribute -> T.Text
548− printMessageAttribute MessageAll = "All"
549−diff -ru orig/aws.cabal new/aws.cabal
550−--- orig/aws.cabal 2014-04-04 10:18:25.120401065 +0300
551−+++ new/aws.cabal 2014-04-04 10:18:24.000000000 +0300
552−@@ -98,8 +98,6 @@
553− Aws.DynamoDb.Core
554−
555− Build-depends:
556−- attempt >= 0.3.1.1 && < 0.5,
557−- attoparsec-conduit >= 1.0 && < 1.1,
558− aeson >= 0.6 && < 0.8,
559− base == 4.*,
560− base16-bytestring == 0.1.*,
561−@@ -108,29 +106,30 @@
562− bytestring >= 0.9 && < 0.11,
563− case-insensitive >= 0.2 && < 1.3,
564− cereal >= 0.3 && < 0.5,
565−- conduit >= 1.0 && < 1.1,
566−+ conduit >= 1.1 && < 1.2,
567−+ conduit-extra >= 1.1 && < 1.2,
568− containers >= 0.4,
569− crypto-api >= 0.9,
570− cryptohash >= 0.8 && < 0.12,
571− cryptohash-cryptoapi == 0.1.*,
572− data-default == 0.5.*,
573− directory >= 1.0 && < 1.3,
574−- failure >= 0.2.0.1 && < 0.3,
575− filepath >= 1.1 && < 1.4,
576−- http-conduit >= 1.9 && < 2.1,
577−+ http-conduit >= 2.1 && < 2.2,
578− http-types >= 0.7 && < 0.9,
579− lifted-base >= 0.1 && < 0.3,
580− monad-control >= 0.3,
581− mtl == 2.*,
582− old-locale == 1.*,
583−- resourcet >= 0.3.3 && <0.5,
584−+ resourcet >= 1.1 && < 1.2,
585− text >= 0.11,
586− time >= 1.1.4 && < 1.5,
587− transformers >= 0.2.2.0 && < 0.4,
588− unordered-containers >= 0.2,
589− utf8-string == 0.3.*,
590− vector >= 0.10,
591−- xml-conduit >= 1.1 && <1.2
592−+ xml-conduit >= 1.2 && <1.3
593−+ , ghc-prim
594−
595− GHC-Options: -Wall
596−
patching/patches/aws-0.9.3.patchnew file+12
@@ -0,0 +1,12 @@
1+diff -ruN orig/aws.cabal new/aws.cabal
2+--- orig/aws.cabal 2014-08-28 07:02:24.655832025 +0300
3++++ new/aws.cabal 2014-08-28 07:02:24.000000000 +0300
4+@@ -109,7 +109,7 @@
5+ bytestring >= 0.9 && < 0.11,
6+ case-insensitive >= 0.2 && < 1.3,
7+ cereal >= 0.3 && < 0.5,
8+- conduit >= 1.1 && < 1.2,
9++ conduit >= 1.1 && < 1.3,
10+ conduit-extra >= 1.1 && < 1.2,
11+ containers >= 0.4,
12+ cryptohash >= 0.11 && < 0.12,
patching/patches/bytes-0.14.0.1.patchdeleted−25
@@ -1,25 +0,0 @@
1−diff -ru orig/src/Data/Bytes/Serial.hs new/src/Data/Bytes/Serial.hs
2−--- orig/src/Data/Bytes/Serial.hs 2014-06-08 07:58:00.820951939 +0300
3−+++ new/src/Data/Bytes/Serial.hs 2014-06-08 07:58:00.000000000 +0300
4−@@ -58,7 +58,9 @@
5− import Data.Int
6− import Data.Bits
7− import Data.Monoid as Monoid
8−+#if MIN_VERSION_base(4, 6, 0)
9− import Data.Ord (Down(..))
10−+#endif
11− import Data.Functor.Identity as Functor
12− import Data.Functor.Constant as Functor
13− import Data.Functor.Product as Functor
14−@@ -475,9 +477,11 @@
15− serialize = serialize . (fromIntegral::Int -> Int8) . fromEnum
16− deserialize = (toEnum . (fromIntegral::Int8 -> Int)) `liftM` deserialize
17−
18−+#if MIN_VERSION_base(4, 6, 0)
19− instance Serial a => Serial (Down a) where
20− serialize (Down a) = serialize a
21− deserialize = Down `liftM` deserialize
22−+#endif
23−
24− instance Serial Version where
25− serialize (Version vb ts) = serialize (fmap VarInt vb, ts)
patching/patches/bzlib-conduit-0.2.1.1.patchdeleted−46
@@ -1,46 +0,0 @@
1−diff -ru orig/bzlib-conduit.cabal new/bzlib-conduit.cabal
2−--- orig/bzlib-conduit.cabal 2014-04-02 12:25:07.231917434 +0300
3−+++ new/bzlib-conduit.cabal 2014-04-02 12:25:06.000000000 +0300
4−@@ -26,7 +26,8 @@
5− build-depends: base == 4.*
6− , bytestring >=0.9 && <0.11
7− , mtl == 2.*
8−- , conduit >= 0.5 && < 1.1
9−+ , conduit >= 0.5 && < 1.2
10−+ , conduit-extra >= 1.0 && < 1.2
11− , resourcet
12− , data-default
13− , bindings-DSL
14−@@ -54,7 +55,9 @@
15− , QuickCheck
16− , random
17− , conduit
18−+ , conduit-extra
19− , bzlib-conduit
20−+ , resourcet
21−
22− benchmark bench
23− type: exitcode-stdio-1.0
24−@@ -62,4 +65,5 @@
25− main-is: bench.hs
26− build-depends: base == 4.*
27− , conduit
28−+ , conduit-extra
29− , bzlib-conduit
30−diff -ru orig/test/test.hs new/test/test.hs
31−--- orig/test/test.hs 2014-04-02 12:25:07.227917434 +0300
32−+++ new/test/test.hs 2014-04-02 12:25:06.000000000 +0300
33−@@ -1,6 +1,7 @@
34− {-# LANGUAGE ViewPatterns #-}
35− import Control.Applicative
36− import Control.Monad
37−+import Control.Monad.Trans.Resource (runResourceT)
38− import qualified Data.ByteString.Char8 as S
39− import qualified Data.ByteString.Lazy.Char8 as L
40− import Data.Conduit
41−@@ -36,4 +37,4 @@
42− <$> replicateM (abs n) randomIO
43− dest <- runResourceT $ do
44− C.sourceList (P.map S.pack ss) =$= bzip2 =$= bunzip2 $$ B.take (10^9)
45−- return $ dest == L.pack (concat ss)
46−+ return $ dest == L.pack (P.concat ss)
patching/patches/cereal-conduit-0.7.2.patchdeleted−53
@@ -1,53 +0,0 @@
1−diff -ru orig/cereal-conduit.cabal new/cereal-conduit.cabal
2−--- orig/cereal-conduit.cabal 2014-04-03 08:22:14.122388542 +0300
3−+++ new/cereal-conduit.cabal 2014-04-03 08:22:13.000000000 +0300
4−@@ -19,7 +19,8 @@
5−
6− library
7− build-depends: base >= 4 && < 5
8−- , conduit >= 1.0.0 && < 1.1
9−+ , conduit >= 1.0.0 && < 1.2
10−+ , resourcet >= 0.4 && < 1.2
11− , cereal >= 0.4.0.0 && < 0.5
12− , bytestring
13− , transformers >= 0.2.0.0
14−diff -ru orig/Data/Conduit/Cereal.hs new/Data/Conduit/Cereal.hs
15−--- orig/Data/Conduit/Cereal.hs 2014-04-03 08:22:14.122388542 +0300
16−+++ new/Data/Conduit/Cereal.hs 2014-04-03 08:22:13.000000000 +0300
17−@@ -19,6 +19,7 @@
18−
19− import Control.Exception.Base
20− import Control.Monad.Trans.Class (MonadTrans, lift)
21−+import Control.Monad.Trans.Resource (MonadThrow, monadThrow)
22− import qualified Data.ByteString as BS
23− import qualified Data.ByteString.Lazy as LBS
24− import qualified Data.Conduit as C
25−@@ -34,7 +35,7 @@
26− instance Exception GetException
27−
28− -- | Run a 'Get' repeatedly on the input stream, producing an output stream of whatever the 'Get' outputs.
29−-conduitGet :: C.MonadThrow m => Get o -> C.Conduit BS.ByteString m o
30−+conduitGet :: MonadThrow m => Get o -> C.Conduit BS.ByteString m o
31− conduitGet = mkConduitGet errorHandler
32− where errorHandler msg = pipeError $ GetException msg
33−
34−@@ -42,7 +43,7 @@
35− --
36− -- If 'Get' succeed it will return the data read and unconsumed part of the input stream.
37− -- If the 'Get' fails due to deserialization error or early termination of the input stream it raise an error.
38−-sinkGet :: C.MonadThrow m => Get r -> C.Consumer BS.ByteString m r
39−+sinkGet :: MonadThrow m => Get r -> C.Consumer BS.ByteString m r
40− sinkGet = mkSinkGet errorHandler terminationHandler
41− where errorHandler msg = pipeError $ GetException msg
42− terminationHandler f = case f BS.empty of
43−@@ -50,8 +51,8 @@
44− Done r lo -> C.leftover lo >> return r
45− Partial _ -> pipeError $ GetException "Failed reading: Internal error: unexpected Partial."
46−
47−-pipeError :: (C.MonadThrow m, MonadTrans t, Exception e) => e -> t m a
48−-pipeError e = lift $ C.monadThrow e
49−+pipeError :: (MonadThrow m, MonadTrans t, Exception e) => e -> t m a
50−+pipeError e = lift $ monadThrow e
51−
52− -- | Convert a 'Put' into a 'Source'. Runs in constant memory.
53− sourcePut :: Monad m => Put -> C.Producer m BS.ByteString
patching/patches/concurrent-extra-0.7.0.6.patchdeleted−21
@@ -1,21 +0,0 @@
1−diff -ru orig/concurrent-extra.cabal new/concurrent-extra.cabal
2−--- orig/concurrent-extra.cabal 2014-04-04 14:42:42.732063525 +0300
3−+++ new/concurrent-extra.cabal 2014-04-04 14:42:42.000000000 +0300
4−@@ -50,7 +50,7 @@
5− -------------------------------------------------------------------------------
6−
7− library
8−- build-depends: base >= 3 && < 4.7
9−+ build-depends: base >= 3 && < 4.8
10− , base-unicode-symbols >= 0.1.1 && < 0.3
11− , stm >= 2.1.2.1 && < 2.5
12− , unbounded-delays >= 0.1 && < 0.2
13−@@ -80,7 +80,7 @@
14−
15− ghc-options: -Wall -threaded
16−
17−- build-depends: base >= 3 && < 4.7
18−+ build-depends: base >= 3 && < 4.8
19− , base-unicode-symbols >= 0.1.1 && < 0.3
20− , stm >= 2.1.2.1 && < 2.5
21− , unbounded-delays >= 0.1 && < 0.2
patching/patches/criterion-1.0.0.2.patchdeleted−1643
@@ -1,1643 +0,0 @@
1−diff -ruN orig/criterion.cabal new/criterion.cabal
2−--- orig/criterion.cabal 2014-08-10 20:30:05.797809138 +0300
3−+++ new/criterion.cabal 2014-08-10 20:30:05.000000000 +0300
4−@@ -131,6 +131,7 @@
5− type: exitcode-stdio-1.0
6− hs-source-dirs: tests
7− main-is: Tests.hs
8−+ other-modules: Properties
9−
10− ghc-options:
11− -Wall -threaded -O0 -rtsopts
12−diff -ruN orig/examples/fibber.html new/examples/fibber.html
13−--- orig/examples/fibber.html 2014-08-10 20:30:05.789809138 +0300
14−+++ new/examples/fibber.html 1970-01-01 02:00:00.000000000 +0200
15−@@ -1,726 +0,0 @@
16−-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
17−-<html>
18−- <head>
19−- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
20−- <title>criterion report</title>
21−- <script language="javascript" type="text/javascript">
22−- /*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
23−-!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.1",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="<select msallowclip=''><option selected=''></option></select>",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+Math.random()}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)
24−-},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ab=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ib={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wb=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var zb=/^(none|table(?!-c[ea]).+)/,Ab=new RegExp("^("+Q+")(.*)$","i"),Bb=new RegExp("^([+-])=("+Q+")","i"),Cb={position:"absolute",visibility:"hidden",display:"block"},Db={letterSpacing:"0",fontWeight:"400"},Eb=["Webkit","O","Moz","ms"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Hb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ib(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?"border":"content"),d,f)+"px"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",tb(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),"normal"===e&&b in Db&&(e=Db[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pb=/queueHooks$/,Qb=[Vb],Rb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Ob.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||tb(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?tb(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb("show"),slideUp:Tb("hide"),slideToggle:Tb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Lb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Mb||(Mb=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Mb),Mb=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Yb,Zb,$b=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))
25−-},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cc=n.now(),dc=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var ec,fc,gc=/#.*$/,hc=/([?&])_=[^&]*/,ic=/^(.*?):[ \t]*([^\r\n]*)$/gm,jc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,kc=/^(?:GET|HEAD)$/,lc=/^\/\//,mc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,nc={},oc={},pc="*/".concat("*");try{fc=location.href}catch(qc){fc=l.createElement("a"),fc.href="",fc=fc.href}ec=mc.exec(fc.toLowerCase())||[];function rc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function sc(a,b,c,d){var e={},f=a===oc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function tc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function uc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function vc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:fc,type:"GET",isLocal:jc.test(ec[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":pc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?tc(tc(a,n.ajaxSettings),b):tc(n.ajaxSettings,a)},ajaxPrefilter:rc(nc),ajaxTransport:rc(oc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=ic.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||fc)+"").replace(gc,"").replace(lc,ec[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=mc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===ec[1]&&h[2]===ec[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(ec[3]||("http:"===ec[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),sc(nc,k,b,v),2===t)return v;i=k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!kc.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=hc.test(d)?d.replace(hc,"$1_="+cc++):d+(dc.test(d)?"&":"?")+"_="+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+pc+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=sc(oc,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=uc(k,v,f)),u=vc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var wc=/%20/g,xc=/\[\]$/,yc=/\r?\n/g,zc=/^(?:submit|button|image|reset|file)$/i,Ac=/^(?:input|select|textarea|keygen)/i;function Bc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||xc.test(a)?d(a,e):Bc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Bc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Bc(c,a[c],b,e);return d.join("&").replace(wc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Ac.test(this.nodeName)&&!zc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(yc,"\r\n")}}):{name:b.name,value:c.replace(yc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Cc=0,Dc={},Ec={0:200,1223:204},Fc=n.ajaxSettings.xhr();a.ActiveXObject&&n(a).on("unload",function(){for(var a in Dc)Dc[a]()}),k.cors=!!Fc&&"withCredentials"in Fc,k.ajax=Fc=!!Fc,n.ajaxTransport(function(a){var b;return k.cors||Fc&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Cc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Dc[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Ec[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Dc[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Gc=[],Hc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Gc.pop()||n.expando+"_"+cc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Hc.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Hc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Hc,"$1"+e):b.jsonp!==!1&&(b.url+=(dc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Gc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Ic=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Ic)return Ic.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Jc=a.document.documentElement;function Kc(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Kc(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Jc;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Jc})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Kc(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=yb(k.pixelPosition,function(a,c){return c?(c=xb(a,b),vb.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Lc=a.jQuery,Mc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Mc),b&&a.jQuery===n&&(a.jQuery=Lc),n},typeof b===U&&(a.jQuery=a.$=n),n});
26−-
27−- </script>
28−- <script language="javascript" type="text/javascript">
29−- /* Javascript plotting library for jQuery, version 0.8.3.
30−-
31−-Copyright (c) 2007-2014 IOLA and Ole Laursen.
32−-Licensed under the MIT license.
33−-
34−-*/
35−-(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);(function($){var hasOwnProperty=Object.prototype.hasOwnProperty;if(!$.fn.detach){$.fn.detach=function(){return this.each(function(){if(this.parentNode){this.parentNode.removeChild(this)}})}}function Canvas(cls,container){var element=container.children("."+cls)[0];if(element==null){element=document.createElement("canvas");element.className=cls;$(element).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(container);if(!element.getContext){if(window.G_vmlCanvasManager){element=window.G_vmlCanvasManager.initElement(element)}else{throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.")}}}this.element=element;var context=this.context=element.getContext("2d");var devicePixelRatio=window.devicePixelRatio||1,backingStoreRatio=context.webkitBackingStorePixelRatio||context.mozBackingStorePixelRatio||context.msBackingStorePixelRatio||context.oBackingStorePixelRatio||context.backingStorePixelRatio||1;this.pixelRatio=devicePixelRatio/backingStoreRatio;this.resize(container.width(),container.height());this.textContainer=null;this.text={};this._textCache={}}Canvas.prototype.resize=function(width,height){if(width<=0||height<=0){throw new Error("Invalid dimensions for plot, width = "+width+", height = "+height)}var element=this.element,context=this.context,pixelRatio=this.pixelRatio;if(this.width!=width){element.width=width*pixelRatio;element.style.width=width+"px";this.width=width}if(this.height!=height){element.height=height*pixelRatio;element.style.height=height+"px";this.height=height}context.restore();context.save();context.scale(pixelRatio,pixelRatio)};Canvas.prototype.clear=function(){this.context.clearRect(0,0,this.width,this.height)};Canvas.prototype.render=function(){var cache=this._textCache;for(var layerKey in cache){if(hasOwnProperty.call(cache,layerKey)){var layer=this.getTextLayer(layerKey),layerCache=cache[layerKey];layer.hide();for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){if(position.active){if(!position.rendered){layer.append(position.element);position.rendered=true}}else{positions.splice(i--,1);if(position.rendered){position.element.detach()}}}if(positions.length==0){delete styleCache[key]}}}}}layer.show()}}};Canvas.prototype.getTextLayer=function(classes){var layer=this.text[classes];if(layer==null){if(this.textContainer==null){this.textContainer=$("<div class='flot-text'></div>").css({position:"absolute",top:0,left:0,bottom:0,right:0,"font-size":"smaller",color:"#545454"}).insertAfter(this.element)}layer=this.text[classes]=$("<div></div>").addClass(classes).css({position:"absolute",top:0,left:0,bottom:0,right:0}).appendTo(this.textContainer)}return layer};Canvas.prototype.getTextInfo=function(layer,text,font,angle,width){var textStyle,layerCache,styleCache,info;text=""+text;if(typeof font==="object"){textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px/"+font.lineHeight+"px "+font.family}else{textStyle=font}layerCache=this._textCache[layer];if(layerCache==null){layerCache=this._textCache[layer]={}}styleCache=layerCache[textStyle];if(styleCache==null){styleCache=layerCache[textStyle]={}}info=styleCache[text];if(info==null){var element=$("<div></div>").html(text).css({position:"absolute","max-width":width,top:-9999}).appendTo(this.getTextLayer(layer));if(typeof font==="object"){element.css({font:textStyle,color:font.color})}else if(typeof font==="string"){element.addClass(font)}info=styleCache[text]={width:element.outerWidth(true),height:element.outerHeight(true),element:element,positions:[]};element.detach()}return info};Canvas.prototype.addText=function(layer,x,y,text,font,angle,width,halign,valign){var info=this.getTextInfo(layer,text,font,angle,width),positions=info.positions;if(halign=="center"){x-=info.width/2}else if(halign=="right"){x-=info.width}if(valign=="middle"){y-=info.height/2}else if(valign=="bottom"){y-=info.height}for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=true;return}}position={active:true,rendered:false,element:positions.length?info.element.clone():info.element,x:x,y:y};positions.push(position);position.element.css({top:Math.round(y),left:Math.round(x),"text-align":halign})};Canvas.prototype.removeText=function(layer,x,y,text,font,angle){if(text==null){var layerCache=this._textCache[layer];if(layerCache!=null){for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){position.active=false}}}}}}}else{var positions=this.getTextInfo(layer,text,font,angle).positions;for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=false}}}};function Plot(placeholder,data_,options_,plugins){var series=[],options={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:.85,sorted:null},xaxis:{show:null,position:"bottom",mode:null,font:null,color:null,tickColor:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,reserveSpace:null,tickLength:null,alignTicksWithAxis:null,tickDecimals:null,tickSize:null,minTickSize:null},yaxis:{autoscaleMargin:.02,position:"left"},xaxes:[],yaxes:[],series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff",symbol:"circle"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false,zero:true},shadowSize:3,highlightColor:null},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,borderColor:null,tickColor:null,margin:0,labelMargin:5,axisMargin:8,borderWidth:2,minBorderMargin:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},interaction:{redrawOverlayInterval:1e3/60},hooks:{}},surface=null,overlay=null,eventHolder=null,ctx=null,octx=null,xaxes=[],yaxes=[],plotOffset={left:0,right:0,top:0,bottom:0},plotWidth=0,plotHeight=0,hooks={processOptions:[],processRawData:[],processDatapoints:[],processOffset:[],drawBackground:[],drawSeries:[],draw:[],bindEvents:[],drawOverlay:[],shutdown:[]},plot=this;plot.setData=setData;plot.setupGrid=setupGrid;plot.draw=draw;plot.getPlaceholder=function(){return placeholder};plot.getCanvas=function(){return surface.element};plot.getPlotOffset=function(){return plotOffset};plot.width=function(){return plotWidth};plot.height=function(){return plotHeight};plot.offset=function(){var o=eventHolder.offset();o.left+=plotOffset.left;o.top+=plotOffset.top;return o};plot.getData=function(){return series};plot.getAxes=function(){var res={},i;$.each(xaxes.concat(yaxes),function(_,axis){if(axis)res[axis.direction+(axis.n!=1?axis.n:"")+"axis"]=axis});return res};plot.getXAxes=function(){return xaxes};plot.getYAxes=function(){return yaxes};plot.c2p=canvasToAxisCoords;plot.p2c=axisToCanvasCoords;plot.getOptions=function(){return options};plot.highlight=highlight;plot.unhighlight=unhighlight;plot.triggerRedrawOverlay=triggerRedrawOverlay;plot.pointOffset=function(point){return{left:parseInt(xaxes[axisNumber(point,"x")-1].p2c(+point.x)+plotOffset.left,10),top:parseInt(yaxes[axisNumber(point,"y")-1].p2c(+point.y)+plotOffset.top,10)}};plot.shutdown=shutdown;plot.destroy=function(){shutdown();placeholder.removeData("plot").empty();series=[];options=null;surface=null;overlay=null;eventHolder=null;ctx=null;octx=null;xaxes=[];yaxes=[];hooks=null;highlights=[];plot=null};plot.resize=function(){var width=placeholder.width(),height=placeholder.height();surface.resize(width,height);overlay.resize(width,height)};plot.hooks=hooks;initPlugins(plot);parseOptions(options_);setupCanvases();setData(data_);setupGrid();draw();bindEvents();function executeHooks(hook,args){args=[plot].concat(args);for(var i=0;i<hook.length;++i)hook[i].apply(this,args)}function initPlugins(){var classes={Canvas:Canvas};for(var i=0;i<plugins.length;++i){var p=plugins[i];p.init(plot,classes);if(p.options)$.extend(true,options,p.options)}}function parseOptions(opts){$.extend(true,options,opts);if(opts&&opts.colors){options.colors=opts.colors}if(options.xaxis.color==null)options.xaxis.color=$.color.parse(options.grid.color).scale("a",.22).toString();if(options.yaxis.color==null)options.yaxis.color=$.color.parse(options.grid.color).scale("a",.22).toString();if(options.xaxis.tickColor==null)options.xaxis.tickColor=options.grid.tickColor||options.xaxis.color;if(options.yaxis.tickColor==null)options.yaxis.tickColor=options.grid.tickColor||options.yaxis.color;if(options.grid.borderColor==null)options.grid.borderColor=options.grid.color;if(options.grid.tickColor==null)options.grid.tickColor=$.color.parse(options.grid.color).scale("a",.22).toString();var i,axisOptions,axisCount,fontSize=placeholder.css("font-size"),fontSizeDefault=fontSize?+fontSize.replace("px",""):13,fontDefaults={style:placeholder.css("font-style"),size:Math.round(.8*fontSizeDefault),variant:placeholder.css("font-variant"),weight:placeholder.css("font-weight"),family:placeholder.css("font-family")};axisCount=options.xaxes.length||1;for(i=0;i<axisCount;++i){axisOptions=options.xaxes[i];if(axisOptions&&!axisOptions.tickColor){axisOptions.tickColor=axisOptions.color}axisOptions=$.extend(true,{},options.xaxis,axisOptions);options.xaxes[i]=axisOptions;if(axisOptions.font){axisOptions.font=$.extend({},fontDefaults,axisOptions.font);if(!axisOptions.font.color){axisOptions.font.color=axisOptions.color}if(!axisOptions.font.lineHeight){axisOptions.font.lineHeight=Math.round(axisOptions.font.size*1.15)}}}axisCount=options.yaxes.length||1;for(i=0;i<axisCount;++i){axisOptions=options.yaxes[i];if(axisOptions&&!axisOptions.tickColor){axisOptions.tickColor=axisOptions.color}axisOptions=$.extend(true,{},options.yaxis,axisOptions);options.yaxes[i]=axisOptions;if(axisOptions.font){axisOptions.font=$.extend({},fontDefaults,axisOptions.font);if(!axisOptions.font.color){axisOptions.font.color=axisOptions.color}if(!axisOptions.font.lineHeight){axisOptions.font.lineHeight=Math.round(axisOptions.font.size*1.15)}}}if(options.xaxis.noTicks&&options.xaxis.ticks==null)options.xaxis.ticks=options.xaxis.noTicks;if(options.yaxis.noTicks&&options.yaxis.ticks==null)options.yaxis.ticks=options.yaxis.noTicks;if(options.x2axis){options.xaxes[1]=$.extend(true,{},options.xaxis,options.x2axis);options.xaxes[1].position="top";if(options.x2axis.min==null){options.xaxes[1].min=null}if(options.x2axis.max==null){options.xaxes[1].max=null}}if(options.y2axis){options.yaxes[1]=$.extend(true,{},options.yaxis,options.y2axis);options.yaxes[1].position="right";if(options.y2axis.min==null){options.yaxes[1].min=null}if(options.y2axis.max==null){options.yaxes[1].max=null}}if(options.grid.coloredAreas)options.grid.markings=options.grid.coloredAreas;if(options.grid.coloredAreasColor)options.grid.markingsColor=options.grid.coloredAreasColor;if(options.lines)$.extend(true,options.series.lines,options.lines);if(options.points)$.extend(true,options.series.points,options.points);if(options.bars)$.extend(true,options.series.bars,options.bars);if(options.shadowSize!=null)options.series.shadowSize=options.shadowSize;if(options.highlightColor!=null)options.series.highlightColor=options.highlightColor;for(i=0;i<options.xaxes.length;++i)getOrCreateAxis(xaxes,i+1).options=options.xaxes[i];for(i=0;i<options.yaxes.length;++i)getOrCreateAxis(yaxes,i+1).options=options.yaxes[i];for(var n in hooks)if(options.hooks[n]&&options.hooks[n].length)hooks[n]=hooks[n].concat(options.hooks[n]);executeHooks(hooks.processOptions,[options])}function setData(d){series=parseData(d);fillInSeriesOptions();processData()}function parseData(d){var res=[];for(var i=0;i<d.length;++i){var s=$.extend(true,{},options.series);if(d[i].data!=null){s.data=d[i].data;delete d[i].data;$.extend(true,s,d[i]);d[i].data=s.data}else s.data=d[i];res.push(s)}return res}function axisNumber(obj,coord){var a=obj[coord+"axis"];if(typeof a=="object")a=a.n;if(typeof a!="number")a=1;return a}function allAxes(){return $.grep(xaxes.concat(yaxes),function(a){return a})}function canvasToAxisCoords(pos){var res={},i,axis;for(i=0;i<xaxes.length;++i){axis=xaxes[i];if(axis&&axis.used)res["x"+axis.n]=axis.c2p(pos.left)}for(i=0;i<yaxes.length;++i){axis=yaxes[i];if(axis&&axis.used)res["y"+axis.n]=axis.c2p(pos.top)}if(res.x1!==undefined)res.x=res.x1;if(res.y1!==undefined)res.y=res.y1;return res}function axisToCanvasCoords(pos){var res={},i,axis,key;for(i=0;i<xaxes.length;++i){axis=xaxes[i];if(axis&&axis.used){key="x"+axis.n;if(pos[key]==null&&axis.n==1)key="x";if(pos[key]!=null){res.left=axis.p2c(pos[key]);break}}}for(i=0;i<yaxes.length;++i){axis=yaxes[i];if(axis&&axis.used){key="y"+axis.n;if(pos[key]==null&&axis.n==1)key="y";if(pos[key]!=null){res.top=axis.p2c(pos[key]);break}}}return res}function getOrCreateAxis(axes,number){if(!axes[number-1])axes[number-1]={n:number,direction:axes==xaxes?"x":"y",options:$.extend(true,{},axes==xaxes?options.xaxis:options.yaxis)};return axes[number-1]}function fillInSeriesOptions(){var neededColors=series.length,maxIndex=-1,i;for(i=0;i<series.length;++i){var sc=series[i].color;if(sc!=null){neededColors--;if(typeof sc=="number"&&sc>maxIndex){maxIndex=sc}}}if(neededColors<=maxIndex){neededColors=maxIndex+1}var c,colors=[],colorPool=options.colors,colorPoolSize=colorPool.length,variation=0;for(i=0;i<neededColors;i++){c=$.color.parse(colorPool[i%colorPoolSize]||"#666");if(i%colorPoolSize==0&&i){if(variation>=0){if(variation<.5){variation=-variation-.2}else variation=0}else variation=-variation}colors[i]=c.scale("rgb",1+variation)}var colori=0,s;for(i=0;i<series.length;++i){s=series[i];if(s.color==null){s.color=colors[colori].toString();++colori}else if(typeof s.color=="number")s.color=colors[s.color].toString();if(s.lines.show==null){var v,show=true;for(v in s)if(s[v]&&s[v].show){show=false;break}if(show)s.lines.show=true}if(s.lines.zero==null){s.lines.zero=!!s.lines.fill}s.xaxis=getOrCreateAxis(xaxes,axisNumber(s,"x"));s.yaxis=getOrCreateAxis(yaxes,axisNumber(s,"y"))}}function processData(){var topSentry=Number.POSITIVE_INFINITY,bottomSentry=Number.NEGATIVE_INFINITY,fakeInfinity=Number.MAX_VALUE,i,j,k,m,length,s,points,ps,x,y,axis,val,f,p,data,format;function updateAxis(axis,min,max){if(min<axis.datamin&&min!=-fakeInfinity)axis.datamin=min;if(max>axis.datamax&&max!=fakeInfinity)axis.datamax=max}$.each(allAxes(),function(_,axis){axis.datamin=topSentry;axis.datamax=bottomSentry;axis.used=false});for(i=0;i<series.length;++i){s=series[i];s.datapoints={points:[]};executeHooks(hooks.processRawData,[s,s.data,s.datapoints])}for(i=0;i<series.length;++i){s=series[i];data=s.data;format=s.datapoints.format;if(!format){format=[];format.push({x:true,number:true,required:true});format.push({y:true,number:true,required:true});if(s.bars.show||s.lines.show&&s.lines.fill){var autoscale=!!(s.bars.show&&s.bars.zero||s.lines.show&&s.lines.zero);format.push({y:true,number:true,required:false,defaultValue:0,autoscale:autoscale});if(s.bars.horizontal){delete format[format.length-1].y;format[format.length-1].x=true}}s.datapoints.format=format}if(s.datapoints.pointsize!=null)continue;s.datapoints.pointsize=format.length;ps=s.datapoints.pointsize;points=s.datapoints.points;var insertSteps=s.lines.show&&s.lines.steps;s.xaxis.used=s.yaxis.used=true;for(j=k=0;j<data.length;++j,k+=ps){p=data[j];var nullify=p==null;if(!nullify){for(m=0;m<ps;++m){val=p[m];f=format[m];if(f){if(f.number&&val!=null){val=+val;if(isNaN(val))val=null;else if(val==Infinity)val=fakeInfinity;else if(val==-Infinity)val=-fakeInfinity}if(val==null){if(f.required)nullify=true;if(f.defaultValue!=null)val=f.defaultValue}}points[k+m]=val}}if(nullify){for(m=0;m<ps;++m){val=points[k+m];if(val!=null){f=format[m];if(f.autoscale!==false){if(f.x){updateAxis(s.xaxis,val,val)}if(f.y){updateAxis(s.yaxis,val,val)}}}points[k+m]=null}}else{if(insertSteps&&k>0&&points[k-ps]!=null&&points[k-ps]!=points[k]&&points[k-ps+1]!=points[k+1]){for(m=0;m<ps;++m)points[k+ps+m]=points[k+m];points[k+1]=points[k-ps+1];k+=ps}}}}for(i=0;i<series.length;++i){s=series[i];executeHooks(hooks.processDatapoints,[s,s.datapoints])}for(i=0;i<series.length;++i){s=series[i];points=s.datapoints.points;ps=s.datapoints.pointsize;format=s.datapoints.format;var xmin=topSentry,ymin=topSentry,xmax=bottomSentry,ymax=bottomSentry;for(j=0;j<points.length;j+=ps){if(points[j]==null)continue;for(m=0;m<ps;++m){val=points[j+m];f=format[m];if(!f||f.autoscale===false||val==fakeInfinity||val==-fakeInfinity)continue;if(f.x){if(val<xmin)xmin=val;if(val>xmax)xmax=val}if(f.y){if(val<ymin)ymin=val;if(val>ymax)ymax=val}}}if(s.bars.show){var delta;switch(s.bars.align){case"left":delta=0;break;case"right":delta=-s.bars.barWidth;break;default:delta=-s.bars.barWidth/2}if(s.bars.horizontal){ymin+=delta;ymax+=delta+s.bars.barWidth}else{xmin+=delta;xmax+=delta+s.bars.barWidth}}updateAxis(s.xaxis,xmin,xmax);updateAxis(s.yaxis,ymin,ymax)}$.each(allAxes(),function(_,axis){if(axis.datamin==topSentry)axis.datamin=null;if(axis.datamax==bottomSentry)axis.datamax=null})}function setupCanvases(){placeholder.css("padding",0).children().filter(function(){return!$(this).hasClass("flot-overlay")&&!$(this).hasClass("flot-base")}).remove();if(placeholder.css("position")=="static")placeholder.css("position","relative");surface=new Canvas("flot-base",placeholder);overlay=new Canvas("flot-overlay",placeholder);ctx=surface.context;octx=overlay.context;eventHolder=$(overlay.element).unbind();var existing=placeholder.data("plot");if(existing){existing.shutdown();overlay.clear()}placeholder.data("plot",plot)}function bindEvents(){if(options.grid.hoverable){eventHolder.mousemove(onMouseMove);eventHolder.bind("mouseleave",onMouseLeave)}if(options.grid.clickable)eventHolder.click(onClick);executeHooks(hooks.bindEvents,[eventHolder])}function shutdown(){if(redrawTimeout)clearTimeout(redrawTimeout);eventHolder.unbind("mousemove",onMouseMove);eventHolder.unbind("mouseleave",onMouseLeave);eventHolder.unbind("click",onClick);executeHooks(hooks.shutdown,[eventHolder])}function setTransformationHelpers(axis){function identity(x){return x}var s,m,t=axis.options.transform||identity,it=axis.options.inverseTransform;if(axis.direction=="x"){s=axis.scale=plotWidth/Math.abs(t(axis.max)-t(axis.min));m=Math.min(t(axis.max),t(axis.min))}else{s=axis.scale=plotHeight/Math.abs(t(axis.max)-t(axis.min));s=-s;m=Math.max(t(axis.max),t(axis.min))}if(t==identity)axis.p2c=function(p){return(p-m)*s};else axis.p2c=function(p){return(t(p)-m)*s};if(!it)axis.c2p=function(c){return m+c/s};else axis.c2p=function(c){return it(m+c/s)}}function measureTickLabels(axis){var opts=axis.options,ticks=axis.ticks||[],labelWidth=opts.labelWidth||0,labelHeight=opts.labelHeight||0,maxWidth=labelWidth||(axis.direction=="x"?Math.floor(surface.width/(ticks.length||1)):null),legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=opts.font||"flot-tick-label tickLabel";for(var i=0;i<ticks.length;++i){var t=ticks[i];if(!t.label)continue;var info=surface.getTextInfo(layer,t.label,font,null,maxWidth);labelWidth=Math.max(labelWidth,info.width);labelHeight=Math.max(labelHeight,info.height)}axis.labelWidth=opts.labelWidth||labelWidth;axis.labelHeight=opts.labelHeight||labelHeight}function allocateAxisBoxFirstPhase(axis){var lw=axis.labelWidth,lh=axis.labelHeight,pos=axis.options.position,isXAxis=axis.direction==="x",tickLength=axis.options.tickLength,axisMargin=options.grid.axisMargin,padding=options.grid.labelMargin,innermost=true,outermost=true,first=true,found=false;$.each(isXAxis?xaxes:yaxes,function(i,a){if(a&&(a.show||a.reserveSpace)){if(a===axis){found=true}else if(a.options.position===pos){if(found){outermost=false}else{innermost=false}}if(!found){first=false}}});if(outermost){axisMargin=0}if(tickLength==null){tickLength=first?"full":5}if(!isNaN(+tickLength))padding+=+tickLength;if(isXAxis){lh+=padding;if(pos=="bottom"){plotOffset.bottom+=lh+axisMargin;axis.box={top:surface.height-plotOffset.bottom,height:lh}}else{axis.box={top:plotOffset.top+axisMargin,height:lh};plotOffset.top+=lh+axisMargin}}else{lw+=padding;if(pos=="left"){axis.box={left:plotOffset.left+axisMargin,width:lw};plotOffset.left+=lw+axisMargin}else{plotOffset.right+=lw+axisMargin;axis.box={left:surface.width-plotOffset.right,width:lw}}}axis.position=pos;axis.tickLength=tickLength;axis.box.padding=padding;axis.innermost=innermost}function allocateAxisBoxSecondPhase(axis){if(axis.direction=="x"){axis.box.left=plotOffset.left-axis.labelWidth/2;axis.box.width=surface.width-plotOffset.left-plotOffset.right+axis.labelWidth}else{axis.box.top=plotOffset.top-axis.labelHeight/2;axis.box.height=surface.height-plotOffset.bottom-plotOffset.top+axis.labelHeight}}function adjustLayoutForThingsStickingOut(){var minMargin=options.grid.minBorderMargin,axis,i;if(minMargin==null){minMargin=0;for(i=0;i<series.length;++i)minMargin=Math.max(minMargin,2*(series[i].points.radius+series[i].points.lineWidth/2))}var margins={left:minMargin,right:minMargin,top:minMargin,bottom:minMargin};$.each(allAxes(),function(_,axis){if(axis.reserveSpace&&axis.ticks&&axis.ticks.length){if(axis.direction==="x"){margins.left=Math.max(margins.left,axis.labelWidth/2);margins.right=Math.max(margins.right,axis.labelWidth/2)}else{margins.bottom=Math.max(margins.bottom,axis.labelHeight/2);margins.top=Math.max(margins.top,axis.labelHeight/2)}}});plotOffset.left=Math.ceil(Math.max(margins.left,plotOffset.left));plotOffset.right=Math.ceil(Math.max(margins.right,plotOffset.right));plotOffset.top=Math.ceil(Math.max(margins.top,plotOffset.top));plotOffset.bottom=Math.ceil(Math.max(margins.bottom,plotOffset.bottom))}function setupGrid(){var i,axes=allAxes(),showGrid=options.grid.show;for(var a in plotOffset){var margin=options.grid.margin||0;plotOffset[a]=typeof margin=="number"?margin:margin[a]||0}executeHooks(hooks.processOffset,[plotOffset]);for(var a in plotOffset){if(typeof options.grid.borderWidth=="object"){plotOffset[a]+=showGrid?options.grid.borderWidth[a]:0}else{plotOffset[a]+=showGrid?options.grid.borderWidth:0}}$.each(axes,function(_,axis){var axisOpts=axis.options;axis.show=axisOpts.show==null?axis.used:axisOpts.show;axis.reserveSpace=axisOpts.reserveSpace==null?axis.show:axisOpts.reserveSpace;setRange(axis)});if(showGrid){var allocatedAxes=$.grep(axes,function(axis){return axis.show||axis.reserveSpace});$.each(allocatedAxes,function(_,axis){setupTickGeneration(axis);setTicks(axis);snapRangeToTicks(axis,axis.ticks);measureTickLabels(axis)});for(i=allocatedAxes.length-1;i>=0;--i)allocateAxisBoxFirstPhase(allocatedAxes[i]);adjustLayoutForThingsStickingOut();$.each(allocatedAxes,function(_,axis){allocateAxisBoxSecondPhase(axis)})}plotWidth=surface.width-plotOffset.left-plotOffset.right;plotHeight=surface.height-plotOffset.bottom-plotOffset.top;$.each(axes,function(_,axis){setTransformationHelpers(axis)});if(showGrid){drawAxisLabels()}insertLegend()}function setRange(axis){var opts=axis.options,min=+(opts.min!=null?opts.min:axis.datamin),max=+(opts.max!=null?opts.max:axis.datamax),delta=max-min;if(delta==0){var widen=max==0?1:.01;if(opts.min==null)min-=widen;if(opts.max==null||opts.min!=null)max+=widen}else{var margin=opts.autoscaleMargin;if(margin!=null){if(opts.min==null){min-=delta*margin;if(min<0&&axis.datamin!=null&&axis.datamin>=0)min=0}if(opts.max==null){max+=delta*margin;if(max>0&&axis.datamax!=null&&axis.datamax<=0)max=0}}}axis.min=min;axis.max=max}function setupTickGeneration(axis){var opts=axis.options;var noTicks;if(typeof opts.ticks=="number"&&opts.ticks>0)noTicks=opts.ticks;else noTicks=.3*Math.sqrt(axis.direction=="x"?surface.width:surface.height);var delta=(axis.max-axis.min)/noTicks,dec=-Math.floor(Math.log(delta)/Math.LN10),maxDec=opts.tickDecimals;if(maxDec!=null&&dec>maxDec){dec=maxDec}var magn=Math.pow(10,-dec),norm=delta/magn,size;if(norm<1.5){size=1}else if(norm<3){size=2;if(norm>2.25&&(maxDec==null||dec+1<=maxDec)){size=2.5;++dec}}else if(norm<7.5){size=5}else{size=10}size*=magn;if(opts.minTickSize!=null&&size<opts.minTickSize){size=opts.minTickSize}axis.delta=delta;axis.tickDecimals=Math.max(0,maxDec!=null?maxDec:dec);axis.tickSize=opts.tickSize||size;if(opts.mode=="time"&&!axis.tickGenerator){throw new Error("Time mode requires the flot.time plugin.")}if(!axis.tickGenerator){axis.tickGenerator=function(axis){var ticks=[],start=floorInBase(axis.min,axis.tickSize),i=0,v=Number.NaN,prev;do{prev=v;v=start+i*axis.tickSize;ticks.push(v);++i}while(v<axis.max&&v!=prev);return ticks};axis.tickFormatter=function(value,axis){var factor=axis.tickDecimals?Math.pow(10,axis.tickDecimals):1;var formatted=""+Math.round(value*factor)/factor;if(axis.tickDecimals!=null){var decimal=formatted.indexOf(".");var precision=decimal==-1?0:formatted.length-decimal-1;if(precision<axis.tickDecimals){return(precision?formatted:formatted+".")+(""+factor).substr(1,axis.tickDecimals-precision)}}return formatted}}if($.isFunction(opts.tickFormatter))axis.tickFormatter=function(v,axis){return""+opts.tickFormatter(v,axis)};if(opts.alignTicksWithAxis!=null){var otherAxis=(axis.direction=="x"?xaxes:yaxes)[opts.alignTicksWithAxis-1];if(otherAxis&&otherAxis.used&&otherAxis!=axis){var niceTicks=axis.tickGenerator(axis);if(niceTicks.length>0){if(opts.min==null)axis.min=Math.min(axis.min,niceTicks[0]);if(opts.max==null&&niceTicks.length>1)axis.max=Math.max(axis.max,niceTicks[niceTicks.length-1])}axis.tickGenerator=function(axis){var ticks=[],v,i;for(i=0;i<otherAxis.ticks.length;++i){v=(otherAxis.ticks[i].v-otherAxis.min)/(otherAxis.max-otherAxis.min);v=axis.min+v*(axis.max-axis.min);ticks.push(v)}return ticks};if(!axis.mode&&opts.tickDecimals==null){var extraDec=Math.max(0,-Math.floor(Math.log(axis.delta)/Math.LN10)+1),ts=axis.tickGenerator(axis);if(!(ts.length>1&&/\..*0$/.test((ts[1]-ts[0]).toFixed(extraDec))))axis.tickDecimals=extraDec}}}}function setTicks(axis){var oticks=axis.options.ticks,ticks=[];if(oticks==null||typeof oticks=="number"&&oticks>0)ticks=axis.tickGenerator(axis);else if(oticks){if($.isFunction(oticks))ticks=oticks(axis);else ticks=oticks}var i,v;axis.ticks=[];for(i=0;i<ticks.length;++i){var label=null;var t=ticks[i];if(typeof t=="object"){v=+t[0];if(t.length>1)label=t[1]}else v=+t;if(label==null)label=axis.tickFormatter(v,axis);if(!isNaN(v))axis.ticks.push({v:v,label:label})}}function snapRangeToTicks(axis,ticks){if(axis.options.autoscaleMargin&&ticks.length>0){if(axis.options.min==null)axis.min=Math.min(axis.min,ticks[0].v);if(axis.options.max==null&&ticks.length>1)axis.max=Math.max(axis.max,ticks[ticks.length-1].v)}}function draw(){surface.clear();executeHooks(hooks.drawBackground,[ctx]);var grid=options.grid;if(grid.show&&grid.backgroundColor)drawBackground();if(grid.show&&!grid.aboveData){drawGrid()}for(var i=0;i<series.length;++i){executeHooks(hooks.drawSeries,[ctx,series[i]]);drawSeries(series[i])}executeHooks(hooks.draw,[ctx]);if(grid.show&&grid.aboveData){drawGrid()}surface.render();triggerRedrawOverlay()}function extractRange(ranges,coord){var axis,from,to,key,axes=allAxes();for(var i=0;i<axes.length;++i){axis=axes[i];if(axis.direction==coord){key=coord+axis.n+"axis";if(!ranges[key]&&axis.n==1)key=coord+"axis";if(ranges[key]){from=ranges[key].from;to=ranges[key].to;break}}}if(!ranges[key]){axis=coord=="x"?xaxes[0]:yaxes[0];from=ranges[coord+"1"];to=ranges[coord+"2"]}if(from!=null&&to!=null&&from>to){var tmp=from;from=to;to=tmp}return{from:from,to:to,axis:axis}}function drawBackground(){ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.fillStyle=getColorOrGradient(options.grid.backgroundColor,plotHeight,0,"rgba(255, 255, 255, 0)");ctx.fillRect(0,0,plotWidth,plotHeight);ctx.restore()}function drawGrid(){var i,axes,bw,bc;ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var markings=options.grid.markings;if(markings){if($.isFunction(markings)){axes=plot.getAxes();axes.xmin=axes.xaxis.min;axes.xmax=axes.xaxis.max;axes.ymin=axes.yaxis.min;axes.ymax=axes.yaxis.max;markings=markings(axes)}for(i=0;i<markings.length;++i){var m=markings[i],xrange=extractRange(m,"x"),yrange=extractRange(m,"y");if(xrange.from==null)xrange.from=xrange.axis.min;if(xrange.to==null)xrange.to=xrange.axis.max;
36−-if(yrange.from==null)yrange.from=yrange.axis.min;if(yrange.to==null)yrange.to=yrange.axis.max;if(xrange.to<xrange.axis.min||xrange.from>xrange.axis.max||yrange.to<yrange.axis.min||yrange.from>yrange.axis.max)continue;xrange.from=Math.max(xrange.from,xrange.axis.min);xrange.to=Math.min(xrange.to,xrange.axis.max);yrange.from=Math.max(yrange.from,yrange.axis.min);yrange.to=Math.min(yrange.to,yrange.axis.max);var xequal=xrange.from===xrange.to,yequal=yrange.from===yrange.to;if(xequal&&yequal){continue}xrange.from=Math.floor(xrange.axis.p2c(xrange.from));xrange.to=Math.floor(xrange.axis.p2c(xrange.to));yrange.from=Math.floor(yrange.axis.p2c(yrange.from));yrange.to=Math.floor(yrange.axis.p2c(yrange.to));if(xequal||yequal){var lineWidth=m.lineWidth||options.grid.markingsLineWidth,subPixel=lineWidth%2?.5:0;ctx.beginPath();ctx.strokeStyle=m.color||options.grid.markingsColor;ctx.lineWidth=lineWidth;if(xequal){ctx.moveTo(xrange.to+subPixel,yrange.from);ctx.lineTo(xrange.to+subPixel,yrange.to)}else{ctx.moveTo(xrange.from,yrange.to+subPixel);ctx.lineTo(xrange.to,yrange.to+subPixel)}ctx.stroke()}else{ctx.fillStyle=m.color||options.grid.markingsColor;ctx.fillRect(xrange.from,yrange.to,xrange.to-xrange.from,yrange.from-yrange.to)}}}axes=allAxes();bw=options.grid.borderWidth;for(var j=0;j<axes.length;++j){var axis=axes[j],box=axis.box,t=axis.tickLength,x,y,xoff,yoff;if(!axis.show||axis.ticks.length==0)continue;ctx.lineWidth=1;if(axis.direction=="x"){x=0;if(t=="full")y=axis.position=="top"?0:plotHeight;else y=box.top-plotOffset.top+(axis.position=="top"?box.height:0)}else{y=0;if(t=="full")x=axis.position=="left"?0:plotWidth;else x=box.left-plotOffset.left+(axis.position=="left"?box.width:0)}if(!axis.innermost){ctx.strokeStyle=axis.options.color;ctx.beginPath();xoff=yoff=0;if(axis.direction=="x")xoff=plotWidth+1;else yoff=plotHeight+1;if(ctx.lineWidth==1){if(axis.direction=="x"){y=Math.floor(y)+.5}else{x=Math.floor(x)+.5}}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff);ctx.stroke()}ctx.strokeStyle=axis.options.tickColor;ctx.beginPath();for(i=0;i<axis.ticks.length;++i){var v=axis.ticks[i].v;xoff=yoff=0;if(isNaN(v)||v<axis.min||v>axis.max||t=="full"&&(typeof bw=="object"&&bw[axis.position]>0||bw>0)&&(v==axis.min||v==axis.max))continue;if(axis.direction=="x"){x=axis.p2c(v);yoff=t=="full"?-plotHeight:t;if(axis.position=="top")yoff=-yoff}else{y=axis.p2c(v);xoff=t=="full"?-plotWidth:t;if(axis.position=="left")xoff=-xoff}if(ctx.lineWidth==1){if(axis.direction=="x")x=Math.floor(x)+.5;else y=Math.floor(y)+.5}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff)}ctx.stroke()}if(bw){bc=options.grid.borderColor;if(typeof bw=="object"||typeof bc=="object"){if(typeof bw!=="object"){bw={top:bw,right:bw,bottom:bw,left:bw}}if(typeof bc!=="object"){bc={top:bc,right:bc,bottom:bc,left:bc}}if(bw.top>0){ctx.strokeStyle=bc.top;ctx.lineWidth=bw.top;ctx.beginPath();ctx.moveTo(0-bw.left,0-bw.top/2);ctx.lineTo(plotWidth,0-bw.top/2);ctx.stroke()}if(bw.right>0){ctx.strokeStyle=bc.right;ctx.lineWidth=bw.right;ctx.beginPath();ctx.moveTo(plotWidth+bw.right/2,0-bw.top);ctx.lineTo(plotWidth+bw.right/2,plotHeight);ctx.stroke()}if(bw.bottom>0){ctx.strokeStyle=bc.bottom;ctx.lineWidth=bw.bottom;ctx.beginPath();ctx.moveTo(plotWidth+bw.right,plotHeight+bw.bottom/2);ctx.lineTo(0,plotHeight+bw.bottom/2);ctx.stroke()}if(bw.left>0){ctx.strokeStyle=bc.left;ctx.lineWidth=bw.left;ctx.beginPath();ctx.moveTo(0-bw.left/2,plotHeight+bw.bottom);ctx.lineTo(0-bw.left/2,0);ctx.stroke()}}else{ctx.lineWidth=bw;ctx.strokeStyle=options.grid.borderColor;ctx.strokeRect(-bw/2,-bw/2,plotWidth+bw,plotHeight+bw)}}ctx.restore()}function drawAxisLabels(){$.each(allAxes(),function(_,axis){var box=axis.box,legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=axis.options.font||"flot-tick-label tickLabel",tick,x,y,halign,valign;surface.removeText(layer);if(!axis.show||axis.ticks.length==0)return;for(var i=0;i<axis.ticks.length;++i){tick=axis.ticks[i];if(!tick.label||tick.v<axis.min||tick.v>axis.max)continue;if(axis.direction=="x"){halign="center";x=plotOffset.left+axis.p2c(tick.v);if(axis.position=="bottom"){y=box.top+box.padding}else{y=box.top+box.height-box.padding;valign="bottom"}}else{valign="middle";y=plotOffset.top+axis.p2c(tick.v);if(axis.position=="left"){x=box.left+box.width-box.padding;halign="right"}else{x=box.left+box.padding}}surface.addText(layer,x,y,tick.label,font,null,null,halign,valign)}})}function drawSeries(series){if(series.lines.show)drawSeriesLines(series);if(series.bars.show)drawSeriesBars(series);if(series.points.show)drawSeriesPoints(series)}function drawSeriesLines(series){function plotLine(datapoints,xoffset,yoffset,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,prevx=null,prevy=null;ctx.beginPath();for(var i=ps;i<points.length;i+=ps){var x1=points[i-ps],y1=points[i-ps+1],x2=points[i],y2=points[i+1];if(x1==null||x2==null)continue;if(y1<=y2&&y1<axisy.min){if(y2<axisy.min)continue;x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min}else if(y2<=y1&&y2<axisy.min){if(y1<axisy.min)continue;x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min}if(y1>=y2&&y1>axisy.max){if(y2>axisy.max)continue;x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max}else if(y2>=y1&&y2>axisy.max){if(y1>axisy.max)continue;x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max}if(x1<=x2&&x1<axisx.min){if(x2<axisx.min)continue;y1=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.min}else if(x2<=x1&&x2<axisx.min){if(x1<axisx.min)continue;y2=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.min}if(x1>=x2&&x1>axisx.max){if(x2>axisx.max)continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max}else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max)continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max}if(x1!=prevx||y1!=prevy)ctx.moveTo(axisx.p2c(x1)+xoffset,axisy.p2c(y1)+yoffset);prevx=x2;prevy=y2;ctx.lineTo(axisx.p2c(x2)+xoffset,axisy.p2c(y2)+yoffset)}ctx.stroke()}function plotLineArea(datapoints,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,bottom=Math.min(Math.max(0,axisy.min),axisy.max),i=0,top,areaOpen=false,ypos=1,segmentStart=0,segmentEnd=0;while(true){if(ps>0&&i>points.length+ps)break;i+=ps;var x1=points[i-ps],y1=points[i-ps+ypos],x2=points[i],y2=points[i+ypos];if(areaOpen){if(ps>0&&x1!=null&&x2==null){segmentEnd=i;ps=-ps;ypos=2;continue}if(ps<0&&i==segmentStart+ps){ctx.fill();areaOpen=false;ps=-ps;ypos=1;i=segmentStart=segmentEnd+ps;continue}}if(x1==null||x2==null)continue;if(x1<=x2&&x1<axisx.min){if(x2<axisx.min)continue;y1=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.min}else if(x2<=x1&&x2<axisx.min){if(x1<axisx.min)continue;y2=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.min}if(x1>=x2&&x1>axisx.max){if(x2>axisx.max)continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max}else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max)continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max}if(!areaOpen){ctx.beginPath();ctx.moveTo(axisx.p2c(x1),axisy.p2c(bottom));areaOpen=true}if(y1>=axisy.max&&y2>=axisy.max){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.max));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.max));continue}else if(y1<=axisy.min&&y2<=axisy.min){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.min));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.min));continue}var x1old=x1,x2old=x2;if(y1<=y2&&y1<axisy.min&&y2>=axisy.min){x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min}else if(y2<=y1&&y2<axisy.min&&y1>=axisy.min){x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min}if(y1>=y2&&y1>axisy.max&&y2<=axisy.max){x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max}else if(y2>=y1&&y2>axisy.max&&y1<=axisy.max){x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max}if(x1!=x1old){ctx.lineTo(axisx.p2c(x1old),axisy.p2c(y1))}ctx.lineTo(axisx.p2c(x1),axisy.p2c(y1));ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));if(x2!=x2old){ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));ctx.lineTo(axisx.p2c(x2old),axisy.p2c(y2))}}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineJoin="round";var lw=series.lines.lineWidth,sw=series.shadowSize;if(lw>0&&sw>0){ctx.lineWidth=sw;ctx.strokeStyle="rgba(0,0,0,0.1)";var angle=Math.PI/18;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/2),Math.cos(angle)*(lw/2+sw/2),series.xaxis,series.yaxis);ctx.lineWidth=sw/2;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/4),Math.cos(angle)*(lw/2+sw/4),series.xaxis,series.yaxis)}ctx.lineWidth=lw;ctx.strokeStyle=series.color;var fillStyle=getFillStyle(series.lines,series.color,0,plotHeight);if(fillStyle){ctx.fillStyle=fillStyle;plotLineArea(series.datapoints,series.xaxis,series.yaxis)}if(lw>0)plotLine(series.datapoints,0,0,series.xaxis,series.yaxis);ctx.restore()}function drawSeriesPoints(series){function plotPoints(datapoints,radius,fillStyle,offset,shadow,axisx,axisy,symbol){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i<points.length;i+=ps){var x=points[i],y=points[i+1];if(x==null||x<axisx.min||x>axisx.max||y<axisy.min||y>axisy.max)continue;ctx.beginPath();x=axisx.p2c(x);y=axisy.p2c(y)+offset;if(symbol=="circle")ctx.arc(x,y,radius,0,shadow?Math.PI:Math.PI*2,false);else symbol(ctx,x,y,radius,shadow);ctx.closePath();if(fillStyle){ctx.fillStyle=fillStyle;ctx.fill()}ctx.stroke()}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var lw=series.points.lineWidth,sw=series.shadowSize,radius=series.points.radius,symbol=series.points.symbol;if(lw==0)lw=1e-4;if(lw>0&&sw>0){var w=sw/2;ctx.lineWidth=w;ctx.strokeStyle="rgba(0,0,0,0.1)";plotPoints(series.datapoints,radius,null,w+w/2,true,series.xaxis,series.yaxis,symbol);ctx.strokeStyle="rgba(0,0,0,0.2)";plotPoints(series.datapoints,radius,null,w/2,true,series.xaxis,series.yaxis,symbol)}ctx.lineWidth=lw;ctx.strokeStyle=series.color;plotPoints(series.datapoints,radius,getFillStyle(series.points,series.color),0,false,series.xaxis,series.yaxis,symbol);ctx.restore()}function drawBar(x,y,b,barLeft,barRight,fillStyleCallback,axisx,axisy,c,horizontal,lineWidth){var left,right,bottom,top,drawLeft,drawRight,drawTop,drawBottom,tmp;if(horizontal){drawBottom=drawRight=drawTop=true;drawLeft=false;left=b;right=x;top=y+barLeft;bottom=y+barRight;if(right<left){tmp=right;right=left;left=tmp;drawLeft=true;drawRight=false}}else{drawLeft=drawRight=drawTop=true;drawBottom=false;left=x+barLeft;right=x+barRight;bottom=b;top=y;if(top<bottom){tmp=top;top=bottom;bottom=tmp;drawBottom=true;drawTop=false}}if(right<axisx.min||left>axisx.max||top<axisy.min||bottom>axisy.max)return;if(left<axisx.min){left=axisx.min;drawLeft=false}if(right>axisx.max){right=axisx.max;drawRight=false}if(bottom<axisy.min){bottom=axisy.min;drawBottom=false}if(top>axisy.max){top=axisy.max;drawTop=false}left=axisx.p2c(left);bottom=axisy.p2c(bottom);right=axisx.p2c(right);top=axisy.p2c(top);if(fillStyleCallback){c.fillStyle=fillStyleCallback(bottom,top);c.fillRect(left,top,right-left,bottom-top)}if(lineWidth>0&&(drawLeft||drawRight||drawTop||drawBottom)){c.beginPath();c.moveTo(left,bottom);if(drawLeft)c.lineTo(left,top);else c.moveTo(left,top);if(drawTop)c.lineTo(right,top);else c.moveTo(right,top);if(drawRight)c.lineTo(right,bottom);else c.moveTo(right,bottom);if(drawBottom)c.lineTo(left,bottom);else c.moveTo(left,bottom);c.stroke()}}function drawSeriesBars(series){function plotBars(datapoints,barLeft,barRight,fillStyleCallback,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i<points.length;i+=ps){if(points[i]==null)continue;drawBar(points[i],points[i+1],points[i+2],barLeft,barRight,fillStyleCallback,axisx,axisy,ctx,series.bars.horizontal,series.bars.lineWidth)}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineWidth=series.bars.lineWidth;ctx.strokeStyle=series.color;var barLeft;switch(series.bars.align){case"left":barLeft=0;break;case"right":barLeft=-series.bars.barWidth;break;default:barLeft=-series.bars.barWidth/2}var fillStyleCallback=series.bars.fill?function(bottom,top){return getFillStyle(series.bars,series.color,bottom,top)}:null;plotBars(series.datapoints,barLeft,barLeft+series.bars.barWidth,fillStyleCallback,series.xaxis,series.yaxis);ctx.restore()}function getFillStyle(filloptions,seriesColor,bottom,top){var fill=filloptions.fill;if(!fill)return null;if(filloptions.fillColor)return getColorOrGradient(filloptions.fillColor,bottom,top,seriesColor);var c=$.color.parse(seriesColor);c.a=typeof fill=="number"?fill:.4;c.normalize();return c.toString()}function insertLegend(){if(options.legend.container!=null){$(options.legend.container).html("")}else{placeholder.find(".legend").remove()}if(!options.legend.show){return}var fragments=[],entries=[],rowStarted=false,lf=options.legend.labelFormatter,s,label;for(var i=0;i<series.length;++i){s=series[i];if(s.label){label=lf?lf(s.label,s):s.label;if(label){entries.push({label:label,color:s.color})}}}if(options.legend.sorted){if($.isFunction(options.legend.sorted)){entries.sort(options.legend.sorted)}else if(options.legend.sorted=="reverse"){entries.reverse()}else{var ascending=options.legend.sorted!="descending";entries.sort(function(a,b){return a.label==b.label?0:a.label<b.label!=ascending?1:-1})}}for(var i=0;i<entries.length;++i){var entry=entries[i];if(i%options.legend.noColumns==0){if(rowStarted)fragments.push("</tr>");fragments.push("<tr>");rowStarted=true}fragments.push('<td class="legendColorBox"><div style="border:1px solid '+options.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+entry.color+';overflow:hidden"></div></div></td>'+'<td class="legendLabel">'+entry.label+"</td>")}if(rowStarted)fragments.push("</tr>");if(fragments.length==0)return;var table='<table style="font-size:smaller;color:'+options.grid.color+'">'+fragments.join("")+"</table>";if(options.legend.container!=null)$(options.legend.container).html(table);else{var pos="",p=options.legend.position,m=options.legend.margin;if(m[0]==null)m=[m,m];if(p.charAt(0)=="n")pos+="top:"+(m[1]+plotOffset.top)+"px;";else if(p.charAt(0)=="s")pos+="bottom:"+(m[1]+plotOffset.bottom)+"px;";if(p.charAt(1)=="e")pos+="right:"+(m[0]+plotOffset.right)+"px;";else if(p.charAt(1)=="w")pos+="left:"+(m[0]+plotOffset.left)+"px;";var legend=$('<div class="legend">'+table.replace('style="','style="position:absolute;'+pos+";")+"</div>").appendTo(placeholder);if(options.legend.backgroundOpacity!=0){var c=options.legend.backgroundColor;if(c==null){c=options.grid.backgroundColor;if(c&&typeof c=="string")c=$.color.parse(c);else c=$.color.extract(legend,"background-color");c.a=1;c=c.toString()}var div=legend.children();$('<div style="position:absolute;width:'+div.width()+"px;height:"+div.height()+"px;"+pos+"background-color:"+c+';"> </div>').prependTo(legend).css("opacity",options.legend.backgroundOpacity)}}}var highlights=[],redrawTimeout=null;function findNearbyItem(mouseX,mouseY,seriesFilter){var maxDistance=options.grid.mouseActiveRadius,smallestDistance=maxDistance*maxDistance+1,item=null,foundPoint=false,i,j,ps;for(i=series.length-1;i>=0;--i){if(!seriesFilter(series[i]))continue;var s=series[i],axisx=s.xaxis,axisy=s.yaxis,points=s.datapoints.points,mx=axisx.c2p(mouseX),my=axisy.c2p(mouseY),maxx=maxDistance/axisx.scale,maxy=maxDistance/axisy.scale;ps=s.datapoints.pointsize;if(axisx.options.inverseTransform)maxx=Number.MAX_VALUE;if(axisy.options.inverseTransform)maxy=Number.MAX_VALUE;if(s.lines.show||s.points.show){for(j=0;j<points.length;j+=ps){var x=points[j],y=points[j+1];if(x==null)continue;if(x-mx>maxx||x-mx<-maxx||y-my>maxy||y-my<-maxy)continue;var dx=Math.abs(axisx.p2c(x)-mouseX),dy=Math.abs(axisy.p2c(y)-mouseY),dist=dx*dx+dy*dy;if(dist<smallestDistance){smallestDistance=dist;item=[i,j/ps]}}}if(s.bars.show&&!item){var barLeft,barRight;switch(s.bars.align){case"left":barLeft=0;break;case"right":barLeft=-s.bars.barWidth;break;default:barLeft=-s.bars.barWidth/2}barRight=barLeft+s.bars.barWidth;for(j=0;j<points.length;j+=ps){var x=points[j],y=points[j+1],b=points[j+2];if(x==null)continue;if(series[i].bars.horizontal?mx<=Math.max(b,x)&&mx>=Math.min(b,x)&&my>=y+barLeft&&my<=y+barRight:mx>=x+barLeft&&mx<=x+barRight&&my>=Math.min(b,y)&&my<=Math.max(b,y))item=[i,j/ps]}}}if(item){i=item[0];j=item[1];ps=series[i].datapoints.pointsize;return{datapoint:series[i].datapoints.points.slice(j*ps,(j+1)*ps),dataIndex:j,series:series[i],seriesIndex:i}}return null}function onMouseMove(e){if(options.grid.hoverable)triggerClickHoverEvent("plothover",e,function(s){return s["hoverable"]!=false})}function onMouseLeave(e){if(options.grid.hoverable)triggerClickHoverEvent("plothover",e,function(s){return false})}function onClick(e){triggerClickHoverEvent("plotclick",e,function(s){return s["clickable"]!=false})}function triggerClickHoverEvent(eventname,event,seriesFilter){var offset=eventHolder.offset(),canvasX=event.pageX-offset.left-plotOffset.left,canvasY=event.pageY-offset.top-plotOffset.top,pos=canvasToAxisCoords({left:canvasX,top:canvasY});pos.pageX=event.pageX;pos.pageY=event.pageY;var item=findNearbyItem(canvasX,canvasY,seriesFilter);if(item){item.pageX=parseInt(item.series.xaxis.p2c(item.datapoint[0])+offset.left+plotOffset.left,10);item.pageY=parseInt(item.series.yaxis.p2c(item.datapoint[1])+offset.top+plotOffset.top,10)}if(options.grid.autoHighlight){for(var i=0;i<highlights.length;++i){var h=highlights[i];if(h.auto==eventname&&!(item&&h.series==item.series&&h.point[0]==item.datapoint[0]&&h.point[1]==item.datapoint[1]))unhighlight(h.series,h.point)}if(item)highlight(item.series,item.datapoint,eventname)}placeholder.trigger(eventname,[pos,item])}function triggerRedrawOverlay(){var t=options.interaction.redrawOverlayInterval;if(t==-1){drawOverlay();return}if(!redrawTimeout)redrawTimeout=setTimeout(drawOverlay,t)}function drawOverlay(){redrawTimeout=null;octx.save();overlay.clear();octx.translate(plotOffset.left,plotOffset.top);var i,hi;for(i=0;i<highlights.length;++i){hi=highlights[i];if(hi.series.bars.show)drawBarHighlight(hi.series,hi.point);else drawPointHighlight(hi.series,hi.point)}octx.restore();executeHooks(hooks.drawOverlay,[octx])}function highlight(s,point,auto){if(typeof s=="number")s=series[s];if(typeof point=="number"){var ps=s.datapoints.pointsize;point=s.datapoints.points.slice(ps*point,ps*(point+1))}var i=indexOfHighlight(s,point);if(i==-1){highlights.push({series:s,point:point,auto:auto});triggerRedrawOverlay()}else if(!auto)highlights[i].auto=false}function unhighlight(s,point){if(s==null&&point==null){highlights=[];triggerRedrawOverlay();return}if(typeof s=="number")s=series[s];if(typeof point=="number"){var ps=s.datapoints.pointsize;point=s.datapoints.points.slice(ps*point,ps*(point+1))}var i=indexOfHighlight(s,point);if(i!=-1){highlights.splice(i,1);triggerRedrawOverlay()}}function indexOfHighlight(s,p){for(var i=0;i<highlights.length;++i){var h=highlights[i];if(h.series==s&&h.point[0]==p[0]&&h.point[1]==p[1])return i}return-1}function drawPointHighlight(series,point){var x=point[0],y=point[1],axisx=series.xaxis,axisy=series.yaxis,highlightColor=typeof series.highlightColor==="string"?series.highlightColor:$.color.parse(series.color).scale("a",.5).toString();if(x<axisx.min||x>axisx.max||y<axisy.min||y>axisy.max)return;var pointRadius=series.points.radius+series.points.lineWidth/2;octx.lineWidth=pointRadius;octx.strokeStyle=highlightColor;var radius=1.5*pointRadius;x=axisx.p2c(x);y=axisy.p2c(y);octx.beginPath();if(series.points.symbol=="circle")octx.arc(x,y,radius,0,2*Math.PI,false);else series.points.symbol(octx,x,y,radius,false);octx.closePath();octx.stroke()}function drawBarHighlight(series,point){var highlightColor=typeof series.highlightColor==="string"?series.highlightColor:$.color.parse(series.color).scale("a",.5).toString(),fillStyle=highlightColor,barLeft;switch(series.bars.align){case"left":barLeft=0;break;case"right":barLeft=-series.bars.barWidth;break;default:barLeft=-series.bars.barWidth/2}octx.lineWidth=series.bars.lineWidth;octx.strokeStyle=highlightColor;drawBar(point[0],point[1],point[2]||0,barLeft,barLeft+series.bars.barWidth,function(){return fillStyle},series.xaxis,series.yaxis,octx,series.bars.horizontal,series.bars.lineWidth)}function getColorOrGradient(spec,bottom,top,defaultColor){if(typeof spec=="string")return spec;else{var gradient=ctx.createLinearGradient(0,top,0,bottom);for(var i=0,l=spec.colors.length;i<l;++i){var c=spec.colors[i];if(typeof c!="string"){var co=$.color.parse(defaultColor);if(c.brightness!=null)co=co.scale("rgb",c.brightness);if(c.opacity!=null)co.a*=c.opacity;c=co.toString()}gradient.addColorStop(i/(l-1),c)}return gradient}}}$.plot=function(placeholder,data,options){var plot=new Plot($(placeholder),data,options,$.plot.plugins);return plot};$.plot.version="0.8.3";$.plot.plugins=[];$.fn.plot=function(data,options){return this.each(function(){$.plot(this,data,options)})};function floorInBase(n,base){return base*Math.floor(n/base)}})(jQuery);
37−- </script>
38−- <script language="javascript" type="text/javascript">
39−- (function ($) {
40−- $.zip = function(a,b) {
41−- var x = Math.min(a.length,b.length);
42−- var c = new Array(x);
43−- for (var i = 0; i < x; i++)
44−- c[i] = [a[i],b[i]];
45−- return c;
46−- };
47−-
48−- $.mean = function(ary) {
49−- var m = 0, i = 0;
50−-
51−- while (i < ary.length) {
52−- var j = i++;
53−- m += (ary[j] - m) / i;
54−- }
55−-
56−- return m;
57−- };
58−-
59−- $.timeUnits = function(secs) {
60−- if (secs < 0) return $.timeUnits(-secs);
61−- else if (secs >= 1e9) return [1e-9, "Gs"];
62−- else if (secs >= 1e6) return [1e-6, "Ms"];
63−- else if (secs >= 1) return [1, "s"];
64−- else if (secs >= 1e-3) return [1e3, "ms"];
65−- else if (secs >= 1e-6) return [1e6, "\u03bcs"];
66−- else if (secs >= 1e-9) return [1e9, "ns"];
67−- else if (secs >= 1e-12) return [1e12, "ps"];
68−- return [1, "s"];
69−- };
70−-
71−- $.scaleTimes = function(ary) {
72−- var s = $.timeUnits($.mean(ary));
73−- return [$.scaleBy(s[0], ary), s[0]];
74−- };
75−-
76−- $.prepareTime = function(secs) {
77−- var units = $.timeUnits(secs);
78−- var scaled = secs * units[0];
79−- var s = scaled.toPrecision(3);
80−- var t = scaled.toString();
81−- return [t.length < s.length ? t : s, units[1]];
82−- };
83−-
84−- $.scaleBy = function(x, ary) {
85−- var nary = new Array(ary.length);
86−- for (var i = 0; i < ary.length; i++)
87−- nary[i] = ary[i] * x;
88−- return nary;
89−- };
90−-
91−- $.renderTime = function(secs) {
92−- var x = $.prepareTime(secs);
93−- return x[0] + ' ' + x[1];
94−- };
95−-
96−- $.unitFormatter = function(scale) {
97−- var labelname;
98−- return function(secs,axis) {
99−- var x = $.prepareTime(secs / scale);
100−- if (labelname === x[1])
101−- return x[0];
102−- else {
103−- labelname = x[1];
104−- return x[0] + ' ' + x[1];
105−- }
106−- };
107−- };
108−-
109−- $.addTooltip = function(name, renderText) {
110−- function showTooltip(x, y, contents) {
111−- $('<div id="tooltip">' + contents + '</div>').css( {
112−- position: 'absolute',
113−- display: 'none',
114−- top: y + 5,
115−- left: x + 5,
116−- border: '1px solid #fdd',
117−- padding: '2px',
118−- 'background-color': '#fee',
119−- opacity: 0.80
120−- }).appendTo("body").fadeIn(200);
121−- };
122−- var pp = null;
123−- $(name).bind("plothover", function (event, pos, item) {
124−- $("#x").text(pos.x.toFixed(2));
125−- $("#y").text(pos.y.toFixed(2));
126−-
127−- if (item) {
128−- if (pp != item.dataIndex) {
129−- pp = item.dataIndex;
130−-
131−- $("#tooltip").remove();
132−- var x = item.datapoint[0],
133−- y = item.datapoint[1];
134−-
135−- showTooltip(item.pageX, item.pageY, renderText(x,y));
136−- }
137−- }
138−- else {
139−- $("#tooltip").remove();
140−- pp = null;
141−- }
142−- });
143−- };
144−-})(jQuery);
145−-
146−- </script>
147−- <style type="text/css">
148−-html, body {
149−- height: 100%;
150−- margin: 0;
151−-}
152−-
153−-#wrap {
154−- min-height: 100%;
155−-}
156−-
157−-#main {
158−- overflow: auto;
159−- padding-bottom: 180px; /* must be same height as the footer */
160−-}
161−-
162−-#footer {
163−- position: relative;
164−- margin-top: -180px; /* negative value of footer height */
165−- height: 180px;
166−- clear: both;
167−- background: #888;
168−- margin: 40px 0 0;
169−- color: white;
170−- font-size: larger;
171−- font-weight: 300;
172−-}
173−-
174−-body:before {
175−- /* Opera fix */
176−- content: "";
177−- height: 100%;
178−- float: left;
179−- width: 0;
180−- margin-top: -32767px;
181−-}
182−-
183−-body {
184−- font: 14px Helvetica Neue;
185−- text-rendering: optimizeLegibility;
186−- margin-top: 1em;
187−-}
188−-
189−-a:link {
190−- color: steelblue;
191−- text-decoration: none;
192−-}
193−-
194−-a:visited {
195−- color: #4a743b;
196−- text-decoration: none;
197−-}
198−-
199−-#footer a {
200−- color: white;
201−- text-decoration: underline;
202−-}
203−-
204−-.hover {
205−- color: steelblue;
206−- text-decoration: none;
207−-}
208−-
209−-.body {
210−- width: 960px;
211−- margin: auto;
212−-}
213−-
214−-.footfirst {
215−- position: relative;
216−- top: 30px;
217−-}
218−-
219−-th {
220−- font-weight: 500;
221−- opacity: 0.8;
222−-}
223−-
224−-th.cibound {
225−- opacity: 0.4;
226−-}
227−-
228−-.confinterval {
229−- opacity: 0.5;
230−-}
231−-
232−-h1 {
233−- font-size: 36px;
234−- font-weight: 300;
235−- margin-bottom: .3em;
236−-}
237−-
238−-h2 {
239−- font-size: 30px;
240−- font-weight: 300;
241−- margin-bottom: .3em;
242−-}
243−-
244−-.meanlegend {
245−- color: #404040;
246−- background-color: #ffffff;
247−- opacity: 0.6;
248−- font-size: smaller;
249−-}
250−-
251−- </style>
252−- <!--[if !IE 7]>
253−- <style type="text/css">
254−- #wrap {display:table;height:100%}
255−- </style>
256−- <![endif]-->
257−- </head>
258−- <body>
259−- <div id="wrap">
260−- <div id="main" class="body">
261−- <h1>criterion performance measurements</h1>
262−-
263−-<h2>overview</h2>
264−-
265−-<p><a href="#grokularation">want to understand this report?</a></p>
266−-
267−-<div id="overview" class="ovchart" style="width:900px;height:100px;"></div>
268−-
269−-<h2><a name="b0">fib/1</a></h2>
270−- <table width="100%">
271−- <tbody>
272−- <tr>
273−- <td><div id="kde0" class="kdechart"
274−- style="width:450px;height:278px;"></div></td>
275−- <td><div id="time0" class="timechart"
276−- style="width:450px;height:278px;"></div></td>
277−-<!--
278−- <td><div id="cycle0" class="cyclechart"
279−- style="width:300px;height:278px;"></div></td>
280−--->
281−- </tr>
282−- </tbody>
283−- </table>
284−-
285−- <table>
286−- <thead class="analysis">
287−- <th></th>
288−- <th class="cibound"
289−- title="0.95 confidence level">lower bound</th>
290−- <th>estimate</th>
291−- <th class="cibound"
292−- title="0.95 confidence level">upper bound</th>
293−- </thead>
294−- <tbody>
295−- <tr>
296−- <td>OLS regression</td>
297−- <td><span class="confinterval olstimelb0">xxx</span></td>
298−- <td><span class="olstimept0">xxx</span></td>
299−- <td><span class="confinterval olstimeub0">xxx</span></td>
300−- </tr>
301−- <tr>
302−- <td>R&#xb2; goodness-of-fit</td>
303−- <td><span class="confinterval olsr2lb0">xxx</span></td>
304−- <td><span class="olsr2pt0">xxx</span></td>
305−- <td><span class="confinterval olsr2ub0">xxx</span></td>
306−- </tr>
307−- <tr>
308−- <td>Mean execution time</td>
309−- <td><span class="confinterval citime">2.31459993168433e-8</span></td>
310−- <td><span class="time">2.374225969306158e-8</span></td>
311−- <td><span class="confinterval citime">2.4336041431094957e-8</span></td>
312−- </tr>
313−- <tr>
314−- <td>Standard deviation</td>
315−- <td><span class="confinterval citime">1.7147402747620926e-9</span></td>
316−- <td><span class="time">1.984234308811127e-9</span></td>
317−- <td><span class="confinterval citime">2.3435359738948246e-9</span></td>
318−- </tr>
319−- </tbody>
320−- </table>
321−-
322−- <span class="outliers">
323−- <p>Outlying measurements have severe
324−- (<span class="percent">0.8827515417826841</span>%)
325−- effect on estimated standard deviation.</p>
326−- </span>
327−-<h2><a name="b1">fib/5</a></h2>
328−- <table width="100%">
329−- <tbody>
330−- <tr>
331−- <td><div id="kde1" class="kdechart"
332−- style="width:450px;height:278px;"></div></td>
333−- <td><div id="time1" class="timechart"
334−- style="width:450px;height:278px;"></div></td>
335−-<!--
336−- <td><div id="cycle1" class="cyclechart"
337−- style="width:300px;height:278px;"></div></td>
338−--->
339−- </tr>
340−- </tbody>
341−- </table>
342−-
343−- <table>
344−- <thead class="analysis">
345−- <th></th>
346−- <th class="cibound"
347−- title="0.95 confidence level">lower bound</th>
348−- <th>estimate</th>
349−- <th class="cibound"
350−- title="0.95 confidence level">upper bound</th>
351−- </thead>
352−- <tbody>
353−- <tr>
354−- <td>OLS regression</td>
355−- <td><span class="confinterval olstimelb1">xxx</span></td>
356−- <td><span class="olstimept1">xxx</span></td>
357−- <td><span class="confinterval olstimeub1">xxx</span></td>
358−- </tr>
359−- <tr>
360−- <td>R&#xb2; goodness-of-fit</td>
361−- <td><span class="confinterval olsr2lb1">xxx</span></td>
362−- <td><span class="olsr2pt1">xxx</span></td>
363−- <td><span class="confinterval olsr2ub1">xxx</span></td>
364−- </tr>
365−- <tr>
366−- <td>Mean execution time</td>
367−- <td><span class="confinterval citime">3.640686812141915e-7</span></td>
368−- <td><span class="time">3.7647973827317373e-7</span></td>
369−- <td><span class="confinterval citime">3.8862828356384757e-7</span></td>
370−- </tr>
371−- <tr>
372−- <td>Standard deviation</td>
373−- <td><span class="confinterval citime">3.5904833037515274e-8</span></td>
374−- <td><span class="time">4.150785932735141e-8</span></td>
375−- <td><span class="confinterval citime">4.81505001531474e-8</span></td>
376−- </tr>
377−- </tbody>
378−- </table>
379−-
380−- <span class="outliers">
381−- <p>Outlying measurements have severe
382−- (<span class="percent">0.917699613099007</span>%)
383−- effect on estimated standard deviation.</p>
384−- </span>
385−-<h2><a name="b2">fib/9</a></h2>
386−- <table width="100%">
387−- <tbody>
388−- <tr>
389−- <td><div id="kde2" class="kdechart"
390−- style="width:450px;height:278px;"></div></td>
391−- <td><div id="time2" class="timechart"
392−- style="width:450px;height:278px;"></div></td>
393−-<!--
394−- <td><div id="cycle2" class="cyclechart"
395−- style="width:300px;height:278px;"></div></td>
396−--->
397−- </tr>
398−- </tbody>
399−- </table>
400−-
401−- <table>
402−- <thead class="analysis">
403−- <th></th>
404−- <th class="cibound"
405−- title="0.95 confidence level">lower bound</th>
406−- <th>estimate</th>
407−- <th class="cibound"
408−- title="0.95 confidence level">upper bound</th>
409−- </thead>
410−- <tbody>
411−- <tr>
412−- <td>OLS regression</td>
413−- <td><span class="confinterval olstimelb2">xxx</span></td>
414−- <td><span class="olstimept2">xxx</span></td>
415−- <td><span class="confinterval olstimeub2">xxx</span></td>
416−- </tr>
417−- <tr>
418−- <td>R&#xb2; goodness-of-fit</td>
419−- <td><span class="confinterval olsr2lb2">xxx</span></td>
420−- <td><span class="olsr2pt2">xxx</span></td>
421−- <td><span class="confinterval olsr2ub2">xxx</span></td>
422−- </tr>
423−- <tr>
424−- <td>Mean execution time</td>
425−- <td><span class="confinterval citime">2.5489390737084626e-6</span></td>
426−- <td><span class="time">2.614524699113428e-6</span></td>
427−- <td><span class="confinterval citime">2.700766045605913e-6</span></td>
428−- </tr>
429−- <tr>
430−- <td>Standard deviation</td>
431−- <td><span class="confinterval citime">2.0893167057513842e-7</span></td>
432−- <td><span class="time">2.4922772413717383e-7</span></td>
433−- <td><span class="confinterval citime">3.0480780278156827e-7</span></td>
434−- </tr>
435−- </tbody>
436−- </table>
437−-
438−- <span class="outliers">
439−- <p>Outlying measurements have severe
440−- (<span class="percent">0.86814310186276</span>%)
441−- effect on estimated standard deviation.</p>
442−- </span>
443−-<h2><a name="b3">fib/11</a></h2>
444−- <table width="100%">
445−- <tbody>
446−- <tr>
447−- <td><div id="kde3" class="kdechart"
448−- style="width:450px;height:278px;"></div></td>
449−- <td><div id="time3" class="timechart"
450−- style="width:450px;height:278px;"></div></td>
451−-<!--
452−- <td><div id="cycle3" class="cyclechart"
453−- style="width:300px;height:278px;"></div></td>
454−--->
455−- </tr>
456−- </tbody>
457−- </table>
458−-
459−- <table>
460−- <thead class="analysis">
461−- <th></th>
462−- <th class="cibound"
463−- title="0.95 confidence level">lower bound</th>
464−- <th>estimate</th>
465−- <th class="cibound"
466−- title="0.95 confidence level">upper bound</th>
467−- </thead>
468−- <tbody>
469−- <tr>
470−- <td>OLS regression</td>
471−- <td><span class="confinterval olstimelb3">xxx</span></td>
472−- <td><span class="olstimept3">xxx</span></td>
473−- <td><span class="confinterval olstimeub3">xxx</span></td>
474−- </tr>
475−- <tr>
476−- <td>R&#xb2; goodness-of-fit</td>
477−- <td><span class="confinterval olsr2lb3">xxx</span></td>
478−- <td><span class="olsr2pt3">xxx</span></td>
479−- <td><span class="confinterval olsr2ub3">xxx</span></td>
480−- </tr>
481−- <tr>
482−- <td>Mean execution time</td>
483−- <td><span class="confinterval citime">6.347714383730146e-6</span></td>
484−- <td><span class="time">6.496202868182492e-6</span></td>
485−- <td><span class="confinterval citime">6.668634037917654e-6</span></td>
486−- </tr>
487−- <tr>
488−- <td>Standard deviation</td>
489−- <td><span class="confinterval citime">4.0420784296930194e-7</span></td>
490−- <td><span class="time">4.919233380857326e-7</span></td>
491−- <td><span class="confinterval citime">6.202125623223447e-7</span></td>
492−- </tr>
493−- </tbody>
494−- </table>
495−-
496−- <span class="outliers">
497−- <p>Outlying measurements have severe
498−- (<span class="percent">0.7876656352417168</span>%)
499−- effect on estimated standard deviation.</p>
500−- </span>
501−-
502−- <h2><a name="grokularation">understanding this report</a></h2>
503−-
504−- <p>In this report, each function benchmarked by criterion is assigned
505−- a section of its own. The charts in each section are active; if
506−- you hover your mouse over data points and annotations, you will see
507−- more details.</p>
508−-
509−- <ul>
510−- <li>The chart on the left is a
511−- <a href="http://en.wikipedia.org/wiki/Kernel_density_estimation">kernel
512−- density estimate</a> (also known as a KDE) of time
513−- measurements. This graphs the probability of any given time
514−- measurement occurring. A spike indicates that a measurement of a
515−- particular time occurred; its height indicates how often that
516−- measurement was repeated.</li>
517−-
518−- <li>The chart on the right is the raw data from which the kernel
519−- density estimate is built. The <i>x</i> axis indicates the
520−- number of loop iterations, while the <i>y</i> axis shows measured
521−- execution time for the given number of loop iterations. The
522−- line behind the values is the linear regression prediction of
523−- execution time for a given number of iterations. Ideally, all
524−- measurements will be on (or very near) this line.</li>
525−- </ul>
526−-
527−- <p>Under the charts is a small table.
528−- The first two rows are the results of a linear regression run
529−- on the measurements displayed in the right-hand chart.</p>
530−-
531−- <ul>
532−- <li><i>OLS regression</i> indicates the
533−- time estimated for a single loop iteration using an ordinary
534−- least-squares regression model. This number is more accurate
535−- than the <i>mean</i> estimate below it, as it more effectively
536−- eliminates measurement overhead and other constant factors.</li>
537−- <li><i>R&#xb2; goodness-of-fit</i> is a measure of how
538−- accurately the linear regression model fits the observed
539−- measurements. If the measurements are not too noisy, R&#xb2;
540−- should lie between 0.99 and 1, indicating an excellent fit. If
541−- the number is below 0.99, something is confounding the accuracy
542−- of the linear model.</li>
543−- <li><i>Mean execution time</i> and <i>standard deviation</i> are
544−- statistics calculated from execution time
545−- divided by number of iterations.</li>
546−- </ul>
547−-
548−- <p>We use a statistical technique called
549−- the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a>
550−- to provide confidence intervals on our estimates. The
551−- bootstrap-derived upper and lower bounds on estimates let you see
552−- how accurate we believe those estimates to be. (Hover the mouse
553−- over the table headers to see the confidence levels.)</p>
554−-
555−- <p>A noisy benchmarking environment can cause some or many
556−- measurements to fall far from the mean. These outlying
557−- measurements can have a significant inflationary effect on the
558−- estimate of the standard deviation. We calculate and display an
559−- estimate of the extent to which the standard deviation has been
560−- inflated by outliers.</p>
561−-
562−-<script type="text/javascript">
563−-$(function () {
564−- function mangulate(rpt) {
565−- var measured = function(key) {
566−- var idx = rpt.reportKeys.indexOf(key);
567−- return rpt.reportMeasured.map(function(r) { return r[idx]; });
568−- };
569−- var number = rpt.reportNumber;
570−- var name = rpt.reportName;
571−- var mean = rpt.reportAnalysis.anMean.estPoint;
572−- var iters = measured("iters");
573−- var times = measured("time");
574−- var kdetimes = rpt.reportKDEs[0].kdeValues;
575−- var kdepdf = rpt.reportKDEs[0].kdePDF;
576−-
577−- var meanSecs = mean;
578−- var units = $.timeUnits(mean);
579−- var rgrs = rpt.reportAnalysis.anRegress[0];
580−- var scale = units[0];
581−- var olsTime = rgrs.regCoeffs.iters;
582−- $(".olstimept" + number).text(function() {
583−- return $.renderTime(olsTime.estPoint);
584−- });
585−- $(".olstimelb" + number).text(function() {
586−- return $.renderTime(olsTime.estLowerBound);
587−- });
588−- $(".olstimeub" + number).text(function() {
589−- return $.renderTime(olsTime.estUpperBound);
590−- });
591−- $(".olsr2pt" + number).text(function() {
592−- return rgrs.regRSquare.estPoint.toFixed(3);
593−- });
594−- $(".olsr2lb" + number).text(function() {
595−- return rgrs.regRSquare.estLowerBound.toFixed(3);
596−- });
597−- $(".olsr2ub" + number).text(function() {
598−- return rgrs.regRSquare.estUpperBound.toFixed(3);
599−- });
600−- mean *= scale;
601−- kdetimes = $.scaleBy(scale, kdetimes);
602−- var kq = $("#kde" + number);
603−- var k = $.plot(kq,
604−- [{ label: name + " time densities",
605−- data: $.zip(kdetimes, kdepdf),
606−- }],
607−- { xaxis: { tickFormatter: $.unitFormatter(scale) },
608−- yaxis: { ticks: false },
609−- grid: { borderColor: "#777",
610−- hoverable: true, markings: [ { color: '#6fd3fb',
611−- lineWidth: 1.5, xaxis: { from: mean, to: mean } } ] },
612−- });
613−- var o = k.pointOffset({ x: mean, y: 0});
614−- kq.append('<div class="meanlegend" title="' + $.renderTime(meanSecs) +
615−- '" style="position:absolute;left:' + (o.left + 4) +
616−- 'px;bottom:139px;">mean</div>');
617−- $.addTooltip("#kde" + number,
618−- function(secs) { return $.renderTime(secs / scale); });
619−- var timepairs = new Array(times.length);
620−- var lastiter = iters[iters.length-1];
621−- var olspairs = [[0,0], [lastiter, lastiter * scale * olsTime.estPoint]];
622−- for (var i = 0; i < times.length; i++)
623−- timepairs[i] = [iters[i],times[i]*scale];
624−- iterFormatter = function() {
625−- var denom = 0;
626−- return function(iters) {
627−- if (iters == 0)
628−- return '';
629−- if (denom > 0)
630−- return (iters / denom).toFixed();
631−- var power;
632−- if (iters >= 1e9) {
633−- denom = '1e9'; power = '&#x2079;';
634−- }
635−- if (iters >= 1e6) {
636−- denom = '1e6'; power = '&#x2076;';
637−- }
638−- else if (iters >= 1e3) {
639−- denom = '1e3'; power = '&#xb3;';
640−- }
641−- else denom = 1;
642−- if (denom > 1) {
643−- iters = (iters / denom).toFixed();
644−- iters += '&times;10' + power + ' iters';
645−- } else {
646−- iters += ' iters';
647−- }
648−- return iters;
649−- };
650−- };
651−- $.plot($("#time" + number),
652−- [{ label: "regression", data: olspairs,
653−- lines: { show: true } },
654−- { label: name + " times", data: timepairs,
655−- points: { show: true } }],
656−- { grid: { borderColor: "#777", hoverable: true },
657−- xaxis: { tickFormatter: iterFormatter() },
658−- yaxis: { tickFormatter: $.unitFormatter(scale) } });
659−- $.addTooltip("#time" + number,
660−- function(iters,secs) {
661−- return ($.renderTime(secs / scale) + ' / ' +
662−- iters.toLocaleString() + ' iters');
663−- });
664−- if (0) {
665−- var cyclepairs = new Array(cycles.length);
666−- for (var i = 0; i < cycles.length; i++)
667−- cyclepairs[i] = [cycles[i],i];
668−- $.plot($("#cycle" + number),
669−- [{ label: name + " cycles",
670−- data: cyclepairs }],
671−- { points: { show: true },
672−- grid: { borderColor: "#777", hoverable: true },
673−- xaxis: { tickFormatter:
674−- function(cycles,axis) { return cycles + ' cycles'; }},
675−- yaxis: { ticks: false },
676−- });
677−- $.addTooltip("#cycles" + number, function(x,y) { return x + ' cycles'; });
678−- }
679−- };
680−- var reports = [{"reportAnalysis":{"anMean":{"estUpperBound":2.4336041431094957e-8,"estLowerBound":2.31459993168433e-8,"estPoint":2.374225969306158e-8,"estConfidenceLevel":0.95},"anRegress":[{"regRSquare":{"estUpperBound":0.9968607334095598,"estLowerBound":0.9931281346179867,"estPoint":0.9952316835320134,"estConfidenceLevel":0.95},"regResponder":"time","regCoeffs":{"y":{"estUpperBound":-3.425955804843936e-4,"estLowerBound":-7.654756798125064e-4,"estPoint":-5.600471908843124e-4,"estConfidenceLevel":0.95},"iters":{"estUpperBound":2.5046637898223406e-8,"estLowerBound":2.3842309287675006e-8,"estPoint":2.452217275933509e-8,"estConfidenceLevel":0.95}}}],"anStdDev":{"estUpperBound":2.3435359738948246e-9,"estLowerBound":1.7147402747620926e-9,"estPoint":1.984234308811127e-9,"estConfidenceLevel":0.95},"anOutlierVar":{"ovFraction":0.8827515417826841,"ovDesc":"severe","ovEffect":"Severe"},"anOverhead":3.161534180001628e-6},"reportKDEs":[{"kdeValues":[1.989878208361153e-8,1.9968424229205795e-8,2.003806637480006e-8,2.0107708520394325e-8,2.0177350665988587e-8,2.024699281158285e-8,2.0316634957177116e-8,2.038627710277138e-8,2.0455919248365646e-8,2.052556139395991e-8,2.0595203539554173e-8,2.0664845685148438e-8,2.0734487830742702e-8,2.0804129976336967e-8,2.0873772121931232e-8,2.0943414267525497e-8,2.1013056413119762e-8,2.1082698558714023e-8,2.1152340704308288e-8,2.1221982849902553e-8,2.1291624995496818e-8,2.1361267141091083e-8,2.1430909286685348e-8,2.150055143227961e-8,2.1570193577873874e-8,2.163983572346814e-8,2.1709477869062404e-8,2.177912001465667e-8,2.1848762160250934e-8,2.1918404305845195e-8,2.198804645143946e-8,2.2057688597033725e-8,2.212733074262799e-8,2.2196972888222255e-8,2.226661503381652e-8,2.2336257179410785e-8,2.2405899325005046e-8,2.247554147059931e-8,2.2545183616193576e-8,2.261482576178784e-8,2.2684467907382106e-8,2.275411005297637e-8,2.2823752198570635e-8,2.2893394344164897e-8,2.2963036489759162e-8,2.3032678635353427e-8,2.310232078094769e-8,2.3171962926541956e-8,2.3241605072136218e-8,2.3311247217730483e-8,2.3380889363324748e-8,2.3450531508919013e-8,2.3520173654513278e-8,2.3589815800107542e-8,2.3659457945701807e-8,2.372910009129607e-8,2.3798742236890334e-8,2.38683843824846e-8,2.3938026528078863e-8,2.4007668673673128e-8,2.407731081926739e-8,2.4146952964861658e-8,2.421659511045592e-8,2.4286237256050185e-8,2.435587940164445e-8,2.4425521547238714e-8,2.449516369283298e-8,2.456480583842724e-8,2.463444798402151e-8,2.470409012961577e-8,2.4773732275210035e-8,2.48433744208043e-8,2.4913016566398565e-8,2.498265871199283e-8,2.505230085758709e-8,2.5121943003181356e-8,2.519158514877562e-8,2.5261227294369886e-8,2.533086943996415e-8,2.5400511585558416e-8,2.547015373115268e-8,2.5539795876746942e-8,2.5609438022341207e-8,2.5679080167935472e-8,2.5748722313529737e-8,2.5818364459124002e-8,2.5888006604718263e-8,2.595764875031253e-8,2.6027290895906793e-8,2.6096933041501058e-8,2.6166575187095323e-8,2.6236217332689588e-8,2.6305859478283853e-8,2.6375501623878114e-8,2.644514376947238e-8,2.6514785915066644e-8,2.658442806066091e-8,2.6654070206255174e-8,2.672371235184944e-8,2.6793354497443703e-8,2.6862996643037965e-8,2.693263878863223e-8,2.7002280934226495e-8,2.707192307982076e-8,2.7141565225415025e-8,2.7211207371009286e-8,2.7280849516603554e-8,2.7350491662197816e-8,2.742013380779208e-8,2.7489775953386346e-8,2.755941809898061e-8,2.7629060244574875e-8,2.7698702390169137e-8,2.7768344535763405e-8,2.7837986681357667e-8,2.790762882695193e-8,2.7977270972546196e-8,2.8046913118140458e-8,2.8116555263734726e-8,2.8186197409328988e-8,2.8255839554923253e-8,2.8325481700517517e-8,2.8395123846111782e-8,2.8464765991706047e-8,2.853440813730031e-8,2.8604050282894577e-8,2.867369242848884e-8,2.8743334574083103e-8],"kdeType":"time","kdePDF":[1.1395895337002747e8,1.1399586448390599e8,1.1406966699669889e8,1.141803208709782e8,1.143277645338929e8,1.1451191306306463e8,1.1473265577838261e8,1.1498985325011694e8,1.152833337379588e8,1.1561288908069459e8,1.1597827006230259e8,1.1637918128730445e8,1.1681527560615641e8,1.1728614814018439e8,1.1779132996487482e8,1.1833028151996909e8,1.1890238582449803e8,1.1950694158429071e8,1.201431562882586e8,1.2081013939751814e8,1.2150689573782589e8,1.2223231921050385e8,1.2298518693974209e8,1.2376415397459902e8,1.2456774866200176e8,1.2539436880242184e8,1.2624227869264197e8,1.2710960715014195e8,1.2799434660125354e8,1.2889435330055325e8,1.2980734873227204e8,1.3073092222615018e8,1.3166253480058819e8,1.3259952422560526e8,1.3353911127754031e8,1.3447840713714716e8,1.3541442186329383e8,1.3634407385640383e8,1.372642002095804e8,1.381715678314893e8,1.3906288521393478e8,1.3993481470897296e8,1.4078398517559382e8,1.4160700485461792e8,1.4240047433251885e8,1.4316099946035716e8,1.4388520410270315e8,1.4456974260309508e8,1.4521131186685443e8,1.458066629785387e8,1.463526122894414e8,1.468460519298112e8,1.4728395972024703e8,1.476634084764515e8,1.479815747205615e8,1.4823574683005878e8,1.4842333267122668e8,1.4854186677778667e8,1.4858901714627486e8,1.485625917275835e8,1.4846054469862348e8,1.482809825991286e8,1.4802217041616246e8,1.4768253769297192e8,1.4726068472961387e8,1.4675538893053663e8,1.4616561133936232e8,1.4549050338394704e8,1.4472941383586738e8,1.4388189596837926e8,1.4294771487617913e8,1.419268548996135e8,1.408195270759097e8,1.3962617652117708e8,1.383474896298825e8,1.3698440096379948e8,1.3553809969048512e8,1.3401003542258318e8,1.3240192330394386e8,1.3071574818694907e8,1.2895376774760398e8,1.2711851439096606e8,1.2521279580920233e8,1.2323969406786159e8,1.2120256311251064e8,1.1910502460740013e8,1.1695096203983772e8,1.1474451304800186e8,1.1249005995546557e8,1.1019221852217361e8,1.0785582494841896e8,1.0548592119492327e8,1.0308773870783295e8,1.0066668066176452e8,9.822830285641795e7,9.577829342227527e7,9.332245150807737e7,9.086666513679452e7,8.841688842738897e7,8.597911838663742e7,8.355937147851193e7,8.116366017811044e7,7.87979697129248e7,7.646823518650009e7,7.418031926847933e7,7.193999062095061e7,6.975290321426049e7,6.76245766664537e7,6.5560377719679065e7,6.356550294477145e7,6.164496274226723e7,5.9803566684867114e7,5.804591022332826e7,5.637636275545833e7,5.479905703675971e7,5.331787989178828e7,5.19364641678301e7,5.0658181857415326e7,4.9486138303759255e7,4.842316739367089e7,4.74718276359435e7,4.663439901982578e7,4.591288054786622e7,4.530898834016642e7,4.4824154212732054e7,4.44595246409754e7,4.421596003023277e7,4.409403422810118e7]}],"reportKeys":["time","cpuTime","cycles","iters","allocated","numGcs","bytesCopied","mutatorWallSeconds","mutatorCpuSeconds","gcWallSeconds","gcCpuSeconds"],"reportNumber":0,"reportName":"fib/1","reportOutliers":{"highSevere":0,"highMild":0,"lowMild":0,"samplesSeen":41,"lowSevere":0},"reportMeasured":[[7.638998795300722e-6,6.000000000000796e-6,4658,1,null,null,null,null,null,null,null],[2.0030129235237837e-6,2.0000000000002655e-6,3978,2,null,null,null,null,null,null,null],[1.601001713424921e-6,9.999999999992654e-7,3144,3,null,null,null,null,null,null,null],[1.5189871191978455e-6,9.999999999975306e-7,3118,4,null,null,null,null,null,null,null],[1.4929973985999823e-6,9.999999999992654e-7,3084,5,null,null,null,null,null,null,null],[1.447013346478343e-6,2.0000000000002655e-6,3018,6,null,null,null,null,null,null,null],[1.4870020095258951e-6,9.999999999992654e-7,3126,7,null,null,null,null,null,null,null],[1.5980040188878775e-6,1.9999999999985307e-6,3436,8,null,null,null,null,null,null,null],[1.5170080587267876e-6,9.999999999992654e-7,3234,9,null,null,null,null,null,null,null],[1.561013050377369e-6,1.000000000001e-6,3362,10,null,null,null,null,null,null,null],[1.6170088201761246e-6,2.0000000000002655e-6,3464,11,null,null,null,null,null,null,null],[1.6060075722634792e-6,9.999999999992654e-7,3308,12,null,null,null,null,null,null,null],[1.620996044948697e-6,2.999999999999531e-6,3336,13,null,null,null,null,null,null,null],[1.5929981600493193e-6,9.999999999992654e-7,3450,14,null,null,null,null,null,null,null],[1.6530102584511042e-6,2.0000000000002655e-6,3582,15,null,null,null,null,null,null,null],[1.66997779160738e-6,3.0000000000012655e-6,3634,16,null,null,null,null,null,null,null],[1.6599951777607203e-6,1.000000000001e-6,3480,17,null,null,null,null,null,null,null],[1.7060083337128162e-6,1.9999999999985307e-6,3622,18,null,null,null,null,null,null,null],[1.7429993022233248e-6,9.999999999992654e-7,3750,19,null,null,null,null,null,null,null],[1.7330166883766651e-6,2.0000000000002655e-6,3690,20,null,null,null,null,null,null,null],[1.7400016076862812e-6,1.000000000001e-6,3700,21,null,null,null,null,null,null,null],[1.7929996829479933e-6,1.9999999999985307e-6,3744,22,null,null,null,null,null,null,null],[1.8269929569214582e-6,9.999999999975306e-7,3856,23,null,null,null,null,null,null,null],[1.9319995772093534e-6,1.9999999999985307e-6,4000,25,null,null,null,null,null,null,null],[1.8299906514585018e-6,2.0000000000002655e-6,4004,26,null,null,null,null,null,null,null],[2.001994289457798e-6,1.9999999999985307e-6,4084,27,null,null,null,null,null,null,null],[1.9379949662834406e-6,2.0000000000002655e-6,4032,28,null,null,null,null,null,null,null],[1.9339786376804113e-6,2.0000000000002655e-6,4132,30,null,null,null,null,null,null,null],[2.001004759222269e-6,2.0000000000002655e-6,4260,31,null,null,null,null,null,null,null],[1.99698843061924e-6,2.0000000000002655e-6,4264,33,null,null,null,null,null,null,null],[2.0099978428333998e-6,2.0000000000002655e-6,4332,35,null,null,null,null,null,null,null],[2.1180021576583385e-6,2.0000000000002655e-6,4468,36,null,null,null,null,null,null,null],[2.0809820853173733e-6,2.000000000002e-6,4422,38,null,null,null,null,null,null,null],[2.2199819795787334e-6,2.000000000002e-6,4714,40,null,null,null,null,null,null,null],[2.173997927457094e-6,1.9999999999985307e-6,4662,42,null,null,null,null,null,null,null],[2.2099993657320738e-6,1.9999999999985307e-6,4772,44,null,null,null,null,null,null,null],[2.2700114641338587e-6,1.9999999999985307e-6,4926,47,null,null,null,null,null,null,null],[2.3389875423163176e-6,2.000000000002e-6,5104,49,null,null,null,null,null,null,null],[2.3679749574512243e-6,4.000000000000531e-6,5072,52,null,null,null,null,null,null,null],[2.521992428228259e-6,2.999999999999531e-6,5520,54,null,null,null,null,null,null,null],[2.4710025172680616e-6,2.000000000002e-6,5356,57,null,null,null,null,null,null,null],[2.5459739845246077e-6,2.000000000002e-6,5598,60,null,null,null,null,null,null,null],[2.6070047169923782e-6,3.0000000000012655e-6,5578,63,null,null,null,null,null,null,null],[2.7070054784417152e-6,2.999999999999531e-6,5796,66,null,null,null,null,null,null,null],[2.7520000003278255e-6,2.999999999999531e-6,5938,69,null,null,null,null,null,null,null],[2.820015652105212e-6,2.999999999999531e-6,6094,73,null,null,null,null,null,null,null],[2.903980202972889e-6,2.999999999999531e-6,6318,76,null,null,null,null,null,null,null],[3.0809896998107433e-6,3.0000000000012655e-6,6580,80,null,null,null,null,null,null,null],[3.022985765710473e-6,3.0000000000012655e-6,6520,84,null,null,null,null,null,null,null],[3.1730160117149353e-6,2.999999999999531e-6,6874,89,null,null,null,null,null,null,null],[3.281020326539874e-6,2.999999999999531e-6,7098,93,null,null,null,null,null,null,null],[3.390974598005414e-6,4.000000000000531e-6,7286,98,null,null,null,null,null,null,null],[3.4409749787300825e-6,3.999999999998796e-6,7480,103,null,null,null,null,null,null,null],[3.568013198673725e-6,3.0000000000012655e-6,7696,108,null,null,null,null,null,null,null],[3.6860001273453236e-6,4.000000000002266e-6,7956,113,null,null,null,null,null,null,null],[3.816006937995553e-6,4.000000000000531e-6,8276,119,null,null,null,null,null,null,null],[3.908004146069288e-6,4.000000000000531e-6,8570,125,null,null,null,null,null,null,null],[4.076020559296012e-6,3.999999999998796e-6,8784,131,null,null,null,null,null,null,null],[4.16202237829566e-6,4.999999999999796e-6,9164,138,null,null,null,null,null,null,null],[4.309986252337694e-6,4.999999999999796e-6,9398,144,null,null,null,null,null,null,null],[4.4630141928792e-6,4.999999999999796e-6,9746,152,null,null,null,null,null,null,null],[4.6009954530745745e-6,4.000000000000531e-6,10108,159,null,null,null,null,null,null,null],[4.8349902499467134e-6,4.999999999999796e-6,10498,167,null,null,null,null,null,null,null],[4.989997250959277e-6,4.9999999999980616e-6,10970,176,null,null,null,null,null,null,null],[5.174020770937204e-6,4.999999999999796e-6,11270,185,null,null,null,null,null,null,null],[5.331996362656355e-6,6.000000000000796e-6,11654,194,null,null,null,null,null,null,null],[5.553010851144791e-6,6.000000000000796e-6,12124,204,null,null,null,null,null,null,null],[5.785987013950944e-6,5.000000000001531e-6,12610,214,null,null,null,null,null,null,null],[5.962996510788798e-6,5.999999999999062e-6,13048,224,null,null,null,null,null,null,null],[6.223010132089257e-6,5.999999999999062e-6,13574,236,null,null,null,null,null,null,null],[6.432994268834591e-6,5.999999999999062e-6,14166,247,null,null,null,null,null,null,null],[6.759015377610922e-6,7.000000000000062e-6,14820,260,null,null,null,null,null,null,null],[7.066992111504078e-6,6.999999999998327e-6,15352,273,null,null,null,null,null,null,null],[9.720999514684081e-6,9.999999999999593e-6,22118,287,null,null,null,null,null,null,null],[2.340899663977325e-5,2.5000000000000716e-5,52294,301,null,null,null,null,null,null,null],[1.178999082185328e-5,1.1999999999999858e-5,26130,316,null,null,null,null,null,null,null],[1.2989010429009795e-5,1.3000000000000858e-5,28826,332,null,null,null,null,null,null,null],[1.3224984286352992e-5,1.2999999999999123e-5,29304,348,null,null,null,null,null,null,null],[1.3598008081316948e-5,1.2999999999999123e-5,30028,366,null,null,null,null,null,null,null],[1.3850018149241805e-5,1.2999999999999123e-5,30792,384,null,null,null,null,null,null,null],[1.4401011867448688e-5,1.4000000000001858e-5,31864,403,null,null,null,null,null,null,null],[1.6610982129350305e-5,1.6000000000002124e-5,36708,424,null,null,null,null,null,null,null],[1.5012978110462427e-5,1.5000000000001124e-5,33002,445,null,null,null,null,null,null,null],[1.7034995835274458e-5,1.8000000000000654e-5,37708,467,null,null,null,null,null,null,null],[1.7721002222970128e-5,1.8999999999998185e-5,39234,490,null,null,null,null,null,null,null],[1.8552993424236774e-5,1.799999999999892e-5,41084,515,null,null,null,null,null,null,null],[1.917898771353066e-5,1.9999999999999185e-5,42286,541,null,null,null,null,null,null,null],[2.1567975636571646e-5,2.1000000000000185e-5,47586,568,null,null,null,null,null,null,null],[2.230500103905797e-5,2.300000000000045e-5,49198,596,null,null,null,null,null,null,null],[2.272101119160652e-5,2.1999999999997716e-5,50234,626,null,null,null,null,null,null,null],[2.3773027351126075e-5,2.3000000000002185e-5,52362,657,null,null,null,null,null,null,null],[2.4245004169642925e-5,2.2999999999998716e-5,53572,690,null,null,null,null,null,null,null],[7.000000914558768e-5,6.899999999999962e-5,155598,725,null,null,null,null,null,null,null],[1.7465994460508227e-5,1.6999999999999654e-5,38168,761,null,null,null,null,null,null,null],[1.807598164305091e-5,1.800000000000239e-5,39576,799,null,null,null,null,null,null,null],[1.8852995708584785e-5,1.899999999999992e-5,41516,839,null,null,null,null,null,null,null],[1.9677012460306287e-5,2.000000000000092e-5,43246,881,null,null,null,null,null,null,null],[2.064098953269422e-5,2.1000000000000185e-5,45474,925,null,null,null,null,null,null,null],[2.1629995899274945e-5,2.1999999999997716e-5,47668,972,null,null,null,null,null,null,null],[2.2616994101554155e-5,2.199999999999945e-5,49674,1020,null,null,null,null,null,null,null],[2.367299748584628e-5,2.3999999999999716e-5,52114,1071,null,null,null,null,null,null,null],[2.4829001631587744e-5,2.5000000000000716e-5,54638,1125,null,null,null,null,null,null,null],[2.5999004719778895e-5,2.6000000000001716e-5,57144,1181,null,null,null,null,null,null,null],[2.7219997718930244e-5,2.8000000000000247e-5,59942,1240,null,null,null,null,null,null,null],[2.84140114672482e-5,2.9000000000001247e-5,62510,1302,null,null,null,null,null,null,null],[2.97880033031106e-5,3.0000000000000512e-5,65500,1367,null,null,null,null,null,null,null],[3.1288014724850655e-5,3.100000000000325e-5,68730,1436,null,null,null,null,null,null,null],[5.5037991842254996e-5,5.4999999999999494e-5,123386,1507,null,null,null,null,null,null,null],[3.455500700511038e-5,3.399999999999931e-5,75988,1583,null,null,null,null,null,null,null],[3.6003009881824255e-5,3.600000000000131e-5,79164,1662,null,null,null,null,null,null,null],[3.75809904653579e-5,3.7000000000000574e-5,82780,1745,null,null,null,null,null,null,null],[3.95399983972311e-5,4.0000000000000105e-5,87250,1832,null,null,null,null,null,null,null],[4.142100806348026e-5,4.1999999999998636e-5,91228,1924,null,null,null,null,null,null,null],[4.3387000914663076e-5,4.300000000000137e-5,95434,2020,null,null,null,null,null,null,null],[4.5455992221832275e-5,4.5000000000001636e-5,100018,2121,null,null,null,null,null,null,null],[4.7684996388852596e-5,4.800000000000117e-5,104906,2227,null,null,null,null,null,null,null],[6.012499216012657e-5,5.9999999999997555e-5,134302,2339,null,null,null,null,null,null,null],[5.268098902888596e-5,5.299999999999923e-5,115720,2456,null,null,null,null,null,null,null],[5.501997657120228e-5,5.499999999999776e-5,121068,2579,null,null,null,null,null,null,null],[5.776798934675753e-5,5.8000000000002494e-5,127190,2708,null,null,null,null,null,null,null],[6.043800385668874e-5,5.9999999999997555e-5,133086,2843,null,null,null,null,null,null,null],[6.345799192786217e-5,6.399999999999982e-5,139680,2985,null,null,null,null,null,null,null],[7.470298442058265e-5,7.599999999999794e-5,166252,3134,null,null,null,null,null,null,null],[7.000300684012473e-5,7.099999999999988e-5,153946,3291,null,null,null,null,null,null,null],[7.332497625611722e-5,7.300000000000015e-5,161342,3456,null,null,null,null,null,null,null],[7.68770114518702e-5,7.700000000000068e-5,169196,3629,null,null,null,null,null,null,null],[8.789999992586672e-5,8.800000000000127e-5,195306,3810,null,null,null,null,null,null,null],[8.4783008787781e-5,8.500000000000174e-5,186656,4001,null,null,null,null,null,null,null],[9.577898890711367e-5,9.500000000000133e-5,211296,4201,null,null,null,null,null,null,null],[9.035100811161101e-5,8.99999999999998e-5,198964,4411,null,null,null,null,null,null,null],[1.0181200923398137e-4,1.010000000000004e-4,225996,4631,null,null,null,null,null,null,null],[9.956801659427583e-5,1.0000000000000113e-4,219136,4863,null,null,null,null,null,null,null],[1.0437800665386021e-4,1.0399999999999993e-4,229882,5106,null,null,null,null,null,null,null],[1.0967502021230757e-4,1.1000000000000072e-4,241698,5361,null,null,null,null,null,null,null],[1.2155799777247012e-4,1.2099999999999958e-4,269352,5629,null,null,null,null,null,null,null],[1.2099900050088763e-4,1.2099999999999958e-4,266588,5911,null,null,null,null,null,null,null],[1.3303197920322418e-4,1.3300000000000117e-4,294804,6207,null,null,null,null,null,null,null],[1.3285200111567974e-4,1.329999999999977e-4,292868,6517,null,null,null,null,null,null,null],[1.3966701226308942e-4,1.389999999999985e-4,307730,6843,null,null,null,null,null,null,null],[1.5285800327546895e-4,1.5399999999999962e-4,338356,7185,null,null,null,null,null,null,null],[1.5347101725637913e-4,1.529999999999969e-4,338348,7544,null,null,null,null,null,null,null],[1.7099297838285565e-4,1.7099999999999754e-4,378212,7921,null,null,null,null,null,null,null],[1.6930900164879858e-4,1.6900000000000248e-4,373386,8318,null,null,null,null,null,null,null],[1.8411502242088318e-4,1.8400000000000014e-4,407206,8733,null,null,null,null,null,null,null],[1.8637199536897242e-4,1.8599999999999867e-4,411072,9170,null,null,null,null,null,null,null],[2.0187799236737192e-4,2.020000000000008e-4,446386,9629,null,null,null,null,null,null,null],[2.1173301502130926e-4,2.1200000000000038e-4,467928,10110,null,null,null,null,null,null,null],[2.1559098968282342e-4,2.160000000000009e-4,475428,10616,null,null,null,null,null,null,null],[2.3239498841576278e-4,2.319999999999961e-4,513402,11146,null,null,null,null,null,null,null],[2.44259019382298e-4,2.4500000000000216e-4,539124,11704,null,null,null,null,null,null,null],[2.492629864718765e-4,2.489999999999992e-4,549330,12289,null,null,null,null,null,null,null],[2.82555993180722e-4,2.82000000000001e-4,624162,12903,null,null,null,null,null,null,null],[2.8090798878110945e-4,2.8100000000000347e-4,620318,13549,null,null,null,null,null,null,null],[2.944830048363656e-4,2.930000000000016e-4,650136,14226,null,null,null,null,null,null,null],[3.088400117121637e-4,3.080000000000027e-4,681592,14937,null,null,null,null,null,null,null],[3.238749923184514e-4,3.2400000000000137e-4,714594,15684,null,null,null,null,null,null,null],[3.3987200004048645e-4,3.4e-4,749894,16469,null,null,null,null,null,null,null],[3.563780046533793e-4,3.559999999999987e-4,786214,17292,null,null,null,null,null,null,null],[4.0503000491298735e-4,4.0699999999999764e-4,895990,18157,null,null,null,null,null,null,null],[4.414169816300273e-4,4.4199999999999795e-4,974388,19065,null,null,null,null,null,null,null],[4.2447098530828953e-4,4.2400000000000423e-4,936334,20018,null,null,null,null,null,null,null],[4.500439972616732e-4,4.51e-4,992578,21019,null,null,null,null,null,null,null],[4.667970060836524e-4,4.6700000000000214e-4,1029200,22070,null,null,null,null,null,null,null],[4.899000050500035e-4,4.889999999999999e-4,1080112,23173,null,null,null,null,null,null,null],[5.225820059422404e-4,5.229999999999992e-4,1152140,24332,null,null,null,null,null,null,null],[5.391960148699582e-4,5.400000000000023e-4,1188648,25549,null,null,null,null,null,null,null],[5.743170040659606e-4,5.740000000000016e-4,1266130,26826,null,null,null,null,null,null,null],[5.809750000480562e-4,5.809999999999982e-4,1280390,28167,null,null,null,null,null,null,null],[6.298729858826846e-4,6.289999999999976e-4,1388260,29576,null,null,null,null,null,null,null],[6.868740019854158e-4,6.869999999999966e-4,1514256,31054,null,null,null,null,null,null,null],[7.230019837152213e-4,7.229999999999945e-4,1594024,32607,null,null,null,null,null,null,null],[7.784049957990646e-4,7.779999999999974e-4,1714886,34238,null,null,null,null,null,null,null],[8.11128003988415e-4,8.109999999999992e-4,1786850,35950,null,null,null,null,null,null,null],[8.511709747835994e-4,8.509999999999976e-4,1875110,37747,null,null,null,null,null,null,null],[8.898660016711801e-4,8.900000000000019e-4,1976686,39634,null,null,null,null,null,null,null],[8.725879888515919e-4,8.719999999999978e-4,1922566,41616,null,null,null,null,null,null,null],[8.982520084828138e-4,8.97999999999996e-4,1978524,43697,null,null,null,null,null,null,null],[9.415860113222152e-4,9.419999999999984e-4,2074326,45882,null,null,null,null,null,null,null],[1.089650992071256e-3,1.0899999999999938e-3,2401026,48176,null,null,null,null,null,null,null],[1.155370002379641e-3,1.1560000000000042e-3,2545742,50585,null,null,null,null,null,null,null],[1.2148630048613995e-3,1.2150000000000077e-3,2675642,53114,null,null,null,null,null,null,null],[1.25666699022986e-3,1.2560000000000002e-3,2767644,55770,null,null,null,null,null,null,null],[1.2689899886026978e-3,1.2689999999999924e-3,2794018,58558,null,null,null,null,null,null,null],[1.4192250091582537e-3,1.4199999999999977e-3,3125966,61486,null,null,null,null,null,null,null],[1.5777479857206345e-3,1.577999999999996e-3,3473718,64561,null,null,null,null,null,null,null],[1.4964360161684453e-3,1.4969999999999983e-3,3294886,67789,null,null,null,null,null,null,null],[1.4829070132691413e-3,1.4830000000000051e-3,3264914,71178,null,null,null,null,null,null,null],[1.5313519979827106e-3,1.5309999999999976e-3,3371910,74737,null,null,null,null,null,null,null],[1.6075279854703695e-3,1.6079999999999983e-3,3539220,78474,null,null,null,null,null,null,null],[1.6870959952939302e-3,1.687000000000008e-3,3714218,82398,null,null,null,null,null,null,null],[1.8756950157694519e-3,1.8759999999999957e-3,4129704,86518,null,null,null,null,null,null,null],[1.919757982250303e-3,1.919999999999998e-3,4226354,90843,null,null,null,null,null,null,null],[1.976150000700727e-3,1.9769999999999996e-3,4349974,95386,null,null,null,null,null,null,null],[2.0716410072054714e-3,2.0709999999999965e-3,4560514,100155,null,null,null,null,null,null,null],[2.1728879946749657e-3,2.1729999999999944e-3,4783340,105163,null,null,null,null,null,null,null],[2.286808012286201e-3,2.2869999999999974e-3,5034188,110421,null,null,null,null,null,null,null],[2.3727250227238983e-3,2.373e-3,5222436,115942,null,null,null,null,null,null,null],[2.495694992830977e-3,2.4949999999999972e-3,5493168,121739,null,null,null,null,null,null,null],[2.7471980138216168e-3,2.7469999999999994e-3,6047056,127826,null,null,null,null,null,null,null],[2.9708640067838132e-3,2.9710000000000014e-3,6539236,134217,null,null,null,null,null,null,null],[3.0153070110827684e-3,3.016000000000005e-3,6636142,140928,null,null,null,null,null,null,null],[3.028059989446774e-3,3.027000000000002e-3,6664360,147975,null,null,null,null,null,null,null],[3.2062279933597893e-3,3.2070000000000015e-3,7056602,155373,null,null,null,null,null,null,null],[3.3923529845196754e-3,3.393000000000007e-3,7465758,163142,null,null,null,null,null,null,null],[3.5456200130283833e-3,3.5460000000000075e-3,7803386,171299,null,null,null,null,null,null,null],[3.8079770165495574e-3,3.808999999999993e-3,8381172,179864,null,null,null,null,null,null,null],[3.976773004978895e-3,3.976999999999994e-3,8751452,188858,null,null,null,null,null,null,null],[4.079878999618813e-3,4.08e-3,8978542,198300,null,null,null,null,null,null,null],[4.3269150191918015e-3,4.3269999999999975e-3,9522152,208215,null,null,null,null,null,null,null],[4.470001003937796e-3,4.470000000000002e-3,9836662,218626,null,null,null,null,null,null,null],[4.872428020462394e-3,4.874000000000003e-3,10722288,229558,null,null,null,null,null,null,null],[4.940767015796155e-3,4.941000000000001e-3,10872264,241036,null,null,null,null,null,null,null],[5.223240004852414e-3,5.224000000000006e-3,11494206,253087,null,null,null,null,null,null,null],[5.434965016320348e-3,5.435000000000009e-3,11959708,265742,null,null,null,null,null,null,null],[5.797476973384619e-3,5.79799999999997e-3,12757506,279029,null,null,null,null,null,null,null],[6.133104005130008e-3,6.1340000000000006e-3,13495790,292980,null,null,null,null,null,null,null],[6.2913899892009795e-3,6.291999999999992e-3,13843824,307629,null,null,null,null,null,null,null],[6.648398994002491e-3,6.648000000000015e-3,14629490,323011,null,null,null,null,null,null,null],[7.0558839943259954e-3,7.055999999999979e-3,15526346,339161,null,null,null,null,null,null,null],[7.4249439931008965e-3,7.424999999999987e-3,16337978,356119,null,null,null,null,null,null,null],[7.7092179853934795e-3,7.709000000000021e-3,16963194,373925,null,null,null,null,null,null,null],[8.290446014143527e-3,8.289999999999992e-3,18241776,392622,null,null,null,null,null,null,null],[8.620255015557632e-3,8.619999999999989e-3,18967682,412253,null,null,null,null,null,null,null],[9.032543981447816e-3,9.033000000000013e-3,19874458,432866,null,null,null,null,null,null,null],[9.349416999612004e-3,9.348999999999968e-3,20571820,454509,null,null,null,null,null,null,null],[9.808922972297296e-3,9.808000000000011e-3,21582660,477234,null,null,null,null,null,null,null],[1.4454930002102628e-2,1.4447999999999989e-2,31815998,501096,null,null,null,null,null,null,null],[1.3374889007536694e-2,1.3374999999999998e-2,29425932,526151,null,null,null,null,null,null,null],[1.1378950002836064e-2,1.1378e-2,25036198,552458,null,null,null,null,null,null,null],[1.2026454991428182e-2,1.2026999999999954e-2,26461024,580081,null,null,null,null,null,null,null],[1.2654685007873923e-2,1.2656e-2,27843028,609086,null,null,null,null,null,null,null],[1.3459802023135126e-2,1.3460000000000027e-2,29614906,639540,null,null,null,null,null,null,null],[1.3948107982287183e-2,1.3949000000000045e-2,30688776,671517,null,null,null,null,null,null,null],[1.4484102983260527e-2,1.4485000000000026e-2,31867994,705093,null,null,null,null,null,null,null],[1.5333485003793612e-2,1.5334000000000014e-2,33736424,740347,null,null,null,null,null,null,null],[1.6279800998745486e-2,1.6279000000000043e-2,35818594,777365,null,null,null,null,null,null,null],[1.6825338010676205e-2,1.6825999999999952e-2,37018508,816233,null,null,null,null,null,null,null],[1.7766479984857142e-2,1.7766999999999977e-2,39089300,857045,null,null,null,null,null,null,null],[1.9011694006621838e-2,1.899799999999996e-2,41829334,899897,null,null,null,null,null,null,null],[1.9658203003928065e-2,1.9659000000000038e-2,43250748,944892,null,null,null,null,null,null,null],[2.077190301497467e-2,2.0770999999999984e-2,45700954,992136,null,null,null,null,null,null,null],[2.1526272990740836e-2,2.152599999999999e-2,47360568,1041743,null,null,null,null,null,null,null],[2.2623244993155822e-2,2.261799999999997e-2,49774154,1093831,null,null,null,null,null,null,null],[3.0359007010702044e-2,3.03520000000001e-2,66795244,1148522,null,null,null,null,null,null,null],[2.5625045003835112e-2,2.5626000000000038e-2,56378776,1205948,null,null,null,null,null,null,null],[2.6170302007813007e-2,2.6164999999999994e-2,57577900,1266246,null,null,null,null,null,null,null],[2.7586374984821305e-2,2.7567000000000008e-2,60693648,1329558,null,null,null,null,null,null,null],[2.9113661992596462e-2,2.9113999999999862e-2,64053750,1396036,null,null,null,null,null,null,null],[3.726070001721382e-2,3.7235999999999936e-2,81980104,1465838,null,null,null,null,null,null,null],[3.196953600854613e-2,3.1969000000000025e-2,70336336,1539130,null,null,null,null,null,null,null],[3.3439661987358704e-2,3.3440000000000025e-2,73569820,1616086,null,null,null,null,null,null,null],[4.189192899502814e-2,4.1834999999999845e-2,92168110,1696890,null,null,null,null,null,null,null],[3.732375398976728e-2,3.732399999999991e-2,82115028,1781735,null,null,null,null,null,null,null],[4.544095299206674e-2,4.5420000000000016e-2,99976162,1870822,null,null,null,null,null,null,null],[4.053783800918609e-2,4.0537000000000045e-2,89185944,1964363,null,null,null,null,null,null,null],[4.283254500478506e-2,4.2825e-2,94234986,2062581,null,null,null,null,null,null,null],[5.1143154996680096e-2,5.1068e-2,112521528,2165710,null,null,null,null,null,null,null],[4.755784600274637e-2,4.755800000000021e-2,104629812,2273996,null,null,null,null,null,null,null],[6.301521099521779e-2,6.298800000000027e-2,138641518,2387695,null,null,null,null,null,null,null],[5.287269200198352e-2,5.287300000000017e-2,116322382,2507080,null,null,null,null,null,null,null],[6.673756099189632e-2,6.672800000000012e-2,146835154,2632434,null,null,null,null,null,null,null],[5.9425461979117244e-2,5.942599999999998e-2,130736546,2764056,null,null,null,null,null,null,null],[6.1144414998125285e-2,6.1146000000000145e-2,134521030,2902259,null,null,null,null,null,null,null],[7.016911800019443e-2,7.013800000000026e-2,154379522,3047372,null,null,null,null,null,null,null],[7.348234299570322e-2,7.343800000000034e-2,161669210,3199740,null,null,null,null,null,null,null],[7.894127900362946e-2,7.891399999999993e-2,173681688,3359727,null,null,null,null,null,null,null],[8.066519201383926e-2,8.066199999999979e-2,177468588,3527714,null,null,null,null,null,null,null],[8.884616900468245e-2,8.877899999999994e-2,195467954,3704100,null,null,null,null,null,null,null],[9.39299640012905e-2,9.388999999999981e-2,206653246,3889305,null,null,null,null,null,null,null],[0.10612100997241214,0.10600399999999977,233471288,4083770,null,null,null,null,null,null,null],[0.10183990598306991,0.10175899999999993,224053108,4287958,null,null,null,null,null,null,null],[0.12609586198232137,0.12599300000000024,277420728,4502356,null,null,null,null,null,null,null],[0.10524546899250709,0.10519399999999957,231546430,4727474,null,null,null,null,null,null,null],[0.12472607701784,0.12464599999999981,274402494,4963848,null,null,null,null,null,null,null],[0.12209953300771303,0.12206000000000028,268624580,5212040,null,null,null,null,null,null,null],[0.12803200600319542,0.12799800000000072,281679486,5472642,null,null,null,null,null,null,null],[0.15328322601271793,0.15318900000000024,337230312,5746274,null,null,null,null,null,null,null],[0.14087599600316025,0.14085499999999973,309934058,6033588,null,null,null,null,null,null,null],[0.16443824200541712,0.16430899999999982,361779142,6335268,null,null,null,null,null,null,null],[0.1509496500075329,0.15083299999999955,332103010,6652031,null,null,null,null,null,null,null],[0.15568390398402698,0.15551799999999982,342513570,6984633,null,null,null,null,null,null,null],[0.18309666001005098,0.18303699999999967,402818630,7333864,null,null,null,null,null,null,null],[0.20358702598605305,0.20342700000000002,447898432,7700558,null,null,null,null,null,null,null],[0.18658072702237405,0.18645500000000004,410484044,8085585,null,null,null,null,null,null,null],[0.2140501549874898,0.21389099999999983,470920822,8489865,null,null,null,null,null,null,null],[0.22377065499313176,0.22362600000000032,492300598,8914358,null,null,null,null,null,null,null],[0.23815473800641485,0.23797100000000082,523946830,9360076,null,null,null,null,null,null,null],[0.24803585300105624,0.24782299999999946,545691436,9828080,null,null,null,null,null,null,null]]},{"reportAnalysis":{"anMean":{"estUpperBound":3.8862828356384757e-7,"estLowerBound":3.640686812141915e-7,"estPoint":3.7647973827317373e-7,"estConfidenceLevel":0.95},"anRegress":[{"regRSquare":{"estUpperBound":0.9947907586534039,"estLowerBound":0.9882157738679797,"estPoint":0.9918810346067727,"estConfidenceLevel":0.95},"regResponder":"time","regCoeffs":{"y":{"estUpperBound":2.1544673115009752e-4,"estLowerBound":-3.722560375174092e-4,"estPoint":-6.581833358806193e-5,"estConfidenceLevel":0.95},"iters":{"estUpperBound":3.803164118615079e-7,"estLowerBound":3.59832105979452e-7,"estPoint":3.6979215726516167e-7,"estConfidenceLevel":0.95}}}],"anStdDev":{"estUpperBound":4.81505001531474e-8,"estLowerBound":3.5904833037515274e-8,"estPoint":4.150785932735141e-8,"estConfidenceLevel":0.95},"anOutlierVar":{"ovFraction":0.917699613099007,"ovDesc":"severe","ovEffect":"Severe"},"anOverhead":3.161534180001628e-6},"reportKDEs":[{"kdeValues":[2.9454013709295896e-7,2.9586601888556503e-7,2.9719190067817115e-7,2.985177824707772e-7,2.9984366426338333e-7,3.011695460559894e-7,3.0249542784859546e-7,3.0382130964120157e-7,3.0514719143380764e-7,3.0647307322641375e-7,3.077989550190198e-7,3.091248368116259e-7,3.10450718604232e-7,3.1177660039683806e-7,3.1310248218944413e-7,3.1442836398205025e-7,3.157542457746563e-7,3.1708012756726243e-7,3.184060093598685e-7,3.1973189115247456e-7,3.2105777294508067e-7,3.2238365473768674e-7,3.2370953653029285e-7,3.250354183228989e-7,3.26361300115505e-7,3.276871819081111e-7,3.2901306370071716e-7,3.303389454933233e-7,3.3166482728592935e-7,3.329907090785354e-7,3.3431659087114153e-7,3.356424726637476e-7,3.369683544563537e-7,3.3829423624895977e-7,3.3962011804156584e-7,3.4094599983417195e-7,3.42271881626778e-7,3.4359776341938414e-7,3.449236452119902e-7,3.4624952700459626e-7,3.475754087972024e-7,3.4890129058980845e-7,3.5022717238241456e-7,3.5155305417502063e-7,3.528789359676267e-7,3.542048177602328e-7,3.5553069955283887e-7,3.56856581345445e-7,3.5818246313805105e-7,3.595083449306571e-7,3.6083422672326324e-7,3.621601085158693e-7,3.634859903084754e-7,3.648118721010815e-7,3.6613775389368755e-7,3.6746363568629366e-7,3.6878951747889973e-7,3.7011539927150584e-7,3.714412810641119e-7,3.7276716285671797e-7,3.740930446493241e-7,3.7541892644193015e-7,3.7674480823453627e-7,3.7807069002714234e-7,3.793965718197484e-7,3.807224536123545e-7,3.820483354049606e-7,3.833742171975667e-7,3.8470009899017276e-7,3.8602598078277883e-7,3.873518625753849e-7,3.88677744367991e-7,3.900036261605971e-7,3.913295079532032e-7,3.9265538974580925e-7,3.939812715384153e-7,3.9530715333102144e-7,3.9663303512362755e-7,3.979589169162336e-7,3.992847987088397e-7,4.0061068050144575e-7,4.0193656229405186e-7,4.0326244408665793e-7,4.0458832587926404e-7,4.059142076718701e-7,4.0724008946447617e-7,4.085659712570823e-7,4.0989185304968835e-7,4.1121773484229447e-7,4.1254361663490054e-7,4.138694984275066e-7,4.151953802201127e-7,4.1652126201271883e-7,4.178471438053249e-7,4.1917302559793096e-7,4.2049890739053703e-7,4.2182478918314314e-7,4.2315067097574926e-7,4.244765527683553e-7,4.258024345609614e-7,4.2712831635356745e-7,4.2845419814617357e-7,4.2978007993877964e-7,4.3110596173138575e-7,4.324318435239918e-7,4.337577253165979e-7,4.35083607109204e-7,4.3640948890181006e-7,4.377353706944162e-7,4.3906125248702224e-7,4.403871342796283e-7,4.417130160722344e-7,4.430388978648405e-7,4.443647796574466e-7,4.4569066145005267e-7,4.4701654324265873e-7,4.4834242503526485e-7,4.496683068278709e-7,4.5099418862047703e-7,4.523200704130831e-7,4.5364595220568916e-7,4.549718339982952e-7,4.5629771579090134e-7,4.5762359758350746e-7,4.589494793761135e-7,4.602753611687196e-7,4.6160124296132565e-7,4.6292712475393177e-7],"kdeType":"time","kdePDF":[5530282.79787247,5531627.570567824,5534313.856943901,5538335.146921076,5543681.695225951,5550340.545128092,5558295.559958689,5567527.462300351,5578013.880710751,5589729.403817111,5602645.64159373,5616731.293610986,5631952.224021834,5648271.543030547,5665649.6945689395,5684044.549887086,5703411.5067493785,5723703.593912107,5744871.580546299,5766864.090258815,5789627.719356318,5813107.158990226,5837245.320816616,5861983.465802875,5887261.33581322,5913017.28760732,5939188.428890887,5965710.7560635675,5992519.293318077,6019548.232754992,6046731.075189981,6074000.771344183,6101289.863124023,6128530.624713533,6155655.203220348,6182595.75863547,6209284.602886581,6235654.337784862,6261637.991685717,6287169.154704143,6312182.112345636,6336611.977433017,6360394.820228376,6383467.796666892,6405769.274635612,6427238.95824502,6447818.010054028,6467449.171219864,6486076.87955295,6503647.38546292,6520108.865785552,6535411.535481214,6549507.757193478,6562352.148651839,6573901.687894676,6584115.816278271,6592956.539224207,6600388.524641618,6606379.1989420485,6610898.840543817,6613920.6707395995,6615420.9417758295,6615379.021965917,6613777.477631168,6610602.151634376,6605842.238241498,6599490.354017121,6591542.604429947,6581998.645815822,6570861.742318254,6558138.817400361,6543840.499498445,6527981.161365914,6510578.952638195,6491655.8251342,6471237.550399075,6449353.728986118,6426037.790973625,6401326.98721521,6375262.370830091,6347888.768453294,6319254.740784746,6289412.532000962,6258418.007623806,6226330.580477014,6193213.124403678,6159131.875465549,6124156.32039861,6088359.072157964,6051815.732448713,6014604.741207736,5976807.213073708,5938506.760958669,5899789.306913838,5860742.880564037,5821457.40546895,5782024.473854384,5742537.110242375,5703089.524594396,5663776.855666542,5624694.905358429,5585939.8649180895,5547608.03394246,5509795.53318646,5472598.012262378,5436110.353374675,5400426.3722926285,5365638.517813899,5331837.571015424,5299112.3456237465,5267549.390864068,5237232.698166044,5208243.413113945,5180659.55402919,5154555.738564125,5130002.919667374,5107068.132252829,5085814.251866729,5066299.766600234,5048578.563438857,5032699.730175207,5018707.373938342,5006640.457311918,4996532.652924924,4988412.2173037175,4982301.884672987,4978218.781286921,4976174.360761089]}],"reportKeys":["time","cpuTime","cycles","iters","allocated","numGcs","bytesCopied","mutatorWallSeconds","mutatorCpuSeconds","gcWallSeconds","gcCpuSeconds"],"reportNumber":1,"reportName":"fib/5","reportOutliers":{"highSevere":0,"highMild":0,"lowMild":0,"samplesSeen":41,"lowSevere":0},"reportMeasured":[[6.3689949456602335e-6,4.999999999810711e-6,5118,1,null,null,null,null,null,null,null],[2.195010893046856e-6,2.9999999995311555e-6,4562,2,null,null,null,null,null,null,null],[2.315995516255498e-6,2.000000000279556e-6,4954,3,null,null,null,null,null,null,null],[2.7059868443757296e-6,2.000000000279556e-6,5880,4,null,null,null,null,null,null,null],[2.815009793266654e-6,2.9999999995311555e-6,6058,5,null,null,null,null,null,null,null],[3.1939998734742403e-6,3.000000000419334e-6,6908,6,null,null,null,null,null,null,null],[3.410998033359647e-6,2.9999999995311555e-6,7406,7,null,null,null,null,null,null,null],[3.9000005926936865e-6,4.000000000559112e-6,8644,8,null,null,null,null,null,null,null],[4.108005668967962e-6,3.9999999996709334e-6,8862,9,null,null,null,null,null,null,null],[4.387024091556668e-6,4.999999999810711e-6,9552,10,null,null,null,null,null,null,null],[4.6800123527646065e-6,4.999999999810711e-6,10282,11,null,null,null,null,null,null,null],[4.945992259308696e-6,4.999999999810711e-6,10844,12,null,null,null,null,null,null,null],[5.252019036561251e-6,5.999999999062311e-6,11528,13,null,null,null,null,null,null,null],[5.651992978528142e-6,6.000000000838668e-6,12330,14,null,null,null,null,null,null,null],[5.803012754768133e-6,6.000000000838668e-6,12848,15,null,null,null,null,null,null,null],[6.2800245359539986e-6,5.999999999950489e-6,13764,16,null,null,null,null,null,null,null],[6.430986104533076e-6,6.999999999202089e-6,14066,17,null,null,null,null,null,null,null],[6.895978003740311e-6,7.000000000090267e-6,15020,18,null,null,null,null,null,null,null],[7.040012860670686e-6,7.000000000090267e-6,15400,19,null,null,null,null,null,null,null],[7.291993824765086e-6,7.000000000978446e-6,16156,20,null,null,null,null,null,null,null],[7.642986020073295e-6,7.000000000978446e-6,16806,21,null,null,null,null,null,null,null],[7.983006071299314e-6,8.000000000230045e-6,17478,22,null,null,null,null,null,null,null],[8.310016710311174e-6,8.000000001118224e-6,18172,23,null,null,null,null,null,null,null],[9.011011570692062e-6,8.999999999481645e-6,19702,25,null,null,null,null,null,null,null],[9.112991392612457e-6,9.000000000369823e-6,20052,26,null,null,null,null,null,null,null],[9.556999430060387e-6,1.000000000139778e-5,20914,27,null,null,null,null,null,null,null],[9.766023140400648e-6,9.000000000369823e-6,21306,28,null,null,null,null,null,null,null],[1.0325980838388205e-5,1.0000000000509601e-5,22790,30,null,null,null,null,null,null,null],[1.0646996088325977e-5,1.100000000064938e-5,23420,31,null,null,null,null,null,null,null],[1.1280004400759935e-5,1.09999999997612e-5,24804,33,null,null,null,null,null,null,null],[1.1775991879403591e-5,1.100000000064938e-5,26022,35,null,null,null,null,null,null,null],[1.2259988579899073e-5,1.2000000000789157e-5,26904,36,null,null,null,null,null,null,null],[1.2822012649849057e-5,1.3000000000928935e-5,28158,38,null,null,null,null,null,null,null],[1.3329990906640887e-5,1.3000000000928935e-5,29300,40,null,null,null,null,null,null,null],[1.3923970982432365e-5,1.4000000000180535e-5,30616,42,null,null,null,null,null,null,null],[1.45800004247576e-5,1.5000000000320313e-5,32086,44,null,null,null,null,null,null,null],[1.5372002962976694e-5,1.5000000000320313e-5,33826,47,null,null,null,null,null,null,null],[1.6106991097331047e-5,1.5999999999571912e-5,35566,49,null,null,null,null,null,null,null],[1.7026002751663327e-5,1.700000000059987e-5,37452,52,null,null,null,null,null,null,null],[1.7587997717782855e-5,1.700000000059987e-5,38766,54,null,null,null,null,null,null,null],[1.8515012925490737e-5,1.7999999999851468e-5,40918,57,null,null,null,null,null,null,null],[1.9400002202019095e-5,1.9999999999242846e-5,42726,60,null,null,null,null,null,null,null],[2.024698187597096e-5,2.1000000000270802e-5,44548,63,null,null,null,null,null,null,null],[2.1146988729014993e-5,2.19999999995224e-5,46470,66,null,null,null,null,null,null,null],[2.213899279013276e-5,2.200000000129876e-5,48666,69,null,null,null,null,null,null,null],[2.3361993953585625e-5,2.3999999999801958e-5,51572,73,null,null,null,null,null,null,null],[2.4236011086031795e-5,2.5000000000829914e-5,53334,76,null,null,null,null,null,null,null],[3.775898949243128e-5,3.7999999999094314e-5,85106,80,null,null,null,null,null,null,null],[2.6788009563460946e-5,2.700000000022129e-5,58730,84,null,null,null,null,null,null,null],[2.8058013413101435e-5,2.7999999998584713e-5,61706,89,null,null,null,null,null,null,null],[2.925400622189045e-5,2.9000000000500847e-5,64460,93,null,null,null,null,null,null,null],[3.086499054916203e-5,2.9999999999752447e-5,67964,98,null,null,null,null,null,null,null],[3.23129934258759e-5,3.300000000017178e-5,71208,103,null,null,null,null,null,null,null],[3.3881020499393344e-5,3.400000000031156e-5,74558,108,null,null,null,null,null,null,null],[3.8439000491052866e-5,3.7999999999094314e-5,85440,113,null,null,null,null,null,null,null],[3.7393998354673386e-5,3.799999999998249e-5,82384,119,null,null,null,null,null,null,null],[4.6891014790162444e-5,4.7000000000352316e-5,103600,125,null,null,null,null,null,null,null],[7.765999180264771e-5,7.399999999968543e-5,182542,131,null,null,null,null,null,null,null],[4.910500138066709e-5,4.900000000063187e-5,107362,138,null,null,null,null,null,null,null],[4.986301064491272e-5,4.999999999988347e-5,109630,144,null,null,null,null,null,null,null],[1.7505697906017303e-4,1.760000000006201e-4,404307,152,null,null,null,null,null,null,null],[1.4888800797052681e-4,1.4800000000025904e-4,326376,159,null,null,null,null,null,null,null],[1.554769987706095e-4,1.550000000003493e-4,341968,167,null,null,null,null,null,null,null],[1.6353401588276029e-4,1.6300000000057935e-4,360360,176,null,null,null,null,null,null,null],[1.7213099636137486e-4,1.72000000000061e-4,379104,185,null,null,null,null,null,null,null],[1.7929900786839426e-4,1.7900000000103944e-4,394680,194,null,null,null,null,null,null,null],[1.8859998090192676e-4,1.8900000000066086e-4,415088,204,null,null,null,null,null,null,null],[2.2280000848695636e-4,2.2199999999994446e-4,496200,214,null,null,null,null,null,null,null],[2.0609100465662777e-4,2.0599999999948437e-4,453848,224,null,null,null,null,null,null,null],[2.1693098824471235e-4,2.1699999999924557e-4,477056,236,null,null,null,null,null,null,null],[2.2712702048011124e-4,2.2699999999975518e-4,500136,247,null,null,null,null,null,null,null],[2.3897801293060184e-4,2.3999999999890775e-4,526520,260,null,null,null,null,null,null,null],[2.5460097822360694e-4,2.5500000000011624e-4,561624,273,null,null,null,null,null,null,null],[2.0890400628559291e-4,2.0900000000079189e-4,463179,287,null,null,null,null,null,null,null],[2.0243300241418183e-4,2.0199999999981344e-4,445642,301,null,null,null,null,null,null,null],[2.121889847330749e-4,2.1200000000032304e-4,467333,316,null,null,null,null,null,null,null],[2.2302701836451888e-4,2.2300000000008424e-4,491113,332,null,null,null,null,null,null,null],[2.3343501379713416e-4,2.3299999999970566e-4,514013,348,null,null,null,null,null,null,null],[2.6055998750962317e-4,2.5999999999992696e-4,577594,366,null,null,null,null,null,null,null],[2.5778301642276347e-4,2.579999999987592e-4,568035,384,null,null,null,null,null,null,null],[2.698470198083669e-4,2.699999999995484e-4,594402,403,null,null,null,null,null,null,null],[2.981330035254359e-4,2.9799999999990945e-4,660166,424,null,null,null,null,null,null,null],[2.9759801691398025e-4,2.9799999999990945e-4,655610,445,null,null,null,null,null,null,null],[3.1254399800673127e-4,3.119999999992018e-4,687896,467,null,null,null,null,null,null,null],[3.421930014155805e-4,3.4199999999984243e-4,757280,490,null,null,null,null,null,null,null],[3.441110020503402e-4,3.4500000000026176e-4,758779,515,null,null,null,null,null,null,null],[3.618090122472495e-4,3.6100000000072185e-4,812698,541,null,null,null,null,null,null,null],[3.2865701359696686e-4,3.289999999989135e-4,724444,568,null,null,null,null,null,null,null],[3.142349887639284e-4,3.1400000000036954e-4,692452,596,null,null,null,null,null,null,null],[3.4050201065838337e-4,3.4000000000133923e-4,752628,626,null,null,null,null,null,null,null],[3.458599967416376e-4,3.4600000000040154e-4,762084,657,null,null,null,null,null,null,null],[3.742059925571084e-4,3.7399999999987443e-4,826628,690,null,null,null,null,null,null,null],[3.813380026258528e-4,3.809999999999647e-4,840620,725,null,null,null,null,null,null,null],[4.1083700489252806e-4,4.110000000006053e-4,907316,761,null,null,null,null,null,null,null],[4.203400167170912e-4,4.2100000000022675e-4,926228,799,null,null,null,null,null,null,null],[4.6467300853691995e-4,4.660000000002995e-4,1028484,839,null,null,null,null,null,null,null],[4.632420022971928e-4,4.629999999998802e-4,1020872,881,null,null,null,null,null,null,null],[4.6159399789758027e-4,4.609999999996006e-4,1019450,925,null,null,null,null,null,null,null],[4.5108600170351565e-4,4.50999999999091e-4,995256,972,null,null,null,null,null,null,null],[4.6271400060504675e-4,4.629999999998802e-4,1019532,1020,null,null,null,null,null,null,null],[4.946360131725669e-4,4.940000000006606e-4,1091864,1071,null,null,null,null,null,null,null],[5.189549992792308e-4,5.189999999997141e-4,1144964,1125,null,null,null,null,null,null,null],[4.7801301116123796e-4,4.770000000000607e-4,1053288,1181,null,null,null,null,null,null,null],[4.250619967933744e-4,4.249999999998977e-4,937190,1240,null,null,null,null,null,null,null],[3.9984099566936493e-4,3.9999999999995595e-4,881704,1302,null,null,null,null,null,null,null],[4.1914102621376514e-4,4.18999999999059e-4,924266,1367,null,null,null,null,null,null,null],[4.39752999227494e-4,4.40000000000218e-4,969548,1436,null,null,null,null,null,null,null],[4.6121698687784374e-4,4.610000000004888e-4,1016798,1507,null,null,null,null,null,null,null],[4.838879976887256e-4,4.839999999992628e-4,1066732,1583,null,null,null,null,null,null,null],[5.075119843240827e-4,5.079999999990648e-4,1118646,1662,null,null,null,null,null,null,null],[5.32345991814509e-4,5.310000000005033e-4,1173464,1745,null,null,null,null,null,null,null],[5.587530031334609e-4,5.589999999999762e-4,1232000,1832,null,null,null,null,null,null,null],[5.909939936827868e-4,5.9099999999912e-4,1302372,1924,null,null,null,null,null,null,null],[6.154190050438046e-4,6.159999999999499e-4,1356354,2020,null,null,null,null,null,null,null],[6.507150246761739e-4,6.509999999995131e-4,1433628,2121,null,null,null,null,null,null,null],[7.044719823170453e-4,7.039999999998159e-4,1553214,2227,null,null,null,null,null,null,null],[7.164400012698025e-4,7.159999999997169e-4,1578436,2339,null,null,null,null,null,null,null],[7.520189974457026e-4,7.52000000000308e-4,1656730,2456,null,null,null,null,null,null,null],[7.830010144971311e-4,7.830000000002002e-4,1725056,2579,null,null,null,null,null,null,null],[8.44385998789221e-4,8.449999999990965e-4,1860492,2708,null,null,null,null,null,null,null],[9.220920037478209e-4,9.209999999999496e-4,2032332,2843,null,null,null,null,null,null,null],[1.001694006845355e-3,1.0009999999995856e-3,2207206,2985,null,null,null,null,null,null,null],[1.0566590062808245e-3,1.0570000000003077e-3,2327146,3134,null,null,null,null,null,null,null],[1.1031169851776212e-3,1.1030000000005202e-3,2429542,3291,null,null,null,null,null,null,null],[1.1072819761466235e-3,1.108000000000331e-3,2438996,3456,null,null,null,null,null,null,null],[1.1441060050856322e-3,1.1450000000001737e-3,2519502,3629,null,null,null,null,null,null,null],[2.4604839854873717e-3,2.431000000000516e-3,5432386,3810,null,null,null,null,null,null,null],[2.3727179795969278e-3,2.3719999999993746e-3,5223568,4001,null,null,null,null,null,null,null],[2.2258640092331916e-3,2.227000000000423e-3,4901340,4201,null,null,null,null,null,null,null],[2.14928001514636e-3,2.1500000000003183e-3,4732212,4411,null,null,null,null,null,null,null],[2.1714959875680506e-3,2.1589999999998e-3,4788574,4631,null,null,null,null,null,null,null],[1.9050459959544241e-3,1.9059999999999633e-3,4193858,4863,null,null,null,null,null,null,null],[1.6448509995825589e-3,1.6439999999997568e-3,3620986,5106,null,null,null,null,null,null,null],[1.681102003203705e-3,1.6809999999995995e-3,3701036,5361,null,null,null,null,null,null,null],[1.7672579851932824e-3,1.7680000000002138e-3,3890840,5629,null,null,null,null,null,null,null],[1.8800500256475061e-3,1.8799999999998818e-3,4138754,5911,null,null,null,null,null,null,null],[1.9469289982225746e-3,1.946999999999477e-3,4286054,6207,null,null,null,null,null,null,null],[2.046756009804085e-3,2.0459999999999923e-3,4505718,6517,null,null,null,null,null,null,null],[2.135255024768412e-3,2.1339999999998582e-3,4700226,6843,null,null,null,null,null,null,null],[2.2248120221775025e-3,2.2240000000000038e-3,4897478,7185,null,null,null,null,null,null,null],[2.3560289992019534e-3,2.350999999999992e-3,5190712,7544,null,null,null,null,null,null,null],[2.4483460001647472e-3,2.4479999999993396e-3,5389322,7921,null,null,null,null,null,null,null],[2.567640010965988e-3,2.566999999999986e-3,5651898,8318,null,null,null,null,null,null,null],[2.706719998968765e-3,2.7060000000007634e-3,5957824,8733,null,null,null,null,null,null,null],[2.855366008589044e-3,2.8519999999989665e-3,6285228,9170,null,null,null,null,null,null,null],[2.9326770163606852e-3,2.9320000000003787e-3,6454914,9629,null,null,null,null,null,null,null],[3.124053997453302e-3,3.1249999999998224e-3,6876206,10110,null,null,null,null,null,null,null],[3.2666409970261157e-3,3.26300000000046e-3,7189740,10616,null,null,null,null,null,null,null],[3.391978010768071e-3,3.3919999999998396e-3,7464764,11146,null,null,null,null,null,null,null],[3.592653985833749e-3,3.5929999999995132e-3,7906906,11704,null,null,null,null,null,null,null],[3.7787689943797886e-3,3.778000000000503e-3,8316456,12289,null,null,null,null,null,null,null],[3.925159020582214e-3,3.924999999999734e-3,8637816,12903,null,null,null,null,null,null,null],[4.118347977055237e-3,4.118999999999318e-3,9063018,13549,null,null,null,null,null,null,null],[4.509021004196256e-3,4.50900000000054e-3,9923458,14226,null,null,null,null,null,null,null],[4.594772995915264e-3,4.595000000000127e-3,10111498,14937,null,null,null,null,null,null,null],[4.79835900478065e-3,4.79900000000022e-3,10559422,15684,null,null,null,null,null,null,null],[5.006429011700675e-3,5.006999999999984e-3,11017090,16469,null,null,null,null,null,null,null],[5.4624910117127e-3,5.463000000000662e-3,12021000,17292,null,null,null,null,null,null,null],[5.522830004338175e-3,5.522000000000027e-3,12152918,18157,null,null,null,null,null,null,null],[5.868509993888438e-3,5.86799999999954e-3,12913532,19065,null,null,null,null,null,null,null],[6.239559996174648e-3,6.240999999999275e-3,13729958,20018,null,null,null,null,null,null,null],[6.510671984869987e-3,6.511000000001488e-3,14326438,21019,null,null,null,null,null,null,null],[6.7655949969775975e-3,6.746999999998948e-3,14887816,22070,null,null,null,null,null,null,null],[1.0109009017469361e-2,1.0075999999999752e-2,22259863,23173,null,null,null,null,null,null,null],[1.1043214006349444e-2,1.1044000000000054e-2,24294013,24332,null,null,null,null,null,null,null],[1.2775884009897709e-2,1.2745999999999924e-2,28121738,25549,null,null,null,null,null,null,null],[1.0466584993992e-2,1.0438999999999865e-2,23030743,26826,null,null,null,null,null,null,null],[8.821894996799529e-3,8.82200000000033e-3,19410134,28167,null,null,null,null,null,null,null],[9.05839999904856e-3,9.058000000001343e-3,19931424,29576,null,null,null,null,null,null,null],[9.607458981918171e-3,9.608999999999313e-3,21139722,31054,null,null,null,null,null,null,null],[9.998121997341514e-3,9.997999999999507e-3,21998966,32607,null,null,null,null,null,null,null],[1.0649275995092466e-2,1.0650000000000048e-2,23431704,34238,null,null,null,null,null,null,null],[1.1351645982358605e-2,1.1351999999998696e-2,24976566,35950,null,null,null,null,null,null,null],[1.1748192977393046e-2,1.1749999999999261e-2,25849330,37747,null,null,null,null,null,null,null],[1.6361854010028765e-2,1.6332999999999487e-2,36011226,39634,null,null,null,null,null,null,null],[1.6450644005089998e-2,1.6443999999999903e-2,36194242,41616,null,null,null,null,null,null,null],[1.3593344017863274e-2,1.3594000000001216e-2,29909028,43697,null,null,null,null,null,null,null],[1.4143528998829424e-2,1.4113999999999294e-2,31119100,45882,null,null,null,null,null,null,null],[2.1857529995031655e-2,2.181999999999995e-2,48101196,48176,null,null,null,null,null,null,null],[1.6666358016664162e-2,1.6666000000000736e-2,36666800,50585,null,null,null,null,null,null,null],[1.6369702003430575e-2,1.6370000000000218e-2,36016148,53114,null,null,null,null,null,null,null],[1.7189422011142597e-2,1.719000000000115e-2,37820368,55770,null,null,null,null,null,null,null],[2.0977567008230835e-2,2.0973999999998938e-2,46168823,58558,null,null,null,null,null,null,null],[2.280742398579605e-2,2.2807000000000244e-2,50175534,61486,null,null,null,null,null,null,null],[2.6561063015833497e-2,2.6531000000000304e-2,58442066,64561,null,null,null,null,null,null,null],[2.0786434004548937e-2,2.078600000000108e-2,45732858,67789,null,null,null,null,null,null,null],[2.2607160004554316e-2,2.2606999999998934e-2,49739118,71178,null,null,null,null,null,null,null],[2.336564500001259e-2,2.3365999999999332e-2,51407526,74737,null,null,null,null,null,null,null],[2.4193908990127966e-2,2.4194999999998856e-2,53229650,78474,null,null,null,null,null,null,null],[3.541715198662132e-2,3.5367000000000814e-2,77930312,82398,null,null,null,null,null,null,null],[2.9687178001040593e-2,2.9654999999999987e-2,65318758,86518,null,null,null,null,null,null,null],[3.573231800692156e-2,3.5645999999999844e-2,78617846,90843,null,null,null,null,null,null,null],[2.9777010990073904e-2,2.9748999999998915e-2,65513348,95386,null,null,null,null,null,null,null],[3.896774398162961e-2,3.893199999999908e-2,85736820,100155,null,null,null,null,null,null,null],[4.55451890011318e-2,4.551700000000025e-2,100204946,105163,null,null,null,null,null,null,null],[3.915400800178759e-2,3.91269999999988e-2,86150618,110421,null,null,null,null,null,null,null],[3.71866789937485e-2,3.7173999999998486e-2,81811878,115942,null,null,null,null,null,null,null],[3.7619426992023364e-2,3.76189999999994e-2,82765836,121739,null,null,null,null,null,null,null],[4.603989899624139e-2,4.599900000000012e-2,101293428,127826,null,null,null,null,null,null,null],[5.9948230016743764e-2,5.9899999999998954e-2,131891262,134217,null,null,null,null,null,null,null],[4.348806999041699e-2,4.3489000000001e-2,95676348,140928,null,null,null,null,null,null,null],[6.642680001095869e-2,6.633599999999973e-2,146145502,147975,null,null,null,null,null,null,null],[4.823095098254271e-2,4.823099999999947e-2,106110788,155373,null,null,null,null,null,null,null],[6.95042010047473e-2,6.944900000000054e-2,152915870,163142,null,null,null,null,null,null,null],[6.719720401451923e-2,6.715100000000085e-2,147839372,171299,null,null,null,null,null,null,null],[6.829725802526809e-2,6.825900000000118e-2,150264508,179864,null,null,null,null,null,null,null],[5.856280602165498e-2,5.856300000000125e-2,128839958,188858,null,null,null,null,null,null,null],[8.231437799986452e-2,8.224300000000007e-2,181098420,198300,null,null,null,null,null,null,null],[9.07866460038349e-2,9.072600000000008e-2,199737670,208215,null,null,null,null,null,null,null],[8.800584901473485e-2,8.791100000000007e-2,193619266,218626,null,null,null,null,null,null,null],[9.816788000171073e-2,9.807200000000016e-2,215981134,229558,null,null,null,null,null,null,null],[8.16791650140658e-2,8.161899999999811e-2,179699402,241036,null,null,null,null,null,null,null],[9.940655599348247e-2,9.933800000000126e-2,218718298,253087,null,null,null,null,null,null,null],[0.11120138401747681,0.11112700000000153,244654144,265742,null,null,null,null,null,null,null],[9.786622298997827e-2,9.785500000000091e-2,215306887,279029,null,null,null,null,null,null,null],[0.11794480800745077,0.11783100000000069,259484402,292980,null,null,null,null,null,null,null],[0.10283540200907737,0.1027769999999979,226244166,307629,null,null,null,null,null,null,null],[0.11402164501487277,0.11388900000000035,250853314,323011,null,null,null,null,null,null,null],[0.13191826498950832,0.1318179999999991,290228042,339161,null,null,null,null,null,null,null],[0.14718902899767272,0.14705699999999844,323822326,356119,null,null,null,null,null,null,null],[0.11646585201378912,0.11646599999999907,256227484,373925,null,null,null,null,null,null,null],[0.130337740003597,0.13032800000000044,286750526,392622,null,null,null,null,null,null,null],[0.14089532700018026,0.14082400000000028,309976950,412253,null,null,null,null,null,null,null],[0.15498050500173122,0.15486699999999942,340962370,432866,null,null,null,null,null,null,null],[0.18791693201637827,0.18770999999999916,413426726,454509,null,null,null,null,null,null,null],[0.17427672201301903,0.17420499999999883,383416370,477234,null,null,null,null,null,null,null],[0.19600536601501517,0.19590900000000033,431217902,501096,null,null,null,null,null,null,null],[0.19916906699654646,0.1989959999999975,438191168,526151,null,null,null,null,null,null,null],[0.21339729498140514,0.21320400000000106,469476594,552458,null,null,null,null,null,null,null],[0.21181727599469014,0.21171000000000006,466004624,580081,null,null,null,null,null,null,null],[0.21616315699066035,0.21574699999999858,475566004,609086,null,null,null,null,null,null,null],[0.22467806399799883,0.22451699999999875,494296310,639540,null,null,null,null,null,null,null]]},{"reportAnalysis":{"anMean":{"estUpperBound":2.700766045605913e-6,"estLowerBound":2.5489390737084626e-6,"estPoint":2.614524699113428e-6,"estConfidenceLevel":0.95},"anRegress":[{"regRSquare":{"estUpperBound":0.9963158112849326,"estLowerBound":0.9813766955405638,"estPoint":0.9888135706759168,"estConfidenceLevel":0.95},"regResponder":"time","regCoeffs":{"y":{"estUpperBound":3.36336946581968e-4,"estLowerBound":-5.759459124098816e-4,"estPoint":-1.0139218770465428e-4,"estConfidenceLevel":0.95},"iters":{"estUpperBound":2.7027537748864712e-6,"estLowerBound":2.4813442295249526e-6,"estPoint":2.586203298978693e-6,"estConfidenceLevel":0.95}}}],"anStdDev":{"estUpperBound":3.0480780278156827e-7,"estLowerBound":2.0893167057513842e-7,"estPoint":2.4922772413717383e-7,"estConfidenceLevel":0.95},"anOutlierVar":{"ovFraction":0.86814310186276,"ovDesc":"severe","ovEffect":"Severe"},"anOverhead":3.161534180001628e-6},"reportKDEs":[{"kdeValues":[2.0686914544928066e-6,2.078425810377499e-6,2.0881601662621917e-6,2.097894522146884e-6,2.1076288780315764e-6,2.117363233916269e-6,2.1270975898009615e-6,2.136831945685654e-6,2.1465663015703466e-6,2.156300657455039e-6,2.1660350133397313e-6,2.1757693692244237e-6,2.1855037251091164e-6,2.1952380809938088e-6,2.204972436878501e-6,2.214706792763194e-6,2.224441148647886e-6,2.2341755045325785e-6,2.2439098604172713e-6,2.2536442163019636e-6,2.263378572186656e-6,2.2731129280713487e-6,2.282847283956041e-6,2.2925816398407334e-6,2.302315995725426e-6,2.3120503516101185e-6,2.321784707494811e-6,2.3315190633795036e-6,2.341253419264196e-6,2.3509877751488883e-6,2.3607221310335807e-6,2.3704564869182734e-6,2.3801908428029658e-6,2.3899251986876585e-6,2.399659554572351e-6,2.409393910457043e-6,2.4191282663417355e-6,2.4288626222264283e-6,2.4385969781111206e-6,2.448331333995813e-6,2.4580656898805057e-6,2.467800045765198e-6,2.4775344016498904e-6,2.487268757534583e-6,2.4970031134192755e-6,2.506737469303968e-6,2.5164718251886606e-6,2.526206181073353e-6,2.5359405369580453e-6,2.5456748928427377e-6,2.5554092487274304e-6,2.5651436046121228e-6,2.5748779604968155e-6,2.584612316381508e-6,2.5943466722662e-6,2.6040810281508925e-6,2.6138153840355853e-6,2.6235497399202776e-6,2.63328409580497e-6,2.6430184516896628e-6,2.652752807574355e-6,2.6624871634590474e-6,2.6722215193437398e-6,2.6819558752284325e-6,2.691690231113125e-6,2.7014245869978176e-6,2.71115894288251e-6,2.7208932987672023e-6,2.7306276546518947e-6,2.7403620105365874e-6,2.7500963664212798e-6,2.7598307223059725e-6,2.769565078190665e-6,2.779299434075357e-6,2.7890337899600495e-6,2.7987681458447423e-6,2.8085025017294347e-6,2.818236857614127e-6,2.8279712134988198e-6,2.837705569383512e-6,2.8474399252682044e-6,2.857174281152897e-6,2.8669086370375895e-6,2.876642992922282e-6,2.8863773488069746e-6,2.896111704691667e-6,2.9058460605763593e-6,2.9155804164610517e-6,2.9253147723457444e-6,2.9350491282304368e-6,2.9447834841151295e-6,2.954517839999822e-6,2.9642521958845142e-6,2.9739865517692066e-6,2.9837209076538993e-6,2.9934552635385917e-6,3.0031896194232844e-6,3.0129239753079768e-6,3.022658331192669e-6,3.0323926870773614e-6,3.0421270429620538e-6,3.0518613988467465e-6,3.0615957547314393e-6,3.0713301106161316e-6,3.081064466500824e-6,3.0907988223855163e-6,3.1005331782702087e-6,3.1102675341549014e-6,3.1200018900395938e-6,3.1297362459242865e-6,3.139470601808979e-6,3.1492049576936712e-6,3.1589393135783636e-6,3.1686736694630563e-6,3.1784080253477487e-6,3.1881423812324414e-6,3.1978767371171338e-6,3.207611093001826e-6,3.2173454488865184e-6,3.2270798047712108e-6,3.2368141606559035e-6,3.2465485165405963e-6,3.2562828724252887e-6,3.266017228309981e-6,3.2757515841946733e-6,3.2854859400793657e-6,3.2952202959640584e-6,3.3049546518487508e-6],"kdeType":"time","kdePDF":[193348.37411608477,195787.67943903586,200648.0496875539,207894.41662626184,217477.60419800878,229338.15351163864,243410.9677847057,259630.43054229204,277935.6139420204,298275.18537864153,320611.6398482463,344924.53108626854,371212.4423769799,399493.52259140834,429804.5076097088,462198.2442885739,496739.825945078,533501.5279305208,572556.7934448962,613973.5591982311,657807.2258694681,704093.5698718495,752841.8633543929,804028.423417068,857590.7556605608,913422.3989961696,971368.5260191171,1031222.3136045334,1092722.077741481,1155549.1687915262,1219326.6492767837,1283618.823578413,1347931.751733892,1411714.9488659068,1474364.5361848872,1535228.156119902,1593611.9801298883,1648790.111994119,1700016.6141146778,1746540.2567119885,1787621.9129084416,1822554.3062876717,1850683.577654195,1871431.8957836279,1884320.1178163385,1888989.3344663668,1885220.0373355097,1872947.6393742985,1852273.176346929,1823468.2188309694,1786973.3219293838,1743389.7140752703,1693464.3485281398,1638068.8763004115,1578173.5091379452,1514817.0885404367,1449074.929314927,1382026.1399994812,1314722.1250739216,1248157.8452578573,1183247.1651551079,1120803.2761352921,1061524.779434515,1005987.5879317212,954642.3939246824,907817.0905308761,865723.2555393736,828465.6287808041,796053.4465428785,768412.5370811877,745397.2172074204,726801.240050196,712367.3012671213,701794.8854026187,694746.4963903147,690852.5404979753,689715.2962463385,690912.501385636,694001.1074337641,698521.7011127233,704003.9798254858,709973.5110583926,715959.8226072633,721505.6823087626,726177.2520467232,729574.6579264199,731342.4192055991,731179.130356173,728845.7957563065,724172.2722737687,717061.374495603,707490.3305671671,695509.431627356,681237.8821337967,664857.019906639,646601.2227881057,626746.9446837859,605600.4209590345,583484.6475728014,560726.2679896798,537642.9967931723,514532.170629574,491660.9485854966,469258.589399586,447511.11703277455,426558.55489788984,406494.7690173883,387369.8186463004,369194.576933432,351947.26151982555,335581.4127689706,320034.7819557119,305238.5482667463,291126.27516166767,277642.04462878616,264747.27087790414,252425.78935354357,240686.93668799847,229566.47453294246,219125.35597781054,209446.47769778976,200629.6943643561,192785.48527776,186027.7491541602,180466.2559729677,176199.30150793327,173307.08984033504,171846.31345863192]}],"reportKeys":["time","cpuTime","cycles","iters","allocated","numGcs","bytesCopied","mutatorWallSeconds","mutatorCpuSeconds","gcWallSeconds","gcCpuSeconds"],"reportNumber":2,"reportName":"fib/9","reportOutliers":{"highSevere":0,"highMild":0,"lowMild":0,"samplesSeen":43,"lowSevere":0},"reportMeasured":[[9.025010513141751e-6,9.000000000369823e-6,10070,1,null,null,null,null,null,null,null],[6.454007234424353e-6,6.9999999983139105e-6,14026,2,null,null,null,null,null,null,null],[8.56400583870709e-6,7.999999999341867e-6,18698,3,null,null,null,null,null,null,null],[1.0866002412512898e-5,1.0999999998873022e-5,23874,4,null,null,null,null,null,null,null],[1.3115000911056995e-5,1.2999999999152578e-5,28860,5,null,null,null,null,null,null,null],[1.559098018333316e-5,1.5999999998683734e-5,34492,6,null,null,null,null,null,null,null],[1.771599636413157e-5,1.699999999971169e-5,38994,7,null,null,null,null,null,null,null],[2.0154984667897224e-5,2.100000000204716e-5,44484,8,null,null,null,null,null,null,null],[2.247901284135878e-5,2.19999999995224e-5,49484,9,null,null,null,null,null,null,null],[2.4684995878487825e-5,2.4999999999053557e-5,54322,10,null,null,null,null,null,null,null],[2.7000001864507794e-5,2.6000000000081513e-5,59580,11,null,null,null,null,null,null,null],[2.9360002372413874e-5,3.0000000000640625e-5,64772,12,null,null,null,null,null,null,null],[3.161598579026759e-5,3.1999999999143824e-5,69726,13,null,null,null,null,null,null,null],[3.410899080336094e-5,3.400000000119974e-5,75208,14,null,null,null,null,null,null,null],[3.648200072348118e-5,3.600000000147929e-5,80404,15,null,null,null,null,null,null,null],[3.861100412905216e-5,3.899999999923409e-5,85242,16,null,null,null,null,null,null,null],[4.0942017221823335e-5,4.2000000000541604e-5,90026,17,null,null,null,null,null,null,null],[4.3231004383414984e-5,4.300000000156956e-5,95256,18,null,null,null,null,null,null,null],[4.5541994040831923e-5,4.599999999932436e-5,100604,19,null,null,null,null,null,null,null],[6.048599607311189e-5,6.100000000053285e-5,135170,20,null,null,null,null,null,null,null],[5.038900417275727e-5,5.100000000091143e-5,110876,21,null,null,null,null,null,null,null],[5.247999797575176e-5,5.2000000001939384e-5,115660,22,null,null,null,null,null,null,null],[5.473001510836184e-5,5.499999999969418e-5,120400,23,null,null,null,null,null,null,null],[5.947801400907338e-5,6.000000000128125e-5,130906,25,null,null,null,null,null,null,null],[6.179101183079183e-5,6.20000000015608e-5,136292,26,null,null,null,null,null,null,null],[6.399900303222239e-5,6.400000000184036e-5,140834,27,null,null,null,null,null,null,null],[6.636200123466551e-5,6.699999999959516e-5,146108,28,null,null,null,null,null,null,null],[8.053000783547759e-5,7.999999999874774e-5,197550,30,null,null,null,null,null,null,null],[7.612298941239715e-5,7.600000000174134e-5,167449,31,null,null,null,null,null,null,null],[1.3218598905950785e-4,1.3199999999891077e-4,291486,33,null,null,null,null,null,null,null],[8.550498750992119e-5,8.600000000136276e-5,188223,35,null,null,null,null,null,null,null],[8.784799138084054e-5,8.79999999980896e-5,193612,36,null,null,null,null,null,null,null],[9.27560031414032e-5,9.300000000145303e-5,204376,38,null,null,null,null,null,null,null],[1.0629199096001685e-4,1.0599999999882925e-4,236083,40,null,null,null,null,null,null,null],[1.0212001507170498e-4,1.029999999992981e-4,224758,42,null,null,null,null,null,null,null],[1.0692101204767823e-4,1.0699999999808085e-4,235573,44,null,null,null,null,null,null,null],[1.1425901902839541e-4,1.1399999999994748e-4,251653,47,null,null,null,null,null,null,null],[1.2689499999396503e-4,1.2699999999910005e-4,281569,49,null,null,null,null,null,null,null],[1.262580044567585e-4,1.259999999980721e-4,278153,52,null,null,null,null,null,null,null],[1.7646601190790534e-4,1.7800000000001148e-4,389226,54,null,null,null,null,null,null,null],[1.4653097605332732e-4,1.459999999990913e-4,323374,57,null,null,null,null,null,null,null],[1.5397000242955983e-4,1.5499999999946112e-4,341224,60,null,null,null,null,null,null,null],[1.528009888716042e-4,1.5200000000170633e-4,336943,63,null,null,null,null,null,null,null],[1.598570088390261e-4,1.600000000010482e-4,352477,66,null,null,null,null,null,null,null],[1.7703999765217304e-4,1.7700000000075988e-4,392036,69,null,null,null,null,null,null,null],[1.7054399359039962e-4,1.7000000000066962e-4,376114,73,null,null,null,null,null,null,null],[1.7806902178563178e-4,1.7800000000001148e-4,392362,76,null,null,null,null,null,null,null],[1.936939952429384e-4,1.9300000000121997e-4,428626,80,null,null,null,null,null,null,null],[1.9629302551038563e-4,1.9600000000075113e-4,432900,84,null,null,null,null,null,null,null],[2.1560300956480205e-4,2.1599999999999397e-4,476902,89,null,null,null,null,null,null,null],[2.1720101358368993e-4,2.1700000000102193e-4,478940,93,null,null,null,null,null,null,null],[2.3577900719828904e-4,2.3600000000101318e-4,521462,98,null,null,null,null,null,null,null],[2.4000598932616413e-4,2.3999999999979593e-4,529060,103,null,null,null,null,null,null,null],[2.689130196813494e-4,2.6899999999763224e-4,595922,108,null,null,null,null,null,null,null],[2.6383798103779554e-4,2.6500000000062585e-4,581164,113,null,null,null,null,null,null,null],[2.848590083885938e-4,2.849999999998687e-4,629544,119,null,null,null,null,null,null,null],[2.9143900610506535e-4,2.90999999998931e-4,642830,125,null,null,null,null,null,null,null],[3.314010100439191e-4,3.32000000000221e-4,732346,131,null,null,null,null,null,null,null],[3.408030024729669e-4,3.409999999988145e-4,752136,138,null,null,null,null,null,null,null],[3.719259984791279e-4,3.7200000000048306e-4,838015,144,null,null,null,null,null,null,null],[3.3201402402482927e-4,3.3200000000199736e-4,732194,152,null,null,null,null,null,null,null],[3.535610157996416e-4,3.5400000000151977e-4,780606,159,null,null,null,null,null,null,null],[3.8795600994490087e-4,3.879999999991668e-4,856874,167,null,null,null,null,null,null,null],[4.030359850730747e-4,4.029999999985989e-4,888754,176,null,null,null,null,null,null,null],[4.101049853488803e-4,4.089999999994376e-4,904480,185,null,null,null,null,null,null,null],[4.5459700049832463e-4,4.5499999999876195e-4,1002900,194,null,null,null,null,null,null,null],[4.5129001955501735e-4,4.509999999999792e-4,995144,204,null,null,null,null,null,null,null],[4.8493797658011317e-4,4.849999999994026e-4,1070060,214,null,null,null,null,null,null,null],[5.080150149296969e-4,5.079999999981766e-4,1120512,224,null,null,null,null,null,null,null],[5.283710197545588e-4,5.289999999984474e-4,1165972,236,null,null,null,null,null,null,null],[5.59504987904802e-4,5.60000000000116e-4,1233404,247,null,null,null,null,null,null,null],[5.874079943168908e-4,5.870000000012254e-4,1295364,260,null,null,null,null,null,null,null],[6.147419917397201e-4,6.140000000005585e-4,1354582,273,null,null,null,null,null,null,null],[6.551709957420826e-4,6.559999999993238e-4,1444154,287,null,null,null,null,null,null,null],[6.678270001430064e-4,6.679999999992248e-4,1472302,301,null,null,null,null,null,null,null],[8.210859959945083e-4,7.880000000000109e-4,1813802,316,null,null,null,null,null,null,null],[7.803000044077635e-4,7.809999999999206e-4,1719170,332,null,null,null,null,null,null,null],[8.215210109483451e-4,8.219999999994343e-4,1810584,348,null,null,null,null,null,null,null],[8.625930058769882e-4,8.620000000014727e-4,1900320,366,null,null,null,null,null,null,null],[9.034019894897938e-4,9.0299999999921e-4,1989990,384,null,null,null,null,null,null,null],[9.107229998335242e-4,9.109999999985519e-4,2006526,403,null,null,null,null,null,null,null],[9.354469948448241e-4,9.350000000019065e-4,2060650,424,null,null,null,null,null,null,null],[9.821320127230138e-4,9.830000000015104e-4,2163700,445,null,null,null,null,null,null,null],[1.0278359986841679e-3,1.0279999999998068e-3,2264884,467,null,null,null,null,null,null,null],[1.083791023120284e-3,1.084000000000529e-3,2387530,490,null,null,null,null,null,null,null],[1.1553829826880246e-3,1.1560000000017112e-3,2546456,515,null,null,null,null,null,null,null],[1.285703998291865e-3,1.2860000000003424e-3,2833710,541,null,null,null,null,null,null,null],[1.3429950049612671e-3,1.3430000000003162e-3,2957990,568,null,null,null,null,null,null,null],[1.407958014169708e-3,1.4079999999996318e-3,3103416,596,null,null,null,null,null,null,null],[1.47148099495098e-3,1.4720000000014721e-3,3242800,626,null,null,null,null,null,null,null],[1.5448569902218878e-3,1.5459999999993812e-3,3402196,657,null,null,null,null,null,null,null],[1.6275400121230632e-3,1.6280000000001849e-3,3584376,690,null,null,null,null,null,null,null],[1.7233329999726266e-3,1.7250000000004206e-3,3797122,725,null,null,null,null,null,null,null],[1.676952000707388e-3,1.6770000000008167e-3,3692250,761,null,null,null,null,null,null,null],[1.8132149998564273e-3,1.8129999999985102e-3,3992996,799,null,null,null,null,null,null,null],[1.8865060119424015e-3,1.8860000000007204e-3,4153276,839,null,null,null,null,null,null,null],[2.0333520078565925e-3,2.0329999999990633e-3,4477530,881,null,null,null,null,null,null,null],[2.186147990869358e-3,2.1860000000000213e-3,4812700,925,null,null,null,null,null,null,null],[2.234531013527885e-3,2.2349999999988768e-3,4920346,972,null,null,null,null,null,null,null],[2.2437220031861216e-3,2.2439999999992466e-3,4939532,1020,null,null,null,null,null,null,null],[2.3632259981241077e-3,2.3640000000000327e-3,5202712,1071,null,null,null,null,null,null,null],[2.4740290245972574e-3,2.473999999999421e-3,5446956,1125,null,null,null,null,null,null,null],[2.6580050180200487e-3,2.658999999999523e-3,5854054,1181,null,null,null,null,null,null,null],[2.760325005510822e-3,2.7609999999995694e-3,6078928,1240,null,null,null,null,null,null,null],[2.889148978283629e-3,2.888999999997921e-3,6368080,1302,null,null,null,null,null,null,null],[3.0587739893235266e-3,3.059000000000367e-3,6741256,1367,null,null,null,null,null,null,null],[3.172787983203307e-3,3.1740000000013424e-3,6991352,1436,null,null,null,null,null,null,null],[3.3469090121798217e-3,3.3479999999990184e-3,7374200,1507,null,null,null,null,null,null,null],[3.7601999938488007e-3,3.76000000000154e-3,8290968,1583,null,null,null,null,null,null,null],[3.717967978445813e-3,3.71900000000025e-3,8198438,1662,null,null,null,null,null,null,null],[3.8702079909853637e-3,3.871000000001956e-3,8531532,1745,null,null,null,null,null,null,null],[4.957520985044539e-3,4.925000000000068e-3,10914740,1832,null,null,null,null,null,null,null],[4.731969995191321e-3,4.732999999999876e-3,10417106,1924,null,null,null,null,null,null,null],[6.260136986384168e-3,6.259000000001791e-3,13773342,2020,null,null,null,null,null,null,null],[4.586497001582757e-3,4.585999999999757e-3,10093508,2121,null,null,null,null,null,null,null],[4.863178008235991e-3,4.862999999998507e-3,10702212,2227,null,null,null,null,null,null,null],[5.051475978689268e-3,5.051999999999168e-3,11116046,2339,null,null,null,null,null,null,null],[5.2665589901153e-3,5.266999999999911e-3,11589664,2456,null,null,null,null,null,null,null],[5.532464012503624e-3,5.532000000002313e-3,12173910,2579,null,null,null,null,null,null,null],[1.221357801114209e-2,1.2194000000000926e-2,26883372,2708,null,null,null,null,null,null,null],[7.677442015847191e-3,7.676999999999268e-3,16891160,2843,null,null,null,null,null,null,null],[6.515315995784476e-3,6.5099999999986835e-3,14338932,2985,null,null,null,null,null,null,null],[6.838730012532324e-3,6.838999999999373e-3,15048110,3134,null,null,null,null,null,null,null],[7.074805005686358e-3,7.0750000000003865e-3,15568760,3291,null,null,null,null,null,null,null],[7.407514000078663e-3,7.407999999999859e-3,16299468,3456,null,null,null,null,null,null,null],[1.2365557020530105e-2,1.2347000000000108e-2,27218076,3629,null,null,null,null,null,null,null],[1.487063302192837e-2,1.4864000000001099e-2,32717934,3810,null,null,null,null,null,null,null],[8.677542995428666e-3,8.677999999999741e-3,19093038,4001,null,null,null,null,null,null,null],[1.3501470995834097e-2,1.3498999999997707e-2,29716954,4201,null,null,null,null,null,null,null],[1.6902139992453158e-2,1.689500000000166e-2,37186708,4411,null,null,null,null,null,null,null],[1.009635700029321e-2,1.0097999999999274e-2,22214776,4631,null,null,null,null,null,null,null],[1.03957150131464e-2,1.0395999999998295e-2,22873830,4863,null,null,null,null,null,null,null],[1.0963571985485032e-2,1.0964999999998781e-2,24122952,5106,null,null,null,null,null,null,null],[1.8303408025531098e-2,1.829900000000073e-2,40274822,5361,null,null,null,null,null,null,null],[1.2116741010686383e-2,1.2115999999998905e-2,26659714,5629,null,null,null,null,null,null,null],[1.27997369854711e-2,1.2799000000001115e-2,28162698,5911,null,null,null,null,null,null,null],[1.3315553980646655e-2,1.3314999999998633e-2,29297156,6207,null,null,null,null,null,null,null],[1.400301099056378e-2,1.3990999999998976e-2,30810540,6517,null,null,null,null,null,null,null],[2.1235216001514345e-2,2.1203999999999112e-2,46723796,6843,null,null,null,null,null,null,null],[2.221076699788682e-2,2.2181999999999036e-2,48871974,7185,null,null,null,null,null,null,null],[1.670748699689284e-2,1.666799999999924e-2,36761724,7544,null,null,null,null,null,null,null],[2.1554483013460413e-2,2.1551000000000542e-2,47434276,7921,null,null,null,null,null,null,null],[2.0073012012289837e-2,2.0073000000000008e-2,44161128,8318,null,null,null,null,null,null,null],[1.8873328022891656e-2,1.887299999999925e-2,41524274,8733,null,null,null,null,null,null,null],[1.968980100355111e-2,1.9689999999998875e-2,43320782,9170,null,null,null,null,null,null,null],[2.0864435995463282e-2,2.086399999999955e-2,45904880,9629,null,null,null,null,null,null,null],[2.207880499190651e-2,2.2078999999999738e-2,48576264,10110,null,null,null,null,null,null,null],[2.6395068009151146e-2,2.6391000000000275e-2,58089377,10616,null,null,null,null,null,null,null],[2.7240916999289766e-2,2.7240999999998294e-2,59929207,11146,null,null,null,null,null,null,null],[3.516917198430747e-2,3.511600000000037e-2,77384600,11704,null,null,null,null,null,null,null],[3.7458534992765635e-2,3.742699999999921e-2,82416984,12289,null,null,null,null,null,null,null],[3.291460601030849e-2,3.2906000000000546e-2,72423722,12903,null,null,null,null,null,null,null],[3.6155059991870075e-2,3.614899999999821e-2,79543576,13549,null,null,null,null,null,null,null],[4.1628117993241176e-2,4.156500000000207e-2,91594268,14226,null,null,null,null,null,null,null],[3.4839631989598274e-2,3.483499999999928e-2,76648000,14937,null,null,null,null,null,null,null],[4.0510771999834105e-2,4.0502000000001814e-2,89145186,15684,null,null,null,null,null,null,null],[4.9066898005548865e-2,4.8993000000001174e-2,107970840,16469,null,null,null,null,null,null,null],[4.996129099163227e-2,4.992999999999981e-2,109914860,17292,null,null,null,null,null,null,null],[4.562150500714779e-2,4.5588000000000406e-2,100373992,18157,null,null,null,null,null,null,null],[5.468654099968262e-2,5.462799999999923e-2,120316508,19065,null,null,null,null,null,null,null],[5.1227504009148106e-2,5.1217999999998653e-2,112706366,20018,null,null,null,null,null,null,null],[6.129929900635034e-2,6.123000000000012e-2,134874875,21019,null,null,null,null,null,null,null],[5.15769770136103e-2,5.157200000000195e-2,113468473,22070,null,null,null,null,null,null,null],[5.767232697689906e-2,5.761500000000197e-2,126885276,23173,null,null,null,null,null,null,null],[6.247224801336415e-2,6.2433999999999656e-2,137444260,24332,null,null,null,null,null,null,null],[7.516540100914426e-2,7.508400000000037e-2,165396430,25549,null,null,null,null,null,null,null],[7.343321599182673e-2,7.339199999999835e-2,161552540,26826,null,null,null,null,null,null,null],[6.830699602141976e-2,6.825999999999866e-2,150281128,28167,null,null,null,null,null,null,null],[7.023733499227092e-2,7.02039999999986e-2,154528280,29576,null,null,null,null,null,null,null],[8.683017798466608e-2,8.651099999999978e-2,191040034,31054,null,null,null,null,null,null,null],[7.274429200333543e-2,7.274400000000014e-2,160039058,32607,null,null,null,null,null,null,null],[8.211532200220972e-2,8.206700000000033e-2,180662670,34238,null,null,null,null,null,null,null],[8.70943600020837e-2,8.707700000000074e-2,191615170,35950,null,null,null,null,null,null,null],[8.197724600904621e-2,8.196399999999926e-2,180354382,37747,null,null,null,null,null,null,null],[9.827196502010338e-2,9.818399999999983e-2,216206122,39634,null,null,null,null,null,null,null],[0.10549629898741841,0.10542699999999883,232110622,41616,null,null,null,null,null,null,null],[0.1122115509933792,0.11212699999999742,246868720,43697,null,null,null,null,null,null,null],[0.11293111098348163,0.11289100000000118,248455058,45882,null,null,null,null,null,null,null],[0.12375319001148455,0.12366899999999958,272265397,48176,null,null,null,null,null,null,null],[0.13845999402110465,0.138423999999997,304616934,50585,null,null,null,null,null,null,null],[0.133371153002372,0.1332810000000002,293422502,53114,null,null,null,null,null,null,null],[0.14320144298835658,0.14300400000000124,315050006,55770,null,null,null,null,null,null,null],[0.14068631900590844,0.14066700000000054,309516856,58558,null,null,null,null,null,null,null],[0.1589633270050399,0.15887000000000384,349725216,61486,null,null,null,null,null,null,null],[0.2067215590213891,0.2065960000000011,454803626,64561,null,null,null,null,null,null,null],[0.21341353200841695,0.21326900000000037,469514302,67789,null,null,null,null,null,null,null],[0.1625783139897976,0.16252099999999814,357677982,71178,null,null,null,null,null,null,null],[0.18611083400901407,0.18606000000000122,409451766,74737,null,null,null,null,null,null,null],[0.19076346699148417,0.1907389999999971,419684952,78474,null,null,null,null,null,null,null],[0.2057581989793107,0.20567599999999686,452674120,82398,null,null,null,null,null,null,null],[0.23152257202309556,0.231344,509357080,86518,null,null,null,null,null,null,null],[0.23171886400086805,0.23154100000000355,509788352,90843,null,null,null,null,null,null,null]]},{"reportAnalysis":{"anMean":{"estUpperBound":6.668634037917654e-6,"estLowerBound":6.347714383730146e-6,"estPoint":6.496202868182492e-6,"estConfidenceLevel":0.95},"anRegress":[{"regRSquare":{"estUpperBound":0.9955136915306878,"estLowerBound":0.9915361738646395,"estPoint":0.9933084622105373,"estConfidenceLevel":0.95},"regResponder":"time","regCoeffs":{"y":{"estUpperBound":1.604926501967662e-4,"estLowerBound":-8.528224619350055e-4,"estPoint":-3.893843475459815e-4,"estConfidenceLevel":0.95},"iters":{"estUpperBound":6.807397769730118e-6,"estLowerBound":6.364300170847571e-6,"estPoint":6.615936525692066e-6,"estConfidenceLevel":0.95}}}],"anStdDev":{"estUpperBound":6.202125623223447e-7,"estLowerBound":4.0420784296930194e-7,"estPoint":4.919233380857326e-7,"estConfidenceLevel":0.95},"anOutlierVar":{"ovFraction":0.7876656352417168,"ovDesc":"severe","ovEffect":"Severe"},"anOverhead":3.161534180001628e-6},"reportKDEs":[{"kdeValues":[5.516456561449886e-6,5.536462667632315e-6,5.556468773814743e-6,5.576474879997171e-6,5.5964809861796e-6,5.616487092362028e-6,5.636493198544457e-6,5.6564993047268855e-6,5.676505410909314e-6,5.696511517091742e-6,5.7165176232741705e-6,5.736523729456599e-6,5.756529835639028e-6,5.776535941821456e-6,5.796542048003884e-6,5.816548154186313e-6,5.836554260368741e-6,5.85656036655117e-6,5.876566472733598e-6,5.896572578916027e-6,5.916578685098455e-6,5.936584791280883e-6,5.956590897463312e-6,5.9765970036457406e-6,5.996603109828169e-6,6.016609216010597e-6,6.0366153221930255e-6,6.056621428375454e-6,6.076627534557883e-6,6.096633640740311e-6,6.11663974692274e-6,6.136645853105168e-6,6.156651959287596e-6,6.176658065470025e-6,6.1966641716524534e-6,6.216670277834882e-6,6.23667638401731e-6,6.256682490199738e-6,6.276688596382167e-6,6.2966947025645956e-6,6.316700808747024e-6,6.336706914929453e-6,6.356713021111881e-6,6.376719127294309e-6,6.396725233476738e-6,6.416731339659166e-6,6.436737445841595e-6,6.456743552024023e-6,6.476749658206451e-6,6.49675576438888e-6,6.5167618705713085e-6,6.536767976753737e-6,6.556774082936166e-6,6.576780189118594e-6,6.596786295301022e-6,6.616792401483451e-6,6.636798507665879e-6,6.656804613848308e-6,6.6768107200307355e-6,6.696816826213164e-6,6.716822932395593e-6,6.736829038578021e-6,6.75683514476045e-6,6.7768412509428785e-6,6.796847357125307e-6,6.816853463307735e-6,6.8368595694901635e-6,6.856865675672592e-6,6.876871781855021e-6,6.896877888037448e-6,6.916883994219877e-6,6.936890100402306e-6,6.956896206584734e-6,6.976902312767163e-6,6.996908418949591e-6,7.01691452513202e-6,7.036920631314448e-6,7.056926737496876e-6,7.076932843679305e-6,7.0969389498617335e-6,7.116945056044161e-6,7.13695116222659e-6,7.1569572684090185e-6,7.176963374591447e-6,7.196969480773876e-6,7.216975586956304e-6,7.236981693138733e-6,7.256987799321161e-6,7.276993905503589e-6,7.297000011686018e-6,7.317006117868446e-6,7.337012224050875e-6,7.357018330233303e-6,7.377024436415731e-6,7.39703054259816e-6,7.4170366487805886e-6,7.437042754963017e-6,7.457048861145446e-6,7.477054967327874e-6,7.497061073510302e-6,7.517067179692731e-6,7.537073285875159e-6,7.557079392057587e-6,7.577085498240016e-6,7.597091604422444e-6,7.617097710604873e-6,7.637103816787301e-6,7.65710992296973e-6,7.677116029152159e-6,7.697122135334587e-6,7.717128241517016e-6,7.737134347699443e-6,7.757140453881873e-6,7.7771465600643e-6,7.797152666246729e-6,7.817158772429157e-6,7.837164878611586e-6,7.857170984794014e-6,7.877177090976443e-6,7.897183197158872e-6,7.9171893033413e-6,7.937195409523729e-6,7.957201515706156e-6,7.977207621888586e-6,7.997213728071013e-6,8.017219834253441e-6,8.03722594043587e-6,8.057232046618299e-6],"kdeType":"time","kdePDF":[365084.64335106785,365955.49000460893,367690.6797673853,370277.2877736251,373696.1305380558,377922.0056999675,382924.0037781107,388665.8854552148,395106.51664555265,402200.35255211394,409897.9611181589,418146.57573942543,426890.6668376662,436072.5219040203,445632.82389391947,455511.2183772528,465646.8605945285,475978.9345112456,486447.1370630893,496992.1220043202,507555.89906917716,518082.1854886137,528516.7082305428,538807.4566113031,548904.8861232334,558762.0754064709,568334.8392364082,577581.8011816988,586464.4301979609,594947.0458525838,602996.7971260689,610583.6198109,617680.1774414472,624261.7904538356,630306.3579130819,635794.2756787611,640708.3543346924,645033.7396079227,648757.8373728646,651870.244701885,654362.6878061797,656228.967130115,657464.909335084,658068.3254487243,658038.9740719376,657378.5282359902,656090.544288011,654180.4310554129,651655.4174951238,648524.517066855,644798.4871735352,640489.7821779322,635612.4987223883,630182.3123382808,624216.4046224251,617733.3805687939,610753.1759651479,603296.9550859929,595386.9992264116,587046.5869177949,578299.8669386071,569171.7254748241,559687.6489895955,549873.5845255502,539755.7992817654,529360.7413781392,518714.9037404172,507844.6930087706,496776.3052914023,485535.61045374046,474148.0464555006,462638.52502635546,451031.34971078974,439350.14702059305,427617.81111647346,415856.46210739476,404087.4177165369,392331.17772676033,380607.4202962133,368935.0089371603,357332.0086879874,345815.7097894398,334402.65700934996,323108.68265251216,311948.94124848803,300937.94393305253,290089.59062884044,279417.1982857856,268933.5236574748,258650.77935900452,248580.6422662301,238734.2536648964,229122.21092871844,219754.55088508682,210640.72540199192,201789.57008667773,193209.26731245476,184907.30507346542,176890.4333977947,169164.62021918147,161735.00871083967,154605.878118388,147780.61009186218,141261.66241126214,135050.55183037923,129147.84753638429,123553.1764462819,118265.24124583355,113281.851732915,108599.96966709575,104215.76696218607,100124.69669994565,96321.57610163518,92800.68027911366,89555.84530677927,86580.5789163404,83868.17692294557,81411.84334669443,79204.81209937707,77240.46806235048,75512.46538622786,74014.84089396993,72742.1205624549,71689.41718959752,70852.51751998924,70227.95729717045,69813.08293027095,69606.09870228493]}],"reportKeys":["time","cpuTime","cycles","iters","allocated","numGcs","bytesCopied","mutatorWallSeconds","mutatorCpuSeconds","gcWallSeconds","gcCpuSeconds"],"reportNumber":3,"reportName":"fib/11","reportOutliers":{"highSevere":0,"highMild":0,"lowMild":0,"samplesSeen":42,"lowSevere":0},"reportMeasured":[[1.19420001283288e-5,1.100000000064938e-5,16944,1,null,null,null,null,null,null,null],[1.2820994015783072e-5,1.4000000003733248e-5,28392,2,null,null,null,null,null,null,null],[1.8277991330251098e-5,1.8000000000739647e-5,39682,3,null,null,null,null,null,null,null],[2.3559987312182784e-5,2.3000000002326715e-5,51722,4,null,null,null,null,null,null,null],[2.9238988645374775e-5,2.9000000001389026e-5,64328,5,null,null,null,null,null,null,null],[3.453998942859471e-5,3.499999999689862e-5,76036,6,null,null,null,null,null,null,null],[4.0396000258624554e-5,4.0000000002038405e-5,88826,7,null,null,null,null,null,null,null],[4.578699008561671e-5,4.500000000007276e-5,100714,8,null,null,null,null,null,null,null],[5.118001718074083e-5,5.200000000371574e-5,112756,9,null,null,null,null,null,null,null],[5.6882010539993644e-5,5.699999999819738e-5,125390,10,null,null,null,null,null,null,null],[6.255999323911965e-5,6.199999999623174e-5,137390,11,null,null,null,null,null,null,null],[7.794398698024452e-5,7.799999999846818e-5,173504,12,null,null,null,null,null,null,null],[7.340399315580726e-5,7.299999999688112e-5,161570,13,null,null,null,null,null,null,null],[7.913200533948839e-5,7.899999999949614e-5,174244,14,null,null,null,null,null,null,null],[8.437101496383548e-5,8.39999999975305e-5,185760,15,null,null,null,null,null,null,null],[9.023700840771198e-5,9.000000000014552e-5,198712,16,null,null,null,null,null,null,null],[1.033990120049566e-4,1.0400000000032605e-4,229586,17,null,null,null,null,null,null,null],[1.11757981358096e-4,1.1300000000247223e-4,246470,18,null,null,null,null,null,null,null],[1.0994198964908719e-4,1.0899999999836041e-4,241928,19,null,null,null,null,null,null,null],[1.1555801029317081e-4,1.1600000000200339e-4,254432,20,null,null,null,null,null,null,null],[1.28689018310979e-4,1.2899999999760325e-4,284934,21,null,null,null,null,null,null,null],[1.2716499622911215e-4,1.2699999999910005e-4,280038,22,null,null,null,null,null,null,null],[1.3242900604382157e-4,1.3200000000068712e-4,291694,23,null,null,null,null,null,null,null],[1.4399300562217832e-4,1.44999999996287e-4,317112,25,null,null,null,null,null,null,null],[1.5634798910468817e-4,1.5600000000048908e-4,346348,26,null,null,null,null,null,null,null],[1.554309856146574e-4,1.5499999999946112e-4,342524,27,null,null,null,null,null,null,null],[1.6803698963485658e-4,1.679999999986137e-4,371502,28,null,null,null,null,null,null,null],[1.7268001101911068e-4,1.7199999999917281e-4,380334,30,null,null,null,null,null,null,null],[1.779469894245267e-4,1.7799999999823513e-4,392058,31,null,null,null,null,null,null,null],[1.9628097652457654e-4,1.9700000000000273e-4,433818,33,null,null,null,null,null,null,null],[2.0092999329790473e-4,1.9999999999953388e-4,442772,35,null,null,null,null,null,null,null],[2.1330598974600434e-4,2.1399999999971442e-4,471262,36,null,null,null,null,null,null,null],[2.1800599643029273e-4,2.1799999999672082e-4,480482,38,null,null,null,null,null,null,null],[2.3897402570582926e-4,2.3900000000054433e-4,528306,40,null,null,null,null,null,null,null],[2.4080401635728776e-4,2.420000000036282e-4,530676,42,null,null,null,null,null,null,null],[2.5893800193443894e-4,2.589999999997872e-4,571768,44,null,null,null,null,null,null,null],[2.997240226250142e-4,3.010000000003288e-4,663250,47,null,null,null,null,null,null,null],[3.089199890382588e-4,3.090000000049997e-4,682012,49,null,null,null,null,null,null,null],[3.097500011790544e-4,3.109999999999502e-4,683756,52,null,null,null,null,null,null,null],[3.156309830956161e-4,3.149999999969566e-4,696594,54,null,null,null,null,null,null,null],[3.2612000359222293e-4,3.260000000011587e-4,718494,57,null,null,null,null,null,null,null],[3.49440990248695e-4,3.4899999999638e-4,771438,60,null,null,null,null,null,null,null],[3.667880082502961e-4,3.660000000031971e-4,809170,63,null,null,null,null,null,null,null],[3.8382000639103353e-4,3.85000000001412e-4,846746,66,null,null,null,null,null,null,null],[4.006630042567849e-4,4.010000000000957e-4,883716,69,null,null,null,null,null,null,null],[4.2386798304505646e-4,4.230000000013945e-4,934500,73,null,null,null,null,null,null,null],[4.405810032039881e-4,4.409999999985814e-4,971460,76,null,null,null,null,null,null,null],[4.6515799476765096e-4,4.6599999999941133e-4,1025564,80,null,null,null,null,null,null,null],[4.7230199561454356e-4,4.7199999999847364e-4,1041266,84,null,null,null,null,null,null,null],[4.991129972040653e-4,5.000000000023874e-4,1100296,89,null,null,null,null,null,null,null],[5.213140102569014e-4,5.210000000026582e-4,1149148,93,null,null,null,null,null,null,null],[5.576809926424176e-4,5.5799999999806e-4,1229902,98,null,null,null,null,null,null,null],[5.952950159553438e-4,5.950000000005673e-4,1311972,103,null,null,null,null,null,null,null],[6.037959828972816e-4,6.040000000027135e-4,1330994,108,null,null,null,null,null,null,null],[6.543149938806891e-4,6.540000000008206e-4,1441638,113,null,null,null,null,null,null,null],[6.645909743383527e-4,6.649999999979173e-4,1464412,119,null,null,null,null,null,null,null],[7.063759840093553e-4,7.070000000020116e-4,1556890,125,null,null,null,null,null,null,null],[7.781200110912323e-4,7.780000000003895e-4,1715126,131,null,null,null,null,null,null,null],[7.939600036479533e-4,7.939999999990732e-4,1749020,138,null,null,null,null,null,null,null],[8.328559924848378e-4,8.330000000036364e-4,1835106,144,null,null,null,null,null,null,null],[9.031660156324506e-4,9.040000000020143e-4,1989646,152,null,null,null,null,null,null,null],[8.91278003109619e-4,8.92000000000337e-4,1963454,159,null,null,null,null,null,null,null],[9.401720017194748e-4,9.400000000034936e-4,2070960,167,null,null,null,null,null,null,null],[1.0015619918704033e-3,1.0019999999997253e-3,2206250,176,null,null,null,null,null,null,null],[1.0348139912821352e-3,1.0349999999981208e-3,2279112,185,null,null,null,null,null,null,null],[1.0906099923886359e-3,1.089999999997815e-3,2402064,194,null,null,null,null,null,null,null],[1.1836999910883605e-3,1.1849999999995475e-3,2606210,204,null,null,null,null,null,null,null],[1.2615190062206239e-3,1.2590000000010093e-3,2786174,214,null,null,null,null,null,null,null],[2.7388250164221972e-3,2.7400000000028513e-3,6037129,224,null,null,null,null,null,null,null],[2.820530004100874e-3,2.8200000000033754e-3,6210580,236,null,null,null,null,null,null,null],[2.4992660037241876e-3,2.4989999999966983e-3,5502115,247,null,null,null,null,null,null,null],[2.5506530073471367e-3,2.549999999999386e-3,5616196,260,null,null,null,null,null,null,null],[2.2970070131123066e-3,2.2969999999986612e-3,5057468,273,null,null,null,null,null,null,null],[1.6899800102692097e-3,1.6899999999999693e-3,3719422,287,null,null,null,null,null,null,null],[1.6853169945534319e-3,1.685000000001935e-3,3710062,301,null,null,null,null,null,null,null],[1.7685160273686051e-3,1.7689999999959127e-3,3893132,316,null,null,null,null,null,null,null],[1.8841699929907918e-3,1.8840000000039936e-3,4148350,332,null,null,null,null,null,null,null],[1.967624993994832e-3,1.968000000001524e-3,4331382,348,null,null,null,null,null,null,null],[2.070051006739959e-3,2.071000000000822e-3,4557810,366,null,null,null,null,null,null,null],[2.2437869920395315e-3,2.244000000001023e-3,4939180,384,null,null,null,null,null,null,null],[2.3195589892566204e-3,2.3200000000045407e-3,5105946,403,null,null,null,null,null,null,null],[2.407151012448594e-3,2.4070000000016023e-3,5299018,424,null,null,null,null,null,null,null],[2.4934629909694195e-3,2.493999999998664e-3,5488202,445,null,null,null,null,null,null,null],[2.6152189821004868e-3,2.6149999999987017e-3,5756172,467,null,null,null,null,null,null,null],[2.7877530083060265e-3,2.7879999999989025e-3,6135626,490,null,null,null,null,null,null,null],[2.930979011580348e-3,2.9309999999966863e-3,6451144,515,null,null,null,null,null,null,null],[3.0264430097304285e-3,3.026999999999447e-3,6660530,541,null,null,null,null,null,null,null],[3.2948110019788146e-3,3.294000000000352e-3,7251814,568,null,null,null,null,null,null,null],[6.4053990063257515e-3,6.394000000000233e-3,14112053,596,null,null,null,null,null,null,null],[6.478453986346722e-3,6.478999999998791e-3,14255058,626,null,null,null,null,null,null,null],[4.399085009936243e-3,4.400000000000404e-3,9679508,657,null,null,null,null,null,null,null],[3.958804998546839e-3,3.9589999999982695e-3,8695766,690,null,null,null,null,null,null,null],[4.216228990117088e-3,4.216999999997029e-3,9279334,725,null,null,null,null,null,null,null],[4.354687000159174e-3,4.35399999999575e-3,9582880,761,null,null,null,null,null,null,null],[4.501119983615354e-3,4.5010000000011985e-3,9905912,799,null,null,null,null,null,null,null],[4.693536990089342e-3,4.694000000000642e-3,10328432,839,null,null,null,null,null,null,null],[5.079226975794882e-3,5.079000000002054e-3,11177696,881,null,null,null,null,null,null,null],[5.232052004430443e-3,5.232000000003012e-3,11513176,925,null,null,null,null,null,null,null],[5.49678600509651e-3,5.4970000000018615e-3,12096228,972,null,null,null,null,null,null,null],[5.7394739997107536e-3,5.738999999998384e-3,12629984,1020,null,null,null,null,null,null,null],[1.1832910007797182e-2,1.1796000000003914e-2,26047836,1071,null,null,null,null,null,null,null],[8.19906999822706e-3,8.198999999997625e-3,18038404,1125,null,null,null,null,null,null,null],[1.2609456985956058e-2,1.2579999999999814e-2,27754164,1181,null,null,null,null,null,null,null],[7.599675009259954e-3,7.600000000000051e-3,16720070,1240,null,null,null,null,null,null,null],[1.6028228012146428e-2,1.601399999999842e-2,35279046,1302,null,null,null,null,null,null,null],[1.1054695001803339e-2,1.1053999999997899e-2,24319994,1367,null,null,null,null,null,null,null],[8.091145980870351e-3,8.091000000000292e-3,17803348,1436,null,null,null,null,null,null,null],[8.520992007106543e-3,8.49099999999936e-3,18749474,1507,null,null,null,null,null,null,null],[8.926548005547374e-3,8.926999999996355e-3,19641570,1583,null,null,null,null,null,null,null],[9.448324999539182e-3,9.426000000001267e-3,20790340,1662,null,null,null,null,null,null,null],[9.836914017796516e-3,9.837000000000984e-3,21644446,1745,null,null,null,null,null,null,null],[1.0448998975334689e-2,1.044899999999771e-2,22991020,1832,null,null,null,null,null,null,null],[1.1087464983575046e-2,1.1088000000000875e-2,24395736,1924,null,null,null,null,null,null,null],[1.1767855001380667e-2,1.1768999999997476e-2,25892502,2020,null,null,null,null,null,null,null],[1.8973044003359973e-2,1.8944999999998657e-2,41748136,2121,null,null,null,null,null,null,null],[1.3305653992574662e-2,1.3276999999998651e-2,29280832,2227,null,null,null,null,null,null,null],[1.4363627997227013e-2,1.4362999999995907e-2,31603222,2339,null,null,null,null,null,null,null],[1.5047146996948868e-2,1.5046999999995592e-2,33106548,2456,null,null,null,null,null,null,null],[1.5299685997888446e-2,1.5298999999998841e-2,33663090,2579,null,null,null,null,null,null,null],[1.625170899205841e-2,1.6251999999997935e-2,35756926,2708,null,null,null,null,null,null,null],[1.6641148016788065e-2,1.6639999999998878e-2,36613858,2843,null,null,null,null,null,null,null],[2.9095820005750284e-2,2.9052999999997553e-2,64018498,2985,null,null,null,null,null,null,null],[1.782830199226737e-2,1.7825000000001978e-2,39229460,3134,null,null,null,null,null,null,null],[1.8584322009701282e-2,1.8580999999997516e-2,40888542,3291,null,null,null,null,null,null,null],[1.9624890002887696e-2,1.9597000000000975e-2,43178448,3456,null,null,null,null,null,null,null],[2.060321602039039e-2,2.0603999999998734e-2,45331722,3629,null,null,null,null,null,null,null],[2.4888608983019367e-2,2.4851000000001733e-2,54775375,3810,null,null,null,null,null,null,null],[2.6372749009169638e-2,2.6371999999998508e-2,58019509,4001,null,null,null,null,null,null,null],[2.4860880977939814e-2,2.48609999999978e-2,54697508,4201,null,null,null,null,null,null,null],[3.230335199623369e-2,3.2272999999999996e-2,71075466,4411,null,null,null,null,null,null,null],[2.7945836016442627e-2,2.7947000000001054e-2,61483632,4631,null,null,null,null,null,null,null],[2.8607924992684275e-2,2.8607999999998412e-2,62941524,4863,null,null,null,null,null,null,null],[3.784891200484708e-2,3.781399999999735e-2,83274606,5106,null,null,null,null,null,null,null],[3.114457501214929e-2,3.114400000000117e-2,68520162,5361,null,null,null,null,null,null,null],[3.81150130124297e-2,3.8105999999999085e-2,83865052,5629,null,null,null,null,null,null,null],[4.0344114997424185e-2,4.028300000000229e-2,88766724,5911,null,null,null,null,null,null,null],[4.1936466994229704e-2,4.193100000000172e-2,92265938,6207,null,null,null,null,null,null,null],[3.819815398310311e-2,3.8198000000001286e-2,84039102,6517,null,null,null,null,null,null,null],[4.4795522990170866e-2,4.479100000000358e-2,98561988,6843,null,null,null,null,null,null,null],[4.483502599759959e-2,4.4818999999996834e-2,98638784,7185,null,null,null,null,null,null,null],[4.459751900867559e-2,4.459800000000058e-2,98118968,7544,null,null,null,null,null,null,null],[5.219911300810054e-2,5.216699999999719e-2,114848494,7921,null,null,null,null,null,null,null],[4.9044923012843356e-2,4.9045999999997036e-2,107901480,8318,null,null,null,null,null,null,null],[5.627081400598399e-2,5.623899999999793e-2,123803358,8733,null,null,null,null,null,null,null],[5.9109914989676327e-2,5.908600000000064e-2,130050316,9170,null,null,null,null,null,null,null],[5.6396361003862694e-2,5.639699999999692e-2,124075160,9629,null,null,null,null,null,null,null],[6.598068098537624e-2,6.595199999999934e-2,145164160,10110,null,null,null,null,null,null,null],[6.0812023002654314e-2,6.081299999999601e-2,133789582,10616,null,null,null,null,null,null,null],[7.374249398708344e-2,7.368299999999905e-2,162239292,11146,null,null,null,null,null,null,null],[6.807770600426011e-2,6.807900000000444e-2,149773732,11704,null,null,null,null,null,null,null],[7.960463801282458e-2,7.95600000000043e-2,175137678,12289,null,null,null,null,null,null,null],[0.10123207702417858,0.10112399999999866,222717630,12903,null,null,null,null,null,null,null],[8.555627497844398e-2,8.551399999999987e-2,188229906,13549,null,null,null,null,null,null,null],[9.03350849985145e-2,9.030399999999972e-2,198744208,14226,null,null,null,null,null,null,null],[9.294863900868222e-2,9.287099999999882e-2,204500974,14937,null,null,null,null,null,null,null],[0.1069848730112426,0.10691300000000226,235371716,15684,null,null,null,null,null,null,null],[0.10382141199079342,0.10372500000000073,228413170,16469,null,null,null,null,null,null,null],[0.11392678300035186,0.11385299999999887,250646416,17292,null,null,null,null,null,null,null],[0.11803226202027872,0.11797100000000071,259677136,18157,null,null,null,null,null,null,null],[0.11511843200423755,0.11508900000000111,253276939,19065,null,null,null,null,null,null,null],[0.12226728399400599,0.12199500000000185,268993077,20018,null,null,null,null,null,null,null],[0.13388311900780536,0.133782999999994,294549236,21019,null,null,null,null,null,null,null],[0.15753770200535655,0.15747500000000159,346590682,22070,null,null,null,null,null,null,null],[0.15844429598655552,0.15832499999999783,348586922,23173,null,null,null,null,null,null,null],[0.14716985099948943,0.14712199999999598,323779030,24332,null,null,null,null,null,null,null],[0.1584885419870261,0.1583970000000008,348684024,25549,null,null,null,null,null,null,null],[0.18314656100119464,0.1830260000000017,402931052,26826,null,null,null,null,null,null,null],[0.17360069099231623,0.17351400000000083,381927764,28167,null,null,null,null,null,null,null],[0.21337309398222715,0.21314599999999828,469427278,29576,null,null,null,null,null,null,null],[0.22101753499009646,0.2208749999999995,486249474,31054,null,null,null,null,null,null,null],[0.19837291300063953,0.19831999999999894,436431460,32607,null,null,null,null,null,null,null],[0.2344874179980252,0.23431000000000068,515879454,34238,null,null,null,null,null,null,null],[0.25332475802861154,0.2530089999999987,557328324,35950,null,null,null,null,null,null,null]]}];
681−- reports.map(mangulate);
682−-
683−- var benches = ["fib/1","fib/5","fib/9","fib/11",];
684−- var ylabels = [[-0,'<a href="#b0">fib/1</a>'],[-1,'<a href="#b1">fib/5</a>'],[-2,'<a href="#b2">fib/9</a>'],[-3,'<a href="#b3">fib/11</a>'],];
685−- var means = $.scaleTimes([2.374225969306158e-8,3.7647973827317373e-7,2.614524699113428e-6,6.496202868182492e-6,]);
686−- var xs = [];
687−- var prev = null;
688−- for (var i = 0; i < means[0].length; i++) {
689−- var name = benches[i].split(/\//);
690−- name.pop();
691−- name = name.join('/');
692−- if (name != prev) {
693−- xs.push({ label: name, data: [[means[0][i], -i]]});
694−- prev = name;
695−- }
696−- else
697−- xs[xs.length-1].data.push([means[0][i],-i]);
698−- }
699−- var oq = $("#overview");
700−- o = $.plot(oq, xs, { bars: { show: true, horizontal: true,
701−- barWidth: 0.75, align: "center" },
702−- grid: { borderColor: "#777", hoverable: true },
703−- legend: { show: xs.length > 1 },
704−- xaxis: { max: Math.max.apply(undefined,means[0]) * 1.02 },
705−- yaxis: { ticks: ylabels, tickColor: '#ffffff' } });
706−- if (benches.length > 3)
707−- o.getPlaceholder().height(28*benches.length);
708−- o.resize();
709−- o.setupGrid();
710−- o.draw();
711−- $.addTooltip("#overview", function(x,y) { return $.renderTime(x / means[1]); });
712−-});
713−-$(document).ready(function () {
714−- $(".time").text(function(_, text) {
715−- return $.renderTime(text);
716−- });
717−- $(".citime").text(function(_, text) {
718−- return $.renderTime(text);
719−- });
720−- $(".percent").text(function(_, text) {
721−- return (text*100).toFixed(1);
722−- });
723−- });
724−-</script>
725−-
726−- </div>
727−- </div>
728−- <div id="footer">
729−- <div class="body">
730−- <div class="footfirst">
731−- <h2>colophon</h2>
732−- <p>This report was created using the
733−- <a href="http://hackage.haskell.org/package/criterion">criterion</a>
734−- benchmark execution and performance analysis tool.</p>
735−- <p>Criterion is developed and maintained
736−- by <a href="http://www.serpentine.com/blog/">Bryan O'Sullivan</a>.</p>
737−- </div>
738−- </div>
739−- </div>
740−- </body>
741−-</html>
742−diff -ruN orig/examples/maps.html new/examples/maps.html
743−--- orig/examples/maps.html 2014-08-10 20:30:05.789809138 +0300
744−+++ new/examples/maps.html 1970-01-01 02:00:00.000000000 +0200
745−@@ -1,552 +0,0 @@
746−-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
747−-<html>
748−- <head>
749−- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
750−- <title>criterion report</title>
751−- <script language="javascript" type="text/javascript">
752−- /*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
753−-!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.1",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="<select msallowclip=''><option selected=''></option></select>",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+Math.random()}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)
754−-},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ab=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ib={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wb=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var zb=/^(none|table(?!-c[ea]).+)/,Ab=new RegExp("^("+Q+")(.*)$","i"),Bb=new RegExp("^([+-])=("+Q+")","i"),Cb={position:"absolute",visibility:"hidden",display:"block"},Db={letterSpacing:"0",fontWeight:"400"},Eb=["Webkit","O","Moz","ms"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Hb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ib(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?"border":"content"),d,f)+"px"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",tb(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),"normal"===e&&b in Db&&(e=Db[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pb=/queueHooks$/,Qb=[Vb],Rb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Ob.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||tb(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?tb(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb("show"),slideUp:Tb("hide"),slideToggle:Tb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Lb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Mb||(Mb=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Mb),Mb=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Yb,Zb,$b=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))
755−-},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cc=n.now(),dc=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var ec,fc,gc=/#.*$/,hc=/([?&])_=[^&]*/,ic=/^(.*?):[ \t]*([^\r\n]*)$/gm,jc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,kc=/^(?:GET|HEAD)$/,lc=/^\/\//,mc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,nc={},oc={},pc="*/".concat("*");try{fc=location.href}catch(qc){fc=l.createElement("a"),fc.href="",fc=fc.href}ec=mc.exec(fc.toLowerCase())||[];function rc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function sc(a,b,c,d){var e={},f=a===oc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function tc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function uc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function vc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:fc,type:"GET",isLocal:jc.test(ec[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":pc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?tc(tc(a,n.ajaxSettings),b):tc(n.ajaxSettings,a)},ajaxPrefilter:rc(nc),ajaxTransport:rc(oc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=ic.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||fc)+"").replace(gc,"").replace(lc,ec[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=mc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===ec[1]&&h[2]===ec[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(ec[3]||("http:"===ec[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),sc(nc,k,b,v),2===t)return v;i=k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!kc.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=hc.test(d)?d.replace(hc,"$1_="+cc++):d+(dc.test(d)?"&":"?")+"_="+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+pc+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=sc(oc,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=uc(k,v,f)),u=vc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var wc=/%20/g,xc=/\[\]$/,yc=/\r?\n/g,zc=/^(?:submit|button|image|reset|file)$/i,Ac=/^(?:input|select|textarea|keygen)/i;function Bc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||xc.test(a)?d(a,e):Bc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Bc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Bc(c,a[c],b,e);return d.join("&").replace(wc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Ac.test(this.nodeName)&&!zc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(yc,"\r\n")}}):{name:b.name,value:c.replace(yc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Cc=0,Dc={},Ec={0:200,1223:204},Fc=n.ajaxSettings.xhr();a.ActiveXObject&&n(a).on("unload",function(){for(var a in Dc)Dc[a]()}),k.cors=!!Fc&&"withCredentials"in Fc,k.ajax=Fc=!!Fc,n.ajaxTransport(function(a){var b;return k.cors||Fc&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Cc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Dc[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Ec[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Dc[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Gc=[],Hc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Gc.pop()||n.expando+"_"+cc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Hc.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Hc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Hc,"$1"+e):b.jsonp!==!1&&(b.url+=(dc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Gc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Ic=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Ic)return Ic.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Jc=a.document.documentElement;function Kc(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Kc(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Jc;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Jc})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Kc(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=yb(k.pixelPosition,function(a,c){return c?(c=xb(a,b),vb.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Lc=a.jQuery,Mc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Mc),b&&a.jQuery===n&&(a.jQuery=Lc),n},typeof b===U&&(a.jQuery=a.$=n),n});
756−-
757−- </script>
758−- <script language="javascript" type="text/javascript">
759−- /* Javascript plotting library for jQuery, version 0.8.3.
760−-
761−-Copyright (c) 2007-2014 IOLA and Ole Laursen.
762−-Licensed under the MIT license.
763−-
764−-*/
765−-(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);(function($){var hasOwnProperty=Object.prototype.hasOwnProperty;if(!$.fn.detach){$.fn.detach=function(){return this.each(function(){if(this.parentNode){this.parentNode.removeChild(this)}})}}function Canvas(cls,container){var element=container.children("."+cls)[0];if(element==null){element=document.createElement("canvas");element.className=cls;$(element).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(container);if(!element.getContext){if(window.G_vmlCanvasManager){element=window.G_vmlCanvasManager.initElement(element)}else{throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.")}}}this.element=element;var context=this.context=element.getContext("2d");var devicePixelRatio=window.devicePixelRatio||1,backingStoreRatio=context.webkitBackingStorePixelRatio||context.mozBackingStorePixelRatio||context.msBackingStorePixelRatio||context.oBackingStorePixelRatio||context.backingStorePixelRatio||1;this.pixelRatio=devicePixelRatio/backingStoreRatio;this.resize(container.width(),container.height());this.textContainer=null;this.text={};this._textCache={}}Canvas.prototype.resize=function(width,height){if(width<=0||height<=0){throw new Error("Invalid dimensions for plot, width = "+width+", height = "+height)}var element=this.element,context=this.context,pixelRatio=this.pixelRatio;if(this.width!=width){element.width=width*pixelRatio;element.style.width=width+"px";this.width=width}if(this.height!=height){element.height=height*pixelRatio;element.style.height=height+"px";this.height=height}context.restore();context.save();context.scale(pixelRatio,pixelRatio)};Canvas.prototype.clear=function(){this.context.clearRect(0,0,this.width,this.height)};Canvas.prototype.render=function(){var cache=this._textCache;for(var layerKey in cache){if(hasOwnProperty.call(cache,layerKey)){var layer=this.getTextLayer(layerKey),layerCache=cache[layerKey];layer.hide();for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){if(position.active){if(!position.rendered){layer.append(position.element);position.rendered=true}}else{positions.splice(i--,1);if(position.rendered){position.element.detach()}}}if(positions.length==0){delete styleCache[key]}}}}}layer.show()}}};Canvas.prototype.getTextLayer=function(classes){var layer=this.text[classes];if(layer==null){if(this.textContainer==null){this.textContainer=$("<div class='flot-text'></div>").css({position:"absolute",top:0,left:0,bottom:0,right:0,"font-size":"smaller",color:"#545454"}).insertAfter(this.element)}layer=this.text[classes]=$("<div></div>").addClass(classes).css({position:"absolute",top:0,left:0,bottom:0,right:0}).appendTo(this.textContainer)}return layer};Canvas.prototype.getTextInfo=function(layer,text,font,angle,width){var textStyle,layerCache,styleCache,info;text=""+text;if(typeof font==="object"){textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px/"+font.lineHeight+"px "+font.family}else{textStyle=font}layerCache=this._textCache[layer];if(layerCache==null){layerCache=this._textCache[layer]={}}styleCache=layerCache[textStyle];if(styleCache==null){styleCache=layerCache[textStyle]={}}info=styleCache[text];if(info==null){var element=$("<div></div>").html(text).css({position:"absolute","max-width":width,top:-9999}).appendTo(this.getTextLayer(layer));if(typeof font==="object"){element.css({font:textStyle,color:font.color})}else if(typeof font==="string"){element.addClass(font)}info=styleCache[text]={width:element.outerWidth(true),height:element.outerHeight(true),element:element,positions:[]};element.detach()}return info};Canvas.prototype.addText=function(layer,x,y,text,font,angle,width,halign,valign){var info=this.getTextInfo(layer,text,font,angle,width),positions=info.positions;if(halign=="center"){x-=info.width/2}else if(halign=="right"){x-=info.width}if(valign=="middle"){y-=info.height/2}else if(valign=="bottom"){y-=info.height}for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=true;return}}position={active:true,rendered:false,element:positions.length?info.element.clone():info.element,x:x,y:y};positions.push(position);position.element.css({top:Math.round(y),left:Math.round(x),"text-align":halign})};Canvas.prototype.removeText=function(layer,x,y,text,font,angle){if(text==null){var layerCache=this._textCache[layer];if(layerCache!=null){for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){position.active=false}}}}}}}else{var positions=this.getTextInfo(layer,text,font,angle).positions;for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=false}}}};function Plot(placeholder,data_,options_,plugins){var series=[],options={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:.85,sorted:null},xaxis:{show:null,position:"bottom",mode:null,font:null,color:null,tickColor:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,reserveSpace:null,tickLength:null,alignTicksWithAxis:null,tickDecimals:null,tickSize:null,minTickSize:null},yaxis:{autoscaleMargin:.02,position:"left"},xaxes:[],yaxes:[],series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff",symbol:"circle"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false,zero:true},shadowSize:3,highlightColor:null},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,borderColor:null,tickColor:null,margin:0,labelMargin:5,axisMargin:8,borderWidth:2,minBorderMargin:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},interaction:{redrawOverlayInterval:1e3/60},hooks:{}},surface=null,overlay=null,eventHolder=null,ctx=null,octx=null,xaxes=[],yaxes=[],plotOffset={left:0,right:0,top:0,bottom:0},plotWidth=0,plotHeight=0,hooks={processOptions:[],processRawData:[],processDatapoints:[],processOffset:[],drawBackground:[],drawSeries:[],draw:[],bindEvents:[],drawOverlay:[],shutdown:[]},plot=this;plot.setData=setData;plot.setupGrid=setupGrid;plot.draw=draw;plot.getPlaceholder=function(){return placeholder};plot.getCanvas=function(){return surface.element};plot.getPlotOffset=function(){return plotOffset};plot.width=function(){return plotWidth};plot.height=function(){return plotHeight};plot.offset=function(){var o=eventHolder.offset();o.left+=plotOffset.left;o.top+=plotOffset.top;return o};plot.getData=function(){return series};plot.getAxes=function(){var res={},i;$.each(xaxes.concat(yaxes),function(_,axis){if(axis)res[axis.direction+(axis.n!=1?axis.n:"")+"axis"]=axis});return res};plot.getXAxes=function(){return xaxes};plot.getYAxes=function(){return yaxes};plot.c2p=canvasToAxisCoords;plot.p2c=axisToCanvasCoords;plot.getOptions=function(){return options};plot.highlight=highlight;plot.unhighlight=unhighlight;plot.triggerRedrawOverlay=triggerRedrawOverlay;plot.pointOffset=function(point){return{left:parseInt(xaxes[axisNumber(point,"x")-1].p2c(+point.x)+plotOffset.left,10),top:parseInt(yaxes[axisNumber(point,"y")-1].p2c(+point.y)+plotOffset.top,10)}};plot.shutdown=shutdown;plot.destroy=function(){shutdown();placeholder.removeData("plot").empty();series=[];options=null;surface=null;overlay=null;eventHolder=null;ctx=null;octx=null;xaxes=[];yaxes=[];hooks=null;highlights=[];plot=null};plot.resize=function(){var width=placeholder.width(),height=placeholder.height();surface.resize(width,height);overlay.resize(width,height)};plot.hooks=hooks;initPlugins(plot);parseOptions(options_);setupCanvases();setData(data_);setupGrid();draw();bindEvents();function executeHooks(hook,args){args=[plot].concat(args);for(var i=0;i<hook.length;++i)hook[i].apply(this,args)}function initPlugins(){var classes={Canvas:Canvas};for(var i=0;i<plugins.length;++i){var p=plugins[i];p.init(plot,classes);if(p.options)$.extend(true,options,p.options)}}function parseOptions(opts){$.extend(true,options,opts);if(opts&&opts.colors){options.colors=opts.colors}if(options.xaxis.color==null)options.xaxis.color=$.color.parse(options.grid.color).scale("a",.22).toString();if(options.yaxis.color==null)options.yaxis.color=$.color.parse(options.grid.color).scale("a",.22).toString();if(options.xaxis.tickColor==null)options.xaxis.tickColor=options.grid.tickColor||options.xaxis.color;if(options.yaxis.tickColor==null)options.yaxis.tickColor=options.grid.tickColor||options.yaxis.color;if(options.grid.borderColor==null)options.grid.borderColor=options.grid.color;if(options.grid.tickColor==null)options.grid.tickColor=$.color.parse(options.grid.color).scale("a",.22).toString();var i,axisOptions,axisCount,fontSize=placeholder.css("font-size"),fontSizeDefault=fontSize?+fontSize.replace("px",""):13,fontDefaults={style:placeholder.css("font-style"),size:Math.round(.8*fontSizeDefault),variant:placeholder.css("font-variant"),weight:placeholder.css("font-weight"),family:placeholder.css("font-family")};axisCount=options.xaxes.length||1;for(i=0;i<axisCount;++i){axisOptions=options.xaxes[i];if(axisOptions&&!axisOptions.tickColor){axisOptions.tickColor=axisOptions.color}axisOptions=$.extend(true,{},options.xaxis,axisOptions);options.xaxes[i]=axisOptions;if(axisOptions.font){axisOptions.font=$.extend({},fontDefaults,axisOptions.font);if(!axisOptions.font.color){axisOptions.font.color=axisOptions.color}if(!axisOptions.font.lineHeight){axisOptions.font.lineHeight=Math.round(axisOptions.font.size*1.15)}}}axisCount=options.yaxes.length||1;for(i=0;i<axisCount;++i){axisOptions=options.yaxes[i];if(axisOptions&&!axisOptions.tickColor){axisOptions.tickColor=axisOptions.color}axisOptions=$.extend(true,{},options.yaxis,axisOptions);options.yaxes[i]=axisOptions;if(axisOptions.font){axisOptions.font=$.extend({},fontDefaults,axisOptions.font);if(!axisOptions.font.color){axisOptions.font.color=axisOptions.color}if(!axisOptions.font.lineHeight){axisOptions.font.lineHeight=Math.round(axisOptions.font.size*1.15)}}}if(options.xaxis.noTicks&&options.xaxis.ticks==null)options.xaxis.ticks=options.xaxis.noTicks;if(options.yaxis.noTicks&&options.yaxis.ticks==null)options.yaxis.ticks=options.yaxis.noTicks;if(options.x2axis){options.xaxes[1]=$.extend(true,{},options.xaxis,options.x2axis);options.xaxes[1].position="top";if(options.x2axis.min==null){options.xaxes[1].min=null}if(options.x2axis.max==null){options.xaxes[1].max=null}}if(options.y2axis){options.yaxes[1]=$.extend(true,{},options.yaxis,options.y2axis);options.yaxes[1].position="right";if(options.y2axis.min==null){options.yaxes[1].min=null}if(options.y2axis.max==null){options.yaxes[1].max=null}}if(options.grid.coloredAreas)options.grid.markings=options.grid.coloredAreas;if(options.grid.coloredAreasColor)options.grid.markingsColor=options.grid.coloredAreasColor;if(options.lines)$.extend(true,options.series.lines,options.lines);if(options.points)$.extend(true,options.series.points,options.points);if(options.bars)$.extend(true,options.series.bars,options.bars);if(options.shadowSize!=null)options.series.shadowSize=options.shadowSize;if(options.highlightColor!=null)options.series.highlightColor=options.highlightColor;for(i=0;i<options.xaxes.length;++i)getOrCreateAxis(xaxes,i+1).options=options.xaxes[i];for(i=0;i<options.yaxes.length;++i)getOrCreateAxis(yaxes,i+1).options=options.yaxes[i];for(var n in hooks)if(options.hooks[n]&&options.hooks[n].length)hooks[n]=hooks[n].concat(options.hooks[n]);executeHooks(hooks.processOptions,[options])}function setData(d){series=parseData(d);fillInSeriesOptions();processData()}function parseData(d){var res=[];for(var i=0;i<d.length;++i){var s=$.extend(true,{},options.series);if(d[i].data!=null){s.data=d[i].data;delete d[i].data;$.extend(true,s,d[i]);d[i].data=s.data}else s.data=d[i];res.push(s)}return res}function axisNumber(obj,coord){var a=obj[coord+"axis"];if(typeof a=="object")a=a.n;if(typeof a!="number")a=1;return a}function allAxes(){return $.grep(xaxes.concat(yaxes),function(a){return a})}function canvasToAxisCoords(pos){var res={},i,axis;for(i=0;i<xaxes.length;++i){axis=xaxes[i];if(axis&&axis.used)res["x"+axis.n]=axis.c2p(pos.left)}for(i=0;i<yaxes.length;++i){axis=yaxes[i];if(axis&&axis.used)res["y"+axis.n]=axis.c2p(pos.top)}if(res.x1!==undefined)res.x=res.x1;if(res.y1!==undefined)res.y=res.y1;return res}function axisToCanvasCoords(pos){var res={},i,axis,key;for(i=0;i<xaxes.length;++i){axis=xaxes[i];if(axis&&axis.used){key="x"+axis.n;if(pos[key]==null&&axis.n==1)key="x";if(pos[key]!=null){res.left=axis.p2c(pos[key]);break}}}for(i=0;i<yaxes.length;++i){axis=yaxes[i];if(axis&&axis.used){key="y"+axis.n;if(pos[key]==null&&axis.n==1)key="y";if(pos[key]!=null){res.top=axis.p2c(pos[key]);break}}}return res}function getOrCreateAxis(axes,number){if(!axes[number-1])axes[number-1]={n:number,direction:axes==xaxes?"x":"y",options:$.extend(true,{},axes==xaxes?options.xaxis:options.yaxis)};return axes[number-1]}function fillInSeriesOptions(){var neededColors=series.length,maxIndex=-1,i;for(i=0;i<series.length;++i){var sc=series[i].color;if(sc!=null){neededColors--;if(typeof sc=="number"&&sc>maxIndex){maxIndex=sc}}}if(neededColors<=maxIndex){neededColors=maxIndex+1}var c,colors=[],colorPool=options.colors,colorPoolSize=colorPool.length,variation=0;for(i=0;i<neededColors;i++){c=$.color.parse(colorPool[i%colorPoolSize]||"#666");if(i%colorPoolSize==0&&i){if(variation>=0){if(variation<.5){variation=-variation-.2}else variation=0}else variation=-variation}colors[i]=c.scale("rgb",1+variation)}var colori=0,s;for(i=0;i<series.length;++i){s=series[i];if(s.color==null){s.color=colors[colori].toString();++colori}else if(typeof s.color=="number")s.color=colors[s.color].toString();if(s.lines.show==null){var v,show=true;for(v in s)if(s[v]&&s[v].show){show=false;break}if(show)s.lines.show=true}if(s.lines.zero==null){s.lines.zero=!!s.lines.fill}s.xaxis=getOrCreateAxis(xaxes,axisNumber(s,"x"));s.yaxis=getOrCreateAxis(yaxes,axisNumber(s,"y"))}}function processData(){var topSentry=Number.POSITIVE_INFINITY,bottomSentry=Number.NEGATIVE_INFINITY,fakeInfinity=Number.MAX_VALUE,i,j,k,m,length,s,points,ps,x,y,axis,val,f,p,data,format;function updateAxis(axis,min,max){if(min<axis.datamin&&min!=-fakeInfinity)axis.datamin=min;if(max>axis.datamax&&max!=fakeInfinity)axis.datamax=max}$.each(allAxes(),function(_,axis){axis.datamin=topSentry;axis.datamax=bottomSentry;axis.used=false});for(i=0;i<series.length;++i){s=series[i];s.datapoints={points:[]};executeHooks(hooks.processRawData,[s,s.data,s.datapoints])}for(i=0;i<series.length;++i){s=series[i];data=s.data;format=s.datapoints.format;if(!format){format=[];format.push({x:true,number:true,required:true});format.push({y:true,number:true,required:true});if(s.bars.show||s.lines.show&&s.lines.fill){var autoscale=!!(s.bars.show&&s.bars.zero||s.lines.show&&s.lines.zero);format.push({y:true,number:true,required:false,defaultValue:0,autoscale:autoscale});if(s.bars.horizontal){delete format[format.length-1].y;format[format.length-1].x=true}}s.datapoints.format=format}if(s.datapoints.pointsize!=null)continue;s.datapoints.pointsize=format.length;ps=s.datapoints.pointsize;points=s.datapoints.points;var insertSteps=s.lines.show&&s.lines.steps;s.xaxis.used=s.yaxis.used=true;for(j=k=0;j<data.length;++j,k+=ps){p=data[j];var nullify=p==null;if(!nullify){for(m=0;m<ps;++m){val=p[m];f=format[m];if(f){if(f.number&&val!=null){val=+val;if(isNaN(val))val=null;else if(val==Infinity)val=fakeInfinity;else if(val==-Infinity)val=-fakeInfinity}if(val==null){if(f.required)nullify=true;if(f.defaultValue!=null)val=f.defaultValue}}points[k+m]=val}}if(nullify){for(m=0;m<ps;++m){val=points[k+m];if(val!=null){f=format[m];if(f.autoscale!==false){if(f.x){updateAxis(s.xaxis,val,val)}if(f.y){updateAxis(s.yaxis,val,val)}}}points[k+m]=null}}else{if(insertSteps&&k>0&&points[k-ps]!=null&&points[k-ps]!=points[k]&&points[k-ps+1]!=points[k+1]){for(m=0;m<ps;++m)points[k+ps+m]=points[k+m];points[k+1]=points[k-ps+1];k+=ps}}}}for(i=0;i<series.length;++i){s=series[i];executeHooks(hooks.processDatapoints,[s,s.datapoints])}for(i=0;i<series.length;++i){s=series[i];points=s.datapoints.points;ps=s.datapoints.pointsize;format=s.datapoints.format;var xmin=topSentry,ymin=topSentry,xmax=bottomSentry,ymax=bottomSentry;for(j=0;j<points.length;j+=ps){if(points[j]==null)continue;for(m=0;m<ps;++m){val=points[j+m];f=format[m];if(!f||f.autoscale===false||val==fakeInfinity||val==-fakeInfinity)continue;if(f.x){if(val<xmin)xmin=val;if(val>xmax)xmax=val}if(f.y){if(val<ymin)ymin=val;if(val>ymax)ymax=val}}}if(s.bars.show){var delta;switch(s.bars.align){case"left":delta=0;break;case"right":delta=-s.bars.barWidth;break;default:delta=-s.bars.barWidth/2}if(s.bars.horizontal){ymin+=delta;ymax+=delta+s.bars.barWidth}else{xmin+=delta;xmax+=delta+s.bars.barWidth}}updateAxis(s.xaxis,xmin,xmax);updateAxis(s.yaxis,ymin,ymax)}$.each(allAxes(),function(_,axis){if(axis.datamin==topSentry)axis.datamin=null;if(axis.datamax==bottomSentry)axis.datamax=null})}function setupCanvases(){placeholder.css("padding",0).children().filter(function(){return!$(this).hasClass("flot-overlay")&&!$(this).hasClass("flot-base")}).remove();if(placeholder.css("position")=="static")placeholder.css("position","relative");surface=new Canvas("flot-base",placeholder);overlay=new Canvas("flot-overlay",placeholder);ctx=surface.context;octx=overlay.context;eventHolder=$(overlay.element).unbind();var existing=placeholder.data("plot");if(existing){existing.shutdown();overlay.clear()}placeholder.data("plot",plot)}function bindEvents(){if(options.grid.hoverable){eventHolder.mousemove(onMouseMove);eventHolder.bind("mouseleave",onMouseLeave)}if(options.grid.clickable)eventHolder.click(onClick);executeHooks(hooks.bindEvents,[eventHolder])}function shutdown(){if(redrawTimeout)clearTimeout(redrawTimeout);eventHolder.unbind("mousemove",onMouseMove);eventHolder.unbind("mouseleave",onMouseLeave);eventHolder.unbind("click",onClick);executeHooks(hooks.shutdown,[eventHolder])}function setTransformationHelpers(axis){function identity(x){return x}var s,m,t=axis.options.transform||identity,it=axis.options.inverseTransform;if(axis.direction=="x"){s=axis.scale=plotWidth/Math.abs(t(axis.max)-t(axis.min));m=Math.min(t(axis.max),t(axis.min))}else{s=axis.scale=plotHeight/Math.abs(t(axis.max)-t(axis.min));s=-s;m=Math.max(t(axis.max),t(axis.min))}if(t==identity)axis.p2c=function(p){return(p-m)*s};else axis.p2c=function(p){return(t(p)-m)*s};if(!it)axis.c2p=function(c){return m+c/s};else axis.c2p=function(c){return it(m+c/s)}}function measureTickLabels(axis){var opts=axis.options,ticks=axis.ticks||[],labelWidth=opts.labelWidth||0,labelHeight=opts.labelHeight||0,maxWidth=labelWidth||(axis.direction=="x"?Math.floor(surface.width/(ticks.length||1)):null),legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=opts.font||"flot-tick-label tickLabel";for(var i=0;i<ticks.length;++i){var t=ticks[i];if(!t.label)continue;var info=surface.getTextInfo(layer,t.label,font,null,maxWidth);labelWidth=Math.max(labelWidth,info.width);labelHeight=Math.max(labelHeight,info.height)}axis.labelWidth=opts.labelWidth||labelWidth;axis.labelHeight=opts.labelHeight||labelHeight}function allocateAxisBoxFirstPhase(axis){var lw=axis.labelWidth,lh=axis.labelHeight,pos=axis.options.position,isXAxis=axis.direction==="x",tickLength=axis.options.tickLength,axisMargin=options.grid.axisMargin,padding=options.grid.labelMargin,innermost=true,outermost=true,first=true,found=false;$.each(isXAxis?xaxes:yaxes,function(i,a){if(a&&(a.show||a.reserveSpace)){if(a===axis){found=true}else if(a.options.position===pos){if(found){outermost=false}else{innermost=false}}if(!found){first=false}}});if(outermost){axisMargin=0}if(tickLength==null){tickLength=first?"full":5}if(!isNaN(+tickLength))padding+=+tickLength;if(isXAxis){lh+=padding;if(pos=="bottom"){plotOffset.bottom+=lh+axisMargin;axis.box={top:surface.height-plotOffset.bottom,height:lh}}else{axis.box={top:plotOffset.top+axisMargin,height:lh};plotOffset.top+=lh+axisMargin}}else{lw+=padding;if(pos=="left"){axis.box={left:plotOffset.left+axisMargin,width:lw};plotOffset.left+=lw+axisMargin}else{plotOffset.right+=lw+axisMargin;axis.box={left:surface.width-plotOffset.right,width:lw}}}axis.position=pos;axis.tickLength=tickLength;axis.box.padding=padding;axis.innermost=innermost}function allocateAxisBoxSecondPhase(axis){if(axis.direction=="x"){axis.box.left=plotOffset.left-axis.labelWidth/2;axis.box.width=surface.width-plotOffset.left-plotOffset.right+axis.labelWidth}else{axis.box.top=plotOffset.top-axis.labelHeight/2;axis.box.height=surface.height-plotOffset.bottom-plotOffset.top+axis.labelHeight}}function adjustLayoutForThingsStickingOut(){var minMargin=options.grid.minBorderMargin,axis,i;if(minMargin==null){minMargin=0;for(i=0;i<series.length;++i)minMargin=Math.max(minMargin,2*(series[i].points.radius+series[i].points.lineWidth/2))}var margins={left:minMargin,right:minMargin,top:minMargin,bottom:minMargin};$.each(allAxes(),function(_,axis){if(axis.reserveSpace&&axis.ticks&&axis.ticks.length){if(axis.direction==="x"){margins.left=Math.max(margins.left,axis.labelWidth/2);margins.right=Math.max(margins.right,axis.labelWidth/2)}else{margins.bottom=Math.max(margins.bottom,axis.labelHeight/2);margins.top=Math.max(margins.top,axis.labelHeight/2)}}});plotOffset.left=Math.ceil(Math.max(margins.left,plotOffset.left));plotOffset.right=Math.ceil(Math.max(margins.right,plotOffset.right));plotOffset.top=Math.ceil(Math.max(margins.top,plotOffset.top));plotOffset.bottom=Math.ceil(Math.max(margins.bottom,plotOffset.bottom))}function setupGrid(){var i,axes=allAxes(),showGrid=options.grid.show;for(var a in plotOffset){var margin=options.grid.margin||0;plotOffset[a]=typeof margin=="number"?margin:margin[a]||0}executeHooks(hooks.processOffset,[plotOffset]);for(var a in plotOffset){if(typeof options.grid.borderWidth=="object"){plotOffset[a]+=showGrid?options.grid.borderWidth[a]:0}else{plotOffset[a]+=showGrid?options.grid.borderWidth:0}}$.each(axes,function(_,axis){var axisOpts=axis.options;axis.show=axisOpts.show==null?axis.used:axisOpts.show;axis.reserveSpace=axisOpts.reserveSpace==null?axis.show:axisOpts.reserveSpace;setRange(axis)});if(showGrid){var allocatedAxes=$.grep(axes,function(axis){return axis.show||axis.reserveSpace});$.each(allocatedAxes,function(_,axis){setupTickGeneration(axis);setTicks(axis);snapRangeToTicks(axis,axis.ticks);measureTickLabels(axis)});for(i=allocatedAxes.length-1;i>=0;--i)allocateAxisBoxFirstPhase(allocatedAxes[i]);adjustLayoutForThingsStickingOut();$.each(allocatedAxes,function(_,axis){allocateAxisBoxSecondPhase(axis)})}plotWidth=surface.width-plotOffset.left-plotOffset.right;plotHeight=surface.height-plotOffset.bottom-plotOffset.top;$.each(axes,function(_,axis){setTransformationHelpers(axis)});if(showGrid){drawAxisLabels()}insertLegend()}function setRange(axis){var opts=axis.options,min=+(opts.min!=null?opts.min:axis.datamin),max=+(opts.max!=null?opts.max:axis.datamax),delta=max-min;if(delta==0){var widen=max==0?1:.01;if(opts.min==null)min-=widen;if(opts.max==null||opts.min!=null)max+=widen}else{var margin=opts.autoscaleMargin;if(margin!=null){if(opts.min==null){min-=delta*margin;if(min<0&&axis.datamin!=null&&axis.datamin>=0)min=0}if(opts.max==null){max+=delta*margin;if(max>0&&axis.datamax!=null&&axis.datamax<=0)max=0}}}axis.min=min;axis.max=max}function setupTickGeneration(axis){var opts=axis.options;var noTicks;if(typeof opts.ticks=="number"&&opts.ticks>0)noTicks=opts.ticks;else noTicks=.3*Math.sqrt(axis.direction=="x"?surface.width:surface.height);var delta=(axis.max-axis.min)/noTicks,dec=-Math.floor(Math.log(delta)/Math.LN10),maxDec=opts.tickDecimals;if(maxDec!=null&&dec>maxDec){dec=maxDec}var magn=Math.pow(10,-dec),norm=delta/magn,size;if(norm<1.5){size=1}else if(norm<3){size=2;if(norm>2.25&&(maxDec==null||dec+1<=maxDec)){size=2.5;++dec}}else if(norm<7.5){size=5}else{size=10}size*=magn;if(opts.minTickSize!=null&&size<opts.minTickSize){size=opts.minTickSize}axis.delta=delta;axis.tickDecimals=Math.max(0,maxDec!=null?maxDec:dec);axis.tickSize=opts.tickSize||size;if(opts.mode=="time"&&!axis.tickGenerator){throw new Error("Time mode requires the flot.time plugin.")}if(!axis.tickGenerator){axis.tickGenerator=function(axis){var ticks=[],start=floorInBase(axis.min,axis.tickSize),i=0,v=Number.NaN,prev;do{prev=v;v=start+i*axis.tickSize;ticks.push(v);++i}while(v<axis.max&&v!=prev);return ticks};axis.tickFormatter=function(value,axis){var factor=axis.tickDecimals?Math.pow(10,axis.tickDecimals):1;var formatted=""+Math.round(value*factor)/factor;if(axis.tickDecimals!=null){var decimal=formatted.indexOf(".");var precision=decimal==-1?0:formatted.length-decimal-1;if(precision<axis.tickDecimals){return(precision?formatted:formatted+".")+(""+factor).substr(1,axis.tickDecimals-precision)}}return formatted}}if($.isFunction(opts.tickFormatter))axis.tickFormatter=function(v,axis){return""+opts.tickFormatter(v,axis)};if(opts.alignTicksWithAxis!=null){var otherAxis=(axis.direction=="x"?xaxes:yaxes)[opts.alignTicksWithAxis-1];if(otherAxis&&otherAxis.used&&otherAxis!=axis){var niceTicks=axis.tickGenerator(axis);if(niceTicks.length>0){if(opts.min==null)axis.min=Math.min(axis.min,niceTicks[0]);if(opts.max==null&&niceTicks.length>1)axis.max=Math.max(axis.max,niceTicks[niceTicks.length-1])}axis.tickGenerator=function(axis){var ticks=[],v,i;for(i=0;i<otherAxis.ticks.length;++i){v=(otherAxis.ticks[i].v-otherAxis.min)/(otherAxis.max-otherAxis.min);v=axis.min+v*(axis.max-axis.min);ticks.push(v)}return ticks};if(!axis.mode&&opts.tickDecimals==null){var extraDec=Math.max(0,-Math.floor(Math.log(axis.delta)/Math.LN10)+1),ts=axis.tickGenerator(axis);if(!(ts.length>1&&/\..*0$/.test((ts[1]-ts[0]).toFixed(extraDec))))axis.tickDecimals=extraDec}}}}function setTicks(axis){var oticks=axis.options.ticks,ticks=[];if(oticks==null||typeof oticks=="number"&&oticks>0)ticks=axis.tickGenerator(axis);else if(oticks){if($.isFunction(oticks))ticks=oticks(axis);else ticks=oticks}var i,v;axis.ticks=[];for(i=0;i<ticks.length;++i){var label=null;var t=ticks[i];if(typeof t=="object"){v=+t[0];if(t.length>1)label=t[1]}else v=+t;if(label==null)label=axis.tickFormatter(v,axis);if(!isNaN(v))axis.ticks.push({v:v,label:label})}}function snapRangeToTicks(axis,ticks){if(axis.options.autoscaleMargin&&ticks.length>0){if(axis.options.min==null)axis.min=Math.min(axis.min,ticks[0].v);if(axis.options.max==null&&ticks.length>1)axis.max=Math.max(axis.max,ticks[ticks.length-1].v)}}function draw(){surface.clear();executeHooks(hooks.drawBackground,[ctx]);var grid=options.grid;if(grid.show&&grid.backgroundColor)drawBackground();if(grid.show&&!grid.aboveData){drawGrid()}for(var i=0;i<series.length;++i){executeHooks(hooks.drawSeries,[ctx,series[i]]);drawSeries(series[i])}executeHooks(hooks.draw,[ctx]);if(grid.show&&grid.aboveData){drawGrid()}surface.render();triggerRedrawOverlay()}function extractRange(ranges,coord){var axis,from,to,key,axes=allAxes();for(var i=0;i<axes.length;++i){axis=axes[i];if(axis.direction==coord){key=coord+axis.n+"axis";if(!ranges[key]&&axis.n==1)key=coord+"axis";if(ranges[key]){from=ranges[key].from;to=ranges[key].to;break}}}if(!ranges[key]){axis=coord=="x"?xaxes[0]:yaxes[0];from=ranges[coord+"1"];to=ranges[coord+"2"]}if(from!=null&&to!=null&&from>to){var tmp=from;from=to;to=tmp}return{from:from,to:to,axis:axis}}function drawBackground(){ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.fillStyle=getColorOrGradient(options.grid.backgroundColor,plotHeight,0,"rgba(255, 255, 255, 0)");ctx.fillRect(0,0,plotWidth,plotHeight);ctx.restore()}function drawGrid(){var i,axes,bw,bc;ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var markings=options.grid.markings;if(markings){if($.isFunction(markings)){axes=plot.getAxes();axes.xmin=axes.xaxis.min;axes.xmax=axes.xaxis.max;axes.ymin=axes.yaxis.min;axes.ymax=axes.yaxis.max;markings=markings(axes)}for(i=0;i<markings.length;++i){var m=markings[i],xrange=extractRange(m,"x"),yrange=extractRange(m,"y");if(xrange.from==null)xrange.from=xrange.axis.min;if(xrange.to==null)xrange.to=xrange.axis.max;
766−-if(yrange.from==null)yrange.from=yrange.axis.min;if(yrange.to==null)yrange.to=yrange.axis.max;if(xrange.to<xrange.axis.min||xrange.from>xrange.axis.max||yrange.to<yrange.axis.min||yrange.from>yrange.axis.max)continue;xrange.from=Math.max(xrange.from,xrange.axis.min);xrange.to=Math.min(xrange.to,xrange.axis.max);yrange.from=Math.max(yrange.from,yrange.axis.min);yrange.to=Math.min(yrange.to,yrange.axis.max);var xequal=xrange.from===xrange.to,yequal=yrange.from===yrange.to;if(xequal&&yequal){continue}xrange.from=Math.floor(xrange.axis.p2c(xrange.from));xrange.to=Math.floor(xrange.axis.p2c(xrange.to));yrange.from=Math.floor(yrange.axis.p2c(yrange.from));yrange.to=Math.floor(yrange.axis.p2c(yrange.to));if(xequal||yequal){var lineWidth=m.lineWidth||options.grid.markingsLineWidth,subPixel=lineWidth%2?.5:0;ctx.beginPath();ctx.strokeStyle=m.color||options.grid.markingsColor;ctx.lineWidth=lineWidth;if(xequal){ctx.moveTo(xrange.to+subPixel,yrange.from);ctx.lineTo(xrange.to+subPixel,yrange.to)}else{ctx.moveTo(xrange.from,yrange.to+subPixel);ctx.lineTo(xrange.to,yrange.to+subPixel)}ctx.stroke()}else{ctx.fillStyle=m.color||options.grid.markingsColor;ctx.fillRect(xrange.from,yrange.to,xrange.to-xrange.from,yrange.from-yrange.to)}}}axes=allAxes();bw=options.grid.borderWidth;for(var j=0;j<axes.length;++j){var axis=axes[j],box=axis.box,t=axis.tickLength,x,y,xoff,yoff;if(!axis.show||axis.ticks.length==0)continue;ctx.lineWidth=1;if(axis.direction=="x"){x=0;if(t=="full")y=axis.position=="top"?0:plotHeight;else y=box.top-plotOffset.top+(axis.position=="top"?box.height:0)}else{y=0;if(t=="full")x=axis.position=="left"?0:plotWidth;else x=box.left-plotOffset.left+(axis.position=="left"?box.width:0)}if(!axis.innermost){ctx.strokeStyle=axis.options.color;ctx.beginPath();xoff=yoff=0;if(axis.direction=="x")xoff=plotWidth+1;else yoff=plotHeight+1;if(ctx.lineWidth==1){if(axis.direction=="x"){y=Math.floor(y)+.5}else{x=Math.floor(x)+.5}}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff);ctx.stroke()}ctx.strokeStyle=axis.options.tickColor;ctx.beginPath();for(i=0;i<axis.ticks.length;++i){var v=axis.ticks[i].v;xoff=yoff=0;if(isNaN(v)||v<axis.min||v>axis.max||t=="full"&&(typeof bw=="object"&&bw[axis.position]>0||bw>0)&&(v==axis.min||v==axis.max))continue;if(axis.direction=="x"){x=axis.p2c(v);yoff=t=="full"?-plotHeight:t;if(axis.position=="top")yoff=-yoff}else{y=axis.p2c(v);xoff=t=="full"?-plotWidth:t;if(axis.position=="left")xoff=-xoff}if(ctx.lineWidth==1){if(axis.direction=="x")x=Math.floor(x)+.5;else y=Math.floor(y)+.5}ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff)}ctx.stroke()}if(bw){bc=options.grid.borderColor;if(typeof bw=="object"||typeof bc=="object"){if(typeof bw!=="object"){bw={top:bw,right:bw,bottom:bw,left:bw}}if(typeof bc!=="object"){bc={top:bc,right:bc,bottom:bc,left:bc}}if(bw.top>0){ctx.strokeStyle=bc.top;ctx.lineWidth=bw.top;ctx.beginPath();ctx.moveTo(0-bw.left,0-bw.top/2);ctx.lineTo(plotWidth,0-bw.top/2);ctx.stroke()}if(bw.right>0){ctx.strokeStyle=bc.right;ctx.lineWidth=bw.right;ctx.beginPath();ctx.moveTo(plotWidth+bw.right/2,0-bw.top);ctx.lineTo(plotWidth+bw.right/2,plotHeight);ctx.stroke()}if(bw.bottom>0){ctx.strokeStyle=bc.bottom;ctx.lineWidth=bw.bottom;ctx.beginPath();ctx.moveTo(plotWidth+bw.right,plotHeight+bw.bottom/2);ctx.lineTo(0,plotHeight+bw.bottom/2);ctx.stroke()}if(bw.left>0){ctx.strokeStyle=bc.left;ctx.lineWidth=bw.left;ctx.beginPath();ctx.moveTo(0-bw.left/2,plotHeight+bw.bottom);ctx.lineTo(0-bw.left/2,0);ctx.stroke()}}else{ctx.lineWidth=bw;ctx.strokeStyle=options.grid.borderColor;ctx.strokeRect(-bw/2,-bw/2,plotWidth+bw,plotHeight+bw)}}ctx.restore()}function drawAxisLabels(){$.each(allAxes(),function(_,axis){var box=axis.box,legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=axis.options.font||"flot-tick-label tickLabel",tick,x,y,halign,valign;surface.removeText(layer);if(!axis.show||axis.ticks.length==0)return;for(var i=0;i<axis.ticks.length;++i){tick=axis.ticks[i];if(!tick.label||tick.v<axis.min||tick.v>axis.max)continue;if(axis.direction=="x"){halign="center";x=plotOffset.left+axis.p2c(tick.v);if(axis.position=="bottom"){y=box.top+box.padding}else{y=box.top+box.height-box.padding;valign="bottom"}}else{valign="middle";y=plotOffset.top+axis.p2c(tick.v);if(axis.position=="left"){x=box.left+box.width-box.padding;halign="right"}else{x=box.left+box.padding}}surface.addText(layer,x,y,tick.label,font,null,null,halign,valign)}})}function drawSeries(series){if(series.lines.show)drawSeriesLines(series);if(series.bars.show)drawSeriesBars(series);if(series.points.show)drawSeriesPoints(series)}function drawSeriesLines(series){function plotLine(datapoints,xoffset,yoffset,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,prevx=null,prevy=null;ctx.beginPath();for(var i=ps;i<points.length;i+=ps){var x1=points[i-ps],y1=points[i-ps+1],x2=points[i],y2=points[i+1];if(x1==null||x2==null)continue;if(y1<=y2&&y1<axisy.min){if(y2<axisy.min)continue;x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min}else if(y2<=y1&&y2<axisy.min){if(y1<axisy.min)continue;x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min}if(y1>=y2&&y1>axisy.max){if(y2>axisy.max)continue;x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max}else if(y2>=y1&&y2>axisy.max){if(y1>axisy.max)continue;x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max}if(x1<=x2&&x1<axisx.min){if(x2<axisx.min)continue;y1=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.min}else if(x2<=x1&&x2<axisx.min){if(x1<axisx.min)continue;y2=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.min}if(x1>=x2&&x1>axisx.max){if(x2>axisx.max)continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max}else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max)continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max}if(x1!=prevx||y1!=prevy)ctx.moveTo(axisx.p2c(x1)+xoffset,axisy.p2c(y1)+yoffset);prevx=x2;prevy=y2;ctx.lineTo(axisx.p2c(x2)+xoffset,axisy.p2c(y2)+yoffset)}ctx.stroke()}function plotLineArea(datapoints,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,bottom=Math.min(Math.max(0,axisy.min),axisy.max),i=0,top,areaOpen=false,ypos=1,segmentStart=0,segmentEnd=0;while(true){if(ps>0&&i>points.length+ps)break;i+=ps;var x1=points[i-ps],y1=points[i-ps+ypos],x2=points[i],y2=points[i+ypos];if(areaOpen){if(ps>0&&x1!=null&&x2==null){segmentEnd=i;ps=-ps;ypos=2;continue}if(ps<0&&i==segmentStart+ps){ctx.fill();areaOpen=false;ps=-ps;ypos=1;i=segmentStart=segmentEnd+ps;continue}}if(x1==null||x2==null)continue;if(x1<=x2&&x1<axisx.min){if(x2<axisx.min)continue;y1=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.min}else if(x2<=x1&&x2<axisx.min){if(x1<axisx.min)continue;y2=(axisx.min-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.min}if(x1>=x2&&x1>axisx.max){if(x2>axisx.max)continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max}else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max)continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max}if(!areaOpen){ctx.beginPath();ctx.moveTo(axisx.p2c(x1),axisy.p2c(bottom));areaOpen=true}if(y1>=axisy.max&&y2>=axisy.max){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.max));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.max));continue}else if(y1<=axisy.min&&y2<=axisy.min){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.min));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.min));continue}var x1old=x1,x2old=x2;if(y1<=y2&&y1<axisy.min&&y2>=axisy.min){x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min}else if(y2<=y1&&y2<axisy.min&&y1>=axisy.min){x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min}if(y1>=y2&&y1>axisy.max&&y2<=axisy.max){x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max}else if(y2>=y1&&y2>axisy.max&&y1<=axisy.max){x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max}if(x1!=x1old){ctx.lineTo(axisx.p2c(x1old),axisy.p2c(y1))}ctx.lineTo(axisx.p2c(x1),axisy.p2c(y1));ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));if(x2!=x2old){ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));ctx.lineTo(axisx.p2c(x2old),axisy.p2c(y2))}}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineJoin="round";var lw=series.lines.lineWidth,sw=series.shadowSize;if(lw>0&&sw>0){ctx.lineWidth=sw;ctx.strokeStyle="rgba(0,0,0,0.1)";var angle=Math.PI/18;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/2),Math.cos(angle)*(lw/2+sw/2),series.xaxis,series.yaxis);ctx.lineWidth=sw/2;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/4),Math.cos(angle)*(lw/2+sw/4),series.xaxis,series.yaxis)}ctx.lineWidth=lw;ctx.strokeStyle=series.color;var fillStyle=getFillStyle(series.lines,series.color,0,plotHeight);if(fillStyle){ctx.fillStyle=fillStyle;plotLineArea(series.datapoints,series.xaxis,series.yaxis)}if(lw>0)plotLine(series.datapoints,0,0,series.xaxis,series.yaxis);ctx.restore()}function drawSeriesPoints(series){function plotPoints(datapoints,radius,fillStyle,offset,shadow,axisx,axisy,symbol){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i<points.length;i+=ps){var x=points[i],y=points[i+1];if(x==null||x<axisx.min||x>axisx.max||y<axisy.min||y>axisy.max)continue;ctx.beginPath();x=axisx.p2c(x);y=axisy.p2c(y)+offset;if(symbol=="circle")ctx.arc(x,y,radius,0,shadow?Math.PI:Math.PI*2,false);else symbol(ctx,x,y,radius,shadow);ctx.closePath();if(fillStyle){ctx.fillStyle=fillStyle;ctx.fill()}ctx.stroke()}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var lw=series.points.lineWidth,sw=series.shadowSize,radius=series.points.radius,symbol=series.points.symbol;if(lw==0)lw=1e-4;if(lw>0&&sw>0){var w=sw/2;ctx.lineWidth=w;ctx.strokeStyle="rgba(0,0,0,0.1)";plotPoints(series.datapoints,radius,null,w+w/2,true,series.xaxis,series.yaxis,symbol);ctx.strokeStyle="rgba(0,0,0,0.2)";plotPoints(series.datapoints,radius,null,w/2,true,series.xaxis,series.yaxis,symbol)}ctx.lineWidth=lw;ctx.strokeStyle=series.color;plotPoints(series.datapoints,radius,getFillStyle(series.points,series.color),0,false,series.xaxis,series.yaxis,symbol);ctx.restore()}function drawBar(x,y,b,barLeft,barRight,fillStyleCallback,axisx,axisy,c,horizontal,lineWidth){var left,right,bottom,top,drawLeft,drawRight,drawTop,drawBottom,tmp;if(horizontal){drawBottom=drawRight=drawTop=true;drawLeft=false;left=b;right=x;top=y+barLeft;bottom=y+barRight;if(right<left){tmp=right;right=left;left=tmp;drawLeft=true;drawRight=false}}else{drawLeft=drawRight=drawTop=true;drawBottom=false;left=x+barLeft;right=x+barRight;bottom=b;top=y;if(top<bottom){tmp=top;top=bottom;bottom=tmp;drawBottom=true;drawTop=false}}if(right<axisx.min||left>axisx.max||top<axisy.min||bottom>axisy.max)return;if(left<axisx.min){left=axisx.min;drawLeft=false}if(right>axisx.max){right=axisx.max;drawRight=false}if(bottom<axisy.min){bottom=axisy.min;drawBottom=false}if(top>axisy.max){top=axisy.max;drawTop=false}left=axisx.p2c(left);bottom=axisy.p2c(bottom);right=axisx.p2c(right);top=axisy.p2c(top);if(fillStyleCallback){c.fillStyle=fillStyleCallback(bottom,top);c.fillRect(left,top,right-left,bottom-top)}if(lineWidth>0&&(drawLeft||drawRight||drawTop||drawBottom)){c.beginPath();c.moveTo(left,bottom);if(drawLeft)c.lineTo(left,top);else c.moveTo(left,top);if(drawTop)c.lineTo(right,top);else c.moveTo(right,top);if(drawRight)c.lineTo(right,bottom);else c.moveTo(right,bottom);if(drawBottom)c.lineTo(left,bottom);else c.moveTo(left,bottom);c.stroke()}}function drawSeriesBars(series){function plotBars(datapoints,barLeft,barRight,fillStyleCallback,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i<points.length;i+=ps){if(points[i]==null)continue;drawBar(points[i],points[i+1],points[i+2],barLeft,barRight,fillStyleCallback,axisx,axisy,ctx,series.bars.horizontal,series.bars.lineWidth)}}ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineWidth=series.bars.lineWidth;ctx.strokeStyle=series.color;var barLeft;switch(series.bars.align){case"left":barLeft=0;break;case"right":barLeft=-series.bars.barWidth;break;default:barLeft=-series.bars.barWidth/2}var fillStyleCallback=series.bars.fill?function(bottom,top){return getFillStyle(series.bars,series.color,bottom,top)}:null;plotBars(series.datapoints,barLeft,barLeft+series.bars.barWidth,fillStyleCallback,series.xaxis,series.yaxis);ctx.restore()}function getFillStyle(filloptions,seriesColor,bottom,top){var fill=filloptions.fill;if(!fill)return null;if(filloptions.fillColor)return getColorOrGradient(filloptions.fillColor,bottom,top,seriesColor);var c=$.color.parse(seriesColor);c.a=typeof fill=="number"?fill:.4;c.normalize();return c.toString()}function insertLegend(){if(options.legend.container!=null){$(options.legend.container).html("")}else{placeholder.find(".legend").remove()}if(!options.legend.show){return}var fragments=[],entries=[],rowStarted=false,lf=options.legend.labelFormatter,s,label;for(var i=0;i<series.length;++i){s=series[i];if(s.label){label=lf?lf(s.label,s):s.label;if(label){entries.push({label:label,color:s.color})}}}if(options.legend.sorted){if($.isFunction(options.legend.sorted)){entries.sort(options.legend.sorted)}else if(options.legend.sorted=="reverse"){entries.reverse()}else{var ascending=options.legend.sorted!="descending";entries.sort(function(a,b){return a.label==b.label?0:a.label<b.label!=ascending?1:-1})}}for(var i=0;i<entries.length;++i){var entry=entries[i];if(i%options.legend.noColumns==0){if(rowStarted)fragments.push("</tr>");fragments.push("<tr>");rowStarted=true}fragments.push('<td class="legendColorBox"><div style="border:1px solid '+options.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+entry.color+';overflow:hidden"></div></div></td>'+'<td class="legendLabel">'+entry.label+"</td>")}if(rowStarted)fragments.push("</tr>");if(fragments.length==0)return;var table='<table style="font-size:smaller;color:'+options.grid.color+'">'+fragments.join("")+"</table>";if(options.legend.container!=null)$(options.legend.container).html(table);else{var pos="",p=options.legend.position,m=options.legend.margin;if(m[0]==null)m=[m,m];if(p.charAt(0)=="n")pos+="top:"+(m[1]+plotOffset.top)+"px;";else if(p.charAt(0)=="s")pos+="bottom:"+(m[1]+plotOffset.bottom)+"px;";if(p.charAt(1)=="e")pos+="right:"+(m[0]+plotOffset.right)+"px;";else if(p.charAt(1)=="w")pos+="left:"+(m[0]+plotOffset.left)+"px;";var legend=$('<div class="legend">'+table.replace('style="','style="position:absolute;'+pos+";")+"</div>").appendTo(placeholder);if(options.legend.backgroundOpacity!=0){var c=options.legend.backgroundColor;if(c==null){c=options.grid.backgroundColor;if(c&&typeof c=="string")c=$.color.parse(c);else c=$.color.extract(legend,"background-color");c.a=1;c=c.toString()}var div=legend.children();$('<div style="position:absolute;width:'+div.width()+"px;height:"+div.height()+"px;"+pos+"background-color:"+c+';"> </div>').prependTo(legend).css("opacity",options.legend.backgroundOpacity)}}}var highlights=[],redrawTimeout=null;function findNearbyItem(mouseX,mouseY,seriesFilter){var maxDistance=options.grid.mouseActiveRadius,smallestDistance=maxDistance*maxDistance+1,item=null,foundPoint=false,i,j,ps;for(i=series.length-1;i>=0;--i){if(!seriesFilter(series[i]))continue;var s=series[i],axisx=s.xaxis,axisy=s.yaxis,points=s.datapoints.points,mx=axisx.c2p(mouseX),my=axisy.c2p(mouseY),maxx=maxDistance/axisx.scale,maxy=maxDistance/axisy.scale;ps=s.datapoints.pointsize;if(axisx.options.inverseTransform)maxx=Number.MAX_VALUE;if(axisy.options.inverseTransform)maxy=Number.MAX_VALUE;if(s.lines.show||s.points.show){for(j=0;j<points.length;j+=ps){var x=points[j],y=points[j+1];if(x==null)continue;if(x-mx>maxx||x-mx<-maxx||y-my>maxy||y-my<-maxy)continue;var dx=Math.abs(axisx.p2c(x)-mouseX),dy=Math.abs(axisy.p2c(y)-mouseY),dist=dx*dx+dy*dy;if(dist<smallestDistance){smallestDistance=dist;item=[i,j/ps]}}}if(s.bars.show&&!item){var barLeft,barRight;switch(s.bars.align){case"left":barLeft=0;break;case"right":barLeft=-s.bars.barWidth;break;default:barLeft=-s.bars.barWidth/2}barRight=barLeft+s.bars.barWidth;for(j=0;j<points.length;j+=ps){var x=points[j],y=points[j+1],b=points[j+2];if(x==null)continue;if(series[i].bars.horizontal?mx<=Math.max(b,x)&&mx>=Math.min(b,x)&&my>=y+barLeft&&my<=y+barRight:mx>=x+barLeft&&mx<=x+barRight&&my>=Math.min(b,y)&&my<=Math.max(b,y))item=[i,j/ps]}}}if(item){i=item[0];j=item[1];ps=series[i].datapoints.pointsize;return{datapoint:series[i].datapoints.points.slice(j*ps,(j+1)*ps),dataIndex:j,series:series[i],seriesIndex:i}}return null}function onMouseMove(e){if(options.grid.hoverable)triggerClickHoverEvent("plothover",e,function(s){return s["hoverable"]!=false})}function onMouseLeave(e){if(options.grid.hoverable)triggerClickHoverEvent("plothover",e,function(s){return false})}function onClick(e){triggerClickHoverEvent("plotclick",e,function(s){return s["clickable"]!=false})}function triggerClickHoverEvent(eventname,event,seriesFilter){var offset=eventHolder.offset(),canvasX=event.pageX-offset.left-plotOffset.left,canvasY=event.pageY-offset.top-plotOffset.top,pos=canvasToAxisCoords({left:canvasX,top:canvasY});pos.pageX=event.pageX;pos.pageY=event.pageY;var item=findNearbyItem(canvasX,canvasY,seriesFilter);if(item){item.pageX=parseInt(item.series.xaxis.p2c(item.datapoint[0])+offset.left+plotOffset.left,10);item.pageY=parseInt(item.series.yaxis.p2c(item.datapoint[1])+offset.top+plotOffset.top,10)}if(options.grid.autoHighlight){for(var i=0;i<highlights.length;++i){var h=highlights[i];if(h.auto==eventname&&!(item&&h.series==item.series&&h.point[0]==item.datapoint[0]&&h.point[1]==item.datapoint[1]))unhighlight(h.series,h.point)}if(item)highlight(item.series,item.datapoint,eventname)}placeholder.trigger(eventname,[pos,item])}function triggerRedrawOverlay(){var t=options.interaction.redrawOverlayInterval;if(t==-1){drawOverlay();return}if(!redrawTimeout)redrawTimeout=setTimeout(drawOverlay,t)}function drawOverlay(){redrawTimeout=null;octx.save();overlay.clear();octx.translate(plotOffset.left,plotOffset.top);var i,hi;for(i=0;i<highlights.length;++i){hi=highlights[i];if(hi.series.bars.show)drawBarHighlight(hi.series,hi.point);else drawPointHighlight(hi.series,hi.point)}octx.restore();executeHooks(hooks.drawOverlay,[octx])}function highlight(s,point,auto){if(typeof s=="number")s=series[s];if(typeof point=="number"){var ps=s.datapoints.pointsize;point=s.datapoints.points.slice(ps*point,ps*(point+1))}var i=indexOfHighlight(s,point);if(i==-1){highlights.push({series:s,point:point,auto:auto});triggerRedrawOverlay()}else if(!auto)highlights[i].auto=false}function unhighlight(s,point){if(s==null&&point==null){highlights=[];triggerRedrawOverlay();return}if(typeof s=="number")s=series[s];if(typeof point=="number"){var ps=s.datapoints.pointsize;point=s.datapoints.points.slice(ps*point,ps*(point+1))}var i=indexOfHighlight(s,point);if(i!=-1){highlights.splice(i,1);triggerRedrawOverlay()}}function indexOfHighlight(s,p){for(var i=0;i<highlights.length;++i){var h=highlights[i];if(h.series==s&&h.point[0]==p[0]&&h.point[1]==p[1])return i}return-1}function drawPointHighlight(series,point){var x=point[0],y=point[1],axisx=series.xaxis,axisy=series.yaxis,highlightColor=typeof series.highlightColor==="string"?series.highlightColor:$.color.parse(series.color).scale("a",.5).toString();if(x<axisx.min||x>axisx.max||y<axisy.min||y>axisy.max)return;var pointRadius=series.points.radius+series.points.lineWidth/2;octx.lineWidth=pointRadius;octx.strokeStyle=highlightColor;var radius=1.5*pointRadius;x=axisx.p2c(x);y=axisy.p2c(y);octx.beginPath();if(series.points.symbol=="circle")octx.arc(x,y,radius,0,2*Math.PI,false);else series.points.symbol(octx,x,y,radius,false);octx.closePath();octx.stroke()}function drawBarHighlight(series,point){var highlightColor=typeof series.highlightColor==="string"?series.highlightColor:$.color.parse(series.color).scale("a",.5).toString(),fillStyle=highlightColor,barLeft;switch(series.bars.align){case"left":barLeft=0;break;case"right":barLeft=-series.bars.barWidth;break;default:barLeft=-series.bars.barWidth/2}octx.lineWidth=series.bars.lineWidth;octx.strokeStyle=highlightColor;drawBar(point[0],point[1],point[2]||0,barLeft,barLeft+series.bars.barWidth,function(){return fillStyle},series.xaxis,series.yaxis,octx,series.bars.horizontal,series.bars.lineWidth)}function getColorOrGradient(spec,bottom,top,defaultColor){if(typeof spec=="string")return spec;else{var gradient=ctx.createLinearGradient(0,top,0,bottom);for(var i=0,l=spec.colors.length;i<l;++i){var c=spec.colors[i];if(typeof c!="string"){var co=$.color.parse(defaultColor);if(c.brightness!=null)co=co.scale("rgb",c.brightness);if(c.opacity!=null)co.a*=c.opacity;c=co.toString()}gradient.addColorStop(i/(l-1),c)}return gradient}}}$.plot=function(placeholder,data,options){var plot=new Plot($(placeholder),data,options,$.plot.plugins);return plot};$.plot.version="0.8.3";$.plot.plugins=[];$.fn.plot=function(data,options){return this.each(function(){$.plot(this,data,options)})};function floorInBase(n,base){return base*Math.floor(n/base)}})(jQuery);
767−- </script>
768−- <script language="javascript" type="text/javascript">
769−- (function ($) {
770−- $.zip = function(a,b) {
771−- var x = Math.min(a.length,b.length);
772−- var c = new Array(x);
773−- for (var i = 0; i < x; i++)
774−- c[i] = [a[i],b[i]];
775−- return c;
776−- };
777−-
778−- $.mean = function(ary) {
779−- var m = 0, i = 0;
780−-
781−- while (i < ary.length) {
782−- var j = i++;
783−- m += (ary[j] - m) / i;
784−- }
785−-
786−- return m;
787−- };
788−-
789−- $.timeUnits = function(secs) {
790−- if (secs < 0) return $.timeUnits(-secs);
791−- else if (secs >= 1e9) return [1e-9, "Gs"];
792−- else if (secs >= 1e6) return [1e-6, "Ms"];
793−- else if (secs >= 1) return [1, "s"];
794−- else if (secs >= 1e-3) return [1e3, "ms"];
795−- else if (secs >= 1e-6) return [1e6, "\u03bcs"];
796−- else if (secs >= 1e-9) return [1e9, "ns"];
797−- else if (secs >= 1e-12) return [1e12, "ps"];
798−- return [1, "s"];
799−- };
800−-
801−- $.scaleTimes = function(ary) {
802−- var s = $.timeUnits($.mean(ary));
803−- return [$.scaleBy(s[0], ary), s[0]];
804−- };
805−-
806−- $.prepareTime = function(secs) {
807−- var units = $.timeUnits(secs);
808−- var scaled = secs * units[0];
809−- var s = scaled.toPrecision(3);
810−- var t = scaled.toString();
811−- return [t.length < s.length ? t : s, units[1]];
812−- };
813−-
814−- $.scaleBy = function(x, ary) {
815−- var nary = new Array(ary.length);
816−- for (var i = 0; i < ary.length; i++)
817−- nary[i] = ary[i] * x;
818−- return nary;
819−- };
820−-
821−- $.renderTime = function(secs) {
822−- var x = $.prepareTime(secs);
823−- return x[0] + ' ' + x[1];
824−- };
825−-
826−- $.unitFormatter = function(scale) {
827−- var labelname;
828−- return function(secs,axis) {
829−- var x = $.prepareTime(secs / scale);
830−- if (labelname === x[1])
831−- return x[0];
832−- else {
833−- labelname = x[1];
834−- return x[0] + ' ' + x[1];
835−- }
836−- };
837−- };
838−-
839−- $.addTooltip = function(name, renderText) {
840−- function showTooltip(x, y, contents) {
841−- $('<div id="tooltip">' + contents + '</div>').css( {
842−- position: 'absolute',
843−- display: 'none',
844−- top: y + 5,
845−- left: x + 5,
846−- border: '1px solid #fdd',
847−- padding: '2px',
848−- 'background-color': '#fee',
849−- opacity: 0.80
850−- }).appendTo("body").fadeIn(200);
851−- };
852−- var pp = null;
853−- $(name).bind("plothover", function (event, pos, item) {
854−- $("#x").text(pos.x.toFixed(2));
855−- $("#y").text(pos.y.toFixed(2));
856−-
857−- if (item) {
858−- if (pp != item.dataIndex) {
859−- pp = item.dataIndex;
860−-
861−- $("#tooltip").remove();
862−- var x = item.datapoint[0],
863−- y = item.datapoint[1];
864−-
865−- showTooltip(item.pageX, item.pageY, renderText(x,y));
866−- }
867−- }
868−- else {
869−- $("#tooltip").remove();
870−- pp = null;
871−- }
872−- });
873−- };
874−-})(jQuery);
875−-
876−- </script>
877−- <style type="text/css">
878−-html, body {
879−- height: 100%;
880−- margin: 0;
881−-}
882−-
883−-#wrap {
884−- min-height: 100%;
885−-}
886−-
887−-#main {
888−- overflow: auto;
889−- padding-bottom: 180px; /* must be same height as the footer */
890−-}
891−-
892−-#footer {
893−- position: relative;
894−- margin-top: -180px; /* negative value of footer height */
895−- height: 180px;
896−- clear: both;
897−- background: #888;
898−- margin: 40px 0 0;
899−- color: white;
900−- font-size: larger;
901−- font-weight: 300;
902−-}
903−-
904−-body:before {
905−- /* Opera fix */
906−- content: "";
907−- height: 100%;
908−- float: left;
909−- width: 0;
910−- margin-top: -32767px;
911−-}
912−-
913−-body {
914−- font: 14px Helvetica Neue;
915−- text-rendering: optimizeLegibility;
916−- margin-top: 1em;
917−-}
918−-
919−-a:link {
920−- color: steelblue;
921−- text-decoration: none;
922−-}
923−-
924−-a:visited {
925−- color: #4a743b;
926−- text-decoration: none;
927−-}
928−-
929−-#footer a {
930−- color: white;
931−- text-decoration: underline;
932−-}
933−-
934−-.hover {
935−- color: steelblue;
936−- text-decoration: none;
937−-}
938−-
939−-.body {
940−- width: 960px;
941−- margin: auto;
942−-}
943−-
944−-.footfirst {
945−- position: relative;
946−- top: 30px;
947−-}
948−-
949−-th {
950−- font-weight: 500;
951−- opacity: 0.8;
952−-}
953−-
954−-th.cibound {
955−- opacity: 0.4;
956−-}
957−-
958−-.confinterval {
959−- opacity: 0.5;
960−-}
961−-
962−-h1 {
963−- font-size: 36px;
964−- font-weight: 300;
965−- margin-bottom: .3em;
966−-}
967−-
968−-h2 {
969−- font-size: 30px;
970−- font-weight: 300;
971−- margin-bottom: .3em;
972−-}
973−-
974−-.meanlegend {
975−- color: #404040;
976−- background-color: #ffffff;
977−- opacity: 0.6;
978−- font-size: smaller;
979−-}
980−-
981−- </style>
982−- <!--[if !IE 7]>
983−- <style type="text/css">
984−- #wrap {display:table;height:100%}
985−- </style>
986−- <![endif]-->
987−- </head>
988−- <body>
989−- <div id="wrap">
990−- <div id="main" class="body">
991−- <h1>criterion performance measurements</h1>
992−-
993−-<h2>overview</h2>
994−-
995−-<p><a href="#grokularation">want to understand this report?</a></p>
996−-
997−-<div id="overview" class="ovchart" style="width:900px;height:100px;"></div>
998−-
999−-<h2><a name="b0">ByteString/HashMap/random</a></h2>
1000−- <table width="100%">
1001−- <tbody>
1002−- <tr>
1003−- <td><div id="kde0" class="kdechart"
1004−- style="width:450px;height:278px;"></div></td>
1005−- <td><div id="time0" class="timechart"
1006−- style="width:450px;height:278px;"></div></td>
1007−-<!--
1008−- <td><div id="cycle0" class="cyclechart"
1009−- style="width:300px;height:278px;"></div></td>
1010−--->
1011−- </tr>
1012−- </tbody>
1013−- </table>
1014−-
1015−- <table>
1016−- <thead class="analysis">
1017−- <th></th>
1018−- <th class="cibound"
1019−- title="0.95 confidence level">lower bound</th>
1020−- <th>estimate</th>
1021−- <th class="cibound"
1022−- title="0.95 confidence level">upper bound</th>
1023−- </thead>
1024−- <tbody>
1025−- <tr>
1026−- <td>OLS regression</td>
1027−- <td><span class="confinterval olstimelb0">xxx</span></td>
1028−- <td><span class="olstimept0">xxx</span></td>
1029−- <td><span class="confinterval olstimeub0">xxx</span></td>
1030−- </tr>
1031−- <tr>
1032−- <td>R&#xb2; goodness-of-fit</td>
1033−- <td><span class="confinterval olsr2lb0">xxx</span></td>
1034−- <td><span class="olsr2pt0">xxx</span></td>
1035−- <td><span class="confinterval olsr2ub0">xxx</span></td>
1036−- </tr>
1037−- <tr>
1038−- <td>Mean execution time</td>
1039−- <td><span class="confinterval citime">5.54613319607341e-3</span></td>
1040−- <td><span class="time">5.621667703915931e-3</span></td>
1041−- <td><span class="confinterval citime">5.713526073454561e-3</span></td>
1042−- </tr>
1043−- <tr>
1044−- <td>Standard deviation</td>
1045−- <td><span class="confinterval citime">1.972562820146363e-4</span></td>
1046−- <td><span class="time">2.494938876886024e-4</span></td>
1047−- <td><span class="confinterval citime">3.1487131555210624e-4</span></td>
1048−- </tr>
1049−- </tbody>
1050−- </table>
1051−-
1052−- <span class="outliers">
1053−- <p>Outlying measurements have moderate
1054−- (<span class="percent">0.21993690418913867</span>%)
1055−- effect on estimated standard deviation.</p>
1056−- </span>
1057−-
1058−- <h2><a name="grokularation">understanding this report</a></h2>
1059−-
1060−- <p>In this report, each function benchmarked by criterion is assigned
1061−- a section of its own. The charts in each section are active; if
1062−- you hover your mouse over data points and annotations, you will see
1063−- more details.</p>
1064−-
1065−- <ul>
1066−- <li>The chart on the left is a
1067−- <a href="http://en.wikipedia.org/wiki/Kernel_density_estimation">kernel
1068−- density estimate</a> (also known as a KDE) of time
1069−- measurements. This graphs the probability of any given time
1070−- measurement occurring. A spike indicates that a measurement of a
1071−- particular time occurred; its height indicates how often that
1072−- measurement was repeated.</li>
1073−-
1074−- <li>The chart on the right is the raw data from which the kernel
1075−- density estimate is built. The <i>x</i> axis indicates the
1076−- number of loop iterations, while the <i>y</i> axis shows measured
1077−- execution time for the given number of loop iterations. The
1078−- line behind the values is the linear regression prediction of
1079−- execution time for a given number of iterations. Ideally, all
1080−- measurements will be on (or very near) this line.</li>
1081−- </ul>
1082−-
1083−- <p>Under the charts is a small table.
1084−- The first two rows are the results of a linear regression run
1085−- on the measurements displayed in the right-hand chart.</p>
1086−-
1087−- <ul>
1088−- <li><i>OLS regression</i> indicates the
1089−- time estimated for a single loop iteration using an ordinary
1090−- least-squares regression model. This number is more accurate
1091−- than the <i>mean</i> estimate below it, as it more effectively
1092−- eliminates measurement overhead and other constant factors.</li>
1093−- <li><i>R&#xb2; goodness-of-fit</i> is a measure of how
1094−- accurately the linear regression model fits the observed
1095−- measurements. If the measurements are not too noisy, R&#xb2;
1096−- should lie between 0.99 and 1, indicating an excellent fit. If
1097−- the number is below 0.99, something is confounding the accuracy
1098−- of the linear model.</li>
1099−- <li><i>Mean execution time</i> and <i>standard deviation</i> are
1100−- statistics calculated from execution time
1101−- divided by number of iterations.</li>
1102−- </ul>
1103−-
1104−- <p>We use a statistical technique called
1105−- the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a>
1106−- to provide confidence intervals on our estimates. The
1107−- bootstrap-derived upper and lower bounds on estimates let you see
1108−- how accurate we believe those estimates to be. (Hover the mouse
1109−- over the table headers to see the confidence levels.)</p>
1110−-
1111−- <p>A noisy benchmarking environment can cause some or many
1112−- measurements to fall far from the mean. These outlying
1113−- measurements can have a significant inflationary effect on the
1114−- estimate of the standard deviation. We calculate and display an
1115−- estimate of the extent to which the standard deviation has been
1116−- inflated by outliers.</p>
1117−-
1118−-<script type="text/javascript">
1119−-$(function () {
1120−- function mangulate(rpt) {
1121−- var measured = function(key) {
1122−- var idx = rpt.reportKeys.indexOf(key);
1123−- return rpt.reportMeasured.map(function(r) { return r[idx]; });
1124−- };
1125−- var number = rpt.reportNumber;
1126−- var name = rpt.reportName;
1127−- var mean = rpt.reportAnalysis.anMean.estPoint;
1128−- var iters = measured("iters");
1129−- var times = measured("time");
1130−- var kdetimes = rpt.reportKDEs[0].kdeValues;
1131−- var kdepdf = rpt.reportKDEs[0].kdePDF;
1132−-
1133−- var meanSecs = mean;
1134−- var units = $.timeUnits(mean);
1135−- var rgrs = rpt.reportAnalysis.anRegress[0];
1136−- var scale = units[0];
1137−- var olsTime = rgrs.regCoeffs.iters;
1138−- $(".olstimept" + number).text(function() {
1139−- return $.renderTime(olsTime.estPoint);
1140−- });
1141−- $(".olstimelb" + number).text(function() {
1142−- return $.renderTime(olsTime.estLowerBound);
1143−- });
1144−- $(".olstimeub" + number).text(function() {
1145−- return $.renderTime(olsTime.estUpperBound);
1146−- });
1147−- $(".olsr2pt" + number).text(function() {
1148−- return rgrs.regRSquare.estPoint.toFixed(3);
1149−- });
1150−- $(".olsr2lb" + number).text(function() {
1151−- return rgrs.regRSquare.estLowerBound.toFixed(3);
1152−- });
1153−- $(".olsr2ub" + number).text(function() {
1154−- return rgrs.regRSquare.estUpperBound.toFixed(3);
1155−- });
1156−- mean *= scale;
1157−- kdetimes = $.scaleBy(scale, kdetimes);
1158−- var kq = $("#kde" + number);
1159−- var k = $.plot(kq,
1160−- [{ label: name + " time densities",
1161−- data: $.zip(kdetimes, kdepdf),
1162−- }],
1163−- { xaxis: { tickFormatter: $.unitFormatter(scale) },
1164−- yaxis: { ticks: false },
1165−- grid: { borderColor: "#777",
1166−- hoverable: true, markings: [ { color: '#6fd3fb',
1167−- lineWidth: 1.5, xaxis: { from: mean, to: mean } } ] },
1168−- });
1169−- var o = k.pointOffset({ x: mean, y: 0});
1170−- kq.append('<div class="meanlegend" title="' + $.renderTime(meanSecs) +
1171−- '" style="position:absolute;left:' + (o.left + 4) +
1172−- 'px;bottom:139px;">mean</div>');
1173−- $.addTooltip("#kde" + number,
1174−- function(secs) { return $.renderTime(secs / scale); });
1175−- var timepairs = new Array(times.length);
1176−- var lastiter = iters[iters.length-1];
1177−- var olspairs = [[0,0], [lastiter, lastiter * scale * olsTime.estPoint]];
1178−- for (var i = 0; i < times.length; i++)
1179−- timepairs[i] = [iters[i],times[i]*scale];
1180−- iterFormatter = function() {
1181−- var denom = 0;
1182−- return function(iters) {
1183−- if (iters == 0)
1184−- return '';
1185−- if (denom > 0)
1186−- return (iters / denom).toFixed();
1187−- var power;
1188−- if (iters >= 1e9) {
1189−- denom = '1e9'; power = '&#x2079;';
1190−- }
1191−- if (iters >= 1e6) {
1192−- denom = '1e6'; power = '&#x2076;';
1193−- }
1194−- else if (iters >= 1e3) {
1195−- denom = '1e3'; power = '&#xb3;';
1196−- }
1197−- else denom = 1;
1198−- if (denom > 1) {
1199−- iters = (iters / denom).toFixed();
1200−- iters += '&times;10' + power + ' iters';
1201−- } else {
1202−- iters += ' iters';
1203−- }
1204−- return iters;
1205−- };
1206−- };
1207−- $.plot($("#time" + number),
1208−- [{ label: "regression", data: olspairs,
1209−- lines: { show: true } },
1210−- { label: name + " times", data: timepairs,
1211−- points: { show: true } }],
1212−- { grid: { borderColor: "#777", hoverable: true },
1213−- xaxis: { tickFormatter: iterFormatter() },
1214−- yaxis: { tickFormatter: $.unitFormatter(scale) } });
1215−- $.addTooltip("#time" + number,
1216−- function(iters,secs) {
1217−- return ($.renderTime(secs / scale) + ' / ' +
1218−- iters.toLocaleString() + ' iters');
1219−- });
1220−- if (0) {
1221−- var cyclepairs = new Array(cycles.length);
1222−- for (var i = 0; i < cycles.length; i++)
1223−- cyclepairs[i] = [cycles[i],i];
1224−- $.plot($("#cycle" + number),
1225−- [{ label: name + " cycles",
1226−- data: cyclepairs }],
1227−- { points: { show: true },
1228−- grid: { borderColor: "#777", hoverable: true },
1229−- xaxis: { tickFormatter:
1230−- function(cycles,axis) { return cycles + ' cycles'; }},
1231−- yaxis: { ticks: false },
1232−- });
1233−- $.addTooltip("#cycles" + number, function(x,y) { return x + ' cycles'; });
1234−- }
1235−- };
1236−- var reports = [{"reportAnalysis":{"anMean":{"estUpperBound":5.713526073454561e-3,"estLowerBound":5.54613319607341e-3,"estPoint":5.621667703915931e-3,"estConfidenceLevel":0.95},"anRegress":[{"regRSquare":{"estUpperBound":0.9981729010272332,"estLowerBound":0.9933906306034458,"estPoint":0.9962485177728473,"estConfidenceLevel":0.95},"regResponder":"time","regCoeffs":{"y":{"estUpperBound":1.73831239286272e-3,"estLowerBound":-2.6907153863794868e-3,"estPoint":-5.701833877751966e-4,"estConfidenceLevel":0.95},"iters":{"estUpperBound":5.78662208554795e-3,"estLowerBound":5.560561655965624e-3,"estPoint":5.671235930328669e-3,"estConfidenceLevel":0.95}}}],"anStdDev":{"estUpperBound":3.1487131555210624e-4,"estLowerBound":1.972562820146363e-4,"estPoint":2.494938876886024e-4,"estConfidenceLevel":0.95},"anOutlierVar":{"ovFraction":0.21993690418913867,"ovDesc":"moderate","ovEffect":"Moderate"},"anOverhead":2.7511337567346434e-6},"reportKDEs":[{"kdeValues":[5.119598999459214e-3,5.128773133785027e-3,5.137947268110841e-3,5.1471214024366545e-3,5.156295536762469e-3,5.165469671088282e-3,5.174643805414095e-3,5.1838179397399094e-3,5.192992074065723e-3,5.202166208391536e-3,5.21134034271735e-3,5.2205144770431635e-3,5.229688611368978e-3,5.238862745694791e-3,5.248036880020604e-3,5.2572110143464185e-3,5.266385148672232e-3,5.275559282998045e-3,5.284733417323859e-3,5.293907551649673e-3,5.303081685975487e-3,5.3122558203013e-3,5.321429954627113e-3,5.3306040889529276e-3,5.339778223278741e-3,5.348952357604554e-3,5.358126491930368e-3,5.367300626256182e-3,5.376474760581996e-3,5.385648894907809e-3,5.3948230292336224e-3,5.403997163559437e-3,5.41317129788525e-3,5.422345432211064e-3,5.431519566536877e-3,5.440693700862691e-3,5.449867835188505e-3,5.459041969514318e-3,5.4682161038401315e-3,5.477390238165946e-3,5.486564372491759e-3,5.495738506817573e-3,5.5049126411433865e-3,5.5140867754692e-3,5.523260909795014e-3,5.532435044120827e-3,5.541609178446641e-3,5.550783312772455e-3,5.559957447098268e-3,5.569131581424082e-3,5.5783057157498955e-3,5.587479850075709e-3,5.596653984401523e-3,5.605828118727336e-3,5.6150022530531505e-3,5.624176387378964e-3,5.633350521704777e-3,5.642524656030591e-3,5.651698790356405e-3,5.660872924682218e-3,5.670047059008032e-3,5.679221193333845e-3,5.688395327659659e-3,5.697569461985473e-3,5.706743596311286e-3,5.7159177306371e-3,5.725091864962914e-3,5.734265999288727e-3,5.743440133614541e-3,5.7526142679403544e-3,5.761788402266169e-3,5.770962536591982e-3,5.780136670917795e-3,5.789310805243609e-3,5.798484939569423e-3,5.807659073895236e-3,5.81683320822105e-3,5.8260073425468635e-3,5.835181476872677e-3,5.844355611198491e-3,5.853529745524304e-3,5.8627038798501185e-3,5.871878014175932e-3,5.881052148501745e-3,5.890226282827559e-3,5.8994004171533726e-3,5.908574551479187e-3,5.917748685805e-3,5.926922820130813e-3,5.9360969544566275e-3,5.945271088782441e-3,5.954445223108255e-3,5.963619357434068e-3,5.972793491759882e-3,5.981967626085696e-3,5.991141760411509e-3,6.000315894737322e-3,6.009490029063137e-3,6.01866416338895e-3,6.027838297714763e-3,6.037012432040577e-3,6.046186566366391e-3,6.055360700692205e-3,6.064534835018018e-3,6.0737089693438315e-3,6.082883103669646e-3,6.092057237995459e-3,6.101231372321273e-3,6.1104055066470864e-3,6.1195796409729e-3,6.128753775298714e-3,6.137927909624527e-3,6.147102043950341e-3,6.156276178276155e-3,6.165450312601968e-3,6.174624446927781e-3,6.1837985812535955e-3,6.192972715579409e-3,6.202146849905223e-3,6.211320984231036e-3,6.22049511855685e-3,6.229669252882664e-3,6.238843387208477e-3,6.248017521534291e-3,6.2571916558601046e-3,6.266365790185918e-3,6.275539924511732e-3,6.284714058837545e-3],"kdeType":"time","kdePDF":[545.3406018643898,547.7604964408598,552.5835234544184,559.7762994995815,569.2891013325717,581.0562871577982,594.9968565868016,611.0151474314513,629.0016666408812,648.8340516123199,670.3781567871325,693.4892588878535,718.0133723788433,743.7886647772734,770.646959352757,798.4153105965786,826.9176356903382,855.9763831421388,885.414217874883,915.0557004354534,944.7289367329893,974.2671738896564,1003.5103174688135,1032.3063455895392,1060.5125962828472,1087.9969059134382,1114.638578580714,1140.3291691007228,1164.9730654118175,1188.4878599745812,1210.804503865528,1231.8672416915,1251.6333300617102,1270.0725470211678,1287.166504442057,1302.9077797566918,1317.2988874695457,1330.3511144872584,1342.0832463483428,1352.5202138285747,1361.6916910736854,1369.630677319676,1376.372094378115,1381.9514313884627,1386.4034668948157,1389.7610961362368,1392.0542886142364,1393.3091976024104,1393.5474393905565,1392.7855558190963,1391.0346691763316,1388.3003339216605,1384.5825850817816,1379.8761786596651,1374.1710151048017,1367.4527329151629,1359.703455859914,1350.9026741969292,1341.028237663689,1330.057435982098,1317.9681411582083,1304.739984983345,1290.35554484537,1274.801511217554,1258.0698109758134,1240.1586619629556,1221.0735359229834,1200.8280090176215,1179.4444815546556,1156.9547512468462,1133.4004272230616,1108.8331750741968,1083.314786380294,1056.9170693808599,1029.7215606678844,1001.8190609552112,973.309001064742,944.2986472297946,914.9021576099989,885.2395045052625,855.4352791137583,825.6173977689432,795.9157303818314,766.4606732786749,737.3816897331639,708.8058422221862,680.8563407630685,653.6511316010611,627.3015499956838,601.9110598974106,577.5741019124631,554.3750691326807,532.3874281777079,511.6730001869569,492.2814135481128,474.24973690783065,457.6022975395997,442.35068651491076,428.4939484168154,416.0189496374037,404.9009157051916,395.1041246902782,386.58274062916485,379.28176818856923,373.1381075322609,368.08168664034343,364.03664721565093,360.9225598393534,358.6556442299356,357.1499713174148,356.31862534611537,356.0748063195876,356.3328557329458,357.00919161294235,358.0231422981528,359.29767202005786,360.7599950594725,362.34207891564233,363.98104040137895,365.61944173689216,367.2054964387313,368.6931969866561,370.04237781945346,371.21872810527947,372.19376892518954,372.9448090019323,373.45489193123836,373.7127460898599]}],"reportKeys":["time","cpuTime","cycles","iters","allocated","numGcs","bytesCopied","mutatorWallSeconds","mutatorCpuSeconds","gcWallSeconds","gcCpuSeconds"],"reportNumber":0,"reportName":"ByteString/HashMap/random","reportOutliers":{"highSevere":0,"highMild":0,"lowMild":0,"samplesSeen":34,"lowSevere":0},"reportMeasured":[[4.97827198705636e-3,4.97199999999999e-3,10935260,1,null,null,null,null,null,null,null],[1.0848715988686308e-2,1.0847999999999997e-2,23877636,2,null,null,null,null,null,null,null],[1.7607376008527353e-2,1.7608e-2,38752116,3,null,null,null,null,null,null,null],[2.2017084003891796e-2,2.201800000000001e-2,48451954,4,null,null,null,null,null,null,null],[2.8329552995273843e-2,2.8330000000000022e-2,62340584,5,null,null,null,null,null,null,null],[3.288370498921722e-2,3.2885e-2,72359180,6,null,null,null,null,null,null,null],[3.651821901439689e-2,3.6518999999999996e-2,80349114,7,null,null,null,null,null,null,null],[4.358184800366871e-2,4.358200000000001e-2,95888910,8,null,null,null,null,null,null,null],[4.937931601307355e-2,4.937999999999998e-2,108645950,9,null,null,null,null,null,null,null],[5.358721798984334e-2,5.3586999999999996e-2,117903888,10,null,null,null,null,null,null,null],[5.955264199292287e-2,5.9538000000000035e-2,131027266,11,null,null,null,null,null,null,null],[6.518080999376252e-2,6.518099999999993e-2,143410836,12,null,null,null,null,null,null,null],[7.247712599928491e-2,7.247799999999993e-2,159464728,13,null,null,null,null,null,null,null],[8.270343899494037e-2,8.269899999999997e-2,181965766,14,null,null,null,null,null,null,null],[9.246958102448843e-2,9.240900000000007e-2,203443998,15,null,null,null,null,null,null,null],[9.887698100646958e-2,9.882600000000019e-2,217539578,16,null,null,null,null,null,null,null],[9.008563501993194e-2,9.0086e-2,198198564,17,null,null,null,null,null,null,null],[9.605592401931062e-2,9.605600000000003e-2,211332948,18,null,null,null,null,null,null,null],[0.1098186599847395,0.10976399999999997,241619440,19,null,null,null,null,null,null,null],[0.11373145499965176,0.11368299999999998,250220460,20,null,null,null,null,null,null,null],[0.11196174900396727,0.11196300000000003,246324226,21,null,null,null,null,null,null,null],[0.11884062600438483,0.11883500000000025,261465680,22,null,null,null,null,null,null,null],[0.1309775369882118,0.13096599999999992,288160116,23,null,null,null,null,null,null,null],[0.15469190399744548,0.15454900000000027,340335528,25,null,null,null,null,null,null,null],[0.149413135019131,0.14938300000000004,328727582,26,null,null,null,null,null,null,null],[0.15268685299088247,0.1526869999999998,335924804,27,null,null,null,null,null,null,null],[0.16147131499019451,0.16141300000000003,355254128,28,null,null,null,null,null,null,null],[0.16141338399029337,0.16139899999999985,355124102,30,null,null,null,null,null,null,null],[0.1728718529921025,0.17285800000000018,380334180,31,null,null,null,null,null,null,null],[0.1909069080138579,0.1908850000000002,420007910,33,null,null,null,null,null,null,null],[0.2043934800021816,0.20432799999999984,449680454,35,null,null,null,null,null,null,null],[0.20723143400391564,0.2070940000000001,455922034,36,null,null,null,null,null,null,null],[0.21014673498575576,0.21012200000000014,462335922,38,null,null,null,null,null,null,null],[0.22118496999610215,0.22116299999999978,486620020,40,null,null,null,null,null,null,null],[0.23701548800454475,0.23698700000000006,521448894,42,null,null,null,null,null,null,null],[0.23784394899848849,0.2378,523268016,44,null,null,null,null,null,null,null],[0.26553260401124135,0.26552299999999995,584189408,47,null,null,null,null,null,null,null],[0.28692550500272773,0.28688300000000044,631256144,49,null,null,null,null,null,null,null],[0.29316152300452814,0.29309600000000025,644973614,52,null,null,null,null,null,null,null]]}];
1237−- reports.map(mangulate);
1238−-
1239−- var benches = ["ByteString/HashMap/random",];
1240−- var ylabels = [[-0,'<a href="#b0">ByteString/HashMap/random</a>'],];
1241−- var means = $.scaleTimes([5.621667703915931e-3,]);
1242−- var xs = [];
1243−- var prev = null;
1244−- for (var i = 0; i < means[0].length; i++) {
1245−- var name = benches[i].split(/\//);
1246−- name.pop();
1247−- name = name.join('/');
1248−- if (name != prev) {
1249−- xs.push({ label: name, data: [[means[0][i], -i]]});
1250−- prev = name;
1251−- }
1252−- else
1253−- xs[xs.length-1].data.push([means[0][i],-i]);
1254−- }
1255−- var oq = $("#overview");
1256−- o = $.plot(oq, xs, { bars: { show: true, horizontal: true,
1257−- barWidth: 0.75, align: "center" },
1258−- grid: { borderColor: "#777", hoverable: true },
1259−- legend: { show: xs.length > 1 },
1260−- xaxis: { max: Math.max.apply(undefined,means[0]) * 1.02 },
1261−- yaxis: { ticks: ylabels, tickColor: '#ffffff' } });
1262−- if (benches.length > 3)
1263−- o.getPlaceholder().height(28*benches.length);
1264−- o.resize();
1265−- o.setupGrid();
1266−- o.draw();
1267−- $.addTooltip("#overview", function(x,y) { return $.renderTime(x / means[1]); });
1268−-});
1269−-$(document).ready(function () {
1270−- $(".time").text(function(_, text) {
1271−- return $.renderTime(text);
1272−- });
1273−- $(".citime").text(function(_, text) {
1274−- return $.renderTime(text);
1275−- });
1276−- $(".percent").text(function(_, text) {
1277−- return (text*100).toFixed(1);
1278−- });
1279−- });
1280−-</script>
1281−-
1282−- </div>
1283−- </div>
1284−- <div id="footer">
1285−- <div class="body">
1286−- <div class="footfirst">
1287−- <h2>colophon</h2>
1288−- <p>This report was created using the
1289−- <a href="http://hackage.haskell.org/package/criterion">criterion</a>
1290−- benchmark execution and performance analysis tool.</p>
1291−- <p>Criterion is developed and maintained
1292−- by <a href="http://www.serpentine.com/blog/">Bryan O'Sullivan</a>.</p>
1293−- </div>
1294−- </div>
1295−- </div>
1296−- </body>
1297−-</html>
1298−diff -ruN orig/templates/default2.tpl new/templates/default2.tpl
1299−--- orig/templates/default2.tpl 2014-08-10 20:30:05.793809138 +0300
1300−+++ new/templates/default2.tpl 1970-01-01 02:00:00.000000000 +0200
1301−@@ -1,296 +0,0 @@
1302−-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
1303−-<html>
1304−- <head>
1305−- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1306−- <title>criterion report</title>
1307−- <!--[if lte IE 8]>
1308−- <script language="javascript" type="text/javascript">
1309−- {{#include}}js/excanvas-r3.min.js{{/include}}
1310−- </script>
1311−- <![endif]-->
1312−- <script language="javascript" type="text/javascript">
1313−- {{#include}}js/jquery-1.6.4.min.js{{/include}}
1314−- </script>
1315−- <script language="javascript" type="text/javascript">
1316−- {{#include}}js/jquery.flot-0.7.min.js{{/include}}
1317−- </script>
1318−- <script language="javascript" type="text/javascript">
1319−- {{#include}}js/jquery.criterion.js{{/include}}
1320−- </script>
1321−- <style type="text/css">
1322−-{{#include}}criterion.css{{/include}}
1323−- </style>
1324−- <!--[if !IE 7]>
1325−- <style type="text/css">
1326−- #wrap {display:table;height:100%}
1327−- </style>
1328−- <![endif]-->
1329−- </head>
1330−- <body>
1331−- <div id="wrap">
1332−- <div id="main" class="body">
1333−- <h1>criterion performance measurements</h1>
1334−-
1335−-<h2>overview</h2>
1336−-
1337−-<p><a href="#grokularation">want to understand this report?</a></p>
1338−-
1339−-<div id="overview" class="ovchart" style="width:900px;height:100px;"></div>
1340−-
1341−-{{#report}}
1342−-<h2><a name="b{{number}}">{{name}}</a></h2>
1343−- <table width="100%">
1344−- <tbody>
1345−- <tr>
1346−- <td><div id="kde{{number}}" class="kdechart"
1347−- style="width:450px;height:278px;"></div></td>
1348−- <td><div id="time{{number}}" class="timechart"
1349−- style="width:450px;height:278px;"></div></td>
1350−-<!--
1351−- <td><div id="cycle{{number}}" class="cyclechart"
1352−- style="width:300px;height:278px;"></div></td>
1353−--->
1354−- </tr>
1355−- </tbody>
1356−- </table>
1357−- <table>
1358−- <thead class="analysis">
1359−- <th></th>
1360−- <th class="cibound"
1361−- title="{{anMean.estConfidenceLevel}} confidence level">lower bound</th>
1362−- <th>estimate</th>
1363−- <th class="cibound"
1364−- title="{{anMean.estConfidenceLevel}} confidence level">upper bound</th>
1365−- </thead>
1366−- <tbody>
1367−- <tr>
1368−- <td>Mean execution time</td>
1369−- <td><span class="citime">{{anMean.estLowerBound}}</span></td>
1370−- <td><span class="time">{{anMean.estPoint}}</span></td>
1371−- <td><span class="citime">{{anMean.estUpperBound}}</span></td>
1372−- </tr>
1373−- <tr>
1374−- <td>Standard deviation</td>
1375−- <td><span class="citime">{{anStdDev.estLowerBound}}</span></td>
1376−- <td><span class="time">{{anStdDev.estPoint}}</span></td>
1377−- <td><span class="citime">{{anStdDev.estUpperBound}}</span></td>
1378−- </tr>
1379−- </tbody>
1380−- </table>
1381−-
1382−- <span class="outliers">
1383−- <p>Outlying measurements have {{anOutlierVar.ovDesc}}
1384−- (<span class="percent">{{anOutlierVar.ovFraction}}</span>%)
1385−- effect on estimated standard deviation.</p>
1386−- </span>
1387−-{{/report}}
1388−-
1389−- <h2><a name="grokularation">understanding this report</a></h2>
1390−-
1391−- <p>In this report, each function benchmarked by criterion is assigned
1392−- a section of its own. In each section, we display two charts, each
1393−- with an <i>x</i> axis that represents measured execution time.
1394−- These charts are active; if you hover your mouse over data points
1395−- and annotations, you will see more details.</p>
1396−-
1397−- <ul>
1398−- <li>The chart on the left is a
1399−- <a href="http://en.wikipedia.org/wiki/Kernel_density_estimation">kernel
1400−- density estimate</a> (also known as a KDE) of time
1401−- measurements. This graphs the probability of any given time
1402−- measurement occurring. A spike indicates that a measurement of a
1403−- particular time occurred; its height indicates how often that
1404−- measurement was repeated.</li>
1405−-
1406−- <li>The chart on the right is the raw data from which the kernel
1407−- density estimate is built. Measurements are displayed on
1408−- the <i>x</i> axis in the order in which they occurred. The
1409−- number of iterations of the measurement loop increases with each
1410−- successive measurement.</li>
1411−- </ul>
1412−-
1413−- <p>Under the charts is a small table displaying the mean and standard
1414−- deviation of the measurements. We use a statistical technique
1415−- called
1416−- the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a>
1417−- to provide confidence intervals on our estimates of these values.
1418−- The bootstrap-derived upper and lower bounds on the mean and
1419−- standard deviation let you see how accurate we believe those
1420−- estimates to be. (Hover the mouse over the table headers to see
1421−- the confidence levels.)</p>
1422−-
1423−- <p>A noisy benchmarking environment can cause some or many
1424−- measurements to fall far from the mean. These outlying
1425−- measurements can have a significant inflationary effect on the
1426−- estimate of the standard deviation. We calculate and display an
1427−- estimate of the extent to which the standard deviation has been
1428−- inflated by outliers.</p>
1429−-
1430−-<script type="text/javascript">
1431−-$(function () {
1432−-/*
1433−- function mangulate(number, name, mean, iters, times, cycles,
1434−- kdetimes, kdepdf) */
1435−- function mangulate(rpt) {
1436−- var number = rpt.reportNumber;
1437−- var name = rpt.reportName;
1438−- var mean = rpt.reportAnalysis.anMean.estPoint;
1439−- var measured = function(key) {
1440−- var idx = rpt.reportKeys.indexOf(key);
1441−- return rpt.reportMeasured.map(function(r) { return r[idx]; });
1442−- };
1443−- var iters = measured("iters");
1444−- var times = measured("times");
1445−- var meanSecs = mean;
1446−- var units = $.timeUnits(mean);
1447−- var scale = units[0];
1448−- mean *= scale;
1449−- kdetimes = $.scaleBy(scale, kdetimes);
1450−- var kq = $("#kde" + number);
1451−- var k = $.plot(kq,
1452−- [{ label: name + " time densities",
1453−- data: $.zip(kdetimes, kdepdf),
1454−- }],
1455−- { xaxis: { tickFormatter: $.unitFormatter(scale) },
1456−- yaxis: { ticks: false },
1457−- grid: { borderColor: "#777",
1458−- hoverable: true, markings: [ { color: '#6fd3fb',
1459−- lineWidth: 1.5, xaxis: { from: mean, to: mean } } ] },
1460−- });
1461−- var o = k.pointOffset({ x: mean, y: 0});
1462−- kq.append('<div class="meanlegend" title="' + $.renderTime(meanSecs) +
1463−- '" style="position:absolute;left:' + (o.left + 4) +
1464−- 'px;bottom:139px;">mean</div>');
1465−- $.addTooltip("#kde" + number,
1466−- function(secs) { return $.renderTime(secs / scale); });
1467−- var timepairs = new Array(times.length);
1468−- for (var i = 0; i < times.length; i++)
1469−- timepairs[i] = [iters[i],times[i]*scale];
1470−- iterFormatter = function() {
1471−- var denom = 0;
1472−- return function(iters) {
1473−- if (iters == 0)
1474−- return '';
1475−- if (denom > 0)
1476−- return (iters / denom).toFixed();
1477−- var exp;
1478−- if (iters >= 1e9) {
1479−- denom = '1e9'; exp = 9;
1480−- }
1481−- if (iters >= 1e6) {
1482−- denom = '1e6'; exp = 6;
1483−- }
1484−- else if (iters >= 1e3) {
1485−- denom = '1e3'; exp = 3;
1486−- }
1487−- else denom = 1;
1488−- if (denom > 1) {
1489−- iters = (iters / denom).toFixed();
1490−- iters += '&times;10<sup>' + exp + '</sup> iters';
1491−- } else {
1492−- iters += ' iters';
1493−- }
1494−- return iters;
1495−- };
1496−- };
1497−- $.plot($("#time" + number),
1498−- [{ label: name + " times",
1499−- data: timepairs }],
1500−- { points: { show: true },
1501−- grid: { borderColor: "#777", hoverable: true },
1502−- xaxis: { tickFormatter: iterFormatter() },
1503−- yaxis: { tickFormatter: $.unitFormatter(scale) },
1504−- });
1505−- $.addTooltip("#time" + number,
1506−- function(iters,secs) {
1507−- return ($.renderTime(secs / scale) + ' / ' +
1508−- iters.toLocaleString() + ' iters');
1509−- });
1510−- if (0) {
1511−- var cyclepairs = new Array(cycles.length);
1512−- for (var i = 0; i < cycles.length; i++)
1513−- cyclepairs[i] = [cycles[i],i];
1514−- $.plot($("#cycle" + number),
1515−- [{ label: name + " cycles",
1516−- data: cyclepairs }],
1517−- { points: { show: true },
1518−- grid: { borderColor: "#777", hoverable: true },
1519−- xaxis: { tickFormatter:
1520−- function(cycles,axis) { return cycles + ' cycles'; }},
1521−- yaxis: { ticks: false },
1522−- });
1523−- $.addTooltip("#cycles" + number, function(x,y) { return x + ' cycles'; });
1524−- }
1525−- };
1526−- var reports = {{json}};
1527−- reports.map(mangulate);
1528−- {{#report}}
1529−- mangulate(/* report number */ {{number}},
1530−- /* report name */ "{{name}}",
1531−- /* estimated mean */ {{anMean.estPoint}},
1532−- /* iterations */ [{{#iters}}{{x}},{{/iters}}],
1533−- /* measured times */ [{{#times}}{{x}},{{/times}}],
1534−- /* measured cycles */ [{{#cycles}}{{x}},{{/cycles}}],
1535−- /* kde times */ [{{#kdetimes}}{{x}},{{/kdetimes}}],
1536−- /* kde pdf */ [{{#kdepdf}}{{x}},{{/kdepdf}}]);
1537−- {{/report}}
1538−-
1539−- var benches = [{{#report}}"{{name}}",{{/report}}];
1540−- var ylabels = [{{#report}}[-{{number}},'<a href="#b{{number}}">{{name}}</a>'],{{/report}}];
1541−- var means = $.scaleTimes([{{#report}}{{anMean.estPoint}},{{/report}}]);
1542−- var xs = [];
1543−- var prev = null;
1544−- for (var i = 0; i < means[0].length; i++) {
1545−- var name = benches[i].split(/\//);
1546−- name.pop();
1547−- name = name.join('/');
1548−- if (name != prev) {
1549−- xs.push({ label: name, data: [[means[0][i], -i]]});
1550−- prev = name;
1551−- }
1552−- else
1553−- xs[xs.length-1].data.push([means[0][i],-i]);
1554−- }
1555−- var oq = $("#overview");
1556−- o = $.plot(oq, xs, { bars: { show: true, horizontal: true,
1557−- barWidth: 0.75, align: "center" },
1558−- grid: { borderColor: "#777", hoverable: true },
1559−- legend: { show: xs.length > 1 },
1560−- xaxis: { max: Math.max.apply(undefined,means[0]) * 1.02 },
1561−- yaxis: { ticks: ylabels, tickColor: '#ffffff' } });
1562−- if (benches.length > 3)
1563−- o.getPlaceholder().height(28*benches.length);
1564−- o.resize();
1565−- o.setupGrid();
1566−- o.draw();
1567−- $.addTooltip("#overview", function(x,y) { return $.renderTime(x / means[1]); });
1568−-});
1569−-$(document).ready(function () {
1570−- $(".time").text(function(_, text) {
1571−- return $.renderTime(text);
1572−- });
1573−- $(".citime").text(function(_, text) {
1574−- return $.renderTime(text);
1575−- });
1576−- $(".percent").text(function(_, text) {
1577−- return (text*100).toFixed(1);
1578−- });
1579−- });
1580−-</script>
1581−-
1582−- </div>
1583−- </div>
1584−- <div id="footer">
1585−- <div class="body">
1586−- <div class="footfirst">
1587−- <h2>colophon</h2>
1588−- <p>This report was created using the
1589−- <a href="http://hackage.haskell.org/package/criterion">criterion</a>
1590−- benchmark execution and performance analysis tool.</p>
1591−- <p>Criterion is developed and maintained
1592−- by <a href="http://www.serpentine.com/blog/">Bryan O'Sullivan</a>.</p>
1593−- </div>
1594−- </div>
1595−- </div>
1596−- </body>
1597−-</html>
1598−diff -ruN orig/tests/Properties.hs new/tests/Properties.hs
1599−--- orig/tests/Properties.hs 1970-01-01 02:00:00.000000000 +0200
1600−+++ new/tests/Properties.hs 2014-08-10 20:30:05.000000000 +0300
1601−@@ -0,0 +1,42 @@
1602−+{-# LANGUAGE CPP #-}
1603−+{-# OPTIONS_GHC -fno-warn-orphans #-}
1604−+
1605−+module Properties (tests) where
1606−+
1607−+import Control.Applicative ((<$>))
1608−+import Criterion.Analysis
1609−+import Statistics.Types (Sample)
1610−+import Test.Framework (Test, testGroup)
1611−+import Test.Framework.Providers.QuickCheck2 (testProperty)
1612−+import Test.QuickCheck
1613−+import qualified Data.Vector.Generic as G
1614−+import qualified Data.Vector.Unboxed as U
1615−+
1616−+#if __GLASGOW_HASKELL__ >= 704
1617−+import Data.Monoid ((<>))
1618−+#else
1619−+import Data.Monoid
1620−+
1621−+(<>) :: Monoid m => m -> m -> m
1622−+(<>) = mappend
1623−+infixr 6 <>
1624−+#endif
1625−+
1626−+instance (Arbitrary a, U.Unbox a) => Arbitrary (U.Vector a) where
1627−+ arbitrary = U.fromList <$> arbitrary
1628−+ shrink = map U.fromList . shrink . U.toList
1629−+
1630−+outlier_bucketing :: Double -> Sample -> Bool
1631−+outlier_bucketing y ys =
1632−+ countOutliers (classifyOutliers xs) <= fromIntegral (G.length xs)
1633−+ where xs = U.cons y ys
1634−+
1635−+outlier_bucketing_weighted :: Double -> Sample -> Bool
1636−+outlier_bucketing_weighted x xs =
1637−+ outlier_bucketing x (xs <> G.replicate (G.length xs * 10) 0)
1638−+
1639−+tests :: Test
1640−+tests = testGroup "Properties" [
1641−+ testProperty "outlier_bucketing" outlier_bucketing
1642−+ , testProperty "outlier_bucketing_weighted" outlier_bucketing_weighted
1643−+ ]
patching/patches/csv-conduit-0.6.2.1.patchdeleted−32
@@ -1,32 +0,0 @@
1−diff -ru orig/csv-conduit.cabal new/csv-conduit.cabal
2−--- orig/csv-conduit.cabal 2014-04-03 10:44:52.994206357 +0300
3−+++ new/csv-conduit.cabal 2014-04-03 10:44:52.000000000 +0300
4−@@ -78,6 +78,7 @@
5− , base >= 4 && < 5
6− , bytestring
7− , conduit >= 1.0 && < 2.0
8−+ , conduit-extra
9− , containers >= 0.3
10− , monad-control
11− , text
12−@@ -90,6 +91,7 @@
13− , mtl
14− , mmorph
15− , primitive
16−+ , resourcet
17− ghc-prof-options: -fprof-auto
18−
19− if impl(ghc >= 7.2.1)
20−diff -ru orig/src/Data/CSV/Conduit.hs new/src/Data/CSV/Conduit.hs
21−--- orig/src/Data/CSV/Conduit.hs 2014-04-03 10:44:52.962206360 +0300
22−+++ new/src/Data/CSV/Conduit.hs 2014-04-03 10:44:52.000000000 +0300
23−@@ -36,6 +36,9 @@
24− import Control.Monad.Primitive
25− import Control.Monad.ST
26− import Control.Monad.Trans
27−+import Control.Monad.Trans.Resource (MonadResource, MonadThrow,
28−+ runExceptionT,
29−+ runResourceT)
30− import Data.Attoparsec.Types (Parser)
31− import qualified Data.ByteString as B
32− import Data.ByteString.Char8 (ByteString)
patching/patches/diagrams-builder-0.5.0.10.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/diagrams-builder.cabal new/diagrams-builder.cabal
2−--- orig/diagrams-builder.cabal 2014-05-23 06:40:50.633726383 +0300
3−+++ new/diagrams-builder.cabal 2014-05-23 06:40:50.000000000 +0300
4−@@ -59,7 +59,7 @@
5− cmdargs >= 0.6 && < 0.11,
6− lens >= 3.9 && < 4.2,
7− hashable >= 1.1 && < 1.3,
8−- exceptions >= 0.3 && < 0.6
9−+ exceptions >= 0.3 && < 0.7
10− hs-source-dirs: src
11− default-language: Haskell2010
12− other-extensions: StandaloneDeriving,
patching/patches/diagrams-builder-0.5.0.6.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/diagrams-builder.cabal new/diagrams-builder.cabal
2−--- orig/diagrams-builder.cabal 2014-04-03 08:17:21.630394766 +0300
3−+++ new/diagrams-builder.cabal 2014-04-03 08:17:21.000000000 +0300
4−@@ -59,7 +59,7 @@
5− cmdargs >= 0.6 && < 0.11,
6− lens >= 3.9 && < 4.2,
7− hashable >= 1.1 && < 1.3,
8−- exceptions >= 0.3 && < 0.4
9−+ exceptions >= 0.3 && < 0.6
10− hs-source-dirs: src
11− default-language: Haskell2010
12− other-extensions: StandaloneDeriving,
patching/patches/diagrams-builder-0.5.0.9.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/diagrams-builder.cabal new/diagrams-builder.cabal
2−--- orig/diagrams-builder.cabal 2014-05-11 11:28:24.019992070 +0300
3−+++ new/diagrams-builder.cabal 2014-05-11 11:28:23.000000000 +0300
4−@@ -59,7 +59,7 @@
5− cmdargs >= 0.6 && < 0.11,
6− lens >= 3.9 && < 4.2,
7− hashable >= 1.1 && < 1.3,
8−- exceptions >= 0.3 && < 0.6
9−+ exceptions >= 0.3 && < 0.7
10− hs-source-dirs: src
11− default-language: Haskell2010
12− other-extensions: StandaloneDeriving,
patching/patches/diagrams-builder-0.6.patchdeleted−27
@@ -1,27 +0,0 @@
1−diff -ruN orig/diagrams-builder.cabal new/diagrams-builder.cabal
2−--- orig/diagrams-builder.cabal 2014-08-10 08:43:22.462711726 +0300
3−+++ new/diagrams-builder.cabal 2014-08-10 08:43:22.000000000 +0300
4−@@ -57,7 +57,7 @@
5− split >= 0.2 && < 0.3,
6− haskell-src-exts >= 1.14 && < 1.16,
7− cmdargs >= 0.6 && < 0.11,
8−- lens >= 3.9 && < 4.3,
9−+ lens,
10− hashable >= 1.1 && < 1.3,
11− exceptions >= 0.3 && < 0.7
12− hs-source-dirs: src
13−@@ -100,7 +100,7 @@
14− diagrams-lib >= 0.6 && < 1.3,
15− diagrams-cairo >= 0.6 && < 1.3,
16− cmdargs >= 0.6 && < 0.11,
17−- lens >= 3.8 && < 4.3
18−+ lens
19−
20− executable diagrams-builder-svg
21− main-is: diagrams-builder-svg.hs
22−@@ -141,4 +141,4 @@
23− diagrams-lib >= 0.6 && < 1.3,
24− diagrams-postscript >= 0.6 && < 1.2,
25− cmdargs >= 0.6 && < 0.11,
26−- lens >= 3.8 && < 4.3
27−+ lens
patching/patches/diagrams-haddock-0.2.2.10.patchdeleted−21
@@ -1,21 +0,0 @@
1−diff -ruN orig/diagrams-haddock.cabal new/diagrams-haddock.cabal
2−--- orig/diagrams-haddock.cabal 2014-08-10 08:43:22.698711721 +0300
3−+++ new/diagrams-haddock.cabal 2014-08-10 08:43:22.000000000 +0300
4−@@ -48,7 +48,7 @@
5− diagrams-lib >= 0.6 && < 1.3,
6− diagrams-svg >= 0.8.0.1 && < 1.2,
7− vector-space >= 0.8 && < 0.9,
8−- lens >= 3.8 && < 4.3,
9−+ lens,
10− cpphs >= 1.15,
11− cautious-file >= 1.0 && < 1.1,
12− uniplate >= 1.6 && < 1.7,
13−@@ -81,7 +81,7 @@
14− tasty-quickcheck >= 0.8 && < 0.9,
15− parsec >= 3,
16− haskell-src-exts >= 1.14 && < 1.16,
17−- lens >= 3.8 && < 4.3,
18−+ lens,
19− diagrams-haddock
20− hs-source-dirs: test
21− default-language: Haskell2010
patching/patches/distributed-process-0.4.2.patchdeleted−96
@@ -1,96 +0,0 @@
1−diff -ru orig/distributed-process.cabal new/distributed-process.cabal
2−--- orig/distributed-process.cabal 2014-03-27 18:23:44.792359466 +0200
3−+++ new/distributed-process.cabal 2014-03-27 18:23:44.000000000 +0200
4−@@ -39,7 +39,7 @@
5−
6− Library
7− Build-Depends: base >= 4.4 && < 5,
8−- binary >= 0.5 && < 0.7,
9−+ binary >= 0.5,
10− network-transport >= 0.3 && < 0.4,
11− stm >= 2.3 && < 2.5,
12− transformers >= 0.2 && < 0.4,
13−@@ -53,7 +53,7 @@
14− ghc-prim >= 0.2 && < 0.4,
15− distributed-static >= 0.2 && < 0.3,
16− rank1dynamic >= 0.1 && < 0.2,
17−- syb >= 0.3 && < 0.4
18−+ syb >= 0.3
19− Exposed-modules: Control.Distributed.Process,
20− Control.Distributed.Process.Serializable,
21− Control.Distributed.Process.Closure,
22−@@ -90,11 +90,11 @@
23− Main-Is: TestCH.hs
24− Build-Depends: base >= 4.4 && < 5,
25− random >= 1.0 && < 1.1,
26−- ansi-terminal >= 0.5 && < 0.6,
27−+ ansi-terminal >= 0.5,
28− distributed-process,
29− network-transport >= 0.3 && < 0.4,
30− network-transport-tcp >= 0.3 && < 0.4,
31−- binary >= 0.5 && < 0.7,
32−+ binary >= 0.5,
33− network >= 2.3 && < 2.5,
34− HUnit >= 1.2 && < 1.3,
35− test-framework >= 0.6 && < 0.9,
36−@@ -111,7 +111,7 @@
37− Main-Is: TestClosure.hs
38− Build-Depends: base >= 4.4 && < 5,
39− random >= 1.0 && < 1.1,
40−- ansi-terminal >= 0.5 && < 0.6,
41−+ ansi-terminal >= 0.5,
42− distributed-static >= 0.2 && < 0.3,
43− distributed-process,
44− network-transport >= 0.3 && < 0.4,
45−@@ -131,13 +131,13 @@
46− Main-Is: TestStats.hs
47− Build-Depends: base >= 4.4 && < 5,
48− random >= 1.0 && < 1.1,
49−- ansi-terminal >= 0.5 && < 0.6,
50−+ ansi-terminal >= 0.5,
51− containers >= 0.4 && < 0.6,
52− stm >= 2.3 && < 2.5,
53− distributed-process,
54− network-transport >= 0.3 && < 0.4,
55− network-transport-tcp >= 0.3 && < 0.4,
56−- binary >= 0.5 && < 0.7,
57−+ binary >= 0.5,
58− network >= 2.3 && < 2.5,
59− HUnit >= 1.2 && < 1.3,
60− test-framework >= 0.6 && < 0.9,
61−@@ -156,7 +156,7 @@
62− distributed-process,
63− network-transport-tcp >= 0.3 && < 0.4,
64− bytestring >= 0.9 && < 0.11,
65−- binary >= 0.5 && < 0.7
66−+ binary >= 0.5
67− else
68− buildable: False
69− Main-Is: benchmarks/Throughput.hs
70−@@ -169,7 +169,7 @@
71− distributed-process,
72− network-transport-tcp >= 0.3 && < 0.4,
73− bytestring >= 0.9 && < 0.11,
74−- binary >= 0.5 && < 0.7
75−+ binary >= 0.5
76− else
77− buildable: False
78− Main-Is: benchmarks/Latency.hs
79−@@ -182,7 +182,7 @@
80− distributed-process,
81− network-transport-tcp >= 0.3 && < 0.4,
82− bytestring >= 0.9 && < 0.11,
83−- binary >= 0.5 && < 0.7
84−+ binary >= 0.5
85− else
86− buildable: False
87− Main-Is: benchmarks/Channels.hs
88−@@ -195,7 +195,7 @@
89− distributed-process,
90− network-transport-tcp >= 0.3 && < 0.4,
91− bytestring >= 0.9 && < 0.11,
92−- binary >= 0.5 && < 0.7
93−+ binary >= 0.5
94− else
95− buildable: False
96− Main-Is: benchmarks/Spawns.hs
patching/patches/distributed-process-simplelocalnet-0.2.0.9.patchdeleted−21
@@ -1,21 +0,0 @@
1−diff -ru orig/distributed-process-simplelocalnet.cabal new/distributed-process-simplelocalnet.cabal
2−--- orig/distributed-process-simplelocalnet.cabal 2014-03-27 18:23:44.960359467 +0200
3−+++ new/distributed-process-simplelocalnet.cabal 2014-03-27 18:23:44.000000000 +0200
4−@@ -33,7 +33,7 @@
5− network >= 2.3 && < 2.5,
6− network-multicast >= 0.0 && < 0.1,
7− data-accessor >= 0.2 && < 0.3,
8−- binary >= 0.5 && < 0.7,
9−+ binary >= 0.5,
10− containers >= 0.4 && < 0.6,
11− transformers >= 0.2 && < 0.4,
12− network-transport >= 0.3 && < 0.4,
13−@@ -55,7 +55,7 @@
14− network >= 2.3 && < 2.5,
15− network-multicast >= 0.0 && < 0.1,
16− data-accessor >= 0.2 && < 0.3,
17−- binary >= 0.5 && < 0.7,
18−+ binary >= 0.5,
19− containers >= 0.4 && < 0.6,
20− transformers >= 0.2 && < 0.4,
21− network-transport >= 0.3 && < 0.4,
patching/patches/distributive-0.4.3.patchdeleted−11
@@ -1,11 +0,0 @@
1−diff -ru orig/distributive.cabal new/distributive.cabal
2−--- orig/distributive.cabal 2014-04-03 09:44:06.518283977 +0300
3−+++ new/distributive.cabal 2014-04-03 09:44:06.000000000 +0300
4−@@ -36,6 +36,7 @@
5− tagged >= 0.7 && < 1,
6− transformers >= 0.2 && < 0.4,
7− transformers-compat >= 0.1 && < 0.2
8−+ , ghc-prim
9−
10− hs-source-dirs: src
11− exposed-modules:
patching/patches/esqueleto-1.3.8.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/esqueleto.cabal new/esqueleto.cabal
2−--- orig/esqueleto.cabal 2014-04-03 08:31:02.238377300 +0300
3−+++ new/esqueleto.cabal 2014-04-03 08:31:01.000000000 +0300
4−@@ -91,7 +91,7 @@
5− , containers
6− , HUnit
7− , QuickCheck
8−- , hspec >= 1.9
9−+ , hspec >= 1.8
10− , persistent-sqlite >= 1.2 && < 1.4
11− , persistent-template >= 1.2 && < 1.4
12− , monad-control
patching/patches/fay-0.19.0.2.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/fay.cabal new/fay.cabal
2−--- orig/fay.cabal 2014-03-13 05:59:43.874058759 +0200
3−+++ new/fay.cabal 2014-03-13 05:59:43.000000000 +0200
4−@@ -122,7 +122,7 @@
5− , language-ecmascript >= 0.15 && < 1.0
6− , mtl < 2.2
7− , pretty-show >= 1.6 && < 1.7
8−- , process < 1.2
9−+ , process < 1.3
10− , safe < 0.4
11− , split < 0.3
12− , syb < 0.5
patching/patches/fb-1.0.1.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/fb.cabal new/fb.cabal
2−--- orig/fb.cabal 2014-06-30 12:41:53.267551936 +0300
3−+++ new/fb.cabal 2014-06-30 12:41:52.000000000 +0300
4−@@ -76,7 +76,7 @@
5− , data-default
6− , http-types
7− , http-conduit >= 2.0 && < 2.2
8−- , attoparsec >= 0.10.4 && < 0.12
9−+ , attoparsec >= 0.10.4 && < 0.13
10− , unordered-containers
11− , aeson >= 0.5 && < 0.8
12− , base16-bytestring >= 0.1
patching/patches/foldl-1.0.2.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/foldl.cabal new/foldl.cabal
2−--- orig/foldl.cabal 2014-03-13 07:47:41.009928017 +0200
3−+++ new/foldl.cabal 2014-03-13 07:47:40.000000000 +0200
4−@@ -24,7 +24,7 @@
5− base >= 4 && < 5 ,
6− bytestring >= 0.9.2.1 && < 0.11,
7− primitive < 0.6 ,
8−- text >= 0.11.2.0 && < 1.1 ,
9−+ text >= 0.11.2.0 && < 1.2 ,
10− vector >= 0.7 && < 0.11
11− Exposed-Modules:
12− Control.Foldl,
patching/patches/force-layout-0.3.0.5.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ruN orig/force-layout.cabal new/force-layout.cabal
2−--- orig/force-layout.cabal 2014-08-10 08:43:22.898711717 +0300
3−+++ new/force-layout.cabal 2014-08-10 08:43:22.000000000 +0300
4−@@ -23,7 +23,7 @@
5− build-depends: base >= 4.2 && < 4.8,
6− vector-space >=0.7 && <0.9,
7− vector-space-points >= 0.1.1 && < 0.3,
8−- lens >= 3 && < 4.3,
9−+ lens,
10− containers >=0.4 && < 0.6,
11− data-default-class >= 0.0.1 && < 0.1
12− hs-source-dirs: src
patching/patches/github-0.7.4.patchdeleted−23
@@ -1,23 +0,0 @@
1−diff -ru orig/Github/Private.hs new/Github/Private.hs
2−--- orig/Github/Private.hs 2014-04-03 09:50:34.182275724 +0300
3−+++ new/Github/Private.hs 2014-04-03 09:50:33.000000000 +0300
4−@@ -14,7 +14,7 @@
5− import qualified Data.ByteString.Lazy.Char8 as LBS
6− import Network.HTTP.Types (Method, Status(..))
7− import Network.HTTP.Conduit
8−-import Data.Conduit (ResourceT)
9−+import Control.Monad.Trans.Resource (ResourceT)
10− import qualified Control.Exception as E
11− import Data.Maybe (fromMaybe)
12−
13−diff -ru orig/github.cabal new/github.cabal
14−--- orig/github.cabal 2014-04-03 09:50:34.194275724 +0300
15−+++ new/github.cabal 2014-04-03 09:50:33.000000000 +0300
16−@@ -158,6 +158,7 @@
17− http-types,
18− data-default,
19− vector,
20−+ resourcet,
21− unordered-containers >= 0.2 && < 0.3
22−
23− -- Modules not exported by this package.
patching/patches/gitlib-3.0.2.patchdeleted−191
@@ -1,191 +0,0 @@
1−diff -ru orig/Git/Commit/Push.hs new/Git/Commit/Push.hs
2−--- orig/Git/Commit/Push.hs 2014-04-06 09:02:45.571789820 +0300
3−+++ new/Git/Commit/Push.hs 2014-04-06 09:02:45.000000000 +0300
4−@@ -1,11 +1,11 @@
5− module Git.Commit.Push where
6−
7− import Control.Applicative
8−-import Control.Failure
9− import Control.Monad
10− import Control.Monad.IO.Class
11− import Control.Monad.Trans.Class
12− import Control.Monad.Trans.Control
13−+import Control.Monad.Trans.Resource
14− import Data.Function
15− import qualified Data.HashSet as HashSet
16− import Data.List
17−@@ -33,14 +33,14 @@
18− mrref' <- for mrref $ \rref ->
19− if rref `elem` commits
20− then lift $ copyCommitOid rref
21−- else failure $ PushNotFastForward
22−+ else throwM $ PushNotFastForward
23− $ "SHA " <> renderObjOid rref
24− <> " not found in remote"
25− objs <- lift $ listAllObjects mrref' coid
26− let shas = HashSet.fromList $ map (renderOid . untagObjOid) objs
27− (cref,_) <- copyCommit coid Nothing shas
28− unless (renderObjOid coid == renderObjOid cref) $
29−- failure $ BackendError $ "Error copying commit: "
30−+ throwM $ BackendError $ "Error copying commit: "
31− <> renderObjOid coid <> " /= " <> renderObjOid cref
32− -- jww (2013-04-18): This is something the user must decide to do
33− -- updateReference_ remoteRefName (RefObj cref)
34−@@ -79,6 +79,6 @@
35−
36− mref <- fmap renderOid <$> resolveReference refName
37− unless (maybe False (renderObjOid coid ==) mref) $
38−- failure (BackendError $
39−+ throwM (BackendError $
40− "Could not resolve destination reference '"
41− <> refName <> "'in project")
42−diff -ru orig/Git/Commit.hs new/Git/Commit.hs
43−--- orig/Git/Commit.hs 2014-04-06 09:02:45.571789820 +0300
44−+++ new/Git/Commit.hs 2014-04-06 09:02:45.000000000 +0300
45−@@ -1,8 +1,8 @@
46− module Git.Commit where
47−
48−-import Control.Failure
49− import Control.Monad
50− import Control.Monad.Trans.Class
51−+import Control.Monad.Trans.Resource
52− import Data.Conduit
53− import qualified Data.Conduit.List as CL
54− import Data.Function
55−@@ -41,7 +41,7 @@
56− (parentRefs,needed') <- foldM copyParent ([],needed) parents
57− (tr,needed'') <- copyTree (commitTree commit) needed'
58− unless (renderObjOid (commitTree commit) == renderObjOid tr) $
59−- failure $ BackendError $ "Error copying tree: "
60−+ throwM $ BackendError $ "Error copying tree: "
61− <> renderObjOid (commitTree commit)
62− <> " /= " <> renderObjOid tr
63−
64−@@ -60,7 +60,7 @@
65− copyParent (prefs,needed') cref = do
66− (cref2,needed'') <- copyCommit cref Nothing needed'
67− unless (renderObjOid cref == renderObjOid cref2) $
68−- failure $ BackendError $ "Error copying commit: "
69−+ throwM $ BackendError $ "Error copying commit: "
70− <> renderObjOid cref <> " /= " <> renderObjOid cref2
71− let x = cref2 `seq` (cref2:prefs)
72− return $ x `seq` needed'' `seq` (x,needed'')
73−diff -ru orig/Git/Repository.hs new/Git/Repository.hs
74−--- orig/Git/Repository.hs 2014-04-06 09:02:45.571789820 +0300
75−+++ new/Git/Repository.hs 2014-04-06 09:02:45.000000000 +0300
76−@@ -6,6 +6,7 @@
77− import Data.Conduit
78− import Git.Types
79− import System.Directory
80−+import Control.Monad.Trans.Control (MonadBaseControl)
81−
82− withNewRepository :: (MonadGit r n, MonadBaseControl IO n, MonadIO m)
83− => RepositoryFactory n m r
84−diff -ru orig/Git/Tree/Builder.hs new/Git/Tree/Builder.hs
85−--- orig/Git/Tree/Builder.hs 2014-04-06 09:02:45.571789820 +0300
86−+++ new/Git/Tree/Builder.hs 2014-04-06 09:02:45.000000000 +0300
87−@@ -25,12 +25,12 @@
88− ) where
89−
90− import Control.Applicative
91−-import Control.Failure
92− import Control.Monad
93− import Control.Monad.Fix
94− import Control.Monad.Logger
95− import Control.Monad.IO.Class
96− import Control.Monad.Trans.Class
97−+import Control.Monad.Trans.Resource
98− import Control.Monad.Trans.State
99− import qualified Data.ByteString as B
100− import Data.Char
101−@@ -143,9 +143,9 @@
102−
103− update bm _ _ (Right Nothing) = return (bm, TreeEntryNotFound)
104− update _ _ _ (Right (Just BlobEntry {})) =
105−- failure TreeCannotTraverseBlob
106−+ throwM TreeCannotTraverseBlob
107− update _ _ _ (Right (Just CommitEntry {})) =
108−- failure TreeCannotTraverseCommit
109−+ throwM TreeCannotTraverseCommit
110−
111− update bm name names arg = do
112− sbm <- case arg of
113−diff -ru orig/Git/Tree.hs new/Git/Tree.hs
114−--- orig/Git/Tree.hs 2014-04-06 09:02:45.571789820 +0300
115−+++ new/Git/Tree.hs 2014-04-06 09:02:45.000000000 +0300
116−@@ -1,8 +1,8 @@
117− module Git.Tree where
118−
119−-import Control.Failure
120− import Control.Monad
121− import Control.Monad.Trans.Class
122−+import Control.Monad.Trans.Resource
123− import Data.Conduit
124− import qualified Data.Conduit.List as CL
125− import Data.HashSet (HashSet)
126−@@ -22,7 +22,7 @@
127− copyTreeEntry (BlobEntry oid kind) needed = do
128− (b,needed') <- copyBlob oid needed
129− unless (renderObjOid oid == renderObjOid b) $
130−- failure $ BackendError $ "Error copying blob: "
131−+ throwM $ BackendError $ "Error copying blob: "
132− <> renderObjOid oid <> " /= " <> renderObjOid b
133− return (BlobEntry b kind, needed')
134− copyTreeEntry (CommitEntry oid) needed = do
135−diff -ru orig/Git/Types.hs new/Git/Types.hs
136−--- orig/Git/Types.hs 2014-04-06 09:02:45.571789820 +0300
137−+++ new/Git/Types.hs 2014-04-06 09:02:45.000000000 +0300
138−@@ -2,9 +2,9 @@
139−
140− import Control.Applicative
141− import qualified Control.Exception.Lifted as Exc
142−-import Control.Failure
143− import Control.Monad
144− import Control.Monad.Trans.Class
145−+import Control.Monad.Trans.Resource
146− import Data.ByteString (ByteString)
147− import qualified Data.ByteString.Base16 as B16
148− import qualified Data.ByteString.Lazy as BL
149−@@ -35,7 +35,7 @@
150−
151− -- | 'Repository' is the central point of contact between user code and Git
152− -- data objects. Every object must belong to some repository.
153−-class (Applicative m, Monad m, Failure GitException m,
154−+class (Applicative m, Monad m, MonadThrow m,
155− IsOid (Oid r), Show (Oid r), Eq (Oid r), Ord (Oid r))
156− => MonadGit r m | m -> r where
157− type Oid r :: *
158−diff -ru orig/Git/Working.hs new/Git/Working.hs
159−--- orig/Git/Working.hs 2014-04-06 09:02:45.571789820 +0300
160−+++ new/Git/Working.hs 2014-04-06 09:02:45.000000000 +0300
161−@@ -3,7 +3,6 @@
162− module Git.Working where
163−
164− import Control.Applicative
165−-import Control.Failure
166− import Control.Monad.IO.Class
167− import Control.Monad.Trans.Resource
168− import Data.Conduit
169−@@ -39,7 +38,7 @@
170− | cloneSubmodules -> cloneSubmodule oid fullPath
171− | otherwise -> liftIO $ createDirectory fullPath
172− where
173−- decodeError path e = failure $ PathEncodingError $
174−+ decodeError path e = throwM $ PathEncodingError $
175− "Could not decode path " <> T.pack (show path) <> ":" <> T.pack e
176−
177− checkoutBlob oid kind fullPath = do
178−diff -ru orig/gitlib.cabal new/gitlib.cabal
179−--- orig/gitlib.cabal 2014-04-06 09:02:45.575789820 +0300
180−+++ new/gitlib.cabal 2014-04-06 09:02:45.000000000 +0300
181−@@ -43,9 +43,9 @@
182− , base16-bytestring >= 0.1.1.5
183− , bytestring >= 0.9.2.1
184− , conduit >= 1.0.0
185−+ , conduit-extra >= 1.0.0
186− , containers >= 0.4.2.1
187− , directory >= 1.1.0.2
188−- , failure >= 0.2.0.1
189− , filepath >= 1.3.0.0
190− , hashable >= 1.1.2.5
191− , lifted-base >= 0.2
patching/patches/gitlib-cmdline-3.0.1.patchdeleted−43
@@ -1,43 +0,0 @@
1−diff -ru orig/Git/CmdLine.hs new/Git/CmdLine.hs
2−--- orig/Git/CmdLine.hs 2014-04-06 18:49:23.851795879 +0300
3−+++ new/Git/CmdLine.hs 2014-04-06 18:49:23.000000000 +0300
4−@@ -23,8 +23,9 @@
5− import Control.Monad.Reader.Class
6− import Control.Monad.Trans.Class
7− import Control.Monad.Trans.Reader (ReaderT, runReaderT)
8−+import Control.Monad.Trans.Resource (MonadThrow (..))
9− import qualified Data.ByteString as B
10−-import Data.Conduit hiding (MonadBaseControl)
11−+import Data.Conduit
12− import qualified Data.Conduit.List as CL
13− import Data.Foldable (for_)
14− import Data.Function
15−@@ -88,7 +89,7 @@
16− -- instance HasCliRepo (env, CliRepo) where
17− -- getCliRepo = snd
18−
19−-instance (Applicative m, Failure GitException m, MonadIO m)
20−+instance (Applicative m, Failure GitException m, MonadIO m, MonadThrow m)
21− => MonadGit CliRepo (ReaderT CliRepo m) where
22− type Oid CliRepo = SHA
23− data Tree CliRepo = CmdLineTree (TreeOid CliRepo)
24−@@ -127,7 +128,7 @@
25−
26− diffContentsWithTree = error "Not defined cliDiffContentsWithTree"
27−
28−-type MonadCli m = (Applicative m, Failure GitException m, MonadIO m)
29−+type MonadCli m = (Applicative m, Failure GitException m, MonadIO m, MonadThrow m)
30−
31− mkOid :: MonadCli m => forall o. TL.Text -> ReaderT CliRepo m (Tagged o SHA)
32− mkOid = fmap Tagged <$> textToSha . toStrict
33−diff -ru orig/gitlib-cmdline.cabal new/gitlib-cmdline.cabal
34−--- orig/gitlib-cmdline.cabal 2014-04-06 18:49:23.895795879 +0300
35−+++ new/gitlib-cmdline.cabal 2014-04-06 18:49:23.000000000 +0300
36−@@ -39,6 +39,7 @@
37− , transformers >= 0.2.2
38− , transformers-base >= 0.4.1
39− , unordered-containers >= 0.2.3.0
40−+ , resourcet
41− exposed-modules:
42− Git.CmdLine
43−
patching/patches/gitlib-libgit2-3.0.1.patchdeleted−280
@@ -1,280 +0,0 @@
1−diff -ru orig/Git/Libgit2/Internal.hs new/Git/Libgit2/Internal.hs
2−--- orig/Git/Libgit2/Internal.hs 2014-04-06 09:02:46.523789820 +0300
3−+++ new/Git/Libgit2/Internal.hs 2014-04-06 09:02:46.000000000 +0300
4−@@ -8,9 +8,9 @@
5−
6− import Bindings.Libgit2
7− import Control.Applicative
8−-import Control.Failure
9− import Control.Monad
10− import Control.Monad.Trans.Control
11−+import Control.Monad.Trans.Resource
12− import Data.ByteString
13− import qualified Data.Text as T
14− import qualified Data.Text.ICU.Convert as U
15−@@ -85,7 +85,7 @@
16− let p = castPtr ptr'
17− fptr <- FC.newForeignPtr p (c'git_object_free p)
18− run $ Right <$> createFn coidCopy (castForeignPtr fptr) ptr'
19−- either (failure . Git.BackendError) return result
20−+ either (throwM . Git.BackendError) return result
21−
22− -- lgLookupObject :: Text -> LgRepository Dynamic
23− -- lgLookupObject str
24−diff -ru orig/Git/Libgit2/Types.hs new/Git/Libgit2/Types.hs
25−--- orig/Git/Libgit2/Types.hs 2014-04-06 09:02:46.523789820 +0300
26−+++ new/Git/Libgit2/Types.hs 2014-04-06 09:02:46.000000000 +0300
27−@@ -10,10 +10,10 @@
28−
29− import Bindings.Libgit2
30− import Control.Applicative
31−-import Control.Failure
32− import Control.Monad.IO.Class
33− import Control.Monad.Logger
34− import Control.Monad.Trans.Control
35−+import Control.Monad.Trans.Resource
36− import Data.IORef
37− import Foreign.ForeignPtr
38− import qualified Git
39−@@ -52,7 +52,7 @@
40− type TreeBuilder = Git.TreeBuilder LgRepo
41− type Options = Git.Options LgRepo
42−
43−-type MonadLg m = (Applicative m, Failure Git.GitException m,
44−+type MonadLg m = (Applicative m, MonadThrow m,
45− MonadIO m, MonadBaseControl IO m, MonadLogger m)
46−
47− -- Types.hs
48−diff -ru orig/Git/Libgit2.hs new/Git/Libgit2.hs
49−--- orig/Git/Libgit2.hs 2014-04-06 09:02:46.523789820 +0300
50−+++ new/Git/Libgit2.hs 2014-04-06 09:02:46.000000000 +0300
51−@@ -60,7 +60,6 @@
52− import Control.Concurrent.Async.Lifted
53− import Control.Concurrent.STM
54− import Control.Exception.Lifted
55−-import Control.Failure
56− import Control.Monad hiding (forM, forM_, mapM, mapM_, sequence)
57− import Control.Monad.IO.Class
58− import Control.Monad.Logger
59−@@ -154,11 +153,11 @@
60−
61− lgParseOid :: MonadLg m => Text -> m Oid
62− lgParseOid str
63−- | len > 40 = failure (Git.OidParseFailed str)
64−+ | len > 40 = throwM (Git.OidParseFailed str)
65− | otherwise = do
66− moid <- liftIO $ lgParseOidIO str len
67− case moid of
68−- Nothing -> failure (Git.OidParseFailed str)
69−+ Nothing -> throwM (Git.OidParseFailed str)
70− Just oid -> return oid
71− where
72− len = T.length str
73−@@ -179,7 +178,7 @@
74− instance Eq OidPtr where
75− oid1 == oid2 = oid1 `compare` oid2 == EQ
76−
77−-instance (Applicative m, Failure Git.GitException m,
78−+instance (Applicative m, MonadThrow m,
79− MonadBaseControl IO m, MonadIO m, MonadLogger m)
80− => Git.MonadGit LgRepo (ReaderT LgRepo m) where
81− type Oid LgRepo = OidPtr
82−@@ -427,7 +426,7 @@
83− return $ Just fptr
84− case mfptr of
85− Nothing ->
86−- failure (Git.TreeCreateFailed "Failed to create new tree builder")
87−+ throwM (Git.TreeCreateFailed "Failed to create new tree builder")
88− Just fptr -> do
89− toid <- mapM Git.treeOid mtree
90− return (lgMakeBuilder fptr) { Git.mtbBaseTreeOid = toid }
91−@@ -441,7 +440,7 @@
92− withFilePath key $ \name ->
93− c'git_treebuilder_insert nullPtr ptr name coid
94− (fromIntegral mode)
95−- when (r2 < 0) $ failure (Git.TreeBuilderInsertFailed key)
96−+ when (r2 < 0) $ throwM (Git.TreeBuilderInsertFailed key)
97−
98− treeEntryToOid :: TreeEntry -> (Oid, CUInt)
99− treeEntryToOid (Git.BlobEntry oid kind) =
100−@@ -503,7 +502,7 @@
101− liftIO $ withForeignPtr fptr $ \builder -> alloca $ \pptr -> do
102− r <- c'git_treebuilder_create pptr nullPtr
103− when (r < 0) $
104−- failure (Git.BackendError "Could not create new treebuilder")
105−+ throwM (Git.BackendError "Could not create new treebuilder")
106− builder' <- peek pptr
107− bracket
108− (mk'git_treebuilder_filter_cb (callback builder'))
109−@@ -522,7 +521,7 @@
110− coid
111− fmode
112− when (r < 0) $
113−- failure (Git.BackendError "Could not insert entry in treebuilder")
114−+ throwM (Git.BackendError "Could not insert entry in treebuilder")
115− return 0
116−
117− lgLookupTree :: MonadLg m => TreeOid -> ReaderT LgRepo m Tree
118−@@ -547,7 +546,7 @@
119− 0o100644 -> return Git.PlainBlob
120− 0o100755 -> return Git.ExecutableBlob
121− 0o120000 -> return Git.SymlinkBlob
122−- _ -> failure $ Git.BackendError $
123−+ _ -> throwM $ Git.BackendError $
124− "Unknown blob mode: " <> T.pack (show mode)
125− | typ == c'GIT_OBJ_TREE ->
126− return $ Git.TreeEntry (Tagged (mkOid oid))
127−@@ -642,7 +641,7 @@
128− r1 <- c'git_odb_exists ptr coid 0
129− c'git_odb_free ptr
130− return (Just (r1 == 0))
131−- maybe (failure Git.RepositoryInvalid) return result
132−+ maybe (throwM Git.RepositoryInvalid) return result
133−
134− lgForEachObject :: Ptr C'git_odb
135− -> (Ptr C'git_oid -> Ptr () -> IO CInt)
136−@@ -663,7 +662,7 @@
137− r <- withForeignPtr (repoObj repo) $ \repoPtr ->
138− c'git_revwalk_new pptr repoPtr
139− when (r < 0) $
140−- failure (Git.BackendError "Could not create revwalker")
141−+ throwM (Git.BackendError "Could not create revwalker")
142− ptr <- peek pptr
143− FC.newForeignPtr ptr (c'git_revwalk_free ptr)
144−
145−@@ -673,7 +672,7 @@
146− liftIO $ withForeignPtr (getOid oid) $ \coid -> do
147− r2 <- withForeignPtr walker $ flip c'git_revwalk_push coid
148− when (r2 < 0) $
149−- failure (Git.BackendError $ "Could not push oid "
150−+ throwM (Git.BackendError $ "Could not push oid "
151− <> pack (show oid) <> " onto revwalker")
152−
153− case mhave of
154−@@ -681,7 +680,7 @@
155− Just have -> liftIO $ withForeignPtr (getOid (untag have)) $ \coid -> do
156− r2 <- withForeignPtr walker $ flip c'git_revwalk_hide coid
157− when (r2 < 0) $
158−- failure (Git.BackendError $ "Could not hide commit "
159−+ throwM (Git.BackendError $ "Could not hide commit "
160− <> pack (show (untag have)) <> " from revwalker")
161−
162− liftIO $ withForeignPtr walker $ flip c'git_revwalk_sorting
163−@@ -831,7 +830,7 @@
164− else do
165− ref <- peek ptr
166− c'git_reference_delete ref
167−- when (r < 0) $ failure (Git.ReferenceDeleteFailed name)
168−+ when (r < 0) $ throwM (Git.ReferenceDeleteFailed name)
169−
170− -- int git_reference_packall(git_repository *repo)
171−
172−@@ -957,7 +956,7 @@
173−
174− --compareRef = c'git_reference_cmp
175−
176−-lgThrow :: (MonadIO m, Failure e m) => (Text -> e) -> m ()
177−+lgThrow :: (Exception e, MonadIO m, MonadThrow m) => (Text -> e) -> m ()
178− lgThrow f = do
179− errStr <- liftIO $ do
180− errPtr <- c'giterr_last
181−@@ -966,7 +965,7 @@
182− else do
183− err <- peek errPtr
184− peekCString (c'git_error'message err)
185−- failure (f (pack errStr))
186−+ throwM (f (pack errStr))
187−
188− -- withLgTempRepo :: MonadLg m => ReaderT LgRepo m a -> m a
189− -- withLgTempRepo f = withTempDir $ \dir -> do
190−@@ -1048,13 +1047,13 @@
191− -- (Either Git.SHA ByteString)) m
192− -- (Git.TreeFilePath, Either Git.SHA ByteString)
193− handlePath (Right _) =
194−- lift $ failure $ Git.DiffTreeToIndexFailed
195−+ lift $ throwM $ Git.DiffTreeToIndexFailed
196− "Received a Right value when a Left RawFilePath was expected"
197− handlePath (Left path) = do
198− mcontent <- await
199− case mcontent of
200− Nothing ->
201−- lift $ failure $ Git.DiffTreeToIndexFailed $
202−+ lift $ throwM $ Git.DiffTreeToIndexFailed $
203− "Content not provided for " <> T.pack (show path)
204− Just x -> handleContent path x
205−
206−@@ -1064,11 +1063,11 @@
207− -- (Either Git.SHA ByteString)) m
208− -- (Git.TreeFilePath, Either Git.SHA ByteString)
209− handleContent _path (Left _) =
210−- lift $ failure $ Git.DiffTreeToIndexFailed
211−+ lift $ throwM $ Git.DiffTreeToIndexFailed
212− "Received a Left value when a Right ByteString was expected"
213− handleContent path (Right content) = return (path, content)
214−
215−- -- diffBlob :: Failure Git.GitException m
216−+ -- diffBlob :: MonadThrow m
217− -- => Git.TreeFilePath
218− -- -> Maybe (Either Git.SHA ByteString)
219− -- -> Maybe (ForeignPtr C'git_oid)
220−@@ -1183,8 +1182,8 @@
221− B.cons (fromIntegral lineOrigin) bs
222− return 0
223−
224−-checkResult :: (Eq a, Num a, Failure Git.GitException m) => a -> Text -> m ()
225−-checkResult r why = when (r /= 0) $ failure (Git.BackendError why)
226−+checkResult :: (Eq a, Num a, MonadThrow m) => a -> Text -> m ()
227−+checkResult r why = when (r /= 0) $ throwM (Git.BackendError why)
228−
229− lgBuildPackFile :: MonadLg m
230− => FilePath -> [Either CommitOid TreeOid]
231−@@ -1353,7 +1352,7 @@
232−
233− lgLoadPackFileInMemory
234− :: (MonadBaseControl IO m, MonadIO m, MonadLogger m,
235−- Failure Git.GitException m)
236−+ MonadThrow m)
237− => FilePath
238− -> Ptr (Ptr C'git_odb_backend)
239− -> Ptr (Ptr C'git_odb)
240−@@ -1385,7 +1384,7 @@
241− return odbPtr
242−
243− lgOpenPackFile :: (MonadBaseControl IO m, MonadIO m, MonadLogger m,
244−- Failure Git.GitException m)
245−+ MonadThrow m)
246− => FilePath -> m (Ptr C'git_odb)
247− lgOpenPackFile idxPath = control $ \run ->
248− alloca $ \odbPtrPtr ->
249−@@ -1393,17 +1392,17 @@
250− lgLoadPackFileInMemory idxPath backendPtrPtr odbPtrPtr
251−
252− lgClosePackFile :: (MonadBaseControl IO m, MonadIO m, MonadLogger m,
253−- Failure Git.GitException m)
254−+ MonadThrow m)
255− => Ptr C'git_odb -> m ()
256− lgClosePackFile = liftIO . c'git_odb_free
257−
258− lgWithPackFile :: (MonadBaseControl IO m, MonadIO m, MonadLogger m,
259−- Failure Git.GitException m)
260−+ MonadThrow m)
261− => FilePath -> (Ptr C'git_odb -> m a) -> m a
262− lgWithPackFile idxPath = bracket (lgOpenPackFile idxPath) lgClosePackFile
263−
264− lgReadFromPack :: (MonadBaseControl IO m, MonadIO m, MonadLogger m,
265−- Failure Git.GitException m)
266−+ MonadThrow m)
267− => Ptr C'git_odb -> Git.SHA -> Bool
268− -> m (Maybe (C'git_otype, CSize, ByteString))
269− lgReadFromPack odbPtr sha metadataOnly = liftIO $ do
270−diff -ru orig/gitlib-libgit2.cabal new/gitlib-libgit2.cabal
271−--- orig/gitlib-libgit2.cabal 2014-04-06 09:02:46.527789820 +0300
272−+++ new/gitlib-libgit2.cabal 2014-04-06 09:02:46.000000000 +0300
273−@@ -42,7 +42,6 @@
274− , conduit >= 0.5.5
275− , containers >= 0.4.2.1
276− , directory >= 1.1.0.2
277−- , failure >= 0.2.0.1
278− , fast-logger
279− , filepath >= 1.3.0
280− , lifted-async >= 0.1.0
patching/patches/gitlib-s3-3.0.2.patchdeleted−276
@@ -1,276 +0,0 @@
1−diff -ru orig/Git/S3.hs new/Git/S3.hs
2−--- orig/Git/S3.hs 2014-04-06 09:02:47.247789820 +0300
3−+++ new/Git/S3.hs 2014-04-06 09:02:47.000000000 +0300
4−@@ -42,7 +42,6 @@
5− import Control.Monad.Trans.Resource
6− import Control.Retry
7− import Data.Aeson as A
8−-import Data.Attempt
9− import Data.Bifunctor
10− import Data.Binary as Bin
11− import Data.ByteString (ByteString)
12−@@ -141,7 +140,7 @@
13− }
14− deriving (Eq, Show, Generic)
15−
16−-type MonadS3 m = (Failure Git.GitException m,
17−+type MonadS3 m = (MonadThrow m,
18− MonadIO m, MonadBaseControl IO m, MonadLogger m)
19−
20− data BackendCallbacks = BackendCallbacks
21−@@ -478,7 +477,10 @@
22− -> ResourceT m (Response (ResponseMetadata a) a)
23− awsRetry cfg svcfg mgr r =
24− transResourceT liftIO $
25−- retrying def (isFailure . responseResult) $ aws cfg svcfg mgr r
26−+ retrying def (isLeft . responseResult) $ aws cfg svcfg mgr r
27−+ where
28−+ isLeft Left{} = True
29−+ isLeft Right{} = False
30−
31− listBucketS3 :: MonadS3 m => OdbS3Details -> ResourceT m [Text]
32− listBucketS3 dets = do
33−@@ -622,7 +624,7 @@
34− sha <- oidToSha oid
35− modifyIORef mshas (sha:)
36− return c'GIT_OK
37−- checkResult r "lgForEachObject failed"
38−+ either throwM return $ checkResult r "lgForEachObject failed"
39−
40− -- Update the known objects map with the fact that we've got a local cache
41− -- of the pack file.
42−@@ -637,7 +639,7 @@
43− ++ show (Prelude.length shas) ++ " objects"
44− return shas
45−
46−-catalogPackFile :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
47−+catalogPackFile :: (MonadS3 m, MonadThrow m)
48− => OdbS3Details -> Text -> FilePath -> m [SHA]
49− catalogPackFile dets packSha idxPath = do
50− -- Load the pack file, and iterate over the objects within it to determine
51−@@ -710,7 +712,7 @@
52− lgDebug $ "cacheUpdateEntry " ++ show (shaToText sha) ++ " " ++ show ce
53− liftIO $ atomically $ modifyTVar (knownObjects dets) $ M.insert sha ce
54−
55−-cacheLoadObject :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
56−+cacheLoadObject :: (MonadS3 m, MonadThrow m)
57− => OdbS3Details -> SHA -> CacheEntry -> Bool
58− -> m (Maybe ObjectInfo)
59− cacheLoadObject dets sha ce metadataOnly = do
60−@@ -958,7 +960,7 @@
61− remoteStoreObject _ _ _ =
62− throw (Git.BackendError "remoteStoreObject was not given any data")
63−
64−-remoteCatalogContents :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
65−+remoteCatalogContents :: (MonadS3 m, MonadThrow m)
66− => OdbS3Details -> ResourceT m ()
67− remoteCatalogContents dets = do
68− lgDebug "remoteCatalogContents"
69−@@ -982,7 +984,7 @@
70−
71− | otherwise -> return ()
72−
73−-accessObject :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
74−+accessObject :: (MonadS3 m, MonadThrow m)
75− => OdbS3Details -> SHA -> Bool -> m (Maybe CacheEntry)
76− accessObject dets sha checkRemote = do
77− mentry <- cacheLookupEntry dets sha
78−@@ -1032,19 +1034,19 @@
79− -- cache and with the callback interface. This is to avoid recataloging
80− -- in the future.
81−
82−-objectExists :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
83−+objectExists :: (MonadS3 m, MonadThrow m)
84− => OdbS3Details -> SHA -> Bool -> m CacheEntry
85− objectExists dets sha checkRemote = do
86− mce <- accessObject dets sha checkRemote
87− return $ fromMaybe DoesNotExist mce
88−
89−-readObject :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
90−+readObject :: (MonadS3 m, MonadThrow m)
91− => OdbS3Details -> SHA -> Bool -> m (Maybe ObjectInfo)
92− readObject dets sha metadataOnly = do
93− ce <- objectExists dets sha True
94− cacheLoadObject dets sha ce metadataOnly `orElse` return Nothing
95−
96−-readObjectMetadata :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
97−+readObjectMetadata :: (MonadS3 m, MonadThrow m)
98− => OdbS3Details -> SHA -> m (Maybe ObjectInfo)
99− readObjectMetadata dets sha = readObject dets sha True
100−
101−@@ -1054,7 +1056,7 @@
102− callbackRegisterObject dets sha info
103− cacheStoreObject dets sha info
104−
105−-writePackFile :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
106−+writePackFile :: (MonadS3 m, MonadThrow m)
107− => OdbS3Details -> BL.ByteString -> m ()
108− writePackFile dets bytes = do
109− let dir = tempDirectory dets
110−@@ -1073,7 +1075,7 @@
111− shas <- catalogPackFile dets packSha idxPath
112− callbackRegisterPackFile dets packSha shas
113−
114−-readCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
115−+readCallback :: (MonadS3 m, MonadThrow m)
116− => Ptr (Ptr ())
117− -> Ptr CSize
118− -> Ptr C'git_otype
119−@@ -1104,7 +1106,7 @@
120− BU.unsafeUseAsCString chunk $ copyBytes p ?? len
121− return $ p `plusPtr` len
122−
123−-readPrefixCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
124−+readPrefixCallback :: (MonadS3 m, MonadThrow m)
125− => Ptr C'git_oid
126− -> Ptr (Ptr ())
127− -> Ptr CSize
128−@@ -1140,7 +1142,7 @@
129− go dets sha False
130− | otherwise = return Nothing
131−
132−-readHeaderCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
133−+readHeaderCallback :: (MonadS3 m, MonadThrow m)
134− => Ptr CSize
135− -> Ptr C'git_otype
136− -> Ptr C'git_odb_backend
137−@@ -1158,7 +1160,7 @@
138− poke len_p (toLength len)
139− poke type_p (toType typ)
140−
141−-writeCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
142−+writeCallback :: (MonadS3 m, MonadThrow m)
143− => Ptr C'git_oid
144− -> Ptr C'git_odb_backend
145− -> Ptr ()
146−@@ -1184,7 +1186,7 @@
147− (ObjectInfo (fromLength len) (fromType obj_type)
148− Nothing (Just (BL.fromChunks [bytes])))
149−
150−-existsCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
151−+existsCallback :: (MonadS3 m, MonadThrow m)
152− => Ptr C'git_odb_backend -> Ptr C'git_oid -> CInt -> m CInt
153− existsCallback be oid confirmNotExists = do
154− (dets, sha) <- liftIO $ unpackDetails be oid
155−@@ -1194,18 +1196,18 @@
156− return $ if ce == DoesNotExist then 0 else 1)
157− (return c'GIT_ERROR)
158−
159−-refreshCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
160−+refreshCallback :: (MonadS3 m, MonadThrow m)
161− => Ptr C'git_odb_backend -> m CInt
162− refreshCallback _ =
163− return c'GIT_OK -- do nothing
164−
165−-foreachCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
166−+foreachCallback :: (MonadS3 m, MonadThrow m)
167− => Ptr C'git_odb_backend -> C'git_odb_foreach_cb -> Ptr ()
168− -> m CInt
169− foreachCallback _be _callback _payload =
170− return c'GIT_ERROR -- fallback to standard method
171−
172−-writePackCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
173−+writePackCallback :: (MonadS3 m, MonadThrow m)
174− => Ptr (Ptr C'git_odb_writepack)
175− -> Ptr C'git_odb_backend
176− -> C'git_transfer_progress_callback
177−@@ -1248,7 +1250,7 @@
178− foreign import ccall "&freeCallback"
179− freeCallbackPtr :: FunPtr F'git_odb_backend_free_callback
180−
181−-packAddCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
182−+packAddCallback :: (MonadS3 m, MonadThrow m)
183− => Ptr C'git_odb_writepack
184− -> Ptr ()
185− -> CSize
186−@@ -1267,7 +1269,7 @@
187− (castPtr dataPtr) (fromIntegral len)
188− writePackFile dets (BL.fromChunks [bytes])
189−
190−-packCommitCallback :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
191−+packCommitCallback :: (MonadS3 m, MonadThrow m)
192− => Ptr C'git_odb_writepack -> Ptr C'git_transfer_progress
193− -> m CInt
194− packCommitCallback _wp _progress =
195−@@ -1380,7 +1382,7 @@
196− liftIO $ writeIORef result res
197− readIORef result
198−
199−-odbS3Backend :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
200−+odbS3Backend :: (MonadS3 m, MonadThrow m)
201− => Aws.S3Configuration NormalQuery
202− -> Configuration
203− -> Manager
204−@@ -1475,7 +1477,7 @@
205−
206− -- | Given a repository object obtained from Libgit2, add an S3 backend to it,
207− -- making it the primary store for objects associated with that repository.
208−-addS3Backend :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
209−+addS3Backend :: (MonadS3 m, MonadThrow m)
210− => LgRepo
211− -> Text -- ^ bucket
212− -> Text -- ^ prefix
213−@@ -1505,7 +1507,7 @@
214− void $ liftIO $ odbBackendAdd repo odbS3 100
215− return repo
216−
217−-s3Factory :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
218−+s3Factory :: (MonadS3 m, MonadThrow m)
219− => Maybe Text -> Text -> Text -> FilePath -> BackendCallbacks
220− -> Git.RepositoryFactory (ReaderT LgRepo (NoLoggingT m)) m LgRepo
221− s3Factory bucket accessKey secretKey dir callbacks = lgFactory
222−@@ -1528,7 +1530,7 @@
223− dir
224− callbacks
225−
226−-s3FactoryLogger :: (MonadS3 m, MonadUnsafeIO m, MonadThrow m)
227−+s3FactoryLogger :: (MonadS3 m, MonadThrow m)
228− => Maybe Text -> Text -> Text -> FilePath -> BackendCallbacks
229− -> Git.RepositoryFactory (ReaderT LgRepo m) m LgRepo
230− s3FactoryLogger bucket accessKey secretKey dir callbacks = lgFactoryLogger
231−diff -ru orig/gitlib-s3.cabal new/gitlib-s3.cabal
232−--- orig/gitlib-s3.cabal 2014-04-06 09:02:47.247789820 +0300
233−+++ new/gitlib-s3.cabal 2014-04-06 09:02:47.000000000 +0300
234−@@ -33,7 +33,6 @@
235− , hspec-expectations >= 0.3
236− , data-default >= 0.5.1
237− , directory >= 1.1.0.2
238−- , failure >= 0.2.0.1
239− , filepath >= 1.3.0
240− , monad-logger >= 0.3.1.1
241− , resourcet >= 0.4.6
242−@@ -52,12 +51,12 @@
243− , ghc-prim
244− , hlibgit2 >= 0.18.0.11
245− , aeson >= 0.6.1.0
246−- , attempt >= 0.4.0
247− , aws >= 0.7.5
248− , bifunctors >= 3.2.0.1
249− , binary >= 0.5.1.0
250− , bytestring >= 0.9.2.1
251− , conduit >= 0.5.5
252−+ , conduit-extra
253− , data-default >= 0.5.1
254− , directory >= 1.1.0.2
255− , filepath >= 1.3.0
256−diff -ru orig/test/Smoke.hs new/test/Smoke.hs
257−--- orig/test/Smoke.hs 2014-04-06 09:02:47.247789820 +0300
258−+++ new/test/Smoke.hs 2014-04-06 09:02:47.000000000 +0300
259−@@ -11,7 +11,6 @@
260−
261− import Aws
262− import Control.Applicative
263−-import Control.Failure
264− import Control.Monad.IO.Class
265− import Control.Monad.Logger
266− import Control.Monad.Trans.Reader
267−@@ -30,8 +29,7 @@
268− import Test.Hspec.Runner
269−
270− s3Factory
271−- :: (Failure Git.GitException m, MonadIO m, MonadBaseControl IO m,
272−- MonadUnsafeIO m, MonadThrow m)
273−+ :: (MonadThrow m, MonadIO m, MonadBaseControl IO m)
274− => Git.RepositoryFactory (ReaderT Lg.LgRepo (NoLoggingT m)) m Lg.LgRepo
275− s3Factory = Lg.lgFactory
276− { Git.runRepository = \ctxt m ->
patching/patches/gitlib-test-3.0.1.patchdeleted−11
@@ -1,11 +0,0 @@
1−diff -ru orig/gitlib-test.cabal new/gitlib-test.cabal
2−--- orig/gitlib-test.cabal 2014-04-06 09:02:47.671789820 +0300
3−+++ new/gitlib-test.cabal 2014-04-06 09:02:47.000000000 +0300
4−@@ -28,6 +28,7 @@
5− , bytestring
6− , failure >= 0.2.0
7− , conduit
8−+ , conduit-extra
9− , monad-control >= 0.3.1
10− , tagged >= 0.4.4
11− , text >= 0.11.2
patching/patches/haskell-names-0.3.2.6.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/haskell-names.cabal new/haskell-names.cabal
2−--- orig/haskell-names.cabal 2014-03-06 15:00:30.424709530 +0200
3−+++ new/haskell-names.cabal 2014-03-06 15:00:30.000000000 +0200
4−@@ -271,7 +271,7 @@
5− , data-lens-template
6− , tagged
7− , traverse-with-class
8−- , type-eq == 0.4
9−+ , type-eq >= 0.4
10− , Cabal >= 1.14 && < 1.20
11− Hs-source-dirs: src
12− Ghc-options: -Wall -fno-warn-name-shadowing
patching/patches/haskell-packages-0.2.3.3.patchdeleted−11
@@ -1,11 +0,0 @@
1−diff -ru orig/haskell-packages.cabal new/haskell-packages.cabal
2−--- orig/haskell-packages.cabal 2014-02-20 12:04:23.945608732 +0200
3−+++ new/haskell-packages.cabal 2014-02-20 12:04:23.000000000 +0200
4−@@ -48,6 +48,6 @@
5− , containers
6− , mtl >= 2.1
7− , hse-cpp
8−- , EitherT
9−+ , either
10− , haskell-src-exts >= 1.14
11− , tagged
patching/patches/hdaemonize-0.4.5.0.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ruN orig/System/Posix/Daemonize.hs new/System/Posix/Daemonize.hs
2−--- orig/System/Posix/Daemonize.hs 2014-08-10 13:47:22.378323475 +0300
3−+++ new/System/Posix/Daemonize.hs 2014-08-10 13:47:22.000000000 +0300
4−@@ -147,7 +147,7 @@
5− process daemon' args
6− where
7−
8−- program' daemon = withSyslog (fromJust $ name daemon) (syslogOptions daemon) DAEMON $
9−+ program' daemon = withSyslog (fromJust $ name daemon) (syslogOptions daemon) DAEMON [] $
10− do let log = syslog Notice
11− log "starting"
12− pidWrite daemon
patching/patches/heist-0.13.0.6.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/heist.cabal new/heist.cabal
2−--- orig/heist.cabal 2014-03-13 06:02:39.554055215 +0200
3−+++ new/heist.cabal 2014-03-13 06:02:39.000000000 +0200
4−@@ -153,7 +153,7 @@
5− filepath >= 1.3 && < 1.4,
6− hashable >= 1.1 && < 1.3,
7− mtl >= 2.0 && < 2.2,
8−- process >= 1.1 && < 1.2,
9−+ process >= 1.1 && < 1.3,
10− random >= 1.0.1.0 && < 1.1,
11− text >= 0.10 && < 1.2,
12− time >= 1.1 && < 1.5,
patching/patches/hint-0.4.2.0.patchdeleted−21
@@ -1,21 +0,0 @@
1−diff -ru orig/unit-tests/run-unit-tests.hs new/unit-tests/run-unit-tests.hs
2−--- orig/unit-tests/run-unit-tests.hs 2014-05-11 18:47:29.102698531 +0300
3−+++ new/unit-tests/run-unit-tests.hs 2014-05-11 18:47:28.000000000 +0300
4−@@ -191,7 +191,7 @@
5− test_catch :: TestCase
6− test_catch = TestCase "catch" [] $ do
7− setImports ["Prelude"]
8−- succeeds (action `catch` handler) @@? "catch failed"
9−+ succeeds (action `MC.catch` handler) @@? "catch failed"
10− where handler DivideByZero = return "catched"
11− handler e = throwM e
12− action = do s <- eval "1 `div` 0 :: Int"
13−@@ -203,7 +203,7 @@
14− liftIO $ do
15− r <- newEmptyMVar
16− let concurrent = runInterpreter (liftIO $ putMVar r False)
17−- `catch` \MultipleInstancesNotAllowed ->
18−+ `MC.catch` \MultipleInstancesNotAllowed ->
19− do liftIO $ putMVar r True
20− return $ Right ()
21− _ <- forkIO $ concurrent >> return ()
patching/patches/hoogle-4.2.32.patchdeleted−58
@@ -1,58 +0,0 @@
1−diff -ru orig/src/General/Web.hs new/src/General/Web.hs
2−--- orig/src/General/Web.hs 2014-06-09 15:25:38.583521732 +0300
3−+++ new/src/General/Web.hs 2014-06-09 15:25:38.000000000 +0300
4−@@ -21,6 +21,9 @@
5− import General.Base
6− import System.FilePath
7− import Network.Wai
8−+#if MIN_VERSION_wai(3, 0, 0)
9−+import Data.IORef
10−+#endif
11− #if MIN_VERSION_wai(2, 0, 0)
12− import Network.Wai.Internal
13− #endif
14−@@ -46,7 +49,15 @@
15−
16− responseFlatten :: Response -> IO (Status, ResponseHeaders, LBString)
17− responseFlatten r = do
18−-#if MIN_VERSION_wai(2, 0, 0)
19−+#if MIN_VERSION_wai(3, 0, 0)
20−+ let (s,hs,withBody) = responseToStream r
21−+ ref <- newIORef mempty
22−+ let addChunk builder = modifyIORef ref (<> builder)
23−+ withBody $ \body -> body addChunk (return ())
24−+ builder <- readIORef ref
25−+ let res = toLazyByteString builder
26−+ return (s,hs,res)
27−+#elif MIN_VERSION_wai(2, 0, 0)
28− let (s,hs,withSrc) = responseToSource r
29− chunks <- withSrc $ \src -> src $$ consume
30− let res = toLazyByteString $ mconcat [x | Chunk x <- chunks]
31−diff -ru orig/src/Web/Server.hs new/src/Web/Server.hs
32−--- orig/src/Web/Server.hs 2014-06-09 15:25:38.575521732 +0300
33−+++ new/src/Web/Server.hs 2014-06-09 15:25:38.000000000 +0300
34−@@ -32,14 +32,23 @@
35− resp <- respArgs q
36− v <- newMVar ()
37− putStrLn $ "Starting Hoogle Server on port " ++ show port
38−- runSettings defaultSettings{settingsOnException=exception, settingsPort=port} $ \r -> liftIO $ do
39−+ runSettings defaultSettings{settingsOnException=exception, settingsPort=port}
40−+#if MIN_VERSION_wai(3, 0, 0)
41−+ $ \r sendResponse -> do
42−+#else
43−+ $ \r -> liftIO $ do
44−+#endif
45− start <- getCurrentTime
46− res <- talk resp q r
47− responseEvaluate res
48− stop <- getCurrentTime
49− let t = floor $ diffUTCTime stop start * 1000
50− withMVar v $ const $ putStrLn $ bsUnpack (rawPathInfo r) ++ bsUnpack (rawQueryString r) ++ " ms:" ++ show t
51−+#if MIN_VERSION_wai(3, 0, 0)
52−+ sendResponse res
53−+#else
54− return res
55−+#endif
56−
57−
58− #if MIN_VERSION_wai(2, 0, 0)
patching/patches/hweblib-0.6.1.patchdeleted−23
@@ -1,23 +0,0 @@
1−diff -ru orig/src/Network/Parser/Mime.hs new/src/Network/Parser/Mime.hs
2−--- orig/src/Network/Parser/Mime.hs 2014-03-19 12:03:48.222054709 +0200
3−+++ new/src/Network/Parser/Mime.hs 2014-03-19 12:03:47.000000000 +0200
4−@@ -43,7 +43,7 @@
5− _ -> MultiPart (Extension s)
6− (t, s) -> Other t s
7− where
8−- paired s = let (a,b) = (T.break (== '/') . T.toLower . TE.decodeLatin1) s in
9−+ paired s = let (a,b) = (T.break (== '/') . T.toLower . TE.decodeUtf8) s in
10− (a, T.drop 1 b)
11−
12− -- Parse headers and map them to a MimeValue
13−@@ -53,8 +53,8 @@
14− let mv = L.foldl f nullMimeValue eh
15− return mv
16− where
17−- bs2t = M.fromList . Prelude.map (TE.decodeLatin1 *** TE.decodeLatin1) . M.toList
18−- hVal = TE.decodeLatin1 . hValue
19−+ bs2t = M.fromList . Prelude.map (TE.decodeUtf8 *** TE.decodeUtf8) . M.toList
20−+ hVal = TE.decodeUtf8 . hValue
21− f z x =
22− case hType x of
23− IdH -> z { mvHeaders = M.insert IdH (hVal x) (mvHeaders z) }
patching/patches/incremental-parser-0.2.3.2.patchdeleted−20
@@ -1,20 +0,0 @@
1−diff -ru orig/incremental-parser.cabal new/incremental-parser.cabal
2−--- orig/incremental-parser.cabal 2014-06-15 10:20:01.864931460 +0300
3−+++ new/incremental-parser.cabal 2014-06-15 10:20:01.000000000 +0300
4−@@ -29,15 +29,3 @@
5− GHC-prof-options: -auto-all
6− if impl(ghc >= 7.0.0)
7− default-language: Haskell2010
8−-
9−-test-suite Main
10−- Type: exitcode-stdio-1.0
11−- x-uses-tf: true
12−- Build-Depends: base < 5, monoid-subclasses < 0.4,
13−- QuickCheck >= 2 && < 3, checkers >= 0.2 && < 0.4,
14−- test-framework >= 0.4.1, test-framework-quickcheck2
15−- Main-is: Test/TestIncrementalParser.hs
16−- Other-Modules: Text.ParserCombinators.Incremental,
17−- Text.ParserCombinators.Incremental.LeftBiasedLocal, Text.ParserCombinators.Incremental.Symmetric,
18−- Control.Applicative.Monoid
19−- default-language: Haskell2010
20−Only in orig: Test
patching/patches/network-transport-tests-0.1.0.1.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/network-transport-tests.cabal new/network-transport-tests.cabal
2−--- orig/network-transport-tests.cabal 2014-03-25 06:24:53.648644213 +0200
3−+++ new/network-transport-tests.cabal 2014-03-25 06:24:53.000000000 +0200
4−@@ -24,7 +24,7 @@
5− bytestring >= 0.9 && < 0.11,
6− random >= 1.0 && < 1.1,
7− mtl >= 2.1 && < 2.2,
8−- ansi-terminal >= 0.5 && < 0.6
9−+ ansi-terminal >= 0.5
10− hs-source-dirs: src
11− ghc-options: -Wall -fno-warn-unused-do-bind
12− extensions: CPP,
patching/patches/primitive-0.5.3.0.patchdeleted−62
@@ -1,62 +0,0 @@
1−diff -ruN orig/Control/Monad/Primitive.hs new/Control/Monad/Primitive.hs
2−--- orig/Control/Monad/Primitive.hs 2014-08-01 14:49:04.175318972 +0300
3−+++ new/Control/Monad/Primitive.hs 2014-08-01 14:49:03.000000000 +0300
4−@@ -44,7 +44,9 @@
5− primitive_ :: PrimMonad m
6− => (State# (PrimState m) -> State# (PrimState m)) -> m ()
7− {-# INLINE primitive_ #-}
8−-primitive_ f = primitive (\s# -> (# f s#, () #))
9−+primitive_ f = primitive (\s# ->
10−+ case f s# of
11−+ s'# -> (# s'#, () #))
12−
13− instance PrimMonad IO where
14− type PrimState IO = RealWorld
15−diff -ruN orig/primitive.cabal new/primitive.cabal
16−--- orig/primitive.cabal 2014-08-01 14:49:04.175318972 +0300
17−+++ new/primitive.cabal 2014-08-01 14:49:03.000000000 +0300
18−@@ -50,6 +50,16 @@
19− if arch(i386) || arch(x86_64)
20− cc-options: -msse2
21−
22−+test-suite test
23−+ Default-Language: Haskell2010
24−+ hs-source-dirs: test
25−+ main-is: main.hs
26−+ type: exitcode-stdio-1.0
27−+ build-depends: base
28−+ , ghc-prim
29−+ , primitive
30−+ ghc-options: -O2
31−+
32− source-repository head
33− type: git
34− location: https://github.com/haskell/primitive
35−diff -ruN orig/test/main.hs new/test/main.hs
36−--- orig/test/main.hs 1970-01-01 02:00:00.000000000 +0200
37−+++ new/test/main.hs 2014-08-01 14:49:03.000000000 +0300
38−@@ -0,0 +1,24 @@
39−+{-# LANGUAGE MagicHash, UnboxedTuples #-}
40−+import Control.Monad.Primitive
41−+import Data.Primitive.Array
42−+import GHC.IO
43−+import GHC.Prim
44−+
45−+-- Since we only have a single test case right now, I'm going to avoid the
46−+-- issue of choosing a test framework for the moment. This also keeps the
47−+-- package as a whole light on dependencies.
48−+
49−+main :: IO ()
50−+main = do
51−+ arr <- newArray 1 'A'
52−+ let unit =
53−+ case writeArray arr 0 'B' of
54−+ IO f ->
55−+ case f realWorld# of
56−+ _ -> ()
57−+ c1 <- readArray arr 0
58−+ return $! unit
59−+ c2 <- readArray arr 0
60−+ if c1 == 'A' && c2 == 'B'
61−+ then return ()
62−+ else error $ "Expected AB, got: " ++ show (c1, c2)
patching/patches/process-conduit-1.0.0.1.patchdeleted−12
@@ -1,12 +0,0 @@
1−Only in new: dist
2−diff -ru orig/process-conduit.cabal new/process-conduit.cabal
3−--- orig/process-conduit.cabal 2014-03-30 12:27:40.781431440 +0300
4−+++ new/process-conduit.cabal 2014-03-30 12:27:40.000000000 +0300
5−@@ -35,6 +35,7 @@
6− , process >= 1.0
7− , conduit == 1.0.*
8− , shakespeare-text >= 1.0
9−+ , shakespeare
10−
11− ghc-options: -Wall
12−
patching/patches/process-conduit-1.0.0.2.patchdeleted−62
@@ -1,62 +0,0 @@
1−diff -ru orig/Data/Conduit/Process.hs new/Data/Conduit/Process.hs
2−--- orig/Data/Conduit/Process.hs 2014-04-03 08:26:07.254383579 +0300
3−+++ new/Data/Conduit/Process.hs 2014-04-03 08:26:06.000000000 +0300
4−@@ -21,6 +21,7 @@
5− import Control.Monad
6− import Control.Monad.Trans
7− import Control.Monad.Trans.Loop
8−+import Control.Monad.Trans.Resource (MonadResource, monadThrow)
9− import qualified Data.ByteString as S
10− import Data.Conduit
11− import qualified Data.Conduit.List as CL
12−diff -ru orig/process-conduit.cabal new/process-conduit.cabal
13−--- orig/process-conduit.cabal 2014-04-03 08:26:07.258383579 +0300
14−+++ new/process-conduit.cabal 2014-04-03 08:26:06.000000000 +0300
15−@@ -33,7 +33,8 @@
16− , bytestring >= 0.9
17− , text >= 0.11
18− , process >= 1.0
19−- , conduit == 1.0.*
20−+ , conduit >= 1.0 && < 1.2
21−+ , resourcet >= 0.4 && < 1.2
22− , shakespeare-text >= 1.0
23− , shakespeare
24−
25−@@ -47,4 +48,6 @@
26− , bytestring
27− , hspec >= 1.3
28− , conduit
29−+ , conduit-extra
30−+ , resourcet
31− , process-conduit
32−diff -ru orig/System/Process/QQ.hs new/System/Process/QQ.hs
33−--- orig/System/Process/QQ.hs 2014-04-03 08:26:07.254383579 +0300
34−+++ new/System/Process/QQ.hs 2014-04-03 08:26:06.000000000 +0300
35−@@ -14,6 +14,7 @@
36− import qualified Data.Text.Lazy as LT
37− import Language.Haskell.TH.Quote
38− import Text.Shakespeare.Text
39−+import Control.Monad.Trans.Resource (runResourceT)
40−
41− import Data.Conduit.Process
42−
43−@@ -28,7 +29,7 @@
44− -- | Command result of (Lazy) ByteString.
45− cmd :: QuasiQuoter
46− cmd = def { quoteExp = \str -> [|
47−- BL.fromChunks <$> C.runResourceT (sourceCmd (LT.unpack $(quoteExp lt str)) C.$$ CL.consume)
48−+ BL.fromChunks <$> runResourceT (sourceCmd (LT.unpack $(quoteExp lt str)) C.$$ CL.consume)
49− |] }
50−
51− -- | Source of shell command
52−diff -ru orig/test.hs new/test.hs
53−--- orig/test.hs 2014-04-03 08:26:07.254383579 +0300
54−+++ new/test.hs 2014-04-03 08:26:06.000000000 +0300
55−@@ -7,6 +7,7 @@
56− import Data.Conduit
57− import qualified Data.Conduit.Binary as CB
58− import Test.Hspec
59−+import Control.Monad.Trans.Resource (runResourceT)
60−
61− main :: IO ()
62− main = hspec $ do
patching/patches/process-conduit-1.1.0.0.patchdeleted−21
@@ -1,21 +0,0 @@
1−diff -ru orig/process-conduit.cabal new/process-conduit.cabal
2−--- orig/process-conduit.cabal 2014-04-04 10:13:39.716407142 +0300
3−+++ new/process-conduit.cabal 2014-04-04 10:13:39.000000000 +0300
4−@@ -48,4 +48,6 @@
5− , bytestring
6− , hspec >= 1.3
7− , conduit
8−+ , conduit-extra
9−+ , resourcet
10− , process-conduit
11−diff -ru orig/test.hs new/test.hs
12−--- orig/test.hs 2014-04-04 10:13:39.692407142 +0300
13−+++ new/test.hs 2014-04-04 10:13:39.000000000 +0300
14−@@ -5,6 +5,7 @@
15−
16− import qualified Data.ByteString.Lazy.Char8 as L
17− import Data.Conduit
18−+import Control.Monad.Trans.Resource (runResourceT)
19− import qualified Data.Conduit.Binary as CB
20− import Test.Hspec
21−
patching/patches/retry-0.4.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/retry.cabal new/retry.cabal
2−--- orig/retry.cabal 2014-05-11 11:28:24.319992770 +0300
3−+++ new/retry.cabal 2014-05-11 11:28:24.000000000 +0300
4−@@ -30,7 +30,7 @@
5− exposed-modules: Control.Retry
6− build-depends:
7− base ==4.*,
8−- exceptions >= 0.5 && < 0.6,
9−+ exceptions >= 0.5 && < 0.7,
10− transformers,
11− data-default
12− hs-source-dirs: src
patching/patches/retry-0.5.patchdeleted−19
@@ -1,19 +0,0 @@
1−diff -ruN orig/retry.cabal new/retry.cabal
2−--- orig/retry.cabal 2014-08-05 09:28:48.350961123 +0300
3−+++ new/retry.cabal 2014-08-05 09:28:48.000000000 +0300
4−@@ -44,13 +44,13 @@
5− ghc-options: -threaded
6− build-depends:
7− base ==4.*
8−- , exceptions >= 0.5 && < 0.6
9−+ , exceptions >= 0.5
10− , transformers
11− , data-default-class
12− , time
13− , QuickCheck >= 2.7 && < 2.8
14− , HUnit >= 1.2.5.2 && < 1.3
15−- , hspec >= 1.9 && < 1.10
16−+ , hspec >= 1.9
17− default-language: Haskell2010
18−
19−
patching/patches/scientific-0.2.0.1.patchdeleted−14
@@ -1,14 +0,0 @@
1−diff -ru orig/scientific.cabal new/scientific.cabal
2−--- orig/scientific.cabal 2014-03-06 14:57:06.880706336 +0200
3−+++ new/scientific.cabal 2014-03-06 14:57:06.000000000 +0200
4−@@ -47,8 +47,8 @@
5−
6− build-depends: scientific
7− , base >= 4.3 && < 4.8
8−- , tasty >= 0.3.1 && < 0.8
9−- , tasty-smallcheck >= 0.2 && < 0.3
10−+ , tasty >= 0.3.1 && < 0.9
11−+ , tasty-smallcheck >= 0.2 && < 0.9
12− , smallcheck >= 1.0 && < 1.2
13− , text >= 0.8 && < 1.2
14−
patching/patches/snap-0.13.2.2.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/snap.cabal new/snap.cabal
2−--- orig/snap.cabal 2014-03-19 10:17:25.886213731 +0200
3−+++ new/snap.cabal 2014-03-19 10:17:25.000000000 +0200
4−@@ -154,7 +154,7 @@
5− containers >= 0.3 && < 0.6,
6− directory >= 1.0 && < 1.3,
7− directory-tree >= 0.11 && < 0.12,
8−- dlist >= 0.5 && < 0.7,
9−+ dlist >= 0.5 && < 0.8,
10− errors >= 1.4 && < 1.5,
11− filepath >= 1.1 && < 1.4,
12− -- Blacklist bad versions of hashable
patching/patches/sqlite-simple-0.4.5.1.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/Database/SQLite/Simple.hs new/Database/SQLite/Simple.hs
2−--- orig/Database/SQLite/Simple.hs 2014-02-14 14:38:24.411759783 +0200
3−+++ new/Database/SQLite/Simple.hs 2014-02-14 14:38:24.000000000 +0200
4−@@ -343,7 +343,7 @@
5− | otherwise -> errorColumnMismatch (ColumnOutOfBounds col)
6− Errors [] -> throwIO $ ConversionFailed "" "" "unknown error"
7− Errors [x] ->
8−- throw x `catch` (\e -> errorColumnMismatch (e :: ColumnOutOfBounds))
9−+ throw x `Control.Exception.catch` (\e -> errorColumnMismatch (e :: ColumnOutOfBounds))
10− Errors xs -> throwIO $ ManyErrors xs
11− where
12− errorColumnMismatch :: ColumnOutOfBounds -> IO r
patching/patches/statistics-0.10.5.2.patchdeleted−705
@@ -1,705 +0,0 @@
1−diff -ru orig/Statistics/Distribution/Beta.hs new/Statistics/Distribution/Beta.hs
2−--- orig/Statistics/Distribution/Beta.hs 2014-04-14 09:04:31.421509375 +0300
3−+++ new/Statistics/Distribution/Beta.hs 2014-04-14 09:04:31.000000000 +0300
4−@@ -1,4 +1,4 @@
5−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
6−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
7− -----------------------------------------------------------------------------
8− -- |
9− -- Module : Statistics.Distribution.Beta
10−@@ -27,6 +27,10 @@
11− incompleteBeta, invIncompleteBeta, logBeta, digamma)
12− import Numeric.MathFunctions.Constants (m_NaN)
13− import qualified Statistics.Distribution as D
14−+#if !MIN_VERSION_binary(0, 6, 0)
15−+import Data.Binary (put, get)
16−+import Control.Applicative ((<$>), (<*>))
17−+#endif
18−
19− -- | The beta distribution
20− data BetaDistribution = BD
21−@@ -36,7 +40,11 @@
22− -- ^ Beta shape parameter
23− } deriving (Eq, Read, Show, Typeable, Data, Generic)
24−
25−-instance Binary BetaDistribution
26−+instance Binary BetaDistribution where
27−+#if !MIN_VERSION_binary(0, 6, 0)
28−+ put (BD x y) = put x >> put y
29−+ get = BD <$> get <*> get
30−+#endif
31−
32− -- | Create beta distribution. Both shape parameters must be positive.
33− betaDistr :: Double -- ^ Shape parameter alpha
34−diff -ru orig/Statistics/Distribution/Binomial.hs new/Statistics/Distribution/Binomial.hs
35−--- orig/Statistics/Distribution/Binomial.hs 2014-04-14 09:04:31.421509375 +0300
36−+++ new/Statistics/Distribution/Binomial.hs 2014-04-14 09:04:31.000000000 +0300
37−@@ -1,4 +1,4 @@
38−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
39−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
40− -- |
41− -- Module : Statistics.Distribution.Binomial
42− -- Copyright : (c) 2009 Bryan O'Sullivan
43−@@ -30,6 +30,10 @@
44− import qualified Statistics.Distribution.Poisson.Internal as I
45− import Numeric.SpecFunctions (choose,incompleteBeta)
46− import Numeric.MathFunctions.Constants (m_epsilon)
47−+#if !MIN_VERSION_binary(0, 6, 0)
48−+import Data.Binary (put, get)
49−+import Control.Applicative ((<$>), (<*>))
50−+#endif
51−
52−
53− -- | The binomial distribution.
54−@@ -40,7 +44,11 @@
55− -- ^ Probability.
56− } deriving (Eq, Read, Show, Typeable, Data, Generic)
57−
58−-instance Binary BinomialDistribution
59−+instance Binary BinomialDistribution where
60−+#if !MIN_VERSION_binary(0, 6, 0)
61−+ put (BD x y) = put x >> put y
62−+ get = BD <$> get <*> get
63−+#endif
64−
65− instance D.Distribution BinomialDistribution where
66− cumulative = cumulative
67−diff -ru orig/Statistics/Distribution/CauchyLorentz.hs new/Statistics/Distribution/CauchyLorentz.hs
68−--- orig/Statistics/Distribution/CauchyLorentz.hs 2014-04-14 09:04:31.421509375 +0300
69−+++ new/Statistics/Distribution/CauchyLorentz.hs 2014-04-14 09:04:31.000000000 +0300
70−@@ -1,4 +1,4 @@
71−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
72−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
73− -- |
74− -- Module : Statistics.Distribution.CauchyLorentz
75− -- Copyright : (c) 2011 Aleksey Khudyakov
76−@@ -25,6 +25,10 @@
77− import Data.Data (Data, Typeable)
78− import GHC.Generics (Generic)
79− import qualified Statistics.Distribution as D
80−+#if !MIN_VERSION_binary(0, 6, 0)
81−+import Data.Binary (put, get)
82−+import Control.Applicative ((<$>), (<*>))
83−+#endif
84−
85− -- | Cauchy-Lorentz distribution.
86− data CauchyDistribution = CD {
87−@@ -39,7 +43,11 @@
88− }
89− deriving (Eq, Show, Read, Typeable, Data, Generic)
90−
91−-instance Binary CauchyDistribution
92−+instance Binary CauchyDistribution where
93−+#if !MIN_VERSION_binary(0, 6, 0)
94−+ put (CD x y) = put x >> put y
95−+ get = CD <$> get <*> get
96−+#endif
97−
98− -- | Cauchy distribution
99− cauchyDistribution :: Double -- ^ Central point
100−diff -ru orig/Statistics/Distribution/ChiSquared.hs new/Statistics/Distribution/ChiSquared.hs
101−--- orig/Statistics/Distribution/ChiSquared.hs 2014-04-14 09:04:31.421509375 +0300
102−+++ new/Statistics/Distribution/ChiSquared.hs 2014-04-14 09:04:31.000000000 +0300
103−@@ -1,4 +1,4 @@
104−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
105−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
106− -- |
107− -- Module : Statistics.Distribution.ChiSquared
108− -- Copyright : (c) 2010 Alexey Khudyakov
109−@@ -26,13 +26,20 @@
110−
111− import qualified Statistics.Distribution as D
112− import qualified System.Random.MWC.Distributions as MWC
113−+#if !MIN_VERSION_binary(0, 6, 0)
114−+import Data.Binary (put, get)
115−+#endif
116−
117−
118− -- | Chi-squared distribution
119− newtype ChiSquared = ChiSquared Int
120− deriving (Eq, Read, Show, Typeable, Data, Generic)
121−
122−-instance Binary ChiSquared
123−+instance Binary ChiSquared where
124−+#if !MIN_VERSION_binary(0, 6, 0)
125−+ get = fmap ChiSquared get
126−+ put (ChiSquared x) = put x
127−+#endif
128−
129− -- | Get number of degrees of freedom
130− chiSquaredNDF :: ChiSquared -> Int
131−diff -ru orig/Statistics/Distribution/Exponential.hs new/Statistics/Distribution/Exponential.hs
132−--- orig/Statistics/Distribution/Exponential.hs 2014-04-14 09:04:31.421509375 +0300
133−+++ new/Statistics/Distribution/Exponential.hs 2014-04-14 09:04:31.000000000 +0300
134−@@ -1,4 +1,4 @@
135−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
136−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
137− -- |
138− -- Module : Statistics.Distribution.Exponential
139− -- Copyright : (c) 2009 Bryan O'Sullivan
140−@@ -31,13 +31,20 @@
141− import qualified Statistics.Sample as S
142− import qualified System.Random.MWC.Distributions as MWC
143− import Statistics.Types (Sample)
144−+#if !MIN_VERSION_binary(0, 6, 0)
145−+import Data.Binary (put, get)
146−+#endif
147−
148−
149− newtype ExponentialDistribution = ED {
150− edLambda :: Double
151− } deriving (Eq, Read, Show, Typeable, Data, Generic)
152−
153−-instance Binary ExponentialDistribution
154−+instance Binary ExponentialDistribution where
155−+#if !MIN_VERSION_binary(0, 6, 0)
156−+ put = put . edLambda
157−+ get = fmap ED get
158−+#endif
159−
160− instance D.Distribution ExponentialDistribution where
161− cumulative = cumulative
162−diff -ru orig/Statistics/Distribution/FDistribution.hs new/Statistics/Distribution/FDistribution.hs
163−--- orig/Statistics/Distribution/FDistribution.hs 2014-04-14 09:04:31.421509375 +0300
164−+++ new/Statistics/Distribution/FDistribution.hs 2014-04-14 09:04:31.000000000 +0300
165−@@ -1,4 +1,4 @@
166−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
167−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
168− -- |
169− -- Module : Statistics.Distribution.FDistribution
170− -- Copyright : (c) 2011 Aleksey Khudyakov
171−@@ -23,6 +23,10 @@
172− import qualified Statistics.Distribution as D
173− import Numeric.SpecFunctions (
174− logBeta, incompleteBeta, invIncompleteBeta, digamma)
175−+#if !MIN_VERSION_binary(0, 6, 0)
176−+import Data.Binary (put, get)
177−+import Control.Applicative ((<$>), (<*>))
178−+#endif
179−
180−
181−
182−@@ -33,7 +37,11 @@
183− }
184− deriving (Eq, Show, Read, Typeable, Data, Generic)
185−
186−-instance Binary FDistribution
187−+instance Binary FDistribution where
188−+#if !MIN_VERSION_binary(0, 6, 0)
189−+ get = F <$> get <*> get <*> get
190−+ put (F x y z) = put x >> put y >> put z
191−+#endif
192−
193− fDistribution :: Int -> Int -> FDistribution
194− fDistribution n m
195−diff -ru orig/Statistics/Distribution/Gamma.hs new/Statistics/Distribution/Gamma.hs
196−--- orig/Statistics/Distribution/Gamma.hs 2014-04-14 09:04:31.421509375 +0300
197−+++ new/Statistics/Distribution/Gamma.hs 2014-04-14 09:04:31.000000000 +0300
198−@@ -1,4 +1,4 @@
199−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
200−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
201− -- |
202− -- Module : Statistics.Distribution.Gamma
203− -- Copyright : (c) 2009, 2011 Bryan O'Sullivan
204−@@ -34,6 +34,10 @@
205− import Statistics.Distribution.Poisson.Internal as Poisson
206− import qualified Statistics.Distribution as D
207− import qualified System.Random.MWC.Distributions as MWC
208−+#if !MIN_VERSION_binary(0, 6, 0)
209−+import Data.Binary (put, get)
210−+import Control.Applicative ((<$>), (<*>))
211−+#endif
212−
213− -- | The gamma distribution.
214− data GammaDistribution = GD {
215−@@ -41,7 +45,11 @@
216− , gdScale :: {-# UNPACK #-} !Double -- ^ Scale parameter, &#977;.
217− } deriving (Eq, Read, Show, Typeable, Data, Generic)
218−
219−-instance Binary GammaDistribution
220−+instance Binary GammaDistribution where
221−+#if !MIN_VERSION_binary(0, 6, 0)
222−+ put (GD x y) = put x >> put y
223−+ get = GD <$> get <*> get
224−+#endif
225−
226− -- | Create gamma distribution. Both shape and scale parameters must
227− -- be positive.
228−diff -ru orig/Statistics/Distribution/Geometric.hs new/Statistics/Distribution/Geometric.hs
229−--- orig/Statistics/Distribution/Geometric.hs 2014-04-14 09:04:31.421509375 +0300
230−+++ new/Statistics/Distribution/Geometric.hs 2014-04-14 09:04:31.000000000 +0300
231−@@ -1,4 +1,4 @@
232−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
233−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
234− -- |
235− -- Module : Statistics.Distribution.Geometric
236− -- Copyright : (c) 2009 Bryan O'Sullivan
237−@@ -37,6 +37,10 @@
238− import Numeric.MathFunctions.Constants(m_pos_inf,m_neg_inf)
239− import qualified Statistics.Distribution as D
240− import qualified System.Random.MWC.Distributions as MWC
241−+#if !MIN_VERSION_binary(0, 6, 0)
242−+import Data.Binary (put, get)
243−+import Control.Applicative ((<$>))
244−+#endif
245−
246− ----------------------------------------------------------------
247− -- Distribution over [1..]
248−@@ -45,7 +49,11 @@
249− gdSuccess :: Double
250− } deriving (Eq, Read, Show, Typeable, Data, Generic)
251−
252−-instance Binary GeometricDistribution
253−+instance Binary GeometricDistribution where
254−+#if !MIN_VERSION_binary(0, 6, 0)
255−+ get = GD <$> get
256−+ put (GD x) = put x
257−+#endif
258−
259− instance D.Distribution GeometricDistribution where
260− cumulative = cumulative
261−@@ -115,7 +123,11 @@
262− gdSuccess0 :: Double
263− } deriving (Eq, Read, Show, Typeable, Data, Generic)
264−
265−-instance Binary GeometricDistribution0
266−+instance Binary GeometricDistribution0 where
267−+#if !MIN_VERSION_binary(0, 6, 0)
268−+ get = GD0 <$> get
269−+ put (GD0 x) = put x
270−+#endif
271−
272− instance D.Distribution GeometricDistribution0 where
273− cumulative (GD0 s) x = cumulative (GD s) (x + 1)
274−diff -ru orig/Statistics/Distribution/Hypergeometric.hs new/Statistics/Distribution/Hypergeometric.hs
275−--- orig/Statistics/Distribution/Hypergeometric.hs 2014-04-14 09:04:31.421509375 +0300
276−+++ new/Statistics/Distribution/Hypergeometric.hs 2014-04-14 09:04:31.000000000 +0300
277−@@ -1,4 +1,4 @@
278−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
279−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
280− -- |
281− -- Module : Statistics.Distribution.Hypergeometric
282− -- Copyright : (c) 2009 Bryan O'Sullivan
283−@@ -33,6 +33,10 @@
284− import Numeric.MathFunctions.Constants (m_epsilon)
285− import Numeric.SpecFunctions (choose)
286− import qualified Statistics.Distribution as D
287−+#if !MIN_VERSION_binary(0, 6, 0)
288−+import Data.Binary (put, get)
289−+import Control.Applicative ((<$>), (<*>))
290−+#endif
291−
292− data HypergeometricDistribution = HD {
293− hdM :: {-# UNPACK #-} !Int
294−@@ -40,7 +44,11 @@
295− , hdK :: {-# UNPACK #-} !Int
296− } deriving (Eq, Read, Show, Typeable, Data, Generic)
297−
298−-instance Binary HypergeometricDistribution
299−+instance Binary HypergeometricDistribution where
300−+#if !MIN_VERSION_binary(0, 6, 0)
301−+ get = HD <$> get <*> get <*> get
302−+ put (HD x y z) = put x >> put y >> put z
303−+#endif
304−
305− instance D.Distribution HypergeometricDistribution where
306− cumulative = cumulative
307−diff -ru orig/Statistics/Distribution/Normal.hs new/Statistics/Distribution/Normal.hs
308−--- orig/Statistics/Distribution/Normal.hs 2014-04-14 09:04:31.421509375 +0300
309−+++ new/Statistics/Distribution/Normal.hs 2014-04-14 09:04:31.000000000 +0300
310−@@ -1,4 +1,4 @@
311−-{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric #-}
312−+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, CPP #-}
313− -- |
314− -- Module : Statistics.Distribution.Normal
315− -- Copyright : (c) 2009 Bryan O'Sullivan
316−@@ -28,6 +28,8 @@
317− import qualified Statistics.Distribution as D
318− import qualified Statistics.Sample as S
319− import qualified System.Random.MWC.Distributions as MWC
320−+import Data.Binary (put, get)
321−+import Control.Applicative ((<$>), (<*>))
322−
323−
324−
325−@@ -39,7 +41,9 @@
326− , ndCdfDenom :: {-# UNPACK #-} !Double
327− } deriving (Eq, Read, Show, Typeable, Data, Generic)
328−
329−-instance Binary NormalDistribution
330−+instance Binary NormalDistribution where
331−+ put (ND w x y z) = put w >> put x >> put y >> put z
332−+ get = ND <$> get <*> get <*> get <*> get
333−
334− instance D.Distribution NormalDistribution where
335− cumulative = cumulative
336−diff -ru orig/Statistics/Distribution/Poisson/Internal.hs new/Statistics/Distribution/Poisson/Internal.hs
337−--- orig/Statistics/Distribution/Poisson/Internal.hs 2014-04-14 09:04:31.421509375 +0300
338−+++ new/Statistics/Distribution/Poisson/Internal.hs 2014-04-14 09:04:31.000000000 +0300
339−@@ -36,8 +36,8 @@
340− -- | Compute entropy using Theorem 1 from "Sharp Bounds on the Entropy
341− -- of the Poisson Law". This function is unused because 'directEntorpy'
342− -- is just as accurate and is faster by about a factor of 4.
343−-alyThm1 :: Double -> Double
344−-alyThm1 lambda =
345−+_alyThm1 :: Double -> Double
346−+_alyThm1 lambda =
347− sum (takeWhile (\x -> abs x >= m_epsilon * lll) alySeries) + lll
348− where lll = lambda * (1 - log lambda)
349− alySeries =
350−@@ -175,4 +175,4 @@
351− | lambda <= 18 = alyThm2 lambda upperCoefficients6 lowerCoefficients6
352− | lambda <= 24 = alyThm2 lambda upperCoefficients8 lowerCoefficients8
353− | lambda <= 30 = alyThm2 lambda upperCoefficients10 lowerCoefficients10
354−- | otherwise = alyThm2 lambda upperCoefficients12 lowerCoefficients12
355−\ No newline at end of file
356−+ | otherwise = alyThm2 lambda upperCoefficients12 lowerCoefficients12
357−diff -ru orig/Statistics/Distribution/Poisson.hs new/Statistics/Distribution/Poisson.hs
358−--- orig/Statistics/Distribution/Poisson.hs 2014-04-14 09:04:31.421509375 +0300
359−+++ new/Statistics/Distribution/Poisson.hs 2014-04-14 09:04:31.000000000 +0300
360−@@ -1,4 +1,4 @@
361−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
362−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
363− -- |
364− -- Module : Statistics.Distribution.Poisson
365− -- Copyright : (c) 2009, 2011 Bryan O'Sullivan
366−@@ -31,13 +31,20 @@
367− import qualified Statistics.Distribution.Poisson.Internal as I
368− import Numeric.SpecFunctions (incompleteGamma,logFactorial)
369− import Numeric.MathFunctions.Constants (m_neg_inf)
370−+#if !MIN_VERSION_binary(0, 6, 0)
371−+import Data.Binary (put, get)
372−+#endif
373−
374−
375− newtype PoissonDistribution = PD {
376− poissonLambda :: Double
377− } deriving (Eq, Read, Show, Typeable, Data, Generic)
378−
379−-instance Binary PoissonDistribution
380−+instance Binary PoissonDistribution where
381−+#if !MIN_VERSION_binary(0, 6, 0)
382−+ get = fmap PD get
383−+ put = put . poissonLambda
384−+#endif
385−
386− instance D.Distribution PoissonDistribution where
387− cumulative (PD lambda) x
388−@@ -78,8 +85,9 @@
389− poisson :: Double -> PoissonDistribution
390− poisson l
391− | l >= 0 = PD l
392−- | otherwise = error $ "Statistics.Distribution.Poisson.poisson:\
393−- \ lambda must be non-negative. Got " ++ show l
394−+ | otherwise = error $
395−+ "Statistics.Distribution.Poisson.poisson: lambda must be non-negative. Got "
396−+ ++ show l
397− {-# INLINE poisson #-}
398−
399− -- $references
400−diff -ru orig/Statistics/Distribution/StudentT.hs new/Statistics/Distribution/StudentT.hs
401−--- orig/Statistics/Distribution/StudentT.hs 2014-04-14 09:04:31.421509375 +0300
402−+++ new/Statistics/Distribution/StudentT.hs 2014-04-14 09:04:31.000000000 +0300
403−@@ -1,4 +1,4 @@
404−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
405−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
406− -- |
407− -- Module : Statistics.Distribution.StudentT
408− -- Copyright : (c) 2011 Aleksey Khudyakov
409−@@ -23,12 +23,19 @@
410− import Statistics.Distribution.Transform (LinearTransform (..))
411− import Numeric.SpecFunctions (
412− logBeta, incompleteBeta, invIncompleteBeta, digamma)
413−+#if !MIN_VERSION_binary(0, 6, 0)
414−+import Data.Binary (put, get)
415−+#endif
416−
417− -- | Student-T distribution
418− newtype StudentT = StudentT { studentTndf :: Double }
419− deriving (Eq, Show, Read, Typeable, Data, Generic)
420−
421−-instance Binary StudentT
422−+instance Binary StudentT where
423−+#if !MIN_VERSION_binary(0, 6, 0)
424−+ put = put . studentTndf
425−+ get = fmap StudentT get
426−+#endif
427−
428− -- | Create Student-T distribution. Number of parameters must be positive.
429− studentT :: Double -> StudentT
430−diff -ru orig/Statistics/Distribution/Transform.hs new/Statistics/Distribution/Transform.hs
431−--- orig/Statistics/Distribution/Transform.hs 2014-04-14 09:04:31.421509375 +0300
432−+++ new/Statistics/Distribution/Transform.hs 2014-04-14 09:04:31.000000000 +0300
433−@@ -1,5 +1,5 @@
434− {-# LANGUAGE DeriveDataTypeable, DeriveGeneric, FlexibleContexts,
435−- FlexibleInstances, UndecidableInstances #-}
436−+ FlexibleInstances, UndecidableInstances, CPP #-}
437− -- |
438− -- Module : Statistics.Distribution.Transform
439− -- Copyright : (c) 2013 John McDonnell;
440−@@ -21,6 +21,10 @@
441− import GHC.Generics (Generic)
442− import Data.Functor ((<$>))
443− import qualified Statistics.Distribution as D
444−+#if !MIN_VERSION_binary(0, 6, 0)
445−+import Data.Binary (put, get)
446−+import Control.Applicative ((<*>))
447−+#endif
448−
449− -- | Linear transformation applied to distribution.
450− --
451−@@ -35,7 +39,11 @@
452− -- ^ Distribution being transformed.
453− } deriving (Eq, Show, Read, Typeable, Data, Generic)
454−
455−-instance (Binary d) => Binary (LinearTransform d)
456−+instance (Binary d) => Binary (LinearTransform d) where
457−+#if !MIN_VERSION_binary(0, 6, 0)
458−+ get = LinearTransform <$> get <*> get <*> get
459−+ put (LinearTransform x y z) = put x >> put y >> put z
460−+#endif
461−
462− -- | Apply linear transformation to distribution.
463− scaleAround :: Double -- ^ Fixed point
464−diff -ru orig/Statistics/Distribution/Uniform.hs new/Statistics/Distribution/Uniform.hs
465−--- orig/Statistics/Distribution/Uniform.hs 2014-04-14 09:04:31.421509375 +0300
466−+++ new/Statistics/Distribution/Uniform.hs 2014-04-14 09:04:31.000000000 +0300
467−@@ -1,4 +1,4 @@
468−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
469−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, CPP #-}
470− -- |
471− -- Module : Statistics.Distribution.Uniform
472− -- Copyright : (c) 2011 Aleksey Khudyakov
473−@@ -24,6 +24,10 @@
474− import GHC.Generics (Generic)
475− import qualified Statistics.Distribution as D
476− import qualified System.Random.MWC as MWC
477−+#if !MIN_VERSION_binary(0, 6, 0)
478−+import Data.Binary (put, get)
479−+import Control.Applicative ((<$>), (<*>))
480−+#endif
481−
482−
483− -- | Uniform distribution from A to B
484−@@ -32,7 +36,11 @@
485− , uniformB :: {-# UNPACK #-} !Double -- ^ Upper boundary of distribution
486− } deriving (Eq, Read, Show, Typeable, Data, Generic)
487−
488−-instance Binary UniformDistribution
489−+instance Binary UniformDistribution where
490−+#if !MIN_VERSION_binary(0, 6, 0)
491−+ put (UniformDistribution x y) = put x >> put y
492−+ get = UniformDistribution <$> get <*> get
493−+#endif
494−
495− -- | Create uniform distribution.
496− uniformDistr :: Double -> Double -> UniformDistribution
497−diff -ru orig/Statistics/Math/RootFinding.hs new/Statistics/Math/RootFinding.hs
498−--- orig/Statistics/Math/RootFinding.hs 2014-04-14 09:04:31.421509375 +0300
499−+++ new/Statistics/Math/RootFinding.hs 2014-04-14 09:04:31.000000000 +0300
500−@@ -1,4 +1,4 @@
501−-{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric #-}
502−+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, CPP #-}
503−
504− -- |
505− -- Module : Statistics.Math.RootFinding
506−@@ -27,6 +27,11 @@
507− import Control.Monad (MonadPlus(..), ap)
508− import Data.Data (Data, Typeable)
509− import GHC.Generics (Generic)
510−+#if !MIN_VERSION_binary(0, 6, 0)
511−+import Data.Binary (put, get)
512−+import Data.Binary.Put (putWord8)
513−+import Data.Binary.Get (getWord8)
514−+#endif
515−
516−
517− -- | The result of searching for a root of a mathematical function.
518−@@ -40,7 +45,20 @@
519− -- ^ A root was successfully found.
520− deriving (Eq, Read, Show, Typeable, Data, Generic)
521−
522−-instance (Binary a) => Binary (Root a)
523−+instance (Binary a) => Binary (Root a) where
524−+#if !MIN_VERSION_binary(0, 6, 0)
525−+ put NotBracketed = putWord8 0
526−+ put SearchFailed = putWord8 1
527−+ put (Root a) = putWord8 2 >> put a
528−+
529−+ get = do
530−+ i <- getWord8
531−+ case i of
532−+ 0 -> return NotBracketed
533−+ 1 -> return SearchFailed
534−+ 2 -> fmap Root get
535−+ _ -> fail $ "Root.get: Invalid value: " ++ show i
536−+#endif
537−
538− instance Functor Root where
539− fmap _ NotBracketed = NotBracketed
540−diff -ru orig/Statistics/Resampling/Bootstrap.hs new/Statistics/Resampling/Bootstrap.hs
541−--- orig/Statistics/Resampling/Bootstrap.hs 2014-04-14 09:04:31.421509375 +0300
542−+++ new/Statistics/Resampling/Bootstrap.hs 2014-04-14 09:04:31.000000000 +0300
543−@@ -1,5 +1,5 @@
544− {-# LANGUAGE DeriveDataTypeable, DeriveGeneric, OverloadedStrings,
545−- RecordWildCards #-}
546−+ RecordWildCards, CPP #-}
547−
548− -- |
549− -- Module : Statistics.Resampling.Bootstrap
550−@@ -35,6 +35,10 @@
551− import Statistics.Sample (mean)
552− import Statistics.Types (Estimator, Sample)
553− import qualified Data.Vector.Unboxed as U
554−+#if !MIN_VERSION_binary(0, 6, 0)
555−+import Data.Binary (put, get)
556−+import Control.Applicative ((<$>), (<*>))
557−+#endif
558−
559− -- | A point and interval estimate computed via an 'Estimator'.
560− data Estimate = Estimate {
561−@@ -50,7 +54,11 @@
562− -- ^ Confidence level of the confidence intervals.
563− } deriving (Eq, Read, Show, Typeable, Data, Generic)
564−
565−-instance Binary Estimate
566−+instance Binary Estimate where
567−+#if !MIN_VERSION_binary(0, 6, 0)
568−+ put (Estimate w x y z) = put w >> put x >> put y >> put z
569−+ get = Estimate <$> get <*> get <*> get <*> get
570−+#endif
571− instance NFData Estimate
572−
573− -- | Multiply the point, lower bound, and upper bound in an 'Estimate'
574−diff -ru orig/Statistics/Resampling.hs new/Statistics/Resampling.hs
575−--- orig/Statistics/Resampling.hs 2014-04-14 09:04:31.421509375 +0300
576−+++ new/Statistics/Resampling.hs 2014-04-14 09:04:31.000000000 +0300
577−@@ -1,4 +1,4 @@
578−-{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric #-}
579−+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, CPP #-}
580−
581− -- |
582− -- Module : Statistics.Resampling
583−@@ -42,7 +42,11 @@
584− fromResample :: U.Vector Double
585− } deriving (Eq, Read, Show, Typeable, Data, Generic)
586−
587−-instance Binary Resample
588−+instance Binary Resample where
589−+#if !MIN_VERSION_binary(0, 6, 0)
590−+ put = put . fromResample
591−+ get = fmap Resample get
592−+#endif
593−
594− -- | /O(e*r*s)/ Resample a data set repeatedly, with replacement,
595− -- computing each estimate over the resampled data.
596−diff -ru orig/Statistics/Sample/KernelDensity/Simple.hs new/Statistics/Sample/KernelDensity/Simple.hs
597−--- orig/Statistics/Sample/KernelDensity/Simple.hs 2014-04-14 09:04:31.425509375 +0300
598−+++ new/Statistics/Sample/KernelDensity/Simple.hs 2014-04-14 09:04:31.000000000 +0300
599−@@ -1,4 +1,4 @@
600−-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, FlexibleContexts #-}
601−+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, FlexibleContexts, CPP #-}
602− -- |
603− -- Module : Statistics.Sample.KernelDensity.Simple
604− -- Copyright : (c) 2009 Bryan O'Sullivan
605−@@ -61,7 +61,11 @@
606− fromPoints :: U.Vector Double
607− } deriving (Eq, Read, Show, Typeable, Data, Generic)
608−
609−-instance Binary Points
610−+instance Binary Points where
611−+#if !MIN_VERSION_binary(0, 6, 0)
612−+ get = fmap Points get
613−+ put = put . fromPoints
614−+#endif
615−
616− -- | Bandwidth estimator for an Epanechnikov kernel.
617− epanechnikovBW :: Double -> Bandwidth
618−diff -ru orig/Statistics/Sample/Powers.hs new/Statistics/Sample/Powers.hs
619−--- orig/Statistics/Sample/Powers.hs 2014-04-14 09:04:31.421509375 +0300
620−+++ new/Statistics/Sample/Powers.hs 2014-04-14 09:04:31.000000000 +0300
621−@@ -1,5 +1,5 @@
622− {-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric,
623−- FlexibleContexts #-}
624−+ FlexibleContexts, CPP #-}
625− -- |
626− -- Module : Statistics.Sample.Powers
627− -- Copyright : (c) 2009, 2010 Bryan O'Sullivan
628−@@ -65,7 +65,11 @@
629− newtype Powers = Powers (U.Vector Double)
630− deriving (Eq, Read, Show, Typeable, Data, Generic)
631−
632−-instance Binary Powers
633−+instance Binary Powers where
634−+#if !MIN_VERSION_binary(0, 6, 0)
635−+ put (Powers v) = put v
636−+ get = fmap Powers get
637−+#endif
638−
639− -- | O(/n/) Collect the /n/ simple powers of a sample.
640− --
641−diff -ru orig/statistics.cabal new/statistics.cabal
642−--- orig/statistics.cabal 2014-04-14 09:04:31.429509375 +0300
643−+++ new/statistics.cabal 2014-04-14 09:04:31.000000000 +0300
644−@@ -90,7 +90,7 @@
645− Statistics.Test.Internal
646− build-depends:
647− base < 5,
648−- binary >= 0.6.3.0,
649−+ binary >= 0.5.1.0,
650− deepseq >= 1.1.0.2,
651− erf,
652− monad-par >= 0.3.4,
653−diff -ru orig/tests/Tests/Distribution.hs new/tests/Tests/Distribution.hs
654−--- orig/tests/Tests/Distribution.hs 2014-04-14 09:04:31.425509375 +0300
655−+++ new/tests/Tests/Distribution.hs 2014-04-14 09:04:31.000000000 +0300
656−@@ -188,7 +188,7 @@
657−
658− -- Quantile is inverse of CDF
659− quantileIsInvCDF :: (Param d, ContDistr d) => T d -> d -> Double -> Property
660−-quantileIsInvCDF _ d (snd . properFraction -> p) =
661−+quantileIsInvCDF _ d ((snd :: (Int, y) -> y) . properFraction -> p) =
662− p > 0 && p < 1 ==> ( printTestCase (printf "Quantile = %g" q )
663− $ printTestCase (printf "Probability = %g" p )
664− $ printTestCase (printf "Probability' = %g" p')
665−@@ -203,8 +203,8 @@
666− quantileShouldFail :: (ContDistr d) => T d -> d -> Double -> Property
667− quantileShouldFail _ d p =
668− p < 0 || p > 1 ==> QC.monadicIO $ do r <- QC.run $ catch
669−- (do { return $! quantile d p; return False })
670−- (\(e :: SomeException) -> return True)
671−+ (do { _ <- return $! quantile d p; return False })
672−+ (\(_e :: SomeException) -> return True)
673− QC.assert r
674−
675−
676−diff -ru orig/tests/Tests/Function.hs new/tests/Tests/Function.hs
677−--- orig/tests/Tests/Function.hs 2014-04-14 09:04:31.425509375 +0300
678−+++ new/tests/Tests/Function.hs 2014-04-14 09:04:31.000000000 +0300
679−@@ -1,7 +1,6 @@
680− module Tests.Function ( tests ) where
681−
682− import qualified Data.Vector.Unboxed as U
683−-import Data.Vector.Unboxed ((!))
684−
685− import Test.QuickCheck
686− import Test.Framework
687−@@ -29,5 +28,5 @@
688− p_nextHighestPowerOfTwo
689− = all (\(good, is) -> all ((==good) . nextHighestPowerOfTwo) is) lists
690− where
691−- pows = [1 .. 17]
692−+ pows = [1 .. 17 :: Int]
693− lists = [ (2^m, [2^n+1 .. 2^m]) | (n,m) <- pows `zip` tail pows ]
694−diff -ru orig/tests/Tests/Transform.hs new/tests/Tests/Transform.hs
695−--- orig/tests/Tests/Transform.hs 2014-04-14 09:04:31.425509375 +0300
696−+++ new/tests/Tests/Transform.hs 2014-04-14 09:04:31.000000000 +0300
697−@@ -15,7 +15,7 @@
698− import Test.Framework (Test, testGroup)
699− import Test.Framework.Providers.QuickCheck2 (testProperty)
700− import Test.QuickCheck (Positive(..),Property,Arbitrary(..),Gen,choose,vectorOf,
701−- printTestCase, quickCheck)
702−+ printTestCase)
703−
704− import Text.Printf
705−
patching/patches/stm-conduit-2.3.0.patchdeleted−16
@@ -1,16 +0,0 @@
1−diff -ru orig/stm-conduit.cabal new/stm-conduit.cabal
2−--- orig/stm-conduit.cabal 2014-04-03 08:22:14.310388538 +0300
3−+++ new/stm-conduit.cabal 2014-04-03 08:22:14.000000000 +0300
4−@@ -29,9 +29,10 @@
5− , stm-chans >= 2.0 && < 3.1
6− , cereal >= 0.4.0.1
7− , cereal-conduit >= 0.7.2
8−- , conduit == 1.0.*
9−+ , conduit >= 1.0 && < 1.2
10−+ , conduit-extra >= 1.0 && < 1.2
11− , directory >= 1.1
12−- , resourcet >= 0.3 && < 0.5
13−+ , resourcet >= 0.3 && < 1.2
14− , async >= 2.0.1
15− , monad-control >= 0.3.2
16− , monad-loops >= 0.4.2
patching/patches/stm-conduit-2.5.1.patchdeleted−201
@@ -1,201 +0,0 @@
1−diff -ruN orig/Data/Conduit/TMChan.hs new/Data/Conduit/TMChan.hs
2−--- orig/Data/Conduit/TMChan.hs 2014-08-27 18:36:44.141176333 +0300
3−+++ new/Data/Conduit/TMChan.hs 2014-08-27 18:36:43.000000000 +0300
4−@@ -63,22 +63,23 @@
5− import Control.Concurrent.STM.TMChan
6−
7− import Data.Conduit
8−-import Data.Conduit.Internal (Pipe (..), ConduitM (..))
9−+import qualified Data.Conduit.List as CL
10−
11−-chanSource
12−+chanSource
13− :: MonadIO m
14− => chan -- ^ The channel.
15− -> (chan -> STM (Maybe a)) -- ^ The 'read' function.
16− -> (chan -> STM ()) -- ^ The 'close' function.
17− -> Source m a
18−-chanSource ch reader closer = ConduitM src
19−- where
20−- src = PipeM pull
21−- pull = do a <- liftSTM $ reader ch
22−- case a of
23−- Just x -> return $ HaveOutput src close x
24−- Nothing -> return $ Done ()
25−- close = liftSTM $ closer ch
26−+chanSource ch reader closer =
27−+ loop
28−+ where
29−+ loop = do
30−+ a <- liftSTM $ reader ch
31−+ case a of
32−+ Just x -> yieldOr x close >> loop
33−+ Nothing -> return ()
34−+ close = liftSTM $ closer ch
35− {-# INLINE chanSource #-}
36−
37− chanSink
38−@@ -87,13 +88,9 @@
39− -> (chan -> a -> STM ()) -- ^ The 'write' function.
40− -> (chan -> STM ()) -- ^ The 'close' function.
41− -> Sink a m ()
42−-chanSink ch writer closer = ConduitM sink
43−- where
44−- sink = NeedInput push close
45−-
46−- push input = PipeM ((liftIO . atomically $ writer ch input)
47−- >> (return $ NeedInput push close))
48−- close = const . liftSTM $ closer ch
49−+chanSink ch writer closer = do
50−+ CL.mapM_ $ liftIO . atomically . writer ch
51−+ liftSTM $ closer ch
52− {-# INLINE chanSink #-}
53−
54− -- | A simple wrapper around a TBMChan. As data is pushed into the channel, the
55−diff -ruN orig/Data/Conduit/TQueue.hs new/Data/Conduit/TQueue.hs
56−--- orig/Data/Conduit/TQueue.hs 2014-08-27 18:36:44.141176333 +0300
57−+++ new/Data/Conduit/TQueue.hs 2014-08-27 18:36:43.000000000 +0300
58−@@ -58,46 +58,28 @@
59− import Control.Monad
60− import Control.Monad.IO.Class
61− import Data.Conduit
62−-import Data.Conduit.Internal
63−+import qualified Data.Conduit.List as CL
64−
65− -- | A simple wrapper around a "TQueue". As data is pushed into the queue, the
66− -- source will read it and pass it down the conduit pipeline.
67− sourceTQueue :: MonadIO m => TQueue a -> Source m a
68−-sourceTQueue q = ConduitM src
69−- where src = PipeM pull
70−- pull = do x <- liftSTM $ readTQueue q
71−- return $ HaveOutput src close x
72−- close = return ()
73−+sourceTQueue q = forever $ liftSTM (readTQueue q) >>= yield
74−
75− -- | A simple wrapper around a "TQueue". As data is pushed into this sink, it
76− -- will magically begin to appear in the queue.
77− sinkTQueue :: MonadIO m => TQueue a -> Sink a m ()
78−-sinkTQueue q = ConduitM src
79−- where src = sink
80−- sink = NeedInput push close
81−- push input = PipeM ((liftSTM $ writeTQueue q input)
82−- >> (return $ NeedInput push close))
83−- close _ = return ()
84−+sinkTQueue q = CL.mapM_ (liftSTM . writeTQueue q)
85−
86− -- | A simple wrapper around a "TBQueue". As data is pushed into the queue, the
87− -- source will read it and pass it down the conduit pipeline.
88− sourceTBQueue :: MonadIO m => TBQueue a -> Source m a
89−-sourceTBQueue q = ConduitM src
90−- where src = PipeM pull
91−- pull = do x <- liftSTM $ readTBQueue q
92−- return $ HaveOutput src close x
93−- close = return ()
94−+sourceTBQueue q = forever $ liftSTM (readTBQueue q) >>= yield
95−
96− -- | A simple wrapper around a "TBQueue". As data is pushed into this sink, it
97− -- will magically begin to appear in the queue. Boolean argument is used
98− -- to specify if queue should be closed when the sink is closed.
99− sinkTBQueue :: MonadIO m => TBQueue a -> Sink a m ()
100−-sinkTBQueue q = ConduitM src
101−- where src = sink
102−- sink = NeedInput push close
103−- push input = PipeM ((liftSTM $ writeTBQueue q input)
104−- >> (return $ NeedInput push close))
105−- close _ = return ()
106−+sinkTBQueue q = CL.mapM_ (liftSTM . writeTBQueue q)
107−
108− -- | A convenience wrapper for creating a source and sink TBQueue of the given
109− -- size at once, without exposing the underlying queue.
110−@@ -109,14 +91,15 @@
111− -- source will read it and pass it down the conduit pipeline. When the
112− -- queue is closed, the source will close also.
113− sourceTMQueue :: MonadIO m => TMQueue a -> Source m a
114−-sourceTMQueue q = ConduitM src
115−- where src = PipeM pull
116−- pull = do mx <- liftSTM $ readTMQueue q
117−- case mx of
118−- Nothing -> return $ Done ()
119−- Just x -> return $ HaveOutput src close x
120−- close = do liftSTM $ closeTMQueue q
121−- return ()
122−+sourceTMQueue q =
123−+ loop
124−+ where
125−+ loop = do
126−+ mx <- liftSTM $ readTMQueue q
127−+ case mx of
128−+ Nothing -> return ()
129−+ Just x -> yieldOr x close >> loop
130−+ close = liftSTM $ closeTMQueue q
131−
132− -- | A simple wrapper around a "TMQueue". As data is pushed into this sink, it
133− -- will magically begin to appear in the queue.
134−@@ -124,26 +107,23 @@
135− => TMQueue a
136− -> Bool -- ^ Should the queue be closed when the sink is closed?
137− -> Sink a m ()
138−-sinkTMQueue q shouldClose = ConduitM src
139−- where src = sink
140−- sink = NeedInput push close
141−- push input = PipeM ((liftSTM $ writeTMQueue q input)
142−- >> (return $ NeedInput push close))
143−- close _ = do when shouldClose (liftSTM $ closeTMQueue q)
144−- return ()
145−+sinkTMQueue q shouldClose = do
146−+ CL.mapM_ (liftSTM . writeTMQueue q)
147−+ when shouldClose (liftSTM $ closeTMQueue q)
148−
149− -- | A simple wrapper around a "TBMQueue". As data is pushed into the queue, the
150− -- source will read it and pass it down the conduit pipeline. When the
151− -- queue is closed, the source will close also.
152− sourceTBMQueue :: MonadIO m => TBMQueue a -> Source m a
153−-sourceTBMQueue q = ConduitM src
154−- where src = PipeM pull
155−- pull = do mx <- liftSTM $ readTBMQueue q
156−- case mx of
157−- Nothing -> return $ Done ()
158−- Just x -> return $ HaveOutput src close x
159−- close = do liftSTM $ closeTBMQueue q
160−- return ()
161−+sourceTBMQueue q =
162−+ loop
163−+ where
164−+ loop = do
165−+ mx <- liftSTM $ readTBMQueue q
166−+ case mx of
167−+ Nothing -> return ()
168−+ Just x -> yieldOr x close >> loop
169−+ close = liftSTM $ closeTBMQueue q
170−
171− -- | A simple wrapper around a "TBMQueue". As data is pushed into this sink, it
172− -- will magically begin to appear in the queue.
173−@@ -151,13 +131,9 @@
174− => TBMQueue a
175− -> Bool -- ^ Should the queue be closed when the sink is closed?
176− -> Sink a m ()
177−-sinkTBMQueue q shouldClose = ConduitM src
178−- where src = sink
179−- sink = NeedInput push close
180−- push input = PipeM ((liftSTM $ writeTBMQueue q input)
181−- >> (return $ NeedInput push close))
182−- close _ = do when shouldClose (liftSTM $ closeTBMQueue q)
183−- return ()
184−+sinkTBMQueue q shouldClose = do
185−+ CL.mapM_ (liftSTM . writeTBMQueue q)
186−+ when shouldClose (liftSTM $ closeTBMQueue q)
187−
188−
189− liftSTM :: forall (m :: * -> *) a. MonadIO m => STM a -> m a
190−diff -ruN orig/stm-conduit.cabal new/stm-conduit.cabal
191−--- orig/stm-conduit.cabal 2014-08-27 18:36:44.145176333 +0300
192−+++ new/stm-conduit.cabal 2014-08-27 18:36:43.000000000 +0300
193−@@ -29,7 +29,7 @@
194− , stm-chans >= 2.0 && < 3.1
195− , cereal >= 0.4.0.1
196− , cereal-conduit >= 0.7.2
197−- , conduit >= 1.0 && < 1.2
198−+ , conduit >= 1.0 && < 1.3
199− , conduit-extra >= 1.0 && < 1.2
200− , directory >= 1.1
201− , resourcet >= 0.3 && < 1.2
patching/patches/temporary-1.2.0.1.patchdeleted−12
@@ -1,12 +0,0 @@
1−diff -ru orig/temporary.cabal new/temporary.cabal
2−--- orig/temporary.cabal 2014-04-03 08:17:21.902394760 +0300
3−+++ new/temporary.cabal 2014-04-03 08:17:21.000000000 +0300
4−@@ -23,7 +23,7 @@
5− other-modules: Distribution.Compat.Exception
6− Distribution.Compat.TempFile
7− build-depends: base >= 3 && < 6, filepath >= 1.1 && < 1.4, directory >= 1.0 && < 1.3,
8−- transformers >= 0.2.0.0 && < 0.4, exceptions >= 0.1.1 && < 0.4
9−+ transformers >= 0.2.0.0 && < 0.4, exceptions >= 0.1.1 && < 0.6
10−
11− if !os(windows)
12− build-depends: unix >= 2.3 && < 2.8
patching/patches/temporary-1.2.0.2.patchdeleted−39
@@ -1,39 +0,0 @@
1−diff -ru orig/System/IO/Temp.hs new/System/IO/Temp.hs
2−--- orig/System/IO/Temp.hs 2014-05-11 15:04:23.887266736 +0300
3−+++ new/System/IO/Temp.hs 2014-05-11 15:04:23.000000000 +0300
4−@@ -24,7 +24,7 @@
5− --
6− -- Behaves exactly the same as 'withTempFile', except that the parent temporary directory
7− -- will be that returned by 'getTemporaryDirectory'.
8−-withSystemTempFile :: (MonadIO m, MonadCatch m) =>
9−+withSystemTempFile :: (MonadIO m, MonadMask m) =>
10− String -- ^ File name template. See 'openTempFile'.
11− -> (FilePath -> Handle -> m a) -- ^ Callback that can use the file
12− -> m a
13−@@ -34,7 +34,7 @@
14− --
15− -- Behaves exactly the same as 'withTempDirectory', except that the parent temporary directory
16− -- will be that returned by 'getTemporaryDirectory'.
17−-withSystemTempDirectory :: (MonadIO m, MonadCatch m) =>
18−+withSystemTempDirectory :: (MonadIO m, MonadMask m) =>
19− String -- ^ Directory name template. See 'openTempFile'.
20− -> (FilePath -> m a) -- ^ Callback that can use the directory
21− -> m a
22−@@ -50,7 +50,7 @@
23− --
24− -- The @tmpFlie@ will be file in the given directory, e.g.
25− -- @src/sdist.342@.
26−-withTempFile :: (MonadIO m, MonadCatch m) =>
27−+withTempFile :: (MonadIO m, MonadMask m) =>
28− FilePath -- ^ Temp dir to create the file in
29− -> String -- ^ File name template. See 'openTempFile'.
30− -> (FilePath -> Handle -> m a) -- ^ Callback that can use the file
31−@@ -70,7 +70,7 @@
32− --
33− -- The @tmpDir@ will be a new subdirectory of the given directory, e.g.
34− -- @src/sdist.342@.
35−-withTempDirectory :: (MonadCatch m, MonadIO m) =>
36−+withTempDirectory :: (MonadMask m, MonadIO m) =>
37− FilePath -- ^ Temp directory to create the directory in
38− -> String -- ^ Directory name template. See 'openTempFile'.
39− -> (FilePath -> m a) -- ^ Callback that can use the directory
patching/patches/th-desugar-1.4.2.patchdeleted−20
@@ -1,20 +0,0 @@
1−diff -ruN orig/Test/Run.hs new/Test/Run.hs
2−--- orig/Test/Run.hs 2014-08-19 09:57:25.537902164 +0300
3−+++ new/Test/Run.hs 2014-08-19 09:57:25.000000000 +0300
4−@@ -27,6 +27,7 @@
5− import Language.Haskell.TH.Desugar.Expand
6− import Language.Haskell.TH.Desugar.Sweeten
7− import Language.Haskell.TH
8−+import Language.Haskell.TH.Syntax (qRunIO)
9−
10− import Control.Monad
11−
12−@@ -121,7 +122,7 @@
13− case (resK, lhs) of
14− (DStarK, [DVarT _]) -> [| True |]
15− _ -> do
16−- runIO $ do
17−+ qRunIO $ do
18− putStrLn "Failed bug8884 test:"
19− putStrLn $ show dinfo
20− [| False |] )
patching/patches/threepenny-gui-0.4.1.0.patchdeleted−47
@@ -1,47 +0,0 @@
1−diff -ru orig/src/Graphics/UI/Threepenny/Internal/Driver.hs new/src/Graphics/UI/Threepenny/Internal/Driver.hs
2−--- orig/src/Graphics/UI/Threepenny/Internal/Driver.hs 2014-03-13 10:29:00.049732639 +0200
3−+++ new/src/Graphics/UI/Threepenny/Internal/Driver.hs 2014-03-13 10:28:59.000000000 +0200
4−@@ -248,7 +248,7 @@
5− signal Session{..} = do
6− input <- getParam "signal"
7− let err = error $ "Unable to parse " ++ show input
8−- case JSON.decode . LBS.fromStrict =<< input of
9−+ case JSON.decode . LBS.fromChunks . return =<< input of
10− Just signal -> liftIO $ writeChan sSignals signal
11− Nothing -> err
12−
13−diff -ru orig/src/Graphics/UI/Threepenny/Internal/Types.hs new/src/Graphics/UI/Threepenny/Internal/Types.hs
14−--- orig/src/Graphics/UI/Threepenny/Internal/Types.hs 2014-03-13 10:29:00.049732639 +0200
15−+++ new/src/Graphics/UI/Threepenny/Internal/Types.hs 2014-03-13 10:28:59.000000000 +0200
16−@@ -17,6 +17,7 @@
17− import Data.Map (Map)
18− import Data.String (fromString)
19− import Data.Time
20−+import Data.Text.Encoding (encodeUtf8, decodeUtf8)
21−
22− import Network.URI
23− import Data.Data
24−@@ -62,9 +63,9 @@
25−
26− -- Marshalling ElementId
27− instance ToJSON ElementId where
28−- toJSON (ElementId o) = toJSON o
29−+ toJSON (ElementId o) = toJSON $ decodeUtf8 o
30− instance FromJSON ElementId where
31−- parseJSON (Object v) = ElementId <$> v .: "Element"
32−+ parseJSON (Object v) = (ElementId . encodeUtf8) <$> v .: "Element"
33− parseJSON _ = mzero
34−
35−
36−diff -ru orig/threepenny-gui.cabal new/threepenny-gui.cabal
37−--- orig/threepenny-gui.cabal 2014-03-13 10:29:00.057732639 +0200
38−+++ new/threepenny-gui.cabal 2014-03-13 10:28:59.000000000 +0200
39−@@ -92,7 +92,7 @@
40− cpp-options: -DREBUG
41− ghc-options: -O2
42− build-depends: base >= 4 && < 5
43−- ,aeson == 0.6.*
44−+ ,aeson >= 0.6
45− ,attoparsec-enumerator == 0.3.*
46− ,bytestring >= 0.9.2 && < 0.11
47− ,containers >= 0.4.2 && < 0.6
patching/patches/transformers-compat-0.3.3.4.patchdeleted−50
@@ -1,50 +0,0 @@
1−Only in orig: 0.2
2−diff -ru orig/transformers-compat.cabal new/transformers-compat.cabal
3−--- orig/transformers-compat.cabal 2014-06-20 06:30:48.534077053 +0300
4−+++ new/transformers-compat.cabal 2014-06-20 06:30:48.000000000 +0300
5−@@ -38,17 +38,6 @@
6− type: git
7− location: git://github.com/ekmett/transformers-compat.git
8−
9−-flag two
10−- default: False
11−- description: Use transformers 0.2. This must be selected manually and should
12−- probably only be used on older GHCs around 7.0.x.
13−- manual: True
14−-
15−-flag three
16−- default: False
17−- manual: True
18−- description: Use transformers 0.3. This should toggle on/off automatically.
19−-
20− library
21− build-depends:
22− base >= 4.3 && < 5
23−@@ -56,24 +45,10 @@
24− other-modules:
25− Paths_transformers_compat
26−
27−- if flag(three)
28−- hs-source-dirs: 0.3
29−- build-depends: transformers >= 0.3 && < 0.4
30−- else
31−- if flag(two)
32−- hs-source-dirs: 0.2 0.3
33−- build-depends: transformers >= 0.2 && < 0.3
34−- else
35−- build-depends: transformers >= 0.4.1 && < 0.5
36−-
37−- if flag(two)
38−- exposed-modules:
39−- Control.Applicative.Backwards
40−- Control.Applicative.Lift
41−- Data.Functor.Reverse
42−+ hs-source-dirs: 0.3
43−+ build-depends: transformers >= 0.3 && < 0.4
44−
45−- if flag(two) || flag(three)
46−- exposed-modules:
47−+ exposed-modules:
48− Control.Monad.Trans.Except
49− Control.Monad.Signatures
50− Data.Functor.Classes
patching/patches/uniqueid-0.1.1.patchdeleted−100
@@ -1,100 +0,0 @@
1−diff -ru orig/Data/Unique/Id.hs new/Data/Unique/Id.hs
2−--- orig/Data/Unique/Id.hs 2014-04-14 09:11:35.637516354 +0300
3−+++ new/Data/Unique/Id.hs 2014-04-14 09:11:35.000000000 +0300
4−@@ -1,3 +1,4 @@
5−+{-# LANGUAGE CPP #-}
6− {-# LANGUAGE MagicHash #-}
7−
8− -- | This module provides splittable supplies for unique identifiers.
9−@@ -13,6 +14,86 @@
10−
11− ) where
12−
13−+#if MIN_VERSION_base(4,7,0)
14−+
15−+import GHC.Exts
16−+import GHC.IO ( unsafeDupableInterleaveIO )
17−+
18−+import Data.IORef
19−+import System.IO.Unsafe ( unsafePerformIO )
20−+
21−+-- | Unique identifiers are of type 'Id' and can be hashed to an 'Int'
22−+-- usning the function 'hashedId'.
23−+newtype Id = Id { hashedId :: Int }
24−+
25−+-- | Supplies for unique identifiers are of type 'IdSupply' and can be
26−+-- split into two new supplies or yield a unique identifier.
27−+data IdSupply = IdSupply Int# IdSupply IdSupply
28−+
29−+-- | Generates a new supply of unique identifiers. The given character
30−+-- is prepended to generated numbers.
31−+initIdSupply :: Char -> IO IdSupply
32−+initIdSupply (C# c) =
33−+ case uncheckedIShiftL# (ord# c) (unboxedInt 24) of
34−+ mask ->
35−+ let mkSupply =
36−+ unsafeDupableInterleaveIO (
37−+ nextInt >>= \ (I# u) ->
38−+ mkSupply >>= \ l ->
39−+ mkSupply >>= \ r ->
40−+ return (IdSupply (word2Int# (or# (int2Word# mask) (int2Word# u))) l r))
41−+ in mkSupply
42−+
43−+-- | Splits a supply of unique identifiers to yield two of them.
44−+splitIdSupply :: IdSupply -> (IdSupply,IdSupply)
45−+splitIdSupply (IdSupply _ l r) = (l,r)
46−+
47−+-- | Splits a supply of unique identifiers to yield an infinite list of them.
48−+splitIdSupplyL :: IdSupply -> [IdSupply]
49−+splitIdSupplyL ids = ids1 : splitIdSupplyL ids2
50−+ where
51−+ (ids1, ids2) = splitIdSupply ids
52−+
53−+-- | Yields the unique identifier from a supply.
54−+idFromSupply :: IdSupply -> Id
55−+idFromSupply (IdSupply n _ _) = Id (I# n)
56−+
57−+instance Eq Id where Id (I# x) == Id (I# y) = I# (x ==# y) /= 0
58−+
59−+instance Ord Id
60−+ where
61−+ Id (I# x) < Id (I# y) = I# (x <# y) /= 0
62−+ Id (I# x) <= Id (I# y) = I# (x <=# y) /= 0
63−+
64−+ compare (Id (I# x)) (Id (I# y)) =
65−+ if I# (x ==# y) /= 0 then EQ else if I# (x <# y) /= 0 then LT else GT
66−+
67−+instance Show Id
68−+ where
69−+ showsPrec _ i s = case unpackId i of (c,n) -> c:show n++s
70−+
71−+
72−+
73−+
74−+unboxedInt :: Int -> Int#
75−+unboxedInt (I# x) = x
76−+
77−+global :: IORef Int
78−+global = unsafePerformIO (newIORef 0)
79−+
80−+nextInt :: IO Int
81−+nextInt = do
82−+ n <- readIORef global
83−+ writeIORef global (succ n)
84−+ return n
85−+
86−+unpackId :: Id -> (Char,Int)
87−+unpackId (Id (I# i)) =
88−+ let tag = C# (chr# (uncheckedIShiftRL# i (unboxedInt 24)))
89−+ num = I# (word2Int# (and# (int2Word# i)
90−+ (int2Word# (unboxedInt 16777215))))
91−+ in (tag, num)
92−+#else
93− import GHC.Exts
94− import GHC.IOBase ( unsafeDupableInterleaveIO )
95−
96−@@ -90,3 +171,4 @@
97− num = I# (word2Int# (and# (int2Word# i)
98− (int2Word# (unboxedInt 16777215))))
99− in (tag, num)
100−+#endif
patching/patches/websockets-0.8.2.0.patchdeleted−21
@@ -1,21 +0,0 @@
1−diff -ru orig/websockets.cabal new/websockets.cabal
2−--- orig/websockets.cabal 2014-04-03 08:32:53.818374925 +0300
3−+++ new/websockets.cabal 2014-04-03 08:32:53.000000000 +0300
4−@@ -69,7 +69,7 @@
5− binary >= 0.5 && < 0.8,
6− blaze-builder >= 0.3 && < 0.4,
7− bytestring >= 0.9 && < 0.11,
8−- case-insensitive >= 0.3 && < 1.2,
9−+ case-insensitive >= 0.3 && < 1.3,
10− containers >= 0.3 && < 0.6,
11− io-streams >= 1.1 && < 1.2,
12− mtl >= 2.0 && < 2.2,
13−@@ -105,7 +105,7 @@
14− binary >= 0.5 && < 0.8,
15− blaze-builder >= 0.3 && < 0.4,
16− bytestring >= 0.9 && < 0.11,
17−- case-insensitive >= 0.3 && < 1.2,
18−+ case-insensitive >= 0.3 && < 1.3,
19− containers >= 0.3 && < 0.6,
20− io-streams >= 1.1 && < 1.2,
21− mtl >= 2.0 && < 2.2,
patching/patches/yesod-auth-fb-1.6.1.patchdeleted−77
@@ -1,77 +0,0 @@
1−diff -ru orig/demo/clientside.hs new/demo/clientside.hs
2−--- orig/demo/clientside.hs 2014-03-30 12:27:40.941431437 +0300
3−+++ new/demo/clientside.hs 2014-03-30 12:27:40.000000000 +0300
4−@@ -27,7 +27,7 @@
5−
6−
7− instance Yesod Test where
8−- approot = ApprootStatic "http://dev.whonodes.org:3000"
9−+ approot = FIXME -- FIXME: Put your approot here
10−
11− instance RenderMessage Test FormMessage where
12− renderMessage _ _ = englishFormMessage
13−diff -ru orig/src/Yesod/Auth/Facebook/ClientSide.hs new/src/Yesod/Auth/Facebook/ClientSide.hs
14−--- orig/src/Yesod/Auth/Facebook/ClientSide.hs 2014-03-30 12:27:40.941431437 +0300
15−+++ new/src/Yesod/Auth/Facebook/ClientSide.hs 2014-03-30 12:27:40.000000000 +0300
16−@@ -364,7 +364,7 @@
17− AuthPlugin "fbcs" dispatch login
18− where
19− dispatch :: YesodAuthFbClientSide site =>
20−- Text -> [Text] -> HandlerT Auth (HandlerT site IO) ()
21−+ Text -> [Text] -> HandlerT Auth (HandlerT site IO) TypedContent
22− -- Login route used when successfully logging in. Called via
23− -- AJAX by JavaScript code on 'facebookJSSDK'.
24− dispatch "GET" ["login"] = do
25−@@ -372,7 +372,7 @@
26− when (redirectToReferer y) (lift setUltDestReferer)
27− etoken <- lift getUserAccessTokenFromFbCookie
28− case etoken of
29−- Right token -> lift $ setCreds True (createCreds token)
30−+ Right token -> lift $ setCredsRedirect (createCreds token)
31− Left msg -> fail msg
32−
33− -- Login routes used to forcefully require the user to login.
34−@@ -406,7 +406,7 @@
35− token <- lift $
36− YF.runYesodFbT $
37− FB.getUserAccessTokenStep2 proceedUrl query'
38−- lift $ setCreds True (createCreds token)
39−+ lift $ setCredsRedirect (createCreds token)
40−
41− -- Everything else gives 404
42− dispatch _ _ = notFound
43−diff -ru orig/src/Yesod/Auth/Facebook/ServerSide.hs new/src/Yesod/Auth/Facebook/ServerSide.hs
44−--- orig/src/Yesod/Auth/Facebook/ServerSide.hs 2014-03-30 12:27:40.941431437 +0300
45−+++ new/src/Yesod/Auth/Facebook/ServerSide.hs 2014-03-30 12:27:40.000000000 +0300
46−@@ -56,7 +56,7 @@
47− proceedR = PluginR "fb" ["proceed"]
48−
49− dispatch :: (YesodAuth site, YF.YesodFacebook site) =>
50−- Text -> [Text] -> HandlerT Auth (HandlerT site IO) ()
51−+ Text -> [Text] -> HandlerT Auth (HandlerT site IO) TypedContent
52− -- Redirect the user to Facebook.
53− dispatch "GET" ["login"] = do
54− ur <- getUrlRender
55−@@ -73,7 +73,7 @@
56− lift $ do
57− token <- YF.runYesodFbT $ FB.getUserAccessTokenStep2 proceedUrl query'
58− setUserAccessToken token
59−- setCreds True (createCreds token)
60−+ setCredsRedirect (createCreds token)
61− -- Logout the user from our site and from Facebook.
62− dispatch "GET" ["logout"] = do
63− y <- lift getYesod
64−diff -ru orig/yesod-auth-fb.cabal new/yesod-auth-fb.cabal
65−--- orig/yesod-auth-fb.cabal 2014-03-30 12:27:40.945431436 +0300
66−+++ new/yesod-auth-fb.cabal 2014-03-30 12:27:40.000000000 +0300
67−@@ -43,8 +43,9 @@
68− Build-depends: base >= 4.3 && < 5
69− , lifted-base >= 0.1 && < 0.3
70− , yesod-core == 1.2.*
71−- , yesod-auth == 1.2.*
72−+ , yesod-auth == 1.3.*
73− , hamlet
74−+ , shakespeare
75− , shakespeare-js >= 1.0.2
76− , wai
77− , http-conduit >= 1.9
patching/patches/yesod-auth-oauth-1.2.0.patchdeleted−26
@@ -1,26 +0,0 @@
1−diff -ru orig/Yesod/Auth/OAuth.hs new/Yesod/Auth/OAuth.hs
2−--- orig/Yesod/Auth/OAuth.hs 2014-03-30 12:34:43.941422434 +0300
3−+++ new/Yesod/Auth/OAuth.hs 2014-03-30 12:34:43.000000000 +0300
4−@@ -72,7 +72,7 @@
5− master <- getYesod
6− accTok <- getAccessToken oauth reqTok (authHttpManager master)
7− creds <- liftIO $ mkCreds accTok
8−- setCreds True creds
9−+ setCredsRedirect creds
10− dispatch _ _ = notFound
11− login tm = do
12− render <- getUrlRender
13−diff -ru orig/yesod-auth-oauth.cabal new/yesod-auth-oauth.cabal
14−--- orig/yesod-auth-oauth.cabal 2014-03-30 12:34:43.941422434 +0300
15−+++ new/yesod-auth-oauth.cabal 2014-03-30 12:34:43.000000000 +0300
16−@@ -23,8 +23,8 @@
17− build-depends: authenticate-oauth >= 1.4 && < 1.5
18− , bytestring >= 0.9.1.4
19− , yesod-core >= 1.2 && < 1.3
20−- , yesod-auth >= 1.2 && < 1.3
21−- , text >= 0.7 && < 0.12
22−+ , yesod-auth >= 1.3 && < 1.4
23−+ , text >= 0.7 && < 1.2
24− , yesod-form >= 1.3 && < 1.4
25− , transformers >= 0.2.2 && < 0.4
26− , lifted-base >= 0.2 && < 0.3