3
\$\begingroup\$

Theme of my course work in institute is simulation of bus route. Could you determine any faults and defects in this code? I will be very grateful if you give me some advice about one global variable, counters or etc. It's a console version. I have one month to do GUI with help of Qt or Visual C++. I don't use either them until yesterday. I am trying to use Qt now. I think it must be ordinary graph with points as bus stops and lines as roads.

What do you select in my shoes? I work in VS 2012 usually. I have pretty much time if I need to remake all code below.

Autobus.h

#pragma once

#include "Passenger.h"
#include "NecessaryHeaders.h"

using namespace std;

class Autobus{
private:
    string brand_;
    int capacity_; 
    int max_speed_; 
    int bus_numberplate_; 
    bool is_door_open_; 
    int x_bus_; 
    int y_bus_;  
    int current_speed_;

    static int counter_bus_; 
    static string const mas_brand_buses [];
    static int const mas_cap_buses [];
    static int const mas_max_speed_buses [];

 public:
    Autobus(string brand, int const capacity, int max_speed)
        :brand_(brand), capacity_(capacity), max_speed_(max_speed), is_door_open_(false), bus_numberplate_(counter_bus_ + 1), x_bus_(0), y_bus_(0), current_speed_(max_speed){
            counter_bus_++;
    }

    Autobus(Autobus const &bus)
        :brand_(bus.brand_), capacity_(bus.capacity_), max_speed_(bus.max_speed_), is_door_open_(false), bus_numberplate_(bus.bus_numberplate_), x_bus_(0), y_bus_(0), current_speed_(bus.current_speed_), salon(bus.salon){

    }

    ~Autobus(){
    }

    vector <Passenger> salon;

    size_t get_capacity() const;
    string get_brand() const;
    int get_max_speed() const;
    int get_bus_numberplate() const;
    bool get_door() const;
    int const get_x_bus() const;
    int const get_y_bus() const;
    int get_current_speed() const;

    int set_x_bus(int temp_x);
    int set_y_bus(int temp_y);
    void open_door();
    void shut_door();
    int set_current_speed(int new_speed);

    static int get_count_bus();
    static void generate_buses(deque <Autobus> &buses);

    friend ostream & operator << (std::ostream & os, Autobus & bus);
};

Autobus.cpp

#include "Autobus.h"
#include "NecessaryHeaders.h"

using namespace std;

extern ofstream otchet;

string const Autobus::mas_brand_buses [] = {"Paz", "Gazel", "Liaz"};
int const Autobus::mas_cap_buses [] = { 40, 20, 100 };
int const Autobus::mas_max_speed_buses [] = { 90, 110, 70};

int Autobus::counter_bus_ = 0;

int Autobus::get_count_bus(){
    return counter_bus_;
}


size_t Autobus::get_capacity() const{
    return capacity_;
}

string Autobus::get_brand() const{
    return brand_;
}

int Autobus::get_max_speed() const{
    return max_speed_;
}

int Autobus::get_bus_numberplate() const{
    return bus_numberplate_;
}

bool Autobus::get_door() const{
    return is_door_open_;
}

int const Autobus::get_x_bus() const{
    return x_bus_;
}

int const Autobus::get_y_bus() const{
    return y_bus_;
}

int Autobus::get_current_speed() const{
    return current_speed_;
}


int Autobus::set_x_bus(int temp_x){
    x_bus_ = temp_x;
    return x_bus_;
}

int Autobus::set_y_bus(int temp_y){
    y_bus_ = temp_y;
    return y_bus_;
}

void Autobus::open_door(){
    is_door_open_ = true;
}

void Autobus::shut_door(){
    is_door_open_ = false;
}

int Autobus::set_current_speed(int new_speed){
    current_speed_ = new_speed;
    return current_speed_;
}

ostream & operator << (std::ostream & os, Autobus & bus){
    otchet << "Bus #" << bus.get_bus_numberplate() << " brand " \
            << bus.get_brand() << " with capacity " << bus.get_capacity() << endl;
    /*otchet << "Coordinate x: " << bus.get_x_bus() << endl;
    otchet << "Coordinate y: " << bus.get_y_bus() << endl;*/
    otchet << "Number of passengers: " << bus.salon.size() << endl;
    otchet << "Full names of passengers:\n";

    cout << "Bus #" << bus.get_bus_numberplate() << " brand " \
            << bus.get_brand() << " with capacity " << bus.get_capacity() << endl;
    /*cout << "Coordinate x: " << bus.get_x_bus() << endl;
    cout << "Coordinate y: " << bus.get_y_bus() << endl;*/
    cout << "Number of passengers: " << bus.salon.size() << endl;
    cout << "Full names of passengers:\n";
    for(size_t i = 0; i < bus.salon.size(); ++i){
        otchet << bus.salon[i] << endl;
        cout << bus.salon[i] << endl;
    }
    return os;
}

void Autobus::generate_buses(deque <Autobus> &buses){
    for(int i = 0; i < 3; ++i){
        int temp_rand = 0;
        temp_rand = rand() % 5 + 1;
        for(int j = 0; j < temp_rand; ++j){
            buses.push_back( Autobus(mas_brand_buses[i], mas_cap_buses[i], mas_max_speed_buses[i]) );
        }
    }

    for(size_t i = 0; i < buses.size(); ++i){
        cout << buses[i];
    }
}

BusStop.h

#pragma once
#include "Passenger.h"
#include "Autobus.h"
#include "NecessaryHeaders.h"

using namespace std;

class BusStop{
private:
    string name_bus_stop_;
    int x_bus_stop_;
    int y_bus_stop_;
    int bus_stop_numberplate_;

    static int counter_bus_stop_;
    static string mas_names_bus_stops [];

    deque <Passenger> platform;

public:
    BusStop(string name_bus_stop, int x_bus_stop, int y_bus_stop)
        :name_bus_stop_(name_bus_stop), x_bus_stop_(x_bus_stop), y_bus_stop_(y_bus_stop), bus_stop_numberplate_(counter_bus_stop_ + 1){
            counter_bus_stop_++;
    }

    BusStop(BusStop const &bus_stop)
        :name_bus_stop_(bus_stop.name_bus_stop_), x_bus_stop_(bus_stop.x_bus_stop_), y_bus_stop_(bus_stop.y_bus_stop_), bus_stop_numberplate_(bus_stop.bus_stop_numberplate_){
            parking = bus_stop.parking;
            platform = bus_stop.platform;
    }

    ~BusStop(){
    }

    deque <Autobus> parking; 

    int get_x_bus_stop() const;
    int get_y_bus_stop() const;
    string get_name_bus_stop() const;
    int get_bus_stop_numberplate() const;
    Passenger get_first_passenger() const;
    int get_count_passengers_on_platform() const;
    bool is_platform_empty() const;

    void enter_passenger_on_platform(Passenger temp_pas);
    void go_out_first_passenger();
    void evacuation();

    static void generate_bus_stops(vector <BusStop> &bus_stops);
    static int get_count_bus_stop();

    friend ostream & operator << (std::ostream & os, BusStop & bus_stop);
    BusStop & operator = (BusStop const & temp_bus_stop);

};

BusStop.cpp

#include "BusStop.h"
#include "NecessaryHeaders.h"

using namespace std;

extern ofstream otchet;


string BusStop::mas_names_bus_stops [] = {"Kindergarten", "School", "University", "Factory", \
"Market", "Bank", "Restaurant", "Pharmacy", "Cinema", "Administration"};


int BusStop::counter_bus_stop_ = 0;

int BusStop::get_count_bus_stop(){
    return counter_bus_stop_;
}

string BusStop::get_name_bus_stop() const{
    return name_bus_stop_;
}

int BusStop::get_bus_stop_numberplate() const{
    return bus_stop_numberplate_;
}

int BusStop::get_x_bus_stop() const{
    return x_bus_stop_;
}

int BusStop::get_y_bus_stop() const{
    return y_bus_stop_;
}

bool BusStop::is_platform_empty() const{
    return platform.empty(); 
}

Passenger BusStop::get_first_passenger() const{
    return platform.front();
}

int BusStop::get_count_passengers_on_platform() const{
    return platform.size();
}

ostream & operator << (std::ostream & os, BusStop & bus_stop){
    otchet << "Bus stop #" << bus_stop.bus_stop_numberplate_ << endl;
    otchet << "Name: " << bus_stop.get_name_bus_stop() << endl;
    otchet << "Coordinate x: " << bus_stop.get_x_bus_stop() << endl;
    otchet << "Coordinate y: " << bus_stop.get_y_bus_stop() << endl;
    otchet << "\nNumber people on platform: " << bus_stop.platform.size() << endl;
    otchet << "Full names of people:\n";

    cout << "Bus stop #" << bus_stop.bus_stop_numberplate_ << endl;
    cout << "Name: " << bus_stop.get_name_bus_stop() << endl;
    cout << "Coordinate x: " << bus_stop.get_x_bus_stop() << endl;
    cout << "Coordinate y: " << bus_stop.get_y_bus_stop() << endl;
    cout << "\nNumber people on platform: " << bus_stop.platform.size() << endl;
    cout << "Full names of people:\n";
    size_t i = 0;
    for(i = 0; i < bus_stop.platform.size(); ++i){
        otchet << bus_stop.platform[i] << endl;
        cout << bus_stop.platform[i] << endl;
    }

    otchet << "Number buses on parking: " << bus_stop.parking.size() << endl;
    cout << "Number buses on parking: " << bus_stop.parking.size() << endl;

    if( !bus_stop.parking.empty() ){
        otchet << "Full information about buses:\n";
        cout << "Full information about buses:\n";
    }

    for(i = 0; i < bus_stop.parking.size(); ++i){
        otchet << "Bus #" << bus_stop.parking[i].get_bus_numberplate() << " brand " \
            << bus_stop.parking[i].get_brand() << " with capacity " << bus_stop.parking[i].get_capacity() \
            << " and " << bus_stop.parking[i].salon.size() << " passengers.\n";

        cout << "Bus #" << bus_stop.parking[i].get_bus_numberplate() << " brand " \
            << bus_stop.parking[i].get_brand() << " with capacity " << bus_stop.parking[i].get_capacity() \
            << " and " << bus_stop.parking[i].salon.size() << " passengers.\n";

        otchet << "Full names of passengers:\n";
        cout << "Full names of passengers:\n";
        for(size_t j = 0; j < bus_stop.parking[i].salon.size(); ++j){
            otchet << bus_stop.parking[i].salon[j] << endl;
            cout << bus_stop.parking[i].salon[j] << endl;
        }
    }
    return os;
}

