package edu.byu.cs.roots.opg.util; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Queue; import edu.byu.cs.roots.opg.model.Family; import edu.byu.cs.roots.opg.model.Individual; public class RelationFinder { public ArrayList<Integer> cousins; private HashMap<String, RelationInfo> marriages; private HashMap<String, Integer> hGensAway = new HashMap<String,Integer>(); private HashMap<String, Integer> wGensAway = new HashMap<String,Integer>(); int indiCount; int maxGen; public RelationFinder(Individual indi) { hGensAway = new HashMap<String,Integer>(); wGensAway = new HashMap<String,Integer>(); marriages = new HashMap<String,RelationInfo>(); indiCount = countIndividuals(indi); findMarriageRelations(indi); } public int countIndividuals(Individual indi) { maxGen = 0; HashMap<String,Integer> dup = new HashMap<String,Integer>(); Queue<Individual> queue = new LinkedList<Individual>(); dup.put(indi.id, 0); queue.add(indi); Individual cur; while(!queue.isEmpty()) { cur = queue.remove(); maxGen = Math.max(maxGen, dup.get(cur.id)); if(cur.father != null && !dup.containsKey(cur.father.id)) { dup.put(cur.father.id, dup.get(cur.id)+1); queue.add(cur.father); } if(cur.mother != null && !dup.containsKey(cur.mother.id)) { dup.put(cur.mother.id, dup.get(cur.id)+1); queue.add(cur.mother); } } return dup.size(); } public void findMarriageRelations(Individual indi) { Queue<Individual> queue = new LinkedList<Individual>(); marriages.clear(); Individual cur; //get individuals marriages for(Family fam : indi.fams) { RelationInfo rel = findSpouseRelation(fam.husband, fam.wife); marriages.put(fam.husband.id + fam.wife.id, rel); } queue.add(indi); //get ancestor marriages while(!queue.isEmpty()) { cur = queue.remove(); if(cur.father != null && cur.mother !=null) { String key = cur.father.id + cur.mother.id; if(!marriages.containsKey(key)) { RelationInfo rel = findSpouseRelation(cur.father, cur.mother); marriages.put(key, rel); queue.add(cur.father); queue.add(cur.mother); } } } } public RelationInfo findSpouseRelation(Individual husband, Individual wife) { RelationInfo rel = new RelationInfo(); if(husband != null && wife !=null) { hGensAway.clear(); wGensAway.clear(); markGensAway(husband); rel = findGensAway(wife); rel.husband = husband; rel.wife = wife; } return rel; } protected void markGensAway(Individual indi) { Queue<Individual> queue = new LinkedList<Individual>(); queue.add(indi); hGensAway.put(indi.id,0); while(!queue.isEmpty()) { Individual cur = queue.remove(); if(cur.father != null && !hGensAway.containsKey(cur.father.id)) { hGensAway.put(cur.father.id,hGensAway.get(cur.id)+1); queue.add(cur.father); } if(cur.mother != null && !hGensAway.containsKey(cur.mother.id)) { hGensAway.put(cur.mother.id,hGensAway.get(cur.id)+1); queue.add(cur.mother); } } } protected RelationInfo findGensAway(Individual indi) { RelationInfo rel = new RelationInfo(); Queue<Individual> queue = new LinkedList<Individual>(); queue.add(indi); wGensAway.put(indi.id,0); while(!queue.isEmpty()) { Individual cur = queue.remove(); if(cur.father != null) { if(hGensAway.containsKey(cur.father.id)) { rel.commonAnces = cur.father; rel.fromHusband = hGensAway.get(cur.father.id); rel.fromWife = wGensAway.get(cur.id)+1; return rel; } else if(!wGensAway.containsKey(cur.father.id)) { wGensAway.put(cur.father.id,wGensAway.get(cur.id)+1); queue.add(cur.father); } } if(cur.mother != null) { if(hGensAway.containsKey(cur.mother.id)) { rel.commonAnces = cur.mother; rel.fromHusband = hGensAway.get(cur.mother.id); rel.fromWife = wGensAway.get(cur.id)+1; return rel; } else if(!wGensAway.containsKey(cur.mother.id)) { wGensAway.put(cur.mother.id,wGensAway.get(cur.id)+1); queue.add(cur.mother); } } } return rel; } public void printCousins() { } private class RelationInfo { public Individual commonAnces; public Individual husband; public Individual wife; public int fromHusband; public int fromWife; public RelationInfo(Individual ca, int h, int w) { commonAnces = ca; fromHusband =h; fromWife = w; }; public RelationInfo() { commonAnces = null; fromHusband = -1; fromWife = -1; }; public boolean hasRelation() { if(fromHusband != -1 && fromWife != -1) return true; return false; } public void print() { if(hasRelation() && commonAnces !=null) { System.out.println("Husband: " + husband.givenName + " " +husband.surname + " ( " + fromHusband + " )"); System.out.println("Wife: " + wife.givenName + " " +wife.surname + " ( " + fromWife + " )"); System.out.println("Common Ancestor: " + commonAnces.givenName + " " + commonAnces.surname); System.out.println(); } } } public void printRelation(Individual indi) { for(Family fam : indi.fams) { RelationInfo rel = findSpouseRelation(fam.husband, fam.wife); rel.print(); } } public void printStats() { System.out.println("Number of Marriages: " + marriages.size()); System.out.println("Number of Individuals: " + indiCount); System.out.println("Max Number of Generations: " + maxGen); System.out.println(); ArrayList<Integer> cousins = new ArrayList<Integer>(); for(int i=0; i < 100; i++) cousins.add(0); for(RelationInfo ri : marriages.values()) { int index = Math.min(ri.fromHusband-1, ri.fromWife-1); if(index > -1) cousins.set(index, cousins.get(index) + 1); } int total = 0; for(int i=0; i < cousins.size(); i++) { String suffix = ""; switch (i) { case 1 : suffix = "st"; break; case 2 : suffix = "nd"; break; case 3 : suffix = "rd"; break; default : suffix = "th"; } if(cousins.get(i) > 0) { total += cousins.get(i); System.out.println(i + suffix +" cousins : " + cousins.get(i)); } } System.out.println("Total cousins : " + total); System.out.println("\nDetails:"); for(RelationInfo ri : marriages.values()) { ri.print(); } } }