~ubuntu-branches/ubuntu/saucy/goldencheetah/saucy

« back to all changes in this revision

Viewing changes to src/RideFile.cpp

  • Committer: Package Import Robot
  • Author(s): KURASHIKI Satoru
  • Date: 2013-08-18 07:02:45 UTC
  • mfrom: (4.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20130818070245-zgdvb47e1k3mtgil
Tags: 3.0-3
debian/control: remove needless dependency. (Closes: #719571)

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
#include "RideFile.h"
21
21
#include "DataProcessor.h"
 
22
#include "RideEditor.h"
 
23
#include "RideMetadata.h"
 
24
#include "MetricAggregator.h"
 
25
#include "SummaryMetrics.h"
22
26
#include "Settings.h"
23
27
#include "Units.h"
24
28
#include <QtXml/QtXml>
33
37
    start = point->secs; \
34
38
}
35
39
 
36
 
#define tr(s) QObject::tr(s)
37
 
 
38
40
RideFile::RideFile(const QDateTime &startTime, double recIntSecs) :
39
41
            startTime_(startTime), recIntSecs_(recIntSecs),
40
 
            deviceType_("unknown"), data(NULL)
 
42
            deviceType_("unknown"), data(NULL), weight_(0)
41
43
{
42
44
    command = new RideFileCommand(this);
43
45
}
44
46
 
45
 
RideFile::RideFile() : recIntSecs_(0.0), deviceType_("unknown"), data(NULL)
 
47
RideFile::RideFile() : recIntSecs_(0.0), deviceType_("unknown"), data(NULL), weight_(0)
46
48
{
47
49
    command = new RideFileCommand(this);
48
50
}
49
51
 
50
52
RideFile::~RideFile()
51
53
{
 
54
    emit deleted();
52
55
    foreach(RideFilePoint *point, dataPoints_)
53
56
        delete point;
54
57
    delete command;
 
58
    //!!! if (data) delete data; // need a mechanism to notify the editor
55
59
}
56
60
 
57
61
QString
65
69
    case RideFile::kph: return QString(tr("Speed"));
66
70
    case RideFile::nm: return QString(tr("Torque"));
67
71
    case RideFile::watts: return QString(tr("Power"));
 
72
    case RideFile::xPower: return QString(tr("xPower"));
 
73
    case RideFile::NP: return QString(tr("Normalized Power"));
68
74
    case RideFile::alt: return QString(tr("Altitude"));
69
75
    case RideFile::lon: return QString(tr("Longitude"));
70
76
    case RideFile::lat: return QString(tr("Latitude"));
71
77
    case RideFile::headwind: return QString(tr("Headwind"));
72
 
    case RideFile::interval: return QString(tr("Interval"));
73
 
    default: return QString(tr("Unknown"));
74
 
    }
75
 
}
76
 
 
 
78
    case RideFile::slope: return QString(tr("Slope"));
 
79
    case RideFile::temp: return QString(tr("Temperature"));
 
80
    case RideFile::lrbalance: return QString(tr("Left/Right Balance"));
 
81
    case RideFile::interval: return QString(tr("Interval"));
 
82
    case RideFile::vam: return QString(tr("VAM"));
 
83
    case RideFile::wattsKg: return QString(tr("Watts per Kilogram"));
 
84
    default: return QString(tr("Unknown"));
 
85
    }
 
86
}
 
87
 
 
88
QString
 
89
RideFile::unitName(SeriesType series, MainWindow *main)
 
90
{
 
91
    bool useMetricUnits = main->useMetricUnits;
 
92
 
 
93
    switch (series) {
 
94
    case RideFile::secs: return QString(tr("seconds"));
 
95
    case RideFile::cad: return QString(tr("rpm"));
 
96
    case RideFile::hr: return QString(tr("bpm"));
 
97
    case RideFile::km: return QString(useMetricUnits ? tr("km") : tr("miles"));
 
98
    case RideFile::kph: return QString(useMetricUnits ? tr("kph") : tr("mph"));
 
99
    case RideFile::nm: return QString(tr("N"));
 
100
    case RideFile::watts: return QString(tr("watts"));
 
101
    case RideFile::xPower: return QString(tr("watts"));
 
102
    case RideFile::NP: return QString(tr("watts"));
 
103
    case RideFile::alt: return QString(useMetricUnits ? tr("metres") : tr("feet"));
 
104
    case RideFile::lon: return QString(tr("lon"));
 
105
    case RideFile::lat: return QString(tr("lat"));
 
106
    case RideFile::headwind: return QString(tr("kph"));
 
107
    case RideFile::slope: return QString(tr("%"));
 
108
    case RideFile::temp: return QString(tr("°C"));
 
109
    case RideFile::lrbalance: return QString(tr("%"));
 
110
    case RideFile::interval: return QString(tr("Interval"));
 
111
    case RideFile::vam: return QString(tr("meters per hour"));
 
112
    case RideFile::wattsKg: return QString(useMetricUnits ? tr("watts/kg") : tr("watts/lb"));
 
113
    default: return QString(tr("Unknown"));
 
114
    }
 
115
}
77
116
 
78
117
void
79
118
RideFile::clearIntervals()
89
128
    intervals_.clear();
90
129
    double start = 0.0;
91
130
    int interval = dataPoints().first()->interval;
92
 
    const RideFilePoint *point, *previous;
 
131
    const RideFilePoint *point=NULL, *previous=NULL;
93
132
    foreach (point, dataPoints()) {
94
133
        if (point->interval != interval)
95
134
            mark();
151
190
    QVector<RideFilePoint*>::const_iterator i = std::lower_bound(
152
191
        dataPoints_.begin(), dataPoints_.end(), &p, ComparePointSecs());
153
192
    if (i == dataPoints_.end())
154
 
        return dataPoints_.size();
 
193
        return dataPoints_.size()-1;
155
194
    return i - dataPoints_.begin();
156
195
}
157
196
 
169
208
    return i - dataPoints_.begin();
170
209
}
171
210
 
172
 
void RideFile::writeAsCsv(QFile &file, bool bIsMetric) const
173
 
{
174
 
 
175
 
    // Use the column headers that make WKO+ happy.
176
 
    double convertUnit;
177
 
    QTextStream out(&file);
178
 
    if (!bIsMetric)
179
 
    {
180
 
        out << "Minutes,Torq (N-m),MPH,Watts,Miles,Cadence,Hrate,ID,Altitude (feet)\n";
181
 
        convertUnit = MILES_PER_KM;
182
 
    }
183
 
    else {
184
 
        out << "Minutes,Torq (N-m),Km/h,Watts,Km,Cadence,Hrate,ID,Altitude (m)\n";
185
 
        convertUnit = 1.0;
186
 
    }
187
 
 
188
 
    foreach (const RideFilePoint *point, dataPoints()) {
189
 
        if (point->secs == 0.0)
190
 
            continue;
191
 
        out << point->secs/60.0;
192
 
        out << ",";
193
 
        out << ((point->nm >= 0) ? point->nm : 0.0);
194
 
        out << ",";
195
 
        out << ((point->kph >= 0) ? (point->kph * convertUnit) : 0.0);
196
 
        out << ",";
197
 
        out << ((point->watts >= 0) ? point->watts : 0.0);
198
 
        out << ",";
199
 
        out << point->km * convertUnit;
200
 
        out << ",";
201
 
        out << point->cad;
202
 
        out << ",";
203
 
        out << point->hr;
204
 
        out << ",";
205
 
        out << point->interval;
206
 
        out << ",";
207
 
        out << point->alt;
208
 
        out << "\n";
209
 
    }
210
 
 
211
 
    file.close();
212
 
}
213
211
 
214
212
RideFileFactory *RideFileFactory::instance_;
215
213
 
235
233
    return readFuncs_.keys();
236
234
}
237
235
 
 
236
QStringList RideFileFactory::writeSuffixes() const
 
237
{
 
238
    QStringList returning;
 
239
    QMapIterator<QString,RideFileReader*> i(readFuncs_);
 
240
    while (i.hasNext()) {
 
241
        i.next();
 
242
        if (i.value()->hasWrite()) returning << i.key();
 
243
    }
 
244
    return returning;
 
245
}
 
246
 
238
247
QRegExp
239
248
RideFileFactory::rideFileRegExp() const
240
249
{
243
252
    return QRegExp(s.arg(suffixList.join("|")), Qt::CaseInsensitive);
244
253
}
245
254
 
246
 
RideFile *RideFileFactory::openRideFile(QFile &file,
247
 
                                           QStringList &errors) const
 
255
bool
 
256
RideFileFactory::writeRideFile(MainWindow *main, const RideFile *ride, QFile &file, QString format) const
 