BusStop & BusStop::operator = (BusStop const & temp_bus_stop){
    if ( this != &temp_bus_stop){
        name_bus_stop_ = temp_bus_stop.name_bus_stop_;
        x_bus_stop_ = temp_bus_stop.x_bus_stop_ ;
        y_bus_stop_ = temp_bus_stop.y_bus_stop_;
        bus_stop_numberplate_ = temp_bus_stop.bus_stop_numberplate_;
        parking = temp_bus_stop.parking;
        platform = temp_bus_stop.platform;  
    }
    return *this;
}

void BusStop::generate_bus_stops(vector <BusStop> &bus_stops){
    int n = 10;
    string temp_str = " ";
    int temp_x = 0;
    int temp_y = 0;

    int temp_n = rand() % 7 + 3;
    for(int i = 0; i < temp_n; ++i){
        temp_x += 100 * ( rand() % 5 + 5);
        temp_y += 100 * ( rand() % 5 + 5);
        int temp_index = rand() % n--;
        bus_stops.push_back( BusStop(mas_names_bus_stops[temp_index], temp_x, temp_y) );

        temp_str = mas_names_bus_stops[n];
        mas_names_bus_stops[n] = mas_names_bus_stops[temp_index];
        mas_names_bus_stops[temp_index] = temp_str; 
    }

    otchet << "\nNumber of bus stops: " << bus_stops.size() << endl << endl;
    cout << "\nNumber of bus stops: " << bus_stops.size() << endl << endl;
    for(size_t i = 0; i < bus_stops.size(); ++i){
        cout << bus_stops[i];
    }
}

void BusStop::enter_passenger_on_platform(Passenger temp_pas){
    platform.push_back(temp_pas);
}


void BusStop::go_out_first_passenger(){
    platform.pop_front();
}

void BusStop::evacuation(){
    platform.clear();
}

Passenger.h

#pragma once
#include "NecessaryHeaders.h"

using namespace std;

class Passenger{
private:
    bool is_girl_;
    string name_;
    string surname_;

    static int counter_pas_;
    static const string female_names [];
    static const string male_names [];

    static const string female_surnames [];
    static const string male_surnames [];

public:
    Passenger(bool is_girl, string name, string surname)
    :is_girl_(is_girl), name_(name), surname_(surname){
        counter_pas_++;
    }
    Passenger(Passenger const &pas)
        :is_girl_(pas.is_girl_), name_(pas.name_), surname_(pas.surname_){
    }

    ~Passenger(){
    }

    string get_name() const;
    string get_surname() const;
    bool get_gender() const;

    static int const get_count_pas();
    static void generate_passenger(bool &temp_is_girl, string &temp_name, string &temp_surname);

    friend ostream & operator << (std::ostream & os, Passenger & temp_pas);
};

Passenger.cpp

#include "Passenger.h"
#include "NecessaryHeaders.h"

using namespace std;

const string Passenger::female_names [] = {"Anya", "Alla", "Alsu", "Bella", "Camilla", "Carolina", "Clavdia", "Dasha", "Diana", "Dina", "Ella", "Elena", "Faina", "Galya", \
    "Ira", "Julya", "Katya", "Kira", "Klara", "Ksenia", "Larisa", "Lera", "Liza", "Lubov", "Ludmila", "Marfa", "Marina", "Masha", "Nadya", "Nastya", "Nelli", "Nonna", \
    "Olya", "Polina", "Raisa", "Regina", "Rita", "Snezhana", "Sofia", "Sonya", "Tamara", "Tanya", "Vera", "Yana", "Valya", "Varvara", "Veronika", "Vika", "Zhanna", "Zoya"};

const string Passenger::male_names [] = {"Adolf", "Alexei", "Albert", "Andrej", "Anton", "Arkadij", "Arsenij", "Artyom", "Artur", "Avgust", "Bogdan", "Borya", "Danila", "Denis", \
    "Dima", "Efim", "Egor", "Gena", "Gleb", "Igor", "Ilya", "Kirill", "Kolya", "Kostya", "Kuzma", "Leonid", "Lev", "Matvej", "Maxim", "Misha", "Nikita", "Oleg", "Pavel", "Petr", \
    "Rodion", "Roman", "Ruslan", "Sasha", "Semen", "Seva", "Slava", "Timoha", "Timur", "Tolya", "Vadim", "Valera", "Vasya", "Vitya", "Yura", "Zhenya"};

