bowling-analysis-system
Version:
A comprehensive system for analyzing bowling techniques using video processing and metrics calculation
104 lines (89 loc) • 3.14 kB
JavaScript
/**
* @fileoverview File saver stage for saving final results
*/
const fs = require('fs');
class FileSaver {
/**
* Build and save final result
* @param {Object} params - Stage parameters
* @param {Object} params.context - Pipeline context
* @param {string} params.outputPath - Path to save output
* @param {Object} params.options - Stage options
* @param {boolean} [params.options.debug] - Enable debug logging
* @returns {Promise<Object>} Final result
*/
async execute({ context, outputPath, options = {} }) {
const { debug = false } = options;
// Build final result object
const result = this.buildFinalResult(context);
// Save to file if path provided
if (outputPath) {
// Ensure we're writing a single, complete result
const finalResult = JSON.stringify(result, null, 2);
fs.writeFileSync(outputPath, finalResult);
if (debug) {
console.log(`Results saved to ${outputPath}`);
}
}
return result;
}
/**
* Build the final result object
* @param {Object} context - Pipeline context
* @returns {Object} Final result
*/
buildFinalResult(context) {
// Debug the input context metrics
if (context.metrics) {
console.log(`\nBuilding final result with ${Object.keys(context.metrics).length} metrics categories`);
for (const category in context.metrics) {
const metrics = context.metrics[category];
console.log(`- ${category}: ${Object.keys(metrics).length} metrics`);
}
}
// Include all required top-level keys
const result = {
metrics: context.metrics || {},
events: context.events || {},
timeSeries: context.timeSeries || {},
metadata: {
frameCount: context.metadata?.totalFrames || 0,
validFrames: context.metadata?.validFrames || 0,
nullFrames: context.metadata?.nullFrames || 0,
validFramesStart: 0,
analysisTimestamp: new Date().toISOString(),
pipelineId: context.pipeline?.id || 'unknown',
pipelineName: context.pipeline?.name || 'unknown',
timings: context.metadata?.timings || {}
}
};
// Include analysis if available
if (context.analysis) {
result.analysis = context.analysis;
}
// Include bias data if available
if (context.bias) {
result.bias = context.bias;
}
// Include moments data if available
if (context.events && context.events.moments) {
result.moments = context.events.moments;
// Remove moments from events object to avoid duplication
const eventsCopy = { ...context.events };
delete eventsCopy.moments;
result.events = eventsCopy;
}
// Debug the output result metrics
if (result.metrics) {
console.log(`\nFinal result has ${Object.keys(result.metrics).length} metrics categories`);
for (const category in result.metrics) {
const metrics = result.metrics[category];
console.log(`- ${category}: ${Object.keys(metrics).length} metrics`);
}
}
return result;
}
}
module.exports = {
FileSaver
};