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=%s&ID2=%s" % (ID,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 += "previous - %s,%s" \
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 += '
 next - %s,%s'\
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=%s" %(row[1])
114 return link_Template.substitute(script = script\
115 ,title = add_quotes(name),text = name)
117 return "%s,%s" % (row[0],row[1])
124 def print_children(n):
130 def print_age_child_count(row,newLine):
131 if newLine == '<br>':
132 script = "listAge.py?age=%s" % (row[0])
133 link = link_Template.substitute(script = \
134 script, title = add_quotes(row[0]), text = row[0])
136 out = '%s %s had children at age %s %s'\
137 % (row[1],print_people(row[1]),link,newLine)
140 return print_row(row,newLine)
142 def print_age_death_count(row,newLine):
144 script = "listAgeDeath.py?age=%s" % (row[0])
145 link = link_Template.substitute(script = script,\
146 title = add_quotes(row[0]),text = row[0])
147 out = "%s %s died at age %s %s " \
148 %(row[1],print_people(row[1]), link,newLine)
151 return print_row(row,newLine)
153 def print_name_count(row,newLine):
155 script = "name.py?name=%s" % (row[0])
156 link = link_Template.substitute(script =\
157 script, title = add_quotes(row[0]),text = row[0])
158 return "%s people called %s%s"\
159 %(row[1],link, newLine)
161 return print_row(row,newLine)
163 def print_children_count(row,newLine):
164 out = "%s %s had " % (row[0],print_people(row[0]))
166 if newLine == '<br>':
167 script = "listChildCount.py?nc="+str(row[1])
168 link = link_Template.substitute(script =\
169 script, title = add_quotes(row[1]),text = row[1])
173 out += "%s %s %s" % (link,print_children(row[1]),newLine)
177 def print_tagged_name(relationship,row,newLine):
179 out = relationship + " not yet entered: " + row[1]
180 out = "%s not yet entered: %s" % (relationship,row[1])
182 if newLine == '<br>':
186 if relationship =='':
187 out = '%s ' % (name_html(row,html))
189 out = relationship + ": " + name_html(row,html)
190 out = '%s: %s' % (relationship,name_html(row,html))
193 def month_numbers(monthN):
195 month ='unknown month'
221 month = 'Incorrectly entered month ' + str(monthN)
224 def ordinal_numbers(number):
226 out = '%d' % (number)
227 if number % 10==1 and number/10 % 10 !=1:
229 elif number % 10==2 and number/10 % 10 !=1:
231 elif number % 10==3 and number/10 % 10 !=1:
237 def list_territories(newLine):
238 s = "SELECT DISTINCT territory"\
239 +" FROM territories"\
240 +" ORDER BY territory;"
243 for row in run_query(s,()):
244 out += terr_html(row[0],newLine,0,0) +newLine
247 def list_people_parents():
248 s = "SELECT name,id"\
253 for row in run_query(s,()):
256 [parents, parentIDs,parentNames] = find_parents(ID)
257 [spouses,spousesID,spousesNames] = find_spouses(ID)
259 [self,myID,myName] = find_person(ID)
260 output.append([self,parents,spouses])
264 def list_people(newLine):
265 s = "SELECT name,id,bornyear"\
267 +" ORDER BY bornyear;"
271 out = out + 'born in unknown year:' +newLine
272 for row in run_query(s,()):
273 if row[2]!=0 and row[2]/100==0:
274 out +='%sborn in 1st century:%s' % (newLine,newLine)
276 if row[2]/100!=year/100:
277 century = row[2]/100 + 1
278 out +='%sborn in %s century: %s'\
279 %(newLine,ordinal_numbers(century),newLine)
282 out+= name_html(row,newLine) +newLine
284 if row[2] == 0: #unknown year
286 t = (row[1],) #person ID
290 u = "SELECT diedyear FROM people WHERE ID = ?;"
294 for r in run_query(u,t):
296 bornAfter = r[0] -100
298 out += "Died: %s %s"\
301 u = "Select people.bornYear from"\
302 +" people INNER JOIN parents"\
303 +" ON people.ID = parents.ID"\
304 +" WHERE parents.parentID = ?"\
305 + " ORDER BY people.bornYear;"
309 for r in run_query(u,t):
311 hadChild.append(r[0])
314 out += "had children in: "
317 out = out[:-1] + newLine
318 bornBefore = hadChild[0]-12
320 bornAfter = hadChild[0]-100
322 u = "Select styles.startYear, styles.style from"\
323 +" people INNER JOIN styles"\
324 +" ON people.ID = styles.ID"\
325 +" WHERE people.ID = ? and"\
326 +" styles.startYear <>0"\
327 +" ORDER BY styles.startYear;"
329 for r in run_query(u,t):
330 out += "%s from %s %s"\
333 bornAfter = r[0] -100
338 out += "probably born after %s"\
341 out +="probably born between %s and %s"\
342 %(bornAfter, bornBefore)
348 def count_names(newLine):
349 s = "SELECT firstName, count(*)"\
351 +" GROUP BY firstName"\
352 +" ORDER BY count(*) DESC;"
355 for row in run_query(s,()):
356 out += print_name_count(row,newLine)
362 def count_children(newLine):
364 s = "SELECT count(*),nc"\
366 +" SELECT count(*) AS nc"\
368 +" GROUP BY parentID"\
369 +" HAVING parentID <>'?'"\
370 +" AND parentID <> '0')"\
374 for row in run_query(s,()):
375 out += print_children_count(row,newLine)
378 def parents_with_children(nChildren,newLine):
379 s = "SELECT name,parentID"\
381 + " LEFT JOIN people"\
382 + " ON parentID = people.ID"\
383 + " GROUP BY parentID"\
384 + " HAVING count(*) = ?"\
385 + " AND parentID <> 0"\
386 + " ORDER BY bornYear;"
389 u = "SELECT count(*)"\
390 +" FROM parents INNER JOIN people"\
391 +" ON parents.ID = people.ID"\
392 +" WHERE parentID = ?"\
393 +" AND (diedyear-bornyear>? OR died='present');"
395 out = "People who had %s %s:%s" \
396 %(nChildren,print_children(nChildren),newLine)
398 for row in run_query(s,(nChildren,)):
399 out += name_html(row,newLine)
400 for r in run_query(u,(row[1],1)):
401 out += " %d survived infancy" % r[0]
402 for r in run_query(u,(row[1],18)):
403 out += " and %s survived to adulthood" % r[0]
408 def search_name(name,newLine):
409 s = "SELECT name, ID"\
411 +" WHERE name LIKE ?;"
416 out = 'Names starting with %s:%s' % (name,newLine)
419 for row in run_query(s,t):
420 out += name_html(row,newLine) + newLine
421 fullIDs.append(row[1])
425 t = ('%' + name + '%',)
426 out += '%sNames containing %s:%s' %(newLine,name,newLine)
427 for row in run_query(s,t):
428 if row[1] not in fullIDs:
429 out += name_html(row,newLine) + newLine
433 s = "SELECT name,people.ID,style"\
434 +" FROM people INNER JOIN styles"\
435 +" ON styles.id = people.id"\
436 +" WHERE style LIKE ?;"
437 out += '%sStyles containing %s:%s' %(newLine,name,newLine)
438 for row in run_query(s,t):
439 out +="%s %s %s" %(name_html(row,newLine),row[2],newLine)
440 return [out,names,IDs]
443 def people_with_name(name,newLine):
444 s = "SELECT name, ID"\
446 +" WHERE firstname = ?;"
452 for row in run_query(s,t):
453 out += name_html(row,newLine) + newLine
457 def count_birth_month(newLine):
458 s = "SELECT bornMonth, count(*)"\
460 +" GROUP BY bornMonth"\
461 +" ORDER BY bornMonth;"
463 t = "SELECT * FROM people WHERE bornMonth = ?;"
466 for row in run_query(s,()):
467 month = month_numbers(row[0])
468 out += "%s:%s%s" %( month,row[1],newLine)
472 out +=print_query(t,u,newLine)
476 def count_death_month(newLine):
477 s = "SELECT diedMonth, count(*)"\
479 +" GROUP BY diedMonth"\
480 +" ORDER BY diedMonth;"
482 t = "SELECT * FROM people WHERE diedMonth = ?;"
485 for row in run_query(s,()):
486 month = month_numbers(row[0])
487 out += '%s:%s%s'%(month,row[1], newLine)
491 out +=print_query(t,u,newLine)
495 def count_age_at_child(newLine):
497 s = "select p1.bornYear - p2.bornYear as age, count(*)"\
499 +" parents INNER JOIN people p1"\
500 +" ON parents.ID = p1.ID"\
501 +" INNER JOIN people p2"\
502 +" ON parents.parentID = p2.ID"\
503 +" WHERE p1.bornYear <> 0 and p2.bornYear<>0"\
507 for row in run_query(s,()):
508 out +=print_age_child_count(row,newLine)
512 def people_had_child_at_age(age,newLine):
514 s = "select p1.bornYear - p2.bornYear as age, p1.name, p1.ID"\
515 +",p2.name,p2.ID FROM"\
516 +" parents INNER JOIN people p1"\
517 +" ON parents.ID = p1.ID"\
518 +" INNER JOIN people p2"\
519 +" ON parents.parentID = p2.ID"\
520 +" WHERE age = ? AND p1.bornYear<>0 AND p2.bornYear<>0"
525 out = 'At age ' + str(age) + ' :'
526 for row in run_query(s,t):
527 parent = name_html([row[3],row[4]],newLine)
528 child = name_html([row[1],row[2]],newLine)
529 out += "%s%s had %s" % (newLine,parent,child)
532 def count_age_at_death(newLine):
533 s = "select diedYear-bornYear as age,count(*)"\
535 +" WHERE diedYear<>0 AND bornYear<>0"\
538 for row in run_query(s,()):
539 out += print_age_death_count(row,newLine)
543 def people_died_at_age(age,newLine):
544 s = "SELECT diedYear-bornYear as age, name,ID"\
546 +" WHERE age = ? AND bornYear<>0 AND diedYear<>0;"
549 out = 'These people died at age ' +str(age) + ' :'
550 for row in run_query(s,t):
551 out += newLine+ name_html([row[1],row[2]],newLine)
554 def all_ancestors(personID,newLine):
557 ancestors = [personID]
558 allAncestors = [personID]
562 t = "SELECT name,id FROM people WHERE id=?"
565 out = "Ancestors of "
566 for row in run_query(t,id):
567 out += name_html(row,newLine)+newLine
569 while len(ancestors)>0:
572 thisout = "%s %s:%s" \
573 % (newLine,parent_level(level,'parent'),newLine)
575 for ancestor in ancestors:
576 [parents, parentIDs,parentNames] \
577 = find_parents(ancestor)
578 for i in range(len(parents)):
579 r = [parentNames[i],parentIDs[i]]
580 thisout +=name_html(r,newLine)+newLine
582 if r[1] not in allAncestors\
585 allAncestors.append(r[1])
586 trackLevel.append(level)
592 image = "<img src = ancestorGraph.py?id=%s>" %personID
593 out +=newLine + image+newLine
594 return [out, allAncestors,trackLevel]
597 def common_ancestors(IDA, IDB,newLine):
598 out = 'Common ancestors of:' + newLine
600 s = "SELECT name,id FROM people WHERE id==?"
606 for row in run_query(s,t):
607 out += name_html(row,newLine)+newLine
614 related = 'No details held on one party'
616 return [out,[],related]
619 a = all_ancestors(IDA,newLine)
620 b = all_ancestors(IDB,newLine)
622 ancestorsB = set(b[1])
623 ancestorsA = set(a[1])
625 common = ancestorsA.intersection(ancestorsB)
626 common = list(common)
633 aLevels.append(a[2][i])
635 bLevels.append(b[2][i])
637 s = "SELECT Name, ID, bornyear"\
640 for i in range(len(common)):
644 s = s+") ORDER BY bornyear;"
648 related = '%s and %s are not related' %(names[0], names[1])
649 out = out + newLine + related
650 return [out, common,related]
653 out += print_tagged_query('',s,common,newLine)
658 for i in range(len(common)):
659 if aLevels[i] == min(aLevels):
661 if bLevels[i] == min(bLevels):
666 s = "SELECT name, id"\
670 out += '%sMost Recent Common Ancestors:%s' %(newLine,newLine)
674 mrca.append(common[a])
675 out += print_tagged_query('',s,t,newLine)
677 out += 'and' + newLine
679 out += parent_level(aLevels[indexA[0]],'parent')
683 out +=' of %s%s'%( name_html([names[0],IDA],newLine),newLine)
685 out += parent_level(bLevels[indexB[0]],'parent')
688 out += ' of %s%s' %(name_html([names[1],IDB],newLine),newLine)
691 al = aLevels[indexA[0]]
692 bl = bLevels[indexB[0]]
694 related = relationship(al,bl,names)
695 out +=newLine + related
698 image = "<img src = jointAncestorGraph.py?id="+str(IDA)\
699 +"&id2="+str(IDB) + "&LA=" + str(min(aLevels)) \
700 +"&LB=" + str(min(bLevels))+">"
702 image = "<img src = jointAncestorGraph.py?id=%s&id2=%s&LA=%d&LB=%d>"\
703 %(IDA,IDB,min(aLevels),min(bLevels))
706 out +=newLine + image+newLine
708 return [out,common,related]
710 def relationship(level1, level2,names):
712 if level1==0 and level2==0:
713 return "%s is %s" %(names[0],names[1])
715 return "%s is %s's %s" \
716 %(names[0],names[1],parent_level(level2,'parent'))
719 return "%s is %s's %s" \
720 %(names[1],names[0],parent_level(level1,'parent'))
724 remove = level1-level2
727 remove = level2-level1
731 uaLevel = parent_level(remove,'uncle or aunt')
733 return "%s is %s's %s" % (names[0],names[1],uaLevel)
736 return "%s is %s's %s" % (names[1],names[0],uaLevel)
738 c=ordinal_numbers(cousinNum)
744 rem = str(remove) + ' times'
746 r = "%s and %s are %s cousins" % (names[0],names[1],c)
748 r += ' %s removed' % rem
752 def parent_level(level,type):
767 for i in range(2,level):
771 def rulers_of(aTerritory,newLine):
773 tq = "SELECT name, people.ID, startyear,stopyear,territory"\
774 +" FROM territories INNER JOIN people"\
775 +" ON people.ID = territories.ID"\
776 +" WHERE territory LIKE ?"\
777 +" ORDER BY territory,startyear,stopyear;"
784 for row in run_query(tq,(aTerritory+'%',)):
785 if row[4]!=last and last!='':
786 out += 'Rulers of %s:%s%s%s'\
787 %(terr_html(last,newLine,0,0),newLine,thisT,newLine)
790 thisT += "%s from %s to %s%s" \
791 % (name_html(row,newLine),row[2],row[3],newLine)
794 out += 'Rulers of %s:%s%s' \
795 % (terr_html(row[4],newLine,0,0),newLine,thisT)
800 s = "SELECT name || ','||ID, name, ID FROM people WHERE ID=?"
803 for row in run_query(s,t):
807 return [Self, selfID,selfName]
809 ID = int(ID.split(',')[-1])
810 s= "SELECT style FROM styles WHERE ID=?"
814 spellingsOfKing = ['King','Queen','king','queen']
815 for row in run_query(s,t):
816 for s in spellingsOfKing:
817 if re.match('.*'+s,row[0]) != None:
822 def find_parents(ID):
823 s = "SELECT name, parentID"\
824 +" FROM parents LEFT JOIN people"\
825 +" ON people.ID = parentID"\
826 +" WHERE parents.ID = ?;"
833 for row in run_query(s,t):
835 p = row[0] + ',' + str(row[1])
839 p = row[1] + ',p' + str(ID)
843 parentIDs.append(pID)
844 parentNames.append(pN)
846 if parents[1]==parents[0]:
847 parents[1] = parents[1] + ' 2'
849 return [parents,parentIDs,parentNames]
851 def find_spouses(ID):
854 order = [["IDb","IDa"],["IDa","IDb"]]
860 s = "SELECT name, marriages." + o[0]\
861 +" FROM marriages LEFT JOIN people"\
862 +" ON marriages." +o[0]+" = people.ID"\
863 +" WHERE marriages."+o[1]+" = ?;"
866 for row in run_query(s,t):
868 s = row[0] + "," +str(row[1])
872 s=row[1] + ",s" +str(ID)
877 spousesID.append(sID)
878 spousesNames.append(sN)
880 return [spouses,spousesID,spousesNames]
883 def find_children(ID):
884 s = "SELECT p1.name, p1.ID,p3.parentID,p4.name,p1.bornYear"\
886 +" INNER JOIN parents p2"\
887 +" ON p1.ID = p2.ID"\
888 +" INNER JOIN parents p3"\
889 +" ON p1.ID = p3.ID"\
890 +" LEFT JOIN people"\
891 +" p4 ON p3.parentID = p4.ID"\
892 +" WHERE p2.parentID = ?"\
893 +" AND p3.parentID<>?"\
894 +" ORDER BY p1.bornYear;"
903 for row in run_query(s,t):
904 c = row[0] + ',' + str(row[1])
908 childrenBorn.append(born)
910 op = row[3] + ',' + str(row[2])
914 op = row[2] + ',s' + str(ID)
919 IDs.append([cID,opID])
920 names.append([cName,opN])
922 return [nodes,IDs,names,childrenBorn]
924 def person_info(personID,newLine):
935 #Id, Name, Dates, Style, Style-Dates
936 s = "SELECT * FROM people WHERE ID = ?"
937 for row in run_query(s,t):
939 mainDiv += 'ID: %s%s' %(row[0] ,newLine)
940 mainDiv += print_tagged_name('Name',[row[1], row[0]]\
948 mainDiv += '%sBorn:%s%s '% (newLine,row[3],newLine)
950 mainDiv +='Died: %s' % row[5]
952 if row[6] != 0 and row[4] !=0:
953 mainDiv += ", aged %s" %(row[6]-row[4])
957 s = "SELECT * FROM styles WHERE ID = ?"
958 for row in run_query(s,t):
960 mainDiv +='%sStyle: %s%s'%(newLine,row[1],newLine)
962 mainDiv += 'Territories:%s' % newLine
964 u = "SELECT * FROM territories"\
965 +" WHERE ID =? AND startYear =? AND stopYear=?"
966 v=(personID,row[3],row[5])
969 for r in run_query(u,v):
970 mainDiv += terr_html(r[1],newLine,r[3],r[5]) +','
973 mainDiv = mainDiv[:-1] + newLine
975 mainDiv += 'From: '+row[2] + newLine
976 mainDiv += 'To: '+row[4]
984 s = "SELECT people.Name,consort "\
985 +"FROM consorts LEFT JOIN people"\
986 +" ON people.ID = consorts.consort"\
987 +" WHERE consorts.ID = ?"
988 for row in run_query(s,t):
989 mainDiv += print_tagged_name\
990 ('Consort of',row,newLine)
995 [parents,parentIDs,parentNames] = find_parents(personID)
997 for i in range(len(parents)):
998 r = [parentNames[i],parentIDs[i]]
999 mainDiv += print_tagged_name('Parent',r,newLine)
1004 [spouses,spousesID,spousesNames] = find_spouses(personID)
1008 for i in range(len(spouses)):
1009 r = [spousesNames[i],spousesID[i]]
1010 mainDiv += print_tagged_name('Spouse',r,newLine)
1012 relationship_html(personID,r[1],newLine)
1014 mainDiv = mainDiv + endP
1017 [nodes,IDs,names,childrenBorn] = \
1018 find_children(personID)
1021 for i in range(len(nodes)):
1022 cr = [names[i][0],IDs[i][0]]
1023 thisChild = print_tagged_name('Child',cr,newLine)
1025 opr=[names[i][1],IDs[i][1]]
1027 if i==0 or top != names[i-1][1]:
1030 mainDiv += print_tagged_name\
1031 ('With',opr, newLine)
1034 #age when child born
1035 cb = childrenBorn[i]
1036 if cb!=0 and bornYear != 0:
1038 thisChild = thisChild[:-4] + \
1039 " at the age of "+str(age) + newLine
1040 mainDiv += thisChild
1045 if newLine == '<br>':
1046 output = '<div id = "main" style = " float:left">';
1047 output += mainDiv + "</div>"
1049 output += "<div id = 'image' "\
1050 +"style = 'float:left; margin-left:20px'>"
1054 imageDiv += "<a href=" + url+">"\
1055 +"<img src=" + picture +" alt = 'wiki link'"\
1056 +" title = 'wiki link'></a>"\
1059 elif url!='.' and url!='. ':
1060 imageDiv += "<a href=" + url +">"\
1061 +name + " (wiki link)</a>"+newLine
1063 output += imageDiv + "</div>"
1066 url = 'http://www.chiark.greenend.org.uk/ucgi/~naath/'\
1070 form += "<form id ='controlForm'"\
1071 +" action ="+ url +" method = 'get'>"
1074 "<input type = 'hidden' name = 'ID' value = "\
1078 "Generations of Parents: "\
1079 +"<input type = 'text' name = 'pl' value='1'>"
1082 "Generations of Children: "\
1083 +" <input type = 'text' name = 'cl' value = '1'>"
1086 "Show siblings: <select name = 's'>"+\
1087 "<option value = '0'>No</option>"+\
1088 "<option value = '1'>Yes</option>"+\
1092 "Show spouse's other spouses: <select name = 'os'>"+\
1093 "<option value = '0'>No</option>"+\
1094 "<option value = '1'>Yes</option>"+\
1098 "Show parents' other spouses: <select name = 'pos'>"+\
1099 "<option value = '0'>No</option>"+\
1100 "<option value = '1'>Yes</option>"+\
1105 "<input type = 'text' name = 'fs' value='8'>"
1109 graph = "smallGraph.py?ID="+str(personID)+"&fs=8"
1111 graph = "<img src ="+ graph + '>'
1113 output += "<div id = 'graph' style = 'clear:both'>"
1114 output += "<p id = 'agraph'>"+graph+"</p>"
1115 output += "Draw this graph with more relatives:"
1116 output += newLine + form
1118 output += "<button onclick='myFunction()'>"+\
1125 'function myFunction()'+\
1127 'var x = document.getElementById("controlForm");'+\
1128 'var txt = "<img src = " + x.action + "?";'+\
1129 'for (var i=0;i<x.length;i++)'+\
1131 'var n=x.elements[i].name;'+\
1132 'var v=x.elements[i].value;'+\
1133 'txt = txt + "&"+n+"="+v;'+\
1135 'txt = txt + ">";'+\
1136 'document.getElementById("agraph").innerHTML=txt;'+\
1147 conn = sqlite3.connect\
1148 ('/home/naath/familyTreeProject/familyTree/tree.db')
1152 return conn.cursor()