const string Passenger::male_surnames [] = {"Alexandrov", "Alexeev", "Andreev", "Barsukov", "Bezrukov", "Bogdanov", "Chebotarev", "Dmitriev", "Dobrynin", "Egorov", "Elizarov", \
    "Ermolov", "Gladkov", "Glushkov", "Fedorov", "Fedosov", "Gribov", "Grigoriev", "Ivanov", "Kalachev", "Korolkov", "Kukushkin", "Kuznetsov", "Lebedev", "Mihailov", "Morgunov", \
    "Moskvin", "Muratov", "Nikitin", "Nikolaev", "Pavlov",  "Petrov", "Polikarpov", "Popov", "Rakov", "Ryabinin", "Semenov", "Smirnov", "Snegirev", "Sokolov",  "Soloviev", "Somov", \
    "Stepanov", "Sudakov", "Uvarov", "Vasiliev", "Volkov", "Yakovlev", "Zlobin", "Zvagintsev"};

const string Passenger::female_surnames [] = {"Agapova", "Alexandrova", "Anisimova",  "Antonova", "Babushkina", "Blinova", "Blohina", "Bolshakova", "Chernyaeva", "Davydova", "Denisova", \
    "Dorohova", "Efimova", "Ermilova", "Filippova", "Fomina", "Gorlova", "Grekova", "Gromova", "Gurova", "Gusheva", "Kalinina", "Kalugina", "Kazakova", "Kazantseva", "Kochergina", \
    "Kolesnikova", "Konovalova", "Korneeva", "Korshunova", "Lykova", "Markelova", "Markova", "Melnikova", "Mironova", "Nikiforova", "Paramonova", "Petuhova", "Postnikova", "Sherbakova", \
    "Shestakova", "Shiryaeva", "Shvetsova", "Suhanova", "Surkova", "Sveshnikova", "Timofeeva", "Usova", "Vdovina", "Veselova"};

int Passenger::counter_pas_ = 0;

int const Passenger::get_count_pas(){
    return counter_pas_;
}

string Passenger::get_name() const{
    return name_;
}

string Passenger::get_surname() const{
    return surname_;
}

bool Passenger::get_gender() const{
    return is_girl_;
}

void Passenger::generate_passenger(bool &temp_is_girl, string &temp_name, string &temp_surname){
    temp_is_girl = bool(rand() % 2);

    int i_name = rand() % 50;
    int j_surname = rand() % 50;

    if (temp_is_girl){
        temp_name = female_names[i_name];
        temp_surname = female_surnames[j_surname];
    }
    else{
        temp_name = male_names[i_name];
        temp_surname = male_surnames[j_surname];
    }

}

ostream & operator << (std::ostream & os, Passenger & temp_pas){
    os << temp_pas.get_name() << ' ' << temp_pas.get_surname();
    return os;
}

RandomEvents.h

#pragma once
#include "NecessaryHeaders.h"
#include "Autobus.h"
#include "BusStop.h"

using namespace std;

class Autobus;
class BusStop;

enum { PEAK_HOUR = 0, CALM = 1, TRAFFIC = 2, BREAKING = 3, FIRE = 4 };

int generate_random_event(vector <BusStop> & bus_stops, int &temp_target_bus_stop);

void arrival_of_passengers(vector <BusStop> & bus_stops, int situation, int extra_passenger_flow = 10); // #0 or #1 random event 

void traffic(Autobus &temp_bus);//#2 random event 
void breaking_bus(deque <Autobus> &temp_buses, BusStop &temp_bus_stop);//#3 random event 
void fire_on_bus_stop(vector <BusStop> &temp_bus_stops, int temp_index);//#4 random event 

RandomEvents.cpp

#include "NecessaryHeaders.h"
#include "RandomEvents.h"

using namespace std;
extern ofstream otchet;

int generate_random_event(vector <BusStop> & bus_stops, int &temp_target_bus_stop){
    static int counter_fire = 0;

    int divider = 5;
    if( counter_fire ){
        divider = 4;
    }
    int temp_event = rand() % divider;
    if(temp_event == FIRE){
        ++counter_fire;
    }

    if(temp_event != 0 && temp_event != 1){
        temp_target_bus_stop = rand() % bus_stops.size();
        cout << "Target bus stop:\n" << bus_stops[temp_target_bus_stop] << endl;
    }
    return temp_event;
}

void arrival_of_passengers(vector <BusStop> & bus_stops, int situation, int extra_passenger_flow){

    switch(situation){
    case PEAK_HOUR:{
        extra_passenger_flow = 15;
        break;
                   }
    case CALM:{
        extra_passenger_flow = 5;
        break;
              }
    }

    for(size_t k = 0; k < bus_stops.size() - 1; ++k){
        size_t num_pas_on_stop = rand() % 10 + extra_passenger_flow;//10 is default for extra_passenger_flow
        for (size_t i = 0; i < num_pas_on_stop; ++i){
            bool temp_is_girl = false;
            string temp_name = " ";
            string temp_surname  = " ";
            Passenger::generate_passenger(temp_is_girl, temp_name , temp_surname);
            bus_stops[k].enter_passenger_on_platform( Passenger(temp_is_girl, temp_name , temp_surname) );
        }
        cout << num_pas_on_stop  << " passengers arrived in bus stop #" \
            << bus_stops[k].get_bus_stop_numberplate() << " with name " << bus_stops[k].get_name_bus_stop() << ".\n";
        otchet << num_pas_on_stop  << " passengers arrived in bus stop #" \
            << bus_stops[k].get_bus_stop_numberplate() << " with name " << bus_stops[k].get_name_bus_stop() << ".\n";
        cout << bus_stops[k];
    }
    cout << "Last station:\n" << bus_stops [bus_stops.size() - 1];
}

