Porting to new calendar modules.
This commit is contained in:
parent
21a58e9536
commit
cc463991c1
10 changed files with 57 additions and 545 deletions
51
src/Makefile
51
src/Makefile
|
@ -31,20 +31,20 @@ static: ../hackerbase
|
||||||
|
|
||||||
CSC=csc
|
CSC=csc
|
||||||
|
|
||||||
HACKERBASE-DEPS=hackerbase.scm month.import.scm \
|
HACKERBASE-DEPS=hackerbase.scm cal-month.import.scm \
|
||||||
command-line.import.scm mbase.import.scm brmember.import.scm \
|
command-line.import.scm mbase.import.scm brmember.import.scm \
|
||||||
configuration.import.scm cards.import.scm \
|
configuration.import.scm cards.import.scm \
|
||||||
members-print.import.scm members-payments.import.scm \
|
members-print.import.scm members-payments.import.scm \
|
||||||
web-static.import.scm environment.import.scm \
|
web-static.import.scm environment.import.scm \
|
||||||
mailman.import.scm texts.import.scm tests.import.scm \
|
mailman.import.scm texts.import.scm tests.import.scm \
|
||||||
notifications.import.scm logging.import.scm \
|
notifications.import.scm logging.import.scm \
|
||||||
progress.import.scm period.import.scm
|
progress.import.scm cal-period.import.scm
|
||||||
|
|
||||||
HACKERBASE-OBJS=hackerbase.o testing.o listing.o month.o period.o \
|
HACKERBASE-OBJS=hackerbase.o testing.o listing.o cal-month.o \
|
||||||
ansi.o util-dict-list.o command-line.o mbase.o primes.o \
|
cal-period.o ansi.o util-dict-list.o command-line.o mbase.o \
|
||||||
brmember.o configuration.o progress.o table.o cards.o \
|
primes.o brmember.o configuration.o progress.o table.o \
|
||||||
members-print.o members-fees.o mbase-dir.o util-csv.o \
|
cards.o members-print.o members-fees.o mbase-dir.o \
|
||||||
bank-account.o bank-fio.o members-payments.o \
|
util-csv.o bank-account.o bank-fio.o members-payments.o \
|
||||||
brmember-parser.o web-static.o environment.o mailman.o \
|
brmember-parser.o web-static.o environment.o mailman.o \
|
||||||
util-set-list.o util-time.o util-tag.o util-io.o \
|
util-set-list.o util-time.o util-tag.o util-io.o \
|
||||||
util-string.o util-io.o util-list.o util-parser.o texts.o \
|
util-string.o util-io.o util-list.o util-parser.o texts.o \
|
||||||
|
@ -106,17 +106,6 @@ UTIL-DICT-LIST-SOURCES=util-dict-list.scm testing.import.scm \
|
||||||
util-dict-list.o: util-dict-list.import.scm
|
util-dict-list.o: util-dict-list.import.scm
|
||||||
util-dict-list.import.scm: $(UTIL-DICT-LIST-SOURCES)
|
util-dict-list.import.scm: $(UTIL-DICT-LIST-SOURCES)
|
||||||
|
|
||||||
MONTH-SOURCES=month.scm testing.import.scm
|
|
||||||
|
|
||||||
month.o: month.import.scm
|
|
||||||
month.import.scm: $(MONTH-SOURCES)
|
|
||||||
|
|
||||||
PERIOD-SOURCES=period.scm testing.import.scm month.import.scm \
|
|
||||||
configuration.import.scm
|
|
||||||
|
|
||||||
period.o: period.import.scm
|
|
||||||
period.import.scm: $(PERIOD-SOURCES)
|
|
||||||
|
|
||||||
ANSI-SOURCES=ansi.scm testing.import.scm util-list.import.scm
|
ANSI-SOURCES=ansi.scm testing.import.scm util-list.import.scm
|
||||||
|
|
||||||
ansi.o: ansi.import.scm
|
ansi.o: ansi.import.scm
|
||||||
|
@ -130,9 +119,10 @@ command-line.import.scm: $(COMMAND-LINE-SOURCES)
|
||||||
|
|
||||||
MBASE-SOURCES=mbase.scm testing.import.scm util-dict-list.import.scm \
|
MBASE-SOURCES=mbase.scm testing.import.scm util-dict-list.import.scm \
|
||||||
primes.import.scm brmember.import.scm ansi.import.scm \
|
primes.import.scm brmember.import.scm ansi.import.scm \
|
||||||
period.import.scm month.import.scm configuration.import.scm \
|
cal-period.import.scm cal-month.import.scm \
|
||||||
progress.import.scm table.import.scm mbase-dir.import.scm \
|
configuration.import.scm progress.import.scm \
|
||||||
util-list.import.scm util-tag.import.scm
|
table.import.scm mbase-dir.import.scm util-list.import.scm \
|
||||||
|
util-tag.import.scm
|
||||||
|
|
||||||
mbase.o: mbase.import.scm
|
mbase.o: mbase.import.scm
|
||||||
mbase.import.scm: $(MBASE-SOURCES)
|
mbase.import.scm: $(MBASE-SOURCES)
|
||||||
|
@ -148,7 +138,7 @@ primes.o: primes.import.scm
|
||||||
primes.import.scm: $(PRIMES-SOURCES)
|
primes.import.scm: $(PRIMES-SOURCES)
|
||||||
|
|
||||||
BRMEMBER-SOURCES=brmember.scm util-dict-list.import.scm \
|
BRMEMBER-SOURCES=brmember.scm util-dict-list.import.scm \
|
||||||
period.import.scm testing.import.scm month.import.scm \
|
cal-period.import.scm testing.import.scm cal-month.import.scm \
|
||||||
configuration.import.scm primes.import.scm \
|
configuration.import.scm primes.import.scm \
|
||||||
bank-account.import.scm util-list.import.scm \
|
bank-account.import.scm util-list.import.scm \
|
||||||
util-tag.import.scm
|
util-tag.import.scm
|
||||||
|
@ -156,8 +146,7 @@ BRMEMBER-SOURCES=brmember.scm util-dict-list.import.scm \
|
||||||
brmember.o: brmember.import.scm
|
brmember.o: brmember.import.scm
|
||||||
brmember.import.scm: $(BRMEMBER-SOURCES)
|
brmember.import.scm: $(BRMEMBER-SOURCES)
|
||||||
|
|
||||||
CONFIGURATION-SOURCES=configuration.scm month.import.scm \
|
CONFIGURATION-SOURCES=configuration.scm util-parser.import.scm
|
||||||
util-parser.import.scm
|
|
||||||
|
|
||||||
configuration.o: configuration.import.scm
|
configuration.o: configuration.import.scm
|
||||||
configuration.import.scm: $(CONFIGURATION-SOURCES)
|
configuration.import.scm: $(CONFIGURATION-SOURCES)
|
||||||
|
@ -180,8 +169,8 @@ cards.o: cards.import.scm
|
||||||
cards.import.scm: $(CARDS-SOURCES)
|
cards.import.scm: $(CARDS-SOURCES)
|
||||||
|
|
||||||
BRMEMBER-PARSER-SOURCES=brmember-parser.scm brmember.import.scm \
|
BRMEMBER-PARSER-SOURCES=brmember-parser.scm brmember.import.scm \
|
||||||
testing.import.scm util-dict-list.import.scm month.import.scm \
|
testing.import.scm util-dict-list.import.scm cal-month.import.scm \
|
||||||
period.import.scm configuration.import.scm \
|
cal-period.import.scm configuration.import.scm \
|
||||||
util-string.import.scm util-list.import.scm \
|
util-string.import.scm util-list.import.scm \
|
||||||
util-parser.import.scm
|
util-parser.import.scm
|
||||||
|
|
||||||
|
@ -189,8 +178,8 @@ brmember-parser.o: brmember-parser.import.scm
|
||||||
brmember-parser.import.scm: $(BRMEMBER-PARSER-SOURCES)
|
brmember-parser.import.scm: $(BRMEMBER-PARSER-SOURCES)
|
||||||
|
|
||||||
MEMBERS-PRINT-SOURCES=members-print.scm util-dict-list.import.scm \
|
MEMBERS-PRINT-SOURCES=members-print.scm util-dict-list.import.scm \
|
||||||
brmember.import.scm month.import.scm table.import.scm \
|
brmember.import.scm cal-month.import.scm table.import.scm \
|
||||||
listing.import.scm ansi.import.scm period.import.scm \
|
listing.import.scm ansi.import.scm cal-period.import.scm \
|
||||||
primes.import.scm mbase.import.scm configuration.import.scm \
|
primes.import.scm mbase.import.scm configuration.import.scm \
|
||||||
bank-account.import.scm members-fees.import.scm \
|
bank-account.import.scm members-fees.import.scm \
|
||||||
members-payments.import.scm util-list.import.scm \
|
members-payments.import.scm util-list.import.scm \
|
||||||
|
@ -200,7 +189,7 @@ members-print.o: members-print.import.scm
|
||||||
members-print.import.scm: $(MEMBERS-PRINT-SOURCES)
|
members-print.import.scm: $(MEMBERS-PRINT-SOURCES)
|
||||||
|
|
||||||
MEMBERS-FEES-SOURCES=members-fees.scm configuration.import.scm \
|
MEMBERS-FEES-SOURCES=members-fees.scm configuration.import.scm \
|
||||||
brmember.import.scm month.import.scm table.import.scm \
|
brmember.import.scm cal-month.import.scm table.import.scm \
|
||||||
mbase.import.scm specification.import.scm \
|
mbase.import.scm specification.import.scm \
|
||||||
util-list.import.scm
|
util-list.import.scm
|
||||||
|
|
||||||
|
@ -233,7 +222,7 @@ bank-fio.import.scm: $(BANK-FIO-SOURCES)
|
||||||
|
|
||||||
MEMBERS-PAYMENTS-SOURCES=members-payments.scm bank-account.import.scm \
|
MEMBERS-PAYMENTS-SOURCES=members-payments.scm bank-account.import.scm \
|
||||||
util-dict-list.import.scm members-fees.import.scm \
|
util-dict-list.import.scm members-fees.import.scm \
|
||||||
period.import.scm configuration.import.scm \
|
cal-period.import.scm configuration.import.scm \
|
||||||
progress.import.scm bank-fio.import.scm util-list.import.scm \
|
progress.import.scm bank-fio.import.scm util-list.import.scm \
|
||||||
specification.import.scm
|
specification.import.scm
|
||||||
|
|
||||||
|
@ -354,7 +343,7 @@ LOGGING-SOURCES=logging.scm util-string.import.scm
|
||||||
logging.o: logging.import.scm
|
logging.o: logging.import.scm
|
||||||
logging.import.scm: $(LOGGING-SOURCES)
|
logging.import.scm: $(LOGGING-SOURCES)
|
||||||
|
|
||||||
SPECIFICATION-SOURCES=specification.scm period.import.scm
|
SPECIFICATION-SOURCES=specification.scm cal-period.import.scm
|
||||||
|
|
||||||
specification.o: specification.import.scm
|
specification.o: specification.import.scm
|
||||||
specification.import.scm: $(SPECIFICATION-SOURCES)
|
specification.import.scm: $(SPECIFICATION-SOURCES)
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
brmember
|
brmember
|
||||||
testing
|
testing
|
||||||
util-dict-list
|
util-dict-list
|
||||||
month
|
cal-month
|
||||||
period
|
cal-period
|
||||||
util-list
|
util-list
|
||||||
configuration
|
configuration
|
||||||
util-string
|
util-string
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
(kind (cadr mk)))
|
(kind (cadr mk)))
|
||||||
(foldl (lambda (mr value)
|
(foldl (lambda (mr value)
|
||||||
(let* ((mspec (string-first+rest (car value)))
|
(let* ((mspec (string-first+rest (car value)))
|
||||||
(month (string->month (car mspec)))
|
(month (string->cal-month (car mspec)))
|
||||||
(comment (cdr mspec)))
|
(comment (cdr mspec)))
|
||||||
(if month
|
(if month
|
||||||
(brmember-sub-prepend
|
(brmember-sub-prepend
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
,(lambda (mr output key value)
|
,(lambda (mr output key value)
|
||||||
(case key
|
(case key
|
||||||
((student suspend member)
|
((student suspend member)
|
||||||
(let* ((res (period-markers->periods value))
|
(let* ((res (period-markers->cal-periods value))
|
||||||
(ok? (car res))
|
(ok? (car res))
|
||||||
(periods (cadr res))
|
(periods (cadr res))
|
||||||
(msg (caddr res))
|
(msg (caddr res))
|
||||||
|
|
|
@ -84,8 +84,8 @@
|
||||||
(chicken format)
|
(chicken format)
|
||||||
util-dict-list
|
util-dict-list
|
||||||
testing
|
testing
|
||||||
month
|
cal-month
|
||||||
period
|
cal-period
|
||||||
configuration
|
configuration
|
||||||
primes
|
primes
|
||||||
util-list
|
util-list
|
||||||
|
@ -273,14 +273,14 @@
|
||||||
(let ((member (brmember-info mr 'member)))
|
(let ((member (brmember-info mr 'member)))
|
||||||
(if (null? member)
|
(if (null? member)
|
||||||
#f
|
#f
|
||||||
(month>=? (*current-month*)
|
(cal-month>=? (*current-month*)
|
||||||
(period-since (car member)))))))
|
(cal-period-since (car member)))))))
|
||||||
|
|
||||||
;; Generic period-based predicate
|
;; Generic period-based predicate
|
||||||
(define ((member-period-predicate? key) mr)
|
(define ((member-period-predicate? key) mr)
|
||||||
(let ((periods (brmember-info mr key #f)))
|
(let ((periods (brmember-info mr key #f)))
|
||||||
(and periods
|
(and periods
|
||||||
(month-in-periods? periods))))
|
(cal-month-in-periods? periods))))
|
||||||
|
|
||||||
;; Returns true if the member is now suspended
|
;; Returns true if the member is now suspended
|
||||||
(define member-is-suspended?
|
(define member-is-suspended?
|
||||||
|
@ -302,12 +302,12 @@
|
||||||
|
|
||||||
;; Returns true if the member is active (not suspended or destroyed).
|
;; Returns true if the member is active (not suspended or destroyed).
|
||||||
(define (brmember-active? mr)
|
(define (brmember-active? mr)
|
||||||
(and (month-in-periods? (brmember-info mr 'member))
|
(and (cal-month-in-periods? (brmember-info mr 'member))
|
||||||
(not (brmember-suspended? mr))))
|
(not (brmember-suspended? mr))))
|
||||||
|
|
||||||
;; Returns true if the member is currently a member
|
;; Returns true if the member is currently a member
|
||||||
(define (brmember-existing? mr)
|
(define (brmember-existing? mr)
|
||||||
(month-in-periods?
|
(cal-month-in-periods?
|
||||||
(brmember-info mr 'member)))
|
(brmember-info mr 'member)))
|
||||||
|
|
||||||
;; Returns a list of flags of given member record.
|
;; Returns a list of flags of given member record.
|
||||||
|
@ -331,9 +331,9 @@
|
||||||
;; suspended.
|
;; suspended.
|
||||||
(define (brmember-suspended-months mr)
|
(define (brmember-suspended-months mr)
|
||||||
(if (brmember-suspended? mr)
|
(if (brmember-suspended? mr)
|
||||||
(let ((period (periods-match (brmember-info mr 'suspend))))
|
(let ((period (cal-periods-match (brmember-info mr 'suspend))))
|
||||||
(if period
|
(if period
|
||||||
(month-diff (car period) (*current-month*))
|
(cal-month-diff (cal-period-since period) (*current-month*))
|
||||||
0))
|
0))
|
||||||
0))
|
0))
|
||||||
|
|
||||||
|
@ -352,8 +352,8 @@
|
||||||
(define (brmember-payments mr)
|
(define (brmember-payments mr)
|
||||||
(filter (lambda (tr)
|
(filter (lambda (tr)
|
||||||
(let* ((isodate (bank-transaction-date tr))
|
(let* ((isodate (bank-transaction-date tr))
|
||||||
(month (iso-date->month isodate)))
|
(month (iso-date->cal-month isodate)))
|
||||||
(month<=? month (*current-month*))))
|
(cal-month<=? month (*current-month*))))
|
||||||
(ldict-ref mr 'payments '())))
|
(ldict-ref mr 'payments '())))
|
||||||
|
|
||||||
;; Returns a list of MLs this member is subscribed to
|
;; Returns a list of MLs this member is subscribed to
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
(chicken time posix)
|
(chicken time posix)
|
||||||
(chicken file)
|
(chicken file)
|
||||||
(chicken io)
|
(chicken io)
|
||||||
month
|
|
||||||
util-parser)
|
util-parser)
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -73,8 +73,8 @@
|
||||||
primes
|
primes
|
||||||
brmember
|
brmember
|
||||||
ansi
|
ansi
|
||||||
period
|
cal-period
|
||||||
month
|
cal-month
|
||||||
configuration
|
configuration
|
||||||
progress
|
progress
|
||||||
mbase-dir
|
mbase-dir
|
||||||
|
@ -224,7 +224,7 @@
|
||||||
di7))
|
di7))
|
||||||
|
|
||||||
(define (members-base-oldest-month mb)
|
(define (members-base-oldest-month mb)
|
||||||
(make-month 2015 1))
|
(make-cal-month 2015 1))
|
||||||
|
|
||||||
;; Returns a list two lists: keys, data.
|
;; Returns a list two lists: keys, data.
|
||||||
;; Each data record contains values for all keys.
|
;; Each data record contains values for all keys.
|
||||||
|
@ -232,14 +232,14 @@
|
||||||
(let ((keys '(month total active suspended students destroyed invalid)))
|
(let ((keys '(month total active suspended students destroyed invalid)))
|
||||||
(let mloop ((data '())
|
(let mloop ((data '())
|
||||||
(month (members-base-oldest-month mb)))
|
(month (members-base-oldest-month mb)))
|
||||||
(if (month<? month (*current-month*))
|
(if (cal-month<? month (*current-month*))
|
||||||
(let ((bi (parameterize ((*current-month* month))
|
(let ((bi (parameterize ((*current-month* month))
|
||||||
(mbase-info mb))))
|
(mbase-info mb))))
|
||||||
(let kloop ((row (list (ldict-ref bi 'month)))
|
(let kloop ((row (list (ldict-ref bi 'month)))
|
||||||
(keys (cdr keys)))
|
(keys (cdr keys)))
|
||||||
(if (null? keys)
|
(if (null? keys)
|
||||||
(mloop (cons (reverse row) data)
|
(mloop (cons (reverse row) data)
|
||||||
(month-add month 1))
|
(cal-month-add month 1))
|
||||||
(kloop (cons (length (ldict-ref bi (car keys))) row)
|
(kloop (cons (length (ldict-ref bi (car keys))) row)
|
||||||
(cdr keys)))))
|
(cdr keys)))))
|
||||||
(list keys (reverse data))))))
|
(list keys (reverse data))))))
|
||||||
|
|
|
@ -47,17 +47,17 @@
|
||||||
(chicken sort)
|
(chicken sort)
|
||||||
configuration
|
configuration
|
||||||
brmember
|
brmember
|
||||||
month
|
cal-month
|
||||||
ansi
|
ansi
|
||||||
table
|
table
|
||||||
mbase
|
mbase
|
||||||
period
|
cal-period
|
||||||
specification
|
specification
|
||||||
util-list)
|
util-list)
|
||||||
|
|
||||||
;; Returns a matching list of (list regular student)
|
;; Returns a matching list of (list regular student)
|
||||||
(define (lookup-member-fees)
|
(define (lookup-member-fees)
|
||||||
(lookup-by-period member-fees-lookup-table))
|
(lookup-by-cal-period member-fees-lookup-table))
|
||||||
|
|
||||||
;; Returns time-based fee for given type
|
;; Returns time-based fee for given type
|
||||||
(define (lookup-member-fee type)
|
(define (lookup-member-fee type)
|
||||||
|
@ -74,12 +74,12 @@
|
||||||
(let ((last-month (if (null? args)
|
(let ((last-month (if (null? args)
|
||||||
(*current-month*)
|
(*current-month*)
|
||||||
(car args)))
|
(car args)))
|
||||||
(first-month (period-since (car (brmember-info mr 'member)))))
|
(first-month (cal-period-since (car (brmember-info mr 'member)))))
|
||||||
(let loop ((cm first-month)
|
(let loop ((cm first-month)
|
||||||
(cal '()))
|
(cal '()))
|
||||||
(if (month>? cm last-month)
|
(if (cal-month>? cm last-month)
|
||||||
(reverse cal)
|
(reverse cal)
|
||||||
(loop (month-add cm)
|
(loop (cal-month-add cm)
|
||||||
(cons (list cm
|
(cons (list cm
|
||||||
(parameterize ((*current-month* cm))
|
(parameterize ((*current-month* cm))
|
||||||
(brmember-flags mr)))
|
(brmember-flags mr)))
|
||||||
|
@ -134,8 +134,8 @@
|
||||||
'()
|
'()
|
||||||
(let* ((fm (member-calendar-first-month mc))
|
(let* ((fm (member-calendar-first-month mc))
|
||||||
(lm (member-calendar-last-month mc))
|
(lm (member-calendar-last-month mc))
|
||||||
(fy (month-year fm))
|
(fy (cal-month-year fm))
|
||||||
(ly (month-year lm)))
|
(ly (cal-month-year lm)))
|
||||||
(let loop ((y fy)
|
(let loop ((y fy)
|
||||||
(rows '()))
|
(rows '()))
|
||||||
(if (> y ly)
|
(if (> y ly)
|
||||||
|
@ -147,7 +147,7 @@
|
||||||
(reverse row)
|
(reverse row)
|
||||||
(mloop (add1 m)
|
(mloop (add1 m)
|
||||||
(cons (member-calendar-entry->string
|
(cons (member-calendar-entry->string
|
||||||
(member-calendar-query mc (make-month y m)))
|
(member-calendar-query mc (make-cal-month y m)))
|
||||||
row))))
|
row))))
|
||||||
rows)))))))
|
rows)))))))
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
bank-fio
|
bank-fio
|
||||||
util-dict-list
|
util-dict-list
|
||||||
members-fees
|
members-fees
|
||||||
period
|
cal-period
|
||||||
configuration
|
configuration
|
||||||
util-list
|
util-list
|
||||||
progress
|
progress
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
|
|
||||||
;; Lookup CZK/EUR
|
;; Lookup CZK/EUR
|
||||||
(define (lookup-eur-rate)
|
(define (lookup-eur-rate)
|
||||||
(car (lookup-by-period exchange-rates-lookup-table)))
|
(car (lookup-by-cal-period exchange-rates-lookup-table)))
|
||||||
|
|
||||||
;; Extract probable member-id from transaction
|
;; Extract probable member-id from transaction
|
||||||
(define (transaction-extract-member-id transaction)
|
(define (transaction-extract-member-id transaction)
|
||||||
|
|
192
src/month.scm
192
src/month.scm
|
@ -1,192 +0,0 @@
|
||||||
;;
|
|
||||||
;; month.scm
|
|
||||||
;;
|
|
||||||
;; Month processing support.
|
|
||||||
;;
|
|
||||||
;; ISC License
|
|
||||||
;;
|
|
||||||
;; Copyright 2023 Brmlab, z.s.
|
|
||||||
;; Dominik Pantůček <dominik.pantucek@trustica.cz>
|
|
||||||
;;
|
|
||||||
;; Permission to use, copy, modify, and/or distribute this software
|
|
||||||
;; for any purpose with or without fee is hereby granted, provided
|
|
||||||
;; that the above copyright notice and this permission notice appear
|
|
||||||
;; in all copies.
|
|
||||||
;;
|
|
||||||
;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
||||||
;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
||||||
;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
||||||
;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
|
||||||
;; CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
||||||
;; OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
;; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
;; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
;;
|
|
||||||
|
|
||||||
(declare (unit month))
|
|
||||||
|
|
||||||
(module
|
|
||||||
month
|
|
||||||
(
|
|
||||||
make-month
|
|
||||||
month-year
|
|
||||||
month-month
|
|
||||||
month-valid?
|
|
||||||
string->month
|
|
||||||
month->string
|
|
||||||
month=?
|
|
||||||
month<?
|
|
||||||
month<=?
|
|
||||||
month>=?
|
|
||||||
month>?
|
|
||||||
month-diff
|
|
||||||
month-add
|
|
||||||
iso-date->month
|
|
||||||
month-tests!
|
|
||||||
)
|
|
||||||
|
|
||||||
(import scheme
|
|
||||||
(chicken base)
|
|
||||||
(chicken string)
|
|
||||||
(chicken format)
|
|
||||||
testing)
|
|
||||||
|
|
||||||
;; Simple wrapper for creating month representation as a list.
|
|
||||||
(define (make-month y m)
|
|
||||||
(list y m))
|
|
||||||
|
|
||||||
;; Accessors
|
|
||||||
(define month-year car)
|
|
||||||
(define month-month cadr)
|
|
||||||
|
|
||||||
;; Returns true if this is a valid month representation - a list with
|
|
||||||
;; two integer elements within the allowed range.
|
|
||||||
(define (month-valid? m)
|
|
||||||
(and (list? m)
|
|
||||||
(car m)
|
|
||||||
(cdr m)
|
|
||||||
(cadr m)
|
|
||||||
(null? (cddr m))
|
|
||||||
(integer? (car m))
|
|
||||||
(integer? (cadr m))
|
|
||||||
(>= (car m) 1000)
|
|
||||||
(<= (car m) 9999)
|
|
||||||
(>= (cadr m) 1)
|
|
||||||
(<= (cadr m) 12)))
|
|
||||||
|
|
||||||
;; Converts string in a format YYYY-MM to valid month. Returns #f if
|
|
||||||
;; the conversion fails.
|
|
||||||
(define (string->month s)
|
|
||||||
(let ((l (string-split s "-")))
|
|
||||||
(if (or (not l)
|
|
||||||
(null? l)
|
|
||||||
(null? (cdr l))
|
|
||||||
(not (null? (cddr l))))
|
|
||||||
#f
|
|
||||||
(let ((y (string->number (car l)))
|
|
||||||
(m (string->number (cadr l))))
|
|
||||||
(if (and y m)
|
|
||||||
(let ((M (list y m)))
|
|
||||||
(if (month-valid? M)
|
|
||||||
M
|
|
||||||
#f))
|
|
||||||
#f)))))
|
|
||||||
|
|
||||||
;; Formats (valid) month as YYYY-MM string
|
|
||||||
(define (month->string M)
|
|
||||||
(if M
|
|
||||||
(if (month-valid? M)
|
|
||||||
(let ((y (car M))
|
|
||||||
(m (cadr M)))
|
|
||||||
(sprintf "~A-~A~A"
|
|
||||||
y
|
|
||||||
(if (< m 10) "0" "")
|
|
||||||
m))
|
|
||||||
(error 'string->month "Invalid month" M))
|
|
||||||
"____-__"))
|
|
||||||
|
|
||||||
;; Returns true if both arguments are a valid month and are equal
|
|
||||||
(define (month=? m n)
|
|
||||||
(and (month-valid? m)
|
|
||||||
(month-valid? n)
|
|
||||||
(equal? m n)))
|
|
||||||
|
|
||||||
;; Returns true if the first argument is a month in the past of the
|
|
||||||
;; second argument month
|
|
||||||
(define (month<? m n)
|
|
||||||
(and (month-valid? m)
|
|
||||||
(month-valid? n)
|
|
||||||
(or (< (car m) (car n))
|
|
||||||
(and (= (car m) (car n))
|
|
||||||
(< (cadr m) (cadr n))))))
|
|
||||||
|
|
||||||
;; Returns true if m is less than or equal n
|
|
||||||
(define (month<=? m n)
|
|
||||||
(or (month<? m n)
|
|
||||||
(month=? m n)))
|
|
||||||
|
|
||||||
;; Returns true if m is greater than or equal to n
|
|
||||||
(define (month>=? m n)
|
|
||||||
(not (month<? m n)))
|
|
||||||
|
|
||||||
;; Returns true if m is greater than n
|
|
||||||
(define (month>? m n)
|
|
||||||
(not (month<=? m n)))
|
|
||||||
|
|
||||||
;; Returns the number of months between from f and to t. The first
|
|
||||||
;; month is included in the count, the last month is not.
|
|
||||||
(define (month-diff f t)
|
|
||||||
(if (month-valid? f)
|
|
||||||
(if (month-valid? t)
|
|
||||||
(let ((F (+ (* (car f) 12) (cadr f) -1))
|
|
||||||
(T (+ (* (car t) 12) (cadr t) -1)))
|
|
||||||
(- T F))
|
|
||||||
(error 'month-diff "Second argument is not a valid month" t))
|
|
||||||
(error 'month-diff "First argument is not a valid month" f)))
|
|
||||||
|
|
||||||
;; Returns a month n months after the month m. The number n defaults
|
|
||||||
;; to 1.
|
|
||||||
(define (month-add m . ns)
|
|
||||||
(let* ((n (if (null? ns)
|
|
||||||
1
|
|
||||||
(car ns)))
|
|
||||||
(mi (+ (* 12 (car m)) (cadr m) n -1)))
|
|
||||||
(list (quotient mi 12)
|
|
||||||
(+ (remainder mi 12) 1))))
|
|
||||||
|
|
||||||
;; Converts ISO date to single month
|
|
||||||
(define (iso-date->month str)
|
|
||||||
(let* ((lst (string-split str "-"))
|
|
||||||
(year (car lst))
|
|
||||||
(mon (cadr lst)))
|
|
||||||
(make-month (string->number year)
|
|
||||||
(string->number mon))))
|
|
||||||
|
|
||||||
;; Performs self-tests of the month module.
|
|
||||||
(define (month-tests!)
|
|
||||||
(run-tests
|
|
||||||
month
|
|
||||||
(test-true month-valid? (month-valid? '(2023 5)))
|
|
||||||
(test-false month-valid? (month-valid? '(999 8)))
|
|
||||||
(test-false month-valid? (month-valid? '(2023 -5)))
|
|
||||||
(test-equal? string->month (string->month "2023-01") '(2023 1))
|
|
||||||
(test-false string->month (string->month "2023-13"))
|
|
||||||
(test-false string->month (string->month "YYYY-01"))
|
|
||||||
(test-false string->month (string->month "2023-MMM"))
|
|
||||||
(test-equal? month->string (month->string '(2023 1)) "2023-01")
|
|
||||||
(test-exn month->string (month->string '(999 12)))
|
|
||||||
(test-exn month->string (month->string '(2023 13)))
|
|
||||||
(test-true month<? (month<? '(2023 5) '(2023 6)))
|
|
||||||
(test-true month<? (month<? '(2022 12) '(2023 1)))
|
|
||||||
(test-false month<? (month<? '(2023 1) '(2023 1)))
|
|
||||||
(test-false month<? (month<? '(2023 1) '(2023 1)))
|
|
||||||
(test-true month=? (month=? '(2023 4) '(2023 4)))
|
|
||||||
(test-false month=? (month=? '(2023 4) '(2023 5)))
|
|
||||||
(test-eq? month-diff (month-diff '(2023 1) '(2023 2)) 1)
|
|
||||||
(test-eq? month-diff (month-diff '(2023 1) '(2023 12)) 11)
|
|
||||||
(test-eq? month-diff (month-diff '(2023 1) '(2022 2)) -11)
|
|
||||||
(test-eq? month-add (month-add '(2023 1) 2) '(2023 3))
|
|
||||||
(test-equal? iso-date->month (iso-date->month "2023-04-03") '(2023 4))
|
|
||||||
))
|
|
||||||
|
|
||||||
)
|
|
284
src/period.scm
284
src/period.scm
|
@ -1,284 +0,0 @@
|
||||||
;;
|
|
||||||
;; period.scm
|
|
||||||
;;
|
|
||||||
;; Month periods.
|
|
||||||
;;
|
|
||||||
;; ISC License
|
|
||||||
;;
|
|
||||||
;; Copyright 2023 Brmlab, z.s.
|
|
||||||
;; Dominik Pantůček <dominik.pantucek@trustica.cz>
|
|
||||||
;;
|
|
||||||
;; Permission to use, copy, modify, and/or distribute this software
|
|
||||||
;; for any purpose with or without fee is hereby granted, provided
|
|
||||||
;; that the above copyright notice and this permission notice appear
|
|
||||||
;; in all copies.
|
|
||||||
;;
|
|
||||||
;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
||||||
;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
||||||
;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
||||||
;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
|
||||||
;; CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
||||||
;; OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
;; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
;; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
;;
|
|
||||||
|
|
||||||
(declare (unit period))
|
|
||||||
|
|
||||||
(module
|
|
||||||
period
|
|
||||||
(
|
|
||||||
*current-month*
|
|
||||||
|
|
||||||
make-period
|
|
||||||
|
|
||||||
period-since
|
|
||||||
period-before
|
|
||||||
period-scomment
|
|
||||||
period-bcomment
|
|
||||||
|
|
||||||
period-markers->periods
|
|
||||||
|
|
||||||
periods-duration
|
|
||||||
|
|
||||||
month-in-period?
|
|
||||||
month-in-periods?
|
|
||||||
|
|
||||||
periods->string
|
|
||||||
periods-match
|
|
||||||
|
|
||||||
make-period-lookup-table
|
|
||||||
lookup-by-period
|
|
||||||
|
|
||||||
period-tests!
|
|
||||||
)
|
|
||||||
|
|
||||||
(import scheme
|
|
||||||
(chicken base)
|
|
||||||
(chicken sort)
|
|
||||||
(chicken time)
|
|
||||||
(chicken time posix)
|
|
||||||
(chicken format)
|
|
||||||
(chicken string)
|
|
||||||
month
|
|
||||||
testing
|
|
||||||
configuration)
|
|
||||||
|
|
||||||
;; Current month - if changed, we get the actual state for given month.
|
|
||||||
(define *current-month*
|
|
||||||
(make-parameter
|
|
||||||
(let ((d (seconds->local-time (current-seconds))))
|
|
||||||
(list (+ 1900 (vector-ref d 5))
|
|
||||||
(+ (vector-ref d 4) 1)))))
|
|
||||||
|
|
||||||
;; Creates a new period value with optional since and before
|
|
||||||
;; comments.
|
|
||||||
(define (make-period since before . args)
|
|
||||||
(let ((scomment (if (not (null? args)) (car args) #f))
|
|
||||||
(bcomment (if (and (not (null? args))
|
|
||||||
(not (null? (cdr args))))
|
|
||||||
(cadr args)
|
|
||||||
#f)))
|
|
||||||
(list since before scomment bcomment)))
|
|
||||||
|
|
||||||
;; Simple accessors
|
|
||||||
(define period-since car)
|
|
||||||
(define period-before cadr)
|
|
||||||
(define period-scomment caddr)
|
|
||||||
(define period-bcomment cadddr)
|
|
||||||
|
|
||||||
;; Sorts period markers (be it start or end) chronologically and
|
|
||||||
;; returns the sorted list.
|
|
||||||
(define (sort-period-markers l)
|
|
||||||
(sort l
|
|
||||||
(lambda (a b)
|
|
||||||
(month<? (cadr a) (cadr b)))))
|
|
||||||
|
|
||||||
;; Converts list of start/stop markers to list of pairs of months -
|
|
||||||
;; periods.
|
|
||||||
(define (period-markers->periods l)
|
|
||||||
(let loop ((l (sort-period-markers l))
|
|
||||||
(ps '())
|
|
||||||
(cb #f))
|
|
||||||
(if (null? l)
|
|
||||||
(list #t
|
|
||||||
(if cb
|
|
||||||
(reverse (cons (make-period (car cb) #f (cadr cb)) ps))
|
|
||||||
(reverse ps))
|
|
||||||
""
|
|
||||||
-1)
|
|
||||||
(let* ((marker (car l))
|
|
||||||
(rmt (if cb 'stop 'start))
|
|
||||||
(mtype (car marker))
|
|
||||||
(month (cadr marker))
|
|
||||||
(line-number (if (null? (cddr marker))
|
|
||||||
#f
|
|
||||||
(caddr marker)))
|
|
||||||
(comment (if (and line-number
|
|
||||||
(not (null? (cdddr marker))))
|
|
||||||
(cadddr marker)
|
|
||||||
#f)))
|
|
||||||
(if (eq? mtype rmt)
|
|
||||||
(if cb
|
|
||||||
(loop (cdr l)
|
|
||||||
(cons (make-period (car cb) month (cadr cb) comment) ps)
|
|
||||||
#f)
|
|
||||||
(loop (cdr l)
|
|
||||||
ps
|
|
||||||
(list month comment)))
|
|
||||||
(list #f
|
|
||||||
(reverse ps)
|
|
||||||
(sprintf "Invalid start/stop sequence marker ~A" marker)
|
|
||||||
line-number))))))
|
|
||||||
|
|
||||||
;; Returns duration of period in months. Start is included, end is
|
|
||||||
;; not. The period contains the month just before the specified end.
|
|
||||||
(define (period->duration p)
|
|
||||||
(let* ((b (period-since p))
|
|
||||||
(e (period-before p))
|
|
||||||
(e- (if e e (*current-month*))))
|
|
||||||
(month-diff b e-)))
|
|
||||||
|
|
||||||
;; Returns sum of periods lengths.
|
|
||||||
(define (periods-duration l)
|
|
||||||
(apply + (map period->duration l)))
|
|
||||||
|
|
||||||
;; True if month belongs to given month period - start inclusive, end
|
|
||||||
;; exclusive.
|
|
||||||
(define (month-in-period? p . ml)
|
|
||||||
(let ((m (if (null? ml)
|
|
||||||
(*current-month*)
|
|
||||||
(car ml))))
|
|
||||||
(and (or (not (period-before p))
|
|
||||||
(month<? m (period-before p)))
|
|
||||||
(not (month<? m (period-since p))))))
|
|
||||||
|
|
||||||
;; Returns true if given month is in at least one of the periods
|
|
||||||
;; given. Defaults to current month.
|
|
||||||
(define (month-in-periods? ps . ml)
|
|
||||||
(let ((m (if (null? ml)
|
|
||||||
(*current-month*)
|
|
||||||
(car ml))))
|
|
||||||
(let loop ((ps ps))
|
|
||||||
(if (null? ps)
|
|
||||||
#f
|
|
||||||
(if (month-in-period? (car ps) m)
|
|
||||||
#t
|
|
||||||
(loop (cdr ps)))))))
|
|
||||||
|
|
||||||
;; Returns string representing a month period with possibly open end.
|
|
||||||
(define (period->string p)
|
|
||||||
(sprintf "~A..~A"
|
|
||||||
(month->string (period-since p))
|
|
||||||
(month->string (period-before p))))
|
|
||||||
|
|
||||||
;; Returns a string representing a list of periods.
|
|
||||||
(define (periods->string ps)
|
|
||||||
(string-intersperse
|
|
||||||
(map period->string ps)
|
|
||||||
", "))
|
|
||||||
|
|
||||||
;; Finds a period the month matches and returns it. If no period
|
|
||||||
;; matches, it returns #f.
|
|
||||||
(define (periods-match ps . ml)
|
|
||||||
(let ((m (if (null? ml) (*current-month*) (car ml))))
|
|
||||||
(let loop ((ps ps))
|
|
||||||
(if (null? ps)
|
|
||||||
#f
|
|
||||||
(if (month-in-period? (car ps) m)
|
|
||||||
(car ps)
|
|
||||||
(loop (cdr ps)))))))
|
|
||||||
|
|
||||||
;; Creates lookup table from definition source
|
|
||||||
(define (make-period-lookup-table source)
|
|
||||||
(let loop ((lst source)
|
|
||||||
(res '())
|
|
||||||
(prev #f))
|
|
||||||
(if (null? lst)
|
|
||||||
(reverse
|
|
||||||
(cons (cons (make-period (car prev) #f)
|
|
||||||
(cdr prev))
|
|
||||||
res))
|
|
||||||
(loop (cdr lst)
|
|
||||||
(if prev
|
|
||||||
(cons (cons (make-period (car prev) (caar lst))
|
|
||||||
(cdr prev))
|
|
||||||
res)
|
|
||||||
res)
|
|
||||||
(car lst)))))
|
|
||||||
|
|
||||||
;; Looks up current month and returns associated definitions
|
|
||||||
(define (lookup-by-period table)
|
|
||||||
(let loop ((lst table))
|
|
||||||
(if (null? lst)
|
|
||||||
#f
|
|
||||||
(if (month-in-period? (caar lst))
|
|
||||||
(cdar lst)
|
|
||||||
(loop (cdr lst))))))
|
|
||||||
|
|
||||||
;; Performs self-tests of the period module.
|
|
||||||
(define (period-tests!)
|
|
||||||
(run-tests
|
|
||||||
period
|
|
||||||
(test-equal? sort-period-markers
|
|
||||||
(sort-period-markers '((start (2023 1)) (stop (2022 10)) (start (2022 3))))
|
|
||||||
'((start (2022 3)) (stop (2022 10)) (start (2023 1))))
|
|
||||||
(test-equal? period-markers->periods
|
|
||||||
(period-markers->periods
|
|
||||||
'((start (2022 3)) (stop (2022 10)) (start (2023 1)) (stop (2023 4))))
|
|
||||||
'(#t
|
|
||||||
(((2022 3) (2022 10) #f #f)
|
|
||||||
((2023 1) (2023 4) #f #f))
|
|
||||||
""
|
|
||||||
-1))
|
|
||||||
(test-equal? period-markers->periods-open
|
|
||||||
(period-markers->periods
|
|
||||||
'((start (2022 3)) (stop (2022 10)) (start (2023 1)) (stop (2023 4)) (start (2023 5))))
|
|
||||||
'(#t
|
|
||||||
(((2022 3) (2022 10) #f #f)
|
|
||||||
((2023 1) (2023 4) #f #f)
|
|
||||||
((2023 5) #f #f #f))
|
|
||||||
""
|
|
||||||
-1))
|
|
||||||
(test-eq? period-duration
|
|
||||||
(period->duration '((2023 1) (2023 4) #f #f)) 3)
|
|
||||||
(parameterize ((*current-month* (list 2023 4)))
|
|
||||||
(test-eq? period-duration
|
|
||||||
(period->duration '((2023 1) #f #f #f)) 3))
|
|
||||||
(test-eq? periods-duration
|
|
||||||
(periods-duration '(((2022 3) (2022 10) #f #f)
|
|
||||||
((2023 1) (2023 4) #f #f)))
|
|
||||||
10)
|
|
||||||
(test-true month-in-period?
|
|
||||||
(month-in-period? '((2022 1) (2022 4) #f #f) '(2022 3)))
|
|
||||||
(test-false month-in-period?
|
|
||||||
(month-in-period? '((2022 1) (2022 4) #f #f) '(2022 5)))
|
|
||||||
(test-true month-in-periods?
|
|
||||||
(month-in-periods? '(((2022 1) (2022 4) #f #f)
|
|
||||||
((2023 5) (2023 10) #f #f))
|
|
||||||
'(2022 3)))
|
|
||||||
(test-true month-in-periods?
|
|
||||||
(month-in-periods? '(((2022 1) (2022 4) #f #f)
|
|
||||||
((2023 5) (2023 10) #f #f))
|
|
||||||
'(2023 7)))
|
|
||||||
(test-false month-in-periods?
|
|
||||||
(month-in-periods? '(((2022 1) (2022 4) #f #f)
|
|
||||||
((2023 5) (2023 10) #f #f))
|
|
||||||
'(2022 10)))
|
|
||||||
(test-equal? period->string
|
|
||||||
(period->string '((2022 1) (2022 4) #f #f))
|
|
||||||
"2022-01..2022-04")
|
|
||||||
(test-equal? periods->string
|
|
||||||
(periods->string '(((2022 1) (2022 4) #f #f)
|
|
||||||
((2022 12) (2023 2) #f #f)))
|
|
||||||
"2022-01..2022-04, 2022-12..2023-02")
|
|
||||||
(test-false periods-match (periods-match '(((2022 1) (2022 4) #f #f)
|
|
||||||
((2022 12) (2023 2) #f #f))
|
|
||||||
'(2022 5)))
|
|
||||||
(test-equal? periods-match (periods-match '(((2022 1) (2022 4) #f #f)
|
|
||||||
((2022 12) (2023 2) #f #f))
|
|
||||||
'(2022 2))
|
|
||||||
'((2022 1) (2022 4) #f #f))
|
|
||||||
))
|
|
||||||
|
|
||||||
)
|
|
|
@ -34,16 +34,16 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
(import scheme
|
(import scheme
|
||||||
period)
|
cal-period)
|
||||||
|
|
||||||
;; Convert into lookups - a list of (list period regular student)
|
;; Convert into lookups - a list of (list period regular student)
|
||||||
(define member-fees-lookup-table
|
(define member-fees-lookup-table
|
||||||
(make-period-lookup-table
|
(make-cal-period-lookup-table
|
||||||
'(((2010 1) 500 250))))
|
'(((2010 1) 500 250))))
|
||||||
|
|
||||||
;; Exchange rates
|
;; Exchange rates
|
||||||
(define exchange-rates-lookup-table
|
(define exchange-rates-lookup-table
|
||||||
(make-period-lookup-table
|
(make-cal-period-lookup-table
|
||||||
'(((2010 1) 25))))
|
'(((2010 1) 25))))
|
||||||
|
|
||||||
;; How long the member can be suspended without any action required?
|
;; How long the member can be suspended without any action required?
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue