-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript.js
145 lines (125 loc) · 5.67 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
document.getElementById('fileInput').addEventListener('change', handleFileUpload);
function handleFileUpload(event) {
const file = event.target.files[0];
if (!file) return;
Papa.parse(file, {
header: true,
skipEmptyLines: true,
complete: function (results) {
processCSVData(results.data);
},
error: function (error) {
console.error("Error parsing CSV:", error);
}
});
}
async function processCSVData(data) {
document.getElementById('stats').style.display = 'block';
let totalSongs = 0;
let totalMilliseconds = 0;
let totalPodcastMinutes = 0;
const songCounts = {};
const genreCounts = {};
const podcastCounts = {};
const artistCounts = {};
const albumCounts = {};
const songsListenedToBefore = new Set(); // Track songs already listened to
let newSongs = 0;
const artistsToFetchGenres = new Set(); // Collect artists for batch genre requests
const uniqueArtists = new Set(); // Track unique artists
const uniqueAlbums = new Set(); // Track unique albums
const uniqueGenres = new Set(); // Track unique genres
for (const row of data) {
const track = row['Track Name']?.trim();
const artist = row['Artist Name']?.trim();
const duration = parseInt(row['Milliseconds Played']?.trim() || '0', 10);
const podcast = row['Podcast Name']?.trim(); // Assuming podcasts are identified by this field
const album = row['Album Name']?.trim();
if (track && artist && duration) {
totalSongs++;
totalMilliseconds += duration;
artistCounts[artist] = (artistCounts[artist] || 0) + 1;
songCounts[track] = (songCounts[track] || 0) + 1;
// Track if the song is new
if (!songsListenedToBefore.has(track)) {
newSongs++;
songsListenedToBefore.add(track);
}
// Collect artists for batch genre fetch
artistsToFetchGenres.add(artist);
// Track unique artists and albums
uniqueArtists.add(artist);
if (album) {
uniqueAlbums.add(album);
albumCounts[album] = (albumCounts[album] || 0) + 1;
}
}
if (podcast && duration) {
totalPodcastMinutes += Math.round(duration / 60000);
podcastCounts[podcast] = (podcastCounts[podcast] || 0) + 1;
}
}
// Fetch genres in batch
const genreData = await fetchGenresForArtists(Array.from(artistsToFetchGenres));
// Process the genres and update counts
genreData.forEach(({ artist, genres }) => {
genres.forEach(genre => {
genreCounts[genre] = (genreCounts[genre] || 0) + 1;
uniqueGenres.add(genre); // Track unique genres
});
});
// Calculate new songs percentage
const newSongsPercentage = totalSongs > 0 ? (newSongs / totalSongs) * 100 : 0;
// Calculate top 5 songs
const topSongs = Object.entries(songCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([song, count]) => `${song} (${count} plays)`);
// Calculate top 5 genres
const topGenres = Object.entries(genreCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([genre, count]) => `${genre} (${count} plays)`);
// Calculate top 5 podcasts
const topPodcasts = Object.entries(podcastCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([podcast, count]) => `${podcast} (${count} plays)`);
// Calculate top 5 albums
const topAlbums = Object.entries(albumCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([album, count]) => `${album} (${count} plays)`);
// Update stats
document.getElementById('totalSongs').textContent = totalSongs;
document.getElementById('totalMinutes').textContent = Math.round(totalMilliseconds / 60000);
document.getElementById('topSongs').innerHTML = topSongs.map(song => `<li>${song}</li>`).join('');
document.getElementById('topGenres').innerHTML = topGenres.map(genre => `<li>${genre}</li>`).join('');
document.getElementById('topAlbums').innerHTML = topAlbums.map(album => `<li>${album}</li>`).join('');
document.getElementById('mostPlayedPodcast').textContent = Object.keys(podcastCounts)[0] || 'N/A';
document.getElementById('totalPodcastMinutes').textContent = totalPodcastMinutes;
document.getElementById('topPodcasts').innerHTML = topPodcasts.map(podcast => `<li>${podcast}</li>`).join('');
document.getElementById('newSongsPercentage').textContent = `${newSongsPercentage.toFixed(2)}%`;
document.getElementById('uniqueArtists').textContent = uniqueArtists.size;
document.getElementById('uniqueAlbums').textContent = uniqueAlbums.size;
document.getElementById('uniqueGenres').textContent = uniqueGenres.size;
}
async function fetchGenresFromAPI(artist) {
try {
const response = await fetch(`http://localhost:3000/genres?artist=${encodeURIComponent(artist)}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.genres || []; // Ensure that genres are returned even if empty
} catch (error) {
console.error('Error fetching genres:', error);
return []; // Return an empty array in case of error
}
}
// Fetch genres for a list of artists
async function fetchGenresForArtists(artists) {
const fetchPromises = artists.map(artist => fetchGenresFromAPI(artist));
const genresArray = await Promise.all(fetchPromises);
return artists.map((artist, index) => ({ artist, genres: genresArray[index] }));
}