packages feed

casr-logbook-html (empty) → 0.0.1

raw patch · 6 files changed

+876/−0 lines, 6 filesdep +QuickCheckdep +basedep +casr-logbookbuild-type:Customsetup-changed

Dependencies added: QuickCheck, base, casr-logbook, digit, directory, doctest, filepath, lens, lucid, template-haskell, text, time

Files

+ LICENSE view
@@ -0,0 +1,27 @@+Copyright 2016 Tony Morris+All rights reserved.++Redistribution and use in source and binary forms, with or without modification,+are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+list of conditions, the following disclaimer and the following SHA-512 checksum.++2. Redistributions in binary form must reproduce the above copyright notice,+this list of conditions, the following disclaimer and the following SHA-512+checksum in the documentation and/or other materials provided with the+distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++THIS SOFTWARE IS PROVIDED WITH A SHA-512 CHECKSUM.+ecdfdf543fd166b13b76b11e0b010e00d693028771880ffd8f9252ae0b8ac42bddf8eb7a23c21c86a3b50039d642ad9eeb7e8a0e82f6a345f60feb4a54808362
+ Setup.lhs view
@@ -0,0 +1,44 @@+#!/usr/bin/env runhaskell+\begin{code}+{-# OPTIONS_GHC -Wall #-}+module Main (main) where++import Data.List ( nub )+import Data.Version ( showVersion )+import Distribution.Package ( PackageName(PackageName), PackageId, InstalledPackageId, packageVersion, packageName )+import Distribution.PackageDescription ( PackageDescription(), TestSuite(..) )+import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )+import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )+import Distribution.Simple.BuildPaths ( autogenModulesDir )+import Distribution.Simple.Setup ( BuildFlags(buildVerbosity), fromFlag )+import Distribution.Simple.LocalBuildInfo ( withLibLBI, withTestLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps) )+import Distribution.Verbosity ( Verbosity )+import System.FilePath ( (</>) )++main :: IO ()+main = defaultMainWithHooks simpleUserHooks+  { buildHook = \pkg lbi hooks flags -> do+     generateBuildModule (fromFlag (buildVerbosity flags)) pkg lbi+     buildHook simpleUserHooks pkg lbi hooks flags+  }++generateBuildModule :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO ()+generateBuildModule verbosity pkg lbi = do+  let dir = autogenModulesDir lbi+  createDirectoryIfMissingVerbose verbosity True dir+  withLibLBI pkg lbi $ \_ libcfg -> do+    withTestLBI pkg lbi $ \suite suitecfg -> do+      rewriteFile (dir </> "Build_" ++ testName suite ++ ".hs") $ unlines+        [ "module Build_" ++ testName suite ++ " where"+        , "deps :: [String]"+        , "deps = " ++ (show $ formatdeps (testDeps libcfg suitecfg))+        ]+  where+    formatdeps = map (formatone . snd)+    formatone p = case packageName p of+      PackageName n -> n ++ "-" ++ showVersion (packageVersion p)++testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]+testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys++\end{code}
+ casr-logbook-html.cabal view
@@ -0,0 +1,78 @@+name:               casr-logbook-html+version:            0.0.1+license:            OtherLicense+license-file:       LICENSE+author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>+maintainer:         Tony Morris+copyright:          Copyright (C) 2016 Tony Morris+synopsis:           CASR 61.345 Pilot Personal Logbook HTML output+category:           Aviation+description:        +  <<https://i.imgur.com/p6LT40r.png>>+  .+  CASR 61.345 Pilot Personal Logbook HTML output+  .+  <<https://i.imgur.com/Lfhcmtg.png>>++homepage:           https://github.com/tonymorris/casr-logbook-html+bug-reports:        https://github.com/tonymorris/casr-logbook-html/issues+cabal-version:      >= 1.10+build-type:         Custom+extra-source-files: changelog++source-repository   head+  type:             git+  location:         git@github.com:tonymorris/casr-logbook-html.git++flag                small_base+  description:      Choose the new, split-up base package.++library+  default-language:+                    Haskell2010++  build-depends:+                    base < 5 && >= 4.8+                    , casr-logbook >= 0.1.3 && < 0.2+                    , lucid >= 2.9 && < 3+                    , lens >= 4.1 && < 5+                    , digit >= 0.2.8 && < 3+                    , time >= 1.5 && < 1.6+                    , text >= 1.2 && < 1.3++  ghc-options:+                    -Wall++  default-extensions:+                    NoImplicitPrelude++  hs-source-dirs:+                    src++  exposed-modules:+                    Data.Aviation.Casr.Logbook.Html.Html++test-suite doctests+  type:+                    exitcode-stdio-1.0++  main-is:+                    doctests.hs++  default-language:+                    Haskell2010++  build-depends:+                    base < 5 && >= 3+                    , doctest >= 0.9.7+                    , filepath >= 1.3+                    , directory >= 1.1+                    , QuickCheck >= 2.0+                    , template-haskell >= 2.8++  ghc-options:+                    -Wall+                    -threaded++  hs-source-dirs:+                    test
+ changelog view
@@ -0,0 +1,4 @@+0.0.1++* Initial release+
+ src/Data/Aviation/Casr/Logbook/Html/Html.hs view
@@ -0,0 +1,691 @@+{-# LANGUAGE OverloadedStrings #-}++module Data.Aviation.Casr.Logbook.Html.Html(+  htmlTimeAmount+, strTimeAmount+, strEngine+, htmlAircraft+, htmlRatingDay+, htmlRating+, htmlRatingShort+, htmlRatings+, htmlRatingsShort+, htmlAviatorName+, htmlAviatorARN+, htmlAviatorDob+, htmlAviatorRatings+, htmlAviator+, htmlAviatorShort+, htmlFlightPoint+, htmlFlightPath+, htmlCommand+, htmlTimeAmountZero+, htmlTimeAmountZeroWith +, htmlAviators+, htmlAircraftFlightName+, htmlAircraftFlight+, htmlTimeOfDayTime+, htmlTime+, htmlFlightPathTime+, htmlSimulatorFlightName+, htmlSimulatorFlight+, htmlLocation+, htmlExamResult+, htmlExamName+, htmlExam+, htmlBriefingName+, htmlBriefing+, space2dot+, htmlEntryTag+, htmlEntry +, htmlEntries +, htmlLogbook+, htmlTitleAviator+, htmlLogbookDocument+, htmlLogbookHeader+) where++import Control.Applicative((*>))+import Control.Category((.), id)+import Control.Lens((^.))+import Control.Monad(when, (=<<), (>>=))+import Data.Aviation.Casr.Logbook(+    arn+  , firstname+  , surname+  , logbookaviator+  , daytime+  , briefingTime+  , briefingName+  , examName+  , examTime+  , simulatorflightname+  , simulatortype+  , point+  , flightStart+  , flightEnd+  , flightpath+  , aircraftRegistration+  , aircraftflightname+  , flightaircraft+  , landingTime+  , zerotimeamount+  , flightPathList+  , Command(ICUS, Dual, InCommand)+  , Rating(Rating)+  , Aircraft(Aircraft)+  , Engine(Single, Multi)+  , FlightPath+  , FlightPoint(FlightPoint)+  , Time(Time)+  , TimeAmount(TimeAmount)+  , DayNight(DayNight)+  , Briefing(Briefing)+  , Exam(Exam)+  , Location(Location)+  , Aviator(Aviator)+  , Entries(Entries)+  , Logbook(Logbook)+  , AircraftFlight(AircraftFlight)+  , SimulatorFlight(SimulatorFlight)+  , Briefing+  , Exam+  , Entry(BriefingEntry, ExamEntry, SimulatorFlightEntry, AircraftFlightEntry)+  )+import Data.Bool(not)+import Data.Char(toUpper)+import Data.Digit(Digit)+import Data.Eq((==))+import Data.Foldable(fold, sequence_, mapM_, null)+import Data.Function(($))+import Data.Functor((<$>))+import Data.Int(Int)+import Data.List(intersperse, concat)+import Data.Maybe(Maybe, maybe)+import Data.Monoid(Monoid, (<>), mempty)+import Data.String(String, fromString)+import Data.Time(Day, TimeOfDay)+import Data.Text(Text)+import qualified Data.Text as Text(pack)+import Lucid(+    id_+  , class_+  , h1_+  , h2_+  , h3_+  , span_+  , a_+  , div_+  , href_+  , src_+  , type_+  , script_+  , body_+  , title_+  , rel_+  , link_+  , title_+  , html_+  , doctype_+  , head_+  , lang_+  , hr_+  , ul_+  , li_+  , Html+  , toHtmlRaw+  )+import Text.Printf(printf)++import Prelude(show, fromIntegral, (/), (*), Double)++htmlTimeAmount ::+  TimeAmount+  -> Html ()+htmlTimeAmount t =+  span_ [] $+    do  fromString (strTimeAmount t)+        "hrs"++strTimeAmount ::+  TimeAmount+  -> String+strTimeAmount (TimeAmount h x) =+  show h <> "." <> show x++strEngine ::+  Engine+  -> String+strEngine Single =+  "single-engine"+strEngine Multi =+  "multi-engine"++htmlAircraft ::+  AircraftFlight+  -> Aircraft+  -> Html ()+htmlAircraft _ (Aircraft t r e) =+  span_ [class_ "aircraft"] $+    do  span_ [class_ "aircrafttype"] (fromString t)+        " "+        span_ [class_ "aircraftregistration"] (fromString r)+        " "+        span_ [class_ "aircraftengine"] (fromString (strEngine e))++htmlRatingDay ::+  Maybe Day+  -> Html ()+htmlRatingDay =+  maybe mempty (\q -> +    do  " "+        span_ [] $+          fromString (show q))++htmlRating ::+  Rating+  -> Html ()+htmlRating (Rating n d) =+  span_ [] $+    do  span_ [] (fromString n)+        htmlRatingDay d++htmlRatingShort ::+  Rating+  -> Html ()+htmlRatingShort (Rating n _) =+  span_ [] (fromString n)++htmlRatings ::+  [Rating]+  -> Html ()+htmlRatings =+  sequence_ . intersperse ", " . (htmlRating <$>)++htmlRatingsShort ::+  [Rating]+  -> Html ()+htmlRatingsShort =+  sequence_ . intersperse ", " . (htmlRatingShort <$>)++htmlAviatorName ::+  String+  -> String+  -> Html ()+htmlAviatorName s f =+  do  li_ [id_ "aviatorname"] $+        do  span_ [class_ "key"] "Name: "+            span_ [class_ "value"] $+              do  fromString (toUpper <$> s)+                  ", "+                  fromString f++htmlAviatorARN ::+  [Digit]+  -> Html ()+htmlAviatorARN a =+  when (not . null $ a) $+    do  li_ [id_ "aviatorarn"] $ +          do  span_ [class_ "key"] "ARN: "+              span_ [class_ "value"] $+                fromString (a >>= show)++htmlAviatorDob ::+  Maybe Day+  -> Html ()+htmlAviatorDob =+  maybe mempty (\q ->+    do  li_ [id_ "aviatordob"] $+          do  span_ [class_ "key"] "Date of Birth: "+              span_ [class_ "value"] .+                fromString . show $ q)++htmlAviatorRatings ::+  [Rating]+  -> Html ()+htmlAviatorRatings r =+  when (not . null $ r) $+    do  li_ [id_ "aviatorratings"] $ +          do  span_ [class_ "key"] "Ratings: "+              span_ [class_ "value"] .+                htmlRatings $ r++htmlAviator ::+  Aviator+  -> Html ()+htmlAviator (Aviator s f a d r) =+  div_ [id_ "aviator", class_ "aviator"] .+    ul_ [] $+      do  htmlAviatorName s f+          htmlAviatorARN a+          htmlAviatorDob d+          htmlAviatorRatings r+            +htmlAviatorShort ::+  Aviator+  -> Html ()    +htmlAviatorShort (Aviator s f a _ r) =+  do  fromString f+      " "+      fromString s+      when (not . null $ a) $ " "+      fromString (a >>= show)+      when (not . null $ r) $ " "+      htmlRatingsShort r++htmlFlightPoint ::+  AircraftFlight+  -> FlightPoint+  -> Html ()+htmlFlightPoint _ (FlightPoint p _ _) =+  span_ [class_ "flightpoint"] $+    fromString p++htmlFlightPath ::+  AircraftFlight+  -> FlightPath+  -> Html ()+htmlFlightPath fl p =+  span_ [class_ "flightpath"] $+    fold (intersperse (toHtmlRaw (" &mdash; " :: Text)) (htmlFlightPoint fl <$> flightPathList p))+    +htmlCommand ::+  AircraftFlight+  -> Command+  -> Html ()+htmlCommand _ InCommand =+  span_ [class_ "command incommand"] "In-Command"+htmlCommand _ (ICUS a) =+  do  span_ [class_ "command incommandunderinstruction"] "In-Command Under-Instruction"+      span_ [class_ "commandphrase"] $ " by "+      span_ [class_ "commandaviator"] $ htmlAviatorShort a+htmlCommand _ (Dual a) =+  do  span_ [class_ "command dualunderinstruction"] "Dual Under-Instruction"+      span_ [class_ "commandphrase"] $ " by "+      span_ [class_ "commandaviator"] $ htmlAviatorShort a++htmlTimeAmountZero ::+  TimeAmount+  -> Html ()+htmlTimeAmountZero =+  htmlTimeAmountZeroWith id++htmlTimeAmountZeroWith :: +  Monoid a =>+  (Html () -> a)+  -> TimeAmount+  -> a+htmlTimeAmountZeroWith f z =+  if z == zerotimeamount+    then+      mempty+    else+      f (htmlTimeAmount z)++htmlAviators ::+  [Aviator]+  -> Html ()+htmlAviators =+  ul_ [] .+    mapM_ (li_ [] . htmlAviatorShort)++htmlAircraftFlightName ::+  String+  -> Html ()+htmlAircraftFlightName n =+  h3_ [class_ "aircraftflightname"] $+          fromString n++htmlAircraftFlight ::+  AircraftFlight+  -> Html ()+htmlAircraftFlight fl@(AircraftFlight n a c (DayNight d m) p o i) =+  div_ [class_ "aircraftflight"] $+    do  htmlAircraftFlightName n+        ul_ [] $+          do  li_ [] $+                do  span_ [class_ "key"] "Time: "+                    span_ [class_ "value"] .+                     htmlFlightPathTime $ p+              li_ [] $+                do  span_ [class_ "key"] "Aircraft: "+                    span_ [class_ "value"] .+                     htmlAircraft fl $ a+              li_ [] $+                do  span_ [class_ "key"] "Command: "+                    span_ [class_ "value"] .+                     htmlCommand fl $ c+              htmlTimeAmountZeroWith (\t ->+                li_ [] $+                do  span_ [class_ "key"] "Amount (day): "+                    span_ [class_ "value"] t) d+              htmlTimeAmountZeroWith (\t ->+                li_ [] $+                do  span_ [class_ "key"] "Amount (night): "+                    span_ [class_ "value"] t) m+              htmlTimeAmountZeroWith (\t ->+                li_ [] $+                do  span_ [class_ "key"] "Amount (instrument): "+                    span_ [class_ "value"] t) i+              li_ [] $+                do  span_ [class_ "key"] "Flight Path: "+                    span_ [class_ "value"] .+                      htmlFlightPath fl $ p+              when (not . null $ o) . li_ [] $+                do  span_ [class_ "key"] "Other Crew: "+                    span_ [class_ "value"] .+                      htmlAviators $ o++htmlTimeOfDayTime ::+  Maybe TimeOfDay+  -> Html ()+htmlTimeOfDayTime =+  maybe mempty (\e -> do  " "+                          fromString (show e))++htmlTime ::+  Time+  -> Html ()+htmlTime (Time t d) =+  span_ [class_ "time"] $ +    do  fromString (show t)+        htmlTimeOfDayTime d++htmlFlightPathTime ::+  FlightPath+  -> Html()+htmlFlightPathTime p =+  let s = p ^. flightStart . landingTime+      e = p ^. flightEnd . landingTime+  in  if s == e+        then+          htmlTime s+        else+          do  htmlTime s+              toHtmlRaw (" &mdash; " :: Text)+              htmlTime e++htmlSimulatorFlightName ::+  String+  -> Html ()+htmlSimulatorFlightName n =+  h3_ [class_ "simulatorflightname"] $+          fromString n++htmlSimulatorFlight ::+  SimulatorFlight+  -> Html ()+htmlSimulatorFlight (SimulatorFlight n t y o a i) =+  div_ [class_ "simulatorflight"] $+    do  htmlSimulatorFlightName n+        ul_ [] $+          do  li_ [] $+                do  span_ [class_ "key"] "Time: "+                    span_ [class_ "value"] .+                     htmlTime $ t+              li_ [] $+                do  span_ [class_ "key"] "Type: "+                    span_ [class_ "value"] (fromString y)+              when (not . null $ o) . li_ [] $+                do  span_ [class_ "key"] "Other Crew: "+                    div_ [class_ "value"] .+                      htmlAviators $ o+              li_ [] $+                do  span_ [class_ "key"] "Amount: "+                    span_ [class_ "value"] .+                     htmlTimeAmount $ a+              li_ [] $+                do  span_ [class_ "key"] "Instrument: "+                    span_ [class_ "value"] .+                     htmlTimeAmount $ i+  +htmlLocation ::+  Location+  -> Html ()+htmlLocation (Location n t o) =  +  span_ [class_ "location"] $ +    do  fromString n+        " "+        let t' = fromString (show t)+            o' = fromString (show o)+        span_ [class_ "locationopenstreetmap"] $+          a_ [href_ ("http://www.openstreetmap.org/?mlat=" <> t' <> "&mlon=" <> o' <> "#map=16/" <> t' <> "/" <> o')] +          "osm"+        " "+        span_ [class_ "locationgooglemaps"] $+          a_ [href_ ("https://www.google.com/maps/?q=" <> t' <> "," <> o')]+          "gmap"+        +htmlExamResult ::+  Int+  -> Int+  -> Html ()+htmlExamResult x y =+  do  fromString (show x)+      "/"+      fromString (show y)++htmlExamName ::+  String+  -> Html ()+htmlExamName n =+  h3_ [class_ "examname"] $ +    fromString n++htmlExam ::+  Exam+  -> Html ()+htmlExam (Exam n l t a r m) =+  let r' = do  span_ [class_ "examresult"] . fromString . show $ r+               span_ [class_ "examresultoutof"] "/"+               span_ [class_ "examresultmaximum"] . fromString . show $ m+               " ("+               span_ [class_ "examresultpercentage"] . fromString . printf "%.2f" $ (100 * fromIntegral r / fromIntegral m :: Double)+               span_ [class_ "examresultpercentsign"] "%"+               ")"+  in  div_ [class_ "exam"] $+        do  htmlExamName n+            ul_ [] $+              do  li_ [] $+                    do  span_ [class_ "key"] "Time: "+                        span_ [class_ "value"] .+                          htmlTime $ t+                  li_ [] $+                    do  span_ [class_ "key"] "Location: "+                        span_ [class_ "value"] .+                          htmlLocation $ l+                  li_ [] $+                    do  span_ [class_ "key"] "Delegate: "+                        span_ [class_ "value"] .+                          htmlAviatorShort $ a+                  li_ [] $+                    do  span_ [class_ "key"] "Result: "+                        span_ [class_ "value"] r'++htmlBriefingName ::+  String+  -> Html ()+htmlBriefingName n =+  h3_ [class_ "briefingname"] $ +    fromString n++htmlBriefing ::+  Briefing+  -> Html ()+htmlBriefing (Briefing n l t a m) =+  div_ [class_ "briefing"] $+    do  htmlBriefingName n+        ul_ [] $+          do  li_ [] $+                do  span_ [class_ "key"] "Time: "+                    span_ [class_ "value"] .+                      htmlTime $ t+              li_ [] $+                do  span_ [class_ "key"] "Location: "+                    span_ [class_ "value"] .+                      htmlLocation $ l+              li_ [] $+                do  span_ [class_ "key"] "Amount: "+                    span_ [class_ "value"] .+                      htmlTimeAmountZero $ m+              li_ [] $+                do  span_ [class_ "key"] "Briefer: "+                    span_ [class_ "value"] .+                      htmlAviatorShort $ a++space2dot ::+  String+  -> String+space2dot =+  (<$>) $ \c -> case c of +                ' ' -> '.'+                _   -> c++htmlEntryTag ::+  Entry a b c d+  -> Html ()+htmlEntryTag (AircraftFlightEntry e _) =+  let lk = space2dot . concat $+                          [+                            "FLT_"+                          , e ^. aircraftflightname+                          , "_"+                          , e ^. flightaircraft . aircraftRegistration+                          , "_"+                          , e ^. flightpath . flightStart . point+                          , "-"+                          , e ^. flightpath . flightEnd . point+                          ]+  in  do  a_ [id_ (Text.pack ('#' : lk))] ""+          a_ [href_ (Text.pack ('#' : lk))] . span_ [class_ "entrytag"] $ "FLT"++htmlEntryTag (SimulatorFlightEntry e _) =+  let lk = space2dot . concat $+                          [+                            "SIM_"+                          , e ^. simulatorflightname+                          , "_"+                          , e ^. simulatortype+                          ]+  in  do  a_ [id_ (Text.pack ('#' : lk))] ""+          a_ [href_ (Text.pack ('#' : lk))] . span_ [class_ "entrytag"] $ "SIM"+htmlEntryTag (ExamEntry e _) =+  let lk = space2dot . concat $+                          [+                            "EXM_"+                          , e ^. examName+                          , "_"+                          , show (e ^. examTime . daytime)+                          ]+  in  do  a_ [id_ (Text.pack ('#' : lk))] ""+          a_ [href_ (Text.pack ('#' : lk))] . span_ [class_ "entrytag"] $ "EXM"+htmlEntryTag (BriefingEntry e _) =+  let lk = space2dot . concat $+                          [+                            "BRF_"+                          , e ^. briefingName+                          , "_"+                          , show (e ^. briefingTime . daytime)+                          ]+  in  do  a_ [id_ (Text.pack ('#' : lk))] ""+          a_ [href_ (Text.pack ('#' : lk))] . span_ [class_ "entrytag"] $ "BRF"        ++htmlEntry :: +  (AircraftFlight -> a -> Html x)+  -> (SimulatorFlight -> b -> Html x)+  -> (Exam -> c -> Html x)+  -> (Briefing -> d -> Html x)+  -> Entry a b c d+  -> Html x+htmlEntry aircraftFlightMeta' simulatorFlightMeta' examMeta' briefingMeta' x =+  do  htmlEntryTag x+      case x of+        AircraftFlightEntry e ae ->+          do  div_ [] $+                do  htmlAircraftFlight e+                    aircraftFlightMeta' e ae+        SimulatorFlightEntry e ae ->+          do  div_ [] $+                do  htmlSimulatorFlight e+                    simulatorFlightMeta' e ae+        ExamEntry e ae ->+          do  div_ [] $+                do  htmlExam e+                    examMeta' e ae+        BriefingEntry e ae ->+          do  div_ [] $+                do  htmlBriefing e+                    briefingMeta' e ae+  +htmlEntries :: +  (AircraftFlight -> a -> Html x)+  -> (SimulatorFlight -> b -> Html x)+  -> (Exam -> c -> Html x)+  -> (Briefing -> d -> Html x)+  -> Entries a b c d+  -> Html ()+htmlEntries aircraftFlightMeta' simulatorFlightMeta' examMeta' briefingMeta' (Entries es) =+  mapM_ (\e -> hr_ [] *> htmlEntry aircraftFlightMeta' simulatorFlightMeta' examMeta' briefingMeta' e) es++htmlLogbook ::+  (AircraftFlight -> a -> Html x)+  -> (SimulatorFlight -> b -> Html x)+  -> (Exam -> c -> Html x)+  -> (Briefing -> d -> Html x)+  -> Html ()+  -> Logbook a b c d+  -> Html ()+htmlLogbook aircraftFlightMeta' simulatorFlightMeta' examMeta' briefingMeta' reports' (Logbook a es) =+  do  htmlAviator a+      hr_ []+      reports'+      htmlEntries aircraftFlightMeta' simulatorFlightMeta' examMeta' briefingMeta' es++htmlTitleAviator ::+  Aviator+  -> Html ()+htmlTitleAviator a =+  fromString (concat+                [+                  a ^. firstname+                , " "+                , a ^. surname+                , " ("+                , show =<< (a ^. arn)+                , ")"+                ])++htmlLogbookDocument ::+  (AircraftFlight -> a -> Html x)+  -> (SimulatorFlight -> b -> Html x)+  -> (Exam -> c -> Html x)+  -> (Briefing -> d -> Html x)+  -> Html ()+  -> Logbook a b c d+  -> Html ()+htmlLogbookDocument aircraftFlightMeta' simulatorFlightMeta' examMeta' briefingMeta' reports' b =+  do  doctype_+      html_ [lang_ "en"] $+        do  head_ $ +              do  title_ ("Pilot Personal Logbook " <> toHtmlRaw (" &mdash; " :: Text) <> htmlTitleAviator (b ^. logbookaviator))+                  link_ [href_ "https://fonts.googleapis.com/css?family=Inconsolata:400,700", rel_ "stylesheet", type_ "text/css"]+                  link_ [href_ "casr-logbook.css", rel_ "stylesheet", type_ "text/css"]+                  link_ [href_ "/atom.xml", rel_ "alternate", type_ "application/atom+xml", title_ "Atom feed"]+                  script_ [type_ "text/javascript", src_ "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"] ("" :: Text)+                  script_ [type_ "text/javascript", src_ "https://raw.github.com/Mathapedia/LaTeX2HTML5/master/latex2html5.min.js"] ("" :: Text)                  +            body_ [class_ "casr-logbook"] $ +              do  htmlLogbookHeader b+                  htmlLogbook aircraftFlightMeta' simulatorFlightMeta' examMeta' briefingMeta' reports' b++htmlLogbookHeader ::+  Logbook a b c d+  -> Html ()+htmlLogbookHeader _ =+  do  div_ [id_ "header", class_ "header"] $+        h1_ "Pilot Personal Log Book"+      div_ [id_ "subheader", class_ "subheader"] $+        h2_ $+          do  "Civil Aviation Safety Regulation 1998 (61.345)"+              " "+              span_ [class_ "austlii"] $+                a_ [href_ "http://www.austlii.edu.au/au/legis/cth/consol_reg/casr1998333/s61.345.html"] "austlii.edu.au"
+ test/doctests.hs view
@@ -0,0 +1,32 @@+module Main where++import Build_doctests (deps)+import Control.Applicative+import Control.Monad+import Data.List+import System.Directory+import System.FilePath+import Test.DocTest++main ::+  IO ()+main =+  getSources >>= \sources -> doctest $+      "-isrc"+    : "-idist/build/autogen"+    : "-optP-include"+    : "-optPdist/build/autogen/cabal_macros.h"+    : "-hide-all-packages"+    : map ("-package="++) deps ++ sources++getSources :: IO [FilePath]+getSources = filter (isSuffixOf ".hs") <$> go "src"+  where+    go dir = do+      (dirs, files) <- getFilesAndDirectories dir+      (files ++) . concat <$> mapM go dirs++getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])+getFilesAndDirectories dir = do+  c <- map (dir </>) . filter (`notElem` ["..", "."]) <$> getDirectoryContents dir+  (,) <$> filterM doesDirectoryExist c <*> filterM doesFileExist c