13 #define CHART_HEIGHT 250
24 wxColour (127, 201, 127),
25 wxColour (190, 174, 212),
26 wxColour (253, 192, 134),
27 wxColour (255, 255, 153)
39 wxLogError (
"Data loading failed (panel #3)");
44 wxDateTime weekCenter;
46 wxDateTime::wxDateTime_t weekNumber = 0, weekOffset = 0;
47 for (ProcessedData::iterator it =
data.begin(); it !=
data.end(); it++) {
48 weekCenter = it->weekCenter;
49 weekCenter.MakeFromUTC();
50 epochTime = weekCenter.GetTicks();
52 if (weekCenter.GetWeekOfYear() < weekNumber)
53 weekOffset += weekNumber;
54 weekNumber = weekCenter.GetWeekOfYear();
55 vector_X2.push_back (weekNumber + weekOffset);
65 wxDateTime weekCenter;
66 wxDateTime::wxDateTime_t weekNumber = 0, weekOffset = 0,
67 firstOffset = 0, lastOffset = 0;
68 int yearCenter, firstYear =
firstDay.GetYear(), lastYear =
lastDay.GetYear();
69 for (ProcessedData::size_type j = 0; j <
data.size(); j++) {
70 weekCenter =
data[j].weekCenter;
71 if (weekCenter.GetWeekOfYear() < weekNumber) weekOffset += weekNumber;
72 weekNumber = weekCenter.GetWeekOfYear();
73 yearCenter = weekCenter.GetYear();
74 if (yearCenter == firstYear) firstOffset = weekOffset;
75 if (yearCenter == lastYear ) lastOffset = weekOffset;
76 if (yearCenter >= firstYear && yearCenter >= lastYear)
break;
81 firstWeek =
firstDay.GetWeekOfYear();
82 firstWeek += firstOffset;
83 lastWeek =
lastDay.GetWeekOfYear() + lastOffset;
92 wxDateTime::wxDateTime_t currentWeek = 0;
93 wxDateTime::WeekDay currentDay = wxDateTime::Inv_WeekDay;
95 wxDateTime start, stop, firstStartDaily, emptyWeek;
96 wxTimeSpan span, timeDaily, timeRangeDaily, noTime = wxTimeSpan::Hours (0);
100 start = it->start; stop = it->stop; span = stop - start;
101 if (start.GetWeekOfYear() == currentWeek) {
102 data[offset].timeTotal += span;
103 data[offset].minutesAtimeslot =
data[offset].timeTotal.GetSeconds().ToDouble()/++recordCount/60.;
104 if (start.GetWeekDay() == currentDay) {
107 timeRangeDaily = stop - firstStartDaily;
109 data[offset].daysWorked++;
111 firstStartDaily = start; timeRangeDaily = stop - firstStartDaily;
112 currentDay = start.GetWeekDay();
114 if (
data[offset].timeMax < timeDaily )
data[offset].timeMax = timeDaily;
118 firstStartDaily = start; timeRangeDaily = stop - firstStartDaily;
119 currentDay = start.GetWeekDay();
120 start.SetToWeekDayInSameWeek (wxDateTime::Thu); start.ResetTime(); start.SetHour (12);
127 if (currentWeek > 0) {
128 emptyWeek =
data[offset].weekCenter + wxDateSpan::Week();
129 while ( emptyWeek.IsEarlierThan (a.
weekCenter) ) {
136 data.push_back (b); offset++;
137 emptyWeek += wxDateSpan::Week();
140 data.push_back (a); offset++;
141 currentWeek = start.GetWeekOfYear();
157 unsigned long minutes;
159 wxASSERT (clusters !=
none);
162 if (start < firstDay || start >
lastDay)
continue;
163 span = it->stop - start;
164 minutes = span.GetHours()*60 + span.GetMinutes();
167 key = it->client .ToStdString();
170 key = it->project.ToStdString();
173 key = it->task .ToStdString();
176 key = it->tool .ToStdString();
182 Map4pie::iterator it;
int i;
183 for (i = 0; i < 3; i++)
185 string others = _(
"others").ToStdString();
187 if (it->first != others)
196 string key, others = _(
"others").ToStdString();
200 if (element.second < mini) {
201 mini = element.second;
210 if (element.first == others)
continue;
211 if (element.second < mini) {
212 mini = element.second;
226 unsigned long totalMinutes = 0;
228 totalMinutes += element.second;
229 double totalHours = totalMinutes/60.;
230 double totalDays = totalHours/7.;
231 return wxString::Format(_(
"SUM: %.1f hours (%.1f days)"), totalHours, totalDays);
240 wxDateTime::wxDateTime_t currentWeek = 0;
242 wxTimeSpan span, noTime = wxTimeSpan::Hours (0);
247 wxASSERT (clusters !=
none);
250 span = it->stop - start;
251 span_hours = span.GetSeconds().ToDouble()/3600.;
254 s = it->client .ToStdString();
257 s = it->project.ToStdString();
260 s = it->task .ToStdString();
263 s = it->tool .ToStdString();
266 while (s !=
legends[i] && i < 3) i++;
267 if (start.GetWeekOfYear() == currentWeek) {
268 if (i < 3)
data[offset].hours[i] += span_hours;
270 currentWeek = start.GetWeekOfYear();
272 while (
data[offset].timeTotal == noTime);
273 for (j = 0; j < 3; j++)
data[offset].hours[j] = 0.;
274 if (i < 3)
data[offset].hours[i] = span_hours;
284 if (clusters !=
none) {
293 for (
int i = 0; i < 3; i++)
297 ProcessedData::iterator it;
298 wxASSERT (aggregate !=
invalid);
299 if (clusters ==
none) {
300 for (it =
data.begin(); it !=
data.end(); it++) {
303 vector_Y[0].push_back (it->timeTotal.GetSeconds().ToDouble()/3600.);
306 vector_Y[0].push_back ((
double)it->daysWorked);
309 vector_Y[0].push_back (it->timeMax.GetSeconds().ToDouble()/3600.);
312 vector_Y[0].push_back (it->timeRangeMax.GetSeconds().ToDouble()/3600.);
315 vector_Y[0].push_back (it->minutesAtimeslot);
320 for (it =
data.begin(); it !=
data.end(); it++)
321 for (
int i = 0; i < 3; i++)
322 vector_Y[i].push_back (it->hours[i]);
336 Xaxis =
new mpScaleX (_(
"weeks"), mpALIGN_BORDER_BOTTOM,
true, mpX_DATE);
337 AddLayer (
Xaxis,
false);
338 Yaxis =
new mpScaleY (_(
"hours"), mpALIGN_BORDER_LEFT);
339 AddLayer (
Yaxis,
false);
341 EnableDoubleBuffer (
true);
342 wxPen pen [3] = { *wxBLUE_PEN, *wxGREEN_PEN, *wxRED_PEN };
344 for (
int i = 0; i < 3; i++) {
345 title.Printf (
"vector1%d", i);
346 vector1[i] =
new mpFXYVector (title);
347 vector1[i]->SetContinuity (
true);
348 title.Printf (
"vector2%d", i);
349 vector2[i] =
new mpFXYVector (title);
350 pen[i].SetWidth (5);
vector2[i]->SetPen (pen[i]);
356 legend =
new mpInfoLegend ( wxRect (w/2, 0, 50, 50) );
357 legend->SetItemMode (mpLEGEND_SQUARE);
359 legend->SetVisible (
true);
363 if (
SelectData (clusters, aggregate) )
return;
364 if (clusters ==
none) {
370 for (
int i = 1; i < 3; i++) {
371 vector1[i]->SetVisible (
false);
372 vector2[i]->SetVisible (
false);
374 legend->SetVisible (
false);
376 Yaxis->SetName(_(
"days") );
378 Yaxis->SetName(_(
"minutes") );
380 Yaxis->SetName(_(
"hours") );
382 for (
int i = 0; i < 3 &&
legends[i].size(); i++) {
390 legend->SetVisible (
true);
391 Yaxis->SetName(_(
"hours") );
402 for (
int i = 0; i < 3; i++) {
415 #ifdef wxUSE_GRAPHICS_CONTEXT
418 dataset =
new XYSimpleDataset();
419 wxVector<wxRealPoint> vector_XY [3];
420 for (
int i = 0; i < 3; i++) {
421 vector_XY[i].push_back (wxRealPoint (1, i ) );
422 vector_XY[i].push_back (wxRealPoint (2, i+1) );
423 series[i] =
new XYSerie (vector_XY[i]);
424 series[i]->SetName ( wxString::Format (
"#%d", i) );
427 renderer =
new XYLineRenderer (
true,
true);
428 renderer->SetSeriePen ( 0, wxThePenList->FindOrCreatePen (*wxBLUE, 2, wxPENSTYLE_SOLID) );
429 renderer->SetSeriePen ( 1, wxThePenList->FindOrCreatePen (*wxGREEN, 2, wxPENSTYLE_SOLID) );
430 renderer->SetSeriePen ( 2, wxThePenList->FindOrCreatePen (*wxRED, 2, wxPENSTYLE_SOLID) );
434 leftAxis =
new NumberAxis (AXIS_LEFT);
442 plot->LinkDataVerticalAxis (0, 0);
443 plot->LinkDataHorizontalAxis (0, 0);
444 legend =
new Legend (wxCENTER, wxRIGHT);
451 if (
SelectData (clusters, aggregate) )
return;
452 if (clusters ==
none) {
454 for (ProcessedData::size_type j = 0; j <
vector_X.size(); j++)
463 for (
int i = 0; i < 3 &&
legends[i].size(); i++) {
464 for (ProcessedData::size_type j = 0; j <
vector_X2.size(); j++)
475 unsigned int firstWeek, lastWeek;
477 bottomAxis->SetFixedBounds (firstWeek, lastWeek);
483 for (i = 0; i < 3; i++) {
484 j =
series[i]->GetCount();
485 while (j > 0)
series[i]->Remove (--j);
493 #ifdef wxUSE_GRAPHICS_CONTEXT
501 plot =
new PiePlot();
504 legend =
new Legend (wxCENTER, wxRIGHT);
511 wxASSERT (clusters !=
none);
513 Map4pie::iterator it;
int i;
514 for (i = 0; i < 4; i++) {
520 data[i++] = it->second;
544 if (
SelectData (clusters, aggregate) )
return;
545 for (ProcessedData::size_type j = 0; j <
vector_X.size(); j++) {
547 if (clusters ==
none)
550 for (
int i = 0; i < 3 &&
legends[i].size(); i++)
567 for (
int i = 0; i < 3; i++) {
578 data[0] =
new wxChartsDoubleDataset (wxEmptyString,
points[0]);
582 for (
int i = 0; i < 3 &&
legends[i].size(); i++) {
588 wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
592 wxChartsLegendData legendData (
chartData->GetDatasets() );
593 legendCtrl =
new wxChartsLegendCtrl (
this, wxID_ANY, legendData,
594 wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
603 unsigned int firstWeek, lastWeek;
605 for (ProcessedData::size_type j = 0; j <
vector_X.size(); j++) {
612 for (
int i = 0; i < 3 &&
legends[i].size(); i++)
628 chartData = wxPieChartData::make_shared();
630 Map4pie::iterator it;
int i;
632 slices.push_back ( wxChartSliceData ( it->second,
colors[i++], wxString (it->first) ) );
635 wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
637 wxChartsLegendData legendData (
chartData->GetSlices() );
638 legendCtrl =
new wxChartsLegendCtrl(
this, wxID_ANY, legendData,
639 wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
void PlotData(ClusterType, AggregateType)
Plotting interface for yatishFrame:
yatishChartPie(wxWindow *, yatishDBsqlite *)
wxPieChartData::ptr chartData
wxVector< wxChartSliceData > slices
wxPieChartCtrl * pieChartCtrl
wxChartsLegendCtrl * legendCtrl
wxChartsDoubleDataset * data[3]
wxChartsLegendCtrl * legendCtrl
wxChartsCategoricalData::ptr chartData
yatishChartSerie(wxWindow *, yatishDBsqlite *)
wxLineChartCtrl * lineChartCtrl
wxVector< wxString > labels
wxChartsDoubleDataset::ptr dataset[3]
void PlotData(ClusterType, AggregateType)
Plotting interface for yatishFrame:
wxVector< wxDouble > points[3]
ClusterType currentClusters
Interacts with yatish tables in a SQLite database.
bool FillPlotData(RawData &)
Fills a RawData (typedefined in yatishTypes.h).
CategoryRenderer * renderer
ColorScheme * colorScheme
CategorySimpleDataset * dataset
void PlotData(ClusterType, AggregateType)
Plotting interface for yatishFrame:
yatishFreePie(wxWindow *, yatishDBsqlite *)
void PlotData(ClusterType, AggregateType)
Plotting interface for yatishFrame:
XYSimpleDataset * dataset
yatishFreeSerie(wxWindow *, yatishDBsqlite *)
XYLineRenderer * renderer
yatishMathPlot(wxWindow *, yatishDBsqlite *)
void PlotData(ClusterType, AggregateType)
Plotting interface for yatishFrame:
Abstract Base class for the plots of panel #3.
virtual void ClearCurves()
wxString TotalFormattedFromPie()
Creates a wxString with the total hours in the current pie chart.
yatishPlot(yatishDBsqlite *)
The constructor of yatishPlot:
static vector< double > vector_Y[3]
user selected data
static RawData big_data
all timeslot records from the database
void Aggregates()
Builds all the weekly time series (non-clustered aggregates).
void NoMoreThan4()
Modifies member pieData so that there is no more than four record.
static vector< double > vector_X2
week number, counted from the first year in the time series
static vector< double > vector_X
epoch time
Map4pie pieData
total durations (between firstDay and lastDay), in minutes
bool SelectData(ClusterType, AggregateType)
Updates vector_Y[3] if need be (for the plotting libraries).
AggregateType formerAggregate
void ComputePie(ClusterType)
Fills member pieData with data for a pie chart with 4 sectors.
void ClusteredSeries(ClusterType)
Updates the clustered time series.
void GetWeekRange(unsigned int &, unsigned int &)
Computes the week numbers corresponding to members firstDay and lastDay.
static ProcessedData data
weekly times series: various aggregates and clustered sums
static string legends[3]
names of the 3 weekly clustered sums, for the current clustering scheme
Element of typefined std:vector ProcessedData (yatishPlot.data).
ClusterType
Same order as yatishFrame::choiceCluster.
vector< RawRecord > RawData
vector< ProcessedRecord > ProcessedData
AggregateType
Same order as yatishFrame::choiceAggregate (except invalid of course).