family-tree-new.lisp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. ;;;; family-tree-new.lisp
  2. (in-package #:genie)
  3. ;;; "family-tree-new" goes here. Hacks and glory await!
  4. ;;; Generate Edges between people
  5. (defun generate-people-edges (person)
  6. (let* ((birth (get-birth person))
  7. (mother (:/mother birth))
  8. (father (:/father birth)))
  9. (cond
  10. ((and (= 0 father)
  11. (= 0 mother))
  12. nil)
  13. ((= 0 father)
  14. (list :mother-child mother person))
  15. ((= 0 mother)
  16. (list :father-child father person))
  17. (t
  18. (let ((marriage (get-marriage father mother)))
  19. (if (null marriage)
  20. (list :both-to-child father mother person)
  21. (list :marriage-child (:/marriage-id marriage) person)))))))
  22. ;;; Generate edges for a marriage
  23. (defun generate-wedding-edges (marriage)
  24. (let* ((marriage (get-marriage-id marriage))
  25. (husband (:/husband marriage))
  26. (wife (:/wife marriage)))
  27. (list :marriage marriage husband wife)))
  28. ;;; Generate Node statement
  29. (defun generate-node-statement (type id)
  30. (case type
  31. (:marriage
  32. (let* ((marriage (get-marriage-id id))
  33. (start (:/wedding-date marriage))
  34. (end (:/end-date marriage))
  35. (divorce (get-divorce id)))
  36. (cond
  37. ((and (null divorce)
  38. (string= "0" end))
  39. (format nil
  40. "marriage_~a [label = \"Married ~a — Current\", shape = invtrapezium];"
  41. id
  42. start))
  43. ((null divorce)
  44. (format nil
  45. "marriage_~a [label = \"Married ~a — ~a\", shape = invtrapezium];"
  46. id
  47. start
  48. end))
  49. (t
  50. (format nil
  51. "marriage_~a [label = \"Married ~a — Div. ~a\", shape = invtrapezium];"
  52. id
  53. start
  54. end)))))
  55. (:person
  56. (let* ((person (get-person id))
  57. (name (:/person-name person))
  58. (color (if (string= (:/gender person) "M") "blue" "pink"))
  59. (birth (get-birth id))
  60. (date (:/birth-date birth))
  61. (death (get-death id)))
  62. (if (null death)
  63. (format nil
  64. "person_~a [label \"~a\\n~a — Living\", shape = rectangle, color = ~a];"
  65. id
  66. name
  67. date
  68. color)
  69. (format nil
  70. "person_~a [label \"~a\\n~a — ~a\", shape = rectangle, color = ~a];"
  71. id
  72. name
  73. date
  74. (:/death-date death)
  75. color))))))
  76. ;;; generate correct edge statement
  77. (defun generate-edge-statement (edge)
  78. (let ((type (first edge)))
  79. (case type
  80. (:mother-child
  81. (format nil "person_~a -> person_~a;"
  82. (second edge)
  83. (third edge)))
  84. (:father-child
  85. (format nil "person_~a -> person_~a;"
  86. (second edge)
  87. (third edge)))
  88. (:both-to-child
  89. (format nil "{person_~a, person_~a} -> person_~a;"
  90. (second edge)
  91. (third edge)
  92. (fourth edge)))
  93. (:marriage-child
  94. (format nil "marriage_~a -> person_~a;"
  95. (second edge)
  96. (third edge)))
  97. (:marriage
  98. (format nil "{person_~a, person_~a} -> marriage_~a;"
  99. (third edge)
  100. (fourth edge)
  101. (second edge)))
  102. (t
  103. nil))))
  104. ;;; Generate edge list
  105. (defun generate-complete-edge-list ()
  106. (let ((people-edges (iter (for i from 1 to (length (select :people)))
  107. (collect (generate-people-edges i))))
  108. (weddings (iter (for i from 1 to (length (select :marriages)))
  109. (collect (generate-marriage-edges i)))))
  110. (list weddings people-edges)))
  111. ;;; generate dot file
  112. (defun generate-dot-file (file-name)
  113. (let* ((edge-list (generate-complete-edge-list))
  114. (weddings (first edge-list))
  115. (people (second edge-list))
  116. (wedding-nodes (iter (for i from 1 to (length (select :marriags)))
  117. (collect (generate-node-statement :marriage i))))
  118. (people-nodes (iter (for i from 1 to (length (select :people)))
  119. (collect (generate-node-statement :person i))))
  120. (people-edges (map 'list #'generate-edge-statement people))
  121. (wedding-edges (map 'list #'generate-edge-statement weddings)))
  122. (with-open-file (output file-name
  123. :direction :output
  124. :if-exists :supersede
  125. :if-does-not-exist :create)
  126. (format output
  127. "digraph {
  128. ~@{ ~a~^~&~}
  129. ~@{ ~a~^~&~}
  130. ~@{ ~a~^~&~}
  131. ~@{ ~a~^~&~}
  132. }"
  133. people-nodes
  134. wedding-nodes
  135. wedding-edges
  136. people-edges))))