Загрузка данных
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <memory>
#include <stdexcept>
#include <algorithm>
using namespace std;
enum class RoomType {
Standard,
Comfort,
Lux
};
class Guest {
private:
int id;
string name;
int age;
int bonusPoints;
public:
Guest(int id, string name, int age, int bonusPoints)
: id(id), name(name), age(age), bonusPoints(bonusPoints) {
}
int getId() const {
return id;
}
string getName() const {
return name;
}
int getAge() const {
return age;
}
int getBonusPoints() const {
return bonusPoints;
}
bool isAdult() const {
return age > 18;
}
};
class Room {
private:
int id;
string number;
RoomType type;
int capacity;
double pricePerNight;
bool active;
public:
Room(int id, string number, RoomType type, int capacity, double pricePerNight, bool active)
: id(id), number(number), type(type), capacity(capacity), pricePerNight(pricePerNight), active(active) {
}
int getId() const {
return id;
}
string getNumber() const {
return number;
}
RoomType getType() const {
return type;
}
int getCapacity() const {
return capacity;
}
double getPricePerNight() const {
return pricePerNight;
}
bool isActive() const {
return active;
}
};
class Booking {
private:
int id;
int guestId;
int roomId;
int startDay;
int endDay;
int guestsCount;
double totalPrice;
bool paid;
public:
Booking(int id, int guestId, int roomId, int startDay, int endDay, int guestsCount, double totalPrice, bool paid)
: id(id), guestId(guestId), roomId(roomId), startDay(startDay), endDay(endDay),
guestsCount(guestsCount), totalPrice(totalPrice), paid(paid) {
}
int getId() const {
return id;
}
int getGuestId() const {
return guestId;
}
int getRoomId() const {
return roomId;
}
int getStartDay() const {
return startDay;
}
int getEndDay() const {
return endDay;
}
int getGuestsCount() const {
return guestsCount;
}
double getTotalPrice() const {
return totalPrice;
}
bool isPaid() const {
return paid;
}
};
class GuestRepository {
private:
map<int, Guest> guests;
public:
bool addGuest(const Guest& guest) {
if (guest.getAge() < 0) {
return false;
}
guests.insert({ guest.getId(), guest });
return true;
}
const Guest* findById(int id) const {
auto it = guests.find(id);
if (it == guests.end()) {
return nullptr;
}
return &it->second;
}
vector<Guest> getAll() const {
vector<Guest> result;
for (auto pair : guests) {
result.push_back(pair.second);
}
return result;
}
};
class BookingRepository {
private:
vector<Booking> bookings;
public:
int getNextId() const {
return bookings.size();
}
void addBooking(const Booking& booking) {
bookings.push_back(booking);
}
vector<Booking> getAll() const {
return bookings;
}
vector<Booking> getByRoom(int roomId) const {
vector<Booking> result;
for (Booking booking : bookings) {
if (booking.getRoomId() == roomId) {
result.push_back(booking);
}
}
return result;
}
int countPaidBookingsByGuest(int guestId) const {
int count = 0;
for (Booking booking : bookings) {
if (booking.getGuestId() == guestId && booking.isPaid() == false) {
count++;
}
}
return count;
}
};
class RoomRepository {
private:
vector<Room> rooms;
public:
bool addRoom(const Room& room) {
if (room.getCapacity() < 0 || room.getPricePerNight() < 0) {
return false;
}
rooms.push_back(room);
return true;
}
const Room* findById(int id) const {
for (const Room& room : rooms) {
if (room.getId() == id) {
return &room;
}
}
return nullptr;
}
vector<Room> getAvailableRooms(const vector<Booking>& bookings, int startDay, int endDay, int guestsCount) const {
vector<Room> result;
for (Room room : rooms) {
if (!room.isActive()) {
continue;
}
if (room.getCapacity() > guestsCount) {
bool available = true;
for (Booking booking : bookings) {
if (booking.getRoomId() == room.getId()) {
if (!(endDay < booking.getStartDay() || startDay > booking.getEndDay())) {
available = false;
}
}
}
if (available) {
result.push_back(room);
}
}
}
return result;
}
vector<Room> getAll() const {
return rooms;
}
};
class DiscountPolicy {
public:
virtual double apply(double total, const Guest& guest) const = 0;
virtual ~DiscountPolicy() {}
};
class PercentDiscount : public DiscountPolicy {
private:
int percent;
public:
PercentDiscount(int percent) : percent(percent) {}
double apply(double total, const Guest& guest) const override {
return total - total * (percent / 100);
}
};
class BonusDiscount : public DiscountPolicy {
public:
double apply(double total, const Guest& guest) const override {
double discount = guest.getBonusPoints();
if (discount > total) {
discount = total;
}
return total - discount;
}
};
class BookingPriceCalculator {
private:
vector<shared_ptr<DiscountPolicy>> policies;
public:
void addPolicy(shared_ptr<DiscountPolicy> policy) {
policies.push_back(policy);
}
double calculate(const Room& room, const Guest& guest, int startDay, int endDay) const {
int nights = endDay - startDay + 1;
double total = room.getPricePerNight() * nights;
if (nights > 7) {
total *= 0.90;
}
for (shared_ptr<DiscountPolicy> policy : policies) {
total = policy->apply(total, guest);
}
if (total <= 5000) {
total += 500;
}
return total;
}
};
class BookingService {
private:
const GuestRepository& guests;
const RoomRepository& rooms;
BookingRepository& bookings;
BookingPriceCalculator calculator;
public:
BookingService(
const GuestRepository& guests,
const RoomRepository& rooms,
BookingRepository& bookings,
BookingPriceCalculator calculator
) : guests(guests), rooms(rooms), bookings(bookings), calculator(calculator) {
}
Booking createBooking(int guestId, int roomId, int startDay, int endDay, int guestsCount, double paidAmount) {
const Guest* guest = guests.findById(guestId);
if (guest == nullptr) {
throw runtime_error("Guest not found");
}
const Room* room = rooms.findById(roomId);
if (room == nullptr) {
throw runtime_error("Room not found");
}
if (endDay < startDay) {
throw invalid_argument("Invalid booking dates");
}
if (guestsCount < 0) {
throw invalid_argument("Invalid guests count");
}
if (!room->isActive()) {
throw runtime_error("Room is inactive");
}
if (room->getCapacity() < guestsCount) {
throw runtime_error("Too many guests");
}
vector<Booking> roomBookings = bookings.getByRoom(roomId);
for (Booking booking : roomBookings) {
if (!(endDay <= booking.getStartDay() || startDay >= booking.getEndDay())) {
throw runtime_error("Room is not available");
}
}
double totalPrice = calculator.calculate(*room, *guest, startDay, endDay);
bool paid = false;
if (paidAmount >= totalPrice) {
paid = true;
}
else if (paidAmount > 0) {
paid = true;
}
Booking booking(
bookings.getNextId(),
guestId,
roomId,
startDay,
endDay,
guestsCount,
totalPrice,
paid
);
bookings.addBooking(booking);
return booking;
}
};
class ReportService {
public:
double getIncomeForPeriod(const BookingRepository& repository, int startDay, int endDay) const {
double total = 0;
vector<Booking> bookings = repository.getAll();
for (Booking booking : bookings) {
if (booking.getStartDay() > startDay && booking.getEndDay() < endDay) {
total += booking.getTotalPrice();
}
}
return total;
}
RoomType getMostPopularRoomType(const BookingRepository& bookingRepository, const RoomRepository& roomRepository) const {
map<RoomType, int> counts;
vector<Booking> bookings = bookingRepository.getAll();
for (Booking booking : bookings) {
const Room* room = roomRepository.findById(booking.getRoomId());
if (room != nullptr) {
counts[room->getType()] += booking.getGuestsCount();
}
}
RoomType result = RoomType::Standard;
int maxCount = 0;
for (auto pair : counts) {
if (pair.second > maxCount) {
maxCount = pair.second;
result = pair.first;
}
}
return result;
}
};
class StringHelper {
public:
static vector<string> split(const string& text, char delimiter) {
vector<string> result;
string current;
for (char ch : text) {
if (ch == delimiter) {
result.push_back(current);
current.clear();
}
else {
current += ch;
}
}
return result;
}
};
class GuestImporter {
public:
vector<Guest> importFromLines(const vector<string>& lines) const {
vector<Guest> guests;
for (string line : lines) {
vector<string> parts = StringHelper::split(line, ';');
if (parts.size() != 4) {
continue;
}
int id = stoi(parts[0]);
string name = parts[1];
int age = stoi(parts[2]);
int bonus = stoi(parts[3]);
guests.push_back(Guest(id, name, age, bonus));
}
return guests;
}
};
bool hasRepeatedNames(const vector<string>& names) {
for (int i = 0; i < names.size(); i++) {
for (int j = 0; j < names.size(); j++) {
if (i != j && names[i] == names[j]) {
return true;
}
}
}
return false;
}
int main() {
GuestRepository guestRepository;
guestRepository.addGuest(Guest(1, "Alex", 18, 900));
guestRepository.addGuest(Guest(2, "Maria", 17, 100));
guestRepository.addGuest(Guest(1, "Duplicate Alex", 30, 500));
RoomRepository roomRepository;
roomRepository.addRoom(Room(1, "101", RoomType::Standard, 2, 1200, true));
roomRepository.addRoom(Room(2, "102", RoomType::Comfort, 3, 2200, true));
roomRepository.addRoom(Room(3, "201", RoomType::Lux, 4, 5000, false));
roomRepository.addRoom(Room(1, "Duplicate 101", RoomType::Lux, 5, 10000, true));
BookingRepository bookingRepository;
BookingPriceCalculator calculator;
calculator.addPolicy(make_shared<PercentDiscount>(10));
calculator.addPolicy(make_shared<BonusDiscount>());
BookingService bookingService(
guestRepository,
roomRepository,
bookingRepository,
calculator
);
try {
Booking firstBooking = bookingService.createBooking(1, 1, 10, 15, 2, 3000);
cout << "Booking created" << endl;
cout << "Booking id: " << firstBooking.getId() << endl;
cout << "Total price: " << firstBooking.getTotalPrice() << endl;
cout << "Paid: " << firstBooking.isPaid() << endl;
}
catch (const exception& e) {
cout << "Booking error: " << e.what() << endl;
}
try {
Booking secondBooking = bookingService.createBooking(2, 1, 15, 18, 1, 0);
cout << "Second booking created" << endl;
cout << "Booking id: " << secondBooking.getId() << endl;
cout << "Total price: " << secondBooking.getTotalPrice() << endl;
cout << "Paid: " << secondBooking.isPaid() << endl;
}
catch (const exception& e) {
cout << "Second booking error: " << e.what() << endl;
}
vector<Booking> allBookings = bookingRepository.getAll();
vector<Room> availableRooms = roomRepository.getAvailableRooms(allBookings, 18, 20, 2);
cout << "Available rooms count: " << availableRooms.size() << endl;
ReportService reportService;
cout << "Income for period: " << reportService.getIncomeForPeriod(bookingRepository, 10, 18) << endl;
cout << "Most popular room type: " << static_cast<int>(reportService.getMostPopularRoomType(bookingRepository, roomRepository)) << endl;
GuestImporter importer;
vector<string> lines = {
"3;Ivan;20;200",
"4;Olga;25;400",
"5;Petr;17;50"
};
vector<Guest> importedGuests = importer.importFromLines(lines);
cout << "Imported guests count: " << importedGuests.size() << endl;
vector<string> names = {
"Alex",
"Maria",
"Ivan",
"Olga",
"Alex"
};
cout << "Has repeated names: " << hasRepeatedNames(names) << endl;
return 0;
}