5 from string import Template
8 link_Template= Template(\
9 "<a href = http://www.chiark.greenend.org.uk/ucgi/~naath/$script"\
10 +" title=$title>$text</a>")
19 def print_row(row,newLine):
22 out = out + str(item)+'|'
23 return out[:-1] + newLine
25 def print_query(s,t,newLine):
27 for row in run_query(s,t):
28 printMe = printMe + print_row(row,newLine)
38 def print_tagged_query(relationship,s,t,newLine):
40 for row in run_query(s,t):
41 mine = mine + print_tagged_name(relationship,row,newLine)
45 def relationship_html(ID,ID2,newLine):
47 relationship = common_ancestors(ID,ID2,newLine)[2]
49 if relationship[-11:] != 'not related':
50 script = "ancestors.py?ID="+str(ID)+"&ID2="+str(ID2)
51 url = link_Template.substitute\
52 (script = script,title = "Common ancestors"\
53 ,text = "Common ancestors")
54 return relationship + ' '+url + newLine
56 return relationship + newLine
60 def terr_html(terr,newLine,start,stop):
62 if start == 0 and stop ==0:
63 myTitle = add_quotes(terr)
66 s = "SELECT name,people.id"\
67 +" FROM people INNER JOIN territories"\
68 +" ON people.id = territories.id"\
69 +" WHERE territory = ? AND stopyear <= ?"\
70 +" ORDER BY startyear DESC;"
74 for row in run_query(s,t):
75 myTitle = myTitle +"previous - " + row[0] \
79 u = "SELECT name,people.id"\
80 +" FROM people INNER JOIN territories"\
81 +" ON people.id = territories.id"\
82 +" WHERE territory = ? AND startyear >= ?"\
83 +" ORDER BY startyear;"
86 for r in run_query(u,v):
87 myTitle = myTitle + '
' +"next - " + r[0] \
91 myTitle = add_quotes(myTitle)
93 return link_Template.substitute(\
94 script = "territory.py?terr="+terr, title=myTitle,\
98 def name_html(row,html):
110 script = "person.py?ID=" + str(row[1])
112 return link_Template.substitute(script = script\
113 ,title = add_quotes(name),text = name)
115 return row[0] + "," +str(row[1])
123 def print_age_child_count(row,newLine):
124 if newLine == '<br>':
125 script = "age.py?age="+str(row[0])
126 link = link_Template.substitute(script = \
127 script, title = add_quotes(row[0]), text = row[0])
128 out = str(row[1])+print_people(row[1])
130 out = out + 'had children at age '+ link + newLine
133 return print_row(row,newLine)
135 def print_age_death_count(row,newLine):
137 script = "ageDeath.py?age="+str(row[0])
138 link = link_Template.substitute(script = script,\
139 title = add_quotes(row[0]),text = row[0])
140 out = str(row[1])+print_people(row[1])
141 out = out + "died at age " + link + newLine
144 return print_row(row,newLine)
146 def print_name_count(row,newLine):
148 script = "name.py?name=" + row[0]
149 link = link_Template.substitute(script =\
150 script, title = add_quotes(row[0]),text = row[0])
151 return str(row[1]) + " people called "+link + newLine
153 return print_row(row,newLine)
155 def print_tagged_name(relationship,row,newLine):
157 out = relationship + " not yet entered: " + row[1]
159 if newLine == '<br>':
163 if relationship =='':
164 out = name_html(row,html) + ' '
166 out = relationship + ": " + name_html(row,html)
169 def month_numbers(monthN):
171 month ='unknown month'
197 month = 'Incorrectly entered month ' + str(monthN)
200 def ordinal_numbers(number):
202 if number % 10==1 and number/10 % 10 !=1:
203 out = str(number) +'st'
204 elif number % 10==2 and number/10 % 10 !=1:
205 out = str(number) +'nd'
206 elif number % 10==3 and number/10 % 10 !=1:
207 out = str(number) +'rd'
209 out = str(number) +'th'
212 def list_territories(newLine):
213 s = "SELECT DISTINCT territory"\
214 +" FROM territories"\
215 +" ORDER BY territory;"
218 for row in run_query(s,()):
219 out =out + terr_html(row[0],newLine,0,0) +newLine
222 def list_people_parents():
223 s = "SELECT name,id"\
228 for row in run_query(s,()):
231 [parents, parentIDs,parentNames] = find_parents(ID)
232 [spouses,spousesID,spousesNames] = find_spouses(ID)
234 [self,myID,myName] = find_person(ID)
235 output.append([self,parents,spouses])
239 def list_people(newLine):
240 s = "SELECT name,id,bornyear"\
242 +" ORDER BY bornyear;"
246 out = out + 'born in unknown year:' +newLine
247 for row in run_query(s,()):
248 if row[2]!=0 and row[2]/100==0:
249 out = out +newLine+ 'born in 1st century:' +newLine
251 if row[2]/100!=year/100:
252 century = row[2]/100 + 1
253 out = out +newLine+ 'born in '
255 out = out +ordinal_numbers(century) \
256 + ' century:' + newLine
258 out = out + name_html(row,newLine) +newLine
260 if row[2] == 0: #unknown year
262 t = (row[1],) #person ID
266 u = "SELECT diedyear FROM people WHERE ID = ?;"
269 for r in run_query(u,t):
271 out = out + "died: "\
272 + str(r[0]) + newLine
273 bornAfter = r[0] -100
276 u = "Select people.bornYear from"\
277 +" people INNER JOIN parents"\
278 +" ON people.ID = parents.ID"\
279 +" WHERE parents.parentID = ?"\
280 + " ORDER BY people.bornYear;"
284 for r in run_query(u,t):
286 hadChild.append(r[0])
290 out = out + "had children in: "
292 out = out + str(c) + ','
293 out = out[:-1] + newLine
295 bornBefore = hadChild[0]-12
297 bornAfter = hadChild[0]-100
299 u = "Select styles.startYear, styles.style from"\
300 +" people INNER JOIN styles"\
301 +" ON people.ID = styles.ID"\
302 +" WHERE people.ID = ? and"\
303 +" styles.startYear <>0"\
304 +" ORDER BY styles.startYear;"
306 for r in run_query(u,t):
307 out = out + r[1] + " from " + str(r[0])\
310 bornAfter = r[0] -100
315 out = out + "probably born "\
316 +"after " + str(bornAfter)
318 out = out + "probably born "\
319 +"betwen " + str(bornAfter)\
320 +" and " + str(bornBefore)
326 def count_names(newLine):
327 s = "SELECT firstName, count(*)"\
329 +" GROUP BY firstName"\
330 +" ORDER BY count(*) DESC;"
333 for row in run_query(s,()):
334 out = out + print_name_count(row,newLine)
339 def search_name(name,newLine):
340 s = "SELECT name, ID"\
342 +" WHERE name LIKE ?;"
346 out = out + 'Names start with ' + name + ':' + newLine
349 for row in run_query(s,t):
350 out = out + name_html(row,newLine) + newLine
351 fullIDs.append(row[1])
352 t = ('%' + name + '%',)
353 out = out+newLine + 'Names contain ' + name + ':' + newLine
354 for row in run_query(s,t):
355 if row[1] not in fullIDs:
356 out = out + name_html(row,newLine) + newLine
358 s = "SELECT name,people.ID,style"\
359 +" FROM people INNER JOIN styles"\
360 +" ON styles.id = people.id"\
361 +" WHERE style LIKE ?;"
362 out = out +newLine+ 'Styles contain ' + name + ':' + newLine
363 for row in run_query(s,t):
364 out = out + name_html(row,newLine)+' ' + row[2] + newLine
369 def people_with_name(name,newLine):
370 s = "SELECT name, ID"\
372 +" WHERE firstname = ?;"
378 for row in run_query(s,t):
379 out = out + name_html(row,newLine) + newLine
383 def count_birth_month(newLine):
384 s = "SELECT bornMonth, count(*)"\
386 +" GROUP BY bornMonth"\
387 +" ORDER BY bornMonth;"
389 t = "SELECT * FROM people WHERE bornMonth = ?;"
392 for row in run_query(s,()):
393 month = month_numbers(row[0])
394 out = out + month + ': ' + str(row[1]) + newLine
398 out = out +print_query(t,u,newLine)
402 def count_death_month(newLine):
403 s = "SELECT diedMonth, count(*)"\
405 +" GROUP BY diedMonth"\
406 +" ORDER BY diedMonth;"
408 t = "SELECT * FROM people WHERE diedMonth = ?;"
411 for row in run_query(s,()):
412 month = month_numbers(row[0])
413 out = out + month + ': ' + str(row[1]) + newLine
417 out = out +print_query(t,u,newLine)
421 def count_age_at_child(newLine):
423 s = "select p1.bornYear - p2.bornYear as age, count(*)"\
425 +" parents INNER JOIN people p1"\
426 +" ON parents.ID = p1.ID"\
427 +" INNER JOIN people p2"\
428 +" ON parents.parentID = p2.ID"\
429 +" WHERE p1.bornYear <> 0 and p2.bornYear<>0"\
433 for row in run_query(s,()):
434 out = out + print_age_child_count(row,newLine)
438 def people_had_child_at_age(age,newLine):
440 s = "select p1.bornYear - p2.bornYear as age, p1.name, p1.ID"\
441 +",p2.name,p2.ID FROM"\
442 +" parents INNER JOIN people p1"\
443 +" ON parents.ID = p1.ID"\
444 +" INNER JOIN people p2"\
445 +" ON parents.parentID = p2.ID"\
446 +" WHERE age = ? AND p1.bornYear<>0 AND p2.bornYear<>0"
451 out = 'At age ' + str(age) + ' :'
452 for row in run_query(s,t):
454 out =out + name_html([row[3],row[4]],newLine) + ' had '\
455 +name_html([row[1],row[2]],newLine)
459 def count_age_at_death(newLine):
460 s = "select diedYear-bornYear as age,count(*)"\
462 +" WHERE diedYear<>0 AND bornYear<>0"\
465 for row in run_query(s,()):
466 out = out + print_age_death_count(row,newLine)
469 def people_died_at_age(age,newLine):
470 s = "SELECT diedYear-bornYear as age, name,ID"\
472 +" WHERE age = ? AND bornYear<>0 AND diedYear<>0;"
475 out = 'These people died at age ' +str(age) + ' :'
476 for row in run_query(s,t):
478 out = out + name_html([row[1],row[2]],newLine)
481 def all_ancestors(personID,newLine):
484 ancestors = [personID]
485 allAncestors = [personID]
489 t = "SELECT name,id FROM people WHERE id=?"
492 out = "Ancestors of "
493 for row in run_query(t,id):
494 out = out + name_html(row,newLine)+newLine
497 aDict[level] = ancestors
498 while len(ancestors)>0:
501 thisout = newLine + parent_level(level,'parent') +\
503 for ancestor in ancestors:
504 [parents, parentIDs,parentNames] \
505 = find_parents(ancestor)
506 for i in range(len(parents)):
507 r = [parentNames[i],parentIDs[i]]
508 thisout = thisout + \
509 name_html(r,newLine)+newLine
511 if r[1] not in allAncestors\
514 allAncestors.append(r[1])
515 trackLevel.append(level)
519 aDict[level]=ancestors
523 image = "<img src = ancestorGraph.py?id="+str(personID)+">"
524 out = out+newLine + image+newLine
525 return [out, allAncestors,trackLevel,aDict]
528 def common_ancestors(IDA, IDB,newLine):
529 out = 'Common ancestors of:' + newLine
531 s = "SELECT name,id FROM people WHERE id==?"
537 for row in run_query(s,t):
538 out = out + name_html(row,newLine)+newLine
545 related = 'No details held on one party'
547 return [out,[],related]
550 a = all_ancestors(IDA,newLine)
551 b = all_ancestors(IDB,newLine)
553 ancestorsB = set(b[1])
554 ancestorsA = set(a[1])
556 common = ancestorsA.intersection(ancestorsB)
557 common = list(common)
564 aLevels.append(a[2][i])
566 bLevels.append(b[2][i])
568 s = "SELECT Name, ID, bornyear"\
571 for i in range(len(common)):
575 s = s+") ORDER BY bornyear;"
579 related = names[0]+' and '+names[1]+' are not related'
580 out = out + newLine + related
581 return [out, common,related]
584 out = out + print_tagged_query('',s,common,newLine)
589 for i in range(len(common)):
590 if aLevels[i] == min(aLevels):
592 if bLevels[i] == min(bLevels):
597 s = "SELECT name, id"\
601 out = out + newLine + 'Most Recent Common Ancestors:' + newLine
605 mrca.append(common[a])
606 out = out + print_tagged_query('',s,t,newLine)
608 out = out + 'and' + newLine
610 out = out + parent_level(aLevels[indexA[0]],'parent')
614 out = out + ' of ' + name_html([names[0],IDA],newLine)+newLine
619 # out = out + print_tagged_query('',s,t,newLine)
621 # out = out + 'and' + newLine
623 out = out + parent_level(bLevels[indexB[0]],'parent')
626 out = out + ' of ' + name_html([names[1],IDB],newLine)+newLine
629 al = aLevels[indexA[0]]
630 bl = bLevels[indexB[0]]
632 related = relationship(al,bl,names)
633 out = out+newLine + related
636 image = "<img src = jointAncestorGraph.py?id="+str(IDA)\
637 +"&id2="+str(IDB) + "&LA=" + str(min(aLevels)) \
638 +"&LB=" + str(min(bLevels))+">"
642 out = out+newLine + image+newLine
644 return [out,common,related]
646 def relationship(level1, level2,names):
648 if level1==0 and level2==0:
649 return names[0] + ' is ' +names[1]
651 return names[0] + ' is ' + names[1] + '\'s '+ parent_level(level2,'parent')
653 return names[1] + ' is ' + names[0] + '\'s '+ parent_level(level1,'parent')
657 remove = level1-level2
660 remove = level2-level1
664 uaLevel = parent_level(remove,'uncle or aunt')
666 return names[0] + ' is ' + names[1] + '\'s ' + uaLevel
669 return names[1] + ' is ' + names[0] + '\'s ' + uaLevel
671 c=ordinal_numbers(cousinNum)
677 rem = str(remove) + ' times'
679 r = names[0] +' and '+names[1] +' are ' + c + ' cousins '
681 r = r+ rem + ' removed'
685 def parent_level(level,type):
700 for i in range(2,level):
704 def rulers_of(aTerritory,newLine):
706 tq = "SELECT name, people.ID, startyear,stopyear,territory"\
707 +" FROM territories INNER JOIN people"\
708 +" ON people.ID = territories.ID"\
709 +" WHERE territory LIKE ?"\
710 +" ORDER BY territory,startyear,stopyear;"
717 for row in run_query(tq,(aTerritory+'%',)):
718 if row[4]!=last and last!='':
719 out = out + 'Rulers of '+terr_html(last,newLine,0,0) \
720 +':'+ newLine +thisT +newLine
723 thisT = thisT +name_html(row,newLine)
724 thisT = thisT +' from ' + str(row[2])+' to '+str(row[3]) + newLine
727 out = out + 'Rulers of '+terr_html(row[4],newLine,0,0) +':'+ \
733 s = "SELECT name || ','||ID, name, ID FROM people WHERE ID=?"
736 for row in run_query(s,t):
740 return [Self, selfID,selfName]
742 def find_parents(ID):
743 s = "SELECT name, parentID"\
744 +" FROM parents LEFT JOIN people"\
745 +" ON people.ID = parentID"\
746 +" WHERE parents.ID = ?;"
753 for row in run_query(s,t):
755 p = row[0] + ',' + str(row[1])
759 p = row[1] + ',p ' + str(ID)
763 parentIDs.append(pID)
764 parentNames.append(pN)
766 if parents[1]==parents[0]:
767 parents[1] = parents[1] + ' 2'
769 return [parents,parentIDs,parentNames]
771 def find_spouses(ID):
774 order = [["IDb","IDa"],["IDa","IDb"]]
780 s = "SELECT name, marriages." + o[0]\
781 +" FROM marriages LEFT JOIN people"\
782 +" ON marriages." +o[0]+" = people.ID"\
783 +" WHERE marriages."+o[1]+" = ?;"
786 for row in run_query(s,t):
788 s = row[0] + "," +str(row[1])
792 s=row[1] + ",s " +str(ID)
797 spousesID.append(sID)
798 spousesNames.append(sN)
800 return [spouses,spousesID,spousesNames]
803 def find_children(ID):
804 s = "SELECT p1.name, p1.ID,p3.parentID,p4.name,p1.bornYear"\
806 +" INNER JOIN parents p2"\
807 +" ON p1.ID = p2.ID"\
808 +" INNER JOIN parents p3"\
809 +" ON p1.ID = p3.ID"\
810 +" LEFT JOIN people"\
811 +" p4 ON p3.parentID = p4.ID"\
812 +" WHERE p2.parentID = ?"\
813 +" AND p3.parentID<>?"\
814 +" ORDER BY p1.bornYear;"
826 for row in run_query(s,t):
827 c = row[0] + ',' + str(row[1])
832 childrenID.append(cID)
833 childrenNames.append(cName)
834 childrenBorn.append(born)
836 op = row[3] + ',' + str(row[2])
840 op = row[2] + ',s ' + ID
843 otherparents.append(op)
844 otherparentsID.append(opID)
845 otherparentsNames.append(opN)
847 return [children,childrenID,childrenNames\
848 ,otherparents,otherparentsID,otherparentsNames\
851 def person_info(personID,newLine):
855 #Id, Name, Dates, Style, Style-Dates
856 s = "SELECT * FROM people WHERE ID = ?"
857 for row in run_query(s,t):
858 mainDiv = mainDiv + '<p>'
859 mainDiv = mainDiv + 'ID: '+str(row[0]) +newLine
860 mainDiv = mainDiv + print_tagged_name('Name',[row[1], row[0]]\
862 mainDiv = mainDiv + '</p>'
867 mainDiv = mainDiv + '<p>'
868 mainDiv = mainDiv + newLine + 'Born: '+row[3] + newLine
870 mainDiv = mainDiv + 'Died: '+row[5]
872 if row[6] != 0 and row[4] !=0:
873 mainDiv = mainDiv + ", aged " \
875 mainDiv = mainDiv + '</p>'
878 s = "SELECT * FROM styles WHERE ID = ?"
879 for row in run_query(s,t):
880 mainDiv = mainDiv + '<p>'
881 mainDiv = mainDiv +newLine+ 'Style: '+row[1] + newLine
883 mainDiv = mainDiv + 'Territories:' + newLine
885 u = "SELECT * FROM territories"\
886 +" WHERE ID =? AND startYear =? AND stopYear=?"
887 v=(personID,row[3],row[5])
890 for r in run_query(u,v):
892 + terr_html(r[1],newLine,r[3],r[5])\
896 mainDiv = mainDiv[:-1] + newLine
898 mainDiv = mainDiv + 'From: '+row[2] + newLine
899 mainDiv = mainDiv + 'To: '+row[4]
901 mainDiv = mainDiv + '</p>'
906 mainDiv = mainDiv + '<p>'
907 s = "SELECT people.Name,consort "\
908 +"FROM consorts LEFT JOIN people"\
909 +" ON people.ID = consorts.consort"\
910 +" WHERE consorts.ID = ?"
911 for row in run_query(s,t):
912 mainDiv = mainDiv + print_tagged_name\
913 ('Consort of',row,newLine)
914 mainDiv = mainDiv + '</p>'
918 [parents,parentIDs,parentNames] = find_parents(personID)
919 mainDiv = mainDiv + '<p>'
920 for i in range(len(parents)):
921 r = [parentNames[i],parentIDs[i]]
922 mainDiv = mainDiv + print_tagged_name('Parent',r,newLine)
923 mainDiv = mainDiv + "</p>"
927 [spouses,spousesID,spousesNames] = find_spouses(personID)
929 mainDiv = mainDiv + '<p>'
931 for i in range(len(spouses)):
932 r = [spousesNames[i],spousesID[i]]
933 mainDiv = mainDiv + print_tagged_name('Spouse',r,newLine)
934 mainDiv = mainDiv + \
935 relationship_html(personID,r[1],newLine)
937 mainDiv = mainDiv + '</p>'
940 [children,childrenID,childrenNames\
941 ,otherparents,otherparentsID,otherparentsNames\
943 find_children(personID)
946 for i in range(len(children)):
947 cr = [childrenNames[i],childrenID[i]]
948 thisChild = print_tagged_name('Child',cr,newLine)
950 opr=[otherparentsNames[i],otherparentsID[i]]
951 top = otherparentsNames[i]
952 if i==0 or top != otherparentsNames[i-1]:
953 mainDiv = mainDiv +'</p>'
954 mainDiv = mainDiv + '<p>'
955 mainDiv = mainDiv + print_tagged_name\
956 ('With',opr, newLine)
961 if cb!=0 and bornYear != 0:
963 thisChild = thisChild[:-4] + \
964 " at the age of "+str(age) + newLine
965 mainDiv = mainDiv + thisChild
967 mainDiv = mainDiv + '</p>'
969 output = '<div id = "main" style = " float:left">';
970 output = output + mainDiv + "</div>"
972 output = output + "<div id = 'image' "\
973 +"style = 'float:left; margin-left:20px'>"
977 imageDiv = imageDiv + "<a href=" + url+">"\
978 +"<img src=" + picture +" alt = 'wiki link'"\
979 +" title = 'wiki link'></a>"\
982 elif url!='.' and url!='. ':
983 imageDiv = imageDiv + "<a href=" + url +">"\
984 +name + " (wiki link)</a>"+newLine
986 output = output + imageDiv + "</div>"
988 graph = "smallGraph.py?ID="+str(personID)
990 graph ="<img src ="+ graph + '>'
992 output = output + "<div id = 'graph' style = 'clear:both'>"
993 output = output + graph
994 output = output + "</div>"
1002 conn = sqlite3.connect('/home/naath/familyTreeProject/familyTree/tree.db')
1006 return conn.cursor()
1013 # [c, conn] = connect()