Published
Edited
Apr 3, 2021
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
viewof scale = html`<input type=range min=0.5 max=10 step=any value=1>`
Insert cell
Insert cell
path = d3.geoPath().projection(projection).pointRadius(2 / scale)
Insert cell
projection = d3.geoAlbers()
.fitExtent([[50, 50], [width - 50, height - 50]], lineString(parsed.records))
Insert cell
Insert cell
segments = {
const segments = [];
let eventStartIdx = parsed.events.findIndex(({ event_type }) => event_type == 'start');
while (eventStartIdx > -1 && eventStartIdx < parsed.events.length) {
let eventEndIdx = parsed.events.findIndex(
({ event_type }, i) => i > eventStartIdx && event_type == 'stop_all'
);
if (eventEndIdx > -1) {
let { timestamp: eventStart } = parsed.events[eventStartIdx];
let { timestamp: eventEnd } = parsed.events[eventEndIdx];
let recordStartIdx = parsed.records.findIndex(({ timestamp }) => +timestamp == +eventStart);
let recordEndIdx = parsed.records.findIndex(({ timestamp }) => +timestamp == +eventEnd);

if (recordStartIdx > -1 && recordEndIdx > -1) {
const records = parsed.records.slice(recordStartIdx, recordEndIdx);

const lastSegment = segments[segments.length - 1];
if (lastSegment) {
segments.push({
records: [ lastSegment.records[lastSegment.records.length - 1], records[0] ],
active: false,
});
}
segments.push({
records,
active: true
});
}
}

eventStartIdx = eventEndIdx;
}
return segments;
}
Insert cell
Insert cell
Insert cell
Insert cell
totalMeters = parsed.sessions.reduce((total, { total_distance }) => total_distance + total, 0)
Insert cell
totalDuration = parsed.sessions.reduce((total, { total_timer_time }) => total_timer_time + total, 0)
Insert cell
lapPoints = parsed.events
.filter((d) => d.event_type == 'start' || d.event_type == 'stop_all' || d.event_type == 'marker')
.map((d) => {
let event = d.event_type;

let recordIdx = parsed.records.findIndex((r) => +r.timestamp == +d.timestamp);

if (recordIdx > 0) { recordIdx -= 1 };
let { position_long, position_lat } = parsed.records[recordIdx] || {};
return { event, position_long, position_lat }
}).filter(({ position_long, position_lat }) => position_long && position_lat)

Insert cell
Insert cell
Insert cell
md`### Helper Functions`
Insert cell
Insert cell
pace = ({yards, seconds}) => (seconds / yards) * 100
Insert cell
Insert cell
pointColor = d3.scaleOrdinal(['start', 'stop_all', 'marker'], ['green', 'tomato', 'steelblue'])
Insert cell
point = ({ position_long, position_lat }) => {
return {
type: "Point",
coordinates: [ position_long, position_lat ]
}
}
Insert cell

lineString = (records) => {
return {
type: "LineString",
coordinates: records.map(({ position_long, position_lat }) => [ position_long, position_lat ])
}
}
Insert cell
Insert cell
md`### Imports`
Insert cell
FitParser = (await require('https://bundle.run/fit-file-parser@1.9.0')).default
Insert cell
import {fileInput} from "@mbostock/file-input-with-initial-value"
Insert cell
import { React, jsx } from '@mbostock/hello-jsx'
Insert cell
d3 = require('d3@6');
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more