5 from string import Template
9 link_Template= Template(\
10 "<a href = http://www.chiark.greenend.org.uk/ucgi/~naath/$script"\
11 +" title=$title>$text</a>")
20 def print_row(row,newLine):
23 out = out + str(item)+'|'
24 return out[:-1] + newLine
26 def print_query(s,t,newLine):
28 for row in run_query(s,t):
29 printMe = printMe + print_row(row,newLine)
39 def print_tagged_query(relationship,s,t,newLine):
41 for row in run_query(s,t):
42 mine = mine + print_tagged_name(relationship,row,newLine)
46 def relationship_html(ID,ID2,newLine):
48 relationship = common_ancestors(ID,ID2,newLine)[2]
50 if relationship[-11:] != 'not related':
51 script = "ancestors.py?ID="+str(ID)+"&ID2="+str(ID2)
52 url = link_Template.substitute\
53 (script = script,title = "Common ancestors"\
54 ,text = "Common ancestors")
55 return relationship + ' '+url + newLine
57 return relationship + newLine
61 def terr_html(terr,newLine,start,stop):
63 if start == 0 and stop ==0:
64 myTitle = add_quotes(terr)
67 s = "SELECT name,people.id"\
68 +" FROM people INNER JOIN territories"\
69 +" ON people.id = territories.id"\
70 +" WHERE territory = ? AND stopyear <= ?"\
71 +" ORDER BY startyear DESC;"
75 for row in run_query(s,t):
76 myTitle = myTitle +"previous - " + row[0] \
80 u = "SELECT name,people.id"\
81 +" FROM people INNER JOIN territories"\
82 +" ON people.id = territories.id"\
83 +" WHERE territory = ? AND startyear >= ?"\
84 +" ORDER BY startyear;"
87 for r in run_query(u,v):
88 myTitle = myTitle + '
' +"next - " + r[0] \
92 myTitle = add_quotes(myTitle)
94 return link_Template.substitute(\
95 script = "territory.py?terr="+terr, title=myTitle,\
99 def name_html(row,html):
111 script = "person.py?ID=" + str(row[1])
113 return link_Template.substitute(script = script\
114 ,title = add_quotes(name),text = name)
116 return row[0] + "," +str(row[1])
124 def print_age_child_count(row,newLine):
125 if newLine == '<br>':
126 script = "age.py?age="+str(row[0])
127 link = link_Template.substitute(script = \
128 script, title = add_quotes(row[0]), text = row[0])
129 out = str(row[1])+print_people(row[1])
131 out = out + 'had children at age '+ link + newLine
134 return print_row(row,newLine)
136 def print_age_death_count(row,newLine):
138 script = "ageDeath.py?age="+str(row[0])
139 link = link_Template.substitute(script = script,\
140 title = add_quotes(row[0]),text = row[0])
141 out = str(row[1])+print_people(row[1])
142 out = out + "died at age " + link + newLine
145 return print_row(row,newLine)
147 def print_name_count(row,newLine):
149 script = "name.py?name=" + row[0]
150 link = link_Template.substitute(script =\
151 script, title = add_quotes(row[0]),text = row[0])
152 return str(row[1]) + " people called "+link + newLine
154 return print_row(row,newLine)
156 def print_tagged_name(relationship,row,newLine):
158 out = relationship + " not yet entered: " + row[1]
160 if newLine == '<br>':
164 if relationship =='':
165 out = name_html(row,html) + ' '
167 out = relationship + ": " + name_html(row,html)
170 def month_numbers(monthN):
172 month ='unknown month'
198 month = 'Incorrectly entered month ' + str(monthN)
201 def ordinal_numbers(number):
203 if number % 10==1 and number/10 % 10 !=1:
204 out = str(number) +'st'
205 elif number % 10==2 and number/10 % 10 !=1:
206 out = str(number) +'nd'
207 elif number % 10==3 and number/10 % 10 !=1:
208 out = str(number) +'rd'
210 out = str(number) +'th'
213 def list_territories(newLine):
214 s = "SELECT DISTINCT territory"\
215 +" FROM territories"\
216 +" ORDER BY territory;"
219 for row in run_query(s,()):
220 out =out + terr_html(row[0],newLine,0,0) +newLine
223 def list_people_parents():
224 s = "SELECT name,id"\
229 for row in run_query(s,()):
232 [parents, parentIDs,parentNames] = find_parents(ID)
233 [spouses,spousesID,spousesNames] = find_spouses(ID)
235 [self,myID,myName] = find_person(ID)
236 output.append([self,parents,spouses])
240 def list_people(newLine):
241 s = "SELECT name,id,bornyear"\
243 +" ORDER BY bornyear;"
247 out = out + 'born in unknown year:' +newLine
248 for row in run_query(s,()):
249 if row[2]!=0 and row[2]/100==0:
250 out = out +newLine+ 'born in 1st century:' +newLine
252 if row[2]/100!=year/100:
253 century = row[2]/100 + 1
254 out = out +newLine+ 'born in '
256 out = out +ordinal_numbers(century) \
257 + ' century:' + newLine
259 out = out + name_html(row,newLine) +newLine
261 if row[2] == 0: #unknown year
263 t = (row[1],) #person ID
267 u = "SELECT diedyear FROM people WHERE ID = ?;"
270 for r in run_query(u,t):
272 out = out + "died: "\
273 + str(r[0]) + newLine
274 bornAfter = r[0] -100
277 u = "Select people.bornYear from"\
278 +" people INNER JOIN parents"\
279 +" ON people.ID = parents.ID"\
280 +" WHERE parents.parentID = ?"\
281 + " ORDER BY people.bornYear;"
285 for r in run_query(u,t):
287 hadChild.append(r[0])
291 out = out + "had children in: "
293 out = out + str(c) + ','
294 out = out[:-1] + newLine
296 bornBefore = hadChild[0]-12
298 bornAfter = hadChild[0]-100
300 u = "Select styles.startYear, styles.style from"\
301 +" people INNER JOIN styles"\
302 +" ON people.ID = styles.ID"\
303 +" WHERE people.ID = ? and"\
304 +" styles.startYear <>0"\
305 +" ORDER BY styles.startYear;"
307 for r in run_query(u,t):
308 out = out + r[1] + " from " + str(r[0])\
311 bornAfter = r[0] -100
316 out = out + "probably born "\
317 +"after " + str(bornAfter)
319 out = out + "probably born "\
320 +"betwen " + str(bornAfter)\
321 +" and " + str(bornBefore)
327 def count_names(newLine):
328 s = "SELECT firstName, count(*)"\
330 +" GROUP BY firstName"\
331 +" ORDER BY count(*) DESC;"
334 for row in run_query(s,()):
335 out = out + print_name_count(row,newLine)
340 def search_name(name,newLine):
341 s = "SELECT name, ID"\
343 +" WHERE name LIKE ?;"
349 out = out + 'Names starting with ' + name + ':' + newLine
352 for row in run_query(s,t):
353 out = out + name_html(row,newLine) + newLine
354 fullIDs.append(row[1])
358 t = ('%' + name + '%',)
359 out = out+newLine + 'Names containing ' + name + ':' + newLine
360 for row in run_query(s,t):
361 if row[1] not in fullIDs:
362 out = out + name_html(row,newLine) + newLine
366 s = "SELECT name,people.ID,style"\
367 +" FROM people INNER JOIN styles"\
368 +" ON styles.id = people.id"\
369 +" WHERE style LIKE ?;"
370 out = out +newLine+ 'Styles containing ' + name + ':' + newLine
371 for row in run_query(s,t):
372 out = out + name_html(row,newLine)+' ' + row[2] + newLine
374 return [out,names,IDs]
377 def people_with_name(name,newLine):
378 s = "SELECT name, ID"\
380 +" WHERE firstname = ?;"
386 for row in run_query(s,t):
387 out = out + name_html(row,newLine) + newLine
391 def count_birth_month(newLine):
392 s = "SELECT bornMonth, count(*)"\
394 +" GROUP BY bornMonth"\
395 +" ORDER BY bornMonth;"
397 t = "SELECT * FROM people WHERE bornMonth = ?;"
400 for row in run_query(s,()):
401 month = month_numbers(row[0])
402 out = out + month + ': ' + str(row[1]) + newLine
406 out = out +print_query(t,u,newLine)
410 def count_death_month(newLine):
411 s = "SELECT diedMonth, count(*)"\
413 +" GROUP BY diedMonth"\
414 +" ORDER BY diedMonth;"
416 t = "SELECT * FROM people WHERE diedMonth = ?;"
419 for row in run_query(s,()):
420 month = month_numbers(row[0])
421 out = out + month + ': ' + str(row[1]) + newLine
425 out = out +print_query(t,u,newLine)
429 def count_age_at_child(newLine):
431 s = "select p1.bornYear - p2.bornYear as age, count(*)"\
433 +" parents INNER JOIN people p1"\
434 +" ON parents.ID = p1.ID"\
435 +" INNER JOIN people p2"\
436 +" ON parents.parentID = p2.ID"\
437 +" WHERE p1.bornYear <> 0 and p2.bornYear<>0"\
441 for row in run_query(s,()):
442 out = out + print_age_child_count(row,newLine)
446 def people_had_child_at_age(age,newLine):
448 s = "select p1.bornYear - p2.bornYear as age, p1.name, p1.ID"\
449 +",p2.name,p2.ID FROM"\
450 +" parents INNER JOIN people p1"\
451 +" ON parents.ID = p1.ID"\
452 +" INNER JOIN people p2"\
453 +" ON parents.parentID = p2.ID"\
454 +" WHERE age = ? AND p1.bornYear<>0 AND p2.bornYear<>0"
459 out = 'At age ' + str(age) + ' :'
460 for row in run_query(s,t):
462 out =out + name_html([row[3],row[4]],newLine) + ' had '\
463 +name_html([row[1],row[2]],newLine)
467 def count_age_at_death(newLine):
468 s = "select diedYear-bornYear as age,count(*)"\
470 +" WHERE diedYear<>0 AND bornYear<>0"\
473 for row in run_query(s,()):
474 out = out + print_age_death_count(row,newLine)
477 def people_died_at_age(age,newLine):
478 s = "SELECT diedYear-bornYear as age, name,ID"\
480 +" WHERE age = ? AND bornYear<>0 AND diedYear<>0;"
483 out = 'These people died at age ' +str(age) + ' :'
484 for row in run_query(s,t):
486 out = out + name_html([row[1],row[2]],newLine)
489 def all_ancestors(personID,newLine):
492 ancestors = [personID]
493 allAncestors = [personID]
497 t = "SELECT name,id FROM people WHERE id=?"
500 out = "Ancestors of "
501 for row in run_query(t,id):
502 out = out + name_html(row,newLine)+newLine
504 while len(ancestors)>0:
507 thisout = newLine + parent_level(level,'parent') +\
509 for ancestor in ancestors:
510 [parents, parentIDs,parentNames] \
511 = find_parents(ancestor)
512 for i in range(len(parents)):
513 r = [parentNames[i],parentIDs[i]]
514 thisout = thisout + \
515 name_html(r,newLine)+newLine
517 if r[1] not in allAncestors\
520 allAncestors.append(r[1])
521 trackLevel.append(level)
527 image = "<img src = ancestorGraph.py?id="+str(personID)+">"
528 out = out+newLine + image+newLine
529 return [out, allAncestors,trackLevel]
532 def common_ancestors(IDA, IDB,newLine):
533 out = 'Common ancestors of:' + newLine
535 s = "SELECT name,id FROM people WHERE id==?"
541 for row in run_query(s,t):
542 out = out + name_html(row,newLine)+newLine
549 related = 'No details held on one party'
551 return [out,[],related]
554 a = all_ancestors(IDA,newLine)
555 b = all_ancestors(IDB,newLine)
557 ancestorsB = set(b[1])
558 ancestorsA = set(a[1])
560 common = ancestorsA.intersection(ancestorsB)
561 common = list(common)
568 aLevels.append(a[2][i])
570 bLevels.append(b[2][i])
572 s = "SELECT Name, ID, bornyear"\
575 for i in range(len(common)):
579 s = s+") ORDER BY bornyear;"
583 related = names[0]+' and '+names[1]+' are not related'
584 out = out + newLine + related
585 return [out, common,related]
588 out = out + print_tagged_query('',s,common,newLine)
593 for i in range(len(common)):
594 if aLevels[i] == min(aLevels):
596 if bLevels[i] == min(bLevels):
601 s = "SELECT name, id"\
605 out = out + newLine + 'Most Recent Common Ancestors:' + newLine
609 mrca.append(common[a])
610 out = out + print_tagged_query('',s,t,newLine)
612 out = out + 'and' + newLine
614 out = out + parent_level(aLevels[indexA[0]],'parent')
618 out = out + ' of ' + name_html([names[0],IDA],newLine)+newLine
620 out = out + parent_level(bLevels[indexB[0]],'parent')
623 out = out + ' of ' + name_html([names[1],IDB],newLine)+newLine
626 al = aLevels[indexA[0]]
627 bl = bLevels[indexB[0]]
629 related = relationship(al,bl,names)
630 out = out+newLine + related
633 image = "<img src = jointAncestorGraph.py?id="+str(IDA)\
634 +"&id2="+str(IDB) + "&LA=" + str(min(aLevels)) \
635 +"&LB=" + str(min(bLevels))+">"
639 out = out+newLine + image+newLine
641 return [out,common,related]
643 def relationship(level1, level2,names):
645 if level1==0 and level2==0:
646 return names[0] + ' is ' +names[1]
648 return names[0] + ' is ' + names[1] + '\'s '+ parent_level(level2,'parent')
650 return names[1] + ' is ' + names[0] + '\'s '+ parent_level(level1,'parent')
654 remove = level1-level2
657 remove = level2-level1
661 uaLevel = parent_level(remove,'uncle or aunt')
663 return names[0] + ' is ' + names[1] + '\'s ' + uaLevel
666 return names[1] + ' is ' + names[0] + '\'s ' + uaLevel
668 c=ordinal_numbers(cousinNum)
674 rem = str(remove) + ' times'
676 r = names[0] +' and '+names[1] +' are ' + c + ' cousins '
678 r = r+ rem + ' removed'
682 def parent_level(level,type):
697 for i in range(2,level):
701 def rulers_of(aTerritory,newLine):
703 tq = "SELECT name, people.ID, startyear,stopyear,territory"\
704 +" FROM territories INNER JOIN people"\
705 +" ON people.ID = territories.ID"\
706 +" WHERE territory LIKE ?"\
707 +" ORDER BY territory,startyear,stopyear;"
714 for row in run_query(tq,(aTerritory+'%',)):
715 if row[4]!=last and last!='':
716 out = out + 'Rulers of '+terr_html(last,newLine,0,0) \
717 +':'+ newLine +thisT +newLine
720 thisT = thisT +name_html(row,newLine)
721 thisT = thisT +' from ' + str(row[2])+' to '+str(row[3]) + newLine
724 out = out + 'Rulers of '+terr_html(row[4],newLine,0,0) +':'+ \
730 s = "SELECT name || ','||ID, name, ID FROM people WHERE ID=?"
733 for row in run_query(s,t):
737 return [Self, selfID,selfName]
739 def find_parents(ID):
740 s = "SELECT name, parentID"\
741 +" FROM parents LEFT JOIN people"\
742 +" ON people.ID = parentID"\
743 +" WHERE parents.ID = ?;"
750 for row in run_query(s,t):
752 p = row[0] + ',' + str(row[1])
756 p = row[1] + ',p ' + str(ID)
760 parentIDs.append(pID)
761 parentNames.append(pN)
763 if parents[1]==parents[0]:
764 parents[1] = parents[1] + ' 2'
766 return [parents,parentIDs,parentNames]
768 def find_spouses(ID):
771 order = [["IDb","IDa"],["IDa","IDb"]]
777 s = "SELECT name, marriages." + o[0]\
778 +" FROM marriages LEFT JOIN people"\
779 +" ON marriages." +o[0]+" = people.ID"\
780 +" WHERE marriages."+o[1]+" = ?;"
783 for row in run_query(s,t):
785 s = row[0] + "," +str(row[1])
789 s=row[1] + ",s " +str(ID)
794 spousesID.append(sID)
795 spousesNames.append(sN)
797 return [spouses,spousesID,spousesNames]
800 def find_children(ID):
801 s = "SELECT p1.name, p1.ID,p3.parentID,p4.name,p1.bornYear"\
803 +" INNER JOIN parents p2"\
804 +" ON p1.ID = p2.ID"\
805 +" INNER JOIN parents p3"\
806 +" ON p1.ID = p3.ID"\
807 +" LEFT JOIN people"\
808 +" p4 ON p3.parentID = p4.ID"\
809 +" WHERE p2.parentID = ?"\
810 +" AND p3.parentID<>?"\
811 +" ORDER BY p1.bornYear;"
820 for row in run_query(s,t):
821 c = row[0] + ',' + str(row[1])
825 childrenBorn.append(born)
827 op = row[3] + ',' + str(row[2])
831 op = row[2] + ',s ' + str(ID)
836 IDs.append([cID,opID])
837 names.append([cName,opN])
839 return [nodes,IDs,names,childrenBorn]
841 def person_info(personID,newLine):
852 #Id, Name, Dates, Style, Style-Dates
853 s = "SELECT * FROM people WHERE ID = ?"
854 for row in run_query(s,t):
855 mainDiv = mainDiv + startP
856 mainDiv = mainDiv + 'ID: '+str(row[0]) +newLine
857 mainDiv = mainDiv + print_tagged_name('Name',[row[1], row[0]]\
859 mainDiv = mainDiv + endP
864 mainDiv = mainDiv + startP
865 mainDiv = mainDiv + newLine + 'Born: '+row[3] + newLine
867 mainDiv = mainDiv + 'Died: '+row[5]
869 if row[6] != 0 and row[4] !=0:
870 mainDiv = mainDiv + ", aged " \
872 mainDiv = mainDiv + endP
875 s = "SELECT * FROM styles WHERE ID = ?"
876 for row in run_query(s,t):
877 mainDiv = mainDiv + startP
878 mainDiv = mainDiv +newLine+ 'Style: '+row[1] + newLine
880 mainDiv = mainDiv + 'Territories:' + newLine
882 u = "SELECT * FROM territories"\
883 +" WHERE ID =? AND startYear =? AND stopYear=?"
884 v=(personID,row[3],row[5])
887 for r in run_query(u,v):
889 + terr_html(r[1],newLine,r[3],r[5])\
893 mainDiv = mainDiv[:-1] + newLine
895 mainDiv = mainDiv + 'From: '+row[2] + newLine
896 mainDiv = mainDiv + 'To: '+row[4]
898 mainDiv = mainDiv + endP
903 mainDiv = mainDiv + startP
904 s = "SELECT people.Name,consort "\
905 +"FROM consorts LEFT JOIN people"\
906 +" ON people.ID = consorts.consort"\
907 +" WHERE consorts.ID = ?"
908 for row in run_query(s,t):
909 mainDiv = mainDiv + print_tagged_name\
910 ('Consort of',row,newLine)
911 mainDiv = mainDiv + endP
915 [parents,parentIDs,parentNames] = find_parents(personID)
916 mainDiv = mainDiv + startP
917 for i in range(len(parents)):
918 r = [parentNames[i],parentIDs[i]]
919 mainDiv = mainDiv + print_tagged_name('Parent',r,newLine)
920 mainDiv = mainDiv + endP
924 [spouses,spousesID,spousesNames] = find_spouses(personID)
926 mainDiv = mainDiv + startP
928 for i in range(len(spouses)):
929 r = [spousesNames[i],spousesID[i]]
930 mainDiv = mainDiv + print_tagged_name('Spouse',r,newLine)
931 mainDiv = mainDiv + \
932 relationship_html(personID,r[1],newLine)
934 mainDiv = mainDiv + endP
937 [nodes,IDs,names,childrenBorn] = \
938 find_children(personID)
941 for i in range(len(nodes)):
942 cr = [names[i][0],IDs[i][0]]
943 thisChild = print_tagged_name('Child',cr,newLine)
945 opr=[names[i][1],IDs[i][1]]
947 if i==0 or top != names[i-1][1]:
948 mainDiv = mainDiv +endP
949 mainDiv = mainDiv + startP
950 mainDiv = mainDiv + print_tagged_name\
951 ('With',opr, newLine)
956 if cb!=0 and bornYear != 0:
958 thisChild = thisChild[:-4] + \
959 " at the age of "+str(age) + newLine
960 mainDiv = mainDiv + thisChild
962 mainDiv = mainDiv + endP
965 if newLine == '<br>':
966 output = '<div id = "main" style = " float:left">';
967 output = output + mainDiv + "</div>"
969 output = output + "<div id = 'image' "\
970 +"style = 'float:left; margin-left:20px'>"
974 imageDiv = imageDiv + "<a href=" + url+">"\
975 +"<img src=" + picture +" alt = 'wiki link'"\
976 +" title = 'wiki link'></a>"\
979 elif url!='.' and url!='. ':
980 imageDiv = imageDiv + "<a href=" + url +">"\
981 +name + " (wiki link)</a>"+newLine
983 output = output + imageDiv + "</div>"
986 url = 'http://www.chiark.greenend.org.uk/ucgi/~naath/'\
990 form = form + "<form id ='controlForm'"\
991 +" action ="+ url +" method = 'get'>"
994 "<input type = 'hidden' name = 'ID' value = "\
998 "Generations of Parents: "\
999 +"<input type = 'text' name = 'pl' value='1'>"
1000 form = form + newLine
1002 "Generations of Children: "\
1003 +" <input type = 'text' name = 'cl' value = '1'>"
1004 form = form + newLine
1006 "Show siblings: <select name = 's'>"+\
1007 "<option value = '0'>No</option>"+\
1008 "<option value = '1'>Yes</option>"+\
1010 form = form + newLine
1012 "Show spouse's other spouses: <select name = 'os'>"+\
1013 "<option value = '0'>No</option>"+\
1014 "<option value = '1'>Yes</option>"+\
1016 form = form + newLine
1018 "Show parents' other spouses: <select name = 'pos'>"+\
1019 "<option value = '0'>No</option>"+\
1020 "<option value = '1'>Yes</option>"+\
1022 form = form + newLine
1025 "<input type = 'text' name = 'fs' value='8'>"
1026 form = form + newLine
1027 form = form + "</form>"
1029 graph = "smallGraph.py?ID="+str(personID)+"&fs=8"
1031 graph = "<img src ="+ graph + '>'
1033 output = output + "<div id = 'graph' style = 'clear:both'>"
1034 output = output + "<p id = 'agraph'>"+graph+"</p>"
1035 output = output + "Draw this graph with more relatives:"
1036 output = output + newLine + form
1038 output = output + "<button onclick='myFunction()'>"+\
1041 output = output + "</div>"
1045 'function myFunction()'+\
1047 'var x = document.getElementById("controlForm");'+\
1048 'var txt = "<img src = " + x.action + "?";'+\
1049 'for (var i=0;i<x.length;i++)'+\
1051 'var n=x.elements[i].name;'+\
1052 'var v=x.elements[i].value;'+\
1053 'txt = txt + "&"+n+"="+v;'+\
1055 'txt = txt + ">";'+\
1056 'document.getElementById("agraph").innerHTML=txt;'+\
1067 conn = sqlite3.connect\
1068 ('/home/naath/familyTreeProject/familyTree/tree.db')
1072 return conn.cursor()