257
{
 
258
    // get the ride file writer for this format
 
259
    RideFileReader *reader = readFuncs_.value(format.toLower());
 
260
 
 
261
    // write away
 
262
    if (!reader) return false;
 
263
    else return reader->writeRideFile(main, ride, file);
 
264
}
 
265
 
 
266
RideFile *RideFileFactory::openRideFile(MainWindow *main, QFile &file,
 
267
                                           QStringList &errors, QList<RideFile*> *rideList) const
248
268
{
249
269
    QString suffix = file.fileName();
250
270
    int dot = suffix.lastIndexOf(".");
252
272
    suffix.remove(0, dot + 1);
253
273
    RideFileReader *reader = readFuncs_.value(suffix.toLower());
254
274
    assert(reader);
255
 
    RideFile *result = reader->openRideFile(file, errors);
 
275
//qDebug()<<"open"<<file.fileName()<<"start:"<<QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
 
276
    RideFile *result = reader->openRideFile(file, errors, rideList);
 
277
//qDebug()<<"open"<<file.fileName()<<"end:"<<QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
256
278
 
257
279
    // NULL returned to indicate openRide failed
258
280
    if (result) {
 
281
        result->mainwindow = main;
259
282
        if (result->intervals().empty()) result->fillInIntervals();
260
283
 
 
284
 
261
285
        // override the file ride time with that set from the filename
262
286
        // but only if it matches the GC format
263
287
        QFileInfo fileInfo(file.fileName());
271
295
            result->setStartTime(datetime);
272
296
        }
273
297
 
274
 
        result->setTag("Filename", file.fileName());
 
298
        // legacy support for .notes file
 
299
        QString notesFileName = fileInfo.absolutePath() + '/' + fileInfo.baseName() + ".notes";
 
300
        QFile notesFile(notesFileName);
 
301
 
 
302
        // read it in if it exists and "Notes" is not already set
 
303
        if (result->getTag("Notes", "") == "" && notesFile.exists() &&
 
304
            notesFile.open(QFile::ReadOnly | QFile::Text)) {
 
305
            QTextStream in(&notesFile);
 
306
            result->setTag("Notes", in.readAll());
 
307
            notesFile.close();
 
308
        }
 
309
 
 
310
        // Construct the summary text used on the calendar
 
311
        QString calendarText;
 
312
        foreach (FieldDefinition field, main->rideMetadata()->getFields()) {
 
313
            if (field.diary == true && result->getTag(field.name, "") != "") {
 
314
                calendarText += QString("%1\n")
 
315
                        .arg(result->getTag(field.name, ""));
 
316
            }
 
317
        }
 
318
        result->setTag("Calendar Text", calendarText);
 
319
 
 
320
        // set other "special" fields
 
321
        result->setTag("Filename", QFileInfo(file.fileName()).fileName());
 
322
        result->setTag("Device", result->deviceType());
 
323
        result->setTag("File Format", result->fileFormat());
275
324
        result->setTag("Athlete", QFileInfo(file).dir().dirName());
 
325
        result->setTag("Year", result->startTime().toString("yyyy"));
 
326
        result->setTag("Month", result->startTime().toString("MMMM"));
 
327
        result->setTag("Weekday", result->startTime().toString("ddd"));
 
328
 
276
329
        DataProcessorFactory::instance().autoProcess(result);
 
330
 
 
331
        // what data is present - after processor in case 'derived' or adjusted
 
332
        QString flags;
 
333
 
 
334
        if (result->areDataPresent()->secs) flags += 'T'; // time
 
335
        else flags += '-';
 
336
        if (result->areDataPresent()->km) flags += 'D'; // distance
 
337
        else flags += '-';
 
338
        if (result->areDataPresent()->kph) flags += 'S'; // speed
 
339
        else flags += '-';
 
340
        if (result->areDataPresent()->watts) flags += 'P'; // Power
 
341
        else flags += '-';
 
342
        if (result->areDataPresent()->hr) flags += 'H'; // Heartrate
 
343
        else flags += '-';
 
344
        if (result->areDataPresent()->cad) flags += 'C'; // cadence
 
345
        else flags += '-';
 
346
        if (result->areDataPresent()->nm) flags += 'N'; // Torque
 
347
        else flags += '-';
 
348
        if (result->areDataPresent()->alt) flags += 'A'; // Altitude
 
349
        else flags += '-';
 
350
        if (result->areDataPresent()->lat ||
 
351
            result->areDataPresent()->lon ) flags += 'G'; // GPS
 
352
        else flags += '-';
 
353
        if (result->areDataPresent()->headwind) flags += 'W'; // Windspeed
 
354
        else flags += '-';
 
355
        if (result->areDataPresent()->temp) flags += 'E'; // Temperature
 
356
        else flags += '-';
 
357
        if (result->areDataPresent()->lrbalance) flags += 'B'; // Left/Right Balance, TODO Walibu, unsure about this flag? 'B' ok?
 
358
        else flags += '-';
 
359
        result->setTag("Data", flags);
 
360
 
277
361
    }
