Select Git revision
AccountData.js
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
rute.cpp 22.56 KiB
/**
* @file rute.cpp
* @author Andreas Blakli
*/
#include "rute.h"
using namespace std;
extern Stoppesteder* gStoppesteder;
/**
* Constructor for Rute objekt.
*
*/
Rute::Rute() {
}
/**
* Destructor for Rute objektet.
*
*/
Rute::~Rute() {
}
/**
* Lager ett nytt stopp i ruten.
*
* @param eksisterende - Indexen til ett eksisterende stoppested.
* @param pos - Posisjonen til iteratoren.
* @return Stopp* - Ett nytt stopp hvis alt stoppet er lovlig nullptr ellers.
*/
Stopp* Rute::ny(const int& eksisterende, int pos) {
string stoppPlass = "";
Stoppested *stoppested, *forrigeStoppested;
Stopp *stopp, *forrigeStopp;
stoppested = nullptr;
stopp = nullptr;
bool forsteStopp = true;
do {
forrigeStoppested = stoppested;
forrigeStopp = stopp;
if (eksisterende != -1) {
forrigeStoppested = gStoppesteder->hentEksisterende(eksisterende);
forrigeStopp = new Stopp;
forrigeStopp->indexStoppested = eksisterende;
}
stopp = new Stopp;
stoppested = nullptr;
if (alleStoppestedenePaaRuten.size() > 0) forsteStopp = false;
cout << "\nSkriv inn navn eller nummer på stoppeplass du ønsker "
<< "å legge til (blankt for avbryt):";
getline(cin, stoppPlass);
// Strengen ikke er tom
if (!stoppPlass.empty()) {
stoppPlass = hjelp.rensStreng(stoppPlass);
if (!hjelp.erBokstav(stoppPlass)) {
// Hvis tall
stoppested = gStoppesteder->hentEksisterende(stoi(stoppPlass) - 1);
} else
// Else bokstav(r)
stoppested = gStoppesteder->hentEksisterende(stoppPlass);
// Hvis stoppestedet ikke eksisterer fra før og input er bokstaver
if (stoppested == nullptr && hjelp.erBokstav(stoppPlass)) {
cout << "\nError: Stoppested eksisterer ikke!" << '\n'
<< "Oppretter nytt stoppsted basert på forrige gitte parameter."
<< '\n';
if (forsteStopp)
gStoppesteder->ny(stoppPlass, false);
else
gStoppesteder->ny(stoppPlass, true);
stoppested = gStoppesteder->hentEksisterende(stoppPlass);
}
stopp->indexStoppested = gStoppesteder->hentIndex(stoppested);
// Er ikke første stopp og har ikke nabostopp
if (!forsteStopp && stoppested->hentTidNaboStopp() < 0) {
stopp->minutterFraForrigeStoppested = lesTid();
} else if (forsteStopp)
stopp->minutterFraForrigeStoppested = 0;
else {
stopp->minutterFraForrigeStoppested = -1;
}
if (!sjekkOmStoppEksisterer(stopp)) {
oppdaterStoppestedVectorer(stoppested,
forrigeStoppested,
stopp,
forrigeStopp);
if (eksisterende != -1 && pos == alleStoppestedenePaaRuten.size()) {
alleStoppestedenePaaRuten.push_back(stopp);
} else if (eksisterende != -1) {
auto it = alleStoppestedenePaaRuten.begin();
advance(it, pos);
Stopp* tmpstopp = *it;
int tmpTid = tmpstopp->minutterFraForrigeStoppested;
tmpstopp->minutterFraForrigeStoppested = stopp->minutterFraForrigeStoppested;
stopp->minutterFraForrigeStoppested = tmpTid;
alleStoppestedenePaaRuten.insert(it, stopp);
pos++;
} else
alleStoppestedenePaaRuten.push_back(stopp);
cout << "\nStopp lagt til!" << '\n';
} else
cout << "\nError: Stopp er allerede lagt til!" << '\n';
}
} while (!stoppPlass.empty());
// Hvis ikke nok stopp er lagt inn på ruten
if (alleStoppestedenePaaRuten.size() <= 1 && eksisterende == -1) {
cout << "\nIkke nok stopp lagt inn! Avbryter" << '\n';
return nullptr;
}
return stopp;
}
/**
* Sletter alle pekerne i listen over alle stoppestedene i ruten.
*
*/
void Rute::ryddOppMinne() {
for (const auto& val : alleStoppestedenePaaRuten) {
delete val;
}
alleStoppestedenePaaRuten.clear();
}
/**
* Sjekker om et stopp eksiterer fra før i listen over alle
* stoppestedene i ruten.
*
* @param stopp - Peker til stoppet.
* @return true - Hvis stoppet eksisterer i ruten.
* @return false - Hvis stoppet ikke eksisterer i ruten.
*/
bool Rute::sjekkOmStoppEksisterer(Stopp* stopp) {
for (const auto& val : alleStoppestedenePaaRuten) {
if (val->indexStoppested == stopp->indexStoppested) return true;
}
return false;
}
/**
* Skriver ut informasjon om ruten forlengs og baklengs.
*
* @see skrivDataForlengs().
* @see skrivDataBaklengs().
*/
void Rute::skrivData() {
skrivDataForlengs();
skrivDataBaklengs();
}
/**
* Skriver ut informasjon om ruten forlengs. Fra startstopp til
* endestopp til terminal.
*
* @see Stoppested::hentEksisterende().
* @see Stoppested::hentNavn().
*/
void Rute::skrivDataForlengs() {
Stoppested* stopp;
int totalTid, storrelseListe;
totalTid = 0;
storrelseListe = alleStoppestedenePaaRuten.size();
cout << "\n\n\t..::Stoppested navn\tTid mellom stopp"
<< "\tTotal tid fra rutestart::..";
for (const auto& val : alleStoppestedenePaaRuten) {
if (val->minutterFraForrigeStoppested != 0)
totalTid += val->minutterFraForrigeStoppested;
stopp = gStoppesteder->hentEksisterende(val->indexStoppested);
if (stopp != nullptr) {
cout << "\n\t\t"
<< stopp->hentNavn()
<< setw(15)
<< "\t" << val->minutterFraForrigeStoppested
<< setw(15)
<< "\t\t" << totalTid
<< setw(15);
}
}
}
/**
* Skriver ut informasjon om ruten baklengs, dvs
* fra endestopp til startstopp til terminal.
*
* @see Stoppested::hentEksisterende().
* @see Stoppested::hentNavn().
*/
void Rute::skrivDataBaklengs() {
Stoppested* stoppested;
Stopp *stopp, *forrigeStopp;
int totalTid, storrelseListe;
bool forste = true;
totalTid = 0;
cout << "\n\n\t..::Stoppested navn\tTid mellom stopp"
<< "\tTotal tid fra rutestart::..";
for (auto it = alleStoppestedenePaaRuten.rbegin();
it != alleStoppestedenePaaRuten.rend(); it++) {
stopp = *it;
stoppested = gStoppesteder->hentEksisterende(stopp->indexStoppested);
if (!forste) {
totalTid += forrigeStopp->minutterFraForrigeStoppested;
cout << "\n\t\t"
<< stoppested->hentNavn()
<< setw(15)
<< "\t" << forrigeStopp->minutterFraForrigeStoppested
<< setw(15)
<< "\t\t" << totalTid
<< setw(15);
} else {
cout << "\n\t\t"
<< stoppested->hentNavn()
<< setw(15)
<< "\t" << 0
<< setw(15)
<< "\t\t" << 0
<< setw(15);
forste = false;
}
forrigeStopp = *it;
}
}
/**
* Funksjonen styrer om stopp skal slettes eller endres
* i en eksisterende rute.
*
* @see lesData3 lesInt().
* @see slettStoppested().
* @see smettInnStoppested().
*/
void Rute::endre() {
int valg, antall;
cout << "\n\n1 - Slett stoppested\n2 - Smett inn stoppested\n0 - Avbryt" << '\n';
valg = lesInt("Kommando", 0, 2);
antall = alleStoppestedenePaaRuten.size();
if (valg > 0) {
int start, slutt;
start = slutt = 0;
start = lesInt("Hvilke stoppested utgjør start punktet?",
1, antall);
if (valg == 1 && antall > 2 && start < antall) {
slutt = lesInt("Hvilket stoppested utgjør slutt ytterpunkt?",
start + 2, antall);
slettStoppested(start, slutt);
} else if (valg == 2)
slutt = lesInt("Hvilket stoppested utgjør slutt ytterpunkt?",
start, antall);
else
cout << "\nError i sletting: ugyldig input!" << '\n';
if (valg == 2 && slutt - 1 == start || valg == 2 && slutt == start)
smettInnStoppested(start, slutt);
else if (valg == 2)
cout << "\nError: For smett inn så må slutt være rett etter start "
<< "for at innsmettingen skal være entydig!\n"; //" << '\n'
}
}
/**
* Sletter ett eller flere stopp fra ruten mellom
* de angitte parameterne.
*
* @param start - Slett fra.
* @param slutt - Slett til.
*/
void Rute::slettStoppested(const int& start, const int& slutt) {
Stopp* stopp;
auto it = alleStoppestedenePaaRuten.begin();
advance(it, start);
for (int i = start; i < slutt - 1; i++) {
stopp = *it;
delete stopp;
it = alleStoppestedenePaaRuten.erase(it);
}
skrivData();
}
/**
* Smetter inn et stoppested mellom angitte parameter
* verdier.
*
* @param start - Fra stopp.
* @param slutt - Til stopp.
*
* @see ny().
*/
void Rute::smettInnStoppested(const int& start, const int& slutt) {
Stopp* stopp;
list<Stopp*>::iterator it = alleStoppestedenePaaRuten.begin();
advance(it, start - 1);
stopp = *it;
if (slutt == start && start < alleStoppestedenePaaRuten.size())
ny(stopp->indexStoppested, start - 1);
else
ny(stopp->indexStoppested, start);
}
/**
* Legger til ett stopp i ruten hvis det ikke er nullptr.
*
* @param stopp - Peker til stopp.
*/
void Rute::leggTilStoppestedIRute(Stopp* stopp) {
if (stopp != nullptr)
alleStoppestedenePaaRuten.push_back(stopp);
}
void Rute::skrivType() {
}
/**
* Oppdaterer stoppestedet og stoppestedets naboer sine indexer til naboer
* og minutter mellom de relaterte nabo stoppene.
*
* @param stoppested - Peker til nåværende stoppested.
* @param forrigeStoppested - Peker til det forrige stoppestedet.
* @param stopp - Peker til det nåværende stoppet.
* @param forrigeStopp - Peker til det forrige stoppet.
*
* @see Stoppested::hentAntallStoppestedVector().
* @see Stoppested::hentTidNaboStopp().
* @see Stoppested::hentTidForsteNabo().
* @see Stoppested::leggTilNaboBakerst().
* @see Stoppested::leggTilNaboFremst().
* @see Stoppested::leggTilNaboStopp().
*/
void Rute::oppdaterStoppestedVectorer(Stoppested* stoppested,
Stoppested* forrigeStoppested,
Stopp* stopp,
Stopp* forrigeStopp) {
int tmpTid2, tmpTid;
tmpTid2 = tmpTid = -1;
int antIVec = stoppested->hentAntallStoppestedVector();
Stoppested* tmpstd = stoppested;
if (stoppested != nullptr) {
tmpTid = stoppested->hentTidNaboStopp();
}
if (forrigeStoppested != nullptr) {
if (stopp->minutterFraForrigeStoppested == -1) {
tmpTid2 = stoppested->hentTidForsteNabo();
if (tmpTid2 == -1) tmpTid2 = stoppested->hentTidNaboStopp();
// Legger nåværende stopp til i forrige stoppested
forrigeStoppested->leggTilNaboBakerst(stopp->indexStoppested,
tmpTid2);
} else
forrigeStoppested->leggTilNaboBakerst(stopp->indexStoppested,
stopp->minutterFraForrigeStoppested);
if (stoppested->hentIndex() != forrigeStopp->indexStoppested) {
if (stopp->minutterFraForrigeStoppested == -1) {
// Legger til nåværende stopp til stoppested
stoppested->leggTilNaboFremst(forrigeStopp->indexStoppested,
tmpTid2);
} else
stoppested->leggTilNaboFremst(forrigeStopp->indexStoppested,
stopp->minutterFraForrigeStoppested);
}
} else if (antIVec < 1) {
stoppested->leggTilNaboStopp(-1, -1);
}
// Gir stopp nabo-tid slik at rute beskrivelse fungerer korrekt
if (stopp->minutterFraForrigeStoppested == -1)
stopp->minutterFraForrigeStoppested = stoppested->hentTidNaboStopp();
}
/**
* Leser inn tid fra CLI.
*
* @return int - Brukervalgte tid.
* @see LesData3 lesInt().
*/
int Rute::lesTid() {
return lesInt("Tid mellom forrige stopp i minutter",
MIN_MINUTTER,
MAX_MINUTTER);
}
/**
* Styrer alt som har med tabell logikk å gjøre dvs.
* Den skriver ut en tabell for et spesefikt stoppested
* i en spesefikk rute mellom bruker valgte tidspunkt
* enten framlengs eller baklengs.
*
* @see Stoppesteder::hentEksisterende().
* @see Stoppested::hentNavn().
* @see skrivDataForlengs().
* @see skrivDataBaklengs().
* @see HjelpeFunksjoner::rensStreng().
* @see HjelpeFunksjoner::skrivKlokkeslett().
* @see LesData3 lesInt().
* @see HjelpeFunksjoner::lesTall().
* @see hentTotalTidForan().
* @see hentTotalTidTilbake().
*/
void Rute::tabell() {
Retning retning = Annen;
Stoppested* stoppested;
string stopp, stopp2, navn;
char valg = '\0';
bool ikkeFullt, igjen;
ikkeFullt = igjen = true;
vector<vector<int>> valgtTid;
int avgangsTid, fraKlTime, fraKlMin, tilKlTime, tilKlMin,
tmpTime, tmpMin, forrigeTmpMin, totTid, utregning;
tmpTime = tmpMin = forrigeTmpMin = totTid = utregning = fraKlTime = 0;
tilKlMin = MIN_MINUTTER;
tilKlTime = MIN_TIMER;
stopp = gStoppesteder->hentEksisterende(
alleStoppestedenePaaRuten.front()->indexStoppested)
->hentNavn();
stopp2 = gStoppesteder->hentEksisterende(
alleStoppestedenePaaRuten.back()->indexStoppested)
->hentNavn();
cout << "\nFram: Retningen: "
<< stopp
<< " - "
<< stopp2
<< "\nTilbake: Retningen: "
<< stopp2
<< " - "
<< stopp
<< '\n'
<< "\nVelg retning F = Fram, T = Tilbake"
<< '\n';
while (valg != 'F' && valg != 'T') {
valg = lesChar("Kommando: ");
if (valg == 'F')
retning = Fram;
else if (valg == 'T')
retning = Tilbake;
switch (retning) {
case Fram:
skrivDataForlengs();
break;
case Tilbake:
skrivDataBaklengs();
break;
default:
cout << "\nUgyldig valg!" << '\n';
break;
}
}
cout << "\n\nSkriv inn navnet på stoppet: ";
getline(cin, navn);
navn = hjelp.rensStreng(navn);
stoppested = gStoppesteder->hentEksisterende(navn);
if (stoppested != nullptr) {
cout << "\nTime= 0 og Minutt= 0 for å AVSLUTTE innlesning" << '\n';
do {
igjen = true;
do {
cout << "\nFra kl. (";
hjelp.skrivKlokkeslett(tilKlTime, tilKlMin);
cout << " - ";
hjelp.skrivKlokkeslett(MAX_TIMER, MAX_MINUTTER);
cout << "): "
<< "\nTime: ";
fraKlTime = hjelp.lesTall();
cout << "\nMinutt: ";
fraKlMin = hjelp.lesTall();
if (fraKlTime < MAX_TIMER &&
fraKlTime > tilKlTime &&
fraKlMin < MAX_MINUTTER &&
fraKlMin >= 0)
igjen = false;
if (fraKlTime <= 0 && fraKlMin <= 0)
igjen = false;
} while (igjen);
// Hvis ikke avslutte
if (fraKlTime > 0 || fraKlMin > 0) {
avgangsTid = lesInt("Tid mellom avganger", MIN_AVGANGS_TID, MAX_AVGANGS_TID);
tmpTime = fraKlTime + (avgangsTid / 60);
tmpMin = fraKlMin + (avgangsTid % 60);
if (tmpMin > MAX_MINUTTER) {
tmpTime++;
tmpMin = tmpMin % 60;
}
// Hvis tid gitt går over max verdi i.e. 24t
if (tmpTime > MAX_TIMER)
ikkeFullt = false;
do {
cout << "\nTil kl. (";
hjelp.skrivKlokkeslett(tmpTime, tmpMin);
cout << " - ";
hjelp.skrivKlokkeslett(MAX_TIMER, MAX_MINUTTER);
cout << "): "
<< "\nTime: ";
tilKlTime = hjelp.lesTall();
cout << "\nMinutt: ";
tilKlMin = hjelp.lesTall();
} while (tilKlTime > MAX_TIMER ||
tilKlTime < tmpTime ||
tilKlMin > MAX_MINUTTER || tilKlMin < 0);
// Legger til tider i vector
if (ikkeFullt) {
valgtTid.push_back({fraKlTime, fraKlMin, tmpTime,
tmpMin, avgangsTid,
tilKlTime, tilKlMin, tmpTime});
}
} else {
fraKlTime = fraKlMin = tilKlTime = tilKlMin = 0;
}
} while (fraKlTime > 0 || fraKlMin > 0 || tilKlTime > 0 || tilKlMin > 0); // fraKlTime != 0 || fraKlMin != 0 && tilKlTime != 0 || tilKlMin != 0 && ikkeFullt);
if (retning == Fram)
totTid = hentTotalTidForan(gStoppesteder->hentIndex(stoppested));
else
totTid = hentTotalTidTilbake(gStoppesteder->hentIndex(stoppested));
// Har tid har blitt lagt til i vector
if (valgtTid.size() > 0) {
cout << "\n\t..::Rutetabell for stoppestedet: " << navn
<< "::.."
<< "\n\n";
// Klokkeslett
for (int i = valgtTid.front()[0];
i <= valgtTid.back()[5]; i++) {
if (i <= 9)
cout << "\t\t0" << i;
else
cout << "\t\t" << i;
cout << ":";
// Tabell for stopp på 'i' klokkeslett
int tall = 0;
int timeAvgang = 0;
int minutterAvgang = 0;
for (auto& val : valgtTid) {
if (i >= val[0] && i <= val[5]) {
igjen = true;
timeAvgang = (val[4] + totTid) / 60;
minutterAvgang = (val[4] + totTid) % 60;
if ((val[4] + totTid) % 60 != 0)
timeAvgang++;
if (val[7] == i)
tall = minutterAvgang;
else
tall = totTid + val[4];
while (igjen) {
// På samme time
if (i >= val[2]) {
if (tall < MAX_MINUTTER && val[7] == i) {
cout << "\t";
if (tall <= 9)
cout << "0" << tall;
else
cout << tall;
if (val[4] > MAX_MINUTTER)
igjen = false;
tall += totTid + val[4];
} else {
igjen = false;
}
} else
igjen = false;
}
if (val[7] == i)
val[7] += timeAvgang;
}
}
cout << '\n';
}
}
} else
cout << "\nError: Fant ikke noe stoppested med det navnet!" << '\n';
}
/**
* Henter total tid fra stoppested start til angitt parameter.
*
* @param pos - Indexen til stoppestedet.
* @return int - Den totale tiden fra start stopp til pos.
*/
int Rute::hentTotalTidForan(const int& pos) {
int totalTid;
totalTid = 0;
for (const auto& val : alleStoppestedenePaaRuten) {
if (val->minutterFraForrigeStoppested != 0)
totalTid += val->minutterFraForrigeStoppested;
if (val->indexStoppested == pos)
return totalTid;
}
return -1;
}
/**
* Henter total tid fra stoppested slutt til angitt parameter.
* Brukes når man trenger total tid "reversert" som i skrivDataBaklengs().
*
* @param pos - Indexen til stoppestedet.
* @return int - Den totale tiden fra slutt stopp til pos.
*/
int Rute::hentTotalTidTilbake(const int& pos) {
Stopp *stopp, *forrigeStopp;
int totalTid;
bool forste = true;
totalTid = 0;
for (auto it = alleStoppestedenePaaRuten.rbegin();
it != alleStoppestedenePaaRuten.rend(); it++) {
stopp = *it;
if (!forste) {
totalTid += forrigeStopp->minutterFraForrigeStoppested;
if (stopp->indexStoppested == pos) return totalTid;
} else {
forste = false;
}
forrigeStopp = *it;
}
return -1;
}
/**
* Leser inn stopp fra fil og lager en nye pekere til
* Stopp structs som legges til listen over alle stoppesteder
* på ruten.
*
* @param inn - Inn data fil-strøm.
* @see HjelpeFunksjoner::splittStreng().
*/
void Rute::lesFraFil(ifstream& inn) {
Stopp* stopp = nullptr;
vector<string> linjenSplittet;
int pos = 0;
string heleLinjen = "";
do {
getline(inn, heleLinjen);
linjenSplittet = hjelp.splittStreng('*', heleLinjen);
pos = 0;
if (heleLinjen != "Buss" && heleLinjen != "Bane" && heleLinjen != "X") {
for (int i = 0; i < linjenSplittet.size() - 1; i++) {
switch (i) {
case 0: {
stopp = new Stopp;
stopp->indexStoppested = stoi(linjenSplittet[0]);
break;
}
case 1: {
stopp->minutterFraForrigeStoppested = stoi(linjenSplittet[1]);
alleStoppestedenePaaRuten.push_back(stopp);
break;
}
}
pos++;
}
}
} while (heleLinjen != "Buss" && heleLinjen != "Bane" && heleLinjen != "X");
}
/**
* Skriver alle stopp på en rute til fil.
*
* @param ut - Ut data fil-strøm.
*/
void Rute::skrivTilFil(ofstream& ut) {
for (const auto& val : alleStoppestedenePaaRuten) {
ut << val->indexStoppested << '*'
<< val->minutterFraForrigeStoppested << '*'
<< '\n';
}
}