Self-complete

This commit is contained in:
2026-05-22 14:49:02 +03:00
parent 0e74a9eb90
commit a5d6b3af21
47 changed files with 7003 additions and 570 deletions
+8 -1
View File
@@ -3,8 +3,15 @@
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="userId" value="-51ab2c09:19e209689d2:-7dc7" />
<option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="51fce684:19c942ae0f3:-7ffd" />
</MTProjectMetadataState>
</option>
<option name="titleBarState">
<MTProjectTitleBarConfigState>
<option name="overrideColor" value="false" />
</MTProjectTitleBarConfigState>
</option>
</component>
</project>
+37 -17
View File
@@ -3,22 +3,42 @@ project(Lab8)
set(CMAKE_CXX_STANDARD 20)
include(FetchContent)
FetchContent_Declare(
nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.3
)
FetchContent_MakeAvailable(nlohmann_json)
add_executable(Lab8
src/TaxRates.h
src/Property.h
src/Property.cpp
src/Apartment.cpp
src/Apartment.h
src/Car.cpp
src/Car.h
src/CountryHouse.cpp
src/CountryHouse.h
src/main.cpp
src/Property/Property.cpp
src/Property/Property.h
src/Apartment/Apartment.cpp
src/Apartment/Apartment.h
src/Car/Car.cpp
src/Car/Car.h
src/CountryHouse/CountryHouse.cpp
src/CountryHouse/CountryHouse.h
src/Owner/Owner.cpp
src/Owner/Owner.h
src/TaxRates/TaxRates.h
src/Human/Human.cpp
src/Human/Human.h
src/City/City.cpp
src/City/City.h
src/PropertyFactory/PropertyFactory.cpp
src/PropertyFactory/PropertyFactory.h)
src/Owner.cpp
src/Owner.h
src/Ijsonio.cpp
src/Ijsonio.h
src/PropertySimpleFactory.cpp
src/PropertySimpleFactory.h
src/TaxService.cpp
src/TaxService.h
src/tinyxml2.cpp
src/tinyxml2.h
src/Ixmlio.cpp
src/Ixmlio.h
src/FileType.h
src/FileTypeFactory.h
src/FileTypeFactory.cpp
)
target_link_libraries(Lab8 PRIVATE nlohmann_json::nlohmann_json)
+124 -23
View File
@@ -1,42 +1,143 @@
@startuml
skinparam classAttributeIconSize 0
class Property {
# double price
# string address
+ show()
+ clone()
title Lab8 - Property Tax System
' =======================
' ENUM
' =======================
enum FileType {
JSON
XML
ANOTHER
}
' =======================
' INTERFACES
' =======================
interface Ijsonio {
+fromJson(json)
+toJson() : json
}
interface Ixmlio {
+fromXml(XMLElement*)
+toXml(XMLDocument&) : XMLElement*
}
' =======================
' ABSTRACT CLASS
' =======================
abstract class Property {
#worth : double
+Property(worth)
+calculateTax() : double
+incomeTax() : double
+fromJson(json)
+toJson() : json
+fromXml(XMLElement*)
+toXml(XMLDocument&) : XMLElement*
+~Property()
}
Property ..|> Ijsonio
Property ..|> Ixmlio
' =======================
' DERIVED CLASSES
' =======================
class Apartment {
- int rooms
+ show()
+ clone()
#square : double
+calculateTax() : double
}
class Car {
- string brand
- int horsepower
+ show()
+ clone()
#horsepower : double
+calculateTax() : double
}
class CountryHouse {
- int floors
- double landArea
+ show()
+ clone()
}
class City {
- vector<Property>
+ addProperty()
+ showAll()
#distanceFromCity : double
+calculateTax() : double
}
Property <|-- Apartment
Property <|-- Car
Property <|-- CountryHouse
City o-- Property
' =======================
' OWNER
' =======================
class Owner {
-fullname : string
-inn : string
-properties : vector<Property*>
+addProperty(Property*)
+removeProperty(int)
+calculateTotalTax() : double
+showProperties()
+fromJson(json)
+toJson() : json
+fromXml(XMLElement*)
+toXml(XMLDocument&) : XMLElement*
+~Owner()
}
Owner ..|> Ijsonio
Owner ..|> Ixmlio
Owner *-- Property : owns
' =======================
' FACTORY
' =======================
class PropertySimpleFactory {
+static getProperty(key : string) : Property*
}
Owner ..> PropertySimpleFactory
' =======================
' SERVICE LAYER
' =======================
class TaxService {
-owners : vector<Owner*>
+load(filename)
+save(filename)
+loadFromJson()
+saveToJson()
+loadFromXml()
+saveToXml()
+addOwner()
+removeOwner()
+addProperty()
+removeProperty()
+showOwners()
+~TaxService()
}
TaxService o-- Owner
' =======================
' FILE TYPE FACTORY
' =======================
class FileTypeFactory {
+static getFileType(filename) : FileType
}
FileTypeFactory ..> FileType
@enduml
View File
View File
+74
View File
@@ -0,0 +1,74 @@
#include "Apartment.h"
#include "TaxRates.h"
Apartment::Apartment(double worth, double square)
: Property(worth)
{
this->square = square;
}
double Apartment::calculateTax()
{
if (square > TAX_RATES::LIMIT_APARTMENT_SQUARE)
{
return worth * TAX_RATES::APARTMENT_LUXURY_TAX;
}
return worth * TAX_RATES::APARTMENT_TAX;
}
void Apartment::fromJson(json j)
{
worth = j["worth"];
square = j["square"];
}
json Apartment::toJson()
{
json j;
j["worth"] = worth;
j["square"] = square;
j["tax"] = calculateTax();
return j;
}
void Apartment::fromXml(
XMLElement* element)
{
element->QueryDoubleAttribute(
"worth",
&worth
);
element->QueryDoubleAttribute(
"square",
&square
);
}
XMLElement* Apartment::toXml(
XMLDocument& doc)
{
XMLElement* element =
doc.NewElement("Apartment");
element->SetAttribute(
"worth",
worth
);
element->SetAttribute(
"square",
square
);
element->SetAttribute(
"tax",
calculateTax()
);
return element;
}
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include "Property.h"
class Apartment : public Property
{
private:
double square;
public:
Apartment(double worth, double square);
void fromJson(json j) override;
json toJson() override;
void fromXml(XMLElement* element) override;
XMLElement* toXml(XMLDocument& doc) override;
double calculateTax() override;
};
-45
View File
@@ -1,45 +0,0 @@
#include "Apartment.h"
#include <iostream>
Apartment::Apartment() {
rooms = 0;
std::cout << "Apartment created\n";
}
Apartment::Apartment(double price,
std::string address,
int rooms)
: Property(price, address) {
this->rooms = rooms;
std::cout << "Apartment created\n";
}
void Apartment::addResident(Human* resident) {
residents.push_back(resident);
}
void Apartment::show() const {
std::cout
<< "\nApartment\n"
<< "Address: " << address << std::endl
<< "Price: " << price << std::endl
<< "Rooms: " << rooms << std::endl;
std::cout << "Residents:\n";
for (int i = 0; i < residents.size(); i++) {
residents[i]->showInfo();
}
}
Apartment::~Apartment() {
std::cout << "Apartment deleted\n";
}
std::unique_ptr<Property> Apartment::clone() const {
return std::make_unique<Apartment>(*this);
}
-26
View File
@@ -1,26 +0,0 @@
#ifndef APARTMENT_H
#define APARTMENT_H
#include "../Property/Property.h"
#include "../Human/Human.h"
#include <vector>
class Apartment : public Property {
private:
int rooms;
std::vector<Human*> residents;
public:
Apartment();
Apartment(double price,
std::string address,
int rooms);
void addResident(Human* resident);
void show() const override;
~Apartment();
};
#endif
+90
View File
@@ -0,0 +1,90 @@
#include "Car.h"
#include "TaxRates.h"
Car::Car(double worth,
double horsepower)
: Property(worth)
{
this->horsepower = horsepower;
}
double Car::calculateTax()
{
if (horsepower <
TAX_RATES::LOW_HORSEPOWER)
{
return worth *
TAX_RATES::CAR_TAX;
}
if (horsepower <=
TAX_RATES::HIGH_HORSEPOWER)
{
return worth *
TAX_RATES::CAR_TRUCK_TAX;
}
return worth *
TAX_RATES::CAR_LUXURY_TAX;
}
void Car::fromJson(json j)
{
worth = j["worth"];
horsepower =
j["horsepower"];
}
json Car::toJson()
{
json j;
j["worth"] = worth;
j["horsepower"] =
horsepower;
j["tax"] =
calculateTax();
return j;
}
void Car::fromXml(
XMLElement* element)
{
element->QueryDoubleAttribute(
"worth",
&worth
);
element->QueryDoubleAttribute(
"horsepower",
&horsepower
);
}
XMLElement* Car::toXml(
XMLDocument& doc)
{
XMLElement* element =
doc.NewElement("Car");
element->SetAttribute(
"worth",
worth
);
element->SetAttribute(
"horsepower",
horsepower
);
element->SetAttribute(
"tax",
calculateTax()
);
return element;
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "Property.h"
#include "Ijsonio.h"
class Car : public Property
{
private:
double horsepower;
public:
Car(double worth,
double horsepower);
double calculateTax() override;
void fromJson(json j) override;
json toJson() override;
void fromXml(XMLElement* element) override;
XMLElement* toXml(XMLDocument& doc) override;
};
-38
View File
@@ -1,38 +0,0 @@
#include "Car.h"
#include <iostream>
Car::Car() {
brand = "Unknown";
horsepower = 0;
std::cout << "Car created\n";
}
Car::Car(double price,
std::string address,
std::string brand,
int horsepower)
: Property(price, address) {
this->brand = brand;
this->horsepower = horsepower;
std::cout << "Car created\n";
}
void Car::show() const {
std::cout
<< "\nCar\n"
<< "Brand: " << brand << std::endl
<< "Horsepower: " << horsepower << std::endl
<< "Price: " << price << std::endl;
}
Car::~Car() {
std::cout << "Car deleted\n";
}
std::unique_ptr<Property> Car::clone() const {
return std::make_unique<Car>(*this);
}
-24
View File
@@ -1,24 +0,0 @@
#ifndef CAR_H
#define CAR_H
#include "../Property/Property.h"
class Car : public Property {
private:
std::string brand;
int horsepower;
public:
Car();
Car(double price,
std::string address,
std::string brand,
int horsepower);
void show() const override;
~Car();
};
#endif
-49
View File
@@ -1,49 +0,0 @@
#include "City.h"
#include <iostream>
City::City() {
std::cout << "City created\n";
}
City::City(const City& other) {
std::cout << "City COPY\n";
for (const auto& p : other.properties) {
properties.push_back(p->clone());
}
}
City& City::operator=(const City& other) {
std::cout << "City ASSIGN\n";
if (this == &other)
return *this;
properties.clear();
for (const auto& p : other.properties) {
properties.push_back(p->clone());
}
return *this;
}
void City::addProperty(const Property& property) {
properties.push_back(property.clone());
}
void City::showAll() const {
std::cout << "\nCITY PROPERTY LIST\n";
for (const auto& p : properties) {
p->show();
}
}
City::~City() {
std::cout << "City destroyed\n";
}
-25
View File
@@ -1,25 +0,0 @@
#ifndef CITY_H
#define CITY_H
#include <vector>
#include <memory>
#include "../Property/Property.h"
class City {
private:
std::vector<std::unique_ptr<Property>> properties;
public:
City();
void addProperty(const Property& property);
void showAll() const;
City(const City& other);
City& operator=(const City& other);
~City();
};
#endif
+74
View File
@@ -0,0 +1,74 @@
#include "CountryHouse.h"
#include "TaxRates.h"
CountryHouse::CountryHouse(double worth,
double distanceFromCity)
: Property(worth)
{
this->distanceFromCity = distanceFromCity;
}
double CountryHouse::calculateTax()
{
return worth * TAX_RATES::COUNTRY_HOUSE_TAX;
}
void CountryHouse::fromJson(json j)
{
worth = j["worth"];
distanceFromCity =
j["distanceFromCity"];
}
json CountryHouse::toJson()
{
json j;
j["worth"] = worth;
j["distanceFromCity"] =
distanceFromCity;
j["tax"] = calculateTax();
return j;
}
void CountryHouse::fromXml(
XMLElement* element)
{
element->QueryDoubleAttribute(
"worth",
&worth
);
element->QueryDoubleAttribute(
"distanceFromCity",
&distanceFromCity
);
}
XMLElement* CountryHouse::toXml(
XMLDocument& doc)
{
XMLElement* element =
doc.NewElement("CountryHouse");
element->SetAttribute(
"worth",
worth
);
element->SetAttribute(
"distanceFromCity",
distanceFromCity
);
element->SetAttribute(
"tax",
calculateTax()
);
return element;
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "Property.h"
#include "Ijsonio.h"
class CountryHouse : public Property
{
private:
double distanceFromCity;
public:
CountryHouse(double worth, double distanceFromCity);
void fromJson(json j) override;
json toJson() override;
double calculateTax() override;
void fromXml(XMLElement* element) override;
XMLElement* toXml(XMLDocument& doc) override;
};
-39
View File
@@ -1,39 +0,0 @@
#include "CountryHouse.h"
#include <iostream>
CountryHouse::CountryHouse() {
floors = 0;
landArea = 0;
std::cout << "CountryHouse created\n";
}
CountryHouse::CountryHouse(double price,
std::string address,
int floors,
double landArea)
: Property(price, address) {
this->floors = floors;
this->landArea = landArea;
std::cout << "CountryHouse created\n";
}
void CountryHouse::show() const {
std::cout
<< "\nCountry House\n"
<< "Address: " << address << std::endl
<< "Floors: " << floors << std::endl
<< "Land area: " << landArea << std::endl
<< "Price: " << price << std::endl;
}
CountryHouse::~CountryHouse() {
std::cout << "CountryHouse deleted\n";
}
std::unique_ptr<Property> CountryHouse::clone() const {
return std::make_unique<CountryHouse>(*this);
}
-24
View File
@@ -1,24 +0,0 @@
#ifndef COUNTRYHOUSE_H
#define COUNTRYHOUSE_H
#include "../Property/Property.h"
class CountryHouse : public Property {
private:
int floors;
double landArea;
public:
CountryHouse();
CountryHouse(double price,
std::string address,
int floors,
double landArea);
void show() const override;
~CountryHouse();
};
#endif
+8
View File
@@ -0,0 +1,8 @@
#pragma once
enum class FileType
{
JSON,
XML,
ANOTHER
};
+21
View File
@@ -0,0 +1,21 @@
#include "FileTypeFactory.h"
FileType FileTypeFactory::getFileType(
std::string filename)
{
if (filename.size() >= 5 &&
filename.substr(
filename.size() - 5
) == ".json")
{
return FileType::JSON;
}
if (filename.size() >= 4 &&
filename.substr(
filename.size() - 4
) == ".xml")
{
return FileType::XML;
}
return FileType::ANOTHER;
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <string>
#include "FileType.h"
class FileTypeFactory
{
public:
static FileType getFileType(
std::string filename
);
};
-45
View File
@@ -1,45 +0,0 @@
#include "Human.h"
#include <iostream>
Human::Human() {
name = "Unknown";
surname = "Unknown";
age = 0;
std::cout << "Human created\n";
}
Human::Human(std::string name, std::string surname, int age) {
this->name = name;
this->surname = surname;
this->age = age;
std::cout << "Human created: "
<< name << " "
<< surname << std::endl;
}
std::string Human::getName() const {
return name;
}
std::string Human::getSurname() const {
return surname;
}
int Human::getAge() const {
return age;
}
void Human::showInfo() const {
std::cout
<< name << " "
<< surname << ", age: "
<< age << std::endl;
}
Human::~Human() {
std::cout << "Human deleted: "
<< name << " "
<< surname << std::endl;
}
-25
View File
@@ -1,25 +0,0 @@
#ifndef HUMAN_H
#define HUMAN_H
#include <string>
class Human {
private:
std::string name;
std::string surname;
int age;
public:
Human();
Human(std::string name, std::string surname, int age);
std::string getName() const;
std::string getSurname() const;
int getAge() const;
void showInfo() const;
~Human();
};
#endif
+5
View File
@@ -0,0 +1,5 @@
//
// Created by Михаил on 22.05.2026.
//
#include "Ijsonio.h"
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include "nlohmann/json.hpp"
using json = nlohmann::json;
class Ijsonio
{
public:
virtual void fromJson(json j) = 0;
virtual json toJson() = 0;
virtual ~Ijsonio() {}
};
+5
View File
@@ -0,0 +1,5 @@
//
// Created by Михаил on 22.05.2026.
//
#include "Ixmlio.h"
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include "tinyxml2.h"
using namespace tinyxml2;
class Ixmlio
{
public:
virtual void fromXml(
XMLElement* element
) = 0;
virtual XMLElement* toXml(
XMLDocument& doc
) = 0;
virtual ~Ixmlio() {}
};
+239
View File
@@ -0,0 +1,239 @@
#include "Owner.h"
#include <iostream>
#include <cctype>
bool isValidINN(const std::string& inn)
{
if (inn.size() != 12)
return false;
for (char c : inn)
{
if (!std::isdigit(c))
return false;
}
return true;
}
Owner::Owner(std::string fullname,
std::string inn)
{
this->fullname = fullname;
this->inn = inn;
}
Owner::~Owner()
{
for (Property* property : properties)
{
delete property;
}
}
void Owner::addProperty(Property* property)
{
properties.push_back(property);
}
void Owner::removeProperty(int index)
{
if (index < 0 || index >= properties.size())
{
std::cout << "Invalid index" << std::endl;
return;
}
delete properties[index];
properties.erase(properties.begin() + index);
}
double Owner::calculateTotalTax()
{
double total = 0;
for (Property* property : properties)
{
total += property->calculateTax();
}
return total;
}
void Owner::showProperties()
{
std::cout << "Owner: "
<< fullname
<< std::endl;
std::cout << "INN: "
<< inn
<< std::endl;
std::cout << std::endl;
for (int i = 0; i < properties.size(); i++)
{
std::cout << i + 1
<< ". Tax: "
<< properties[i]->calculateTax()
<< std::endl;
}
std::cout << std::endl;
std::cout << "Total tax: "
<< calculateTotalTax()
<< std::endl;
}
std::string Owner::getFullname() const
{
return fullname;
}
int Owner::getPropertiesCount() const
{
return properties.size();
}
void Owner::fromJson(json j)
{
fullname = j["fullname"];
inn = j["inn"];
json propertiesJson =
j["properties"];
for (auto elem : propertiesJson)
{
std::string key =
elem.items().begin().key();
Property* property =
PropertySimpleFactory::
getProperty(key);
property->fromJson(elem[key]);
properties.push_back(property);
}
}
json Owner::toJson()
{
json j;
j["fullname"] = fullname;
j["inn"] = inn;
j["totalTax"] =
calculateTotalTax();
json propertiesJson =
json::array();
for (Property* property : properties)
{
Apartment* apartment =
dynamic_cast<Apartment*>(property);
if (apartment)
{
propertiesJson.push_back(
{
{
"Apartment",
apartment->toJson()
}
});
continue;
}
Car* car =
dynamic_cast<Car*>(property);
if (car)
{
propertiesJson.push_back(
{
{
"Car",
car->toJson()
}
});
}
CountryHouse* house =
dynamic_cast<CountryHouse*>(property);
if (house)
{
propertiesJson.push_back(
{
{
"CountryHouse",
house->toJson()
}
});
}
}
j["properties"] = propertiesJson;
return j;
}
void Owner::fromXml(
XMLElement* element)
{
fullname =
element->Attribute("fullname");
inn =
element->Attribute("inn");
XMLElement* child =
element->FirstChildElement();
while (child)
{
std::string key =
child->Name();
Property* property =
PropertySimpleFactory::
getProperty(key);
property->fromXml(child);
properties.push_back(property);
child =
child->NextSiblingElement();
}
}
XMLElement* Owner::toXml(
XMLDocument& doc)
{
XMLElement* ownerElement =
doc.NewElement("Owner");
ownerElement->SetAttribute(
"fullname",
fullname.c_str()
);
ownerElement->SetAttribute(
"inn",
inn.c_str()
);
for (Property* property : properties)
{
ownerElement->InsertEndChild(
property->toXml(doc)
);
}
return ownerElement;
}
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include <string>
#include <vector>
#include "Property.h"
#include "Apartment.h"
#include "Car.h"
#include "CountryHouse.h"
#include "Ixmlio.h"
#include "PropertySimpleFactory.h"
class Owner : public Ijsonio, public Ixmlio{
private:
std::string fullname;
std::string inn;
std::vector<Property*> properties;
public:
Owner(std::string fullname,
std::string inn);
~Owner();
void addProperty(Property* property);
void removeProperty(int index);
double calculateTotalTax();
void showProperties();
void fromJson(json j) override;
json toJson() override;
std::string getFullname() const;
int getPropertiesCount() const;
void fromXml(XMLElement* element) override;
XMLElement* toXml(XMLDocument& doc) override;
const std::vector<Property*>& getProperties() const;
};
bool isValidINN(const std::string& inn);
-31
View File
@@ -1,31 +0,0 @@
#include "Owner.h"
#include <iostream>
Owner::Owner() : Human() {
std::cout << "Owner created\n";
}
Owner::Owner(std::string name,
std::string surname,
int age)
: Human(name, surname, age) {
std::cout << "Owner created\n";
}
void Owner::addProperty(Property* property) {
properties.push_back(property);
}
void Owner::showProperties() const {
std::cout << "\nOWNER PROPERTY LIST\n";
for (int i = 0; i < properties.size(); i++) {
properties[i]->show();
}
}
Owner::~Owner() {
std::cout << "Owner deleted\n";
}
-26
View File
@@ -1,26 +0,0 @@
#ifndef OWNER_H
#define OWNER_H
#include "../Human/Human.h"
#include "../Property/Property.h"
#include <vector>
class Owner : public Human {
private:
std::vector<Property*> properties;
public:
Owner();
Owner(std::string name,
std::string surname,
int age);
void addProperty(Property* property);
void showProperties() const;
~Owner();
};
#endif
+14
View File
@@ -0,0 +1,14 @@
#include "Property.h"
Property::Property(double worth)
{
this->worth = worth;
}
Property::~Property()
{ }
double Property::calculateIncomeTax() const
{
return worth * 0.13;
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include "Ijsonio.h"
#include "Ixmlio.h"
class Property :
public Ijsonio,
public Ixmlio
{
protected:
double worth;
public:
Property(double worth);
virtual ~Property();
virtual double calculateTax() = 0;
double calculateIncomeTax() const;
};
-16
View File
@@ -1,16 +0,0 @@
#include "Property.h"
#include <iostream>
Property::Property() {
price = 0;
address = "Unknown";
}
Property::Property(double price, std::string address) {
this->price = price;
this->address = address;
}
Property::~Property() {
std::cout << "Property deleted\n";
}
-23
View File
@@ -1,23 +0,0 @@
#ifndef PROPERTY_H
#define PROPERTY_H
#include <string>
#include <memory>
class Property {
protected:
double price;
std::string address;
public:
Property();
Property(double price, std::string address);
virtual void show() const = 0;
virtual std::unique_ptr<Property> clone() const = 0;
virtual ~Property();
};
#endif
-21
View File
@@ -1,21 +0,0 @@
#include "PropertyFactory.h"
#include "../Apartment/Apartment.h"
#include "../Car/Car.h"
#include "../CountryHouse/CountryHouse.h"
std::unique_ptr<Property> PropertyFactory::create(Type type) {
switch (type) {
case APARTMENT:
return std::make_unique<Apartment>(120000, "Moscow", 3);
case CAR:
return std::make_unique<Car>(30000, "Garage", "BMW", 250);
case COUNTRY_HOUSE:
return std::make_unique<CountryHouse>(500000, "Village", 2, 15.5);
}
return nullptr;
}
-18
View File
@@ -1,18 +0,0 @@
#ifndef PROPERTYFACTORY_H
#define PROPERTYFACTORY_H
#include <memory>
#include "../Property/Property.h"
class PropertyFactory {
public:
enum Type {
APARTMENT,
CAR,
COUNTRY_HOUSE
};
static std::unique_ptr<Property> create(Type type);
};
#endif
+26
View File
@@ -0,0 +1,26 @@
#include "PropertySimpleFactory.h"
#include "Apartment.h"
#include "Car.h"
#include "CountryHouse.h"
Property* PropertySimpleFactory::
getProperty(std::string key)
{
if (key == "Apartment")
{
return new Apartment(0, 0);
}
if (key == "Car")
{
return new Car(0, 0);
}
if (key == "CountryHouse")
{
return new CountryHouse(0, 0);
}
return nullptr;
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <string>
#include "Property.h"
class PropertySimpleFactory
{
public:
static Property* getProperty(
std::string key
);
};
+20
View File
@@ -0,0 +1,20 @@
#pragma once
namespace TAX_RATES
{
const double CAR_TAX = 0.0007;
const double CAR_TRUCK_TAX = 0.007;
const double CAR_LUXURY_TAX = 0.027;
const double APARTMENT_TAX = 0.001;
const double APARTMENT_LUXURY_TAX = 0.004;
const double COUNTRY_HOUSE_TAX = 0.01;
const double LOW_HORSEPOWER = 100;
const double HIGH_HORSEPOWER = 200;
const unsigned int LIMIT_DISTANCE_FROM_CITY = 30;
const int LIMIT_APARTMENT_SQUARE = 100;
}
-43
View File
@@ -1,43 +0,0 @@
#ifndef TAXRATES_H
#define TAXRATES_H
namespace TAX_RATES {
// ==========================
// НАЛОГИ ДЛЯ АВТОМОБИЛЕЙ
// ==========================
const double CAR_TAX = 0.0007;
const double CAR_TRUCK_TAX = 0.007;
const double CAR_LUXURY_TAX = 0.027;
// ==========================
// НАЛОГИ ДЛЯ КВАРТИР
// ==========================
const double APARTMENT_TAX = 0.001;
const double APARTMENT_LUXURY_TAX = 0.004;
// ==========================
// НАЛОГ ДЛЯ ДОМА
// ==========================
const double COUNTRY_HOUSE_TAX = 0.01;
// ==========================
// ГРАНИЦЫ
// ==========================
const double LOW_HORSEPOWER = 100;
const double HIGH_HORSEPOWER = 200;
const unsigned int LIMIT_DISTANCE_FROM_CITY = 30;
const int LIMIT_APARTMENT_SQUARE = 100;
}
#endif
+413
View File
@@ -0,0 +1,413 @@
#include "TaxService.h"
#include "FileTypeFactory.h"
#include <fstream>
#include <iostream>
TaxService::~TaxService()
{
for (Owner* owner : owners)
{
delete owner;
}
}
void TaxService::loadFromJson(
std::string filename)
{
std::ifstream in(filename);
if (!in.is_open())
{
throw std::runtime_error(
"Cannot open input file"
);
}
json j;
in >> j;
in.close();
for (auto elem : j)
{
Owner* owner =
new Owner("", "");
owner->fromJson(elem);
owners.push_back(owner);
}
}
void TaxService::saveToJson(
std::string filename)
{
json result =
json::array();
for (Owner* owner : owners)
{
result.push_back(
owner->toJson()
);
}
std::ofstream out(filename);
if (!out.is_open())
{
throw std::runtime_error(
"Cannot open output file"
);
}
out << result.dump(4);
out.close();
}
void TaxService::showOwners()
{
for (Owner* owner : owners)
{
owner->showProperties();
std::cout << std::endl;
}
}
void TaxService::load(
std::string filename)
{
FileType type =
FileTypeFactory::
getFileType(filename);
switch (type)
{
case FileType::JSON:
{
loadFromJson(filename);
break;
}
case FileType::XML:
{
loadFromXml(filename);
break;
}
default:
{
throw std::runtime_error(
"Unknown file type"
);
}
}
}
void TaxService::save(
std::string filename)
{
FileType type =
FileTypeFactory::
getFileType(filename);
switch (type)
{
case FileType::JSON:
{
saveToJson(filename);
break;
}
case FileType::XML:
{
saveToXml(filename);
break;
}
default:
{
throw std::runtime_error(
"Unknown file type"
);
}
}
}
void TaxService::loadFromXml(
std::string filename)
{
XMLDocument doc;
if (doc.LoadFile(
filename.c_str())
!= XML_SUCCESS)
{
throw std::runtime_error(
"Cannot load XML"
);
}
XMLElement* root =
doc.FirstChildElement(
"Owners"
);
XMLElement* elem =
root->FirstChildElement(
"Owner"
);
while (elem)
{
Owner* owner =
new Owner("", "");
owner->fromXml(elem);
owners.push_back(owner);
elem =
elem->NextSiblingElement(
"Owner"
);
}
}
void TaxService::saveToXml(
std::string filename)
{
XMLDocument doc;
XMLElement* root =
doc.NewElement("Owners");
doc.InsertFirstChild(root);
for (Owner* owner : owners)
{
root->InsertEndChild(
owner->toXml(doc)
);
}
doc.SaveFile(
filename.c_str()
);
}
void TaxService::addOwner()
{
std::string fullname;
std::string inn;
std::cin.ignore();
std::cout << "Fullname: ";
std::getline(std::cin, fullname);
std::cout << "INN (12 digits): ";
std::getline(std::cin, inn);
if (!isValidINN(inn))
{
std::clog << "ERROR: Invalid INN\n";
return;
}
Owner* owner = new Owner(fullname, inn);
owners.push_back(owner);
std::cout << "Owner added!\n";
}
void TaxService::removeOwner()
{
showOwners();
int index;
std::cout
<< "Owner index: ";
std::cin
>> index;
if (index < 0 ||
index >= owners.size())
{
std::cout
<< "Invalid index\n";
return;
}
delete owners[index];
owners.erase(
owners.begin() + index
);
std::cout
<< "Owner removed!\n";
}
void TaxService::addProperty() {
showOwners();
int ownerIndex;
std::cout
<< "Choose owner: ";
std::cin
>> ownerIndex;
if (ownerIndex < 0 ||
ownerIndex >= owners.size()) {
std::cout
<< "Invalid index\n";
return;
}
int type;
std::cout
<< "\n1. Apartment\n";
std::cout
<< "2. Car\n";
std::cout
<< "3. CountryHouse\n";
std::cout
<< "Choose type: ";
std::cin
>> type;
if (type == 1) {
double worth;
double square;
std::cout
<< "Worth: ";
std::cin
>> worth;
std::cout
<< "Square: ";
std::cin
>> square;
owners[ownerIndex]
->addProperty(
new Apartment(
worth,
square
)
);
} else if (type == 2) {
double worth;
double horsepower;
std::cout
<< "Worth: ";
std::cin
>> worth;
std::cout
<< "Horsepower: ";
std::cin
>> horsepower;
owners[ownerIndex]
->addProperty(
new Car(
worth,
horsepower
)
);
} else if (type == 3) {
double worth;
double distance;
std::cout
<< "Worth: ";
std::cin
>> worth;
std::cout
<< "Distance: ";
std::cin
>> distance;
owners[ownerIndex]
->addProperty(
new CountryHouse(
worth,
distance
)
);
}
}
void TaxService::removeProperty()
{
if (owners.empty())
{
std::cout << "No owners available\n";
return;
}
showOwners();
int ownerIndex;
std::cout << "Choose owner: ";
std::cin >> ownerIndex;
if (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(
std::numeric_limits<std::streamsize>::max(),
'\n'
);
std::cout << "Invalid input\n";
return;
}
if (ownerIndex < 0 || ownerIndex >= owners.size())
{
std::cout << "Invalid owner index\n";
return;
}
Owner* owner = owners[ownerIndex];
if (owner->getProperties().empty())
{
std::cout << "This owner has no properties\n";
return;
}
std::cout << "\nProperties:\n";
owner->showProperties();
int propertyIndex;
std::cout << "Property index: ";
std::cin >> propertyIndex;
if (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(
std::numeric_limits<std::streamsize>::max(),
'\n'
);
std::cout << "Invalid input\n";
return;
}
if (propertyIndex < 0 ||
propertyIndex >= owner->getProperties().size())
{
std::cout << "Invalid property index\n";
return;
}
owner->removeProperty(propertyIndex);
std::cout << "Property removed successfully\n";
}
+45
View File
@@ -0,0 +1,45 @@
#pragma once
#include <vector>
#include <string>
#include "Owner.h"
class TaxService
{
private:
std::vector<Owner*> owners;
public:
~TaxService();
void loadFromJson(
std::string filename
);
void saveToJson(
std::string filename
);
void showOwners();
void loadFromXml(
std::string filename
);
void saveToXml(
std::string filename
);
void load(std::string filename);
void save(std::string filename);
void addOwner();
void removeOwner();
void addProperty();
void removeProperty();
};
+164 -11
View File
@@ -1,18 +1,171 @@
#include "City/City.h"
#include "Apartment/Apartment.h"
#include "Car/Car.h"
#include "CountryHouse/CountryHouse.h"
#include <iostream>
int main() {
#include "TaxService.h"
City city;
city.addProperty(*PropertyFactory::create(PropertyFactory::CAR));
city.addProperty(*PropertyFactory::create(PropertyFactory::APARTMENT));
city.addProperty(*PropertyFactory::create(PropertyFactory::COUNTRY_HOUSE));
int safeIntInput()
{
int x;
city.showAll();
std::cin >> x;
return 0;
while (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(
std::numeric_limits<std::streamsize>::max(),
'\n'
);
std::cout << "Try again: ";
std::cin >> x;
}
return x;
}
void showMenu()
{
std::cout
<< "\n========================\n";
std::cout
<< " TAX PROPERTY SERVICE\n";
std::cout
<< "========================\n";
std::cout
<< "1. Load file\n";
std::cout
<< "2. Show owners\n";
std::cout
<< "3. Add owner\n";
std::cout
<< "4. Remove owner\n";
std::cout
<< "5. Add property\n";
std::cout
<< "6. Remove property\n";
std::cout
<< "7. Save file\n";
std::cout
<< "8. Exit\n";
std::cout
<< "Choose: ";
}
int main()
{
TaxService service;
int choice;
while (true)
{
showMenu();
int choice = safeIntInput();
switch (choice)
{
case 1:
{
std::string filename;
std::cout
<< "Input file: ";
std::cin
>> filename;
try
{
service.load(filename);
std::cout
<< "Loaded!\n";
}
catch (std::exception& ex)
{
std::clog
<< "ERROR: "
<< ex.what()
<< std::endl;
}
break;
}
case 2:
{
service.showOwners();
break;
}
case 3:
{
service.addOwner();
break;
}
case 4:
{
service.removeOwner();
break;
}
case 5:
{
service.addProperty();
break;
}
case 6:
{
service.removeProperty();
break;
}
case 7:
{
std::string filename;
std::cout
<< "Output file: ";
std::cin
>> filename;
try
{
service.save(filename);
std::cout
<< "Saved!\n";
}
catch (std::exception& ex)
{
std::clog
<< "ERROR: "
<< ex.what()
<< std::endl;
}
break;
}
case 8:
{
return 0;
}
default:
{
std::cout
<< "Invalid choice\n";
}
}
}
}
+3047
View File
File diff suppressed because it is too large Load Diff
+2387
View File
File diff suppressed because it is too large Load Diff