9
9
Generate calendar of birth, death, marriage events arranged by the year, month
10
10
and day that they occurred. Generates a top level index by year, with actual
11
11
events stored in a separate html file for each decade.
12
Warning, this report requires lifelines version 3.0.27 or later.
13
12
Some properties must be set in your lifelines configuration file for this
14
13
report to run, see comments at beginning of the report for details.
15
Warning, this report requires lifelines version 3.0.50 or later.
16
17
by Stephen Dum (stephen.dum@verizon.net)
17
18
Version 1 March 2003
18
Version 2 November 2005
19
Version 2 November 2005 Support privitizing data
20
Version 3 December 2005 Do html char set encoding
21
Version 4 June 2006 incorporated mods by Dave Eaton (dwe@arde.com) May 2006
20
23
This program was inspired by similar efforts by Mitch Blank (mitch@ctrpnt.com)
21
24
but without ever seeing the code he used to do a similar thing.
26
The code used in cron.ll is very similar to anniver.ll. Other than the
27
sort order and print out details, the two programs share about 3/4 of their
23
30
Before using, there are a few properties that need to be customized for your
24
31
own environment so add them to your .linesrc ( or for windows lines.cfg) file.
32
You can also set them on the command line (like -Ianniver.htmldir=/tmp/foo)
25
33
The properties that are looked up are:
26
34
user.fullname -- name of the database owner
27
35
user.email -- email address of the db owner
28
36
cron.htmldir -- path to the directory to store results in
29
37
e.g. /home/joe/genealogy/html
30
(program expects a subdir in this directory with the name
31
of the database in it.)
32
cron.backgroundimage -- path to the background image, no image if not defined.
38
(program expects a subdir in this directory with the name
39
of the database in it.)
40
cron.backgroundimage -- path to the background image,
41
no image if not defined.
33
42
e.g. ../../image/crink.jpg
34
this places image at the same level as /home/joe/genealogy/html
43
this places image at the same level as /home/joe/genealogy/html
44
privatization: This report respects 2 levels of privatization
45
1. if a record "RESN confidential" exists on an individual they are
46
skipped (as this report is designed to be shared, this seems
47
like a reasonable default)
48
2. skip anyone estimated to be living
51
Version 2 Add code to allow respecting privatized data.
52
Version 3 switch from baptism() to get_baptism() for wider coverage
53
use translation tables to convert data to properly
54
escaped html. This is very codeset dependent.
55
Version 4 added changes by Dave Eaton (dwe@arde.com)
56
These were actually changes to anniver4, but merged here too.
57
Added "firstyear" that events may be on the calendar
58
Added "includedeath" check to drop deaths if those are not desired
59
Added ability to generate report for descendants of more than one
61
Added ability to generate report only for living people
62
(omitting confidential if desired)
37
65
/* customization globals */
38
66
char_encoding("ASCII")
39
67
option("explicitvars")
41
global(base_filename) /* where to store the results */
42
global(background) /* path of background image relative to final html
44
global(hi_bg_color) /* highlighted year background color */
45
global(lo_bg_color) /* non-highlighted year background color */
69
global(base_filename) /* where to store the results */
70
global(background) /* path of background image relative to final html
72
global(hi_bg_color) /* highlighted year background color */
73
global(lo_bg_color) /* non-highlighted year background color */
47
75
global(db_owner) /* name of database owner - from config file */
48
76
global(owner_email) /* email of database owner - from config file */
49
global(privatize) /* should we privatize the data */
77
global(justliving) /* should we generate a report only for living people? */
78
global(privatize) /* should we privatize the data
79
* 0 = display all data
80
* 1 = skip confidential records
81
* 2 = skip confidential and living
50
83
global(withkey) /* should we include key's in the output */
51
84
global(cutoff_year) /* 100 years before today */
52
85
/* birth >= cutoff_year is about 101 years,
53
* and we consider person living */
86
* and we consider person living */
88
global(firstyear) /* earliest year for which entries should be included */
89
global(includedeath) /* if set, then include the death events on the calendar */
55
91
global(month_name) /* names of the months */
56
92
global(events) /* list of events to print */
57
93
global(dates) /* list of dates of the events */
94
global(keynames) /* name(s) of the key individuals for this report */
92
129
extractdate(gettoday(),day,mon,cutoff_year)
93
130
decr(cutoff_year,100)
131
set(cs,getproperty("codeset"))
132
if (eqstr(cs,"UTF-8")) {
134
set(dstcs,"UTF-8//html")
135
} elsif (eqstr(cs,"ISO-8859-15")) {
136
set(srccs,"ISO-8859-15//html")
139
print("\nDatabase codeset ",cs," not supported, exiting\n")
95
142
/* end of initialization of globals */
97
getint(privatize,"Enter 1 to privitize data, 0 otherwise")
144
getint(justliving,"Enter 1 to include only living people, 0 otherwise")
146
/* Default the choices which conflict with "justliving" */
148
/* We want living people, so see if we also want confidental */
149
getint(noconfidential,"Enter 1 to omit confidential living people, 0 otherwise")
150
if (noconfidential) {
156
getint(privatize,"\nPrivatization: 0 print all data; 1 skip confidential records; 2 skip confidential and living")
157
getint(includedeath,"Enter 1 to include deaths on calendar, 0 otherwise")
98
159
getint(withkey,"Enter 1 to include keys, 0 otherwise")
99
getindi(person,"Enter person to find descendants of (return for all)")
160
getint(firstyear,"Enter oldest year to be on calendar, 0 for no limit")
161
getindi(person,"Enter person for whom to find descendants (return for all)")
104
168
/* if a person is entered, the generated list of people include
105
169
* person and spouse, and all the children of either
106
170
* and then recursively the people, their spouses and all the children
110
addtoset(thisgen, person, 0)
111
addtoset(allgen, person, 0)
112
print("Computing descendants ")
119
set(spouse,spouseset(thisgen))
120
set(thisgen,childset(union(thisgen,spouse)))
121
set(allgen,union(allgen,spouse))
122
set(allgen,union(allgen,thisgen))
123
set(thisgensize,lengthset(thisgen))
125
print (nl(), "Total of ",d(lengthset(allgen))," individuals",nl())
126
forindiset(allgen,indi,val,i) {
127
if (not(mod(i,100))) {
175
addtoset(thisgen, person, 0)
176
addtoset(allgen, person, 0)
177
print("Computing descendants of ", name(person), " ")
178
enqueue(keynames,concat(name(person)))
183
print("adding ",d(thisgensize)," individuals for generation ",d(gen),"\n")
185
set(spouse,spouseset(thisgen))
186
set(thisgen,childset(union(thisgen,spouse)))
187
set(allgen,union(allgen,spouse))
188
set(allgen,union(allgen,thisgen))
189
set(thisgensize,length(thisgen))
190
/* the following check prevents looping if the
191
* database has been corrupted and a parent is listed
192
* as a child of that parent, and diagnoses the fault
194
if (eq(length(intersect(allgen,thisgen)),thisgensize)) {
196
print("Warning child is listed as its own parent\n")
197
forindiset(thisgen,indi,val,i) {
198
print (name(indi)," ")
207
print ("New total of ")
209
print (d(length(allgen))," individuals",nl())
210
getindi(person,"Enter next person for whom to find descendants")
212
/* now generate list of events */
213
forindiset(allgen,indi,val,i) {
214
if (not(mod(i,100))) {
133
print("Traversing all individuals ")
221
print("Traversing all individuals ")
134
222
forindi (indi, val) {
135
if (not(mod(val,100))) {
141
print (nl(), "Total of ",d(max)," individuals",nl())
223
if (not(mod(val,100))) {
229
print (nl(), "Total of ",d(max)," individuals",nl())
143
231
print( d(length(dates))," events generated",nl())
157
245
print( d(length(dates))," events",nl())
158
246
while(length(dates)) {
159
247
set(val,pop(dates))
160
set(event,pop(events))
161
set(year,div(val,10000))
162
set(mon, mod(val,10000))
163
set(day, mod(mon,100))
164
set(mon, div(mon,100))
165
set(decade, div(year,10))
166
/* print(d(mon),"/",d(day),"/",d(year)," ", event, nl()) debug */
248
set(event,pop(events))
249
set(year,div(val,10000))
250
set(mon, mod(val,10000))
251
set(day, mod(mon,100))
252
set(mon, div(mon,100))
253
set(decade, div(year,10))
254
/* print(d(mon),"/",d(day),"/",d(year)," ", event, nl()) debug */
168
if (ne(lastdecade,decade)) {
169
if (ne(lastdecade,-1)) {
176
call openfile(concat("dec",d(decade)),concat(d(mul(decade,10)),
177
" - ",d(add(mul(decade,10),9))," Events"))
178
set(lastdecade,decade)
180
if (ne(lastyear,year)) {
184
"<p><a name=" d(year) "><h2>" d(year) "</h2></a>" nl()
192
set(title,concat(getel(month_name,mon)," ",d(day)))
194
set(title,getel(month_name,mon))
203
"<tr>\n<td width=\"150\" valign=top align=left>"
204
"<font size=4><b>" title "</b></font>\n"
205
"<td><font size=4>" event "</font></td>\n"
256
if (ne(lastdecade,decade)) {
257
if (ne(lastdecade,-1)) {
264
call openfile(concat("dec",d(decade)),concat(d(mul(decade,10)),
265
" - ",d(add(mul(decade,10),9))," Events"))
266
set(lastdecade,decade)
268
if (ne(lastyear,year)) {
272
"<p><a name=" d(year) "><h2>" d(year) "</h2></a>" nl()
280
set(title,concat(getel(month_name,mon)," ",d(day)))
282
set(title,getel(month_name,mon))
291
"<tr>\n<td width=\"150\" valign=top align=left>"
292
"<font size=4><b>" title "</b></font>\n"
295
convertcode(event,srccs,dstcs)
210
304
call write_tail()
225
319
set(minyear,getel(yearmask,1))
226
320
set(maxyear,getel(yearmask,0))
227
321
forlist(yearmask,this_year,cnt) {
228
while(le(cur_year,this_year)) {
229
if (eq(mod(cur_year,10),0)) {
230
/* print("processing decade ",d(decade),nl()) / * debug */
233
if (eq(cur_year,this_year)) {
234
/* print year with a link to year page */
235
"<td bgcolor=" hi_bg_color
236
" align=center><font size=4><a href=\""
322
while(le(cur_year,this_year)) {
323
if (eq(mod(cur_year,10),0)) {
324
/* print("processing decade ",d(decade),nl()) / * debug */
327
if (eq(cur_year,this_year)) {
328
/* print year with a link to year page */
329
"<td bgcolor=" hi_bg_color
330
" align=center><font size=4><a href=\""
237
331
"dec" d(decade) ".html#" d(cur_year) "\">"
238
d(cur_year) "</a>\n</font></td>\n"
240
if (or(lt(cur_year,minyear),gt(cur_year,maxyear))) {
242
"<td bgcolor=" lo_bg_color
243
" align=center><font size=4></font></td>" nl()
245
/* print year without a link to year page */
246
"<td bgcolor=" lo_bg_color
332
d(cur_year) "</a>\n</font></td>\n"
334
if (or(lt(cur_year,minyear),gt(cur_year,maxyear))) {
336
"<td bgcolor=" lo_bg_color
337
" align=center><font size=4></font></td>" nl()
339
/* print year without a link to year page */
340
"<td bgcolor=" lo_bg_color
247
341
" align=center><font size=4>" d(cur_year) "</font></td>" nl()
251
if (eq(mod(cur_year,10),0)) {
345
if (eq(mod(cur_year,10),0)) {
312
407
proc add_indi(indi) {
313
408
set(birth_type,0)
314
409
if (birth,birth(indi)) {
315
set(birth,get_date(birth))
316
set(birth_type," born")
317
} elsif (birth, baptism(indi)) {
318
set(birth,get_date(birth))
319
set(birth_type," baptized")
410
set(birth,get_date(birth))
411
set(birth_type," born")
412
} elsif (birth, get_baptism(indi)) {
413
set(birth,get_date(birth))
414
set(birth_type," baptized")
321
416
set(death_type,0)
322
417
if (death,death(indi)) {
323
set(death,get_date(death))
324
set(death_type," died")
418
set(death,get_date(death))
419
set(death_type," died")
325
420
} elsif (death, burial(indi)) {
326
set(death,get_date(death))
421
set(death,get_date(death))
327
422
set(death_type," buried")
424
/* skip confidential records and living people */
330
/* skip confidential or living people */
331
if (confidential(indi)) { return() }
332
/* living - birth, no death, and birth < 101 years ago */
333
if (and(birth,not(death))) {
334
if (ge(div(birth,10000),cutoff_year)) { return()}
426
if (confidential(indi)) { return() }
428
/* living - birth, no death, and birth < 101 years ago */
429
if (and(ge(privatize,2),birth,not(death))) {
430
if (ge(div(birth,10000),cutoff_year)) { return()}
339
enqueue(events,concat(name(indi),"(",key(indi),")",birth_type))
341
enqueue(events,concat(name(indi),birth_type))
434
/* Make certain that if we only want living people that this is
435
(or at least may be) */
436
if (not(or(and(justliving,death),and(justliving,lt(mod(birth,10000),cutoff_year))))) {
438
enqueue(events,concat(name(indi),"(",key(indi),")",birth_type))
440
enqueue(events,concat(name(indi),birth_type))
347
enqueue(events,concat(name(indi),"(",key(indi),")",death_type))
349
enqueue(events,concat(name(indi),death_type))
445
if (and(includedeath,death)) {
447
enqueue(events,concat(name(indi),"(",key(indi),")",death_type))
449
enqueue(events,concat(name(indi),death_type))
354
454
families(indi,famly, spouse, cnt) {
356
/* skip confidential families */
357
if (confidential(famly)) { return() }
359
/* to avoid duplication, only enter data
360
* if indi is male, or there is no spouse
362
if (or(male(indi),not(spouse))) {
363
fornodes(fnode(famly), node) {
364
if(eqstr(tag(node),"MARR")) {
366
set(spo,concat(" and ",name(spouse)," married"))
370
set(marr,get_date(node))
373
enqueue(events,concat(name(indi),spo,
374
"(",key(indi),",",key(spouse),")"))
376
enqueue(events,concat(name(indi),spo))
455
/* skip confidential families */
456
if (confidential(famly)) { continue() }
457
if (and(privatize,spouse)) {
458
if (confidential(spouse)) { continue() }
461
/* make sure the person is living: no death, birth and
462
birth < 101 years ago */
463
/* Nope, we know they have died */
464
if (death) { return() }
466
/* Nope, estimated they would be too old now */
467
if (lt(mod(birth,10000),cutoff_year)) { return() }
470
/* living - birth, no death, and birth < 101 years ago */
471
if (ge(privatize,2)) {
472
if (and(birth(spouse),not(death(spouse)))) {
473
if (ge(mod(get_date(birth(spouse)),10000),cutoff_year)) { continue()}
476
/* to avoid duplication, only enter data
477
* if indi is male, or there is no spouse
479
if (or(male(indi),not(spouse))) {
480
fornodes(fnode(famly), node) {
481
if(eqstr(tag(node),"MARR")) {
483
set(names,concat(name(indi)," and ",name(spouse)))
484
set(keys,concat("(",key(indi),",",key(spouse),")"))
486
set(names,name(indi))
487
set(keys,concat("(",key(indi),")"))
489
set(marr,get_date(node))
491
/* Make sure date is plausible for living or that we don't care */
492
if (or(not(justliving),ge(mod(marr,10000),cutoff_year))) {
494
enqueue(events,concat(names,keys," married"))
496
enqueue(events,concat(names," married"))