Website Summary Files Commits Branches @commit @diff @stats
path: root / Week05 / Exercise03 / TaxDatabase.cpp
diff options
context:
space:
mode:
1 files changed, 333 insertions, 0 deletions
-rw-r--r--Week05/Exercise03/TaxDatabase.cpp333
diff --git a/Week05/Exercise03/TaxDatabase.cpp b/Week05/Exercise03/TaxDatabase.cpp
new file mode 100644
index 0000000..c12c228
--- /dev/null
+++ b/Week05/Exercise03/TaxDatabase.cpp
@@ -0,0 +1,333 @@
+#include "TaxDatabase.h"
+#include <iostream>
+
+void TaxDatabase::free() {
+ delete[] people;
+ delete[] reports;
+}
+
+void TaxDatabase::copyFrom(const TaxDatabase& other) {
+ peopleCount = other.peopleCount;
+ peopleAllocated = other.peopleAllocated;
+
+ people = new Person[peopleAllocated];
+ for (unsigned i = 0; i < peopleCount; ++i)
+ people[i] = other.people[i];
+
+ reportsCount = other.reportsCount;
+ reportsAllocated = other.reportsAllocated;
+
+ reports = new TaxReport[reportsAllocated];
+ for (unsigned i = 0; i < reportsCount; ++i)
+ reports[i] = other.reports[i];
+}
+
+void TaxDatabase::resizePeople() {
+ unsigned newAllocated = peopleAllocated == 0 ? 8 : peopleAllocated * 2;
+ Person* newPeople = new Person[newAllocated];
+
+ for (unsigned i = 0; i < peopleCount; ++i)
+ newPeople[i] = people[i];
+
+ delete[] people;
+ people = newPeople;
+ peopleAllocated = newAllocated;
+}
+
+void TaxDatabase::resizeReports() {
+ unsigned newAllocated = reportsAllocated == 0 ? 8 : reportsAllocated * 2;
+ TaxReport* newReports = new TaxReport[newAllocated];
+
+ for (unsigned i = 0; i < reportsCount; ++i)
+ newReports[i] = reports[i];
+
+ delete[] reports;
+ reports = newReports;
+ reportsAllocated = newAllocated;
+}
+
+TaxDatabase::TaxDatabase() {
+ people = nullptr;
+ reports = nullptr;
+ peopleCount = peopleAllocated = reportsCount = reportsAllocated = 0;
+}
+
+TaxDatabase::~TaxDatabase() {
+ free();
+}
+
+TaxDatabase::TaxDatabase(const TaxDatabase& other) {
+ copyFrom(other);
+}
+
+TaxDatabase& TaxDatabase::operator=(const TaxDatabase& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+TaxDatabase::TaxDatabase(TaxDatabase&& other) {
+ people = other.people;
+ peopleCount = other.peopleCount;
+ peopleAllocated = other.peopleAllocated;
+
+ reports = other.reports;
+ reportsCount = other.reportsCount;
+ reportsAllocated = other.reportsAllocated;
+
+ other.people = nullptr;
+ other.reports = nullptr;
+ other.peopleCount = other.peopleAllocated = other.reportsCount = other.reportsAllocated = 0;
+}
+
+TaxDatabase& TaxDatabase::operator=(TaxDatabase&& other) {
+ if (this != &other) {
+ free();
+
+ people = other.people;
+ peopleCount = other.peopleCount;
+ peopleAllocated = other.peopleAllocated;
+
+ reports = other.reports;
+ reportsCount = other.reportsCount;
+ reportsAllocated = other.reportsAllocated;
+
+ other.people = nullptr;
+ other.reports = nullptr;
+ other.peopleCount = other.peopleAllocated = other.reportsCount = other.reportsAllocated = 0;
+ }
+ return *this;
+}
+
+bool TaxDatabase::RegisterPerson(const Person& person) {
+ for (unsigned i = 0; i < peopleCount; ++i) {
+ if (people[i].GetPN() == person.GetPN() ||
+ people[i].GetPhoneNumber() == person.GetPhoneNumber() ||
+ people[i].GetEmail().IsTheSameAs(person.GetEmail()))
+ {
+ return false;
+ }
+ }
+
+ if (peopleCount >= peopleAllocated)
+ resizePeople();
+ people[peopleCount++] = person;
+
+ return true;
+}
+
+bool TaxDatabase::LogTaxReport(const TaxReport& report) {
+ for (unsigned i = 0; i < reportsCount; ++i) {
+ if (reports[i].GetPN() == report.GetPN() &&
+ reports[i].GetYear() == report.GetYear())
+ {
+ return false;
+ }
+ }
+
+ if (reportsCount >= reportsAllocated)
+ resizeReports();
+ reports[reportsCount++] = report;
+
+ return true;
+}
+
+void TaxDatabase::PersonalReports(unsigned long long PN) const {
+ const Person* p = GetPerson(PN);
+ if (p == nullptr) {
+ std::cout << "Person not in database!" << std::endl;
+ return;
+ }
+
+ std::cout << p->GetFirstName().GetStr() << ' ' << p->GetMiddleName().GetStr() << ' ' << p->GetLastName().GetStr() << std::endl
+ << "Personal No: " << p->GetPN() << " Born: " << p->GetBirthYear() << std::endl
+ << "Tel: " << p->GetPhoneNumber() << " Email: " << p->GetEmail().GetStr() << std::endl;
+
+ for (unsigned i = 0; i < reportsCount; ++i) {
+ if (reports[i].GetPN() == PN) {
+ std::cout << reports[i].GetYear()
+ << " Income: " << reports[i].GetIncome()
+ << " Tax rate: " << reports[i].GetTaxRate() << std::endl;
+ }
+ }
+}
+
+void TaxDatabase::YearlyReports(unsigned short year) const {
+ for (unsigned i = 0; i < reportsCount; ++i) {
+ if (reports[i].GetYear() != year)
+ continue;
+
+ const Person* p = GetPerson(reports[i].GetPN());
+ if (p != nullptr) {
+ std::cout << p->GetFirstName().GetStr() << ' ' << p->GetLastName().GetStr()
+ << " Age: " << (year - p->GetBirthYear())
+ << " Income: " << reports[i].GetIncome()
+ << " Tax rate: " << reports[i].GetTaxRate() << std::endl;
+ }
+ }
+}
+
+double TaxDatabase::YearlyAvgIncome(unsigned short year) const {
+ double incomeSum = 0.0;
+ unsigned reportsInYear = 0;
+
+ for (unsigned i = 0; i < reportsCount; ++i) {
+ if (reports[i].GetYear() != year)
+ continue;
+
+ incomeSum += reports[i].GetIncome();
+ ++reportsInYear;
+ }
+
+ return incomeSum / reportsInYear;
+}
+
+double TaxDatabase::YearlyTaxedIncome(unsigned short year) const {
+ double profits = 0.0;
+
+ for (unsigned i = 0; i < reportsCount; ++i) {
+ if (reports[i].GetYear() != year)
+ continue;
+
+ profits += reports[i].GetIncome() * reports[i].GetTaxRate();
+ }
+
+ return profits;
+}
+
+const TaxReport* TaxDatabase::GetReport(unsigned long long PN, unsigned short year) const {
+ for (unsigned i = 0; i < reportsCount; ++i) {
+ if (reports[i].GetPN() == PN && reports[i].GetYear() == year)
+ return reports + i;
+ }
+ return nullptr;
+}
+
+const TaxReport* TaxDatabase::GetReportByAge(unsigned long long PN, unsigned short age) const {
+ const Person* p = GetPerson(PN);
+
+ if (p == nullptr)
+ return nullptr;
+
+ return GetReport(PN, p->GetBirthYear() + age);
+}
+
+void TaxDatabase::Reports::copyFrom(const Reports& other) {
+ reportsCount = other.reportsCount;
+
+ reports = new TaxReport*[reportsCount];
+ for (unsigned i = 0; i < reportsCount; ++i)
+ reports[i] = other.reports[i];
+}
+
+void TaxDatabase::Reports::free() {
+ delete[] reports;
+}
+
+TaxDatabase::Reports::Reports() {
+ reports = nullptr;
+ reportsCount = 0;
+}
+
+TaxDatabase::Reports::~Reports() {
+ free();
+}
+
+TaxDatabase::Reports::Reports(const Reports& other) {
+ copyFrom(other);
+}
+
+TaxDatabase::Reports& TaxDatabase::Reports::operator=(const Reports& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+TaxDatabase::Reports::Reports(Reports&& other) {
+ reports = other.reports;
+ reportsCount = other.reportsCount;
+
+ other.reports = nullptr;
+ other.reportsCount = 0;
+}
+
+TaxDatabase::Reports& TaxDatabase::Reports::operator=(Reports&& other) {
+ if (this != &other) {
+ free();
+
+ reports = other.reports;
+ reportsCount = other.reportsCount;
+
+ other.reports = nullptr;
+ other.reportsCount = 0;
+ }
+ return *this;
+}
+
+unsigned TaxDatabase::Reports::ReportsCount() const {
+ return reportsCount;
+}
+
+const TaxReport* TaxDatabase::Reports::At(unsigned index) const {
+ if (index >= reportsCount)
+ return nullptr;
+
+ return reports[index];
+}
+
+void TaxDatabase::Reports::Allocate(unsigned size) {
+ reportsCount = size;
+ if (reports != nullptr)
+ delete[] reports;
+ reports = new TaxReport*[size];
+}
+
+TaxReport** TaxDatabase::Reports::At(unsigned index) {
+ if (index >= reportsCount)
+ return nullptr;
+
+ return reports + index;
+}
+
+const TaxDatabase::Reports TaxDatabase::GetReports(unsigned long long PN, unsigned short startYear, unsigned short endYear) const {
+ unsigned countReports = 0;
+
+ for (unsigned i = 0; i < reportsCount; ++i) {
+ if (reports[i].GetPN() == PN && startYear <= reports[i].GetYear() && reports[i].GetYear() <= endYear)
+ ++countReports;
+ }
+
+ Reports result;
+ result.Allocate(countReports);
+
+ unsigned reportIndex = 0;
+ for (unsigned i = 0; i < reportsCount; ++i) {
+ if (reports[i].GetPN() == PN && startYear <= reports[i].GetYear() && reports[i].GetYear() <= endYear) {
+ *result.At(reportIndex++) = reports + i;
+ }
+ }
+
+ return result;
+}
+
+const TaxDatabase::Reports TaxDatabase::GetReportsByAge(unsigned long long PN, unsigned short startAge, unsigned short endAge) const {
+ const Person* p = GetPerson(PN);
+
+ if (p == nullptr)
+ return Reports();
+
+ return GetReports(PN, p->GetBirthYear() + startAge, p->GetBirthYear() + endAge);
+}
+
+const Person* TaxDatabase::GetPerson(unsigned long long PN) const {
+ for (unsigned i = 0; i < peopleCount; ++i) {
+ if (people[i].GetPN() == PN) {
+ return people + i;
+ }
+ }
+ return nullptr;
+}