190 lines
5.7 KiB
JavaScript
190 lines
5.7 KiB
JavaScript
// api_v1/scanner/processActivityFile.js
|
|
const path = require('path');
|
|
const fsp = require('fs/promises');
|
|
const { sha256 } = require('./utils');
|
|
const { log } = require('./logger');
|
|
const parseActivityFile = require('./parseActivityFile'); // 🔥 parser FIT/GPX/TCX
|
|
const loc = require('../geo.js');
|
|
const getElevation = require('./elevation');
|
|
const { WEB_ROOT, PATH_FULL } = require('../config');
|
|
|
|
// ---------------------------------------------------------
|
|
// processActivityFile → equivalente di processFile per le attività
|
|
// ---------------------------------------------------------
|
|
async function processActivityFile(userName, cartella, fileRelPath, absPath, ext, st) {
|
|
|
|
// 🔥 PARSING FIT/GPX/TCX
|
|
const parsed = await parseActivityFile(absPath);
|
|
|
|
// parsed contiene:
|
|
// {
|
|
// file_name,
|
|
// file_extension,
|
|
// format,
|
|
// display_name,
|
|
// route_name,
|
|
// title,
|
|
// description,
|
|
// notes,
|
|
// sport,
|
|
// activity_type,
|
|
// device_manufacturer,
|
|
// device_model,
|
|
// source_app,
|
|
// start_time_millis,
|
|
// end_time_millis,
|
|
// duration_millis,
|
|
// distance_meters,
|
|
// elevation_gain_meters,
|
|
// elevation_loss_meters,
|
|
// min_elevation_meters,
|
|
// max_elevation_meters,
|
|
// file_distance_meters,
|
|
// file_elevation_gain_meters,
|
|
// computed_distance_meters,
|
|
// computed_elevation_gain_meters,
|
|
// average_speed_mps,
|
|
// max_speed_mps,
|
|
// average_pace_sec_per_km,
|
|
// average_heart_rate,
|
|
// max_heart_rate,
|
|
// average_cadence,
|
|
// max_cadence,
|
|
// calories,
|
|
// power_avg,
|
|
// power_max,
|
|
// point_count,
|
|
// segment_count,
|
|
// lap_count,
|
|
// min_latitude,
|
|
// max_latitude,
|
|
// min_longitude,
|
|
// max_longitude,
|
|
// center_latitude,
|
|
// center_longitude,
|
|
// tags,
|
|
// diagnostics
|
|
// }
|
|
|
|
// ---------------------------------------------------------
|
|
// GPS → se manca altitudine, la calcoliamo
|
|
// ---------------------------------------------------------
|
|
let gps = null;
|
|
|
|
if (parsed.center_latitude != null && parsed.center_longitude != null) {
|
|
gps = {
|
|
lat: parsed.center_latitude,
|
|
lng: parsed.center_longitude,
|
|
alt: parsed.min_elevation_meters ?? null
|
|
};
|
|
|
|
if (gps.alt == null) {
|
|
gps.alt = await getElevation(gps.lat, gps.lng);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// LOCATION → come per le foto
|
|
// ---------------------------------------------------------
|
|
const location = gps ? await loc(gps.lng, gps.lat) : null;
|
|
|
|
// ---------------------------------------------------------
|
|
// PATH FULL / RELATIVI
|
|
// ---------------------------------------------------------
|
|
const relPath = fileRelPath;
|
|
|
|
const fullPath = PATH_FULL
|
|
? path.posix.join('/activities', userName, cartella, fileRelPath)
|
|
: relPath;
|
|
|
|
// ---------------------------------------------------------
|
|
// ID deterministico
|
|
// ---------------------------------------------------------
|
|
const id = sha256(`${userName}/${cartella}/${fileRelPath}`);
|
|
|
|
// ---------------------------------------------------------
|
|
// COSTRUZIONE META (identico a normalizeActivity)
|
|
// ---------------------------------------------------------
|
|
return {
|
|
id,
|
|
user: userName,
|
|
cartella,
|
|
taken_at: new Date(parsed.start_time_millis).toISOString(),
|
|
file_name: parsed.file_name,
|
|
file_extension: parsed.file_extension,
|
|
format: parsed.format,
|
|
display_name: parsed.display_name,
|
|
route_name: parsed.route_name,
|
|
title: parsed.title,
|
|
description: parsed.description,
|
|
notes: parsed.notes,
|
|
sport: parsed.sport,
|
|
activity_type: parsed.activity_type,
|
|
device_manufacturer: parsed.device_manufacturer,
|
|
device_model: parsed.device_model,
|
|
source_app: parsed.source_app,
|
|
|
|
start_time_millis: parsed.start_time_millis,
|
|
end_time_millis: parsed.end_time_millis,
|
|
duration_millis: parsed.duration_millis,
|
|
|
|
distance_meters: parsed.distance_meters,
|
|
elevation_gain_meters: parsed.elevation_gain_meters,
|
|
elevation_loss_meters: parsed.elevation_loss_meters,
|
|
|
|
min_elevation_meters: parsed.min_elevation_meters,
|
|
max_elevation_meters: parsed.max_elevation_meters,
|
|
|
|
file_distance_meters: parsed.file_distance_meters,
|
|
file_elevation_gain_meters: parsed.file_elevation_gain_meters,
|
|
|
|
computed_distance_meters: parsed.computed_distance_meters,
|
|
computed_elevation_gain_meters: parsed.computed_elevation_gain_meters,
|
|
|
|
average_speed_mps: parsed.average_speed_mps,
|
|
max_speed_mps: parsed.max_speed_mps,
|
|
average_pace_sec_per_km: parsed.average_pace_sec_per_km,
|
|
|
|
average_heart_rate: parsed.average_heart_rate,
|
|
max_heart_rate: parsed.max_heart_rate,
|
|
average_cadence: parsed.average_cadence,
|
|
max_cadence: parsed.max_cadence,
|
|
|
|
calories: parsed.calories,
|
|
power_avg: parsed.power_avg,
|
|
power_max: parsed.power_max,
|
|
|
|
point_count: parsed.point_count,
|
|
segment_count: parsed.segment_count,
|
|
lap_count: parsed.lap_count,
|
|
|
|
min_latitude: parsed.min_latitude,
|
|
max_latitude: parsed.max_latitude,
|
|
min_longitude: parsed.min_longitude,
|
|
max_longitude: parsed.max_longitude,
|
|
center_latitude: parsed.center_latitude,
|
|
center_longitude: parsed.center_longitude,
|
|
|
|
size_bytes: st.size,
|
|
last_modified_millis: st.mtimeMs,
|
|
date_added_millis: Date.now(),
|
|
date_modified_millis: Date.now(),
|
|
last_scan_millis: Date.now(),
|
|
|
|
is_favorite: false,
|
|
is_hidden: false,
|
|
rating: 0,
|
|
|
|
tags: parsed.tags || [],
|
|
track_preview: parsed.track_preview || [],
|
|
scan_status: "ok",
|
|
scan_error: null,
|
|
diagnostics: parsed.diagnostics || null,
|
|
|
|
gps,
|
|
location,
|
|
path: fullPath
|
|
};
|
|
}
|
|
|
|
module.exports = processActivityFile;
|