void traffic(Autobus &temp_bus){

    temp_bus.set_current_speed( temp_bus.get_max_speed() / 2 );
}

void breaking_bus(deque <Autobus> &temp_buses, BusStop &temp_bus_stop){
    while( !temp_buses[0].salon.empty() ){
        Passenger temp_pas = temp_buses[0].salon.back();
        temp_buses[0].salon.pop_back();
        temp_bus_stop.enter_passenger_on_platform(temp_pas);
    }

    temp_buses.pop_front();
}

void fire_on_bus_stop(vector <BusStop> &temp_bus_stops, int temp_index){

    temp_bus_stops[temp_index].evacuation();

    vector <BusStop>::iterator it;
    temp_bus_stops.erase( temp_bus_stops.begin() + temp_index );

    cout << "Bus stop is closed for repair.\n";
    otchet << "Bus stop is closed for repair.\n";

    if( temp_index == temp_bus_stops.size() ){
        cout << "Last bus stop now:\n" << temp_bus_stops[temp_bus_stops.size() - 1] << endl;
        temp_bus_stops[temp_bus_stops.size() - 1].evacuation();
        cout << "All people left new last station.\n" << temp_bus_stops[temp_bus_stops.size() - 1] << endl;
    }
}

SimulationFunctions.h

#pragma once
#include "NecessaryHeaders.h"
#include "BusStop.h"

using namespace std;

class Autobus;

void bus_on_route(BusStop & temp_bus_stop, Autobus & temp_bus, int temp_i, int temp_bus_stop_size);
void bus_on_station(deque <Autobus> &buses, BusStop &temp_bus_stop, bool &temp_last_station);

void arrival_of_bus(BusStop & temp_bus_stop, Autobus & temp_bus, bool last_station);
void leaving_of_bus(BusStop & temp_bus_stop, Autobus & temp_bus);
int exit_of_passengers_from_bus(BusStop & temp_bus_stop, Autobus & temp_bus, bool last_station);
int entrance_of_passengers_on_bus(BusStop & temp_bus_stop, Autobus & temp_bus);

double calculate_distance(int dx1, int dx2, int dy1, int dy2, int temp_i, int temp_bus_stop_size);
double calculate_time(double temp_dist, int temp_speed);
int convert_speed(int temp_speed);

SimulationFunctions.cpp

#include "NecessaryHeaders.h"
#include "SimulationFunctions.h"

class Autobus;
class BusStop;

using namespace std;
extern ofstream otchet;

void bus_on_route(BusStop & temp_bus_stop, Autobus & temp_bus, int temp_i, int temp_bus_stop_size){
    double temp_dist = calculate_distance(temp_bus_stop.get_x_bus_stop(), temp_bus.get_x_bus(), \
    temp_bus_stop.get_y_bus_stop(), temp_bus.get_y_bus(), temp_i, temp_bus_stop_size );
    cout << "Speed (km/h): " << temp_bus.get_current_speed() << endl;
    otchet << "Speed (km/h): " << temp_bus.get_current_speed() << endl;
    double temp_time = calculate_time( temp_dist, convert_speed( temp_bus.get_current_speed() ) );
    cout << "Bus on the way to next station...\n\n";
    otchet << "Bus on the way to next station...\n\n";
}

void bus_on_station(deque <Autobus> &buses, BusStop &temp_bus_stop, bool &temp_last_station){
    arrival_of_bus(temp_bus_stop, buses[0], temp_last_station);
    if( temp_last_station ){
        exit_of_passengers_from_bus(temp_bus_stop, buses[0], temp_last_station);
        leaving_of_bus(temp_bus_stop, buses[0]);
        cout << "\nBus #" << buses[0].get_bus_numberplate() << " brand " \
            << buses[0].get_brand() << " with capacity " << buses[0].get_capacity() << " finished his route!\n";
        otchet << "\nBus #" << buses[0].get_bus_numberplate() << " brand " \
            << buses[0].get_brand() << " with capacity " << buses[0].get_capacity() << " finished his route!\n";
        buses.pop_front();
        return;
    }

    exit_of_passengers_from_bus(temp_bus_stop, buses[0], false);
    entrance_of_passengers_on_bus(temp_bus_stop, buses[0]);
    leaving_of_bus(temp_bus_stop, buses[0]);
}

int exit_of_passengers_from_bus(BusStop & temp_bus_stop, Autobus & temp_bus, bool last_station){
    int pas_out = 0;

    if( last_station ){
        cout << "\nLast station!\n";
        otchet << "\nLast station!\n";
        pas_out = temp_bus_stop.parking[0].salon.size();
        temp_bus_stop.parking[0].salon.clear();
    }
    else{
        if( !temp_bus_stop.parking[0].salon.empty() ){
            pas_out = rand() % temp_bus_stop.parking[0].salon.size();
            for(int i = 0; i < pas_out; ++i){
                temp_bus_stop.parking[0].salon.pop_back();
            }
        }
    }

    cout << "Number of outgoing passengers from autobus: " << pas_out << endl;
    otchet << "Number of outgoing passengers from autobus: " << pas_out << endl;

    if( bool(pas_out) ){
        cout << "Some passengers are leaving bus now...\n";
        otchet << "Some passengers are leaving bus now...\n";
    }

    temp_bus = temp_bus_stop.parking[0];

    //Sleep(pas_out * 2000);
    system("pause");
    cout << endl;
    otchet << endl;

    return pas_out;
}

