fix save and load
This commit is contained in:
@@ -24,18 +24,21 @@ int main()
|
|||||||
init_pair(COLOR_SELECTED, COLOR_YELLOW, -1);
|
init_pair(COLOR_SELECTED, COLOR_YELLOW, -1);
|
||||||
wnoutrefresh(stdscr); /* if not present the first real refresh is missed */
|
wnoutrefresh(stdscr); /* if not present the first real refresh is missed */
|
||||||
|
|
||||||
Tree test1("Dechkovi"); //addTree Dechkovi addTree Karamanovi load 0 load 1 (to work with these example trees)
|
Tree test1("Dechkovi");
|
||||||
|
test1.loadFromFile();
|
||||||
|
|
||||||
Tree test2("Karamanovi");
|
Tree test2("Karamanovi");
|
||||||
|
|
||||||
test1.addPerson("Rumen", true, Nobody, Nobody, {1968, 8, 9});
|
/* test1.addPerson("Rumen", true, Nobody, Nobody, {1968, 8, 9}); */
|
||||||
test1.addPerson("Nadejda", false, Nobody, Nobody, {1972, 12, 15});
|
/* test1.addPerson("Nadejda", false, Nobody, Nobody, {1972, 12, 15}); */
|
||||||
test1.addRelation(0, Spouse, 1);
|
/* test1.addRelation(0, Spouse, 1); */
|
||||||
test1.addPerson("Venelin", true, 0, 1, {1998, 6, 9});
|
/* test1.addPerson("Venelin", true, 0, 1, {1998, 6, 9}); */
|
||||||
test1.addPerson("Vasil", true, 0, 1, {2001, 1, 16});
|
/* test1.addPerson("Vasil", true, 0, 1, {2001, 1, 16}); */
|
||||||
/* test1.addRelation(2, Brother, 3); */
|
/* test1.addRelation(2, Brother, 3); */
|
||||||
/* test1.addPerson("Maria-Veronika", 2009, 9, 3, 1, 0, 1); */
|
/* test1.addPerson("Maria-Veronika", 2009, 9, 3, 1, 0, 1); */
|
||||||
/* test1.addRelation(2, Brother, 4); */
|
/* test1.addRelation(2, Brother, 4); */
|
||||||
/* test1.addRelation(3, Brother, 4); */
|
/* test1.addRelation(3, Brother, 4); */
|
||||||
|
test1.saveToFile();
|
||||||
|
|
||||||
test2.addPerson("Vasil Dimitrov", true, Nobody, Nobody, {1941, 5, 18});
|
test2.addPerson("Vasil Dimitrov", true, Nobody, Nobody, {1941, 5, 18});
|
||||||
test2.addPerson("Maria", false);
|
test2.addPerson("Maria", false);
|
||||||
@@ -58,8 +61,7 @@ int main()
|
|||||||
/* test1.display(); */
|
/* test1.display(); */
|
||||||
|
|
||||||
|
|
||||||
/* test1.saveTree(); */
|
/* test2.saveToFile(); */
|
||||||
/* test2.saveTree(); */
|
|
||||||
|
|
||||||
Tree firstTree("firstTree");
|
Tree firstTree("firstTree");
|
||||||
|
|
||||||
@@ -86,7 +88,7 @@ int main()
|
|||||||
|
|
||||||
/* firstTree.print(); */
|
/* firstTree.print(); */
|
||||||
firstTree.display();
|
firstTree.display();
|
||||||
/* firstTree.saveTree(); */
|
/* firstTree.saveToFile(); */
|
||||||
|
|
||||||
/* firstTree.printRel(3); */
|
/* firstTree.printRel(3); */
|
||||||
firstTree.printOldestAncestors(3);
|
firstTree.printOldestAncestors(3);
|
||||||
@@ -167,11 +169,11 @@ int main()
|
|||||||
/* case 2: //load */
|
/* case 2: //load */
|
||||||
/* cin >> input; */
|
/* cin >> input; */
|
||||||
/* trees.push(Tree(input)); */
|
/* trees.push(Tree(input)); */
|
||||||
/* if (!trees[trees.gNum() - 1].loadTree()) */
|
/* if (!trees[trees.gNum() - 1].loadFromFile()) */
|
||||||
/* std::cout << "File doesnt exist or is empty.\n\n"; */
|
/* std::cout << "File doesnt exist or is empty.\n\n"; */
|
||||||
/* break; */
|
/* break; */
|
||||||
/* case 3: //save */
|
/* case 3: //save */
|
||||||
/* trees[curTree].saveTree(); */
|
/* trees[curTree].saveToFile(); */
|
||||||
/* break; */
|
/* break; */
|
||||||
/* case 4: //addPerson */
|
/* case 4: //addPerson */
|
||||||
/* std::cin >> name >> day >> month >> year >> sex; */
|
/* std::cin >> name >> day >> month >> year >> sex; */
|
||||||
|
|||||||
+3
-6
@@ -62,7 +62,6 @@ void EventTime::print() const
|
|||||||
|
|
||||||
Person::Person(const char* name, EventTime birth, bool isMale, EventTime death)
|
Person::Person(const char* name, EventTime birth, bool isMale, EventTime death)
|
||||||
: name_(name)
|
: name_(name)
|
||||||
, numRel_(0)
|
|
||||||
, birth_(birth)
|
, birth_(birth)
|
||||||
, isMale_(isMale)
|
, isMale_(isMale)
|
||||||
, death_(death)
|
, death_(death)
|
||||||
@@ -72,24 +71,23 @@ Person::Person(const char* name, EventTime birth, bool isMale, EventTime death)
|
|||||||
|
|
||||||
bool Person::operator==(const Person &other)const
|
bool Person::operator==(const Person &other)const
|
||||||
{
|
{
|
||||||
return name_ == other.name_ && isMale_ == other.isMale_; //TODO && day == other.day || !day || !other.day) && (month == other.month || !month || !other.month) && (year == other.year || !year || !other.year);
|
return name_ == other.name_; //&& isMale_ == other.isMale_; //TODO && day == other.day || !day || !other.day) && (month == other.month || !month || !other.month) && (year == other.year || !year || !other.year);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Person::save(std::ofstream &file)const
|
void Person::write(std::ofstream &file)const
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
char nameLen = name_.size();
|
char nameLen = name_.size();
|
||||||
file.write(reinterpret_cast<char*>(&nameLen), sizeof(nameLen));
|
file.write(reinterpret_cast<char*>(&nameLen), sizeof(nameLen));
|
||||||
file.write(name_.data(), nameLen * sizeof(name_[0]));
|
file.write(name_.data(), nameLen * sizeof(name_[0]));
|
||||||
file.write(reinterpret_cast<const char*>(&numRel_), sizeof(numRel_));
|
|
||||||
file.write(reinterpret_cast<const char*>(&isMale_), sizeof(isMale_));
|
file.write(reinterpret_cast<const char*>(&isMale_), sizeof(isMale_));
|
||||||
//file.write(reinterpret_cast<const char*>(&day), sizeof(day)); TODO
|
//file.write(reinterpret_cast<const char*>(&day), sizeof(day)); TODO
|
||||||
//file.write(reinterpret_cast<const char*>(&month), sizeof(month));
|
//file.write(reinterpret_cast<const char*>(&month), sizeof(month));
|
||||||
//file.write(reinterpret_cast<const char*>(&year), sizeof(year));
|
//file.write(reinterpret_cast<const char*>(&year), sizeof(year));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Person::load(std::ifstream &file)
|
void Person::read(std::ifstream &file)
|
||||||
{
|
{
|
||||||
U8 nameLen;
|
U8 nameLen;
|
||||||
file.read((char*)&nameLen, sizeof(nameLen)); //Check len
|
file.read((char*)&nameLen, sizeof(nameLen)); //Check len
|
||||||
@@ -99,7 +97,6 @@ void Person::load(std::ifstream &file)
|
|||||||
nameBuf[nameLen] = '\0';
|
nameBuf[nameLen] = '\0';
|
||||||
name_ = nameBuf;
|
name_ = nameBuf;
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&numRel_), sizeof(numRel_));
|
|
||||||
file.read(reinterpret_cast<char*>(&isMale_), sizeof(isMale_));
|
file.read(reinterpret_cast<char*>(&isMale_), sizeof(isMale_));
|
||||||
//file.read(reinterpret_cast<char*>(&day), sizeof(day)); TODO
|
//file.read(reinterpret_cast<char*>(&day), sizeof(day)); TODO
|
||||||
//file.read(reinterpret_cast<char*>(&month), sizeof(month));
|
//file.read(reinterpret_cast<char*>(&month), sizeof(month));
|
||||||
|
|||||||
@@ -20,13 +20,19 @@ struct EventTime
|
|||||||
I8 minute; //0-59
|
I8 minute; //0-59
|
||||||
};
|
};
|
||||||
|
|
||||||
enum: U8 {
|
enum Genders: U8
|
||||||
|
{
|
||||||
|
FEMALE = 0,
|
||||||
|
MALE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BoxColors: U8 {
|
||||||
COLOR_MALE = 1,
|
COLOR_MALE = 1,
|
||||||
COLOR_FEMALE,
|
COLOR_FEMALE,
|
||||||
COLOR_SELECTED
|
COLOR_SELECTED
|
||||||
};
|
};
|
||||||
|
|
||||||
enum: U8 {
|
enum DisplayDimensons: U8 {
|
||||||
BOX_HEIGHT = 5,
|
BOX_HEIGHT = 5,
|
||||||
LINK_HEIGHT = 3
|
LINK_HEIGHT = 3
|
||||||
};
|
};
|
||||||
@@ -35,20 +41,21 @@ class Person
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Person() = default;
|
Person() = default;
|
||||||
Person(const char* name, EventTime birth, bool sex, EventTime death);
|
Person(const char* name, EventTime birth={}, bool sex=true, EventTime death={});
|
||||||
/* Person(Person&&) = default; */
|
/* Person(Person&&) = default; */
|
||||||
/* Person& operator=(Person&&) = default; */
|
/* Person& operator=(Person&&) = default; */
|
||||||
/* Person& operator=(const Person&) = default; */
|
/* Person& operator=(const Person&) = default; */
|
||||||
|
|
||||||
bool operator==(const Person &other)const;
|
bool operator==(const Person &other) const;
|
||||||
|
|
||||||
void save(std::ofstream &file)const;//
|
void write(std::ofstream &file) const;//
|
||||||
void load(std::ifstream &file);
|
void read(std::ifstream &file);
|
||||||
void rename(const char* newName);
|
void rename(const char* newName);
|
||||||
|
|
||||||
void displayInfo() const;
|
void displayInfo() const;
|
||||||
|
|
||||||
bool isMale() const;
|
bool isMale() const;
|
||||||
|
const EventTime& birth() const { return birth_; };
|
||||||
U16 boxWidth() const;
|
U16 boxWidth() const;
|
||||||
|
|
||||||
/* Draw a Person's box on the terminal
|
/* Draw a Person's box on the terminal
|
||||||
@@ -56,14 +63,8 @@ public:
|
|||||||
returns the width of the box*/
|
returns the width of the box*/
|
||||||
void draw(I16 drawY, I16 drawX, bool selected, bool hasSpouse, bool isSpouse, bool hasChildren=false) const;
|
void draw(I16 drawY, I16 drawX, bool selected, bool hasSpouse, bool isSpouse, bool hasChildren=false) const;
|
||||||
|
|
||||||
/* WINDOW* createPad()const; */
|
|
||||||
|
|
||||||
/* staitc constexpr U8 BOX_HEIGHT = 5; */
|
|
||||||
friend class Tree;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
unsigned numRel_; //Number of close relatives - mother, father, brother, sister, wife/husband, child, ex-wife/husband
|
|
||||||
EventTime birth_;
|
EventTime birth_;
|
||||||
bool isMale_;
|
bool isMale_;
|
||||||
EventTime death_;
|
EventTime death_;
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
# FamilyTree
|
|
||||||
|
|
||||||
I wrote this program in C ++ on Visual Studio 2017, starting with a blank project. I used iostream for input and output and fstream for saving and loading trees. Instead of using vector, I chose to write a dynamic array myself. I used HxD hex editor to look for errors in the files.
|
|
||||||
In the program, "family trees" are weighted graphs implemented through a list of neighbors. The program allows for addition, subtraction (removal of common members) and comparison of trees, saving them to and loading them from files and more.
|
|
||||||
|
|
||||||
Thus large constructs consisting of multiple family trees can be created and managed using this program.
|
|
||||||
|
|
||||||
# How to use
|
|
||||||
|
|
||||||
The program works with an array of trees numbered from 0. In order to execute a command on a tree you need to enter its number(treeID).
|
|
||||||
(S/E) = (Space/Enter)
|
|
||||||
|
|
||||||
Relations are as followed and cap sensitive:
|
|
||||||
|
|
||||||
Father
|
|
||||||
Mother
|
|
||||||
Son
|
|
||||||
Daughter
|
|
||||||
Brother
|
|
||||||
Sister
|
|
||||||
HalfBrother
|
|
||||||
HalfSister
|
|
||||||
Wife
|
|
||||||
Husband
|
|
||||||
ExWife
|
|
||||||
ExHusband
|
|
||||||
|
|
||||||
List of commands:
|
|
||||||
|
|
||||||
"quit" (S/E) - close the program
|
|
||||||
|
|
||||||
"chooseTree" (S/E) TreeID (S/E) - Choose tree to execute commands on
|
|
||||||
|
|
||||||
"addTree" (S/E) TreeName (S/E) - Adds a tree to the array
|
|
||||||
|
|
||||||
"rename" (S/E) NewName (S/E) - Renames a tree
|
|
||||||
|
|
||||||
"load" (S/E) TreeID (S/E) - Loads a tree based on its name
|
|
||||||
|
|
||||||
"save" (S/E) TreeID (S/E) - Saves a tree based on its name
|
|
||||||
|
|
||||||
"addPerson" (S/E) BirthDay (S/E) BirthMonth (S/E) BirthYear (S/E) PersonSex (S/E) - Add a person to a tree with treeID with a birthday on BirthDay.BirthMonth.BirthYear and sex (PersonSex) 0 = Male 1 = Female
|
|
||||||
|
|
||||||
"addPersonWP" (S/E) BirthDay (S/E) BirthMonth (S/E) BirthYear (S/E) PersonSex (S/E) FatherID (S/E) MotherID - The same as addPerson but adds father and motherbased on their IDs
|
|
||||||
|
|
||||||
"addRelation" (S/E) FirstRelativeName (S/E) Relation (S/E) SecondRelativeName - Adds a relation betwean two members based on their full names
|
|
||||||
|
|
||||||
"addRelationID" (S/E) FirstRelativeID (S/E) Relation (S/E) SecondRelativeID - Same as addElation but based on ID
|
|
||||||
|
|
||||||
"findID" (S/E) SoughtPersonName (S/E) - Prints the ID of a person with the given name
|
|
||||||
|
|
||||||
"equate" (S/E) FirstTreeID (S/E) SecondTreeID - Enter the IDs of two trees, the first one becomes equal to the second one
|
|
||||||
|
|
||||||
"combine" (S/E) FirstTreeID (S/E) SecondTreeID - Enter the IDs of two trees, the first one becomes equal to the combinatio of the two
|
|
||||||
|
|
||||||
"subtract" (S/E) FirstTreeID (S/E) SecondTreeID - Enter the IDs of two trees, the members that are present in both trees are removed from the first tree
|
|
||||||
|
|
||||||
"removePerson" (S/E) Name - Remove person with the given name
|
|
||||||
|
|
||||||
"removePersonID" (S/E) Name - Remove person with the given ID
|
|
||||||
|
|
||||||
"removeRelation" (S/E) FirstName (S/E) SecondName - Remove the relation betwean the people with the given names if they have one
|
|
||||||
|
|
||||||
"removeRelationID" (S/E) FirstName (S/E) SecondName - Same as removeRelation but with IDs instead
|
|
||||||
|
|
||||||
"prtRelatives" (S/E) PersonID - Print the relatives the person with the given ID in the console
|
|
||||||
|
|
||||||
"prtMember" (S/E) PersonID - Print the personal data of a member on the console
|
|
||||||
|
|
||||||
"prtCommonAncestor" (S/E) FirstPersonID (S/E) SecondPersonID (S/E)
|
|
||||||
|
|
||||||
"prtOldestAncestor" (S/E) PersonID (S/E)
|
|
||||||
|
|||||||
@@ -1,69 +1,18 @@
|
|||||||
|
#include"tree.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include"tree.h"
|
|
||||||
#include"person.h"
|
#include"person.h"
|
||||||
#include"help.h"
|
#include"help.h"
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
using std::ofstream;
|
||||||
|
using std::ifstream;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
Tree Tree::operator+ (const Tree& other) const
|
Tree Tree::operator+ (const Tree& other) const
|
||||||
{
|
{
|
||||||
/* Tree result(treeName + other.treeName); //The tree resulting from the addition */
|
|
||||||
/* vector<person_id> newId; //The indexes members of the II tree will have in result */
|
|
||||||
/* newId.reserve(other.numPeople); */
|
|
||||||
|
|
||||||
/* U32 idCounter = numPeople; */
|
|
||||||
/* for (U32 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.reserve(result.numPeople); */
|
|
||||||
/* result.people = people; //Adds the members of the I tree to the resulting tree */
|
|
||||||
/* for (U32 i=0; i < other.numPeople; ++i) //Adds the members of the II tree to the resulting tree */
|
|
||||||
/* { */
|
|
||||||
/* if (newId[i] >= numPeople) */
|
|
||||||
/* result.people.push_back(other.people[i]); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* result.relations.reserve(result.numPeople); */
|
|
||||||
/* result.relations = relations; */
|
|
||||||
|
|
||||||
/* for (U32 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.relations.push_back(other.relations[i]); */
|
|
||||||
/* } */
|
|
||||||
/* else //If he's found in both */
|
|
||||||
/* { */
|
|
||||||
/* for (person_id j = 0; j < other.relations[i].size(); ++j) //Adds the number of relatives from the II to the number in the I */
|
|
||||||
/* { */
|
|
||||||
/* if (newId[other.relations[i][j].id] > numPeople) */
|
|
||||||
/* ++result.people[newId[i]].numRel_; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* result.relations[newId[i]].reserve(result.people[newId[i]].numRel_); */
|
|
||||||
|
|
||||||
/* result.relations[newId[i]] = relations[newId[i]]; */
|
|
||||||
|
|
||||||
/* result.relations[newId[i]] += other.relations[i]; //The relatives from the II tree */
|
|
||||||
/* } */
|
|
||||||
/* } */
|
|
||||||
Tree result(*this);
|
Tree result(*this);
|
||||||
|
|
||||||
return result += other;
|
return result += other;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,12 +51,12 @@ Tree& Tree::operator+=(const Tree& other)
|
|||||||
relations.push_back(other.relations[i]);
|
relations.push_back(other.relations[i]);
|
||||||
for (Relation& rel: relations.back())
|
for (Relation& rel: relations.back())
|
||||||
rel.id = newId[rel.id];
|
rel.id = newId[rel.id];
|
||||||
/* for (person_id j = 0; j < other.people[i].numRel_; ++j) */
|
/* for (person_id j = 0; j < other.relations[i].size(); ++j) */
|
||||||
/* relations[newId[i]][j].id = newId[ relations[newId[i]][j].id ]; */
|
/* relations[newId[i]][j].id = newId[ relations[newId[i]][j].id ]; */
|
||||||
}
|
}
|
||||||
else //if present in both trees
|
else //if present in both trees
|
||||||
{
|
{
|
||||||
/* for (person_id j = 0; j < other.people[i].numRel_; ++j) //combine relations */
|
/* for (person_id j = 0; j < other.relations[i].size(); ++j) //combine relations */
|
||||||
/* { */
|
/* { */
|
||||||
/* if (newId[other.relations[i][j].id] >= numPeople) */
|
/* if (newId[other.relations[i][j].id] >= numPeople) */
|
||||||
/* ++people[newId[i]].numRel_; */
|
/* ++people[newId[i]].numRel_; */
|
||||||
@@ -124,11 +73,6 @@ Tree& Tree::operator+=(const Tree& other)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for (person_id j = 0; j < other.people[i].numRel_; ++j) */
|
|
||||||
/* { */
|
|
||||||
/* relations[newId[i]][j + people[newId[i]].numRel_ - other.people[i].numRel_].id = newId[other.relations[i][j].id]; */
|
|
||||||
/* relations[newId[i]][j + people[newId[i]].numRel_ - other.people[i].numRel_].type = other.relations[i][j].type; */
|
|
||||||
/* } */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,30 +98,28 @@ Tree& Tree::operator-= (const Tree& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Tree::rename(const char* newName)
|
void Tree::rename(const char* newName)
|
||||||
{
|
{
|
||||||
treeName = newName;
|
treeName = newName;
|
||||||
}
|
}
|
||||||
|
|
||||||
person_id Tree::findId(const char* name, const short year, const unsigned char month, const unsigned char day) const
|
person_id Tree::findId(const char* name, bool m) const
|
||||||
{
|
{
|
||||||
//TODO
|
Person sought(name, {}, m);
|
||||||
//Person sought(name, day, month, year,)
|
|
||||||
for (person_id i = 0; i < numPeople; ++i)
|
for (person_id 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))
|
if (sought == people[i])
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return Nobody;
|
return Nobody;
|
||||||
}
|
}
|
||||||
|
|
||||||
person_id Tree::findOldestAncestor(unsigned id, bool isMale)const
|
person_id Tree::findOldestAncestor(person_id id, bool isMale) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < people[id].numRel_; ++i)
|
for (const Relation& rel: relations[id])
|
||||||
{
|
{
|
||||||
if (relations[id][i].type == Child && people[ relations[id][i].id ].isMale_ == isMale)
|
if (rel.type == Child && people[ rel.id ].isMale() == isMale)
|
||||||
return findOldestAncestor(relations[id][i].id, isMale);
|
return findOldestAncestor(rel.id, isMale);
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@@ -193,9 +135,9 @@ person_id Tree::findCommonAncestor(const unsigned firstId, const unsigned second
|
|||||||
U16 oldestBday = SHRT_MAX;
|
U16 oldestBday = SHRT_MAX;
|
||||||
for (person_id i = 0; i < numPeople; ++i)
|
for (person_id i = 0; i < numPeople; ++i)
|
||||||
{
|
{
|
||||||
if (visited[i] == 2 && people[i].birth_.year < oldestBday)
|
if (visited[i] == 2 && people[i].birth().year < oldestBday)
|
||||||
{
|
{
|
||||||
oldestBday = people[i].birth_.year;
|
oldestBday = people[i].birth().year;
|
||||||
oldest = i;
|
oldest = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,7 +149,7 @@ person_id Tree::findParent(person_id child, bool isParentMale) const
|
|||||||
person_id parent = Nobody;
|
person_id parent = Nobody;
|
||||||
for(const Relation& rel: relations[child])
|
for(const Relation& rel: relations[child])
|
||||||
{
|
{
|
||||||
if (rel.type == Child && people[rel.id].isMale())
|
if (rel.type == Child && people[rel.id].isMale() == isParentMale)
|
||||||
parent = rel.id;
|
parent = rel.id;
|
||||||
}
|
}
|
||||||
return parent;
|
return parent;
|
||||||
@@ -250,52 +192,42 @@ RelType Tree::findRelation(person_id first, person_id second) const
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::saveTree() const
|
void Tree::saveToFile() const
|
||||||
{
|
{
|
||||||
std::ofstream peopleFile(treeName+ ".people", std::ios::binary);
|
ofstream file(treeName + ".famt", std::ios::binary);
|
||||||
|
|
||||||
peopleFile.write(reinterpret_cast<const char*>(&numPeople), sizeof(numPeople));
|
file.write((const char*)(&numPeople), sizeof(numPeople));
|
||||||
for (unsigned i = 0; i < numPeople; ++i)
|
for (const Person& p: people)
|
||||||
people[i].save(peopleFile);
|
p.write(file);
|
||||||
peopleFile.close();
|
|
||||||
|
|
||||||
std::ofstream relationFile(treeName + ".relations", std::ios::binary);
|
for (auto& rels: relations)
|
||||||
|
|
||||||
for (unsigned i = 0; i < numPeople; ++i)
|
|
||||||
{
|
{
|
||||||
//relationFile.write((char*)&people[i].numRel_, sizeof(people[i].numRel_));
|
U32 numRels = rels.size();
|
||||||
for (unsigned j = 0; j < people[i].numRel_; ++j)
|
file.write((const char*)(& numRels), sizeof(numRels));
|
||||||
relationFile.write(reinterpret_cast<const char*>(&relations[i][j]), sizeof(relations[i][j]));
|
file.write((const char*)(rels.data()), sizeof(Relation) * numRels);
|
||||||
}
|
}
|
||||||
relationFile.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tree::loadTree()
|
bool Tree::loadFromFile()
|
||||||
{
|
{
|
||||||
std::ifstream peopleFile(treeName + ".people", std::ios::binary);
|
ifstream file(treeName + ".famt", std::ios::binary);
|
||||||
if (peopleFile.peek() == std::char_traits<char>::eof())
|
|
||||||
{
|
file.read((char*)(&numPeople), sizeof(numPeople));
|
||||||
peopleFile.close();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
peopleFile.read(reinterpret_cast<char*>(&numPeople), sizeof(numPeople));
|
|
||||||
people.resize(numPeople);
|
people.resize(numPeople);
|
||||||
for (unsigned i = 0; i < numPeople; ++i)
|
for (Person& p: people)
|
||||||
people[i].load(peopleFile);
|
p.read(file);
|
||||||
peopleFile.close();
|
|
||||||
|
|
||||||
|
|
||||||
std::ifstream relationFile(treeName + ".relations", std::ios::binary);
|
|
||||||
relations.resize(numPeople);
|
relations.resize(numPeople);
|
||||||
for (unsigned i = 0; i < numPeople; ++i)
|
for (auto& rels: relations)
|
||||||
{
|
{
|
||||||
relations[i].resize(people[i].numRel_);
|
U32 numRels;
|
||||||
for (unsigned j = 0; j < people[i].numRel_; ++j)
|
file.read((char*)(& numRels), sizeof(numRels));
|
||||||
relationFile.read(reinterpret_cast<char*>(&relations[i][j]), sizeof(relations[i][j]));
|
|
||||||
|
rels.resize(numRels);
|
||||||
|
file.read((char*)(rels.data()), sizeof(Relation) * numRels);
|
||||||
}
|
}
|
||||||
relationFile.close();
|
return true;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::addPerson(const char* name, bool isMale, unsigned father, unsigned mother, EventTime birth, EventTime death)
|
void Tree::addPerson(const char* name, bool isMale, unsigned father, unsigned mother, EventTime birth, EventTime death)
|
||||||
@@ -320,10 +252,10 @@ bool Tree::addRelation(const char* firstName, const RelType type, const char* se
|
|||||||
bool Tree::addRelation(const unsigned firstId, const RelType type, const unsigned secondId, bool opposite)//
|
bool Tree::addRelation(const unsigned firstId, const RelType type, const unsigned secondId, bool opposite)//
|
||||||
{
|
{
|
||||||
if (firstId == Nobody || firstId >= numPeople || secondId == Nobody || secondId >= numPeople || type == None)
|
if (firstId == Nobody || firstId >= numPeople || secondId == Nobody || secondId >= numPeople || type == None)
|
||||||
return 0;
|
return false;
|
||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (; i < people[firstId].numRel_; ++i) //If they are already relatives
|
for (; i < relations[firstId].size(); ++i) //If they are already relatives
|
||||||
{
|
{
|
||||||
if (relations[firstId][i].id == secondId)
|
if (relations[firstId][i].id == secondId)
|
||||||
{
|
{
|
||||||
@@ -331,10 +263,9 @@ bool Tree::addRelation(const unsigned firstId, const RelType type, const unsigne
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i >= people[firstId].numRel_)
|
if (i >= relations[firstId].size())
|
||||||
{
|
{
|
||||||
relations[firstId].push_back({secondId, type});
|
relations[firstId].push_back({secondId, type});
|
||||||
++people[firstId].numRel_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opposite)
|
if (!opposite)
|
||||||
@@ -356,7 +287,7 @@ bool Tree::addRelation(const unsigned firstId, const RelType type, const unsigne
|
|||||||
default: assert(!"Unexpected case"); break;
|
default: assert(!"Unexpected case"); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::removeRelation(const char* firstName, const char* secondName)
|
void Tree::removeRelation(const char* firstName, const char* secondName)
|
||||||
@@ -379,10 +310,10 @@ void Tree::removePerson(const person_id id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < people[numPeople - 2].numRel_; ++i) //Move the last in his place and update IDs
|
for (unsigned i = 0; i < relations[numPeople - 2].size(); ++i) //Move the last in his place and update IDs
|
||||||
{
|
{
|
||||||
relId = relations[numPeople - 1][i].id;
|
relId = relations[numPeople - 1][i].id;
|
||||||
for (unsigned j = 0; j < people[relId].numRel_; ++j)
|
for (unsigned j = 0; j < relations[relId].size(); ++j)
|
||||||
{
|
{
|
||||||
if (relations[relId][j].id == numPeople - 1)
|
if (relations[relId][j].id == numPeople - 1)
|
||||||
{
|
{
|
||||||
@@ -396,10 +327,10 @@ void Tree::removePerson(const person_id id)
|
|||||||
--numPeople;
|
--numPeople;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::removePerson(const char* personName, short year, unsigned char month, unsigned char day)
|
/* void Tree::removePerson(const char* personName, short year, unsigned char month, unsigned char day) */
|
||||||
{
|
/* { */
|
||||||
removePerson(findId(personName, year, month, day));
|
/* removePerson(findId(personName, year, month, day)); */
|
||||||
}
|
/* } */
|
||||||
|
|
||||||
void Tree::removeRelation(const unsigned firstId, const unsigned secondId)
|
void Tree::removeRelation(const unsigned firstId, const unsigned secondId)
|
||||||
{
|
{
|
||||||
@@ -492,8 +423,8 @@ void Tree::print() const
|
|||||||
member.displayInfo();
|
member.displayInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::printRel(const unsigned id)const
|
/* void Tree::printRel(const unsigned id)const */
|
||||||
{
|
/* { */
|
||||||
/* cout << people[id].name_; */
|
/* cout << people[id].name_; */
|
||||||
/* if (people[id].numRel_ == 0) */
|
/* if (people[id].numRel_ == 0) */
|
||||||
/* cout << " has no known relatives"; */
|
/* cout << " has no known relatives"; */
|
||||||
@@ -541,7 +472,7 @@ void Tree::printRel(const unsigned id)const
|
|||||||
/* } */
|
/* } */
|
||||||
/* cout << '\n'; */
|
/* cout << '\n'; */
|
||||||
/* } */
|
/* } */
|
||||||
}
|
/* } */
|
||||||
|
|
||||||
void Tree::printMember(const unsigned id)const
|
void Tree::printMember(const unsigned id)const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
|
|
||||||
void rename(const char* newName);
|
void rename(const char* newName);
|
||||||
|
|
||||||
person_id findId(const char*, short year=0, const unsigned char month=0, const unsigned char day=0) const;
|
person_id findId(const char* name, bool=true) const;
|
||||||
person_id findOldestAncestor(person_id id, bool sex = 0) const;//
|
person_id findOldestAncestor(person_id id, bool sex = 0) const;//
|
||||||
//oldest common ancestor ID, a person is considerd an ancestor of himself
|
//oldest common ancestor ID, a person is considerd an ancestor of himself
|
||||||
person_id findCommonAncestor(person_id firstId, person_id secondId) const;
|
person_id findCommonAncestor(person_id firstId, person_id secondId) const;
|
||||||
@@ -53,22 +53,22 @@ public:
|
|||||||
person_id findSpouse(person_id person) const;
|
person_id findSpouse(person_id person) const;
|
||||||
std::vector<person_id> findChildren(person_id person) const;
|
std::vector<person_id> findChildren(person_id person) const;
|
||||||
|
|
||||||
void saveTree()const;//
|
void saveToFile()const;//
|
||||||
bool loadTree();
|
bool loadFromFile();
|
||||||
|
|
||||||
void addPerson(const char* name, bool isMale, person_id father=Nobody, person_id mother=Nobody, EventTime birth={}, EventTime death={});
|
void addPerson(const char* name, bool isMale, person_id father=Nobody, person_id mother=Nobody, EventTime birth={}, EventTime death={});
|
||||||
bool addRelation(const char* firstName, RelType, const char* secondName); //Adds a new relation or edits an old one. 0 - failure 1 - success
|
bool addRelation(const char* firstName, RelType, const char* secondName); //Adds a new relation or edits an old one. 0 - failure 1 - success
|
||||||
bool addRelation(person_id firstId, RelType, person_id secondId, bool opposite=0); //0 - failure 1 - success
|
bool addRelation(person_id firstId, RelType, person_id secondId, bool opposite=0); //0 - failure 1 - success
|
||||||
|
|
||||||
void removePerson(person_id id); //Removes a member and the last one takes his ID
|
void removePerson(person_id id); //Removes a member and the last one takes his ID
|
||||||
void removePerson(const char*, short year = 0, const unsigned char month = 0, const unsigned char day = 0);
|
/* void removePerson(const char*, short year = 0, const unsigned char month = 0, const unsigned char day = 0); */
|
||||||
void removeRelation(person_id firstId, person_id secondId);
|
void removeRelation(person_id firstId, person_id secondId);
|
||||||
void removeRelation(const char* firstName, const char* secondName);
|
void removeRelation(const char* firstName, const char* secondName);
|
||||||
|
|
||||||
void display();
|
void display();
|
||||||
|
|
||||||
void print()const;
|
void print()const;
|
||||||
void printRel(person_id id)const; //Prints out close relatives
|
/* void printRel(person_id id)const; //Prints out close relatives */
|
||||||
void printMember(person_id id)const;
|
void printMember(person_id id)const;
|
||||||
void printOldestAncestors(person_id id)const;//
|
void printOldestAncestors(person_id id)const;//
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ private:
|
|||||||
void selectLeftSibSpouse(person_id person);
|
void selectLeftSibSpouse(person_id person);
|
||||||
void selectRightSib(person_id person);
|
void selectRightSib(person_id person);
|
||||||
|
|
||||||
std::string treeName = "Unnamed";
|
std::string treeName;
|
||||||
unsigned numPeople = 0;
|
unsigned numPeople = 0;
|
||||||
std::vector<Person> people; //The data for each member
|
std::vector<Person> people; //The data for each member
|
||||||
std::vector<std::vector<Relation>> relations; //The relatives of each member
|
std::vector<std::vector<Relation>> relations; //The relatives of each member
|
||||||
|
|||||||
Reference in New Issue
Block a user