00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef HAVE_CONFIG_H
00019 #include <config.h>
00020 #endif
00021
00022 using namespace std;
00023
00024 #include "messenger.h"
00025 #include "project.h"
00026 #include "reporter.h"
00027
00028 #define MIN(A,B) ((A)<(B) ? (A) : (B))
00029 #define MAX(A,B) ((A)>(B) ? (A) : (B))
00030
00031 int Reporter::Bound(int x, int x1, int x2)
00032 {
00033 if ( x < x1 )
00034 return x1;
00035 if ( x > x2 )
00036 return x2;
00037 return x;
00038 }
00039
00040
00041 int Reporter::Offset(int x, int x1, int x2 )
00042 {
00043 return Bound( x, x1, x2 ) - x1;
00044 }
00045
00046 int Reporter::MapX( Project *project, int dayNo, int start, int finish)
00047 {
00048 if ( dayNo < start )
00049 dayNo = start;
00050 if ( dayNo > finish )
00051 dayNo = finish;
00052
00053 return tg_left + tg_width *
00054 Offset( project->nDays(dayNo),
00055 project->nDays(start),
00056 project->nDays(finish) );
00057 }
00058
00059 FILE *Reporter::OpenTaskGraph(const char *filename, int x1, int y1, int x2, int y2)
00060 {
00061 FILE *f;
00062
00063 f = fopen(filename,"w");
00064 if ( f == NULL )
00065 Error("Cannot open file [%s]",filename);
00066
00067 fprintf(f,"%%!PS-Adobe-2.0 EPSF-2.0\n");
00068 fprintf(f,"%%%%BoundingBox: %d %d %d %d\n",x1,y1,x2,y2);
00069
00070 fprintf(f,"/%s findfont\n", tg_fontname1);
00071 fprintf(f,"dup length dict begin\n");
00072 fprintf(f," { 1 index /FID ne\n");
00073 fprintf(f," {def}\n");
00074 fprintf(f," {pop pop}\n");
00075 fprintf(f," ifelse\n");
00076 fprintf(f," } forall\n");
00077 fprintf(f," /Encoding ISOLatin1Encoding def\n");
00078 fprintf(f," currentdict\n");
00079 fprintf(f,"end\n");
00080 fprintf(f,"/%s-ISOLatin1 exch definefont pop\n", tg_fontname1);
00081
00082 if ( strcmp(tg_fontname1, tg_fontname2) != 0 )
00083 {
00084 fprintf(f,"/%s findfont\n", tg_fontname2);
00085 fprintf(f,"dup length dict begin\n");
00086 fprintf(f," { 1 index /FID ne\n");
00087 fprintf(f," {def}\n");
00088 fprintf(f," {pop pop}\n");
00089 fprintf(f," ifelse\n");
00090 fprintf(f," } forall\n");
00091 fprintf(f," /Encoding ISOLatin 1Encoding def\n");
00092 fprintf(f," currentdict\n");
00093 fprintf(f,"end\n");
00094 fprintf(f,"/%s-ISOLatin1 exch definefont pop\n", tg_fontname2);
00095 }
00096
00097 if ( ( strcmp(tg_fontname1, tg_fontname3) != 0 )
00098 && ( strcmp(tg_fontname2, tg_fontname3) != 0 ) )
00099 {
00100 fprintf(f,"/%s findfont\n", tg_fontname3);
00101 fprintf(f,"dup length dict begin\n");
00102 fprintf(f," { 1 index /FID ne\n");
00103 fprintf(f," {def}\n");
00104 fprintf(f," {pop pop}\n");
00105 fprintf(f," ifelse\n");
00106 fprintf(f," } forall\n");
00107 fprintf(f," /Encoding ISOLatin 1Encoding def\n");
00108 fprintf(f," currentdict\n");
00109 fprintf(f,"end\n");
00110 fprintf(f,"/%s-ISOLatin1 exch definefont pop\n", tg_fontname3);
00111 }
00112
00113 fprintf(f,"/BOX\n");
00114 fprintf(f," {\n");
00115 fprintf(f," /y2 exch def /y1 exch def /x2 exch def /x1 exch def\n");
00116 fprintf(f," x1 y1 moveto\n");
00117 fprintf(f," x2 y1 lineto\n");
00118 fprintf(f," x2 y2 lineto\n");
00119 fprintf(f," x1 y2 lineto\n");
00120 fprintf(f," closepath\n");
00121 fprintf(f," %f setgray\n", tg_gray);
00122 fprintf(f," fill\n");
00123 fprintf(f," } def\n");
00124
00125 fprintf(f,"/OUTLINE\n");
00126 fprintf(f," {\n");
00127 fprintf(f," /y2 exch def /y1 exch def /x2 exch def /x1 exch def\n");
00128 fprintf(f," x1 y1 moveto\n");
00129 fprintf(f," x2 y1 lineto\n");
00130 fprintf(f," x2 y2 lineto\n");
00131 fprintf(f," x1 y2 lineto\n");
00132 fprintf(f," closepath\n");
00133 fprintf(f," %f setgray\n", tg_lightgray);
00134 fprintf(f," fill\n");
00135 fprintf(f," } def\n");
00136
00137
00138 if (tg_showpast)
00139 {
00140 fprintf(f,"/PAST\n");
00141 fprintf(f," {\n");
00142 fprintf(f," /y2 exch def /y1 exch def /x2 exch def /x1 exch def\n");
00143 fprintf(f," /ymiddle y1 y2 add 2 div def\n");
00144 fprintf(f," x1 y1 ymiddle add 2 div moveto\n");
00145 fprintf(f," x2 y1 ymiddle add 2 div lineto\n");
00146 fprintf(f," x2 y2 ymiddle add 2 div lineto\n");
00147 fprintf(f," x1 y2 ymiddle add 2 div lineto\n");
00148 fprintf(f," closepath\n");
00149 fprintf(f," %f setgray\n", tg_pastgray);
00150 fprintf(f," fill\n");
00151 fprintf(f," } def\n");
00152 }
00153
00154
00155 if (tg_showvacation)
00156 {
00157 fprintf(f,"/VACATION\n");
00158 fprintf(f," {\n");
00159 fprintf(f," /y2 exch def /y1 exch def /x2 exch def /x1 exch def\n");
00160 fprintf(f," x1 y1 moveto\n");
00161 fprintf(f," x2 y1 lineto\n");
00162 fprintf(f," x2 y2 lineto\n");
00163 fprintf(f," x1 y2 lineto\n");
00164 fprintf(f," closepath\n");
00165 fprintf(f," %f setgray\n", tg_vacationgray);
00166 fprintf(f," fill\n");
00167 fprintf(f," } def\n");
00168
00169 }
00170
00171 fprintf(f,"/FINISHED\n");
00172 fprintf(f," {\n");
00173 fprintf(f," /y2 exch def /y1 exch def /x2 exch def /x1 exch def\n");
00174 fprintf(f," gsave\n");
00175 fprintf(f," %f setgray\n", tg_white);
00176 fprintf(f," 3 setlinewidth\n");
00177 fprintf(f," x1 y1 moveto\n");
00178 fprintf(f," x2 y2 lineto\n");
00179 fprintf(f," stroke\n");
00180 fprintf(f," grestore\n");
00181 fprintf(f," } def\n");
00182
00183 fprintf(f,"/MBOX\n");
00184 fprintf(f," {\n");
00185 fprintf(f," /y2 exch def /y1 exch def /x2 exch def /x1 exch def\n");
00186 fprintf(f," /x3 x1 x2 add 2 div def\n");
00187
00188 fprintf(f," /y3 y1 y2 add 2 div def\n");
00189 fprintf(f," x1 y1 moveto\n");
00190 fprintf(f," x2 y1 lineto\n");
00191 fprintf(f," x3 y3 lineto\n");
00192 fprintf(f," closepath\n");
00193 fprintf(f," %f setgray\n", tg_gray);
00194 fprintf(f," fill\n");
00195 fprintf(f," x1 y2 moveto\n");
00196 fprintf(f," x2 y2 lineto\n");
00197 fprintf(f," x3 y3 lineto\n");
00198 fprintf(f," closepath\n");
00199 fprintf(f," %f setgray\n", tg_gray);
00200 fprintf(f," fill\n");
00201 fprintf(f," } def\n");
00202
00203 fprintf(f,"/%s-ISOLatin1 findfont %f scalefont setfont\n", tg_fontname1, tg_fontsize1);
00204
00205 fprintf(f,"0 setgray\n");
00206 fprintf(f,"0.01 setlinewidth\n");
00207
00208 fprintf(f,"%d %d moveto\n",x1,y1);
00209 fprintf(f,"%d %d lineto\n",x1,y2);
00210 fprintf(f,"%d %d lineto\n",x2,y2);
00211 fprintf(f,"%d %d lineto\n",x2,y1);
00212 fprintf(f,"stroke\n");
00213
00214 return f;
00215 }
00216
00218 void Project::printTaskList()
00219 {
00220 for ( int i = 0 ; i < nTasks() ; ++i )
00221 {
00222 TASK * t = mSortedTaskList[i];
00223 printf("Task id: %s, Assigned to: %s, Start date: %d\n",
00224 t->id(), t->assigned()->id(), t->start());
00225 }
00226 }
00227
00228
00234 void Reporter::TaskGraph(Project *project,
00235 int start, int finish,
00236 const char *filename)
00237 {
00238 FILE *f;
00239 TASK *t;
00240 TASK *lastt = NULL;
00241 int i;
00242 int y;
00243 int x1=99999, y1=99999, x2=-99999, y2=-99999;
00244 int day;
00245 int daynum;
00246 int tb_x1, tb_y1, tb_x2, tb_y2;
00247
00248 project->SortTasks( tg_sortbyresource );
00249
00250
00251
00252 Debug("TaskGraph(%d/%s,%d/%s,%s)",
00253 start,project->sDays(start),finish,project->sDays(finish),filename);
00254
00255 Debug("start=%d finish=%d",start,finish);
00256
00257 x1 = tg_tasklabel;
00258 x2 = MapX(project,finish+1,start,finish);
00259
00260
00261 y = tg_top;
00262 for( i=0; i<project->nTasks(); ++i )
00263 {
00264 t = project->sortedTask(i);
00265 if ( t->isVacation() )
00266 continue;
00267 if( ! t->overlap(start, finish) )
00268 continue;
00269
00270 t->y2 = y;
00271 t->y1 = t->y2 - tg_height;
00272 y -= tg_space;
00273 y1 = MIN( y1, t->y1 );
00274 y2 = MAX( y2, t->y2 );
00275 }
00276
00277
00278 y1 -= static_cast<int>( tg_space + tg_fontsize3 / 4 );
00279
00280 x1 -= tg_xborder;
00281 y1 -= tg_yborder;
00282 x2 += tg_xborder;
00283 y2 += tg_yborder;
00284
00285 f = OpenTaskGraph(filename, x1, y1, x2, y2);
00286
00287
00288 y = tg_top;
00289 for( i=0; i<project->nTasks(); ++i )
00290 {
00291 t = project->sortedTask(i);
00292 if ( t->isVacation() )
00293 continue;
00294 if( ! t->overlap(start, finish) )
00295 continue;
00296
00297 Debug("... (b) task %s: %d-%d", t->id(),t->start(),t->finish());
00298
00299 t->x1 = MapX(project, t->start(), start, finish );
00300 t->x2 = MapX(project, t->finish(), start, finish ) + tg_width-1;
00301 t->y2 = y;
00302 t->y1 = t->y2 - tg_height;
00303 y -= tg_space;
00304
00305
00306 if (tg_showvacation)
00307 {
00308 for ( int ti = 0; ti < project->nTasks(); ++ti )
00309 {
00310 TASK* vt = project->sortedTask(ti);
00311 if (! vt->isVacation() )
00312 continue;
00313 if (! vt->overlap(start, finish) )
00314 continue;
00315 if ( strcmp(vt->assigned()->id(), t->assigned()->id() ) != 0 )
00316 continue;
00317
00318 int v_x1 = MapX(project, vt->start(), start, finish );
00319 int v_x2 = MapX(project, vt->finish(), start, finish ) + tg_width;
00320 fprintf(f, "%d %d %d %d VACATION\n", v_x1, v_x2, t->y1, t->y2 );
00321 }
00322 }
00323
00324 fprintf(f,"0 setgray\n");
00325 fprintf(f,"%d %d moveto\n", tg_tasklabel, t->y1 + tg_textup );
00326 if ( task_ids )
00327 fprintf(f,"(%s %s: %s) show\n", t->id(), t->name(), t->assigned()->id());
00328 else
00329 fprintf(f,"(%s: %s) show\n", t->name(), t->assigned()->id());
00330 fprintf(f,"%d %d moveto\n", x1, t->y1 );
00331 fprintf(f,"%d %d lineto stroke\n", x2, t->y1 );
00332
00333
00334 if (tg_sortbyresource) {
00335 if ((lastt != NULL) &&
00336 (strcasecmp(t->assigned()->id(),lastt->assigned()->id()) != 0)) {
00337
00338 fprintf(f,"3 setlinewidth\n");
00339 fprintf(f,"%d %d moveto\n", x1, t->y2+tg_height );
00340 fprintf(f,"%d %d lineto stroke\n", x2, t->y2+tg_height );
00341 fprintf(f,"0.01 setlinewidth\n");
00342 }
00343
00344 lastt = t;
00345
00346 }
00347
00348 for (TaskTimeBlockIterator tb = t->begin_when(); tb != t->end_when(); tb++)
00349 {
00350 int i;
00351 Debug("... ... %s timeblock %s-%s type=%d",
00352 t->id(), project->sDays(tb->start()), project->sDays(tb->finish()),
00353 tb->type());
00354 if( tb->finish() < start || tb->start() > finish )
00355 continue;
00356
00357 tb_x1 = MapX(project, tb->start(), start, finish );
00358 tb_x2 = MapX(project, tb->finish(), start, finish ) + tg_width - 1;
00359 tb_y2 = t->y2;
00360 tb_y1 = t->y1;
00361 fprintf(f,"%d %d %d %d OUTLINE\n", tb_x1, tb_x2, tb_y1, tb_y2);
00362 for( i = tb->start(); i <= tb->finish(); ++i )
00363 {
00364 tb_x1 = MapX(project, i, start, finish );
00365 fprintf(f,"%d %d %d %d BOX\n", tb_x1, tb_x1+tg_width, tb_y1, tb_y2);
00366
00367
00368
00369
00370
00371 if (tb->type() == TimeBlock::WORK_DONE &&
00372 tg_showpast && t->percent_complete()<=1)
00373 {
00374 fprintf(f,"%d %d %d %d PAST\n", tb_x1, tb_x1+tg_width, tb_y1, tb_y2);
00375 }
00376 }
00377 }
00378
00379 if( t->percent_complete()>1 )
00380 {
00381 int dayNo, nDays=0;
00382 int x1, x2;
00383 for ( TaskTimeBlockIterator tb = t->begin_when();
00384 tb != t->end_when(); tb++ )
00385 {
00386 for ( dayNo = tb->start(); dayNo <= tb->finish() ; dayNo++ )
00387 {
00388 if( t->DayBooked( dayNo ) )
00389 {
00390 ++nDays;
00391 if( (double)nDays/(double)t->fullduration() <=
00392 0.01*t->percent_complete() )
00393 {
00394 x1 = MapX(project, dayNo, start, finish );
00395 x2 = x1 + tg_width-1;
00396 fprintf(f,"%d %d %d %d FINISHED\n", x1+2, x2-2, t->y1+2, t->y2-2);
00397 }
00398 else
00399 {
00400 break;
00401 }
00402 }
00403 }
00404 }
00405 }
00406
00407 fprintf(f,"\n");
00408 }
00409
00410 y -= tg_space;
00411
00412 for( day=start; day<=finish; ++day )
00413 {
00414
00415 daynum = Offset(project->nDays(day), project->nDays(start), project->nDays(finish));
00416
00417 fprintf(f, "/%s-ISOLatin1 findfont %f scalefont setfont\n", tg_fontname2, tg_fontsize2);
00418
00419
00420 if (!tg_nodays) {
00421
00422 fprintf(f,"0 setgray %d %d moveto (%s) show\n",
00423 tg_left + daynum * tg_width, y + tg_space,
00424 project->dayNames[ Wday( project->tDays(day) ) ] );
00425 fprintf(f,"%f setgray %d %d moveto 0 %d rlineto stroke\n",
00426 tg_gray, tg_left + daynum * tg_width, y + tg_space, tg_space/2 );
00427
00428 if (tg_daysofmonth)
00429 fprintf(f,"0 setgray %d %d moveto (%d) show\n",
00430 tg_left + daynum * tg_width, y + tg_space/2 + 3, Mday( project->tDays(day)));
00431
00432 if ( Wday( project->tDays(day)) == 1 ) {
00433 fprintf(f,"%f setgray %d %d moveto 0 %d rlineto stroke\n",
00434 tg_gray, tg_left + daynum * tg_width,
00435 y + tg_space, tg_top - (y + tg_space) );
00436 } else {
00437 fprintf(f,"%f setgray %d %d moveto 0 %d rlineto stroke\n",
00438 tg_gray, tg_left + daynum * tg_width,
00439 y + tg_space, tg_space/2 );
00440 }
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 if(Mday(project->tDays(day)) == 1 ||
00450 (day > start &&
00451 (Mday(project->tDays(day)) < Mday(project->tDays(day-1)))) ||
00452 (day == start &&
00453 Month(project->tDays(day)) == Month(project->tDays(day+3))))
00454 {
00455 Debug("legend; day=%d yday=%d yday'=%d",
00456 day,project->tDays(day),project->tDays(day-1));
00457
00458 fprintf(f, "/%s-ISOLatin1 findfont %f scalefont setfont\n",
00459 tg_fontname3, tg_fontsize3);
00460 daynum = Offset(project->nDays(day) - Mday( project->tDays(day) ) + 1,
00461 project->nDays(start), project->nDays(finish));
00462 fprintf(f, "%f setgray\n",tg_mlgray);
00463 fprintf(f, "%d %d moveto %d %d lineto stroke\n",
00464 tg_left + daynum * tg_width, y1,
00465 tg_left + daynum * tg_width, y2);
00466 fprintf(f, "0 setgray %d %d moveto (%s) show\n",
00467 tg_left + daynum * tg_width, y,
00468 monthNames[ Month( project->tDays(day) ) ] );
00469 }
00470 }
00471
00472 fprintf(f,"showpage\n");
00473
00474 fclose(f);
00475 }
00476
00477 void Reporter::UtilGraph(Project *project, char *filename)
00478 {
00479 int x1=99999, y1=99999, x2=-99999, y2=-99999;
00480
00481 project->SortTasks(tg_sortbyresource);
00482
00483 FILE * f = OpenOutputFile(filename);
00484
00485 int resNum = 0;
00486 for ( Project::RPLCI rl = project->beginResourceList() ;
00487 rl != project->endResourceList() ; rl++ )
00488 {
00489 RESOURCE * r = *rl;
00490 int y = 72*1 + 72/6 * resNum;
00491 int x = 72;
00492
00493 x1 = MIN(x1,x); x2=MAX(x2,x); y1 = MIN(y1,y); y2=MAX(y2,y);
00494 x += 72;
00495 x1 = MIN(x1,x); x2=MAX(x2,x);
00496 for ( int dayNum = 0 ; dayNum < MAX_TIME ; ++dayNum )
00497 {
00498 x += 4;
00499 if ( r->IsUsed( dayNum ) )
00500 {
00501 x1 = MIN(x1,x); x2=MAX(x2,x+3);
00502 }
00503 }
00504 resNum++;
00505 }
00506
00507 fprintf(f,"%%!PS-Adobe-2.0 EPSF-2.0\n");
00508 fprintf(f,"%%%%BoundingBox: %d %d %d %d\n",x1,y1,x2,y2);
00509
00510 fprintf(f,"/%s findfont\n", tg_fontname1);
00511 fprintf(f,"dup length dict begin\n");
00512 fprintf(f," { 1 index /FID ne\n");
00513 fprintf(f," {def}\n");
00514 fprintf(f," {pop pop}\n");
00515 fprintf(f," ifelse\n");
00516 fprintf(f," } forall\n");
00517 fprintf(f," /Encoding ISOLatin1Encoding def\n");
00518 fprintf(f," currentdict\n");
00519 fprintf(f,"end\n");
00520 fprintf(f,"/%s-ISOLatin1 exch definefont pop\n", tg_fontname1);
00521
00522 if ( strcmp(tg_fontname1, tg_fontname2) != 0 )
00523 {
00524 fprintf(f,"/%s findfont\n", tg_fontname2);
00525 fprintf(f,"dup length dict begin\n");
00526 fprintf(f," { 1 index /FID ne\n");
00527 fprintf(f," {def}\n");
00528 fprintf(f," {pop pop}\n");
00529 fprintf(f," ifelse\n");
00530 fprintf(f," } forall\n");
00531 fprintf(f," /Encoding ISOLatin 1Encoding def\n");
00532 fprintf(f," currentdict\n");
00533 fprintf(f,"end\n");
00534 fprintf(f,"/%s-ISOLatin1 exch definefont pop\n", tg_fontname2);
00535 }
00536
00537 if ( ( strcmp(tg_fontname1, tg_fontname3) != 0 )
00538 && ( strcmp(tg_fontname2, tg_fontname3) != 0 ) )
00539 {
00540 fprintf(f,"/%s findfont\n", tg_fontname3);
00541 fprintf(f,"dup length dict begin\n");
00542 fprintf(f," { 1 index /FID ne\n");
00543 fprintf(f," {def}\n");
00544 fprintf(f," {pop pop}\n");
00545 fprintf(f," ifelse\n");
00546 fprintf(f," } forall\n");
00547 fprintf(f," /Encoding ISOLatin 1Encoding def\n");
00548 fprintf(f," currentdict\n");
00549 fprintf(f,"end\n");
00550 fprintf(f,"/%s-ISOLatin1 exch definefont pop\n", tg_fontname3);
00551 }
00552
00553 fprintf(f, "/%s-ISOLatin1 findfont %f scalefont setfont\n", tg_fontname1, tg_fontsize1);
00554
00555 fprintf(f,"/BOX { 3 0 rlineto 0 3 rlineto -3 0 rlineto closepath stroke } def\n");
00556
00557 resNum = 0;
00558 for ( Project::RPLCI rl = project->beginResourceList() ;
00559 rl != project->endResourceList() ; rl++ )
00560 {
00561 RESOURCE * r = *rl;
00562 int y = 72*1 + 72/6 * resNum;
00563 int x = 72;
00564 fprintf(f,"0 setgray %d %d moveto (%s) show\n", x, y, r->id());
00565 x += 72;
00566 for ( int dayNum = 0 ; dayNum < MAX_TIME ; ++dayNum )
00567 {
00568 x += 4;
00569 if ( r->IsUsed( dayNum ) )
00570 {
00571 fprintf(f,"%d %d moveto BOX\n", x, y);
00572 }
00573 }
00574 resNum++;
00575 }
00576
00577 fprintf(f,"showpage\n");
00578
00579 fclose(f);
00580 }