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