int entrance_of_passengers_on_bus(BusStop & temp_bus_stop, Autobus & temp_bus){
    int pas_in = 0;
    if( !temp_bus_stop.is_platform_empty() ){
        pas_in = rand() % temp_bus_stop.get_count_passengers_on_platform() + 1;
        for(int i = 0; i < pas_in; ++i){
            if( temp_bus_stop.parking[0].salon.size() < temp_bus_stop.parking[0].get_capacity() ){
                temp_bus_stop.parking[0].salon.push_back( temp_bus_stop.get_first_passenger() );
                temp_bus_stop.go_out_first_passenger(); 
            }
            else{
                pas_in = i;
                cout << "\nBus is full now!\n";
                otchet << "\nBus is full now!\n";
                break;
            }
        }
    }

    if( bool(pas_in) ){
        cout << "Some passengers are entering in bus now...\n";
        otchet << "Some passengers are entering in bus now...\n";
    }

    temp_bus = temp_bus_stop.parking[0];

    //Sleep(pas_in * 2000);
    system("pause");
    cout << endl;
    otchet << endl;

    return pas_in;
}

void arrival_of_bus(BusStop & temp_bus_stop, Autobus & temp_bus, bool last_station){
    temp_bus_stop.parking.push_back( temp_bus );
    temp_bus_stop.parking[0].open_door();
    temp_bus_stop.parking[0].set_x_bus( temp_bus_stop.get_x_bus_stop() );
    temp_bus_stop.parking[0].set_y_bus( temp_bus_stop.get_y_bus_stop() );

    temp_bus = temp_bus_stop.parking[0];

    cout << temp_bus_stop;
}

void leaving_of_bus(BusStop & temp_bus_stop, Autobus & temp_bus){
    temp_bus_stop.parking[0].shut_door();
    cout << temp_bus_stop;

    temp_bus = temp_bus_stop.parking[0];

    temp_bus_stop.parking.pop_front();
}

double calculate_distance(int dx1, int dx2, int dy1, int dy2, int temp_i, int temp_bus_stop_size){
    double temp_dist = sqrt( pow( (dx2 - dx1), 2) + pow( (dy2 - dy1), 2)  );
    temp_dist = ceil(temp_dist);
    cout << "\nDistance to next station (m): " << temp_dist << endl;
    otchet << "\nDistance to next station (m): " << temp_dist << endl;
    return temp_dist; 
}

double calculate_time(double temp_dist, int temp_speed){
    double temp_time = temp_dist / temp_speed;
    temp_time = ceil(temp_time);
    cout << "Time to next station (s): " << temp_time << endl;
    otchet << "Time to next station (s): " << temp_time << endl;
    return temp_time;
}

int convert_speed(int temp_speed){
    temp_speed /= 3.6;
    return temp_speed;
}

Simulation.cpp

#include "NecessaryHeaders.h"
#include "SimulationFunctions.h"
#include "RandomEvents.h"
#include "Autobus.h"
#include "BusStop.h"

using namespace std;

ofstream otchet;

int main(){
    srand( (unsigned)time( NULL ) );

    otchet.open( "otchet.doc" ) ;
    if ( !otchet ){
          cout << "Error of opening file!\n" ;
          system("pause");
          return -1;
    }

    deque <Autobus> buses;
    Autobus::generate_buses(buses);

    vector <BusStop> bus_stops;
    BusStop::generate_bus_stops(bus_stops);

    while( !buses.empty() ){
        int situation = 0;
        int target_bus_stop = 0;
        situation = generate_random_event(bus_stops, target_bus_stop);

        arrival_of_passengers(bus_stops, situation);
        system("pause");

        for (size_t i = 0; i < bus_stops.size(); ++i ){

            bool last_station = ( i == (bus_stops.size() - 1) );

            if(situation == TRAFFIC && i == target_bus_stop){
                traffic(buses[0]);
            }

            system("pause");

            if(situation == FIRE && i == target_bus_stop){
                if( last_station ){
                    fire_on_bus_stop(bus_stops, i);
                    buses.pop_front();
                    system("pause");
                    break;

                }
                else{
                    fire_on_bus_stop(bus_stops, i);
                    system("pause");
                }
            }

            bus_on_route( bus_stops[i], buses[0], i, bus_stops.size() );

            //Sleep( temp_time * 1000 );
            system("pause");

            if(situation == BREAKING && i == target_bus_stop){
                breaking_bus(buses, bus_stops[i]);
                break;
            }

            bus_on_station(buses, bus_stops[i], last_station);
            system("pause");

            if( last_station ){
                break;
            }
        }
    }

    otchet.close();
    return 0;
}

