| 1 |
(in-package :bos.m2) |
|---|
| 2 |
|
|---|
| 3 |
(defvar *include-database-id* t) |
|---|
| 4 |
|
|---|
| 5 |
(defun universal-to-iso (timestamp) |
|---|
| 6 |
(multiple-value-bind (second minute hour date month year) |
|---|
| 7 |
(decode-universal-time timestamp 0) |
|---|
| 8 |
(format nil |
|---|
| 9 |
"~D-~2,'0D-~2,'0D ~2,'0D:~2,'0D:~2,'0D" |
|---|
| 10 |
year month date hour minute second))) |
|---|
| 11 |
|
|---|
| 12 |
(defun m2< (a b) |
|---|
| 13 |
(or (< (m2-x a) (m2-x b)) |
|---|
| 14 |
(and (= (m2-x a) (m2-x b)) |
|---|
| 15 |
(< (m2-y a) (m2-y b))))) |
|---|
| 16 |
|
|---|
| 17 |
(defun contract< (a b) |
|---|
| 18 |
(or (sponsor< (contract-sponsor a) (contract-sponsor b)) |
|---|
| 19 |
(and (eq (contract-sponsor a) (contract-sponsor b)) |
|---|
| 20 |
(or (< (contract-date a) (contract-date b)) |
|---|
| 21 |
(and (eql (contract-date a) (contract-date b)) |
|---|
| 22 |
(< (store-object-id a) (store-object-id b))))))) |
|---|
| 23 |
|
|---|
| 24 |
(defun sponsor< (a b) |
|---|
| 25 |
(etypecase (user-login a) |
|---|
| 26 |
(string (string< (user-login a) (user-login b))) |
|---|
| 27 |
(number (< (user-login a) (user-login b))))) |
|---|
| 28 |
|
|---|
| 29 |
(defun area< (a b) |
|---|
| 30 |
(< (store-object-id a) (store-object-id b))) |
|---|
| 31 |
|
|---|
| 32 |
(defun export-m2 (m2) |
|---|
| 33 |
(with-element "m2" |
|---|
| 34 |
(attribute "utm-x" (write-to-string (m2-utm-x m2))) |
|---|
| 35 |
(attribute "utm-y" (write-to-string (m2-utm-y m2))) |
|---|
| 36 |
(attribute "x" (write-to-string (m2-x m2))) |
|---|
| 37 |
(attribute "y" (write-to-string (m2-y m2))) |
|---|
| 38 |
(attribute "sqm-num" (write-to-string (m2-num m2))))) |
|---|
| 39 |
|
|---|
| 40 |
(defun map-sorted (fn predicate sequence) |
|---|
| 41 |
(map nil fn (sort (copy-seq sequence) predicate))) |
|---|
| 42 |
|
|---|
| 43 |
(defun vertex< (a b) |
|---|
| 44 |
(or (< (car a) (car b)) |
|---|
| 45 |
(and (= (car a) (car b)) |
|---|
| 46 |
(< (cdr a) (cdr b))))) |
|---|
| 47 |
|
|---|
| 48 |
(defun export-contract (contract) |
|---|
| 49 |
(with-element "contract" |
|---|
| 50 |
(when *include-database-id* |
|---|
| 51 |
(attribute "database-id" (write-to-string (store-object-id contract)))) |
|---|
| 52 |
(attribute "date" (universal-to-iso (contract-date contract))) |
|---|
| 53 |
(map-sorted #'export-m2 #'m2< (contract-m2s contract)))) |
|---|
| 54 |
|
|---|
| 55 |
(defun export-point (x y) |
|---|
| 56 |
(with-element "point" |
|---|
| 57 |
(attribute "x" (write-to-string x)) |
|---|
| 58 |
(attribute "y" (write-to-string y)))) |
|---|
| 59 |
|
|---|
| 60 |
(defun export-rectangle (left top width height) |
|---|
| 61 |
(with-element "rectangle" |
|---|
| 62 |
(attribute "left" (write-to-string left)) |
|---|
| 63 |
(attribute "top" (write-to-string top)) |
|---|
| 64 |
(attribute "width" (write-to-string width)) |
|---|
| 65 |
(attribute "height" (write-to-string height)))) |
|---|
| 66 |
|
|---|
| 67 |
(defun export-area (area) |
|---|
| 68 |
(with-slots (left top width height active-p y vertices) area |
|---|
| 69 |
(with-element "allocation-area" |
|---|
| 70 |
(attribute "active" (if active-p "yes" "no")) |
|---|
| 71 |
(attribute "y" (write-to-string y)) |
|---|
| 72 |
(with-element "polygon" |
|---|
| 73 |
(map nil |
|---|
| 74 |
(lambda (vertex) |
|---|
| 75 |
(export-point (car vertex) (cdr vertex))) |
|---|
| 76 |
vertices))))) |
|---|
| 77 |
|
|---|
| 78 |
(defun export-sponsor (sponsor) |
|---|
| 79 |
(with-element "sponsor" |
|---|
| 80 |
(when *include-database-id* |
|---|
| 81 |
(attribute "database-id" (write-to-string (store-object-id sponsor)))) |
|---|
| 82 |
(flet ((attr (name accessor) |
|---|
| 83 |
(let ((value (funcall accessor sponsor))) |
|---|
| 84 |
(unless (and (typep value 'sequence) (zerop (length value))) |
|---|
| 85 |
(attribute name (write-to-string value :escape nil)))))) |
|---|
| 86 |
(attr "profile-id" #'user-login) |
|---|
| 87 |
(attr "password" #'user-password) |
|---|
| 88 |
(attr "full-name" #'user-full-name) |
|---|
| 89 |
(attr "email-address" #'user-email) |
|---|
| 90 |
(attr "info-text" #'sponsor-info-text) |
|---|
| 91 |
(attr "country" #'sponsor-country)) |
|---|
| 92 |
(map-sorted #'export-contract #'contract< (sponsor-contracts sponsor)))) |
|---|
| 93 |
|
|---|
| 94 |
(defun export-database (pathname |
|---|
| 95 |
&key (indentation 2) |
|---|
| 96 |
(include-database-id *include-database-id*)) |
|---|
| 97 |
(with-open-file (target-stream |
|---|
| 98 |
pathname |
|---|
| 99 |
:direction :output |
|---|
| 100 |
:element-type '(unsigned-byte 8) |
|---|
| 101 |
:if-exists :supersede |
|---|
| 102 |
:if-does-not-exist :create) |
|---|
| 103 |
(with-xml-output (make-octet-stream-sink |
|---|
| 104 |
target-stream |
|---|
| 105 |
:canonical nil |
|---|
| 106 |
:indentation indentation) |
|---|
| 107 |
(let ((*include-database-id* include-database-id)) |
|---|
| 108 |
(with-element "bos" |
|---|
| 109 |
(attribute "date" (universal-to-iso (get-universal-time))) |
|---|
| 110 |
(with-element "sponsors" |
|---|
| 111 |
(map-sorted #'export-sponsor #'sponsor< |
|---|
| 112 |
(store-objects-with-class 'sponsor))) |
|---|
| 113 |
(with-element "allocation-areas" |
|---|
| 114 |
(map-sorted #'export-area #'area< |
|---|
| 115 |
(store-objects-with-class 'allocation-area)))))) |
|---|
| 116 |
(pathname target-stream))) |
|---|