278
362
 
279
363
    return result;
288
372
        filters << ("*." + i.key());
289
373
    }
290
374
    // This will read the user preferences and change the file list order as necessary:
291
 
    boost::shared_ptr<QSettings> settings = GetApplicationSettings();
292
 
    QVariant isAscending = settings->value(GC_ALLRIDES_ASCENDING,Qt::Checked);
293
375
    QFlags<QDir::Filter> spec = QDir::Files;
294
376
#ifdef Q_OS_WIN32
295
377
    spec |= QDir::Hidden;
296
378
#endif
297
 
    if(isAscending.toInt()>0){
298
 
        return dir.entryList(filters, spec, QDir::Name);
299
 
    }
300
 
    return dir.entryList(filters, spec, QDir::Name|QDir::Reversed);
 
379
    return dir.entryList(filters, spec, QDir::Name);
301
380
}
302
381
 
303
382
void RideFile::appendPoint(double secs, double cad, double hr, double km,
304
383
                           double kph, double nm, double watts, double alt,
305
 
                           double lon, double lat, double headwind, int interval)
 
384
                           double lon, double lat, double headwind,
 
385
                           double slope, double temp, double lrbalance, int interval)
306
386
{
307
387
    // negative values are not good, make them zero
308
 
    // although alt, lat, lon, headwind can be negative of course!
 
388
    // although alt, lat, lon, headwind, slope and temperature can be negative of course!
309
389
    if (!isfinite(secs) || secs<0) secs=0;
310
390
    if (!isfinite(cad) || cad<0) cad=0;
311
391
    if (!isfinite(hr) || hr<0) hr=0;
316
396
    if (!isfinite(interval) || interval<0) interval=0;
317
397
 
318
398
    dataPoints_.append(new RideFilePoint(secs, cad, hr, km, kph,
319
 
                                         nm, watts, alt, lon, lat, headwind, interval));
320
 
    dataPresent.secs  |= (secs != 0);
321
 
    dataPresent.cad   |= (cad != 0);
322
 
    dataPresent.hr    |= (hr != 0);
323
 
    dataPresent.km    |= (km != 0);
324
 
    dataPresent.kph   |= (kph != 0);
325
 
    dataPresent.nm    |= (nm != 0);
326
 
    dataPresent.watts |= (watts != 0);
327
 
    dataPresent.alt   |= (alt != 0);
328
 
    dataPresent.lon   |= (lon != 0);
329
 
    dataPresent.lat   |= (lat != 0);
 
399
                                         nm, watts, alt, lon, lat, headwind, slope, temp, lrbalance, interval));
 
400
    dataPresent.secs     |= (secs != 0);
 
401
    dataPresent.cad      |= (cad != 0);
 
402
    dataPresent.hr       |= (hr != 0);
 
403
    dataPresent.km       |= (km != 0);
 
404
    dataPresent.kph      |= (kph != 0);
 
405
    dataPresent.nm       |= (nm != 0);
 
406
    dataPresent.watts    |= (watts != 0);
 
407
    dataPresent.alt      |= (alt != 0);
 
408
    dataPresent.lon      |= (lon != 0);
 
409
    dataPresent.lat      |= (lat != 0);
330
410
    dataPresent.headwind |= (headwind != 0);
 
411
    dataPresent.slope    |= (slope != 0);
 
412
    dataPresent.temp     |= (temp != noTemp);
 
413
    dataPresent.lrbalance|= (lrbalance != 0);
331
414
    dataPresent.interval |= (interval != 0);
332
415
}
333
416
 
 
417
void RideFile::appendPoint(const RideFilePoint &point)
 
418
{
 
419
    dataPoints_.append(new RideFilePoint(point.secs,point.cad,point.hr,point.km,point.kph,point.nm,point.watts,point.alt,point.lon,point.lat,
 
420
                                         point.headwind, point.slope, point.temp, point.lrbalance, point.interval));
 
421
}
 
