#include #include #include"tree.h" #include"person.h" #include"help.h" using std::cout; Tree::Tree() : treeName("Unnamed") , numPeople(0) {} Tree Tree::operator+ (const Tree& other)// { Tree result(treeName + other.treeName); //The tree resulting from the addition unsigned *newId = new unsigned[other.numPeople]; //The indexes members of the II tree will have in result unsigned idCounter = numPeople; for (unsigned i = 0, j; i < other.numPeople; ++i) //Searches for people present in both trees and gives them the same index in result { for (j = 0; j < numPeople; ++j) { if (other.people[i] == people[j]) { newId[i] = j; break; } } if (j >= numPeople) newId[i] = ++idCounter; } result.numPeople = idCounter; //The number of members the resulting tree has result.people.resize(result.numPeople); result.people = people; //Adds the members of the I tree to the resulting tree for (unsigned i=0; i < other.numPeople; ++i) //Adds the members of the II tree to the resulting tree { if (newId[i] >= numPeople) result.people.push(other.people[i]); } result.relatives.resize(result.numPeople); result.relations.resize(result.numPeople); result.relatives = relatives; result.relations = relations; for (unsigned i=0; i < other.numPeople; ++i) //Adds the relatives from the II tree { if (newId[i] >= numPeople) //If the member is found in the II tree but not in the I { result.relatives.push(other.relatives[i]); result.relations.push(other.relations[i]); } else //If he's found in both { for (unsigned j = 0; j < other.people[i].numRel; ++j) //Adds the number of relatives from the II to the number in the I { if(newId[other.relatives[i][j]] > numPeople) ++result.people[newId[i]].numRel; } result.relatives[newId[i]].resize(result.people[newId[i]].numRel); result.relations[newId[i]].resize(result.people[newId[i]].numRel); result.relatives[newId[i]] = relatives[newId[i]]; result.relations[newId[i]] = relations[newId[i]]; result.relatives[newId[i]] += other.relatives[i]; //The relatives from the II tree result.relations[newId[i]] += other.relations[i]; } } delete[]newId; return result; } Tree& Tree::operator+=(const Tree& other) { unsigned *newId = new unsigned[other.numPeople]; //The indexes people from II tree will have in I tree unsigned idCounter = numPeople; for (unsigned i = 0, j; i < other.numPeople; ++i) //Searches for people present in both trees and gives them the same index in I { for (j = 0; j < numPeople; ++j) { if (other.people[i] == people[j]) { newId[i] = j; break; } } if (j >= numPeople) newId[i] = idCounter++; } people.resize(idCounter); for (unsigned i = 0; i < other.numPeople; ++i) //Adds the member personal data of II tree to I tree { if (newId[i] >= numPeople) people.push(other.people[i]); } relatives.resize(idCounter); relations.resize(idCounter); for (unsigned i = 0; i < other.numPeople; ++i) //Merges the relative data { if (newId[i] >= numPeople) { relatives.push(other.relatives[i]); for (unsigned j = 0; j < other.people[i].numRel; ++j) relatives[newId[i]][j] = newId[ relatives[newId[i]][j] ]; relations.push(other.relations[i]); } else //If the member is present in both trees { for (unsigned j = 0; j < other.people[i].numRel; ++j) //Adds the number of relatives from the II to the number in the I { if (newId[other.relatives[i][j]] >= numPeople) ++people[newId[i]].numRel; } relatives[newId[i]].resize(people[newId[i]].numRel); relations[newId[i]].resize(people[newId[i]].numRel); for (unsigned j = 0; j < other.people[i].numRel; ++j) { relatives[newId[i]][j + people[newId[i]].numRel - other.people[i].numRel] = newId[other.relatives[i][j]]; relations[newId[i]][j + people[newId[i]].numRel - other.people[i].numRel] = other.relations[i][j]; } } } delete[]newId; numPeople = idCounter; //Number of members in I tree return *this; } Tree& Tree::operator-= (const Tree& other) { for (unsigned i = 0; i < numPeople; ++i) { for (unsigned j = 0; j < other.numPeople; ++j) { if (people[i] == other.people[j]) { removePerson(i); --i; break; } } } return *this; } void Tree::rename(const char* newName) { treeName = newName; } unsigned Tree::findId(const char* name, const short year, const unsigned char month, const unsigned char day)const { //TODO //Person sought(name, day, month, year,) for (unsigned i = 0; i < numPeople; ++i) { if (name == people[i].name) //&& (year == people[i].year || !year || !people[i].year) && (month == people[i].month || !month || !people[i].month) && (day == people[i].day || !day || people[i].day)) return i; } return Nobody; } unsigned Tree::findOldestAncestor(const unsigned &id, const bool &isMale)const { for (unsigned i = 0; i < people[id].numRel; ++i) { if (relations[id][i] == Son && people[ relatives[id][i] ].isMale == isMale) return findOldestAncestor(relatives[id][i], isMale); } return id; } unsigned Tree::findCommonAncestor(const unsigned firstId, const unsigned secondId)const { Array visited(numPeople); //if a member is visited twice he's a common ancestor for (unsigned i = 0; i < numPeople; ++i) visited[i] = 0; commonAncestorRec(firstId, visited); commonAncestorRec(secondId, visited); unsigned oldestId = Nobody; U16 oldestBday = SHRT_MAX; for (unsigned i = 0; i < numPeople; ++i) { if (visited[i] == 2 && people[i].birth.year(&numPeople), sizeof(numPeople)); for (unsigned i = 0; i < numPeople; ++i) people[i].save(peopleFile); peopleFile.close(); std::ofstream relativeFile(treeName + ".relatives", std::ios::binary); std::ofstream relationFile(treeName + ".relations", std::ios::binary); /*relativeFile.write((char*)&numPeople, sizeof(numPeople)); relationFile.write((char*)&numPeople, sizeof(numPeople));*/ for (unsigned i = 0; i < numPeople; ++i) { //relativeFile.write((char*)&people[i].numRel, sizeof(people[i].numRel)); for (unsigned j = 0; j < people[i].numRel; ++j) relativeFile.write(reinterpret_cast(&relatives[i][j]), sizeof(relatives[i][j])); //relationFile.write((char*)&people[i].numRel, sizeof(people[i].numRel)); for (unsigned j = 0; j < people[i].numRel; ++j) relationFile.write(reinterpret_cast(&relations[i][j]), sizeof(relations[i][j])); } relativeFile.close(); relationFile.close(); } bool Tree::loadTree() { std::ifstream peopleFile(treeName + ".people", std::ios::binary); if (peopleFile.peek() == std::char_traits::eof()) { peopleFile.close(); return 0; } peopleFile.read(reinterpret_cast(&numPeople), sizeof(numPeople)); people.resize(numPeople); for (unsigned i = 0; i < numPeople; ++i) people[i].load(peopleFile); people.sNum(numPeople); peopleFile.close(); std::ifstream relativeFile(treeName + ".relatives", std::ios::binary); std::ifstream relationFile(treeName + ".relations", std::ios::binary); relatives.resize(numPeople); relations.resize(numPeople); for (unsigned i = 0; i < numPeople; ++i) { relatives[i].resize(people[i].numRel); for (unsigned j = 0; j < people[i].numRel; ++j) relativeFile.read(reinterpret_cast(&relatives[i][j]), sizeof(relatives[i][j])); relatives[i].sNum(people[i].numRel); relations[i].resize(people[i].numRel); for (unsigned j = 0; j < people[i].numRel; ++j) relationFile.read(reinterpret_cast(&relations[i][j]), sizeof(relations[i][j])); relations[i].sNum(people[i].numRel); } relatives.sNum(numPeople); relations.sNum(numPeople); relativeFile.close(); relationFile.close(); return 1; } void Tree::addPerson(const char *name, EventTime birth, bool isMale, unsigned father, unsigned mother) { Person newPerson(name, birth, isMale); people.push(newPerson); Array newRelative; relatives.push(newRelative); Array newRelation; relations.push(newRelation); ++numPeople; addRelation(father, Father, numPeople - 1); addRelation(mother, Mother, numPeople - 1); } bool Tree::addRelation(const char* firstName, const Relation type, const char* secondName) { return addRelation(findId(firstName), type, findId(secondName)); } bool Tree::addRelation(const unsigned firstId, const Relation type, const unsigned secondId, bool opposite)// { if (firstId == Nobody || firstId >= numPeople || secondId == Nobody || secondId >= numPeople || type == Invalid) return 0; unsigned i = 0; for (; i < people[firstId].numRel; ++i) //If they are already relatives { if (relatives[firstId][i] == secondId) { relations[firstId][i] = type; break; } } if (i >= people[firstId].numRel) { relatives[firstId].push(secondId); relations[firstId].push(type); ++people[firstId].numRel; } if (!opposite) { if (people[secondId].isMale) { switch (type) { case Father: case Mother: addRelation(secondId, Son, firstId, 1); break; case Son: case Daughter: addRelation(secondId, Father, firstId, 1); break; case Brother: case Sister: addRelation(secondId, Brother, firstId, 1); break; case HalfBrother: case HalfSister: addRelation(secondId, HalfBrother, firstId, 1); break; case Wife: addRelation(secondId, Husband, firstId, 1); break; case ExWife: addRelation(secondId, ExHusband, firstId, 1); break; } } else { switch (type) { case Father: case Mother: addRelation(secondId, Daughter, firstId, 1); break; case Son: case Daughter: addRelation(secondId, Mother, firstId, 1); break; case Brother: case Sister: addRelation(secondId, Sister, firstId, 1); break; case HalfBrother: case HalfSister: addRelation(secondId, HalfSister, firstId, 1); break; case Husband: addRelation(secondId, Wife, firstId, 1); break; case ExHusband: addRelation(secondId, ExWife, firstId, 1); break; } } } return 1; } void Tree::removeRelation(const char* firstName, const char* secondName) { removeRelation(findId(firstName), findId(secondName)); } void Tree::removePerson(const unsigned id) { unsigned relId; //Íoìåð íà òåêóùèÿ ðîäíèíàòà for (unsigned i = 0; i < people[id].numRel; ++i) //Ïðåìàõâàò ñå âðúçêèòå íà ÷ëåíà çà ïðåìàõâàíå { relId = relatives[id][i]; for (unsigned j = 0; j < people[relId].numRel; ++j) { if (relatives[relId][j] == id) { relatives[relId].remove(j); relations[relId].remove(j); break; } } --people[relId].numRel; } for (unsigned i = 0; i < people[numPeople - 2].numRel; ++i) //Ïîñëåäíèÿò ÷ëåí âçåìà íîìåðà íà ïðåìàõíàòèÿ { relId = relatives[numPeople - 1][i]; for (unsigned j = 0; j < people[relId].numRel; ++j) { if (relatives[relId][j] == numPeople - 1) { relatives[relId][j] = id; break; } } } relatives.remove(id); relations.remove(id); people.remove(id); --numPeople; } void Tree::removePerson(const char* personName, const short year, const unsigned char month, const unsigned char day) { removePerson(findId(personName, year, month, day)); } void Tree::removeRelation(const unsigned firstId, const unsigned secondId) { for (unsigned i = 0; i < people[firstId].numRel; ++i) { if (relatives[firstId][i] == secondId) { relatives[firstId].remove(i); relations[firstId].remove(i); --people[firstId].numRel; break; } } for (unsigned i = 0; i < people[secondId].numRel; ++i) { if (relatives[secondId][i] == firstId) { relatives[secondId].remove(i); relations[secondId].remove(i); --people[secondId].numRel; break; } } } void Tree::print() const { //for(const auto& member: people) // member.print(); for(int i=0; i &visited)const { for (unsigned i = 0; i < people[id].numRel; ++i) { if (relations[id][i] == Son) { ++visited[relatives[id][i]]; commonAncestorRec(relatives[id][i], visited); } } }