NecessaryHeaders.h

#pragma once

#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <windows.h>
#include <cmath>
#include <deque>

I see some problems:

  1. I feel that there is something wrong in function main(). Maybe I forgot to do a new class Simulation or I must organize my project differently.

  2. I hear that global variable is evil but I use it in Simulation.cpp (line ofstream otchet).

  3. All my counters in classes (static int counter_bus_, for example) don't work correctly sometimes. What is wrong generally?

  4. Is it hard to do GUI for this project in Qt for a beginner?

  5. That program doesn't simulate reality. I want to do program for simultaneous movement of buses. Which is better: to do new project or improve this?

\$\endgroup\$
1
  • 2
    \$\begingroup\$ While it's completely okay to post this much code, you may have a better experience here if you break your question down into more focused, easily digestible, chunks. \$\endgroup\$
    – RubberDuck
    Commented Nov 30, 2014 at 13:23

1 Answer 1

4
\$\begingroup\$

Here are some things I see that may help you improve your code. Because C++11 is supported in VS 2012, and because it makes a lot of things easier/better/clearer, I've used C++11 features in my answer.

Consider an event-driven simulation strategy

The current simulation code is "bus-centric" in that it considers things from the point of view of the buses. This can work, but you may find it more natural to use an event-driven simulation strategy instead. Generally, a way to do that is to set up all of the objects (buses, passengers, bus stops, etc.) and then to set them all in motion using events. For example, if you have two buses each leaving two different bus stops, you can generate two next events -- bus1 arrives at next stop, and bus2 arrives at its next stop. Knowing the speed of each bus and the distance between any pair of stops, you can assign a timestamp to each event and store it in a priority queue. The simulation runs by processing the priority queue until the queue is empty. That approach will allow you to have buses simultaneously. If you want to also have smooth animation, you might consider using a time-step based strategy instead in which you consider time as a series of discrete steps of fixed duration (say 30 seconds) and update all object states for each time step.

Decide on which GUI based on your needs

I am a dedicated Linux user, so I would naturally choose Qt over Visual C++ as the basis for a GUI. Your needs may be different. In general, I'd say choose Qt if you can because it allows you many more possibilities (Mac, Linux, Android) than a Windows-only solution. However, if there are particular interface needs that are Windows only, and you don't plan on working with anything else, you might choose the native Windows GUI. In either case, there is a lot to learn, but there are many resources available on the internet for learning either or both.

Don't use system("pause")

There are two reasons not to use system("cls") or system("pause"). The first is that it is not portable to other operating systems which you may or may not care about now. The second is that it's a security hole, which you absolutely must care about. Specifically, if some program is defined and named cls or pause, your program will execute that program instead of what you intend, and that other program could be anything. First, isolate these into a seperate functions cls() and pause() and then modify your code to call those functions instead of system. Then rewrite the contents of those functions to do what you want using C++. In this case, a better alternative would be getchar().

Consider making your code cross-platform

It may surprise you to know that your code can be successfully run under Linux once two small changes are made. First, remove all instances of system("pause") as already mentioned. Second change your NecessaryHeaders.h file to check if the platform is Windows:

#ifdef _WIN32
#include <windows.h>
#endif

Don't specify const on return values

Generally speaking, it doesn't make sense to specify const on a return value of a function when that return values is a simple type such as int. In particular, the following functions should not have const as part of the return value:

Passenger::get_count_pas()
Autobus::get_x_bus()
Autobus::get_y_bus()

The reason is that the return value is a copy of something internal and not a pointer to anything inside the class, so there's no need to restrict what the calling function can do with the value since it can't affect the class.

Specify constructor items in declaration order

In the Autobus.h file, is this constructor:

Autobus(string brand, int const capacity, int max_speed)
    :brand_(brand), capacity_(capacity), max_speed_(max_speed), is_door_open_(false), bus_numberplate_(counter_bus_ + 1), x_bus_(0), y_bus_(0), current_speed_(max_speed){
        counter_bus_++;
}

However, is_door_open_ is declared after bus_numberplate_ and classes are initialized in declaration order, not in the order in which they're listed in the constructor. To avoid confusion, you should always order constructor items in the same order as they're declared. In this case, the simplest fix is to simply swap is_door_open_ and bus_numberplate_

Eliminate "magic numbers"

When there is code, such as in Autobus::generate_buses that uses numbers like this:

for(int i = 0; i < 3; ++i){
    int temp_rand = 0;
    temp_rand = rand() % 5 + 1;
    // etc.
}

it's not clear what 3 signifies or what 5 signifies. It's generally better to either use named constants or to calculate those numbers, reducing the chance for error when the program is modified.

Consider using a struct for Autobus initialization

In the Autobus::generate_buses code, I see a few areas that might be improved. The code currently looks like this:

void Autobus::generate_buses(deque <Autobus> &buses){
    for(int i = 0; i < 3; ++i){
        int temp_rand = 0;
        temp_rand = rand() % 5 + 1;
        for(int j = 0; j < temp_rand; ++j){
            buses.push_back( Autobus(mas_brand_buses[i], mas_cap_buses[i], mas_max_speed_buses[i]) );
        }
    }

    for(size_t i = 0; i < buses.size(); ++i){
        cout << buses[i];
    }
}