422
 
334
423
void
335
424
RideFile::setDataPresent(SeriesType series, bool value)
336
425
{
346
435
        case lon : dataPresent.lon = value; break;
347
436
        case lat : dataPresent.lat = value; break;
348
437
        case headwind : dataPresent.headwind = value; break;
 
438
        case slope : dataPresent.slope = value; break;
 
439
        case temp : dataPresent.temp = value; break;
 
440
        case lrbalance : dataPresent.lrbalance = value; break;
349
441
        case interval : dataPresent.interval = value; break;
 
442
        default:
350
443
        case none : break;
351
444
    }
352
445
}
366
459
        case lon : return dataPresent.lon; break;
367
460
        case lat : return dataPresent.lat; break;
368
461
        case headwind : return dataPresent.headwind; break;
 
462
        case slope : return dataPresent.slope; break;
 
463
        case temp : return dataPresent.temp; break;
 
464
        case lrbalance : return dataPresent.lrbalance; break;
369
465
        case interval : return dataPresent.interval; break;
370
 
        case none : break;
 
466
        default:
 
467
        case none : return false; break;
371
468
    }
372
469
    return false;
373
470
}
386
483
        case lon : dataPoints_[index]->lon = value; break;
387
484
        case lat : dataPoints_[index]->lat = value; break;
388
485
        case headwind : dataPoints_[index]->headwind = value; break;
 
486
        case slope : dataPoints_[index]->slope = value; break;
 
487
        case temp : dataPoints_[index]->temp = value; break;
 
488
        case lrbalance : dataPoints_[index]->lrbalance = value; break;
389
489
        case interval : dataPoints_[index]->interval = value; break;
 
490
        default:
390
491
        case none : break;
391
492
    }
392
493
}
393
494
 
394
495
double
395
 
RideFile::getPointValue(int index, SeriesType series)
 
496
RideFilePoint::value(RideFile::SeriesType series) const
396
497
{
397
498
    switch (series) {
398
 
        case secs : return dataPoints_[index]->secs; break;
399
 
        case cad : return dataPoints_[index]->cad; break;
400
 
        case hr : return dataPoints_[index]->hr; break;
401
 
        case km : return dataPoints_[index]->km; break;
402
 
        case kph : return dataPoints_[index]->kph; break;
403
 
        case nm : return dataPoints_[index]->nm; break;
404
 
        case watts : return dataPoints_[index]->watts; break;
405
 
        case alt : return dataPoints_[index]->alt; break;
406
 
        case lon : return dataPoints_[index]->lon; break;
407
 
        case lat : return dataPoints_[index]->lat; break;
408
 
        case headwind : return dataPoints_[index]->headwind; break;
409
 
        case interval : return dataPoints_[index]->interval; break;
410
 
        case none : break;
 
499
        case RideFile::secs : return secs; break;
 
500
        case RideFile::cad : return cad; break;
 
501
        case RideFile::hr : return hr; break;
 
502
        case RideFile::km : return km; break;
 
503
        case RideFile::kph : return kph; break;
 
504
        case RideFile::nm : return nm; break;
 
505
        case RideFile::watts : return watts; break;
 
506
        case RideFile::alt : return alt; break;
 
507
        case RideFile::lon : return lon; break;
 
508
        case RideFile::lat : return lat; break;
 
509
        case RideFile::headwind : return headwind; break;
 
510
        case RideFile::slope : return slope; break;
 
511
        case RideFile::temp : return temp; break;
 
512
        case RideFile::lrbalance : return lrbalance; break;
 
513
        case RideFile::interval : return interval; break;
 
514
 
 
515
        default:
 
516
        case RideFile::none : break;
411
517
    }
412
 
    return 0.0; // shutup the compiler
 
518
    return 0.0;
 
519
}
 
520
 
 
521
double
 
522
RideFile::getPointValue(int index, SeriesType series) const
 
523
{
 
524
    return dataPoints_[index]->value(series);
 
525
}
 
526
 
 
527
QVariant
 
528
RideFile::getPoint(int index, SeriesType series) const
 
529
{
 
530
    double value = getPointValue(index, series);
 
531
    if (series==RideFile::temp && value == RideFile::noTemp)
 
532
        return "";
 
533
    else if (series==RideFile::wattsKg)
 
534
        return "";
 
535
    return value;
413
536
}
414
537
 
