55
55
#define PROGRESS_MAX_VALUE 100
58
PlanTJScheduler::PlanTJScheduler( Project *project, ScheduleManager *sm, QObject *parent )
58
PlanTJScheduler::PlanTJScheduler( Project *project, ScheduleManager *sm, ulong granularity, QObject *parent )
59
59
: SchedulerThread( project, sm, parent ),
62
62
m_recalculate( false ),
63
63
m_usePert( false ),
65
m_granularity( granularity )
67
68
connect(&TJ::TJMH, SIGNAL(message(int, const QString&, TJ::CoreAttributes*)), this, SLOT(slotMessage(int, const QString&, TJ::CoreAttributes*)));
143
144
m_schedule->setPhaseName( 0, i18nc( "@info/plain" , "Init" ) );
144
145
if ( ! m_backward && locale() ) {
145
logDebug( m_project, 0, QString( "Schedule project using TJ Scheduler, starting at %1" ).arg( QDateTime::currentDateTime().toString() ), 0 );
146
logDebug( m_project, 0, QString( "Schedule project using TJ Scheduler, starting at %1, granularity %2" ).arg( QDateTime::currentDateTime().toString() ).arg( locale()->formatDuration( m_granularity ) ), 0 );
146
147
if ( m_recalculate ) {
147
148
logInfo( m_project, 0, i18nc( "@info/plain" , "Re-calculate project from start time: %1", locale()->formatDateTime( m_project->constraintStartTime() ) ), 0 );
151
152
logInfo( m_project, 0, i18nc( "@info/plain" , "Project target finish time: %1", locale()->formatDateTime( m_project->constraintEndTime() ) ), 0 );
153
154
if ( m_backward && locale() ) {
154
logDebug( m_project, 0, QString( "Schedule project backward using TJ Scheduler, starting at %1" ).arg( locale()->formatDateTime( QDateTime::currentDateTime() ) ), 0 );
155
logDebug( m_project, 0, QString( "Schedule project backward using TJ Scheduler, starting at %1, granularity %2" ).arg( locale()->formatDateTime( QDateTime::currentDateTime() ) ).arg( locale()->formatDuration( m_granularity ) ), 0 );
155
156
logInfo( m_project, 0, i18nc( "@info/plain" , "Schedule project from end time: %1", locale()->formatDateTime( m_project->constraintEndTime() ) ), 0 );
218
219
bool PlanTJScheduler::kplatoToTJ()
220
221
m_tjProject = new TJ::Project();
222
m_tjProject->setScheduleGranularity( m_granularity / 1000 );
221
223
m_tjProject->setNow( m_project->constraintStartTime().toTime_t() );
222
224
m_tjProject->setStart( m_project->constraintStartTime().toTime_t() );
223
225
m_tjProject->setEnd( m_project->constraintEndTime().toTime_t() );
224
m_tjProject->setScheduleGranularity( 300 ); //5 minutes
226
227
m_tjProject->setDailyWorkingHours( m_project->standardWorktime()->day() );
290
TJ::Interval PlanTJScheduler::toTJInterval( const QDateTime &start, const QDateTime &end ) {
291
TJ::Interval ti( start.toTime_t(), end.addSecs( - 1).toTime_t() );
291
TJ::Interval PlanTJScheduler::toTJInterval( const QDateTime &start, const QDateTime &end, ulong granularity ) {
292
int secs = QTime( 0, 0, 0 ).secsTo( start.time() );
293
secs -= secs % granularity;
294
QDateTime s( start.date(), QTime( 0, 0, 0 ).addSecs( secs ) );
295
secs = QTime( 0, 0, 0 ).secsTo( end.time() );
296
secs -= secs % granularity;
297
QDateTime e( end.date(), QTime( 0, 0, 0 ).addSecs( secs ) );
298
TJ::Interval ti( s.toTime_t(), e.addSecs( -1 ).toTime_t() );
296
TJ::Interval PlanTJScheduler::toTJInterval( const QTime &start, const QTime &end ) {
297
time_t s = QTime( 0, 0, 0 ).secsTo( start );
298
time_t e = ( end == QTime( 0, 0, 0 ) ) ? 86399 : QTime( 0, 0, 0 ).secsTo( end );
303
TJ::Interval PlanTJScheduler::toTJInterval( const QTime &start, const QTime &end, ulong granularity ) {
304
int secs = QTime( 0, 0, 0 ).secsTo( start );
305
time_t s = secs - ( secs % granularity );
306
secs = ( end == QTime( 0, 0, 0 ) ) ? 86399 : QTime( 0, 0, 0 ).secsTo( end );
307
time_t e = secs - ( secs % granularity ) - 1;
299
308
TJ::Interval ti( s, e );
312
ulong PlanTJScheduler::tjGranularity() const
314
return m_tjProject->getScheduleGranularity();
303
317
bool PlanTJScheduler::kplatoFromTJ()
305
319
MainSchedule *cs = static_cast<MainSchedule*>( m_project->currentSchedule() );
513
527
foreach ( CalendarDay *day, lst ) {
514
528
if ( day->state() == CalendarDay::NonWorking ) {
515
res->addVacation( new TJ::Interval( toTJInterval( QDateTime( day->date() ), QDateTime( day->date().addDays( 1 ) ) ) ) );
529
res->addVacation( new TJ::Interval( toTJInterval( QDateTime( day->date() ), QDateTime( day->date().addDays( 1 ) ), tjGranularity() ) ) );
516
530
} else if ( day->state() == CalendarDay::Working ) {
517
531
TJ::Shift *shift = new TJ::Shift( m_tjProject, r->id() + day->date().toString( Qt::ISODate ), r->name(), 0, QString(), 0 );
518
532
foreach ( TimeInterval *ti, day->timeIntervals() ) {
519
533
QList<TJ::Interval*> ivs;
520
ivs << new TJ::Interval( toTJInterval( ti->startTime(), ti->endTime() ) );
534
ivs << new TJ::Interval( toTJInterval( ti->startTime(), ti->endTime(), tjGranularity() ) );
521
535
shift->setWorkingHours( day->date().dayOfWeek() - 1, ivs );
523
TJ::Interval period = toTJInterval( day->start(), day->end() );
537
TJ::Interval period = toTJInterval( day->start(), day->end(), tjGranularity() );
524
538
TJ::ShiftSelection *sl = new TJ::ShiftSelection( period, shift );
525
539
res->addShift( sl );
528
if ( m_project->constraintStartTime() < r->availableFrom() ) {
529
res->addVacation( new TJ::Interval( toTJInterval( m_project->constraintStartTime(), r->availableFrom() ) ) );
542
if ( m_project->startTime() < r->availableFrom() ) {
543
res->addVacation( new TJ::Interval( toTJInterval( m_project->startTime(), r->availableFrom(), tjGranularity() ) ) );
531
if ( r->availableUntil().isValid() && m_project->constraintEndTime() > r->availableUntil() ) {
532
res->addVacation( new TJ::Interval( toTJInterval( r->availableUntil(), m_project->constraintEndTime() ) ) );
545
if ( m_project->endTime() > r->availableUntil() ) {
546
res->addVacation( new TJ::Interval( toTJInterval( r->availableUntil(), m_project->startTime(), tjGranularity() ) ) );
534
548
m_resourcemap[res] = r;
535
549
// if ( locale() ) { logDebug( m_project, 0, "Added resource: " + r->name() ); }
670
684
logDebug( task, 0, QString( "FNL: set specified end: %1").arg( TJ::time2ISO( task->constraintEndTime().toTime_t() ) ) );
673
case Node::FixedInterval:
687
case Node::FixedInterval: {
674
688
job->setPriority( 700 );
675
job->setSpecifiedStart( 0, task->constraintStartTime().toTime_t() );
676
job->setSpecifiedEnd( 0, task->constraintEndTime().toTime_t() - 1 );
677
logDebug( task, 0, QString( "FI: set specified: %1 - %2").arg( TJ::time2ISO( task->constraintStartTime().toTime_t() ) ).arg( TJ::time2ISO( task->constraintEndTime().toTime_t() ) ) );
689
TJ::Interval i( toTJInterval( task->constraintStartTime(), task->constraintEndTime(), tjGranularity() ) );
690
job->setSpecifiedPeriod( 0, i );
691
// estimate not allowed
692
job->setDuration( 0, 0.0 );
693
job->setLength( 0, 0.0 );
694
job->setEffort( 0, 0.0 );
695
logDebug( task, 0, QString( "FI: set specified: %1 - %2 -> %3 - %4 (%5)")
696
.arg( TJ::time2ISO( task->constraintStartTime().toTime_t() ) )
697
.arg( TJ::time2ISO( task->constraintEndTime().toTime_t() ) )
698
.arg( TJ::time2ISO( i.getStart() ) )
699
.arg( TJ::time2ISO( i.getEnd() ) )
700
.arg( tjGranularity() ) );
680
704
if ( locale() ) logWarning( task, 0, i18nc( "@info/plain", "Unhandled time constraint type" ) );
699
723
job->setDuration( 0, 0.0 );
702
if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() == 0 ) {
703
job->setDuration( 0, task->estimate()->value( Estimate::Use_Expected, m_usePert ).toDouble( Duration::Unit_d ) );
706
if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() != 0 ) {
707
job->setLength( 0, task->estimate()->value( Estimate::Use_Expected, m_usePert ).toDouble( Duration::Unit_d ) );
710
if ( task->constraint() == Node::FixedInterval ) {
711
job->setSpecifiedPeriod( 0, toTJInterval( task->constraintStartTime(), task->constraintEndTime() ) );
713
if ( m_recalculate && task->completion().isStarted() ) {
714
job->setEffort( 0, task->completion().remainingEffort().toDouble( Duration::Unit_d ) );
716
Estimate *estimate = task->estimate();
717
double e = estimate->scale( estimate->value( Estimate::Use_Expected, m_usePert ), Duration::Unit_d, estimate->scales() );
718
job->setEffort( 0, e );
726
// Note: FI tasks can never have an estimate set (duration, length or effort)
727
if ( task->constraint() != Node::FixedInterval ) {
728
if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() == 0 ) {
729
job->setDuration( 0, task->estimate()->value( Estimate::Use_Expected, m_usePert ).toDouble( Duration::Unit_d ) );
732
if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() != 0 ) {
733
job->setLength( 0, task->estimate()->value( Estimate::Use_Expected, m_usePert ).toDouble( Duration::Unit_d ) );
736
if ( m_recalculate && task->completion().isStarted() ) {
737
job->setEffort( 0, task->completion().remainingEffort().toDouble( Duration::Unit_d ) );
739
Estimate *estimate = task->estimate();
740
double e = estimate->scale( estimate->value( Estimate::Use_Expected, m_usePert ), Duration::Unit_d, estimate->scales() );
741
job->setEffort( 0, e );
720
744
if ( task->requests().isEmpty() ) {