diff --git a/src/lib/aqdiagram/data/date.c b/src/lib/aqdiagram/data/date.c index 3527663..3244a0c 100644 --- a/src/lib/aqdiagram/data/date.c +++ b/src/lib/aqdiagram/data/date.c @@ -235,7 +235,6 @@ AQDG_GRAPH_DATAPAIR_LIST *AQDG_Data_MinutesAverage(const AQDG_GRAPH_DATAPAIR_LIS /* new date */ newDp=AQDG_Graph_DataPair_new(); AQDG_Graph_DataPair_SetValueX(newDp, (floor(currentTimeMinutes/(double) minutes)*(double) minutes)*60.0); -// AQDG_Graph_DataPair_SetValueX(newDp, floor(currentTimeMinutes*60.0)); AQDG_Graph_DataPair_SetValueY(newDp, currentSum/(double)currentCount); AQDG_Graph_DataPair_List_Add(newDp, newList); @@ -253,7 +252,6 @@ AQDG_GRAPH_DATAPAIR_LIST *AQDG_Data_MinutesAverage(const AQDG_GRAPH_DATAPAIR_LIS /* store data for last value */ newDp=AQDG_Graph_DataPair_new(); AQDG_Graph_DataPair_SetValueX(newDp, (floor(currentTimeMinutes/(double) minutes)*(double) minutes)*60.0); -// AQDG_Graph_DataPair_SetValueX(newDp, floor(currentTimeMinutes*60.0)); AQDG_Graph_DataPair_SetValueY(newDp, currentSum/(double)currentCount); AQDG_Graph_DataPair_List_Add(newDp, newList); } @@ -264,3 +262,137 @@ AQDG_GRAPH_DATAPAIR_LIST *AQDG_Data_MinutesAverage(const AQDG_GRAPH_DATAPAIR_LIS +AQDG_GRAPH_DATAPAIR_LIST *AQDG_Data_MinutesMax(const AQDG_GRAPH_DATAPAIR_LIST *dpList, int minutes) +{ + if (dpList && AQDG_Graph_DataPair_List_GetCount(dpList)) { + AQDG_GRAPH_DATAPAIR_LIST *newList; + const AQDG_GRAPH_DATAPAIR *dp; + double currentTimeMinutes=0; + double currentTimeValue; + double currentMax; + int currentCount=0; + + newList=AQDG_Graph_DataPair_List_new(); + dp=AQDG_Graph_DataPair_List_First(dpList); + while(dp) { + if (currentCount==0) { + + /* first value */ + currentTimeValue=AQDG_Graph_DataPair_GetValueX(dp); + currentTimeMinutes=floor(currentTimeValue/60.0); + currentMax=AQDG_Graph_DataPair_GetValueY(dp); + currentCount=1; + } + else { + double newTimeValue; + double newTimeMinutes; + + newTimeValue=AQDG_Graph_DataPair_GetValueX(dp); + newTimeMinutes=floor(newTimeValue/60.0); + if ((newTimeMinutes-currentTimeMinutes)<(double)minutes) { + double v; + + v=AQDG_Graph_DataPair_GetValueY(dp); + currentMax=(v>currentMax)?v:currentMax; + currentCount++; + } + else { + AQDG_GRAPH_DATAPAIR *newDp; + + /* new date */ + newDp=AQDG_Graph_DataPair_new(); + AQDG_Graph_DataPair_SetValueX(newDp, (floor(currentTimeMinutes/(double) minutes)*(double) minutes)*60.0); + AQDG_Graph_DataPair_SetValueY(newDp, currentMax); + AQDG_Graph_DataPair_List_Add(newDp, newList); + + currentMax=AQDG_Graph_DataPair_GetValueY(dp); + currentCount=1; + currentTimeValue=newTimeValue; + currentTimeMinutes=newTimeMinutes; + } + } + dp=AQDG_Graph_DataPair_List_Next(dp); + } + if (currentCount) { + AQDG_GRAPH_DATAPAIR *newDp; + + /* store data for last value */ + newDp=AQDG_Graph_DataPair_new(); + AQDG_Graph_DataPair_SetValueX(newDp, (floor(currentTimeMinutes/(double) minutes)*(double) minutes)*60.0); + AQDG_Graph_DataPair_SetValueY(newDp, currentMax); + AQDG_Graph_DataPair_List_Add(newDp, newList); + } + return newList; + } + return NULL; +} + + + +AQDG_GRAPH_DATAPAIR_LIST *AQDG_Data_MinutesMin(const AQDG_GRAPH_DATAPAIR_LIST *dpList, int minutes) +{ + if (dpList && AQDG_Graph_DataPair_List_GetCount(dpList)) { + AQDG_GRAPH_DATAPAIR_LIST *newList; + const AQDG_GRAPH_DATAPAIR *dp; + double currentTimeMinutes=0; + double currentTimeValue; + double currentMin; + int currentCount=0; + + newList=AQDG_Graph_DataPair_List_new(); + dp=AQDG_Graph_DataPair_List_First(dpList); + while(dp) { + if (currentCount==0) { + + /* first value */ + currentTimeValue=AQDG_Graph_DataPair_GetValueX(dp); + currentTimeMinutes=floor(currentTimeValue/60.0); + currentMin=AQDG_Graph_DataPair_GetValueY(dp); + currentCount=1; + } + else { + double newTimeValue; + double newTimeMinutes; + + newTimeValue=AQDG_Graph_DataPair_GetValueX(dp); + newTimeMinutes=floor(newTimeValue/60.0); + if ((newTimeMinutes-currentTimeMinutes)<(double)minutes) { + double v; + + v=AQDG_Graph_DataPair_GetValueY(dp); + currentMin=(v +#include + #include +#include + /* ------------------------------------------------------------------------------------------------ @@ -23,6 +28,7 @@ static void _setupTicksForTimeAxis(AQDG_GRAPH_AXIS *axis); static void _setupTicksForDataAxis(AQDG_GRAPH_AXIS *axis); +static int _readNumFromString(const char **sPtr); @@ -154,6 +160,90 @@ void _setupTicksForDataAxis(AQDG_GRAPH_AXIS *axis) +void AQDG_TimeGraph_ModifyDataAndAddCurve(AQDG_GRAPH *g, const char *sLabel, const char *sModifier, + AQDG_GRAPH_DATAPAIR_LIST *dpList) +{ + int graphType=AQDG_GRAPH_TYPE_LINE; + const char *s; + int num; + AQDG_GRAPH_DATAPAIR_LIST *newDp; + + AQDG_Graph_DataPair_List_SortByValueX(dpList, 1); + s=sModifier; + while(*s) { + while(*s && isblank(*s)) + s++; + switch(*s) { + case 'L': graphType=AQDG_GRAPH_TYPE_LINE; s++; break; + case 'S': graphType=AQDG_GRAPH_TYPE_STEPLINE; s++; break; + case 'P': graphType=AQDG_GRAPH_TYPE_POINTS; s++; break; + case 'B': graphType=AQDG_GRAPH_TYPE_BARS; s++; break; + case 'd': + newDp=AQDG_Data_DayAverage(dpList); + AQDG_Graph_DataPair_List_free(dpList); + dpList=newDp; + AQDG_Graph_DataPair_List_SortByValueX(dpList, 1); + break; + case 'm': + s++; + num=_readNumFromString(&s); + newDp=AQDG_Data_MinutesAverage(dpList, num); + AQDG_Graph_DataPair_List_free(dpList); + dpList=newDp; + AQDG_Graph_DataPair_List_SortByValueX(dpList, 1); + break; + case 'f': + s++; + num=_readNumFromString(&s); + newDp=AQDG_Data_FloatingAverage(dpList, num); + AQDG_Graph_DataPair_List_free(dpList); + dpList=newDp; + AQDG_Graph_DataPair_List_SortByValueX(dpList, 1); + break; + case 'a': + s++; + num=_readNumFromString(&s); + newDp=AQDG_Data_MinutesMax(dpList, num); + AQDG_Graph_DataPair_List_free(dpList); + dpList=newDp; + AQDG_Graph_DataPair_List_SortByValueX(dpList, 1); + break; + case 'i': + s++; + num=_readNumFromString(&s); + newDp=AQDG_Data_MinutesMin(dpList, num); + AQDG_Graph_DataPair_List_free(dpList); + dpList=newDp; + AQDG_Graph_DataPair_List_SortByValueX(dpList, 1); + break; + default: + DBG_ERROR(NULL, "Invalid modifier \"%c\"", *s); + s++; + break; + } + } + + AQDG_TimeGraph_AddCurve(g, sLabel, graphType, dpList); +} + + + +int _readNumFromString(const char **sPtr) +{ + int x=0; + const char *s; + + s=*sPtr; + while(*s && isdigit(*s)) { + unsigned int i; + + i=*(s++)-'0'; + x*=10; + x+=i; + } + *sPtr=s; + return x; +} diff --git a/src/lib/aqdiagram/graph/timegraph.h b/src/lib/aqdiagram/graph/timegraph.h index dc7362d..5a93fb4 100644 --- a/src/lib/aqdiagram/graph/timegraph.h +++ b/src/lib/aqdiagram/graph/timegraph.h @@ -28,6 +28,24 @@ AQDG_API void AQDG_TimeGraph_AddCurve(AQDG_GRAPH *g, const char *sLabel, int gra AQDG_API void AQDG_TimeGraph_SetupTicks(AQDG_GRAPH *g, uint32_t flags, double minY, double maxY); +/** + * @param g graph object to add curve to + * @param sLabel label for the new curve + * @param sModifier modifier determining the curve setup + * - first char L=line graph, P=points graph, B=bar graph, S=step graph + * - following chars: + * - d=average data over days + * - mXXX=average data over minutes (XXX=minutes) + * - fXXX=floating average (XXX=number of data points to average) + * - aXXX=max data over minutes (XXX=minutes) + * - iXXX=min data over minutes (XXX=minutes) + * @param dpList list of datapoints for the curve (is taken over by this function) + */ +AQDG_API void AQDG_TimeGraph_ModifyDataAndAddCurve(AQDG_GRAPH *g, + const char *sLabel, + const char *sModifier, + AQDG_GRAPH_DATAPAIR_LIST *dpList); + #endif diff --git a/src/lib/aqdiagram/graph/w_legend.c b/src/lib/aqdiagram/graph/w_legend.c index eebf745..c548c9a 100644 --- a/src/lib/aqdiagram/graph/w_legend.c +++ b/src/lib/aqdiagram/graph/w_legend.c @@ -50,6 +50,8 @@ AQDG_OBJECT *AQDG_LegendWidget_new(AQDG_OBJECT *parent, uint32_t options, AQDG_O GWEN_INHERIT_SETDATA(AQDG_OBJECT, AQDG_WIDGET_LEGEND, o, xo, _freeData); xo->graphWidget=graphWidget; + AQDG_Object_SetVSpacing(o, 1); + AQDG_Object_SetHSpacing(o, 1); _setupWidget(o, xo); return o;