The three arrays mas_brand_buses, mas_cap_buses and mas_max_speed_buses are clearly intended to be parallel. That is, index 0 for each refers to one particular type of Autobus. For that reason, it would be better to use a struct instead to keep the associated values together. Here is an alternative approach that makes this function much simpler and easier to maintain:

struct RawAutobus {
    string brand;
    int cap;
    int max_speed;
};

const static RawAutobus rawAutobus[]{
    {"Paz",   40,  90},
    {"Gazel", 20, 110},
    {"Liaz", 100,  70},
};

static const int MAXBUSCOUNT{5};
static const int MINBUSCOUNT{1};

void Autobus::generate_buses(deque <Autobus> &buses){
    for(const auto &bus : rawAutobus) {
        for(int buscount = rand() % MAXBUSCOUNT + MINBUSCOUNT; buscount; --buscount) {
            buses.push_back( Autobus(bus.brand, bus.cap, bus.max_speed));
            cout << buses.back();
        }
    }
}

Also, while it may make sense for your particular project, it's generally better to separate functions like this from input or output operations, so it's worthwhile omitting the cout line and instead have the calling code create output if desired.

Redesign the insert operator implementation

The Autobus print function currently looks like this:

ostream & operator << (std::ostream & os, Autobus & bus){
    otchet << "Bus #" << bus.get_bus_numberplate() << " brand " \
            << bus.get_brand() << " with capacity " << bus.get_capacity() << endl;
    /*otchet << "Coordinate x: " << bus.get_x_bus() << endl;
    otchet << "Coordinate y: " << bus.get_y_bus() << endl;*/
    // etc.
    cout << "Bus #" << bus.get_bus_numberplate() << " brand " \
            << bus.get_brand() << " with capacity " << bus.get_capacity() << endl;
    // etc.
    return os;
}

There are several problems with this. First, the Autobus class being passed in is not altered and so therefore should be const Autobus &bus.

Second, os is not actually used, and there is a lot of needless duplication. Instead of that, use this:

ostream & operator << (std::ostream & os, const Autobus & bus){
    os << "Bus #" << bus.get_bus_numberplate() 
        << " brand " << bus.get_brand() 
        << " with capacity " << bus.get_capacity() 
        << "\nNumber of passengers: " << bus.salon.size() 
        << "\nFull names of passengers:\n";
    for (const auto &passenger : bus.salon)
        os << passenger << '\n';
    return os;
}

Also note that the line continuation char '\' is not needed here. Now the caller can specify which stream is used:

cout << buses.back();
otchet << buses.back();

Prefer '\n' to endl

Unless you actually need to flush the stream, (which is what endl does, you should use '\n' instead. Doing so may confer a performance advantage.

Don't abuse using namespace std

There's nothing wrong with using namespace std carefully, but it's definitely an error to use in global namespace within an include file. See this question for details on why.

Eliminate global variable

If you separate ancillary functions such as generate_buses from printing, you can probably completely eliminate the use of global variable otchet. For example, in main one could use this:

deque <Autobus> buses;
Autobus::generate_buses(buses);
for (const Autobus &bus : buses) {
    otchet << bus;
    cout << bus;
}

Doing so, combined with the rewrite of the ostream extractor mentioned above, will allow you to remove all mention of otchet from Autobus.cpp.

\$\endgroup\$
5
  • \$\begingroup\$ amazing .. you are indeed the for-loop master \$\endgroup\$
    – MORTAL
    Commented Dec 1, 2014 at 18:40
  • \$\begingroup\$ Edward, thank you very much! Your advices are really useful. I like your idea about structure for buses. I see that os is not actually used, it's my rough fault. And I understand main note about simulation strategy. It's rightly too, it's naturally. But I doubt that I can apply it because of knowledge C++. And I show the teacher my first project. I must change many things. I will add more statistics (all transported passangers for bus and etc.), price of ticket. And it's strange that buses discontinue existence after finishing of route. I will think about it. I'm very grateful to you. \$\endgroup\$
    – dimanist
    Commented Dec 2, 2014 at 11:14
  • \$\begingroup\$ @dimanist: In all, it's a pretty solid piece of code for a beginner. You're well on your way to mastery. \$\endgroup\$
    – Edward
    Commented Dec 2, 2014 at 11:54
  • \$\begingroup\$ @Edward, can I ask you some questions more? Is it true that I decide to do deque "platform" (for passengers on a bus stop) as private? It could be public but I want to prevent intervention by outside, for example, now you can't do methods clear() and others. Can I do it for deque parking and vector salon too (they both are as public now)? And I think now that distance between bus stops must be as object of separate class, with random number of traffic lights and etc. \$\endgroup\$
    – dimanist
    Commented Dec 2, 2014 at 17:41
  • \$\begingroup\$ @dimanist: When I write software, I start with what I want to accomplish. Then I write a main in the style that I would like to be able to. Then I write the least amount of software possible to make that interface possible. It's not a direct answer to your question; rather it's general advice that you may be able to use for your own decision-making process. \$\endgroup\$
    – Edward
    Commented Dec 2, 2014 at 17:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.