/**
* @file TimeTable.cpp
* @brief Implements the methods of the TimeTable class.
* @copyright Copyright (C) 2025 ForeFire, Fire Team, SPE, CNRS/Universita di Corsica.
* @license This program is free software; See LICENSE file for details. (See LICENSE file).
* @author JeanBaptiste Filippi 2025
*/
#include "TimeTable.h"
using namespace std;
namespace libforefire {
TimeTable::TimeTable() {
commonInitialization();
}
TimeTable::TimeTable(FFEvent* ev) {
head = nullptr;
commonInitialization();
insert(ev);
}
TimeTable::~TimeTable() {
while ( size() > 0 ) dropEvent(head);
}
void TimeTable::commonInitialization(){
incr = 0;
decr = 0;
}
void TimeTable::setHead(FFEvent* newHead){
head->getPrev()->setNext(newHead);
newHead->setPrev(head->getPrev());
head = newHead;
}
FFEvent* TimeTable::getHead(){
return head;
}
double TimeTable::getTime(){
if ( !head ){
return -numeric_limits::infinity();
}
if(size()==0 ) {
return -numeric_limits::infinity();
}
return head->getTime();
}
void TimeTable::increment(){
incr++;
}
void TimeTable::decrement(){
decr++;
}
size_t TimeTable::size(){
return incr-decr;
}
FFEvent* TimeTable::getUpcomingEvent(){
FFEvent* upEvent = head;
if ( size() > 1 ) {
setHead(head->getNext());
decrement();
} else if ( size() == 1 ) {
// this is the only event left
decrement();
} else {
// no events left to be treated (size=0)
cout setNext(newEv);
head->setPrev(newEv);
} else {
// possible insertion at the head or the tail
// if not, searching for the time of insertion
if ( evTime < head->getTime() + EPSILONT ){
// inserting the event at the head
head->insertBefore(newEv);
head = newEv;
} else if ( evTime > head->getPrev()->getTime() ){
// inserting the event at the tail
head->insertBefore(newEv);
} else {
// searching for the time of insertion
// starting from the head
FFEvent* tmpEv = head;
while ( evTime > tmpEv->getTime() + EPSILONT ){
tmpEv = tmpEv->getNext();
}
tmpEv->insertBefore(newEv);
}
}
increment();
}
void TimeTable::insert(FFEvent* newEv){
// checking the event consistency
double evTime = newEv->getTime();
if ( evTime == numeric_limits::infinity() ){
// deleting the event
delete newEv;
return;
}
if ( size() == 0 ) {
// First element of the timetable
head = newEv;
head->setNext(newEv);
head->setPrev(newEv);
} else {
// possible insertion at the head or the tail
// if not, searching for the time of insertion
if ( evTime < head->getTime() - EPSILONT ){
// inserting the event at the head
head->insertBefore(newEv);
head = newEv;
} else if ( evTime >= head->getPrev()->getTime() - EPSILONT ){
// inserting the event at the tail
FFEvent* tmpEv = head->getPrev();
tmpEv->insertAfter(newEv);
} else {
// searching for the time of insertion
// starting from the head
FFEvent* tmpEv = head;
while ( evTime > tmpEv->getTime() - EPSILONT ){
tmpEv = tmpEv->getNext();
}
tmpEv = tmpEv->getPrev();
tmpEv->insertAfter(newEv);
}
}
increment();
}
void TimeTable::dropEvent(FFEvent* ev){
if ( !head ) return;
if ( size() > 1 ) {
// classical removing
ev->getPrev()->setNext(ev->getNext());
ev->getNext()->setPrev(ev->getPrev());
if ( ev == head ){
head = head->getNext();
}
} else {
head = 0;
}
delete ev;
decrement();
}
void TimeTable::dropAtomEvents(ForeFireAtom* atom){
if ( !head ) return;
FFEvent* tmpEvNext;
// removing possible events at head
while ( head != 0 and head->getAtom() == atom ) dropEvent(head);
FFEvent* tmpEv = head->getNext();
/* scanning all the events to see if they're
* related to the searched ForeFireAtom */
while ( tmpEv != head ) {
tmpEvNext = tmpEv->getNext();
if ( tmpEv->getAtom() == atom ) dropEvent(tmpEv);
tmpEv = tmpEvNext;
}
}
string TimeTable::print(){
if ( !head ) return "";
ostringstream oss;
oss