Files
GoldenCheetah/ptpk.c
Sean C. Rhea aae0d3c116 initial import
2006-09-06 23:59:42 +00:00

230 lines
7.6 KiB
C

/*
* $Id: ptpk.c,v 1.1 2006/05/27 16:17:25 srhea Exp $
*
* Copyright (c) 2006 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include <errno.h>
#include <math.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "pt.h"
void
pt_pack(FILE *in, FILE *out, int wheel_sz_mm, int rec_int)
{
double mins, nm, mph, watts, miles;
int cad, hr, interval = 0;
double last_mins = 0.0, last_miles = 0.0;
int last_interval = 0;
int i;
struct tm start_tm, inc_tm;
time_t start_time, inc_time;
int lineno = 1;
char line[256];
unsigned char buf[6];
regex_t date_reg;
int date_nmatch = 7;
regmatch_t *date_pmatch =
(regmatch_t*) calloc(date_nmatch, sizeof(regmatch_t));
regex_t rider_reg;
int rider_nmatch = 12;
regmatch_t *rider_pmatch =
(regmatch_t*) calloc(rider_nmatch, sizeof(regmatch_t));
if (regcomp(&date_reg, "^<RideDate>([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]?)</RideDate> *$", REG_EXTENDED))
assert(0);
if (regcomp(&rider_reg, "^<Rider><Minutes>([0-9]+\\.[0-9]+)</Minutes>"
"<TorqinLBS>([0-9]+(\\.[0-9]+)?)</TorqinLBS>"
"<Mph>([0-9]+(\\.[0-9]+)?|NaN)</Mph><Watts>([0-9]+|NaN)</Watts>"
"<Miles>([0-9]+(\\.[0-9]+)?)</Miles><Cadence>([0-9]+)</Cadence>"
"<Hrate>([0-9]+|NaN)</Hrate><ID>([0-9]+)</ID></Rider>$",
REG_EXTENDED))
assert(0);
pt_pack_header(buf);
pt_write_data(out, buf);
while (fgets(line, sizeof(line), in)) {
line[strlen(line) - 1] = '\0'; /* drop newline */
if (strcmp(line, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>") == 0) {
/* ignore it */
}
else if (strcmp(line, "<RideData>") == 0) {
/* ignore it */
}
else if (strcmp(line, "</RideData>") == 0) {
/* ignore it */
}
else if (!regexec(&date_reg, line, date_nmatch, date_pmatch, 0)) {
for (i = 1; i < date_nmatch; ++i)
line[date_pmatch[i].rm_eo] = '\0';
memset(&start_tm, 0, sizeof(start_tm));
start_tm.tm_year = atoi(line + date_pmatch[3].rm_so) - 1900;
start_tm.tm_mon = atoi(line + date_pmatch[1].rm_so) - 1;
start_tm.tm_mday = atoi(line + date_pmatch[2].rm_so);
start_tm.tm_hour = atoi(line + date_pmatch[4].rm_so);
start_tm.tm_min = atoi(line + date_pmatch[5].rm_so);
start_tm.tm_sec = atoi(line + date_pmatch[6].rm_so);
start_tm.tm_isdst = -1;
start_time = mktime(&start_tm);
assert(start_time != -1);
pt_pack_time(buf, &start_tm);
pt_write_data(out, buf);
pt_pack_config(buf, interval, rec_int, wheel_sz_mm);
pt_write_data(out, buf);
}
else if (!regexec(&rider_reg, line, rider_nmatch, rider_pmatch, 0)) {
for (i = 1; i < rider_nmatch; ++i)
line[rider_pmatch[i].rm_eo] = '\0';
mins = atof(line + rider_pmatch[1].rm_so);
nm = atof(line + rider_pmatch[2].rm_so);
if (strcmp(line + rider_pmatch[4].rm_so, "NaN") == 0)
mph = -1.0;
else
mph = atof(line + rider_pmatch[4].rm_so);
if (strcmp(line + rider_pmatch[6].rm_so, "NaN") == 0)
watts = -1.0;
else
watts = atof(line + rider_pmatch[6].rm_so);
miles = atof(line + rider_pmatch[7].rm_so);
cad = atoi(line + rider_pmatch[9].rm_so);
if (strcmp(line + rider_pmatch[10].rm_so, "NaN") == 0)
hr = 255;
else
hr = atoi(line + rider_pmatch[10].rm_so);
interval = atoi(line + rider_pmatch[11].rm_so);
if (mins - last_mins - 0.021 > 1.0 / 60.0) {
inc_time = start_time + round((mins - 0.021000001) * 60.0);
if (!localtime_r(&inc_time, &inc_tm))
assert(0);
pt_pack_time(buf, &inc_tm);
pt_write_data(out, buf);
pt_pack_config(buf, interval, rec_int, wheel_sz_mm);
pt_write_data(out, buf);
}
else if (last_interval != interval) {
pt_pack_config(buf, interval, rec_int, wheel_sz_mm);
pt_write_data(out, buf);
}
pt_pack_data(buf, wheel_sz_mm, nm, mph,
miles - last_miles, cad, hr);
pt_write_data(out, buf);
last_mins = mins;
last_interval = interval;
last_miles = miles;
}
else {
fprintf(stderr, "ERROR: line %d unrecognized: \"%s\"\n",
lineno, line);
exit(1);
}
++lineno;
}
}
static void
usage(const char *progname)
{
fprintf(stderr, "usage: %s [-o <output file>] [-r <recording interval>]"
"[-w <wheel size (mm)>] [<input file>]\n",
progname);
exit(1);
}
int
main(int argc, char *argv[])
{
int ch, i;
int wheel_sz_mm = 2096;
int rec_int = 1;
char *inname = NULL, *outname = NULL;
FILE *in, *out = NULL;
while ((ch = getopt(argc, argv, "ho:r:w:")) != -1) {
switch (ch) {
case 'o':
outname = optarg;
if (strcmp(outname, "-") == 0) {
out = stdout;
outname = "STDOUT";
}
break;
case 'r':
rec_int = atoi(optarg);
break;
case 'w':
wheel_sz_mm = atoi(optarg);
break;
case 'h':
case '?':
default:
usage(argv[0]);
}
}
argc -= optind;
argv += optind;
if (argc == 0) {
in = stdin;
inname = "STDIN";
if (outname == NULL) {
out = stdout;
outname = "STDOUT";
}
}
else {
inname = argv[0];
if ((in = fopen(inname, "r")) == NULL) {
fprintf(stderr, "Couldn't open %s for reading: %s\n",
inname, strerror(errno));
exit(1);
}
if (outname == NULL) {
outname = malloc(strlen(inname) + 5);
strcpy(outname, inname);
for (i = strlen(outname); i >= 0; --i)
if (outname[i] == '.') break;
if (i >= 0)
strcpy(outname + i + 1, "raw");
else
strcpy(outname + strlen(outname), ".raw");
}
}
if ((out == NULL) && ((out = fopen(outname, "w")) == NULL)) {
fprintf(stderr, "Couldn't open %s for writing: %s\n",
outname, strerror(errno));
exit(1);
}
pt_pack(in, out, wheel_sz_mm, rec_int);
fclose(in);
fclose(out);
return 0;
}