The Electron BrowserWindow to attach dialogs to
Optional
targetPath: stringOptional pre-defined export path (bypasses user prompt)
Promise resolving to object containing success status, message, and path
// Export library statistics
try {
const result = await exportLibraryStatisticsToCSV(mainWindow);
if (result.success) {
showSuccessMessage(`Library analysis exported to ${result.filePath}`);
}
} catch (error) {
logError("Library export failed", error);
}
export async function exportLibraryStatisticsToCSV(
mainWindow: BrowserWindow,
targetPath?: string,
): Promise<{ success: boolean; message?: string; filePath?: string }> {
try {
// Get library statistics
const libraryStats = await calculateLibrarySkipStatistics();
if (!libraryStats) {
return {
success: false,
message: "No library statistics data available to export",
};
}
// For library stats, we'll create a flat structure with single row summary
// and multiple separate sections
// Summary section
const summaryHeaders = {
totalTracks: "Total Tracks",
totalSkips: "Total Skips",
overallSkipRate: "Overall Skip Rate",
uniqueTracksSkipped: "Unique Tracks Skipped",
avgSkipPercentage: "Average Skip Percentage",
topSkippedGenre: "Top Skipped Genre",
};
const summaryData = [
{
totalTracks: libraryStats.totalTracks || 0,
totalSkips: libraryStats.totalSkips || 0,
overallSkipRate: libraryStats.overallSkipRate || 0,
uniqueTracksSkipped: libraryStats.uniqueTracksSkipped || 0,
avgSkipPercentage: libraryStats.averageSkipPercentage || 0,
topSkippedGenre: "Unknown", // This might need to be added to the libraryStats model
},
];
// Skip distribution section if available
let skipDistributionData: Array<{
skipPercentage: string;
trackCount: number;
percentageOfLibrary: number;
}> = [];
const skipDistHeaders = {
skipPercentage: "Skip Percentage",
trackCount: "Track Count",
percentageOfLibrary: "Percentage of Library",
};
if (libraryStats.skipsByType) {
skipDistributionData = Object.entries(libraryStats.skipsByType).map(
([skipType, count]) => ({
skipPercentage: skipType,
trackCount: count,
percentageOfLibrary: count / (libraryStats.totalTracks || 1),
}),
);
}
// Create the CSV by combining sections with headers
let csvContent = "LIBRARY STATISTICS SUMMARY\n\n";
// Add summary section
csvContent += objectToCSV(summaryData, summaryHeaders);
// Add skip distribution if available
if (skipDistributionData.length > 0) {
csvContent += "\n\nSKIP DISTRIBUTION\n";
csvContent += objectToCSV(skipDistributionData, skipDistHeaders);
}
// Determine file path
let filePath = targetPath;
if (!filePath) {
const timestamp = new Date()
.toISOString()
.replace(/:/g, "-")
.split(".")[0];
const defaultFileName = `library_statistics_${timestamp}.csv`;
filePath = await promptForExportLocation(
mainWindow,
join(ensureExportDir(), defaultFileName),
[{ name: "CSV Files", extensions: ["csv"] }],
);
if (!filePath) {
return { success: false, message: "Export was canceled" };
}
}
// Write the CSV file
writeFileSync(filePath, csvContent);
return {
success: true,
message: "Library statistics data exported successfully",
filePath,
};
} catch (error) {
console.error("Error exporting library statistics to CSV:", error);
return {
success: false,
message: `Error exporting data: ${error instanceof Error ? error.message : "Unknown error"}`,
};
}
}
Exports library statistics to CSV
Creates a specialized CSV export focused on library-wide metrics and skip behavior analysis. Unlike other exports that focus on time-series or item-specific data, this export provides a holistic view of the entire listening library, highlighting overall patterns and distributions.
The export includes multiple sections:
Each section is formatted with appropriate headers and organization to make the CSV readable both in spreadsheet applications and text editors.