diff options
-rw-r--r-- | src/dkp-history.c | 111 |
1 files changed, 81 insertions, 30 deletions
diff --git a/src/dkp-history.c b/src/dkp-history.c index 838956c..8233427 100644 --- a/src/dkp-history.c +++ b/src/dkp-history.c @@ -196,6 +196,11 @@ EggObjList * dkp_history_get_profile_data (DkpHistory *history, gboolean charging) { guint i; + guint non_zero_accuracy = 0; + gfloat average; + guint bin; + guint oldbin = 999; + const DkpHistoryObj *obj_last = NULL; const DkpHistoryObj *obj; const DkpHistoryObj *obj_old = NULL; DkpStatsObj *stats; @@ -203,8 +208,7 @@ dkp_history_get_profile_data (DkpHistory *history, gboolean charging) EggObjList *data; guint time; gdouble value; - guint int_bin; - gdouble total_accuracy = 0.0f; + gdouble total_value = 0.0f; g_return_val_if_fail (DKP_IS_HISTORY (history), NULL); @@ -216,50 +220,87 @@ dkp_history_get_profile_data (DkpHistory *history, gboolean charging) dkp_stats_obj_free (stats); } - /* partition the array into bins */ array = history->priv->data_charge; - egg_debug ("array->len=%i", array->len); for (i=0; i<array->len; i++) { obj = (const DkpHistoryObj *) egg_obj_list_index (array, i); - if (obj_old == NULL || obj->state != obj_old->state) { - obj_old = obj; - egg_debug ("ignoring %i as not the same as prev", obj->time); - continue; - } - /* center the value on a specific time difference */ - time = obj->time - obj_old->time; - value = (obj->value + obj_old->value) / 2.0f; - if (value < 0.0001) { - egg_debug ("ignoring %i as zero", obj->time); - continue; + if (obj_last == NULL || obj->state != obj_last->state) { +// egg_debug ("ignoring %i as not the same as prev", obj->time); + obj_old = NULL; + goto cont; } - /* use the accuracy field as a counter for now */ - if ((charging && obj->state == DKP_DEVICE_STATE_CHARGING) || - (!charging && obj->state == DKP_DEVICE_STATE_DISCHARGING)) { - /* round to the nearest int */ - int_bin = rint (value); - stats = (DkpStatsObj *) egg_obj_list_index (data, int_bin); - stats->value += time; - stats->accuracy++; + /* round to the nearest int */ + bin = rint (obj->value); +// egg_debug ("data %f binned into %i", obj->value, bin); + if (oldbin != bin) { +// egg_debug ("bin changed!, %i->%i", oldbin, bin); + oldbin = bin; + if (obj_old != NULL) { + /* not enough or too much difference */ + value = fabs (obj->value - obj_old->value); + if (value < 0.01f) { +// egg_debug ("ignoring as value difference too small: %f", value); + obj_old = NULL; + goto cont; + } + if (value > 3.0f) { +// egg_debug ("ignoring as value difference too large: %f", value); + obj_old = NULL; + goto cont; + } + + time = obj->time - obj_old->time; +// egg_debug ("time difference at %i is %i", bin, time); + /* use the accuracy field as a counter for now */ + if ((charging && obj->state == DKP_DEVICE_STATE_CHARGING) || + (!charging && obj->state == DKP_DEVICE_STATE_DISCHARGING)) { + stats = (DkpStatsObj *) egg_obj_list_index (data, bin); + stats->value += time; + stats->accuracy++; + } + } + obj_old = obj; } +cont: + obj_last = obj; } - /* calculate average, and find total accuracy */ + /* divide the value by the number of samples to make the average */ for (i=0; i<101; i++) { stats = (DkpStatsObj *) egg_obj_list_index (data, i); if (stats->accuracy != 0) - stats->value /= stats->accuracy; - total_accuracy += stats->accuracy; + stats->value = stats->value / stats->accuracy; + } + + /* find non-zero accuracy values for the average */ + for (i=0; i<101; i++) { + stats = (DkpStatsObj *) egg_obj_list_index (data, i); + if (stats->accuracy > 0) { + total_value += stats->value; + non_zero_accuracy++; + } } - /* set 100% as average */ - total_accuracy = 10000.0f / total_accuracy; + /* average */ + average = total_value / non_zero_accuracy; + egg_debug ("average is %f", average); + + /* make the values a factor of 0, so that 1.0 is twice the + * average, and -1.0 is half the average */ + for (i=0; i<101; i++) { + stats = (DkpStatsObj *) egg_obj_list_index (data, i); + if (stats->accuracy > 0) + stats->value = (stats->value - average) / average; + else + stats->value = 0.0f; + } - /* normalise accuracy */ + /* accuracy is a percentage scale, where each cycle = 20% */ for (i=0; i<101; i++) { stats = (DkpStatsObj *) egg_obj_list_index (data, i); - stats->accuracy *= total_accuracy; + stats->accuracy *= 20; + if (stats->accuracy > 100.0f) + stats->accuracy = 100.0f; } return data; @@ -397,6 +438,7 @@ static gboolean dkp_history_load_data (DkpHistory *history) { gchar *filename; + DkpHistoryObj *obj; /* load rate history from disk */ filename = dkp_history_get_filename (history, "rate"); @@ -418,6 +460,15 @@ dkp_history_load_data (DkpHistory *history) egg_obj_list_from_file (history->priv->data_time_empty, filename); g_free (filename); + /* save a marker so we don't use incomplete percentages */ + obj = dkp_history_obj_create (0, DKP_DEVICE_STATE_UNKNOWN); + egg_obj_list_add (history->priv->data_rate, obj); + egg_obj_list_add (history->priv->data_charge, obj); + egg_obj_list_add (history->priv->data_time_full, obj); + egg_obj_list_add (history->priv->data_time_empty, obj); + dkp_history_obj_free (obj); + dkp_history_schedule_save (history); + return TRUE; } |