
- •Coursework thesis
- •Task for coursework
- •Abstract
- •List of abbreviations
- •Introduction
- •Domain analysis
- •Designing the system
- •Interface classes iSerializible, iEmissionable and iCloneable
- •Class for transport information
- •Bus, Plane, Train classes
- •Data storing. Transport schedule class
- •Array of pointers. Container class.
- •User Interface Design
- •Software implementation
- •Clock and Time classes.
- •Coordinates structure implementation
- •StationInfo structure implementation
- •IEmissionable, iSerializable and iCloneable implementation
- •TransportInfo class implementation
- •Bus, Plane, Train class implementation
- •TransportSchedule class implementation
- •Conclusions
- •References
- •Appendix a File Time.H
- •File Time.Cpp
- •File Clocks.H
- •File Clocks.Cpp
- •File iSerializable.H
- •File iEmissionable.H
- •File iCloneable.H
- •File stdafx.H
- •File stdafx.Cpp
- •CoordinatesData.Json
- •File transports.Csv
- •File Coordinates.Cpp
- •File main.Cpp
- •File Route.Cpp
- •File Route.H
- •File StationInfo. Cpp
- •File StationInfo.H
- •File TransportSchedule.H
- •File TransportSchedule.Cpp
- •File PtrArray.Cpp
- •File TransportInfo.Cpp
- •File TransportInfo.H
- •File Bus.H
- •File Bus.Cpp
- •File Plane.H
- •File Plane.Cpp
- •File Train.H
- •File Train.Cpp
- •Appendix b
File TransportSchedule.Cpp
#include "TransportSchedule.h"
TransportTypes TransportSchedule::selectMeansOfTransport(bool allIsAllowed) const
{
auto stopAt = E_AllTrans + (int)allIsAllowed;
std::cout << "Select means of transport:\n";
size_t i = 1;
for (; i < E_AllTrans; ++i)
std::cout << i << ") " << StaticData::vehiclesStringTypes.at((TransportTypes)i) << '\n';
if (stopAt == E_AllTrans + 1) std::cout << i++ << ") All\n";
std::cout << "Input: ";
int input;
validateInput(input, std::cin, [&stopAt](int val)
{ return val >= 0 && val < stopAt; });
if (input == 0)
return TransportTypes::None;
return (TransportTypes)input;
}
TransportInfo* TransportSchedule::createTransport(std::string_view type) const
{
if (type == "Bus")
return new Bus();
else if (type == "Plane")
return new Plane();
else if (type == "Train")
return new Train();
throw std::runtime_error("Transport \'" + std::string(type) + "\' has not been found\n");
}
void TransportSchedule::addTransportUI()
{
std::cout << "~~~~~~~~~~~~~~~~~~~~~~\n"
"Adding transport\n"
"Type \'0\' to exit\n"
"----------------------\n";
auto transportType = selectMeansOfTransport(false);
if (transportType == None)
return;
auto temp_transport = createTransport(StaticData::vehiclesStringTypes.at(transportType));
validateInput(*temp_transport, std::cin);
this->allTransports.emplace_back(temp_transport);
}
void TransportSchedule::removeTransportUI()
{
if (this->allTransports.empty())
{
std::cout << "\nCannot remove any transport because there aren't any\n";
return;
}
std::cout << "Removing transport\n";
int ID;
std::string choice;
while (true)
{
std::cout <<
"~~~~~~~~~~~~~~~~~~~~~~\n"
"Enter ID of the transport you want to remove.\n"
"Type \'0\' to exit\n"
"----------------------\n"
"Input: ";
validateInput(ID, std::cin);
if (ID == 0)
return;
auto chosenTransport = std::find_if(allTransports.begin(), allTransports.end(), [&ID](TransportInfo const* obj)
{ return obj->getID() == ID; });
if (chosenTransport != allTransports.end())
{
system("cls");
std::cout << **chosenTransport <<
"\nYou want to delete this transport?(yes/no): ";
validateInput(choice, std::cin);
if (choice == "yes" || choice == "y" || choice == "Yes" || choice == "YES")
{
std::cout << "The transport with ID " << ID << " was removed\n";
this->allTransports.erase(chosenTransport);
break;
}
}
else
std::cout << "There is no transport with that ID\n";
}
return;
}
std::vector<Route> TransportSchedule::findRouteCore(std::string_view from, std::string_view to, TransportTypes transportType) const
{
std::vector<Route> validTransports;
for (size_t i = 0; i < allTransports.size(); ++i)
{
const TransportInfo* transport1 = allTransports.at(i);
if (transportType != TransportTypes::E_AllTrans && transport1->getType() != transportType)
continue;
if (transport1->getDeparture().name != from)
continue;
if (transport1->getDestination().name == to)
{
validTransports.emplace_back(Route({ transport1 }));
continue;
}
for (size_t j = i + 1; j < allTransports.size(); ++j)
{
const auto& transport2 = allTransports.at(j);
if (transportType != TransportTypes::E_AllTrans && transport2->getType() != transportType)
continue;
if (transport1->getDestination().name != transport2->getDeparture().name)
continue;
if (transport2->getDestination().name == to)
{
validTransports.emplace_back(Route({ transport1, transport2 }));
continue;
}
for (size_t k = j + 1; k < allTransports.size(); k++)
{
const auto& transport3 = allTransports.at(k);
if (transportType != TransportTypes::E_AllTrans && transport3->getType() != transportType)
continue;
if (transport2->getDestination().name != transport3->getDeparture().name)
continue;
if (transport3->getDestination().name == to &&
transport1->getDeparture().name != transport3->getDeparture().name)
{
validTransports.emplace_back(Route({ transport1, transport2, transport3 }));
break;
}
}
}
}
std::ranges::sort(validTransports, [](Route const& left, Route const& right)
{
return left.totalTime < right.totalTime;
});
return validTransports;
}
void TransportSchedule::findRouteUI() const
{
std::cout << "Enter your initial location: ";
std::string from;
clearBuffer(std::cin);
std::getline(std::cin, from);
std::cout << "Enter where you're going to: ";
std::string to;
std::getline(std::cin, to);
auto transportType = selectMeansOfTransport(true);
if (transportType == None)
return;
std::vector<Route> routes = this->findRouteCore(from, to, transportType);
if (!routes.empty())
{
std::cout << "You've got such options to get to " << to << " from " << from << ":\n";
for (int count = 0; auto const& it : routes)
std::cout << "------ROUTE #" << ++count << "------\n" << it << std::endl;
}
else
std::cout << "No routes were found for this direction, we're sincerely sorry\n";
system("pause");
}
bool TransportSchedule::adminCheckPassword() const
{
std::cout << "To get access to admin settings to must enter the password.\n"
"Input: ";
std::string password;
int attempts = 3;
for (size_t i = 0; i < attempts; i++)
{
validateInput(password, std::cin);
clearBuffer(std::cin);
if (password != "qwerty123")
std::cout << "You have " << attempts - i - 1 << " attempts left.\n";
else
return true;
}
return false;
}
void TransportSchedule::adminMenuUI()
{
if (!this->adminCheckPassword())
{
std::cout << "The password is incorrect.";
system("pause");
return;
}
system("cls");
int input;
bool exit = false;
while (!exit)
{
std::cout <<
"Admin settings\n"
"~~~~~~~~~~~~~~~~~~\n"
"1) Add transport\n"
"2) Remove transport\n"
"3) Sort data\n"
"4) Load data\n"
"5) Save\n"
"6) Exit without saving\n"
"Input: ";
validateInput(input, std::cin, [](int val) {return val >= 1 && val <= 7; });
system("cls");
switch (input)
{
case 1:
this->addTransportUI();
break;
case 2:
this->removeTransportUI();
break;
case 3:
this->sortUI();
break;
case 4:
this->loadDataUI();
break;
case 5:
this->saveDataUI();
break;
case 6:
exit = true;
break;
}
system("pause");
system("cls");
}
}
void TransportSchedule::print() const
{
for (auto& it : this->allTransports)
std::cout << *it << "\n-------------------------------\n";
system("pause");
}
void TransportSchedule::loadDataUI()
{
system("cls");
std::cout <<
"~~~~~~~~~~~~~~~~~~~~~~~~\n"
"Loading data\n"
"Write the file name\n"
"Type \'0\' to exit\n"
"------------------------\n"
"Input: ";
std::string temp;
validateInput(temp, std::cin);
if (temp == "0")
return;
this->allTransports.clear();
this->loadDataCore();
}
void TransportSchedule::loadDataCore()
{
std::ifstream ifs;
try
{
ifs.open(this->_fileName);
if (!ifs.is_open())
throw std::runtime_error("Can't open file" + this->_fileName);
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::string line, type;
//Skip first line
std::getline(ifs, line);
while (std::getline(ifs, line))
{
std::stringstream ss(line);
std::getline(ss, type, ',');
TransportInfo* temp = createTransport(type);
temp->deserialize(ss);
this->allTransports.emplace_back(temp);
}
}
catch (std::ifstream::failure const& ex)
{
if (!ifs.eof())
{
std::cerr << "Exception opening/reading/closing file\n";
std::cerr << ex.what() << '\n';
std::cerr << "Error code: " << ex.code() << '\n';
}
else
std::cout << "The data was successfully loaded\n";
}
catch (std::exception const& ex)
{
std::cerr << "Exception: " << ex.what() << std::endl;
}
ifs.close();
}
void TransportSchedule::sortUI() const
{
system("cls");
std::cout <<
"~~~~~~~~~~~~~~~~~~~~~~~~\n"
"Sorting data\n"
"Select by which parameter sort the list\n"
"Type \'0\' to exit\n"
"------------------------\n"
"1) ID\n" <<
"2) Departure\n" <<
"3) Destination\n" <<
"4) Departure time\n" <<
"5) Destination time\n" <<
"6) Fee\n" <<
"7) Means of transport\n" <<
"Input: ";
int choice;
validateInput(choice, std::cin, [](char ch) {return ch >= 0 || ch <= 7; });
switch (choice)
{
case 0:
return;
case 1:
this->sortBy([](TransportInfo const* obj) {return obj->getID(); });
break;
case 2:
this->sortBy([](TransportInfo const* obj) {return obj->getDeparture().name; });
break;
case 3:
this->sortBy([](TransportInfo const* obj) {return obj->getDestination().name; });
break;
case 4:
this->sortBy([](TransportInfo const* obj) {return obj->getDeparture().time; });
break;
case 5:
this->sortBy([](TransportInfo const* obj) {return obj->getDestination().time; });
break;
case 6:
this->sortBy([](TransportInfo const* obj) {return obj->getFee(); });
break;
case 7:
this->sortBy([](TransportInfo const* obj) {return obj->getTypeString(); });
break;
}
std::cout << "The list was successfully sorted\n";
}
template<typename Function>
void TransportSchedule::sortBy(Function foo) const
{
std::sort(allTransports.begin(), allTransports.end(),
[&foo](TransportInfo*& left, TransportInfo*& right)
{ return foo(left) < foo(right); });
}
void TransportSchedule::saveDataUI()
{
std::cout <<
"~~~~~~~~~~~~~~~~~~~~~~\n"
"Saving data\n"
"Write the file to save data to\n"
"Type \'0\' to exit\n"
"----------------------\n"
"Input: ";
std::string input;
validateInput(input, std::cin);
if (input == "0")
return;
this->_fileName = input;
this->saveDataCore();
}
void TransportSchedule::saveDataCore() const
{
try
{
std::ofstream ofs(this->_fileName);
ofs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
ofs << "TypeOfTransport,ID,Departure,Time,Platform,Destination,Time,Platform,Fee,AdditionalInformation\n";
for (const auto& it : this->allTransports)
it->serialize(ofs);
std::cout << "The data was successfully saved\n";
ofs.close();
}
catch (std::ofstream::failure& ex)
{
std::cerr << ex.what() << '\n' << ex.code() << '\n';
}
}
TransportSchedule::TransportSchedule(const char* fileName)
: _fileName(fileName)
{
this->loadDataCore();
}
void TransportSchedule::menu()
{
int input;
bool exit = false;
while (!exit)
{
system("cls");
std::cout << "Hello to the ISOR app.\n"
"~~~~~~~~~~~~~~~~~~~~~~~~~\n"
"1) Find route\n"
"2) See all transports\n"
"3) Admin settings\n"
"4) Exit\n"
"Input: ";
validateInput(input, std::cin, [](int val) {return val >= 1 && val <= 4; });
system("cls");
switch (input)
{
case 1:
this->findRouteUI();
break;
case 2:
this->print();
break;
case 3:
this->adminMenuUI();
break;
case 4:
exit = true;
break;
default:
continue;
}
}
}