Added initial app with JSON weight extract.
This commit is contained in:
parent
519f3b4f6c
commit
f21fb896d7
|
@ -0,0 +1,16 @@
|
||||||
|
.dub
|
||||||
|
docs.json
|
||||||
|
__dummy.html
|
||||||
|
docs/
|
||||||
|
/fitbit-extract
|
||||||
|
fitbit-extract.so
|
||||||
|
fitbit-extract.dylib
|
||||||
|
fitbit-extract.dll
|
||||||
|
fitbit-extract.a
|
||||||
|
fitbit-extract.lib
|
||||||
|
fitbit-extract-test-*
|
||||||
|
*.exe
|
||||||
|
*.pdb
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.lst
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"Andrew Lalis"
|
||||||
|
],
|
||||||
|
"copyright": "Copyright © 2024, Andrew Lalis",
|
||||||
|
"description": "Tools for parsing and extracting data from your FitBit export.",
|
||||||
|
"license": "MIT",
|
||||||
|
"name": "fitbit-extract"
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import std.stdio;
|
||||||
|
import std.json;
|
||||||
|
import std.algorithm;
|
||||||
|
import std.array;
|
||||||
|
import std.csv;
|
||||||
|
import std.datetime;
|
||||||
|
import std.path;
|
||||||
|
import std.file;
|
||||||
|
import std.format;
|
||||||
|
|
||||||
|
int main(string[] args) {
|
||||||
|
if (args.length < 2) {
|
||||||
|
stderr.writeln("Missing required first argument for FitBit directory.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
string fitbitDir = args[1];
|
||||||
|
auto w = parseWeight(fitbitDir);
|
||||||
|
writeln("Date, Weight");
|
||||||
|
foreach (e; w) {
|
||||||
|
writefln!"%s, %0.1f"(e.date.toISOExtString, e.weight);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WeightEntry {
|
||||||
|
Date date;
|
||||||
|
float weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
WeightEntry[] parseWeight(string fitbitDir) {
|
||||||
|
string exportDataDir = buildPath(fitbitDir, "Global Export Data");
|
||||||
|
Appender!(WeightEntry[]) app;
|
||||||
|
foreach (DirEntry entry; dirEntries(exportDataDir, SpanMode.shallow, false)) {
|
||||||
|
if (startsWith(baseName(entry.name), "weight")) {
|
||||||
|
JSONValue weightArray = parseJSON(cast(string) std.file.read(entry.name));
|
||||||
|
foreach (JSONValue weightObj; weightArray.array) {
|
||||||
|
WeightEntry w;
|
||||||
|
w.weight = weightObj.object["weight"].floating;
|
||||||
|
int day, month, year;
|
||||||
|
formattedRead!"%d/%d/%d"(weightObj.object["date"].str, month, day, year);
|
||||||
|
w.date = Date(year + 2000, month, day);
|
||||||
|
|
||||||
|
bool dateAlreadyExists = false;
|
||||||
|
foreach (WeightEntry existingEntry; app[]) {
|
||||||
|
if (existingEntry.date == w.date) {
|
||||||
|
dateAlreadyExists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dateAlreadyExists) app ~= w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return app[]
|
||||||
|
.sort!((a, b) => a.date < b.date)
|
||||||
|
.array;
|
||||||
|
}
|
Loading…
Reference in New Issue