Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
rute.cpp 9.19 KiB
/**
 * Kode-fil for rute-klassen
 * 
 * @file rute.cpp
 * @author Sondre Sand & Frederik Simonsen
 */
#include <algorithm> //all_of
#include <iostream>
#include <iomanip>
#include <list>
#include <fstream>
#include "rute.h"
#include "stoppested.h"
#include "stoppesteder.h"
#include "LesData3.h"
using namespace std;

extern Stoppesteder gStoppestederBase;

//********STOPP FUNKSJONER*******************


/**
 *  Construct a new Stopp:: Stopp object
 * 
 * @param stoppNr 
 * @param antMin 
 */
Stopp::Stopp(const int stoppNr, const int antMin) {
    nr = stoppNr; minutter = antMin;
}

/**
 * Henter en stopps unike nr
 * 
 * @return Et stoppesteds unike nr
 */
int Stopp::hentNr() {
    return nr;
}

/**
 * skrivTilFil(...)
 * 
 * @param ut 
 */
void Stopp::skrivTilFil(ofstream & ut) {
    ut << nr << ' ' << minutter << '\n';
}

//********RUTE FUNKSJONER*******************


/**
 * Rute()
 */
Rute::Rute() {
    // Gjør ingenting, men må være her så man kan opprette buss/bane
}

/**
 * Opretter en ny rute fra fil
 * 
 * @param inn filen det leses fra
 */
Rute::Rute(ifstream & inn) {
    int antStopp,
        stoppNr,
        antMin;
    inn >> antStopp; inn.ignore();
    for (int i = 0; i < antStopp; i++) {
        inn >> stoppNr >> antMin; inn.ignore();
        stoppene.push_back(new Stopp(stoppNr, antMin));
    }
}

/**
 * -sjekker om lista er mer en 1 entry.
 * 
 * @return true 
 * @return false 
 */
bool Rute::erListeGyldig(){
    if(stoppene.size() > 1){
        return true;
    }
    return false;
}

/**
 * @brief 
 * 
 * @param nvn 
 * @return true 
 * @return false 
 */
bool Rute::erTall(std::string nvn) {
    return all_of(nvn.begin(), nvn.end(), ::isdigit);
}

/**
 * Sjekker om stopp er lagt til i ruta allerede
 * 
 * @param nr 
 * @return true 
 * @return false
 * @see Stopp::hentNr() 
 */
bool Rute::finnesStopp(const int indeks) {
    for (auto it = stoppene.begin(); it != stoppene.end(); it++) {
        if ((*it)->hentNr() == indeks)
            return true;
    }
    return false;
}

/**
 * skrivRetninger(...) brukes med R T
 * 
 */
void Rute::skrivRetninger() const {
    // Hjelpevariabler for å hente stasjonsnavnene knyttet til ruten:
    int startIndeks = stoppene.front()->hentNr(),
        stoppIndeks = stoppene.back()->hentNr();
    string startStasjon = gStoppestederBase.hentNavnVhaIndeks(startIndeks),
           endeStasjon = gStoppestederBase.hentNavnVhaIndeks(stoppIndeks);

    // Skriver ut start- og endestasjon for ruten i begge retninger:
    cout << "\nFram:    Retningen: " << startStasjon << " - "
         << endeStasjon << "\nTilbake: Retningen: "
         << endeStasjon << " - " << startStasjon << '\n';
}

/**
 * skriver rute forlengs eller baklengs
 * 
 * @param retning forlengs eller baklengs
 * @see Stoppesteder::hentNavnVhaIndeks(...)
 */
void Rute::skrivRute(const Retning retning) {
    int minF = 0,
        indeks = 0,
        totMin = 0;
    string navn;
    
    if (retning == Fram) {
        for (auto it = stoppene.begin(); it != stoppene.end(); it++) {
            indeks = (*it)->nr;
            minF = (*it)->minutter;
            navn = gStoppestederBase.hentNavnVhaIndeks(indeks);
            totMin += minF;
            cout << setw(25) << navn << " - " << setw(2) << minF
                 << " min fra forrige  (" << setw(3) << totMin
                 << " min fra rutestart)\n";
        }
    }

    if (retning == Tilbake) {
        for (auto it = stoppene.rbegin(); it != stoppene.rend(); it++) {
            indeks = (*it)->nr;
            navn = gStoppestederBase.hentNavnVhaIndeks(indeks);
            cout << setw(25) << navn << " - " << setw(2) << minF
                    << " min fra forrige  (" << setw(3) << totMin
                    << " min fra rutestart)\n";
            minF = (*it)->minutter;
            totMin += minF;
        }
    }
}

/**
 * @brief - sletter siste entry i stoppene.
 * 
 */
void Rute::slettData(){
    stoppene.clear();
}

/**
 * Leser og oppretter stopp for en ny rute
 * 
 * @see Stoppesteder::byttBokstaver(...)
 * @see Stoppesteder::finnesIndex(...)
 * @see Stoppesteder::hentNavnVhaIndex(...)
 * @see Stoppesteder::finnEntydig(...)
 * @see Stoppesteder::finnDuplikat(...)
 * @see Rute::finnesStopp(...)
 * @see Stoppested::finnesNabo(...)
 * @see Stoppested::hentNaboIndeks(...)
 * @see Stoppested::hentNaboTid(...)
 * @see Stoppested::settNaboIndeks(...)
 * @see Stoppested::settNaboTid(...)
 */
