summaryrefslogtreecommitdiff
path: root/src/charts/TimeChart.cpp
blob: c6a60b9e557449b9ea04d35dbb1d5767775273f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "TimeChart.h"
#include "ChartScene.h"
#include "DataPoint.h"

const QList<int> TimeChart::TimeUnits = QList<int>() <<
    1 << 7 << 30 << 92 << 183;

TimeChart::TimeChart()
{
}

void TimeChart::setDates(const QList<QDateTime>& dates, int period,
    int dataDirection)
{
    this->dates = dates;
    scene->setDataDirection(dataDirection);
    TimeUnit timeUnit = findTimeUnit(period);
    QDate thisIntervalStart = getIntervalStart(QDate::currentDate(), timeUnit);
    QList<DataPoint> dataSet;
    int pointsNum = getDataPointsNum(period, timeUnit);
    for(int i = 0; i < pointsNum; i++)
        dataSet.append(createDataPoint(thisIntervalStart, timeUnit, i));
    scene->setDataSet(dataSet, getTicksInterval(pointsNum));
}

int TimeChart::getDataPointsNum(int period, TimeUnit timeUnit)
{
    return period / TimeUnits.at(timeUnit);
}

int TimeChart::getTicksInterval(int pointsNum)
{
    int ticksInterval = 1;
    while(pointsNum / ticksInterval > MaxXTicks)
        ticksInterval *= 2;
    return ticksInterval;
}

TimeChart::TimeUnit TimeChart::findTimeUnit(int period)
{
    for(int unit = Day; unit < (int)TimeUnitsNum; unit++)
        if(getDataPointsNum(period, (TimeUnit)unit) <= MaxDataPoints)
            return (TimeUnit)unit;
    return HalfYear;
}

QDate TimeChart::getIntervalStart(const QDate& date, TimeUnit timeUnit)
{
    switch(timeUnit)
    {
    case Day:
        return date;
    case Week:
        return date.addDays(-date.dayOfWeek() + 1);
    case Month:
        return QDate(date.year(), date.month(), 1);
    case Quarter:
        return getQuarterStart(date);
    case HalfYear:
        return getHalfYearStart(date);
    default:
        return date;
    }
}

QDate TimeChart::getQuarterStart(const QDate& date)
{
    const int quarterLen = 3;
    int quarter = (date.month() - 1) / quarterLen;
    int startMonth = quarter * quarterLen + 1;
    return QDate(date.year(), startMonth, 1);
}

QDate TimeChart::getHalfYearStart(const QDate& date)
{
    const int secondHalfStart = 7;
    int startMonth = date.month() < secondHalfStart ? 1 : secondHalfStart;
    return QDate(date.year(), startMonth, 1);
}

QDate TimeChart::getInterval(const QDate& start, TimeUnit timeUnit,
    int num)
{
    switch(timeUnit)
    {
    case Day:
        return start.addDays(num);
    case Week:
        return start.addDays(7 * num);
    case Month:
        return start.addMonths(num);
    case Quarter:
        return start.addMonths(3 * num);
    case HalfYear:
        return start.addMonths(6 * num);
    default:
        return start;
    }
}

QDate TimeChart::getIntervalEnd(const QDate& start, TimeUnit timeUnit)
{
    return getInterval(start, timeUnit, 1).addDays(-1);
}

DataPoint TimeChart::createDataPoint(const QDate& thisIntervalStart, TimeUnit timeUnit,
    int intervalIndex)
{
    QDate startDate = getInterval(thisIntervalStart, timeUnit,
        scene->getDataDirection() * intervalIndex);
    QDate endDate = getIntervalEnd(startDate, timeUnit);
    QString xLabel = getDateLabel(startDate, timeUnit);
    int value = getCardsNumForDate(startDate, endDate);
    QString toolTipLabel = getIntervalLabel(startDate, endDate, timeUnit);
    return DataPoint(xLabel, value, toolTipLabel);
}

QString TimeChart::getDateLabel(const QDate& date, TimeUnit timeUnit)
{
    return date.toString(getIntervalFormat(timeUnit));
}

QString TimeChart::getIntervalFormat(TimeUnit timeUnit)
{
    switch(timeUnit)
    {
    case Day:
    case Week:
        return "dd.MM";
    case Month:
    case Quarter:
    case HalfYear:
        return "MM/yy";
    default:
        return "dd.MM";
    }
}

QString TimeChart::getIntervalLabel(const QDate& startDate,
    const QDate& endDate, TimeUnit timeUnit)
{
    QString startLabel = getDateLabel(startDate, timeUnit);
    if(timeUnit == Day || timeUnit == Month)
        return startLabel;
    return startLabel + " - " + getDateLabel(endDate, timeUnit);
}

int TimeChart::getCardsNumForDate(const QDate& startDate, const QDate& endDate)
{
    int cardsNum = 0;
    foreach(QDateTime date, dates)
        if(date.date() >= startDate && date.date() <= endDate)
            cardsNum++;
    return cardsNum;
}