init
This commit is contained in:
commit
1785e4285a
12
.gitignore
vendored
Executable file
12
.gitignore
vendored
Executable file
@ -0,0 +1,12 @@
|
||||
*~
|
||||
|
||||
.DS_Store
|
||||
|
||||
*.pro.user.*
|
||||
*.pro.user
|
||||
|
||||
build-*/
|
||||
*.app
|
||||
*.exe
|
||||
|
||||
build
|
136
Event.cpp
Executable file
136
Event.cpp
Executable file
@ -0,0 +1,136 @@
|
||||
#include "Event.h"
|
||||
#include "Simulation.h"
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
void hatchEvent::processEvent (Simulation& sim) {
|
||||
double total = sim.getJuvenilePopulation() + sim.getAdultPopulation();
|
||||
double saturation = min(total/STARVE_THRESHOLD, 1.0);
|
||||
unsigned ageAverage = MAX_AGE * (1 - saturation);
|
||||
uniform_int_distribution<int> ageDist(0.1 * ageAverage, 1.9 * ageAverage);
|
||||
unsigned ageExpectancy = ageDist(generator);
|
||||
|
||||
Fish* afish = new Fish(eventTime, ageExpectancy);
|
||||
sim.decEggPopulation();
|
||||
sim.incJuvenilePopulation();
|
||||
sim.addFish(afish);
|
||||
|
||||
uniform_int_distribution<int> juvDist(0.8* AVG_MATURATION_TM, 1.2* AVG_MATURATION_TM);
|
||||
unsigned juvenileFor = juvDist(generator);
|
||||
|
||||
if( ageExpectancy < juvenileFor){
|
||||
sim.scheduleEvent(new deathEvent(eventTime + ageExpectancy, afish));
|
||||
}else{
|
||||
sim.scheduleEvent(new matureEvent(eventTime + juvenileFor, afish, generator));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void spawnEvent::processEvent (Simulation& sim) {
|
||||
if(afish->isCaught()){
|
||||
delete afish;
|
||||
afish = nullptr;
|
||||
return;
|
||||
}
|
||||
double concentration = min(sim.getAdultPopulation() / (double)SPAWN_THRESHOLD, 1.0);
|
||||
unsigned avg_max_egg_num =
|
||||
(concentration < MIN_SPAWN_CONC ? 0 : concentration * MAX_AVG_EGGS_NUM);
|
||||
uniform_int_distribution<int> eggDist(0.8 * avg_max_egg_num, 1.2 * avg_max_egg_num);
|
||||
unsigned eggs_num = eggDist(generator);
|
||||
|
||||
sim.incEggPopulation(eggs_num);
|
||||
|
||||
uniform_int_distribution<int> hatchDist(0.6 * HATCH_TM, 1.4 * HATCH_TM);
|
||||
for(unsigned e=0; e < eggs_num; e++){
|
||||
unsigned hatchIn = hatchDist(generator);
|
||||
sim.scheduleEvent(new hatchEvent(eventTime + hatchIn, generator));
|
||||
}
|
||||
unsigned nextSeasonIn = round((eventTime + 365)/(double)365)*365 - eventTime;
|
||||
uniform_int_distribution<int> spawnDist(nextSeasonIn - 30, nextSeasonIn + 30);
|
||||
unsigned spawningIn = spawnDist(generator);
|
||||
|
||||
if(afish->getRemainingLifeExpectancy(eventTime) < spawningIn){
|
||||
sim.scheduleEvent(new deathEvent(eventTime + afish->getRemainingLifeExpectancy(eventTime), afish));
|
||||
}else{
|
||||
sim.scheduleEvent(new spawnEvent(eventTime + spawningIn, afish, generator));
|
||||
}
|
||||
}
|
||||
|
||||
void spawnEvent::withdrawEvent () {
|
||||
if(afish->isCaught()){
|
||||
delete afish;
|
||||
afish = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void matureEvent::processEvent (Simulation& sim) {
|
||||
if(afish->isCaught()){
|
||||
delete afish;
|
||||
afish = nullptr;
|
||||
return;
|
||||
}
|
||||
afish->makeAdult(eventTime);
|
||||
sim.decJuvenilePopulation();
|
||||
sim.incAdultPopulation();
|
||||
|
||||
unsigned nextSeasonIn = round((eventTime + 365)/(double)365)*365 - eventTime;
|
||||
uniform_int_distribution<int> spawnDist(nextSeasonIn - 30, nextSeasonIn + 30);
|
||||
unsigned spawningIn = spawnDist(generator);
|
||||
|
||||
if(afish->getRemainingLifeExpectancy(eventTime) < spawningIn)
|
||||
sim.scheduleEvent(new deathEvent(eventTime + afish->getRemainingLifeExpectancy(eventTime), afish));
|
||||
else
|
||||
sim.scheduleEvent(new spawnEvent(eventTime + spawningIn, afish, generator));
|
||||
}
|
||||
|
||||
void matureEvent::withdrawEvent () {
|
||||
if(afish->isCaught()){
|
||||
delete afish;
|
||||
afish= nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void deathEvent::processEvent (Simulation& sim){
|
||||
if(afish->isCaught()){
|
||||
delete afish;
|
||||
afish = nullptr;
|
||||
return;
|
||||
}
|
||||
if(afish->isJuvenile()){
|
||||
sim.decJuvenilePopulation();
|
||||
} else if(afish->isAdult()) {
|
||||
sim.decAdultPopulation();
|
||||
}
|
||||
afish->makeDead();
|
||||
}
|
||||
|
||||
void deathEvent::withdrawEvent (){
|
||||
if(afish->isCaught()){
|
||||
delete afish;
|
||||
afish=nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void harvestEvent::processEvent (Simulation& sim) {
|
||||
sim.harvestTonnageNow(LANDING,generator);
|
||||
sim.scheduleEvent(new harvestEvent(eventTime + HARVEST_PERIOD, generator));
|
||||
}
|
||||
|
||||
void printEvent::processEvent (Simulation& sim) {
|
||||
file << eventTime
|
||||
<< '\t' << sim.getEggPopulation()
|
||||
<< '\t' << sim.getJuvenilePopulation()
|
||||
<< '\t' << sim.getAdultPopulation()
|
||||
<< '\t' << sim.getJuvenilePopulation() + sim.getAdultPopulation()
|
||||
<< endl;
|
||||
|
||||
cout << eventTime
|
||||
<< '\t' << sim.getEggPopulation()
|
||||
<< '\t' << sim.getJuvenilePopulation()
|
||||
<< '\t' << sim.getAdultPopulation()
|
||||
<< '\t' << sim.getJuvenilePopulation() + sim.getAdultPopulation()
|
||||
<< endl;
|
||||
|
||||
sim.scheduleEvent(new printEvent(eventTime + PRINT_PERIOD, file));
|
||||
}
|
80
Event.h
Executable file
80
Event.h
Executable file
@ -0,0 +1,80 @@
|
||||
#ifndef EVENT_H
|
||||
#define EVENT_H
|
||||
|
||||
#include "Fish.h"
|
||||
#include "config.h"
|
||||
#include <fstream>
|
||||
#include <random>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Simulation;
|
||||
|
||||
class Event {
|
||||
public:
|
||||
Event (unsigned t) : eventTime(t){ }
|
||||
virtual ~Event(){}
|
||||
virtual void processEvent (Simulation&) = 0;
|
||||
virtual void withdrawEvent() = 0;
|
||||
const unsigned eventTime;
|
||||
};
|
||||
|
||||
struct EventComparator {
|
||||
bool operator() (const Event * left, const Event * right) const {
|
||||
return left->eventTime > right->eventTime;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class hatchEvent : public Event {
|
||||
mt19937& generator;
|
||||
public:
|
||||
hatchEvent (unsigned t, mt19937& gen) : Event(t), generator(gen) {}
|
||||
virtual void processEvent (Simulation& sim);
|
||||
virtual void withdrawEvent(){}
|
||||
};
|
||||
|
||||
class spawnEvent : public Event {
|
||||
Fish* afish;
|
||||
mt19937& generator;
|
||||
public:
|
||||
spawnEvent (unsigned t, Fish* _afish, mt19937& gen) : Event(t), afish(_afish), generator(gen){}
|
||||
virtual void processEvent (Simulation& sim);
|
||||
virtual void withdrawEvent();
|
||||
};
|
||||
|
||||
class matureEvent : public Event {
|
||||
Fish* afish;
|
||||
mt19937& generator;
|
||||
public:
|
||||
matureEvent (unsigned t, Fish* _afish, mt19937& gen) : Event(t), afish(_afish),generator(gen){}
|
||||
virtual void processEvent (Simulation& sim);
|
||||
virtual void withdrawEvent();
|
||||
};
|
||||
|
||||
|
||||
class deathEvent : public Event {
|
||||
Fish* afish;
|
||||
public:
|
||||
deathEvent (unsigned t, Fish* _afish) : Event(t), afish(_afish) {}
|
||||
virtual void processEvent (Simulation& sim);
|
||||
virtual void withdrawEvent();
|
||||
};
|
||||
|
||||
class harvestEvent : public Event {
|
||||
mt19937& generator;
|
||||
public:
|
||||
harvestEvent (unsigned t, mt19937& gen): Event(t), generator(gen) {}
|
||||
virtual void processEvent (Simulation& sim);
|
||||
virtual void withdrawEvent() {}
|
||||
};
|
||||
|
||||
class printEvent : public Event {
|
||||
ofstream& file;
|
||||
public:
|
||||
printEvent (unsigned t, ofstream& f) : Event(t), file(f){}
|
||||
virtual void processEvent (Simulation& sim);
|
||||
virtual void withdrawEvent() {}
|
||||
};
|
||||
|
||||
#endif // EVENT_H
|
92
Fish.cpp
Executable file
92
Fish.cpp
Executable file
@ -0,0 +1,92 @@
|
||||
#include "Fish.h"
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
|
||||
unsigned Fish::counter= 0;
|
||||
|
||||
Fish::Fish(unsigned time, unsigned _lifeExpectancy):
|
||||
hatchedTime(time),lifeExpectancy(_lifeExpectancy), id(++counter){
|
||||
}
|
||||
|
||||
void Fish::makeAdult(unsigned t){
|
||||
assert(phase==JuvenilePhase && " making a non juvenile fish adult");
|
||||
adultTime = t;
|
||||
phase = AdultPhase;
|
||||
}
|
||||
|
||||
void Fish::makeDead(){
|
||||
bool aliveFree = isJuvenile() || isAdult();
|
||||
assert(aliveFree && " killing a dead or caught fish");
|
||||
phase = DeadPhase;
|
||||
}
|
||||
|
||||
void Fish::makeCaught(){
|
||||
bool aliveFree = isJuvenile() || isAdult();
|
||||
assert(aliveFree && " catching a dead or caught fish");
|
||||
phase = CaughtPhase;
|
||||
}
|
||||
|
||||
|
||||
bool Fish::isJuvenile()const{
|
||||
return phase == JuvenilePhase;
|
||||
}
|
||||
|
||||
bool Fish::isAdult()const{
|
||||
return phase == AdultPhase;
|
||||
}
|
||||
|
||||
bool Fish::isCaught()const{
|
||||
return phase == CaughtPhase;
|
||||
}
|
||||
|
||||
bool Fish::isDead()const{
|
||||
return phase == DeadPhase;
|
||||
}
|
||||
|
||||
unsigned Fish::getRemainingLifeExpectancy(unsigned now)const{
|
||||
if (now > (lifeExpectancy + hatchedTime))
|
||||
return 0;
|
||||
return lifeExpectancy + hatchedTime - now;
|
||||
}
|
||||
|
||||
bool Fish::catchableNow(unsigned now)const{
|
||||
return (now - hatchedTime) > MIN_CATCHABLE_AGE;
|
||||
}
|
||||
|
||||
|
||||
unsigned Fish::getWeightOnCatch(unsigned tm)const{
|
||||
unsigned age = tm - hatchedTime;
|
||||
return(age < MIN_KEPT_AGE? 0 : age);
|
||||
}
|
||||
|
||||
std::string Fish::print()const{
|
||||
std::stringstream rslt;
|
||||
rslt << "fish";
|
||||
switch(phase){
|
||||
case JuvenilePhase:
|
||||
rslt << "j(";
|
||||
break;
|
||||
case AdultPhase:
|
||||
rslt << "a(";
|
||||
break;
|
||||
case DeadPhase:
|
||||
rslt << "d(";
|
||||
break;
|
||||
case CaughtPhase:
|
||||
rslt << "c(";
|
||||
break;
|
||||
default:
|
||||
rslt << "x(";
|
||||
break;
|
||||
}
|
||||
rslt << id << ")(le=" << lifeExpectancy;
|
||||
rslt << ", ht=" << hatchedTime;
|
||||
rslt << ", at=" << adultTime << ")" ;
|
||||
return rslt.str();
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Fish& fish){
|
||||
out << fish.print();
|
||||
return out;
|
||||
}
|
45
Fish.h
Executable file
45
Fish.h
Executable file
@ -0,0 +1,45 @@
|
||||
#ifndef FISH_H
|
||||
#define FISH_H
|
||||
|
||||
#include "config.h"
|
||||
#include <string>
|
||||
|
||||
class Fish {
|
||||
|
||||
public:
|
||||
enum Phase {JuvenilePhase, AdultPhase, DeadPhase, CaughtPhase};
|
||||
Phase phase=JuvenilePhase;
|
||||
|
||||
unsigned hatchedTime=0;
|
||||
unsigned adultTime=0;
|
||||
unsigned lifeExpectancy=0;
|
||||
unsigned id = 0;
|
||||
static unsigned counter;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Fish(unsigned time, unsigned _lifeExpectancy);
|
||||
|
||||
void makeAdult(unsigned);
|
||||
void makeDead();
|
||||
void makeCaught();
|
||||
|
||||
|
||||
bool isJuvenile() const;
|
||||
bool isAdult()const;
|
||||
bool isCaught()const;
|
||||
bool isDead()const;
|
||||
|
||||
|
||||
|
||||
std::string print()const;
|
||||
|
||||
bool catchableNow(unsigned)const;
|
||||
unsigned getWeightOnCatch(unsigned tm)const;
|
||||
unsigned getRemainingLifeExpectancy(unsigned tm)const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Fish& fish);
|
||||
|
||||
#endif // FISH_H
|
16
MyException.h
Executable file
16
MyException.h
Executable file
@ -0,0 +1,16 @@
|
||||
#ifndef MYEXCEPTION_H
|
||||
#define MYEXCEPTION_H
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#define MYEXCEPTION(msg) MyException(msg, __FILE__, __LINE__)
|
||||
|
||||
inline void MyException(const std::string& msg,
|
||||
char* file,
|
||||
unsigned line){
|
||||
std::stringstream ss;
|
||||
ss << msg << " at " << file << ":" << line;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
#endif // MYEXCEPTION_H
|
81
MyPriorityQueue.h
Executable file
81
MyPriorityQueue.h
Executable file
@ -0,0 +1,81 @@
|
||||
// This is the second .h file you will edit
|
||||
// We have provided a skeleton for you,
|
||||
// but you must finish it as described in the spec.
|
||||
// Also remove these comments here and add your own, as well as on the members.
|
||||
// TODO: remove this comment header
|
||||
|
||||
#ifndef MY_PRIORITY_QUEUE_H
|
||||
#define MY_PRIORITY_QUEUE_H
|
||||
|
||||
#include "MyVector.h"
|
||||
#include "MyException.h"
|
||||
|
||||
|
||||
template <typename T, typename C>
|
||||
class MyPriorityQueue
|
||||
{
|
||||
MyVector<T> vector_array;
|
||||
C strictly_larger_operator;
|
||||
|
||||
public:
|
||||
MyPriorityQueue();
|
||||
|
||||
~MyPriorityQueue();
|
||||
|
||||
void push(const T& t);
|
||||
|
||||
T top()const;
|
||||
|
||||
void pop();
|
||||
|
||||
bool empty()const;
|
||||
|
||||
unsigned size() const;
|
||||
|
||||
private:
|
||||
// Other private members?
|
||||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
MyPriorityQueue<T,C>::MyPriorityQueue(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template <typename T, typename C>
|
||||
MyPriorityQueue<T,C>::~MyPriorityQueue(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template <typename T, typename C>
|
||||
void MyPriorityQueue<T,C>::push(const T& t){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template <typename T, typename C>
|
||||
T MyPriorityQueue<T,C>::top()const{
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template <typename T, typename C>
|
||||
void MyPriorityQueue<T,C>::pop(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template <typename T, typename C>
|
||||
bool MyPriorityQueue<T,C>::empty()const{
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template <typename T, typename C>
|
||||
unsigned MyPriorityQueue<T,C>::size()const{
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
#endif // MY_PRIORITY_QUEUE_H
|
128
MyVector.h
Executable file
128
MyVector.h
Executable file
@ -0,0 +1,128 @@
|
||||
// This is the first .h file you will edit
|
||||
// We have provided a skeleton for you,
|
||||
// but you must finish it as described in the spec.
|
||||
// Also remove these comments here and add your own, as well as on the members.
|
||||
// TODO: remove this comment header
|
||||
|
||||
#ifndef MY_VECTOR_H
|
||||
#define MY_VECTOR_H
|
||||
|
||||
#include "MyException.h"
|
||||
|
||||
template <typename T>
|
||||
class MyVector
|
||||
{
|
||||
|
||||
public:
|
||||
MyVector();
|
||||
|
||||
~MyVector();
|
||||
|
||||
MyVector(const MyVector& other);
|
||||
|
||||
MyVector& operator =(const MyVector& other);
|
||||
|
||||
|
||||
void push_back(const T&);
|
||||
|
||||
void pop_back();
|
||||
|
||||
T& operator[](unsigned i);
|
||||
|
||||
const T& operator[](unsigned i)const;
|
||||
|
||||
bool empty()const;
|
||||
|
||||
T* begin();
|
||||
|
||||
T* end();
|
||||
|
||||
void clear();
|
||||
|
||||
unsigned size()const;
|
||||
|
||||
private:
|
||||
|
||||
// private members?
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
MyVector<T>::MyVector(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MyVector<T>::~MyVector(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MyVector<T>::MyVector(const MyVector& other){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MyVector<T>& MyVector<T>::operator =(const MyVector& other){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MyVector<T>::push_back(const T& e){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MyVector<T>::pop_back(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& MyVector<T>::operator[](unsigned i){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& MyVector<T>::operator[](unsigned i)const{
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool MyVector<T>::empty()const{
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MyVector<T>::clear(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned MyVector<T>::size()const{
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* MyVector<T>::begin(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* MyVector<T>::end(){
|
||||
// TODO: replace the code below with your code for this member
|
||||
MYEXCEPTION("unimplemented method");
|
||||
}
|
||||
|
||||
#endif // MY_VECTOR_H
|
2
README.md
Executable file
2
README.md
Executable file
@ -0,0 +1,2 @@
|
||||
See: labb 6 @ https://www.ida.liu.se/~TDDD86/info/labs.sv.shtml
|
||||
|
120
Simulation.cpp
Executable file
120
Simulation.cpp
Executable file
@ -0,0 +1,120 @@
|
||||
#include "Simulation.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
Simulation::Simulation():
|
||||
simulationTime(0),eggPopulation(0),
|
||||
juvenilePopulation(0),adultPopulation(0){
|
||||
}
|
||||
|
||||
|
||||
Simulation::~Simulation(){
|
||||
assert(eventQueue.empty());
|
||||
for(unsigned i=0; i < allTheFish.size(); ++i){
|
||||
assert(! allTheFish[i]->isCaught());
|
||||
delete allTheFish[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Simulation::run (){
|
||||
while (! eventQueue.empty ()){
|
||||
Event * nextEvent = eventQueue.top ();
|
||||
eventQueue.pop ();
|
||||
if(simulationTime < SIMULATION_HORIZON){
|
||||
simulationTime = nextEvent->eventTime;
|
||||
nextEvent->processEvent(*this);
|
||||
}else{
|
||||
nextEvent->withdrawEvent();
|
||||
}
|
||||
delete nextEvent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Simulation::scheduleEvent (Event * newEvent){
|
||||
eventQueue.push(newEvent);
|
||||
}
|
||||
|
||||
|
||||
void Simulation::harvestTonnageNow(unsigned target, mt19937& generator){
|
||||
// MyVector<Fish*> stillAlive;
|
||||
std::vector<Fish*> stillAlive;
|
||||
for(unsigned i=0; i < allTheFish.size(); ++i){
|
||||
assert(! allTheFish[i]->isCaught());
|
||||
if (allTheFish[i]->isDead()){
|
||||
delete allTheFish[i];
|
||||
} else{
|
||||
stillAlive.push_back(allTheFish[i]);
|
||||
}
|
||||
}
|
||||
allTheFish.clear();
|
||||
shuffle(stillAlive.begin(),stillAlive.end(),generator);
|
||||
unsigned landing =0;
|
||||
unsigned fish=0;
|
||||
for(; fish < stillAlive.size() && landing < target; ++fish){
|
||||
if(stillAlive[fish]->catchableNow(simulationTime)){
|
||||
//fish is large enough to be caught
|
||||
landing += stillAlive[fish]->getWeightOnCatch(simulationTime);
|
||||
if(stillAlive[fish]->isJuvenile()){
|
||||
juvenilePopulation--;
|
||||
}else if(stillAlive[fish]->isAdult()){
|
||||
adultPopulation--;
|
||||
}else{
|
||||
assert(false && "should not get here");
|
||||
}
|
||||
stillAlive[fish]->makeCaught();
|
||||
}else{
|
||||
allTheFish.push_back(stillAlive[fish]);
|
||||
}
|
||||
}
|
||||
for(; fish < stillAlive.size(); ++fish){
|
||||
allTheFish.push_back(stillAlive[fish]);
|
||||
}
|
||||
}
|
||||
|
||||
void Simulation::addFish(Fish* afish){
|
||||
allTheFish.push_back(afish);
|
||||
}
|
||||
|
||||
unsigned Simulation::getEggPopulation()const{
|
||||
return eggPopulation;
|
||||
}
|
||||
|
||||
void Simulation::incEggPopulation(unsigned c){
|
||||
eggPopulation+=c;
|
||||
}
|
||||
|
||||
void Simulation::decEggPopulation(unsigned c){
|
||||
eggPopulation-=c;
|
||||
}
|
||||
|
||||
unsigned Simulation::getJuvenilePopulation()const{
|
||||
return juvenilePopulation;
|
||||
}
|
||||
|
||||
void Simulation::incJuvenilePopulation(unsigned c){
|
||||
juvenilePopulation+=c;
|
||||
}
|
||||
|
||||
void Simulation::decJuvenilePopulation(unsigned c){
|
||||
juvenilePopulation-=c;
|
||||
}
|
||||
|
||||
unsigned Simulation::getAdultPopulation()const{
|
||||
return adultPopulation;
|
||||
}
|
||||
|
||||
void Simulation::incAdultPopulation(unsigned c){
|
||||
adultPopulation+=c;
|
||||
}
|
||||
|
||||
void Simulation::decAdultPopulation(unsigned c){
|
||||
adultPopulation-=c;
|
||||
}
|
||||
|
||||
|
63
Simulation.h
Executable file
63
Simulation.h
Executable file
@ -0,0 +1,63 @@
|
||||
#ifndef SIMULATION_H
|
||||
#define SIMULATION_H
|
||||
|
||||
#include "config.h"
|
||||
#include "Event.h"
|
||||
#include "MyPriorityQueue.h"
|
||||
#include "MyVector.h"
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
class Fish;
|
||||
|
||||
class Simulation {
|
||||
|
||||
public:
|
||||
Simulation();
|
||||
|
||||
~Simulation();
|
||||
|
||||
void run ();
|
||||
|
||||
void scheduleEvent (Event*);
|
||||
|
||||
void harvestTonnageNow(unsigned, mt19937&);
|
||||
|
||||
void addFish(Fish*);
|
||||
|
||||
unsigned getEggPopulation()const;
|
||||
void incEggPopulation(unsigned c=1);
|
||||
void decEggPopulation(unsigned c=1);
|
||||
|
||||
unsigned getJuvenilePopulation()const;
|
||||
void incJuvenilePopulation(unsigned c=1);
|
||||
void decJuvenilePopulation(unsigned c=1);
|
||||
|
||||
unsigned getAdultPopulation()const;
|
||||
void incAdultPopulation(unsigned c=1);
|
||||
void decAdultPopulation(unsigned c=1);
|
||||
|
||||
|
||||
private:
|
||||
// MyPriorityQueue<Event*, EventComparator> eventQueue;
|
||||
|
||||
std::priority_queue<Event*,
|
||||
vector<Event *, allocator<Event*> >,
|
||||
EventComparator> eventQueue;
|
||||
|
||||
// MyVector<Fish*> allTheFish;
|
||||
std::vector<Fish*> allTheFish;
|
||||
|
||||
|
||||
unsigned simulationTime;
|
||||
|
||||
unsigned eggPopulation;
|
||||
unsigned juvenilePopulation;
|
||||
unsigned adultPopulation;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // SIMULATION_H
|
0
answers.txt
Executable file
0
answers.txt
Executable file
29
config.h
Executable file
29
config.h
Executable file
@ -0,0 +1,29 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
//life expectancy
|
||||
const unsigned MAX_AGE = 2000;
|
||||
const unsigned STARVE_THRESHOLD=20000;
|
||||
|
||||
const unsigned HATCH_TM = 40;
|
||||
const unsigned AVG_MATURATION_TM = 500;
|
||||
|
||||
// spawning
|
||||
const unsigned MAX_AVG_EGGS_NUM = 100;
|
||||
const double MIN_SPAWN_CONC = 0.05;
|
||||
const unsigned SPAWN_THRESHOLD= 0.05 * STARVE_THRESHOLD;
|
||||
|
||||
|
||||
// Harvesting
|
||||
const unsigned HARVEST_START= 1000;
|
||||
const unsigned HARVEST_PERIOD= 366;
|
||||
const unsigned MIN_CATCHABLE_AGE = 550;
|
||||
const unsigned MIN_KEPT_AGE = 600;
|
||||
const unsigned LANDING = 70000;
|
||||
|
||||
// Simulation: duration and printing
|
||||
const unsigned SIMULATION_HORIZON=8000;
|
||||
const unsigned PRINT_PERIOD=20;
|
||||
|
||||
|
||||
#endif // CONFIG_H
|
8
fisher.pro
Executable file
8
fisher.pro
Executable file
@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += console c++11
|
||||
CONFIG -= app_bundle
|
||||
CONFIG -= qt
|
||||
|
||||
SOURCES = Event.cpp Fish.cpp main.cpp Simulation.cpp
|
||||
|
||||
HEADERS = $$files(*.h,true)
|
77
main.cpp
Executable file
77
main.cpp
Executable file
@ -0,0 +1,77 @@
|
||||
|
||||
#include "Event.h"
|
||||
#include "Fish.h"
|
||||
#include "Simulation.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
void show();
|
||||
|
||||
int main()
|
||||
{
|
||||
ofstream file("output.dat");
|
||||
|
||||
random_device rd;
|
||||
mt19937 generator(rd());
|
||||
|
||||
|
||||
Simulation sim;
|
||||
sim.scheduleEvent(new printEvent (0,file));
|
||||
for(unsigned i=0; i < 100; ++i){
|
||||
Event* e = new hatchEvent(0,generator);
|
||||
sim.scheduleEvent(e);
|
||||
}
|
||||
sim.incEggPopulation(100);
|
||||
sim.scheduleEvent(new harvestEvent(HARVEST_START,generator));
|
||||
auto comp_start_time = chrono::high_resolution_clock::now();
|
||||
sim.run();
|
||||
auto comp_end_time = chrono::high_resolution_clock::now();
|
||||
std::cout << "simulation took: "
|
||||
<< chrono::duration_cast<chrono::seconds>(comp_end_time - comp_start_time).count()
|
||||
<< " seconds."
|
||||
<< std::endl;
|
||||
file.close();
|
||||
|
||||
show();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void show(){
|
||||
ofstream driver;
|
||||
driver.open("output.driver", ofstream::out);
|
||||
driver << "set terminal wxt size 410,250 enhanced font 'Verdana,9' persist\n"
|
||||
<< "set style line 11 lc rgb '#808080' lt 1\n"
|
||||
<< "set border 3 back ls 11\n"
|
||||
<< "set tics nomirror \n"
|
||||
<< "set style line 12 lc rgb '#808080' lt 0 lw 1\n"
|
||||
<< "set grid back ls 12\n"
|
||||
<< "set style line 1 lc rgb '#000000' pt 0 ps 1 lt 1 lw 1 # --- red\n"
|
||||
<< "set style line 2 lc rgb '#5e9c36' pt 0 ps 1 lt 1 lw 1 # --- green\n"
|
||||
<< "set style line 3 lc rgb '#0000ff' pt 0 ps 1 lt 1 lw 1 # --- blue\n"
|
||||
<< "set style line 4 lc rgb '#99004c' pt 0 ps 1 lt 1 lw 1 # --- purple\n"
|
||||
<< "set key top left\n"
|
||||
<< "set xlabel 'time in days'\n"
|
||||
<< "set ylabel 'population'\n"
|
||||
<< "set xrange [0:" << SIMULATION_HORIZON <<"]\n"
|
||||
<< "set yrange [0:" << int(STARVE_THRESHOLD * 1.3) << "]\n"
|
||||
<< "plot 'output.dat' u 1:3 t 'juvenile' w lp ls 2, \\\n"
|
||||
<< " 'output.dat' u 1:4 t 'adult' w lp ls 3";
|
||||
driver.close();
|
||||
|
||||
#ifdef WIN32
|
||||
const string exe = "C:\\Progra~1\\gnuplot\\bin\\gnuplot.exe";
|
||||
#else
|
||||
const string exe = "gnuplot";
|
||||
#endif
|
||||
const string cmd = exe + " " + "output.driver";
|
||||
system(cmd.c_str());
|
||||
}
|
322
test-harness-myprio.cpp
Executable file
322
test-harness-myprio.cpp
Executable file
@ -0,0 +1,322 @@
|
||||
/*************************************************
|
||||
* File: test-harness-myprio.cpp
|
||||
*
|
||||
* File containing several test cases that can be
|
||||
* used to verify the correctness of the MyPriorityQueue
|
||||
* implementation. You should make sure to do your
|
||||
* own testing in addition to ensuring that the test
|
||||
* cases here pass.
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <cstdarg>
|
||||
#include <set>
|
||||
#include "MyPriorityQueue.h"
|
||||
using namespace std;
|
||||
|
||||
/* These flags control which tests will be run. Initially, only the
|
||||
* basic test will be executed. As you complete more and more parts
|
||||
* of the implementation, you will want to turn more and more of these
|
||||
* flags on.
|
||||
*/
|
||||
#define BasicMyPriorityQueueTestEnabled 1
|
||||
#define ModerateMyPriorityQueueTestEnabled 1
|
||||
|
||||
#define BasicCopyTestEnabled 0
|
||||
#define ModerateCopyTestEnabled 0
|
||||
|
||||
|
||||
/* Utility function that pauses until the user hits ENTER. */
|
||||
void pressEnterToContinue() {
|
||||
/* Use getline to stall until receiving input. */
|
||||
string line;
|
||||
getline(cin, line);
|
||||
}
|
||||
|
||||
/* This function is what the test suite uses to ensure that the MyPriorityQueue works
|
||||
* correctly. It takes as parameters an expression and description, along
|
||||
* with a file and line number, then checks whether the condition is true.
|
||||
* If so, it prints that the test passed. Otherwise, it reports that the
|
||||
* test fails and points the caller to the proper file and line.
|
||||
*/
|
||||
void doCheckCondition(bool expr, const string& rationale, const string& file, int line) {
|
||||
/* It worked! Congrats. */
|
||||
if (expr) {
|
||||
cout << "PASS: " << rationale << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Uh oh! The test failed! */
|
||||
cout << "FAIL: " << rationale << endl;
|
||||
cout << " Error at " << file << ", line " << line << endl;
|
||||
cout << " (ENTER to continue)" << endl;
|
||||
|
||||
/* Pause so that the test fail stands out. */
|
||||
pressEnterToContinue();
|
||||
}
|
||||
|
||||
/* Reports that an unexpected error occurred that caused a test to fail. */
|
||||
void failTest(const exception& e) {
|
||||
cerr << "TEST FAILED: Unexpected exception: " << e.what() << endl;
|
||||
pressEnterToContinue();
|
||||
}
|
||||
|
||||
/* This macro takes in an expression and a string, then invokes
|
||||
* doCheckCondition passing in the arguments along with the file
|
||||
* and line number on which the macro was called. This makes it
|
||||
* easier to track down the source of bugs if a test case should
|
||||
* fail.
|
||||
*/
|
||||
#define checkCondition(expr, rationale) doCheckCondition(expr, rationale, __FILE__, __LINE__)
|
||||
|
||||
/* Utility function to delimit the start and end of test cases. */
|
||||
void printBanner(const string& header) {
|
||||
cout << "\nBeginning test: " << header << endl;
|
||||
cout << setw(40) << setfill('-') << "" << setfill(' ') << endl;
|
||||
}
|
||||
|
||||
/* Utility function to signal that a test isn't begin run. */
|
||||
void testDisabled(const string& header) {
|
||||
cout << "== Test " << header << " NOT RUN: press ENTER to continue ==" << endl;
|
||||
|
||||
/* Pause for the user to hit enter. */
|
||||
pressEnterToContinue();
|
||||
}
|
||||
|
||||
/* Utility function to signal the end of a test. */
|
||||
void endTest() {
|
||||
cout << "== end of test: press ENTER to continue ==" << endl;
|
||||
pressEnterToContinue();
|
||||
}
|
||||
|
||||
struct comp{
|
||||
bool operator()(int l, int r) const{
|
||||
return l > r;
|
||||
}
|
||||
};
|
||||
|
||||
/* Basic test: Can we build an empty priority queue? */
|
||||
void basicMyPriorityQueueTest() try {
|
||||
#if BasicMyPriorityQueueTestEnabled
|
||||
printBanner("Basic MyPriorityQueue Test");
|
||||
|
||||
/* Construct the MyPriorityQueue. */
|
||||
MyPriorityQueue<int,comp> prio;
|
||||
checkCondition(true, "MyPriorityQueue construction completed.");
|
||||
|
||||
/* Check basic properties of the MyPriorityQueue. */
|
||||
checkCondition(prio.size() == 0, "New prio queue has no elements.");
|
||||
checkCondition(prio.empty(), "prio queue is empty.");
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("BasicMyPriorityQueueTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
/* A trickier test that involves a data set .
|
||||
*/
|
||||
void moderateMyPriorityQueueTest() try {
|
||||
#if ModerateMyPriorityQueueTestEnabled
|
||||
printBanner("Moderate MyPriorityQueue Test");
|
||||
|
||||
MyPriorityQueue<int,comp> prio;
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
prio.push(i);
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
prio.push(7-i);
|
||||
|
||||
/* Check that basic properties hold. */
|
||||
checkCondition(prio.size() == 16, "New prio has the right number of elements.");
|
||||
checkCondition(!prio.empty(), "prio queue is nonempty.");
|
||||
|
||||
/* Make sure that the values of these points are correct. */
|
||||
for (size_t i = 0; i < 16; ++i){
|
||||
checkCondition(prio.size() == 16-i, "prio has the right number of elements.");
|
||||
int current = prio.top();
|
||||
checkCondition(current == i/2, "top prio element is correct.");
|
||||
prio.pop();
|
||||
}
|
||||
|
||||
checkCondition(prio.empty(), "prio is empty.");
|
||||
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("moderateMyPriorityQueueTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Tests basic behavior of the copy constructor and assignment operator. */
|
||||
void basicCopyTest() try {
|
||||
#if BasicCopyTestEnabled
|
||||
printBanner("Basic Copy Test");
|
||||
|
||||
/* For simplicity, we'll use one-dimensional MyPriorityQueues in this step. */
|
||||
MyPriorityQueue<int, comp> one;
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
one.push(i);
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
one.push(9 - i);
|
||||
|
||||
|
||||
{
|
||||
/* Create a clone of one and confirm that everything copied correctly.
|
||||
* This uses the copy constructor.
|
||||
*/
|
||||
MyPriorityQueue<int,comp> clone = one;
|
||||
|
||||
/* Basic checks. */
|
||||
checkCondition(one.size() == clone.size(), "clone has the same number of elements as original one.");
|
||||
checkCondition(one.empty() == clone.empty(), "clone and one agree on emptiness.");
|
||||
|
||||
/* Check that everything in one is there. */
|
||||
for (size_t i = 0; i < 20; ++i){
|
||||
checkCondition(clone.size() == 20-i, "clone has the right number of elements.");
|
||||
int current = clone.top();
|
||||
checkCondition(current == i/2, "top clone element is correct.");
|
||||
clone.pop();
|
||||
}
|
||||
|
||||
checkCondition(clone.empty(), "clone is empty.");
|
||||
|
||||
}
|
||||
{
|
||||
/* Create a clone of one and confirm that everything copied correctly.
|
||||
* This uses the assignment operator.
|
||||
*/
|
||||
MyPriorityQueue<int,comp> clone;
|
||||
clone = one;
|
||||
|
||||
/* Check that everything in one is there. */
|
||||
for (size_t i = 0; i < 20; ++i){
|
||||
checkCondition(clone.size() == 20-i, "clone has the right number of elements.");
|
||||
int current = clone.top();
|
||||
checkCondition(current == i/2, "top clone element is correct.");
|
||||
clone.pop();
|
||||
}
|
||||
|
||||
checkCondition(clone.empty(), "clone is empty.");
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Check that everything in one is there. */
|
||||
for (size_t i = 0; i < 20; ++i){
|
||||
checkCondition(one.size() == 20-i, "After clone destructor, one has the right number of elements.");
|
||||
int current = one.top();
|
||||
checkCondition(current == i/2, "After clone destructor, top one element is correct.");
|
||||
one.pop();
|
||||
}
|
||||
|
||||
checkCondition(one.empty(), "one is empty.");
|
||||
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("BasicCopyTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
/* A more merciless test of copy behavior.. */
|
||||
void moderateCopyTest() try {
|
||||
#if BasicCopyTestEnabled
|
||||
printBanner("Moderate Copy Test");
|
||||
|
||||
MyPriorityQueue<int,comp> one;
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
one.push(i);
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
one.push(9 - i);
|
||||
|
||||
{
|
||||
/* Create a clone of one and confirm that everything copied correctly.
|
||||
* This uses the copy constructor.
|
||||
*/
|
||||
MyPriorityQueue<int,comp> clone = one;
|
||||
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
clone.push(2*(10+i));
|
||||
|
||||
/* Confirm that they didn't appear in one. */
|
||||
checkCondition(one.size() == 20, "Adding to clone does not change original one size.");
|
||||
}
|
||||
|
||||
/* Check the integrity of the original out here as well to see that the destructor didn't hose things. */
|
||||
checkCondition(one.size() == 20, "After destructor, one has original size.");
|
||||
|
||||
|
||||
|
||||
{
|
||||
/*Create a clone of one and confirm that everything copied correctly.
|
||||
* This uses the assignment operator.*/
|
||||
MyPriorityQueue<int,comp> clone;
|
||||
clone = one;
|
||||
|
||||
/* Do awful, awful things to the copy.*/
|
||||
clone = clone = (clone = clone);
|
||||
(clone = one) = clone;
|
||||
clone = clone = clone = clone = clone;
|
||||
|
||||
/* Check that everything in one is there.*/
|
||||
for (size_t i = 0; i < 20; ++i){
|
||||
checkCondition(clone.size() == 20-i, "clone has the right number of elements.");
|
||||
int current = clone.top();
|
||||
checkCondition(current == i/2, "top clone element is correct.");
|
||||
clone.pop();
|
||||
}
|
||||
|
||||
checkCondition(clone.empty(), "clone is empty.");
|
||||
|
||||
}
|
||||
|
||||
/* Check that everything in one is there.*/
|
||||
for (size_t i = 0; i < 20; ++i){
|
||||
checkCondition(one.size() == 20-i, "one has the right number of elements.");
|
||||
int current = one.top();
|
||||
checkCondition(current == i/2, "top one element is correct.");
|
||||
one.pop();
|
||||
}
|
||||
|
||||
checkCondition(one.empty(), "one is empty.");
|
||||
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("ModerateCopyTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
/* Main entry point simply runs all the tests. Note that these functions might be no-ops
|
||||
* if they are disabled by the configuration settings at the top of the program.
|
||||
*/
|
||||
int main() {
|
||||
basicMyPriorityQueueTest();
|
||||
moderateMyPriorityQueueTest();
|
||||
basicCopyTest();
|
||||
moderateCopyTest();
|
||||
|
||||
#if (BasicMyPriorityQueueTestEnabled && \
|
||||
ModerateMyPriorityQueueTestEnabled && \
|
||||
BasicCopyTestEnabled && \
|
||||
ModerateCopyTestEnabled)
|
||||
cout << "All tests completed! If they passed, you should be good to go!" << endl << endl;
|
||||
#else
|
||||
cout << "Not all tests were run. Enable the rest of the tests, then run again." << endl << endl;
|
||||
#endif
|
||||
|
||||
pressEnterToContinue();
|
||||
}
|
422
test-harness-myvector.cpp
Executable file
422
test-harness-myvector.cpp
Executable file
@ -0,0 +1,422 @@
|
||||
/*************************************************
|
||||
* File: test-harness-myvector.cpp
|
||||
*
|
||||
* File containing several test cases that can be
|
||||
* used to verify the correctness of the MyVector
|
||||
* implementation. You should make sure to do your
|
||||
* own testing in addition to ensuring that the test
|
||||
* cases here pass.
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <cstdarg>
|
||||
#include <set>
|
||||
#include "MyVector.h"
|
||||
using namespace std;
|
||||
|
||||
/* These flags control which tests will be run. Initially, only the
|
||||
* basic test will be executed. As you complete more and more parts
|
||||
* of the implementation, you will want to turn more and more of these
|
||||
* flags on.
|
||||
*/
|
||||
#define BasicMyVectorTestEnabled 1
|
||||
#define ModerateMyVectorTestEnabled 1
|
||||
#define HarderMyVectorTestEnabled 1
|
||||
#define MutatingMyVectorTestEnabled 1
|
||||
|
||||
#define ConstMyVectorTestEnabled 0
|
||||
#define BasicCopyTestEnabled 0
|
||||
#define ModerateCopyTestEnabled 0
|
||||
|
||||
|
||||
/* Utility function that pauses until the user hits ENTER. */
|
||||
void pressEnterToContinue() {
|
||||
/* Use getline to stall until receiving input. */
|
||||
string line;
|
||||
getline(cin, line);
|
||||
}
|
||||
|
||||
/* This function is what the test suite uses to ensure that the MyVector works
|
||||
* correctly. It takes as parameters an expression and description, along
|
||||
* with a file and line number, then checks whether the condition is true.
|
||||
* If so, it prints that the test passed. Otherwise, it reports that the
|
||||
* test fails and points the caller to the proper file and line.
|
||||
*/
|
||||
void doCheckCondition(bool expr, const string& rationale, const string& file, int line) {
|
||||
/* It worked! Congrats. */
|
||||
if (expr) {
|
||||
cout << "PASS: " << rationale << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Uh oh! The test failed! */
|
||||
cout << "FAIL: " << rationale << endl;
|
||||
cout << " Error at " << file << ", line " << line << endl;
|
||||
cout << " (ENTER to continue)" << endl;
|
||||
|
||||
/* Pause so that the test fail stands out. */
|
||||
pressEnterToContinue();
|
||||
}
|
||||
|
||||
/* Reports that an unexpected error occurred that caused a test to fail. */
|
||||
void failTest(const exception& e) {
|
||||
cerr << "TEST FAILED: Unexpected exception: " << e.what() << endl;
|
||||
pressEnterToContinue();
|
||||
}
|
||||
|
||||
/* This macro takes in an expression and a string, then invokes
|
||||
* doCheckCondition passing in the arguments along with the file
|
||||
* and line number on which the macro was called. This makes it
|
||||
* easier to track down the source of bugs if a test case should
|
||||
* fail.
|
||||
*/
|
||||
#define checkCondition(expr, rationale) doCheckCondition(expr, rationale, __FILE__, __LINE__)
|
||||
|
||||
/* Utility function to delimit the start and end of test cases. */
|
||||
void printBanner(const string& header) {
|
||||
cout << "\nBeginning test: " << header << endl;
|
||||
cout << setw(40) << setfill('-') << "" << setfill(' ') << endl;
|
||||
}
|
||||
|
||||
/* Utility function to signal that a test isn't begin run. */
|
||||
void testDisabled(const string& header) {
|
||||
cout << "== Test " << header << " NOT RUN: press ENTER to continue ==" << endl;
|
||||
|
||||
/* Pause for the user to hit enter. */
|
||||
pressEnterToContinue();
|
||||
}
|
||||
|
||||
/* Utility function to signal the end of a test. */
|
||||
void endTest() {
|
||||
cout << "== end of test: press ENTER to continue ==" << endl;
|
||||
pressEnterToContinue();
|
||||
}
|
||||
|
||||
/* Basic test: Can we build an empty vector and clear it? */
|
||||
void basicMyVectorTest() try {
|
||||
#if BasicMyVectorTestEnabled
|
||||
printBanner("Basic MyVector Test");
|
||||
|
||||
/* Construct the MyVector. */
|
||||
MyVector<int> vect;
|
||||
checkCondition(true, "New MyVector construction completed.");
|
||||
|
||||
/* Check basic properties of the MyVector. */
|
||||
checkCondition(vect.size() == 0, "vector has no elements.");
|
||||
checkCondition(vect.empty(), "vector is empty.");
|
||||
|
||||
/* Clear the MyVctor and check basic properties again. */
|
||||
vect.clear();
|
||||
checkCondition(vect.size() == 0, "vector has no elements.");
|
||||
checkCondition(vect.empty(), "vector is empty.");
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("BasicMyVectorTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
/* A trickier test that involves a data set and iterating through the vector with pointers.
|
||||
*/
|
||||
void moderateMyVectorTest() try {
|
||||
#if ModerateMyVectorTestEnabled
|
||||
printBanner("Moderate MyVector Test");
|
||||
|
||||
/* Build a palindrome. */
|
||||
MyVector<int> vect;
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
vect.push_back(i);
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
vect.push_back(7-i);
|
||||
|
||||
/* Check that basic properties hold. */
|
||||
checkCondition(vect.size() == 16, "New vector has the right number of elements.");
|
||||
checkCondition(!vect.empty(), "vector is nonempty.");
|
||||
|
||||
/* Make sure that the values of these points are correct. */
|
||||
int* fwd = vect.begin();
|
||||
int* bwd = vect.end();
|
||||
while(fwd != bwd){
|
||||
--bwd;
|
||||
checkCondition(*fwd == *bwd, "vector has correct values.");
|
||||
++fwd;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
vect.pop_back();
|
||||
|
||||
/* Check basic properties again. */
|
||||
checkCondition(vect.size() == 8, "vector has 8 elements.");
|
||||
checkCondition(!vect.empty(), "vector is nonempty.");
|
||||
|
||||
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
vect.pop_back();
|
||||
|
||||
/* Check basic properties again. */
|
||||
checkCondition(vect.size() == 0, "vector has no elements.");
|
||||
checkCondition(vect.empty(), "vector is empty.");
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("moderateMyVectorTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
/* This test still uses just the basic functionality, but uses larger
|
||||
* data set and index based access
|
||||
*/
|
||||
void harderMyVectorTest() try {
|
||||
#if HarderMyVectorTestEnabled
|
||||
printBanner("Harder MyVector Test");
|
||||
|
||||
MyVector<int> vect;
|
||||
for (size_t i = 0; i < 4096; ++i)
|
||||
vect.push_back(i);
|
||||
|
||||
/* Check that basic properties hold. */
|
||||
checkCondition(vect.size() == 4096, "New vector has 4096 elements.");
|
||||
checkCondition(!vect.empty(), "vector is nonempty.");
|
||||
|
||||
for (size_t i = 0; i < 2048; ++i)
|
||||
vect.pop_back();
|
||||
|
||||
/* Check basic properties again. */
|
||||
checkCondition(vect.size() == 2048, "vector has now 2048 elements.");
|
||||
checkCondition(!vect.empty(), "vector is nonempty.");
|
||||
|
||||
|
||||
for (size_t i = 0; i < 2048; ++i)
|
||||
vect.push_back(-i);
|
||||
|
||||
/* Check that basic properties hold. */
|
||||
checkCondition(vect.size() == 4096, "vector has now 4096 elements.");
|
||||
checkCondition(!vect.empty(), "vector is nonempty.");
|
||||
|
||||
/* Clear the MyVctor and check basic properties again. */
|
||||
vect.clear();
|
||||
checkCondition(vect.size() == 0, "vector has no elements.");
|
||||
checkCondition(vect.empty(), "vector is empty.");
|
||||
|
||||
for (size_t i = 0; i < 4096; ++i)
|
||||
vect.push_back(i);
|
||||
|
||||
/* Check that basic properties hold. */
|
||||
checkCondition(vect.size() == 4096, "vector has again 4096 elements.");
|
||||
checkCondition(!vect.empty(), "vector is nonempty.");
|
||||
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("HarderMyVectorTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
|
||||
/* This test actively mutates the elements of the MyVector using
|
||||
* operator[]. If you are failing this test, check to make sure
|
||||
* that your implementation of operator[] correctly allows for
|
||||
* mutation.
|
||||
*/
|
||||
void mutatingMyVectorTest() try {
|
||||
#if MutatingMyVectorTestEnabled
|
||||
printBanner("Mutating MyVector Test");
|
||||
|
||||
MyVector<int> vect;
|
||||
for (size_t i = 0; i < 16; ++i)
|
||||
vect.push_back(i);
|
||||
|
||||
/* Check that basic properties hold. */
|
||||
checkCondition(vect.size() == 16, "New vector has 16 elements.");
|
||||
checkCondition(!vect.empty(), "vector is nonempty.");
|
||||
|
||||
for (size_t i = 0; i < 16; ++i)
|
||||
vect[i] = vect[i] + 1;
|
||||
|
||||
for (size_t i = 0; i < 16; ++i)
|
||||
checkCondition(vect[i] == i + 1, "updated vector has correct values.");
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("mutatingMyVectorTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
|
||||
/* A basic test that creates a const MyVector and a non-const MyVector to ensure
|
||||
* the class still compiles properly. It also tests the const version of
|
||||
* [] is working correctly on the basic MyVector tests.
|
||||
*/
|
||||
void constMyVectorTest() try {
|
||||
#if ConstMyVectorTestEnabled
|
||||
printBanner("Const MyVector Test");
|
||||
|
||||
MyVector<int> vect;
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
vect.push_back(i);
|
||||
|
||||
/* Check that the code compiles for the non-const version. */
|
||||
vect.size();
|
||||
vect.empty();
|
||||
vect[3]=10;
|
||||
|
||||
const MyVector<int>& const_vect = vect;
|
||||
|
||||
/* Check that the code compiles for the const version. */
|
||||
const_vect.size();
|
||||
const_vect.empty();
|
||||
const_vect[3];
|
||||
|
||||
checkCondition(true, "Const code compiles.");
|
||||
|
||||
/* Run the basic vect tests using a const vect. */
|
||||
checkCondition(const_vect[0]==0, "const_vect has element zero.");
|
||||
checkCondition(const_vect[1]==1, "const_vect has element one.");
|
||||
checkCondition(const_vect[2]==2, "const_vect has element two.");
|
||||
checkCondition(const_vect[3]==10, "const_vect has element ten.");
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("ConstMyVectorTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
cout << "Note: vect lookup failed, but const code compiles." << endl;
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
|
||||
/* Tests basic behavior of the copy constructor and assignment operator. */
|
||||
void basicCopyTest() try {
|
||||
#if BasicCopyTestEnabled
|
||||
printBanner("Basic Copy Test");
|
||||
|
||||
MyVector<int> one;
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
one.push_back(2*i);
|
||||
|
||||
{
|
||||
/* Create a clone of one and confirm that everything copied correctly.
|
||||
* This uses the copy constructor.
|
||||
*/
|
||||
MyVector<int> clone = one;
|
||||
|
||||
/* Basic checks. */
|
||||
checkCondition(one.size() == clone.size(), "clone has the same number of elements as one.");
|
||||
checkCondition(one.empty() == clone.empty(), "clone and one agree on emptiness.");
|
||||
|
||||
/* Check that everything in one is there. */
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
checkCondition(clone[i]==2*i, "Element from one present in clone.");
|
||||
|
||||
}
|
||||
{
|
||||
/* Create a clone of one and confirm that everything copied correctly.
|
||||
* This uses the assignment operator.
|
||||
*/
|
||||
MyVector<int> clone;
|
||||
clone = one;
|
||||
|
||||
/* Basic checks. */
|
||||
checkCondition(one.size() == clone.size(), "clone has the same number of elements as the one.");
|
||||
checkCondition(one.empty() == clone.empty(), "clone and one agree on emptiness.");
|
||||
|
||||
/* Check that everything in one is there. */
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
checkCondition(clone[i]==2*i, "Element from one present in clone.");
|
||||
}
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("BasicCopyTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
/* A more merciless test of copy behavior.. */
|
||||
void moderateCopyTest() try {
|
||||
#if BasicCopyTestEnabled
|
||||
printBanner("Moderate Copy Test");
|
||||
|
||||
MyVector<int> one;
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
one.push_back(2*i);
|
||||
|
||||
{
|
||||
/* Create a clone of one and confirm that everything copied correctly.
|
||||
* This uses the copy constructor.
|
||||
*/
|
||||
MyVector<int> clone = one;
|
||||
|
||||
/* Add odd numbers to the clone. */
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
clone.push_back(2*(10+i));
|
||||
|
||||
checkCondition(one.size() == 10, "Adding to clone did not change one size.");
|
||||
}
|
||||
|
||||
/* Check the integrity of the original out here as well to see that the destructor didn't hose things. */
|
||||
checkCondition(one.size() == 10, "After clone destructor, one has original size.");
|
||||
for (size_t i = 0; i < 10; ++i) {
|
||||
checkCondition(one[i]==2*i, "After clone destructor, one contains same as original.");
|
||||
}
|
||||
|
||||
{
|
||||
/* Create a clone of one and confirm that everything copied correctly.
|
||||
* This uses the assignment operator.
|
||||
*/
|
||||
MyVector<int> clone;
|
||||
clone = one;
|
||||
|
||||
/* Do awful, awful things to the copy. */
|
||||
clone = clone = (clone = clone);
|
||||
(clone = one) = clone;
|
||||
clone = clone = clone = clone = clone;
|
||||
}
|
||||
|
||||
endTest();
|
||||
#else
|
||||
testDisabled("ModerateCopyTest");
|
||||
#endif
|
||||
} catch (const exception& e) {
|
||||
failTest(e);
|
||||
}
|
||||
|
||||
/* Main entry point simply runs all the tests. Note that these functions might be no-ops
|
||||
* if they are disabled by the configuration settings at the top of the program.
|
||||
*/
|
||||
int main() {
|
||||
basicMyVectorTest();
|
||||
moderateMyVectorTest();
|
||||
harderMyVectorTest();
|
||||
mutatingMyVectorTest();
|
||||
constMyVectorTest();
|
||||
|
||||
basicCopyTest();
|
||||
moderateCopyTest();
|
||||
|
||||
#if (BasicMyVectorTestEnabled && \
|
||||
ModerateMyVectorTestEnabled && \
|
||||
HarderMyVectorTestEnabled && \
|
||||
MutatingMyVectorTestEnabled && \
|
||||
ConstMyVectorTestEnabled && \
|
||||
BasicCopyTestEnabled && \
|
||||
ModerateCopyTestEnabled)
|
||||
cout << "All tests completed! If they passed, you should be good to go!" << endl << endl;
|
||||
#else
|
||||
cout << "Not all tests were run. Enable the rest of the tests, then run again." << endl << endl;
|
||||
#endif
|
||||
|
||||
pressEnterToContinue();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user