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 time patterns for visualization
const result = await exportTimePatternsToCSV(mainWindow);
if (result.success) {
openVisualizationTool(result.filePath);
} else {
showExportError(result.message);
}
export async function exportTimePatternsToCSV(
mainWindow: BrowserWindow,
targetPath?: string,
): Promise<{ success: boolean; message?: string; filePath?: string }> {
try {
// Get time patterns
const timePatterns = await analyzeTimeBasedPatterns();
if (!timePatterns) {
return {
success: false,
message: "No time patterns data available to export",
};
}
// For time patterns, we'll create multiple sections
// Hourly distribution
const hourlyHeaders = {
hour: "Hour of Day",
skips: "Skips",
plays: "Plays",
skipRate: "Skip Rate",
};
const hourlyData = [];
if (timePatterns.hourlyDistribution) {
for (let i = 0; i < 24; i++) {
const skipsData = Array.isArray(timePatterns.hourlyDistribution)
? timePatterns.hourlyDistribution[i] || 0
: 0;
hourlyData.push({
hour: `${i}:00-${i + 1}:00`,
skips: skipsData,
plays: 0, // This data isn't in the current hourlyDistribution model
skipRate: 0, // Needs to be calculated differently
});
}
}
// Daily distribution
const dailyHeaders = {
day: "Day of Week",
skips: "Skips",
plays: "Plays",
skipRate: "Skip Rate",
};
const dayNames = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
const dailyData = [];
if (timePatterns.dayOfWeekDistribution) {
for (let i = 0; i < 7; i++) {
const skipsData = Array.isArray(timePatterns.dayOfWeekDistribution)
? timePatterns.dayOfWeekDistribution[i] || 0
: 0;
dailyData.push({
day: dayNames[i],
skips: skipsData,
plays: 0, // This data isn't in the current model
skipRate: 0, // Needs to be calculated differently
});
}
}
// Create the CSV by combining sections
let csvContent = "TIME-BASED PATTERNS\n\n";
// Add hourly distribution
csvContent += "HOURLY DISTRIBUTION\n";
csvContent += objectToCSV(hourlyData, hourlyHeaders);
// Add daily distribution
csvContent += "\n\nDAILY DISTRIBUTION\n";
csvContent += objectToCSV(dailyData, dailyHeaders);
// Add session metrics if available - session metrics aren't part of the TimePatterns type yet
const sessionMetrics = {
avgDuration: 0,
avgTracks: 0,
avgSkips: 0,
avgTimeBetween: 0,
};
if (sessionMetrics) {
csvContent += "\n\nSESSION METRICS\n";
csvContent += `Average session duration: ${sessionMetrics.avgDuration || 0} ms\n`;
csvContent += `Average tracks per session: ${sessionMetrics.avgTracks || 0}\n`;
csvContent += `Average skips per session: ${sessionMetrics.avgSkips || 0}\n`;
csvContent += `Average time between sessions: ${sessionMetrics.avgTimeBetween || 0} ms\n`;
}
// Determine file path
let filePath = targetPath;
if (!filePath) {
const timestamp = new Date()
.toISOString()
.replace(/:/g, "-")
.split(".")[0];
const defaultFileName = `time_patterns_${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: "Time patterns data exported successfully",
filePath,
};
} catch (error) {
console.error("Error exporting time patterns to CSV:", error);
return {
success: false,
message: `Error exporting data: ${error instanceof Error ? error.message : "Unknown error"}`,
};
}
}
Exports time patterns to CSV
Creates a specialized CSV export focused on temporal listening patterns, providing insights into how listening behavior varies by time of day, day of week, and across different time periods. This export is particularly valuable for identifying rhythms and patterns in user engagement.
The export includes multiple interconnected sections:
The CSV format uses section headers and multi-part organization to present related data in a coherent structure, making it suitable for both visual inspection and programmatic analysis in spreadsheet applications.