root/svg-template-french-revolutionary.scm

(define-module (svg-template-french-revolutionary)
  #:use-module (srfi srfi-19)
  #:use-module (sxml simple)
  #:use-module (file-utils)
  #:export (svg-template-french-revolutionary gdate->fyear))

;;; TODO haven't really checked on the different mappings to gregorian

(define day-w 11)
(define day-h day-w)
(define day-p 2)

(define month-w (* 10 (+ day-p day-w)))
(define month-h (* 3 (+ day-p day-h)))
(define month-p (* 2 day-h))

(define (is-leap-year fyear)
  (let ((year (+ fyear 1793)))
    (and (= 0 (remainder year 4))
         (or (not (= 0 (remainder year 100)))
             (=  0 (remainder year 400))))))

(define (month-max year) 12)

(define (days-in-month year month)
  (if (= 12 month)
      (if (is-leap-year year) 6 5)
      30))

(define (translate-str x y)
  (string-append "translate("
                 (number->string x) ","
                 (number->string y) ")"))

(define (season-name n)
  (cond ((= 0 n) "Autumn")
        ((= 1 n) "Winter")
        ((= 2 n) "Spring")
        ((= 3 n) "Summer")
        ((= 4 n) "Festive")))

(define (month-pos n)
  (define season (floor (/ n 3)))
  (define season-month (remainder n 3))
  (if (= 12 n)
      (cons (* (+ month-w day-p day-p) 1) (* (+ month-h month-p) season))
      (cons (* (+ month-w day-p day-p) season-month) (* (+ month-h month-p) season))))

(define (month-week-offset n)
  0)

(define (generate-month month)
  (let ((x (car (month-pos month)))
        (y (cdr (month-pos month))))
    `(g (@ (transform ,(translate-str x y)) (class "month"))
        (text (@ ;; (fill "#ffffbb")
               (x ,(exact->inexact (/ month-w 2)))
               (y ,-3)
               (text-anchor "middle")
               (font-family "Arial")
               (text-decoration "")
               (font-weight "bold")
               (fill "#ffffff")
               (font-size 9))
              ,(month-name month)))))

(define dayd (* 60 60 24))
(define (add-leap day season year)
  (if (and (is-leap-year year)
           (or (and (= season 0) (> day 59))
               (> season 0)))
      dayd
      0))

(define sept-21 264)

(define (frdate->gregorian day month year)
  ;; (define before-gregorian-year-end (or (< month 3)
  ;;                                       (and (= month 3)
  ;;                                            (<= day 12 ))))

  (time-monotonic->date
   (make-time 'time-monotonic 0
              (+ ;; (add-leap day month year)
                 ;; (if (and (= month 12) (= day 6))
                 ;;     (* 60 dayd)
                 ;;     (* day dayd))
                 (* 30 dayd month)
                 (* dayd day)
                 (* dayd sept-21)
                 (time-second
                  (date->time-monotonic
                       (make-date 0 0 0 0 0 1 (+ year 1791) 0)))
                 ;; (if before-gregorian-year-end
                 ;;     (* dayd sept-21)
                 ;;     (* -1 dayd (+ (* 3 30) 12)))
                 ;; (* 1 dayd)
                 ;; (if before-gregorian-year-end
                 ;;     (time-second
                 ;;      (date->time-monotonic
                 ;;       (make-date 0 0 0 0 0 1 (+ year 1792) 0)))
                 ;;     (time-second
                 ;;      (date->time-monotonic
                 ;;       (make-date 0 0 0 0 0 1 (+ year 1793) 0))))
                 )
              ))) ;; 2lazy2doit→

(define (generate-day day month year day-details-lam)
  (let* ((mo (month-week-offset month))
         (in-week (remainder (- (+ day mo) 1) 10))
         (x (* in-week (+ day-w day-p)))
         (y (* (floor (/ (- (+ day mo) 1) 10)) (+ day-h day-p)))
         (custom (day-details-lam (frdate->gregorian day month year))))
    ;; (warn year month day "is" (frdate->gregorian day month year))
    `(g (@ (transform ,(translate-str x y)) ,(assoc 'class custom))
        ,(assoc 'title custom)
        ,(assoc 'desc custom)
        (rect (@ (height ,day-h)
                 (width ,day-w)
                 ,(assoc 'fill custom)))
        (text (@ (y ,(- day-h 1))
                 (x ,(/ day-w 2.0))
                 (font-size ,(- day-h 1)) (font-weight "bold")
                 (font-family "Arial") (text-anchor "middle") (fill "#ffaaaa"))
              ,day))))

(define (generate-days month-n year day-details-lam)
  (let ((day-tags '()) ;; this code is a shit
        (days-in-m (days-in-month year month-n)))
    (do ((day-n 1 (1+ day-n))) ((> day-n days-in-m))
      (let ((day-tag (generate-day day-n month-n year day-details-lam)))
        (set! day-tags (cons day-tag day-tags))
        day-tags))
    day-tags))

;; Chaos, Discord, Confusion, Bureaucracy, and The Aftermath
(define (month-name n)
  (cond ((= 0 n) "Vendémiaire")
        ((= 1 n) "Brumaire")
        ((= 2 n) "Frimaire")
        ((= 3 n) "Nivôse")
        ((= 4 n) "Pluviôse")
        ((= 5 n) "Ventôse")
        ((= 6 n) "Germinal")
        ((= 7 n) "Floréal")
        ((= 8 n) "Prairial")
        ((= 9 n) "Messidor")
        ((= 10 n) "Thermidor")
        ((= 11 n) "Fructidor")
        ((= 12 n) "Sansculottides")))

(define (generate-months year day-details-lam)
  (let ((month-tags '())) ;; this code is a shit
    (do ((month-n 0 (1+ month-n))) ((> month-n (month-max year)))
      (let* ((month-tag (generate-month month-n)))
        (set! month-tag (append month-tag (generate-days month-n year day-details-lam)))
        (set! month-tags (cons month-tag month-tags))
        month-tags))
    month-tags))

(define (year-legend year)
  `(g (@ (transform ,(string-append (translate-str (* 0.25 month-w) (* (+ month-h month-p) 4.4))
                                    " ")))
      (text (@ (text-anchor "center")
               (font-family "Arial")
               (font-weight "bold")
               (fill "#ffffff")
               (text-decoration "underline")
               (font-size 10))
            ,(string-append "Year: " (number->string year)))))

(define (gdate->fyear date)
  (if (> (date-year-day date) sept-21 )
      (- (date-year date) 1791)
      (- (date-year date) 1792)))

(define (generate-background total-width total-height)
  `((rect (@ (height ,total-width)
             (width ,total-width)
             (fill "#332233")))
    (rect (@ (transform ,(translate-str day-w day-w))
             (height ,(- total-height (* day-w 2)))
             (width ,(- total-width (* day-w 2)))
             (fill "#aa99aa")))
    (rect (@ (transform ,(translate-str (* day-w 2) (* day-w 2)))
             (height ,(- total-height (* day-w 4)))
             (width ,(- total-width (* day-w 4)))
             (fill "#332233")))))

(define add-images #t)
(define image-w 150)

(define (add-image x y scale file)
  (define content (get-file-contents file))
  (define sxml (xml->sxml content))
  `(g (@ (transform ,(string-append
                      (translate-str x y)
                      " scale(" (number->string scale) ")")))
      ,sxml))

(define (generate-svg-french-revolutionary gyear-date day-details-lam)
  (let* ((year (gdate->fyear gyear-date))
         (total-height (+ (* (+ month-p month-h) 5) (* day-w 4) ))
         (base-width (+ 15 (* 3 (+ day-p day-p day-p month-w)) (* day-w 4)))
         (total-width (+ base-width (if add-images (* image-w 2) 0)))
         (background (generate-background total-width total-height))
         (month-tags (generate-months year day-details-lam)))
    `(svg (@ (width ,total-width) (height ,total-height)
             (viewBox ,(string-append
                        "0 0 "
                        (number->string total-width) " "
                        (number->string total-height)))
             (xmlns "http://www.w3.org/2000/svg"))
          ,background
          ,(if add-images
               (list
                (add-image (* day-w 1) 30 4 "img/l.svg")
                (add-image (+ 25 (/ image-w 2) (* day-w 3) base-width) 30 2.9 "img/r.svg")))
          (g (@ (transform ,(translate-str (+ (* day-w 3) (if add-images image-w 0)) (* day-w 4))))
             ,(year-legend year)
             (title ,(string-append "git activity french-revolutionary calendar " (number->string year)))
             ,month-tags
             ))))

(define svg-template-french-revolutionary
  `((fn . ,generate-svg-french-revolutionary)
    (theme . ((day-bg . "rgba(100,100,100,0.9)")))))