5 from string import Template
10 link_Template= Template(\
11 "<a href = http://www.chiark.greenend.org.uk/ucgi/~naath/$script"\
12 +" title=$title>$text</a>")
21 def print_row(row,newLine):
24 out = out + str(item)+'|'
25 return out[:-1] + newLine
27 def print_query(s,t,newLine):
29 for row in run_query(s,t):
30 printMe = printMe + print_row(row,newLine)
40 def print_tagged_query(relationship,s,t,newLine):
42 for row in run_query(s,t):
43 mine = mine + print_tagged_name(relationship,row,newLine)
47 def relationship_html(ID,ID2,newLine):
49 relationship = common_ancestors(ID,ID2,newLine)[2]
51 if relationship[-11:] != 'not related':
52 script = "ancestors.py?ID="+str(ID)+"&ID2="+str(ID2)
53 url = link_Template.substitute\
54 (script = script,title = "Common ancestors"\
55 ,text = "Common ancestors")
56 return relationship + ' '+url + newLine
58 return relationship + newLine
62 def terr_html(terr,newLine,start,stop):
64 if start == 0 and stop ==0:
65 myTitle = add_quotes(terr)
68 s = "SELECT name,people.id"\
69 +" FROM people INNER JOIN territories"\
70 +" ON people.id = territories.id"\
71 +" WHERE territory = ? AND stopyear <= ?"\
72 +" ORDER BY startyear DESC;"
76 for row in run_query(s,t):
77 myTitle = myTitle +"previous - " + row[0] \
81 u = "SELECT name,people.id"\
82 +" FROM people INNER JOIN territories"\
83 +" ON people.id = territories.id"\
84 +" WHERE territory = ? AND startyear >= ?"\
85 +" ORDER BY startyear;"
88 for r in run_query(u,v):
89 myTitle = myTitle + '
' +"next - " + r[0] \
93 myTitle = add_quotes(myTitle)
95 return link_Template.substitute(\
96 script = "territory.py?terr="+terr, title=myTitle,\
100 def name_html(row,html):
112 script = "person.py?ID=" + str(row[1])
114 return link_Template.substitute(script = script\
115 ,title = add_quotes(name),text = name)
117 return row[0] + "," +str(row[1])
125 def print_age_child_count(row,newLine):
126 if newLine == '<br>':
127 script = "age.py?age="+str(row[0])
128 link = link_Template.substitute(script = \
129 script, title = add_quotes(row[0]), text = row[0])
130 out = str(row[1])+print_people(row[1])
132 out = out + 'had children at age '+ link + newLine
135 return print_row(row,newLine)
137 def print_age_death_count(row,newLine):
139 script = "ageDeath.py?age="+str(row[0])
140 link = link_Template.substitute(script = script,\
141 title = add_quotes(row[0]),text = row[0])
142 out = str(row[1])+print_people(row[1])
143 out = out + "died at age " + link + newLine
146 return print_row(row,newLine)
148 def print_name_count(row,newLine):
150 script = "name.py?name=" + row[0]
151 link = link_Template.substitute(script =\
152 script, title = add_quotes(row[0]),text = row[0])
153 return str(row[1]) + " people called "+link + newLine
155 return print_row(row,newLine)
157 def print_tagged_name(relationship,row,newLine):
159 out = relationship + " not yet entered: " + row[1]
161 if newLine == '<br>':
165 if relationship =='':
166 out = name_html(row,html) + ' '
168 out = relationship + ": " + name_html(row,html)
171 def month_numbers(monthN):
173 month ='unknown month'
199 month = 'Incorrectly entered month ' + str(monthN)
202 def ordinal_numbers(number):
204 if number % 10==1 and number/10 % 10 !=1:
205 out = str(number) +'st'
206 elif number % 10==2 and number/10 % 10 !=1:
207 out = str(number) +'nd'
208 elif number % 10==3 and number/10 % 10 !=1:
209 out = str(number) +'rd'
211 out = str(number) +'th'
214 def list_territories(newLine):
215 s = "SELECT DISTINCT territory"\
216 +" FROM territories"\
217 +" ORDER BY territory;"
220 for row in run_query(s,()):
221 out =out + terr_html(row[0],newLine,0,0) +newLine
224 def list_people_parents():
225 s = "SELECT name,id"\
230 for row in run_query(s,()):
233 [parents, parentIDs,parentNames] = find_parents(ID)
234 [spouses,spousesID,spousesNames] = find_spouses(ID)
236 [self,myID,myName] = find_person(ID)
237 output.append([self,parents,spouses])
241 def list_people(newLine):
242 s = "SELECT name,id,bornyear"\
244 +" ORDER BY bornyear;"
248 out = out + 'born in unknown year:' +newLine
249 for row in run_query(s,()):
250 if row[2]!=0 and row[2]/100==0:
251 out = out +newLine+ 'born in 1st century:' +newLine
253 if row[2]/100!=year/100:
254 century = row[2]/100 + 1
255 out = out +newLine+ 'born in '
257 out = out +ordinal_numbers(century) \
258 + ' century:' + newLine
260 out = out + name_html(row,newLine) +newLine
262 if row[2] == 0: #unknown year
264 t = (row[1],) #person ID
268 u = "SELECT diedyear FROM people WHERE ID = ?;"
271 for r in run_query(u,t):
273 out = out + "died: "\
274 + str(r[0]) + newLine
275 bornAfter = r[0] -100
278 u = "Select people.bornYear from"\
279 +" people INNER JOIN parents"\
280 +" ON people.ID = parents.ID"\
281 +" WHERE parents.parentID = ?"\
282 + " ORDER BY people.bornYear;"
286 for r in run_query(u,t):
288 hadChild.append(r[0])
292 out = out + "had children in: "
294 out = out + str(c) + ','
295 out = out[:-1] + newLine
297 bornBefore = hadChild[0]-12
299 bornAfter = hadChild[0]-100
301 u = "Select styles.startYear, styles.style from"\
302 +" people INNER JOIN styles"\
303 +" ON people.ID = styles.ID"\
304 +" WHERE people.ID = ? and"\
305 +" styles.startYear <>0"\
306 +" ORDER BY styles.startYear;"
308 for r in run_query(u,t):
309 out = out + r[1] + " from " + str(r[0])\
312 bornAfter = r[0] -100
317 out = out + "probably born "\
318 +"after " + str(bornAfter)
320 out = out + "probably born "\
321 +"betwen " + str(bornAfter)\
322 +" and " + str(bornBefore)
328 def count_names(newLine):
329 s = "SELECT firstName, count(*)"\
331 +" GROUP BY firstName"\
332 +" ORDER BY count(*) DESC;"
335 for row in run_query(s,()):
336 out = out + print_name_count(row,newLine)
341 def search_name(name,newLine):
342 s = "SELECT name, ID"\
344 +" WHERE name LIKE ?;"
350 out = out + 'Names starting with ' + name + ':' + newLine
353 for row in run_query(s,t):
354 out = out + name_html(row,newLine) + newLine
355 fullIDs.append(row[1])
359 t = ('%' + name + '%',)
360 out = out+newLine + 'Names containing ' + name + ':' + newLine
361 for row in run_query(s,t):
362 if row[1] not in fullIDs:
363 out = out + name_html(row,newLine) + newLine
367 s = "SELECT name,people.ID,style"\
368 +" FROM people INNER JOIN styles"\
369 +" ON styles.id = people.id"\
370 +" WHERE style LIKE ?;"
371 out = out +newLine+ 'Styles containing ' + name + ':' + newLine
372 for row in run_query(s,t):
373 out = out + name_html(row,newLine)+' ' + row[2] + newLine
375 return [out,names,IDs]
378 def people_with_name(name,newLine):
379 s = "SELECT name, ID"\
381 +" WHERE firstname = ?;"
387 for row in run_query(s,t):
388 out = out + name_html(row,newLine) + newLine
392 def count_birth_month(newLine):
393 s = "SELECT bornMonth, count(*)"\
395 +" GROUP BY bornMonth"\
396 +" ORDER BY bornMonth;"
398 t = "SELECT * FROM people WHERE bornMonth = ?;"
401 for row in run_query(s,()):
402 month = month_numbers(row[0])
403 out = out + month + ': ' + str(row[1]) + newLine
407 out = out +print_query(t,u,newLine)
411 def count_death_month(newLine):
412 s = "SELECT diedMonth, count(*)"\
414 +" GROUP BY diedMonth"\
415 +" ORDER BY diedMonth;"
417 t = "SELECT * FROM people WHERE diedMonth = ?;"
420 for row in run_query(s,()):
421 month = month_numbers(row[0])
422 out = out + month + ': ' + str(row[1]) + newLine
426 out = out +print_query(t,u,newLine)
430 def count_age_at_child(newLine):
432 s = "select p1.bornYear - p2.bornYear as age, count(*)"\
434 +" parents INNER JOIN people p1"\
435 +" ON parents.ID = p1.ID"\
436 +" INNER JOIN people p2"\
437 +" ON parents.parentID = p2.ID"\
438 +" WHERE p1.bornYear <> 0 and p2.bornYear<>0"\
442 for row in run_query(s,()):
443 out = out + print_age_child_count(row,newLine)
447 def people_had_child_at_age(age,newLine):
449 s = "select p1.bornYear - p2.bornYear as age, p1.name, p1.ID"\
450 +",p2.name,p2.ID FROM"\
451 +" parents INNER JOIN people p1"\
452 +" ON parents.ID = p1.ID"\
453 +" INNER JOIN people p2"\
454 +" ON parents.parentID = p2.ID"\
455 +" WHERE age = ? AND p1.bornYear<>0 AND p2.bornYear<>0"
460 out = 'At age ' + str(age) + ' :'
461 for row in run_query(s,t):
463 out =out + name_html([row[3],row[4]],newLine) + ' had '\
464 +name_html([row[1],row[2]],newLine)
468 def count_age_at_death(newLine):
469 s = "select diedYear-bornYear as age,count(*)"\
471 +" WHERE diedYear<>0 AND bornYear<>0"\
474 for row in run_query(s,()):
475 out = out + print_age_death_count(row,newLine)
478 def people_died_at_age(age,newLine):
479 s = "SELECT diedYear-bornYear as age, name,ID"\
481 +" WHERE age = ? AND bornYear<>0 AND diedYear<>0;"
484 out = 'These people died at age ' +str(age) + ' :'
485 for row in run_query(s,t):
487 out = out + name_html([row[1],row[2]],newLine)
490 def all_ancestors(personID,newLine):
493 ancestors = [personID]
494 allAncestors = [personID]
498 t = "SELECT name,id FROM people WHERE id=?"
501 out = "Ancestors of "
502 for row in run_query(t,id):
503 out = out + name_html(row,newLine)+newLine
505 while len(ancestors)>0:
508 thisout = newLine + parent_level(level,'parent') +\
510 for ancestor in ancestors:
511 [parents, parentIDs,parentNames] \
512 = find_parents(ancestor)
513 for i in range(len(parents)):
514 r = [parentNames[i],parentIDs[i]]
515 thisout = thisout + \
516 name_html(r,newLine)+newLine
518 if r[1] not in allAncestors\
521 allAncestors.append(r[1])
522 trackLevel.append(level)
528 image = "<img src = ancestorGraph.py?id="+str(personID)+">"
529 out = out+newLine + image+newLine
530 return [out, allAncestors,trackLevel]
533 def common_ancestors(IDA, IDB,newLine):
534 out = 'Common ancestors of:' + newLine
536 s = "SELECT name,id FROM people WHERE id==?"
542 for row in run_query(s,t):
543 out = out + name_html(row,newLine)+newLine
550 related = 'No details held on one party'
552 return [out,[],related]
555 a = all_ancestors(IDA,newLine)
556 b = all_ancestors(IDB,newLine)
558 ancestorsB = set(b[1])
559 ancestorsA = set(a[1])
561 common = ancestorsA.intersection(ancestorsB)
562 common = list(common)
569 aLevels.append(a[2][i])
571 bLevels.append(b[2][i])
573 s = "SELECT Name, ID, bornyear"\
576 for i in range(len(common)):
580 s = s+") ORDER BY bornyear;"
584 related = names[0]+' and '+names[1]+' are not related'
585 out = out + newLine + related
586 return [out, common,related]
589 out = out + print_tagged_query('',s,common,newLine)
594 for i in range(len(common)):
595 if aLevels[i] == min(aLevels):
597 if bLevels[i] == min(bLevels):
602 s = "SELECT name, id"\
606 out = out + newLine + 'Most Recent Common Ancestors:' + newLine
610 mrca.append(common[a])
611 out = out + print_tagged_query('',s,t,newLine)
613 out = out + 'and' + newLine
615 out = out + parent_level(aLevels[indexA[0]],'parent')
619 out = out + ' of ' + name_html([names[0],IDA],newLine)+newLine
621 out = out + parent_level(bLevels[indexB[0]],'parent')
624 out = out + ' of ' + name_html([names[1],IDB],newLine)+newLine
627 al = aLevels[indexA[0]]
628 bl = bLevels[indexB[0]]
630 related = relationship(al,bl,names)
631 out = out+newLine + related
634 image = "<img src = jointAncestorGraph.py?id="+str(IDA)\
635 +"&id2="+str(IDB) + "&LA=" + str(min(aLevels)) \
636 +"&LB=" + str(min(bLevels))+">"
640 out = out+newLine + image+newLine
642 return [out,common,related]
644 def relationship(level1, level2,names):
646 if level1==0 and level2==0:
647 return names[0] + ' is ' +names[1]
649 return names[0] + ' is ' + names[1] + '\'s '+ parent_level(level2,'parent')
651 return names[1] + ' is ' + names[0] + '\'s '+ parent_level(level1,'parent')
655 remove = level1-level2
658 remove = level2-level1
662 uaLevel = parent_level(remove,'uncle or aunt')
664 return names[0] + ' is ' + names[1] + '\'s ' + uaLevel
667 return names[1] + ' is ' + names[0] + '\'s ' + uaLevel
669 c=ordinal_numbers(cousinNum)
675 rem = str(remove) + ' times'
677 r = names[0] +' and '+names[1] +' are ' + c + ' cousins '
679 r = r+ rem + ' removed'
683 def parent_level(level,type):
698 for i in range(2,level):
702 def rulers_of(aTerritory,newLine):
704 tq = "SELECT name, people.ID, startyear,stopyear,territory"\
705 +" FROM territories INNER JOIN people"\
706 +" ON people.ID = territories.ID"\
707 +" WHERE territory LIKE ?"\
708 +" ORDER BY territory,startyear,stopyear;"
715 for row in run_query(tq,(aTerritory+'%',)):
716 if row[4]!=last and last!='':
717 out = out + 'Rulers of '+terr_html(last,newLine,0,0) \
718 +':'+ newLine +thisT +newLine
721 thisT = thisT +name_html(row,newLine)
722 thisT = thisT +' from ' + str(row[2])+' to '+str(row[3]) + newLine
725 out = out + 'Rulers of '+terr_html(row[4],newLine,0,0) +':'+ \
731 s = "SELECT name || ','||ID, name, ID FROM people WHERE ID=?"
734 for row in run_query(s,t):
738 return [Self, selfID,selfName]
740 ID = int(ID.split(',')[-1])
741 s= "SELECT style FROM styles WHERE ID=?"
745 for row in run_query(s,t):
746 a=re.match('.*King',row[0])
747 b=re.match('.*Queen',row[0])
748 if a!=None or b!=None:
753 def find_parents(ID):
754 s = "SELECT name, parentID"\
755 +" FROM parents LEFT JOIN people"\
756 +" ON people.ID = parentID"\
757 +" WHERE parents.ID = ?;"
764 for row in run_query(s,t):
766 p = row[0] + ',' + str(row[1])
770 p = row[1] + ',p' + str(ID)
774 parentIDs.append(pID)
775 parentNames.append(pN)
777 if parents[1]==parents[0]:
778 parents[1] = parents[1] + ' 2'
780 return [parents,parentIDs,parentNames]
782 def find_spouses(ID):
785 order = [["IDb","IDa"],["IDa","IDb"]]
791 s = "SELECT name, marriages." + o[0]\
792 +" FROM marriages LEFT JOIN people"\
793 +" ON marriages." +o[0]+" = people.ID"\
794 +" WHERE marriages."+o[1]+" = ?;"
797 for row in run_query(s,t):
799 s = row[0] + "," +str(row[1])
803 s=row[1] + ",s" +str(ID)
808 spousesID.append(sID)
809 spousesNames.append(sN)
811 return [spouses,spousesID,spousesNames]
814 def find_children(ID):
815 s = "SELECT p1.name, p1.ID,p3.parentID,p4.name,p1.bornYear"\
817 +" INNER JOIN parents p2"\
818 +" ON p1.ID = p2.ID"\
819 +" INNER JOIN parents p3"\
820 +" ON p1.ID = p3.ID"\
821 +" LEFT JOIN people"\
822 +" p4 ON p3.parentID = p4.ID"\
823 +" WHERE p2.parentID = ?"\
824 +" AND p3.parentID<>?"\
825 +" ORDER BY p1.bornYear;"
834 for row in run_query(s,t):
835 c = row[0] + ',' + str(row[1])
839 childrenBorn.append(born)
841 op = row[3] + ',' + str(row[2])
845 op = row[2] + ',s' + str(ID)
850 IDs.append([cID,opID])
851 names.append([cName,opN])
853 return [nodes,IDs,names,childrenBorn]
855 def person_info(personID,newLine):
866 #Id, Name, Dates, Style, Style-Dates
867 s = "SELECT * FROM people WHERE ID = ?"
868 for row in run_query(s,t):
869 mainDiv = mainDiv + startP
870 mainDiv = mainDiv + 'ID: '+str(row[0]) +newLine
871 mainDiv = mainDiv + print_tagged_name('Name',[row[1], row[0]]\
873 mainDiv = mainDiv + endP
878 mainDiv = mainDiv + startP
879 mainDiv = mainDiv + newLine + 'Born: '+row[3] + newLine
881 mainDiv = mainDiv + 'Died: '+row[5]
883 if row[6] != 0 and row[4] !=0:
884 mainDiv = mainDiv + ", aged " \
886 mainDiv = mainDiv + endP
889 s = "SELECT * FROM styles WHERE ID = ?"
890 for row in run_query(s,t):
891 mainDiv = mainDiv + startP
892 mainDiv = mainDiv +newLine+ 'Style: '+row[1] + newLine
894 mainDiv = mainDiv + 'Territories:' + newLine
896 u = "SELECT * FROM territories"\
897 +" WHERE ID =? AND startYear =? AND stopYear=?"
898 v=(personID,row[3],row[5])
901 for r in run_query(u,v):
903 + terr_html(r[1],newLine,r[3],r[5])\
907 mainDiv = mainDiv[:-1] + newLine
909 mainDiv = mainDiv + 'From: '+row[2] + newLine
910 mainDiv = mainDiv + 'To: '+row[4]
912 mainDiv = mainDiv + endP
917 mainDiv = mainDiv + startP
918 s = "SELECT people.Name,consort "\
919 +"FROM consorts LEFT JOIN people"\
920 +" ON people.ID = consorts.consort"\
921 +" WHERE consorts.ID = ?"
922 for row in run_query(s,t):
923 mainDiv = mainDiv + print_tagged_name\
924 ('Consort of',row,newLine)
925 mainDiv = mainDiv + endP
929 [parents,parentIDs,parentNames] = find_parents(personID)
930 mainDiv = mainDiv + startP
931 for i in range(len(parents)):
932 r = [parentNames[i],parentIDs[i]]
933 mainDiv = mainDiv + print_tagged_name('Parent',r,newLine)
934 mainDiv = mainDiv + endP
938 [spouses,spousesID,spousesNames] = find_spouses(personID)
940 mainDiv = mainDiv + startP
942 for i in range(len(spouses)):
943 r = [spousesNames[i],spousesID[i]]
944 mainDiv = mainDiv + print_tagged_name('Spouse',r,newLine)
945 mainDiv = mainDiv + \
946 relationship_html(personID,r[1],newLine)
948 mainDiv = mainDiv + endP
951 [nodes,IDs,names,childrenBorn] = \
952 find_children(personID)
955 for i in range(len(nodes)):
956 cr = [names[i][0],IDs[i][0]]
957 thisChild = print_tagged_name('Child',cr,newLine)
959 opr=[names[i][1],IDs[i][1]]
961 if i==0 or top != names[i-1][1]:
962 mainDiv = mainDiv +endP
963 mainDiv = mainDiv + startP
964 mainDiv = mainDiv + print_tagged_name\
965 ('With',opr, newLine)
970 if cb!=0 and bornYear != 0:
972 thisChild = thisChild[:-4] + \
973 " at the age of "+str(age) + newLine
974 mainDiv = mainDiv + thisChild
976 mainDiv = mainDiv + endP
979 if newLine == '<br>':
980 output = '<div id = "main" style = " float:left">';
981 output = output + mainDiv + "</div>"
983 output = output + "<div id = 'image' "\
984 +"style = 'float:left; margin-left:20px'>"
988 imageDiv = imageDiv + "<a href=" + url+">"\
989 +"<img src=" + picture +" alt = 'wiki link'"\
990 +" title = 'wiki link'></a>"\
993 elif url!='.' and url!='. ':
994 imageDiv = imageDiv + "<a href=" + url +">"\
995 +name + " (wiki link)</a>"+newLine
997 output = output + imageDiv + "</div>"
1000 url = 'http://www.chiark.greenend.org.uk/ucgi/~naath/'\
1004 form = form + "<form id ='controlForm'"\
1005 +" action ="+ url +" method = 'get'>"
1008 "<input type = 'hidden' name = 'ID' value = "\
1012 "Generations of Parents: "\
1013 +"<input type = 'text' name = 'pl' value='1'>"
1014 form = form + newLine
1016 "Generations of Children: "\
1017 +" <input type = 'text' name = 'cl' value = '1'>"
1018 form = form + newLine
1020 "Show siblings: <select name = 's'>"+\
1021 "<option value = '0'>No</option>"+\
1022 "<option value = '1'>Yes</option>"+\
1024 form = form + newLine
1026 "Show spouse's other spouses: <select name = 'os'>"+\
1027 "<option value = '0'>No</option>"+\
1028 "<option value = '1'>Yes</option>"+\
1030 form = form + newLine
1032 "Show parents' other spouses: <select name = 'pos'>"+\
1033 "<option value = '0'>No</option>"+\
1034 "<option value = '1'>Yes</option>"+\
1036 form = form + newLine
1039 "<input type = 'text' name = 'fs' value='8'>"
1040 form = form + newLine
1041 form = form + "</form>"
1043 graph = "smallGraph.py?ID="+str(personID)+"&fs=8"
1045 graph = "<img src ="+ graph + '>'
1047 output = output + "<div id = 'graph' style = 'clear:both'>"
1048 output = output + "<p id = 'agraph'>"+graph+"</p>"
1049 output = output + "Draw this graph with more relatives:"
1050 output = output + newLine + form
1052 output = output + "<button onclick='myFunction()'>"+\
1055 output = output + "</div>"
1059 'function myFunction()'+\
1061 'var x = document.getElementById("controlForm");'+\
1062 'var txt = "<img src = " + x.action + "?";'+\
1063 'for (var i=0;i<x.length;i++)'+\
1065 'var n=x.elements[i].name;'+\
1066 'var v=x.elements[i].value;'+\
1067 'txt = txt + "&"+n+"="+v;'+\
1069 'txt = txt + ">";'+\
1070 'document.getElementById("agraph").innerHTML=txt;'+\
1081 conn = sqlite3.connect\
1082 ('/home/naath/familyTreeProject/familyTree/tree.db')
1086 return conn.cursor()