relation relative merge

This commit is contained in:
vrd
2022-12-28 14:19:44 +02:00
parent cc9b0ccc21
commit b3a2787fcd
6 changed files with 203 additions and 170 deletions
-2
View File
@@ -2,8 +2,6 @@
#include "common/basicTypes.h"
enum Relation : U8;
unsigned strLen(const char* str);
void strCopy(char *to, const char* from);
bool strComp(const char* firts, const char* second); //0 - diffrent 1 - same
+33 -24
View File
@@ -15,33 +15,42 @@ int main()
cbreak(); /* get input instantly */
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"); //addTree Dechkovi addTree Karamanovi load 0 load 1 (to work with these example trees)
Tree test2("Karamanovi");
test1.addPerson("Rumen", 1968, 8, 9, 0);
test1.addPerson("Nadejda", 1972, 12, 15, 1);
test1.addRelation(0, Husband, 1);
test1.addPerson("Venelin", 1998, 6, 9, 0, 0, 1);
test1.addPerson("Vasil", 2001, 1, 16, 0, 0, 1);
test1.addRelation(2, Brother, 3);
test1.addPerson("Maria-Veronika", 2009, 9, 3, 1, 0, 1);
test1.addRelation(2, Brother, 4);
test1.addRelation(3, Brother, 4);
test1.addPerson("Rumen", true, Nobody, Nobody, {1968, 8, 9});
test1.addPerson("Nadejda", false, Nobody, Nobody, {1972, 12, 15});
/* test1.addRelation(0, Husband, 1); */
test1.addPerson("Venelin", true, 0, 1, {1998, 6, 9});
test1.addPerson("Vasil", true, 0, 1, {2001, 1, 16});
/* test1.addRelation(2, Brother, 3); */
/* test1.addPerson("Maria-Veronika", 2009, 9, 3, 1, 0, 1); */
/* test1.addRelation(2, Brother, 4); */
/* test1.addRelation(3, Brother, 4); */
test2.addPerson("Vasil Dimitrov", 1941, 5, 18, 0);
test2.addPerson("Maria", 0, 0, 0, 1);
test2.addRelation(0, Husband, 1);
test2.addPerson("Dimitar", 0, 0, 0, 0, 0, 1);
test2.addPerson("Nadejda", 1972, 12, 15, 1, 0, 1);
test2.addRelation(2, Brother, 3);
test2.addPerson("Branimira", 0, 0, 0, 1);
test2.addRelation(2, Husband, 4);
test2.addPerson("Ioan", 0, 0, 0, 0, 2, 4);
test2.addPerson("Rumiana", 0, 0, 0, 1, 2, 4);
test2.addRelation(5, Brother, 6);
test2.addPerson("Vasil Dimitrov", true, Nobody, Nobody, {1941, 5, 18});
test2.addPerson("Maria", false);
/* test2.addRelation(0, Husband, 1); */
test2.addPerson("Dimitar", true, 0, 1);
test2.addPerson("Nadejda", false, 0, 1, {1972, 12, 15});
/* test2.addRelation(2, Brother, 3); */
test2.addPerson("Branimira", false);
/* test2.addRelation(2, Husband, 4); */
test2.addPerson("Ioan", true, 2, 4);
test2.addPerson("Rumiana", false, 2, 4);
/* test2.addRelation(5, Brother, 6); */
test1.saveTree();
test2.saveTree();*/
test1.draw();
test2.draw();
/* (test1 + test2).draw(4); */
test1 += test2;
test1.draw(4);
test1.draw();
/* test1.saveTree(); */
/* test2.saveTree(); */
Tree firstTree("firstTree");
@@ -68,7 +77,7 @@ int main()
/* firstTree.print(); */
firstTree.draw();
firstTree.saveTree();
/* firstTree.saveTree(); */
/* firstTree.printRel(3); */
firstTree.printOldestAncestors(3);
+3 -2
View File
@@ -161,7 +161,7 @@ void Person::print()const
U16 Person::boxWidth() const
{
return name_.size() + 4 - 1; /* TODO: get actual lenght */
return name_.size() + 4; /* TODO: get actual lenght */
}
@@ -181,7 +181,8 @@ void Person::draw(I16 drawY, I16 drawX) const
U16 width = boxWidth();
WINDOW* pad = newpad(BOX_HEIGHT, width);
box(pad, BOX_HEIGHT, width);
wborder(pad, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE, ACS_LTEE, ACS_URCORNER, ACS_LTEE, ACS_LRCORNER );
/* box(pad, BOX_HEIGHT, width); */
mvwaddstr(pad, 2, 2, name_.data());
pnoutrefresh(pad, 0, 0,
+4 -1
View File
@@ -20,7 +20,10 @@ struct EventTime
I8 minute; //0-59
};
enum { BOX_HEIGHT = 5 };
enum {
BOX_HEIGHT = 5,
LINK_HEIGHT = 3
};
class Person
{
+95 -80
View File
@@ -38,33 +38,28 @@ Tree Tree::operator+ (const Tree& other)//
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)
if(newId[other.relations[i][j].id] > 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];
result.relations[newId[i]] += other.relations[i]; //The relatives from the II tree
}
}
@@ -98,30 +93,28 @@ Tree& Tree::operator+=(const Tree& other)
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]);
for (unsigned j = 0; j < other.people[i].numRel_; ++j)
relations[newId[i]][j].id = newId[ relations[newId[i]][j].id ];
}
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)
if (newId[other.relations[i][j].id] >= 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];
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;
}
}
}
@@ -167,12 +160,12 @@ unsigned Tree::findId(const char* name, const short year, const unsigned char mo
return Nobody;
}
unsigned Tree::findOldestAncestor(const unsigned &id, const bool &isMale)const
unsigned Tree::findOldestAncestor(unsigned id, bool isMale)const
{
for (unsigned i = 0; i < people[id].numRel_; ++i)
{
if (relations[id][i] == Child && people[ relatives[id][i] ].isMale_ == isMale)
return findOldestAncestor(relatives[id][i], isMale);
if (relations[id][i].type == Child && people[ relations[id][i].id ].isMale_ == isMale)
return findOldestAncestor(relations[id][i].id, isMale);
}
return id;
}
@@ -207,22 +200,14 @@ void Tree::saveTree() const
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<char*>(&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<char*>(&relations[i][j]), sizeof(relations[i][j]));
}
relativeFile.close();
relationFile.close();
}
@@ -242,26 +227,17 @@ bool Tree::loadTree()
people.sNum(numPeople);
peopleFile.close();
std::ifstream relativeFile(treeName + ".relatives", std::ios::binary);
std::ifstream relationFile(treeName + ".relations", std::ios::binary);
relatives.resize(numPeople);
std::ifstream relationFile(treeName + ".relations", std::ios::binary);
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<char*>(&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<char*>(&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;
}
@@ -270,22 +246,22 @@ void Tree::addPerson(const char* name, bool isMale, unsigned father, unsigned mo
{
Person newPerson(name, birth, isMale, death);
people.push(newPerson);
Array<unsigned> newRelative;
relatives.push(newRelative);
Array<Relation> newRelation;
relations.push(newRelation);
Array<Relation> newRels;
relations.push(newRels);
++numPeople;
addRelation(father, Parent, numPeople - 1);
addRelation(mother, Parent, numPeople - 1);
}
bool Tree::addRelation(const char* firstName, const Relation type, const char* secondName)
bool Tree::addRelation(const char* firstName, const RelType 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)//
bool Tree::addRelation(const unsigned firstId, const RelType type, const unsigned secondId, bool opposite)//
{
if (firstId == Nobody || firstId >= numPeople || secondId == Nobody || secondId >= numPeople || type == Invalid)
return 0;
@@ -293,16 +269,15 @@ bool Tree::addRelation(const unsigned firstId, const Relation type, const unsign
unsigned i = 0;
for (; i < people[firstId].numRel_; ++i) //If they are already relatives
{
if (relatives[firstId][i] == secondId)
if (relations[firstId][i].id == secondId)
{
relations[firstId][i] = type;
relations[firstId][i].type = type;
break;
}
}
if (i >= people[firstId].numRel_)
{
relatives[firstId].push(secondId);
relations[firstId].push(type);
relations[firstId].push({secondId, type});
++people[firstId].numRel_;
}
@@ -337,12 +312,11 @@ void Tree::removePerson(const unsigned id)
unsigned relId; //Íoìåð íà òåêóùèÿ ðîäíèíàòà
for (unsigned i = 0; i < people[id].numRel_; ++i) //Ïðåìàõâàò ñå âðúçêèòå íà ÷ëåíà çà ïðåìàõâàíå
{
relId = relatives[id][i];
relId = relations[id][i].id;
for (unsigned j = 0; j < people[relId].numRel_; ++j)
{
if (relatives[relId][j] == id)
if (relations[relId][j].id == id)
{
relatives[relId].remove(j);
relations[relId].remove(j);
break;
}
@@ -351,17 +325,16 @@ void Tree::removePerson(const unsigned id)
}
for (unsigned i = 0; i < people[numPeople - 2].numRel_; ++i) //Ïîñëåäíèÿò ÷ëåí âçåìà íîìåðà íà ïðåìàõíàòèÿ
{
relId = relatives[numPeople - 1][i];
relId = relations[numPeople - 1][i].id;
for (unsigned j = 0; j < people[relId].numRel_; ++j)
{
if (relatives[relId][j] == numPeople - 1)
if (relations[relId][j].id == numPeople - 1)
{
relatives[relId][j] = id;
relations[relId][j].id = id;
break;
}
}
}
relatives.remove(id);
relations.remove(id);
people.remove(id);
--numPeople;
@@ -376,9 +349,8 @@ void Tree::removeRelation(const unsigned firstId, const unsigned secondId)
{
for (unsigned i = 0; i < people[firstId].numRel_; ++i)
{
if (relatives[firstId][i] == secondId)
if (relations[firstId][i].id == secondId)
{
relatives[firstId].remove(i);
relations[firstId].remove(i);
--people[firstId].numRel_;
break;
@@ -386,9 +358,8 @@ void Tree::removeRelation(const unsigned firstId, const unsigned secondId)
}
for (unsigned i = 0; i < people[secondId].numRel_; ++i)
{
if (relatives[secondId][i] == firstId)
if (relations[secondId][i].id == firstId)
{
relatives[secondId].remove(i);
relations[secondId].remove(i);
--people[secondId].numRel_;
break;
@@ -396,8 +367,10 @@ void Tree::removeRelation(const unsigned firstId, const unsigned secondId)
}
}
void Tree::draw() const
void Tree::draw(person_id focused) const
{
erase(); //Clear the screen
wnoutrefresh(stdscr);
/* WINDOW* father = people[0].createPad(); */
/* WINDOW* mother = people[1].createPad(); */
@@ -411,16 +384,16 @@ void Tree::draw() const
/* 1, drawX, */
/* 1 +fh-1, drawX + fw-1); */
const U32 numPpl = people.gNum();
std::vector<bool> drawn(numPpl, false);
/* const U32 numPpl = people.gNum(); */
/* std::vector<bool> drawn(numPpl, false); */
U16 drawY = 0/* (LINES) / 2 */;
U16 drawX = 0/* (COLS) / 2 */;
drawLineRec(0, drawY, drawX);
drawLine(focused, drawY, drawX);
/* people[0].draw(drawY, drawY); */
/* for(U32 i=0; i<relations[0].gNum(); ++i) */
/* { */
/* if(relations[0][i] == Relation::Son) */
/* if(relations[0][i] == RelType::Son) */
/* { */
/* drawX = drawLineRec(i, drawY, drawX) + 2; */
/* } */
@@ -504,19 +477,19 @@ void Tree::printOldestAncestors(const unsigned id)const
void Tree::commonAncestorRec(const unsigned &id, const Array<char> &visited)const
void Tree::commonAncestorRec(person_id id, const Array<char> &visited)const
{
for (unsigned i = 0; i < people[id].numRel_; ++i)
{
if (relations[id][i] == Child)
if (relations[id][i].type == Child)
{
++visited[relatives[id][i]];
commonAncestorRec(relatives[id][i], visited);
++visited[relations[id][i].id];
commonAncestorRec(relations[id][i].id, visited);
}
}
}
static void linkToFirstBorn(I16 startY, I16 startX)
static U8 linkToFirstBorn(I16 startY, I16 startX)
{
if(startY >= -2 && startX >= 0)
{
@@ -529,9 +502,10 @@ static void linkToFirstBorn(I16 startY, I16 startX)
wnoutrefresh(win);
delwin(win);
}
return 3;
}
static void linkToChild(I16 startY, I16 startX, I16 endX)
static U8 linkToChild(I16 startY, I16 startX, I16 endX)
{
assert(endX >= startX);
@@ -550,34 +524,75 @@ static void linkToChild(I16 startY, I16 startX, I16 endX)
wnoutrefresh(win);
delwin(win);
}
return 3;
}
I16 Tree::drawLineRec(person_id id, I16 drawY, I16 drawX) const
I16 Tree::drawLine(person_id id, I16 drawY, I16 drawX) const
{
people[id].draw(drawY, drawX);
std::vector<person_id> sons;
std::vector<person_id> children;
for(U32 i=0; i<relations[id].gNum(); ++i)
{
if(relations[id][i] == Relation::Parent)
sons.push_back(relatives[id][i]);
if(relations[id][i].type == RelType::Parent)
children.push_back(relations[id][i].id);
}
if(!sons.empty())
if(!children.empty())
{
auto prevX = drawX;
drawY += BOX_HEIGHT;
linkToFirstBorn(drawY, drawX);
drawX = drawLineRec(sons[0], drawY + 3, drawX) + 1;
auto lnHt = linkToFirstBorn(drawY, drawX); /* Link height */
drawX = drawLine(children[0], drawY + lnHt, drawX);
for(size_t j = 1; j < sons.size(); ++j)
for(size_t j = 1; j < children.size(); ++j)
{
linkToChild(drawY + 1, prevX+1, drawX+1);
lnHt = linkToChild(drawY+1, prevX+1, drawX+1);
prevX = drawX;
drawX = drawLineRec(sons[j], drawY + 3, drawX) + 1;
drawX = drawLine(children[j], drawY + lnHt, drawX);
}
return drawX;
}
return drawX + people[id].boxWidth();
return drawX + people[id].boxWidth() + dist_between;
}
I16 Tree::drawLineWithWives(person_id id, I16 drawY, I16 drawX) const
{
/* const auto& rels = relations[id]; */
/* /\* const auto& rels = relations[id]; *\/ */
/* people[id].draw(drawY, drawX); */
/* /\* for(U32 i = 0; i < re *\/ */
/* std::vector<person_id> children; */
/* for(U32 i=0; i<relations[id].gNum(); ++i) */
/* { */
/* if(relations[id][i] == RelType::Parent) */
/* children.push_back(relatives[id][i]); */
/* } */
/* if(!children.empty()) */
/* { */
/* auto prevX = drawX; */
/* drawY += BOX_HEIGHT; */
/* auto lnHt = linkToFirstBorn(drawY, drawX); /\* Link height *\/ */
/* drawX = drawLine(children[0], drawY + lnHt, drawX); */
/* for(size_t j = 1; j < children.size(); ++j) */
/* { */
/* lnHt = linkToChild(drawY+1, prevX+1, drawX+1); */
/* prevX = drawX; */
/* drawX = drawLine(children[j], drawY + lnHt, drawX); */
/* } */
/* return drawX; */
/* } */
/* return drawX + people[id].boxWidth() + dist_between; */
}
+68 -61
View File
@@ -4,7 +4,74 @@
#include "array.h"
#include "person.h"
enum Relation : U8
using person_id = U32;
enum RelType : U8;
struct Relation
{
person_id id;
RelType type;
};
static constexpr person_id Nobody = UINT_MAX;
class Tree
{
public:
Tree() = default;
template <class Str>
Tree(Str&& Name) : treeName(std::forward<Str>(Name)) {}
/*Tree(const Tree&);
Tree& operator= (const Tree& other);*/
Tree operator+ (const Tree& other);//doesnt work
Tree operator- (const Tree& other);
Tree& operator+= (const Tree& other);
Tree& operator-= (const Tree& other);
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 findOldestAncestor(person_id id, bool sex = 0)const;//
person_id findCommonAncestor(person_id firstId, person_id secondId)const; //oldest common ancestor ID
void saveTree()const;//
bool loadTree();
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(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(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(const char* firstName, const char* secondName);
void draw(person_id focused=0) const;
void print()const;
void printRel(person_id id)const; //Prints out close relatives
void printMember(person_id id)const;
void printOldestAncestors(person_id id)const;//
private:
void commonAncestorRec(person_id id, const Array<char> &visited)const;
/* draw a line of people starting from person with id
return the farthest X that will be drawn */
I16 drawLine(person_id id, I16 drawY, I16 drawX) const;
I16 drawLineWithWives(person_id id, I16 drawY, I16 drawX) const;
std::string treeName = "Unnamed";
unsigned numPeople = 0;
Array<Person> people; //The data for each member
Array<Array<Relation>> relations; //The relatives of each member
U16 offset = 0;
U8 dist_between = 1;
//Search, ect.
};
enum RelType : U8
{
Invalid = 0,
Parent,
@@ -14,63 +81,3 @@ enum Relation : U8
Spouse,
ExSpouse
};
const U32 Nobody = UINT_MAX; //Òîçè íîìåð ùå áúäå çàïàçeí çà ëèïñà íà âðúçêà/÷îâåê
class Tree
{
public:
using person_id = U32;
Tree() = default;
template <class Str>
Tree(Str&& Name) : treeName(std::forward<Str>(Name)) {}
/*Tree(const Tree&);
Tree& operator= (const Tree& other);*/
Tree operator+ (const Tree& other);
Tree operator- (const Tree& other);
Tree& operator+= (const Tree& other);
Tree& operator-= (const Tree& other);
void rename(const char* newName);
unsigned findId(const char*, const short year=0, const unsigned char month=0, const unsigned char day=0)const;
unsigned findOldestAncestor(const unsigned &id, const bool &sex = 0)const;//
unsigned findCommonAncestor(const unsigned firstId, const unsigned secondId)const; //oldest common ancestor ID
void saveTree()const;//
bool loadTree();
void addPerson(const char* name, bool isMale, unsigned father=Nobody, unsigned mother=Nobody, EventTime birth={}, EventTime death={});
bool addRelation(const char* firstName, const Relation, const char* secondName); //Adds a new relation or edits an old one. 0 - failure 1 - success
bool addRelation(const unsigned firstId, const Relation, const unsigned secondId, bool opposite=0); //0 - failure 1 - success
void removePerson(const unsigned id); //Removes a member and the last one takes his ID
void removePerson(const char*, const short year = 0, const unsigned char month = 0, const unsigned char day = 0);
void removeRelation(const unsigned firstId, const unsigned secondId);
void removeRelation(const char* firstName, const char* secondName);
void draw() const;
void print()const;
void printRel(const unsigned id)const; //Prints out close relatives
void printMember(const unsigned id)const;
void printOldestAncestors(const unsigned id)const;//
private:
void commonAncestorRec(const unsigned &id, const Array<char> &visited)const;
/* draw a line of people starting from person with id
return the farthest X that will be drawn */
I16 drawLineRec(person_id id, I16 drawY, I16 drawX) const;
std::string treeName = "Unnamed";
unsigned numPeople = 0;
Array<Person> people; //The data for each member
Array<Array<unsigned>> relatives; //The relatives of each member
Array<Array<Relation>> relations; //The type of relation each member has with his relatives
U16 offset = 0;
//Search, ect.
};