220 lines
5.6 KiB
C++
220 lines
5.6 KiB
C++
#include "Assignment.h"
|
|
#include "structures/Center.h"
|
|
#include <iostream>
|
|
|
|
float Assignment::cost()
|
|
{
|
|
if (this->getCompetenceTotal() == 0) return 1;
|
|
return 1.f / this->getCompetenceTotal();
|
|
}
|
|
|
|
int Assignment::getPreviousId()
|
|
{
|
|
return this->getPreviousId(this->missions.size());
|
|
}
|
|
|
|
int Assignment::getPreviousId(int index)
|
|
{
|
|
int id = 0;
|
|
if (index == 0) // if no missions have been assigned, the center will be the first location
|
|
id = this->employee->center->id;
|
|
else // else use the latest mission
|
|
id = this->missions[index-1]->id;
|
|
return id;
|
|
}
|
|
|
|
Mission* Assignment::getLastMission(int day)
|
|
{
|
|
Mission* last = nullptr;
|
|
for (Mission* mission : this->missions)
|
|
{
|
|
if (mission->day == day && (last == nullptr || last->end <= mission->start))
|
|
last = mission;
|
|
}
|
|
return last;
|
|
}
|
|
|
|
MissionList* Assignment::getMissions(int day)
|
|
{
|
|
MissionList* list = new MissionList {};
|
|
for (Mission* mission : this->missions)
|
|
{
|
|
if (mission->day == day)
|
|
list->push_back(mission);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
// TODO: Make this maintain a sorted list, done
|
|
void Assignment::addMission(Mission* mission)
|
|
{
|
|
// Find index of where to insert
|
|
int index = 0;
|
|
for (index; index < this->missions.size(); index++)
|
|
{
|
|
Mission* m = this->missions[index];
|
|
if (mission->day > m->day)
|
|
continue;
|
|
else if (mission->day < m->day)
|
|
break;
|
|
|
|
if (m->day == mission->day)
|
|
{
|
|
if (m->start > mission->end)
|
|
{ // m starts after mission, insert mission before m
|
|
break;
|
|
}
|
|
else if(mission->start > m->end)
|
|
{ // mission starts after m ends, insert after m
|
|
index++;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error("No free slots for mission");
|
|
}
|
|
}
|
|
}
|
|
|
|
this->missions.insert(this->missions.begin() + index, mission);
|
|
}
|
|
|
|
Mission* Assignment::removeMission(int i)
|
|
{
|
|
Mission* mission = this->missions[i];
|
|
this->missions.erase(this->missions.begin() + i);
|
|
return mission;
|
|
}
|
|
|
|
// TODO: Improve these functions to account for the time
|
|
void Assignment::replaceMission(int i, MissionList* missions)
|
|
{
|
|
Mission* oldMission = this->removeMission(i); // this->missions[i];
|
|
std::cout << "Removing: "; oldMission->print();
|
|
/*std::cout << this->getTotalWorkTime() << "/" << Employee::MaxWorkTimeWeek << " " << this->getWorkTime(oldMission->day) << "/" << Employee::MaxWorkTime << "\n";
|
|
for (Mission* m : *missions)
|
|
{
|
|
if (m->day == oldMission->day)
|
|
m->print();
|
|
}*/
|
|
//this->missions.erase(this->missions.begin() + i);
|
|
|
|
Mission* mission = NULL;
|
|
int index = this->getSuitableMission(oldMission->day, missions, &mission);
|
|
// Even if a mission isn't available, remove the mission and put it back into the available mission pool
|
|
missions->push_back(oldMission);
|
|
|
|
// Sometimes there just aren't any available missions for the employee's profession
|
|
if (index == -1)
|
|
return;
|
|
this->missions.push_back(mission);
|
|
missions->erase(missions->begin() + index);
|
|
}
|
|
|
|
int Assignment::getSuitableMission(int day, MissionList* missions, Mission** mission)
|
|
{
|
|
MissionList* list = this->getSuitableMissions(day, missions);
|
|
if (list->size() == 0)
|
|
return -1;
|
|
int index = rand() % list->size();
|
|
*mission = (*list)[index];
|
|
return index;
|
|
}
|
|
|
|
MissionList* Assignment::getSuitableMissions(int day, MissionList* missions)
|
|
{
|
|
MissionList* list = new MissionList {};
|
|
for (int index = 0; index < missions->size(); index++)
|
|
{
|
|
Mission* mission = (*missions)[index];
|
|
if (mission->day != day)
|
|
continue;
|
|
|
|
// TODO: Make sure mission fits in empty slot
|
|
// Take previous mission and check end time vs selected mission
|
|
// Take next mission in list and check vs selected
|
|
/*Mission* lastMission = this->getLastMission(day);
|
|
if (lastMission != nullptr && lastMission->end > mission->start)
|
|
continue;*/
|
|
|
|
float dailyWorkTime = this->getWorkTime(day);
|
|
float workTime = this->getTotalWorkTime(mission);
|
|
if (mission->profession == employee->profession
|
|
&& Employee::MaxWorkTime >= dailyWorkTime
|
|
&& Employee::MaxWorkTimeWeek >= workTime)
|
|
list->push_back(mission);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
int Assignment::getCompetenceTotal()
|
|
{
|
|
int total = 0;
|
|
for (Mission* mission : this->missions)
|
|
{
|
|
if (this->employee->competence == mission->competence)
|
|
total += 1;
|
|
}
|
|
return total;
|
|
}
|
|
|
|
float Assignment::getTravelDistance()
|
|
{
|
|
int size = this->missions.size();
|
|
if (size == 0) return 0.f;
|
|
float distance = 0.f; // this->distances->getDistance(this->employee->center->id, this->missions[0]->id);
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
int prev = this->getPreviousId(i);
|
|
Mission* m = this->missions[i];
|
|
distance += this->distances->getDistance(prev, m->id);
|
|
}
|
|
return distance;
|
|
}
|
|
|
|
float Assignment::getWorkTime(int day)
|
|
{
|
|
float workTime = 0.f;
|
|
for (Mission* mission : this->missions)
|
|
{
|
|
if (mission->day == day)
|
|
workTime += mission->getDuration();
|
|
}
|
|
return workTime;
|
|
}
|
|
|
|
float Assignment::getTotalWorkTime()
|
|
{
|
|
//float total = this->workTime;
|
|
float total = 0.f;
|
|
for (Mission* mission : this->missions)
|
|
total += mission->getDuration();
|
|
|
|
total += this->getTravelDistance() / 55 * 60;
|
|
return total;
|
|
}
|
|
|
|
float Assignment::getTotalWorkTime(Mission* mission)
|
|
{
|
|
return this->getTotalWorkTime()
|
|
+ mission->getDuration()
|
|
+ this->distances->getTravelTime(this->getPreviousId(), mission->id);
|
|
}
|
|
|
|
void Assignment::print()
|
|
{
|
|
std::cout << "Employee " << this->employee->id << " (" << employee->profession << ", " << employee->competence << ") work schedule " << this->getTotalWorkTime() / 60 << " work hours\n";
|
|
for (int day = 1; day < 6; day ++)
|
|
{
|
|
std::cout << "Day " << day << ": ";
|
|
for (Mission* mission : this->missions)
|
|
{
|
|
if (mission->day != day) continue;
|
|
std::cout << "[" << mission->id << "] (" << mission->start << ", " << mission->end << ") " << mission->competence << ", ";
|
|
}
|
|
std::cout << "\n";
|
|
}
|
|
|
|
|
|
}
|