415
538
int
423
546
        case kph : return 4; break;
424
547
        case nm : return 2; break;
425
548
        case watts : return 0; break;
 
549
        case xPower : return 0; break;
 
550
        case NP : return 0; break;
426
551
        case alt : return 3; break;
427
552
        case lon : return 6; break;
428
553
        case lat : return 6; break;
429
554
        case headwind : return 4; break;
 
555
        case slope : return 1; break;
 
556
        case temp : return 1; break;
430
557
        case interval : return 0; break;
 
558
        case vam : return 0; break;
 
559
        case wattsKg : return 2; break;
 
560
        case lrbalance : return 1; break;
431
561
        case none : break;
432
562
    }
433
563
    return 2; // default
438
568
{
439
569
    switch (series) {
440
570
        case secs : return 999999; break;
441
 
        case cad : return 300; break;
442
 
        case hr : return 300; break;
 
571
        case cad : return 255; break;
 
572
        case hr : return 255; break;
443
573
        case km : return 999999; break;
444
 
        case kph : return 999; break;
445
 
        case nm : return 999; break;
446
 
        case watts : return 4000; break;
 
574
        case kph : return 150; break;
 
575
        case nm : return 100; break;
 
576
        case watts : return 2500; break;
 
577
        case NP : return 2500; break;
 
578
        case xPower : return 2500; break;
447
579
        case alt : return 8850; break; // mt everest is highest point above sea level
448
580
        case lon : return 180; break;
449
581
        case lat : return 90; break;
450
582
        case headwind : return 999; break;
 
583
        case slope : return 100; break;
 
584
        case temp : return 100; break;
451
585
        case interval : return 999; break;
 
586
        case vam : return 9999; break;
 
587
        case wattsKg : return 50; break;
 
588
        case lrbalance : return 100; break;
452
589
        case none : break;
453
590
    }
454
591
    return 9999; // default
465
602
        case kph : return 0; break;
466
603
        case nm : return 0; break;
467
604
        case watts : return 0; break;
 
605
        case xPower : return 0; break;
 
606
        case NP : return 0; break;
468
607
        case alt : return -413; break; // the Red Sea is lowest land point on earth
469
608
        case lon : return -180; break;
470
609
        case lat : return -90; break;
471
610
        case headwind : return -999; break;
 
611
        case slope : return -100; break;
 
612
        case temp : return -100; break;
472
613
        case interval : return 0; break;
 
614
        case vam : return 0; break;
 
615
        case wattsKg : return 0; break;
 
616
        case lrbalance : return 0; break;
473
617
        case none : break;
474
618
    }
475
619
    return 0; // default
504
648
void
505
649
RideFile::emitSaved()
506
650
{
 
651
    weight_ = 0;
507
652
    emit saved();
508
653
}
509
654
 
510
655
void
511
656
RideFile::emitReverted()
512
657
{
 
658
    weight_ = 0;
513
659
    emit reverted();
514
660
}
515
661
 
516
662
void
517
663
RideFile::emitModified()
518
664
{
 
665
    weight_ = 0;
519
666
    emit modified();
520
667
}
 
668
 
 
669
double
 
670
RideFile::getWeight()
 
671
{
 
672
    if (weight_) return weight_; // cached value
 
673
 
 
674
    // ride
 
675
    if ((weight_ = getTag("Weight", "0.0").toDouble()) > 0) {
 
676
        return weight_;
 
677
    }
 
678
 
 
679
    // withings?
 
680
    QList<SummaryMetrics> measures = mainwindow->metricDB->getAllMeasuresFor(QDateTime::fromString("Jan 1 00:00:00 1900"), startTime());
 
681
    int i = measures.count()-1;
 
682
    if (i) {
 
683
        while (i>=0) {
 
684
            if ((weight_ = measures[i].getText("Weight", "0.0").toDouble()) > 0) {
 
685
               return weight_;
 
686
            }
 
687
            i--;
 
688
        }
 
689
    }
 
690
 
 
691
 
 
692
    // global options
 
693
    weight_ = appsettings->cvalue(mainwindow->cyclist, GC_WEIGHT, "75.0").toString().toDouble(); // default to 75kg
 
694
 
 
695
    // if set to zero in global options then override it.
 
696
    // it must not be zero!!!
 
697
    if (weight_ <= 0.00) weight_ = 75.00;
 
698
 
 
699
    return weight_;
 
700
}