module Main where
import System.Time (Day(Monday,Saturday))
import Text.Html(Html, (!), (+++), (<<), toHtml)
import qualified Text.Html as Html
import Data.Maybe (fromMaybe, )
import Data.List.HT (sliceVertical, )
import qualified Data.Map as Map
type Year = Int
-- cf. HTam.NumberTheory
divides :: Int -> Year -> Bool
divides k n = mod n k == 0
isLeapYear :: Year -> Bool
isLeapYear year =
(divides 4 year && not (divides 100 year)) || divides 400 year
{-
We want to know, which years share the same calendar.
That is we want to know, in which year we can re-use the calendar of this year.
There are 14 types of years, because of two parameters:
The starting weekday of the year and whether there is a leap day or not.
-}
type YearType = (Day, Bool)
succDay :: Day -> Day
succDay d = if d==maxBound then minBound else succ d
futureYearTypes :: [(Year, YearType)]
futureYearTypes =
iterate
(\(year,(day,leap)) ->
let newYear = succ year
startDay = succDay $
if leap
then succDay day
else day
in (newYear, (startDay, isLeapYear newYear)))
(2001,(Monday,False))
predDay :: Day -> Day
predDay d = if d==minBound then maxBound else pred d
pastYearTypes :: [(Year, YearType)]
pastYearTypes =
iterate
(\(year,(day,_)) ->
let oldYear = pred year
leap = isLeapYear oldYear
startDay = predDay $
if leap
then predDay day
else day
in (oldYear, (startDay, leap)))
(2000,(Saturday,True))
-- compute equivalent years
exampleYearTypeMap :: Map.Map YearType [Year]
exampleYearTypeMap =
let years = reverse (take 99 futureYearTypes) ++ take 101 pastYearTypes
in Map.fromListWith (++) (map (\(year,yearType) -> (yearType,[year])) years)
exampleYearTypeMapStr :: String
exampleYearTypeMapStr =
let showYear ((day,leap),years) =
show day ++ " " ++
(if leap then "(leap)" else " ") ++ "\t" ++
show years
in unlines $ map showYear $ Map.toList exampleYearTypeMap
weekdays :: [Day]
weekdays = [minBound..maxBound]
yearToHtml :: Year -> Html
yearToHtml = toHtml . show
exampleHtml :: Html
exampleHtml =
let makeYearTable leap =
Html.simpleTable [] []
(map (\d -> (toHtml (show d) :) $
map (\y -> Html.anchor (yearToHtml y) !
[Html.name (show y)]) $
fromMaybe (error "every weekday must exist") $
Map.lookup (d,leap) exampleYearTypeMap) weekdays)
! [Html.border 1]
in Html.simpleTable [] []
(sliceVertical 20 $
map (\y -> Html.anchor (yearToHtml y) ! [Html.href ('#':show y)])
[1900..2099::Int])
! [Html.border 1]
+++ Html.h2 << "Normale Jahre" +++ makeYearTable False
+++ Html.h2 << "Schaltjahre" +++ makeYearTable True
+++ foldl1 (+++) (replicate 30 Html.br)
writeHtml :: IO ()
writeHtml = writeFile "CalendarTable.hsc" (show exampleHtml)
main :: IO ()
main = writeHtml