void Rute::lesData() {
    string navn,
           fNavn,
           nNavn;
    int stoppNr = 0,
        indeks = 0,
        naboIndeks = 0,
        tidTilF = 0;
    Stopp* nyStopp = nullptr;
    Stoppested* fStopp = nullptr;
    Stoppested* nStopp = nullptr;
    
    cout << "\nStoppested (entydig navn / tall / ENTER for å avslutte): ";
    getline(cin, navn); 
    while (navn.size() > 0) {  //Kjør så lenge ikke blank/enter er trykket.
        navn = gStoppestederBase.byttBokstaver(navn); // Fjerner æøåÆØÅ
        
        if (erTall(navn)) {  // SJekker om navn kun består av tall
            stoppNr = stoi(navn); //Hvis kun tall, gjør om til int
            if(gStoppestederBase.finnesIndeks(stoppNr-1)){ //@see finnesIndeks, funker dette?
            navn = gStoppestederBase.hentNavnVhaIndeks(stoppNr); // Hent navn
            }
    }
        
        fNavn = gStoppestederBase.finnEntydig(navn); // Sjekker for entydighet

        if (fNavn.size() > 0) { // Hvis entydig navn:
            cout << '\n' << fNavn << '\n';
            indeks = gStoppestederBase.hentIndeksVhaNavn(fNavn);
            if (!finnesStopp(indeks+1)) { // Hvis stopp ikke finnes fra før på ruten
            if (stoppene.size() > 0) { // Hvis ikke første stopp på ruten
                nStopp = gStoppestederBase.finnDuplikat(fNavn);
                if (nStopp->finnesNabo(naboIndeks+1)) { // Hvis nabo finnes fra før
                    naboIndeks = nStopp->hentNaboIndeks(naboIndeks+1);
                    tidTilF = nStopp->hentNaboTid(naboIndeks);
                    nyStopp = new Stopp(indeks+1, tidTilF);
                    stoppene.push_back(nyStopp);
                    naboIndeks = indeks;
                    cout << "\nTiden mellom stoppestedene er allerede registrert som "
                         << tidTilF << " minutter.\n";
                        

                } else { // Hvis nabo ikke finnes fra før:
                    tidTilF = lesInt("Tid fra forrige stopp", 1, 10); // Leser tid til forrige nabo
                    nStopp = gStoppestederBase.finnDuplikat(fNavn); // Finner egen peker
                    fStopp->settNaboIndeks(indeks); // Oppdaterer forrige stopps nabovektor
                    fStopp->settNaboTid(tidTilF); // Oppdaterer forrige stopps tid til nabo
                    nStopp->settNaboIndeks(naboIndeks); // Oppdaterer nåværende stopps nabovektor
                    nStopp->settNaboTid(tidTilF); // Oppdaterer naværende stopps tid til nabo
                    nyStopp = new Stopp(indeks+1, tidTilF); // Oppretter ny stopp på ruten
                    stoppene.push_back(nyStopp); // Stoppen legges til ruten
                    naboIndeks = indeks;
                }

            } else { // Hvis første stopp på ruten
                nStopp = gStoppestederBase.finnDuplikat(fNavn); // Peker til riktig
                nyStopp = new Stopp(indeks+1, 0); // Setter stopp sitt nr
                // til å korrespondere med indeks i vector, og tid til
                // forrige nabo å være 0, da første stopp på ruten
                stoppene.push_back(nyStopp); // Legges til listen
                naboIndeks = indeks;
            }
            nNavn = fNavn; // Setter nåværende nabo til å være forrige navn
            fStopp = nStopp; // Setter forrige stopp til å bli nåværende stopp
            } else
                cout << "\nStoppet er allerede registrert på ruten!\n";
        } else { // Hvis ikke entydig:
            cout << "\nIkke funnet (den entydige) stoppestedet!\n";
        }
        
        // Forsøker å lese evt. ny eller korrekt stopp:
        cout << "\nStoppested (entydig navn / tall / ENTER for å avslutte): ";
        getline(cin, navn); 
    }
    cout << "\nOk, du angrer og ønsker ikke å legge til ny rute.\n";
}

/**
 * skrivBeskrivelse()
 * skriver forlengs og baklengs
 * 
 * @see Rute::skrivRute(...)
 */
void Rute::skrivBeskrivelse() {
    cout << "Ruten:\n";
    skrivRute(Fram);
    cout << "\n\n";
    skrivRute(Tilbake);
}

/**
 * Skriver ut en rute
 * Første-siste stopp
 * 
 * @see Stoppesteder::hentNavnVhaIndeks(...)
 */
void Rute::skrivData() const {
    int startIndeks,
        stoppIndeks;
    string startNavn,
           stoppNavn;
    
    startIndeks = stoppene.front()->hentNr(); // Henter startsteds unike nr
    stoppIndeks = stoppene.back()->hentNr(); // Henter stopsteds unike nr
    startNavn = gStoppestederBase.hentNavnVhaIndeks(startIndeks);
    stoppNavn = gStoppestederBase.hentNavnVhaIndeks(stoppIndeks);

    cout << startNavn << " - " << stoppNavn;
}

/**
 * @brief skrivKort() (virtuell)
 * 
 */
void Rute::skrivKort() const {

}

/**
 * skriver rute til fil
 * 
 * @param ut fila det skrives til
 * @see Stopp::skrivTilFil(...)
 */
void Rute::skrivTilFil(ofstream & ut) {
    ut << stoppene.size() << '\n';
    for (auto it = stoppene.begin(); it != stoppene.end(); it++)
        (*it)->skrivTilFil(ut);
}