mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 08:08:42 +00:00
converted cpint code to C++ in preparation for making it understand SRM files
This commit is contained in:
@@ -21,9 +21,9 @@
|
||||
CC=gcc
|
||||
CFLAGS=-g -W -Wall -Werror -ansi -pedantic -std=c99
|
||||
CMDS=ptdl ptpk ptunpk cpint
|
||||
LIBS=../lib/libgc.a
|
||||
LIBRARIES=-lm
|
||||
INCLUDES=-I../lib
|
||||
LIBS=../lib/libgc.a ../cpint/libcpint.a
|
||||
LIBRARIES=-lm -lQtCore
|
||||
INCLUDES=-I../lib -I../cpint
|
||||
|
||||
all: $(CMDS)
|
||||
.PHONY: all clean
|
||||
@@ -35,7 +35,7 @@ clean:
|
||||
$(CC) -c $(CFLAGS) $(INCLUDES) $<
|
||||
|
||||
cpint: cpint.o $(LIBS)
|
||||
$(CXX) -o $@ $^ $(LIBRARIES)
|
||||
$(CXX) -o $@ $^ $(LIBS) $(LIBRARIES)
|
||||
|
||||
ptdl: ptdl.o $(LIBS)
|
||||
$(CC) -o $@ $^ $(LIBRARIES)
|
||||
|
||||
@@ -25,23 +25,27 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "srm.h"
|
||||
#include "pt.h"
|
||||
#include "cpint.h"
|
||||
|
||||
struct point
|
||||
struct cpint_point
|
||||
{
|
||||
double secs;
|
||||
int watts;
|
||||
struct point *next;
|
||||
cpint_point(double s, int w) : secs(s), watts(w) {}
|
||||
};
|
||||
|
||||
static struct point *head, *tail;
|
||||
time_t start_since_epoch;
|
||||
static double last_secs;
|
||||
static int rec_int_ms;
|
||||
struct cpint_data {
|
||||
QList<cpint_point> points;
|
||||
time_t start_since_epoch;
|
||||
double last_secs;
|
||||
int rec_int_ms;
|
||||
cpint_data() : start_since_epoch(0), last_secs(0.0), rec_int_ms(0) {}
|
||||
};
|
||||
|
||||
static int
|
||||
secs_to_interval(double secs)
|
||||
secs_to_interval(double secs, int rec_int_ms)
|
||||
{
|
||||
if (rec_int_ms == 0) {
|
||||
fprintf(stderr, "Missing recording interval.\n");
|
||||
@@ -50,62 +54,56 @@ secs_to_interval(double secs)
|
||||
return (int) round(secs * 1000.0 / rec_int_ms);
|
||||
}
|
||||
|
||||
static void
|
||||
add_point(double secs, double watts)
|
||||
{
|
||||
struct point *p = (struct point*) malloc(sizeof(struct point));
|
||||
p->secs = secs;
|
||||
p->watts = watts;
|
||||
p->next = NULL;
|
||||
if (tail) tail->next = p; else head = p;
|
||||
tail = p;
|
||||
}
|
||||
|
||||
static void
|
||||
config_cb(unsigned interval, unsigned rec_int,
|
||||
unsigned wheel_sz_mm, void *context)
|
||||
{
|
||||
double new_rec_int_ms = rec_int * 1.26 * 1000.0;
|
||||
interval = wheel_sz_mm = 0;
|
||||
context = NULL;
|
||||
assert((rec_int_ms == 0.0) || (rec_int_ms == new_rec_int_ms));
|
||||
rec_int_ms = new_rec_int_ms;
|
||||
(void) interval;
|
||||
(void) wheel_sz_mm;
|
||||
cpint_data *data = (cpint_data*) context;
|
||||
int new_rec_int_ms = rec_int * 1260;
|
||||
assert((data->rec_int_ms == 0) || (data->rec_int_ms == new_rec_int_ms));
|
||||
data->rec_int_ms = new_rec_int_ms;
|
||||
}
|
||||
|
||||
static void
|
||||
time_cb(struct tm *time, time_t since_epoch, void *context)
|
||||
{
|
||||
double secs;
|
||||
context = NULL;
|
||||
time = NULL;
|
||||
if (start_since_epoch == 0)
|
||||
start_since_epoch = since_epoch;
|
||||
secs = since_epoch - start_since_epoch;
|
||||
(void) time;
|
||||
cpint_data *data = (cpint_data*) context;
|
||||
if (data->start_since_epoch == 0)
|
||||
data->start_since_epoch = since_epoch;
|
||||
double secs = since_epoch - data->start_since_epoch;
|
||||
/* Be conservative: a sleep interval counts as all zeros. */
|
||||
add_point(secs, 0.0);
|
||||
last_secs = secs;
|
||||
data->points.append(cpint_point(secs, 0));
|
||||
data->last_secs = secs;
|
||||
}
|
||||
|
||||
static void
|
||||
data_cb(double secs, double nm, double mph, double watts, double miles,
|
||||
unsigned cad, unsigned hr, unsigned interval, void *context)
|
||||
{
|
||||
context = NULL;
|
||||
nm = 0.0; miles = 0.0; cad = 0; hr = 0; interval = 0;
|
||||
cpint_data *data = (cpint_data*) context;
|
||||
(void) nm;
|
||||
(void) miles;
|
||||
(void) cad;
|
||||
(void) hr;
|
||||
(void) interval;
|
||||
/* Be conservative: count NaN's as zeros. */
|
||||
add_point(secs, (mph == -1.0) ? 0.0 : watts);
|
||||
last_secs = secs;
|
||||
data->points.append(cpint_point(secs, ((mph == -1.0) ? 0
|
||||
: (int) round(watts))));
|
||||
data->last_secs = secs;
|
||||
}
|
||||
|
||||
static void
|
||||
error_cb(const char *msg, void *context)
|
||||
{
|
||||
context = NULL;
|
||||
(void) context;
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct cpi_file_info *
|
||||
cpi_file_info *
|
||||
cpi_files_to_update(const char *dir)
|
||||
{
|
||||
DIR *dirp;
|
||||
@@ -113,7 +111,7 @@ cpi_files_to_update(const char *dir)
|
||||
regex_t reg;
|
||||
struct stat sbi, sbo;
|
||||
char *inname, *outname;
|
||||
struct cpi_file_info *head = NULL, *tail = NULL;
|
||||
cpi_file_info *head = NULL, *tail = NULL;
|
||||
|
||||
if (regcomp(®, "^([0-9][0-9][0-9][0-9])_([0-9][0-9])_([0-9][0-9])"
|
||||
"_([0-9][0-9])_([0-9][0-9])_([0-9][0-9])\\.raw$", REG_EXTENDED))
|
||||
@@ -125,16 +123,16 @@ cpi_files_to_update(const char *dir)
|
||||
int nmatch = 7;
|
||||
regmatch_t *pmatch = (regmatch_t*) calloc(nmatch, sizeof(regmatch_t));
|
||||
if (regexec(®, dp->d_name, nmatch, pmatch, 0) == 0) {
|
||||
inname = malloc(strlen(dir) + 25);
|
||||
outname = malloc(strlen(dir) + 25);
|
||||
inname = (char*) malloc(strlen(dir) + 25);
|
||||
outname = (char*) malloc(strlen(dir) + 25);
|
||||
sprintf(inname, "%s/%s", dir, dp->d_name);
|
||||
if (stat(inname, &sbi))
|
||||
assert(0);
|
||||
sprintf(outname, "%s/%s", dir, dp->d_name);
|
||||
strcpy(outname + strlen(outname) - 4, ".cpi");
|
||||
if ((stat(outname, &sbo)) || (sbo.st_mtime < sbi.st_mtime)) {
|
||||
struct cpi_file_info *info = (struct cpi_file_info*)
|
||||
malloc(sizeof(struct cpi_file_info));
|
||||
cpi_file_info *info =
|
||||
(cpi_file_info*) malloc(sizeof(cpi_file_info));
|
||||
info->file = strdup(dp->d_name);
|
||||
info->inname = inname;
|
||||
info->outname = outname;
|
||||
@@ -162,40 +160,36 @@ cpi_files_to_update(const char *dir)
|
||||
}
|
||||
|
||||
void
|
||||
update_cpi_file(struct cpi_file_info *info,
|
||||
update_cpi_file(cpi_file_info *info,
|
||||
int (*cancel_cb)(void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
FILE *in, *out;
|
||||
int canceled = 0;
|
||||
double start_secs, prev_secs, dur_secs, avg, sum;
|
||||
int dur_ints, i, total_intervals;
|
||||
int dur_ints, total_intervals;
|
||||
double *bests;
|
||||
struct point *p, *q;
|
||||
int progress_count = 0;
|
||||
|
||||
in = fopen(info->inname, "r");
|
||||
assert(in);
|
||||
out = fopen(info->outname, "w");
|
||||
assert(out);
|
||||
if (head) {
|
||||
p = head;
|
||||
while (p) { q = p; p = p->next; free(q); }
|
||||
head = tail = NULL;
|
||||
}
|
||||
start_since_epoch = 0;
|
||||
last_secs = 0.0;
|
||||
|
||||
pt_read_raw(in, 0 /* not compat */, NULL,
|
||||
cpint_data data;
|
||||
pt_read_raw(in, 0 /* not compat */, &data,
|
||||
&config_cb, &time_cb, &data_cb, &error_cb);
|
||||
|
||||
total_intervals = secs_to_interval(tail->secs);
|
||||
total_intervals =
|
||||
secs_to_interval(data.points.back().secs, data.rec_int_ms);
|
||||
bests = (double*) calloc(total_intervals + 1, sizeof(double));
|
||||
|
||||
start_secs = prev_secs = 0.0;
|
||||
for (p = head; p; p = p->next) {
|
||||
sum = 0.0;
|
||||
for (q = p; q; q = q->next) {
|
||||
for (int i = 0; i < data.points.size(); ++i) {
|
||||
cpint_point *p = &data.points[i];
|
||||
for (int j = i; j < data.points.size(); ++j) {
|
||||
sum = 0.0;
|
||||
cpint_point *q = &data.points[j];
|
||||
if (cancel_cb && (++progress_count % 1000 == 0)) {
|
||||
if (cancel_cb(user_data)) {
|
||||
canceled = 1;
|
||||
@@ -204,7 +198,7 @@ update_cpi_file(struct cpi_file_info *info,
|
||||
}
|
||||
sum += (q->secs - prev_secs) * q->watts;
|
||||
dur_secs = q->secs - start_secs;
|
||||
dur_ints = secs_to_interval(dur_secs);
|
||||
dur_ints = secs_to_interval(dur_secs, data.rec_int_ms);
|
||||
avg = sum / dur_secs;
|
||||
if (bests[dur_ints] < avg)
|
||||
bests[dur_ints] = avg;
|
||||
@@ -213,9 +207,9 @@ update_cpi_file(struct cpi_file_info *info,
|
||||
start_secs = prev_secs = p->secs;
|
||||
}
|
||||
|
||||
for (i = 0; i <= total_intervals; ++i) {
|
||||
for (int i = 0; i <= total_intervals; ++i) {
|
||||
if (bests[i] != 0)
|
||||
fprintf(out, "%6.3f %3.0f\n", i * rec_int_ms / 1000.0 / 60.0,
|
||||
fprintf(out, "%6.3f %3.0f\n", i * data.rec_int_ms / 1000.0 / 60.0,
|
||||
round(bests[i]));
|
||||
}
|
||||
|
||||
@@ -227,9 +221,9 @@ done:
|
||||
}
|
||||
|
||||
void
|
||||
free_cpi_file_info(struct cpi_file_info *head)
|
||||
free_cpi_file_info(cpi_file_info *head)
|
||||
{
|
||||
struct cpi_file_info *tmp;
|
||||
cpi_file_info *tmp;
|
||||
while (head) {
|
||||
free(head->file);
|
||||
free(head->inname);
|
||||
@@ -244,27 +238,24 @@ free_cpi_file_info(struct cpi_file_info *head)
|
||||
static int
|
||||
read_one(const char *inname, double *bests[], int *bestlen)
|
||||
{
|
||||
FILE *in;
|
||||
char line[40];
|
||||
int lineno;
|
||||
double mins;
|
||||
int watts;
|
||||
double *tmp;
|
||||
int interval;
|
||||
|
||||
if (!(in = fopen(inname, "r")))
|
||||
FILE *in = fopen(inname, "r");
|
||||
if (!in)
|
||||
return -1;
|
||||
lineno = 1;
|
||||
int lineno = 1;
|
||||
int rec_int_ms = 0;
|
||||
char line[40];
|
||||
while (fgets(line, sizeof(line), in) != NULL) {
|
||||
double mins;
|
||||
int watts;
|
||||
if (sscanf(line, "%lf %d\n", &mins, &watts) != 2) {
|
||||
fprintf(stderr, "Bad match on line %d: %s", lineno, line);
|
||||
exit(1);
|
||||
}
|
||||
if (rec_int_ms == 0)
|
||||
rec_int_ms = mins * 60.0 * 1000.0;
|
||||
interval = secs_to_interval(mins * 60.0);
|
||||
rec_int_ms = (int) round(mins * 60.0 * 1000.0);
|
||||
int interval = secs_to_interval(mins * 60.0, rec_int_ms);
|
||||
while (interval >= *bestlen) {
|
||||
tmp = calloc(*bestlen * 2, sizeof(double));
|
||||
double *tmp = (double*) calloc(*bestlen * 2, sizeof(double));
|
||||
memcpy(tmp, *bests, *bestlen * sizeof(double));
|
||||
free(*bests);
|
||||
*bests = tmp;
|
||||
@@ -281,15 +272,12 @@ read_one(const char *inname, double *bests[], int *bestlen)
|
||||
int
|
||||
read_cpi_file(const char *dir, const char *raw, double *bests[], int *bestlen)
|
||||
{
|
||||
char *inname;
|
||||
int result;
|
||||
|
||||
*bestlen = 1000;
|
||||
*bests = calloc(*bestlen, sizeof(double));
|
||||
inname = malloc(strlen(dir) + 25);
|
||||
*bests = (double*) calloc(*bestlen, sizeof(double));
|
||||
char *inname = (char*) malloc(strlen(dir) + 25);
|
||||
sprintf(inname, "%s/%s", dir, raw);
|
||||
strcpy(inname + strlen(inname) - 4, ".cpi");
|
||||
result = read_one(inname, bests, bestlen);
|
||||
int result = read_one(inname, bests, bestlen);
|
||||
free(inname);
|
||||
return result;
|
||||
}
|
||||
@@ -302,8 +290,8 @@ combine_cpi_files(const char *dir, double *bests[], int *bestlen)
|
||||
char *inname;
|
||||
|
||||
*bestlen = 1000;
|
||||
*bests = calloc(*bestlen, sizeof(double));
|
||||
inname = malloc(strlen(dir) + 25);
|
||||
*bests = (double*) calloc(*bestlen, sizeof(double));
|
||||
inname = (char*) malloc(strlen(dir) + 25);
|
||||
dirp = opendir(dir);
|
||||
assert(dirp);
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
@@ -316,4 +304,3 @@ combine_cpi_files(const char *dir, double *bests[], int *bestlen)
|
||||
free(inname);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct cpi_file_info {
|
||||
char *file, *inname, *outname;
|
||||
regmatch_t *pmatch;
|
||||
@@ -42,5 +46,9 @@ extern int read_cpi_file(const char *dir, const char *raw,
|
||||
|
||||
extern void combine_cpi_files(const char *dir, double *bests[], int *bestlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __cpint_h */
|
||||
|
||||
16
src/cpint/cpint.pro
Normal file
16
src/cpint/cpint.pro
Normal file
@@ -0,0 +1,16 @@
|
||||
######################################################################
|
||||
# Automatically generated by qmake (2.01a) Sun Apr 8 17:19:06 2007
|
||||
######################################################################
|
||||
|
||||
TEMPLATE = lib
|
||||
TARGET =
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += . ../lib ../srm
|
||||
|
||||
CONFIG += static debug
|
||||
LIBS += -lm
|
||||
|
||||
# Input
|
||||
HEADERS += cpint.h
|
||||
SOURCES += cpint.cpp
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
TEMPLATE = app
|
||||
TARGET +=
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += /home/srhea/src/qwt-5.0.1/src ../lib ../srm
|
||||
INCLUDEPATH += /home/srhea/src/qwt-5.0.1/src ../lib ../srm ../cpint
|
||||
CONFIG += static debug
|
||||
LIBS += /home/srhea/src/qwt-5.0.1/lib/libqwt.a ../lib/libgc.a
|
||||
LIBS += ../srm/libsrm.a
|
||||
LIBS += /home/srhea/src/qwt-5.0.1/lib/libqwt.a
|
||||
LIBS += ../lib/libgc.a ../cpint/libcpint.a ../srm/libsrm.a
|
||||
LIBS += -lm -lz
|
||||
macx {
|
||||
LIBS += -framework Carbon
|
||||
|
||||
@@ -28,7 +28,7 @@ all: libgc.a
|
||||
clean:
|
||||
rm -f *.o libgc.a
|
||||
|
||||
libgc.a: pt.o cpint.o
|
||||
libgc.a: pt.o # cpint.o
|
||||
rm -f $@
|
||||
ar q $@ $^
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#ifndef __pt_h
|
||||
#define __pt_h 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
@@ -96,5 +100,9 @@ extern void pt_read_dat(FILE *in,
|
||||
double, int, int, int, void*),
|
||||
void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __pt_h */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user