/** * 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); }