From f6aff788fc63de32c848d4843f139a5b8b01019a Mon Sep 17 00:00:00 2001 From: nina-perone <143619402+nina-perone@users.noreply.github.com> Date: Wed, 17 Apr 2024 09:50:43 -0400 Subject: [PATCH 01/11] Update README.md added info about what user should see --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 76d1aed..6b025ab 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ A user on the same network the app is hosted on can put the host's IP and port n The first person will click the "Create Session" button and log into their Spotify account. A Session ID will appear on the top of their receipt. -Other users can then click "Join Session" and after entering the shared Session ID, they can log into their Spotify accounts and view the receipt. +Other users can then click "Join Session" and after entering the shared Session ID, they can log into their Spotify accounts and view the receipt. After refreshing the page, checkboxes will appear next to each joined user's name indicating which Spotify accounts data will be included. (CURRENTLY ONLY WORKS FOR TOP ARTISTS) +Screenshot 2024-04-17 at 9 45 04 AM From 1f83a7e53e3024fcbb6193ac9102b58aaa642b69 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Apr 2024 12:55:07 -0400 Subject: [PATCH 02/11] adding for loop --- receiptifyv1/app.js | 4 +- receiptifyv1/public/server.js | 76 ++++++++++++++++++++++++++++------- receiptifyv1/users.csv | 3 +- 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/receiptifyv1/app.js b/receiptifyv1/app.js index 17e2490..aa59f28 100644 --- a/receiptifyv1/app.js +++ b/receiptifyv1/app.js @@ -27,8 +27,8 @@ const cors = require('cors'); require('dotenv').config(); -const client_id = '792207d6524f4255a1730e478d8b66f6'; -const client_secret = 'fd5c90696d984ca7a65a54853f340c70'; +const client_id = '035844db2ccb4d0698ab8e14bb12f27a'; +const client_secret = '8bfd5a9fa7a44aedbf8bf8f513236b4f'; //const privateKey = fs.readFileSync('AuthKey_A8FKGGUQP3.p8').toString(); const teamId = process.env.teamId; const keyId = process.env.keyId; diff --git a/receiptifyv1/public/server.js b/receiptifyv1/public/server.js index 40ff1a3..41576c6 100644 --- a/receiptifyv1/public/server.js +++ b/receiptifyv1/public/server.js @@ -844,10 +844,10 @@ const displayReceipt = (response, stats, state, users_checkbox = []) => { if (type === 'tracks') { console.log('tracks') - $('#save-playlist').show(); - document - .getElementById('save-playlist') - ?.addEventListener('click', () => saveAsPlaylist(response)); + //$('#save-playlist').show(); + //document + //.getElementById('save-playlist') + //?.addEventListener('click', () => saveAsPlaylist(response)); } else { console.log('other types'); $('#save-playlist').hide(); @@ -995,7 +995,7 @@ function shuffleArray(array){ function retrieveItems(stats, state) { console.log('getUsers: ', getUsersCheckbox()); - users_checkbox = getUsersCheckbox(); //needs to be a an array of obj + var users_checkbox = getUsersCheckbox(); //needs to be a an array of obj console.log('getUsers: ', [users_checkbox]); if (users_checkbox.length == 0){ @@ -1045,7 +1045,6 @@ function retrieveItems(stats, state) { if ( type === 'artists') { const promises = []; let combined = []; - const timeRangeSlug = "short_term"; if (users_checkbox[0].token == null || users_checkbox[0].user == null) { displayReceipt([], stats, state, users_checkbox); } @@ -1054,8 +1053,7 @@ function retrieveItems(stats, state) { $.ajax({ url: `${SPOTIFY_ROOT}/me/top/artists?limit=${limit}&time_range=${timeRangeSlug}`, headers: { - //Authorization: 'Bearer ' + users_checkbox[i].id, - Authorization: 'Bearer ' + users_checkbox[i].token //null + Authorization: 'Bearer ' + users_checkbox[i].token }, success: (response) => { resolve(response?.items); @@ -1077,15 +1075,14 @@ function retrieveItems(stats, state) { const combined = [].concat(...artistData); // Combine all artists data console.log('concat final: ', combined); const shuffledCombined = shuffleArray(combined); - console.log('shuffled: ', shuffledCombined) + console.log('shuffled: ', shuffledCombined); // Shuffle the combined data shuffledCombined.splice(num); console.log('spliced: ', shuffledCombined); response_edited = { items: shuffledCombined - } + }; displayReceipt(response_edited, stats, state, users_checkbox); - //return response_edited; }) .catch((errors) => { console.error('Errors:', errors); // Handle any errors @@ -1116,10 +1113,57 @@ function retrieveItems(stats, state) { } }, }); - //console.log(item); - } //else { // shows tracks - else if(type === 'tracks'){ - //console.log('ajax call else'); + } + + else if(type === 'tracks'){ + /* + const promises = []; + let combined = []; + if (users_checkbox[0].token == null || users_checkbox[0].user == null) { + displayReceipt([], stats, state, users_checkbox); + } + for (var i=0; i < users_checkbox.length; i++){ + const promise = new Promise((resolve, reject) => { + $.ajax({ + url: `${SPOTIFY_ROOT}/me/top/tracks?limit=${limit}&time_range=${timeRangeSlug}`, + headers: { + Authorizaton: 'Bearer ' + users_checkbox[i].token, + }, + sucess: (response) => { + resolve(response?.items); + + const tracks = response?.items; + console.log("Top Tracks: ", tracks); + combined = combined.concat(tracks); + console.log("Concat: ", combined); + }, + error: function(error) { + reject(error); + console.error("Error: ", error); + } + }) + }) + promises.push(promise); + } + Promise.all(promises).then((trackData) => { + const combined = [].concat(...trackData); + console.log("concat final: ", combined); + const shuffledCombined = shuffleArray(combined); + console.log("shuffled: ", shuffledCombined); + shuffledCombined.splice(num); + console.log("spliced: ", shuffledCombined); + response_edited = { + items: shuffledCombined + }; + displayReceipt(response_edited, stats, state, users_checkbox); + }) + .catch((errors) => { + console.error("Errors: ", errors); + }); + */ + + + console.log(users_checkbox[0].token); $.ajax({ url: `${SPOTIFY_ROOT}/me/top/${ selectedType ?? 'tracks' @@ -1129,6 +1173,7 @@ function retrieveItems(stats, state) { }, success: displayReceipt, }); + } } catch (error) { console.error('Error: ', error); @@ -1240,6 +1285,7 @@ if (error) { displayName = response.display_name.toUpperCase(); username = response.id; showReceipt(); + console.log(1); retrieveItems(); }, diff --git a/receiptifyv1/users.csv b/receiptifyv1/users.csv index 4802544..24c9df4 100644 --- a/receiptifyv1/users.csv +++ b/receiptifyv1/users.csv @@ -1,3 +1,2 @@ -Ari,BQA8fwaaWA87EUZvia5emYjOq0IyC0_9rePt7Dsnvs6shbeWFRssWwAfsHYvJAbtnYxDO9vi1YRYs7WUXsd6yzX1UgQE9wMgAJ_VksmJThckhV5qVbQG-Z4zG64YVEHNodfeQoTPWvgCEgC4Rjnb5aWphBYHKcBpseuMAERYqeWxxvWerddgmS22u4D0lpiyqTpKaKzbeiRaY-IuhhzrZfFv8hCSJM1dfPVpUXmTIJ2GkC2_GphugfE6,763656,1713334863450, -Ari,BQBP9W-1YdtEPiN84p4PnEXDc658wfuhYs2LsCMNm9mR3c2HGjVGTMmQHG5fSxYJVRhPE995RPlGXrx8tZlbux2YDC1LvBCmoh3ntfgiqKkkOmGoIPAUoV8V0ygebaQDRKD3V_uDuCuhbpSb8NIqwV4KbP8ezBQ3zGmU_vtAtULeNjPTbc-QGXK38tOj9M8bBUPQOBqGJkG_HbQqOcd0POBQmNk3OeDdhDOzYcqnZtF5b6y-LMjFJXOm,763656,1713334879131, +✧ jizzica ✧,BQBQ7Vsu17lp5JzwqfUdtXvsyk2DpavL1L3JCil4ilMKd33tagZoS7Ps_2u8PiZ6RQSfPgfbSiwmRvX77GF-YNlMbCEVueeHRhzB2LCPQOWh7fF84GxPR7o_wXh4KM-L9PXT_mEd1OnafqNmEqeG5fgC_8ilNa5yMSOx3L5RIMvsDda1oYDrjvq4pMzI4eBZkMl46ZpCWaV3IfLzjlWsXvyB8CZX_vyd9M9SyD0,885388,1713544182156, From 9b0eb084caf90ad0dde9d2a9bc0b248ee102bef6 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 20 Apr 2024 15:33:21 -0400 Subject: [PATCH 03/11] Finished Tracks --- receiptifyv1/public/server.js | 204 +++++++++++++++++----------------- receiptifyv1/users.csv | 3 +- 2 files changed, 101 insertions(+), 106 deletions(-) diff --git a/receiptifyv1/public/server.js b/receiptifyv1/public/server.js index 41576c6..4f17a90 100644 --- a/receiptifyv1/public/server.js +++ b/receiptifyv1/public/server.js @@ -351,8 +351,6 @@ const getUsersCheckbox = () => { } var users_checkbox = users.map((user, index) =>({ user, token: tokens[index]})); - - // return list of objects. list of user object with name and token. return users_checkbox; } @@ -648,30 +646,6 @@ async function fetchUsers(sessionID, type) { ;} -function checkboxUpdate(stats, state, users_checkbox, user, isChecked) { - if (users_checkbox.map(obj => obj.user).includes(null) || users_checkbox.map(obj => obj.token).includes(null)) { - users_checkbox.shift(); - } - if (!isChecked){ - console.log(`Before: ${users_checkbox}`); - for (let i = 0; i < users_checkbox.length; i++) { - if (users_checkbox[i].user == user){ - users_checkbox.splice(i, 1); - } - } - console.log(`After: ${users_checkbox}`); - } else { - console.log(`Before: ${users_checkbox}`); - users_checkbox.push(user); - console.log(`After: ${users_checkbox}`); - } - if (users_checkbox.length == 0){ - users_checkbox.push({user: null, token: null}); - } - retrieveItems(stats, state); -;} - - const displayReceipt = (response, stats, state, users_checkbox = []) => { console.log(response, stats, state, users_checkbox); const scrollPosition = window.scrollY; @@ -736,53 +710,26 @@ const displayReceipt = (response, stats, state, users_checkbox = []) => { let total = 0; const date = TODAY.toLocaleDateString('en-US', DATE_OPTIONS).toUpperCase(); - const tracksFormatted = responseItems.map((item, i) => { - total += totalIncrement(item); - return { - id: (i + 1 < 10 ? '0' : '') + (i + 1), - url: item.external_urls?.spotify, - ...Object.fromEntries( - Object.entries(itemFns).map(([key, fn]) => [key, fn(item)]) - ), - }; - }); - const totalFormatted = - type === 'tracks' || showSearch ? getMinSeconds(total) : total.toFixed(2); - - - if (users_checkbox.length == 0){ - console.log("No Previous users_checkbox"); - users_checkbox = users.map((user, index) => ({ user, token: tokens[index]})); - - const userCheckbox = document.getElementById('user-checkbox'); - userCheckbox.innerHTML = ""; - const userCheckboxTitle = document.createElement('p'); - userCheckboxTitle.textContent = "Select Users"; - userCheckbox.appendChild(userCheckboxTitle); - for (let i = 0; i < users.length; i++) { - const checkbox = document.createElement('input'); - checkbox.name = 'user-select-checkbox'; - checkbox.type = 'checkbox'; - checkbox.id = tokens[i]; - checkbox.checked = users_checkbox.map(obj => obj.user).includes(users[i]) - checkbox.onclick = (event) =>{ - const isChecked = event.target.checked; - checkboxUpdate(stats, state, users_checkbox, users[i], isChecked); - } - - const label = document.createElement('label'); - label.textContent = users[i]; - label.htmlFor = checkbox.id; - - userCheckbox.appendChild(checkbox); - userCheckbox.appendChild(label); - userCheckbox.appendChild(document.createElement('br')); - } - } else { - console.log("Previous users_checkbox"); + var tracksFormatted = []; + var totalFormatted = '00:00'; + try { + tracksFormatted = responseItems.map((item, i) => { + total += totalIncrement(item); + return { + id: (i + 1 < 10 ? '0' : '') + (i + 1), + url: item.external_urls?.spotify, + ...Object.fromEntries( + Object.entries(itemFns).map(([key, fn]) => [key, fn(item)]) + ), + }; + }); + totalFormatted = + type === 'tracks' || showSearch ? getMinSeconds(total) : total.toFixed(2); + } catch { + console.log('No Users Selected.') } - console.log(users_checkbox); - if (users_checkbox[0].token == null || users_checkbox[0].user == null) { + + if (getUsersCheckbox() == 0 ) { console.log('before html: ',users_checkbox); console.log(sessionID); userProfilePlaceholder.innerHTML = userProfileTemplate({ @@ -805,8 +752,6 @@ const displayReceipt = (response, stats, state, users_checkbox = []) => { isInternational: font === 'international', }); } else { - console.log('before html: ',users_checkbox); - console.log(sessionID); userProfilePlaceholder.innerHTML = userProfileTemplate({ tracks: tracksFormatted, total: totalFormatted, @@ -994,22 +939,21 @@ function shuffleArray(array){ function retrieveItems(stats, state) { - console.log('getUsers: ', getUsersCheckbox()); - var users_checkbox = getUsersCheckbox(); //needs to be a an array of obj - console.log('getUsers: ', [users_checkbox]); - - if (users_checkbox.length == 0){ - users_checkbox.push({user: null, token: null}); - console.log('push null retrieveItems'); - response_edited = { - items: [] - } - displayReceipt(response_edited, stats, state, users_checkbox); - } - (async () => { try { tokens = await fetchUsers(sessionID, 'access_token'); + users = await fetchUsers(sessionID, 'display_name'); + + var users_checkbox = getUsersCheckbox(); + console.log(users_checkbox); + if (users_checkbox.length == 0){ + response_edited = { + items: [] + } + displayReceipt(response_edited, stats, state, users_checkbox); + } + // + //console.log('Fetched Tokens', tokens); $('#search-form').hide(); $('#custom-name').hide(); @@ -1115,27 +1059,26 @@ function retrieveItems(stats, state) { }); } - else if(type === 'tracks'){ - /* + if (type === 'tracks'){ const promises = []; let combined = []; - if (users_checkbox[0].token == null || users_checkbox[0].user == null) { - displayReceipt([], stats, state, users_checkbox); + if (getUsersCheckbox().length == 0) { + displayReceipt([{items: []}], stats, state, []); } - for (var i=0; i < users_checkbox.length; i++){ + for (var i = 0; i < users_checkbox.length; i++) { const promise = new Promise((resolve, reject) => { $.ajax({ - url: `${SPOTIFY_ROOT}/me/top/tracks?limit=${limit}&time_range=${timeRangeSlug}`, + url: `${SPOTIFY_ROOT}/me/top/tracks?limit=${limit}&time_range=${timeRangeSlug}`, headers: { - Authorizaton: 'Bearer ' + users_checkbox[i].token, + Authorization: 'Bearer ' + users_checkbox[i].token }, - sucess: (response) => { + success: (response) => { resolve(response?.items); const tracks = response?.items; console.log("Top Tracks: ", tracks); combined = combined.concat(tracks); - console.log("Concat: ", combined); + console.log('Concat: ', combined); }, error: function(error) { reject(error); @@ -1146,23 +1089,24 @@ function retrieveItems(stats, state) { promises.push(promise); } Promise.all(promises).then((trackData) => { - const combined = [].concat(...trackData); - console.log("concat final: ", combined); - const shuffledCombined = shuffleArray(combined); - console.log("shuffled: ", shuffledCombined); + const combined = [].concat(...trackData); // Combine all artists data + console.log('concat final: ', combined); + const shuffledCombined = shuffleArray(combined); + console.log('shuffled: ', shuffledCombined); + // Shuffle the combined data shuffledCombined.splice(num); - console.log("spliced: ", shuffledCombined); + console.log('spliced: ', shuffledCombined); response_edited = { items: shuffledCombined }; displayReceipt(response_edited, stats, state, users_checkbox); }) .catch((errors) => { - console.error("Errors: ", errors); + console.error('Errors:', errors); // Handle any errors }); - */ + - + /* console.log(users_checkbox[0].token); $.ajax({ url: `${SPOTIFY_ROOT}/me/top/${ @@ -1173,6 +1117,7 @@ function retrieveItems(stats, state) { }, success: displayReceipt, }); + */ } } catch (error) { @@ -1259,6 +1204,53 @@ function retrieveStats() { .addEventListener('click', () => downloadImg('heavy_rotation')); }*/ +function showCheckbox() { + console.log('showCheckbox()'); + + (async () => { + try { + const tokens = await fetchUsers(sessionID, 'access_token'); + const users = await fetchUsers(sessionID, 'display_name'); + + // Combine user data with tokens (assuming tokens match user order) + const users_checkbox = users.map((user, index) => ({ user, token: tokens[index] })); + + const userCheckbox = document.getElementById('user-checkbox'); + userCheckbox.innerHTML = ""; + + const userCheckboxTitle = document.createElement('p'); + userCheckboxTitle.textContent = "Select Users"; + userCheckbox.appendChild(userCheckboxTitle); + + for (let i = 0; i < users.length; i++) { + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.id = tokens[i]; // Use token for unique ID + checkbox.name = 'user-select-checkbox'; + + // Check if user is already selected based on users_checkbox + checkbox.checked = users_checkbox.map(obj => obj.user).includes(users[i]); + + checkbox.onclick = (event) => { + const isChecked = event.target.checked; + retrieveItems() + }; + + const label = document.createElement('label'); + label.textContent = users[i]; + label.htmlFor = checkbox.id; + + userCheckbox.appendChild(checkbox); + userCheckbox.appendChild(label); + userCheckbox.appendChild(document.createElement('br')); + } + } catch (error) { + console.error('Error: ', error); + } + })(); +} + + let params = getHashParams(); @@ -1285,8 +1277,10 @@ if (error) { displayName = response.display_name.toUpperCase(); username = response.id; showReceipt(); - console.log(1); + //console.log(1); + showCheckbox(); retrieveItems(); + //displayReceipt({items: []}); }, }); diff --git a/receiptifyv1/users.csv b/receiptifyv1/users.csv index 24c9df4..c762448 100644 --- a/receiptifyv1/users.csv +++ b/receiptifyv1/users.csv @@ -1,2 +1,3 @@ -✧ jizzica ✧,BQBQ7Vsu17lp5JzwqfUdtXvsyk2DpavL1L3JCil4ilMKd33tagZoS7Ps_2u8PiZ6RQSfPgfbSiwmRvX77GF-YNlMbCEVueeHRhzB2LCPQOWh7fF84GxPR7o_wXh4KM-L9PXT_mEd1OnafqNmEqeG5fgC_8ilNa5yMSOx3L5RIMvsDda1oYDrjvq4pMzI4eBZkMl46ZpCWaV3IfLzjlWsXvyB8CZX_vyd9M9SyD0,885388,1713544182156, +Martin Duong,BQBq4YqB7OXfUT2ptOYDxZJgVhvLz6PLMnZOQgN1S09N_gJYD0iFZ3_Un9n2r3MTYLg5S-i8KSXgln3iN2ub3j3N9a4TPLk_MWnFBr7JiVKV9tPO1QoLZnnsPaZl0axOBfZA1zBU47FIkn7sKbDSayFpZy5rRdB6xJAgl5mHrFP7R1O1gAJL_CAaud2s5DtpmaqmjD8fr1XiCMWX1PTvVOoCMqOMeWig3P3dJBo,433323,1713640868202, +✧ jizzica ✧,BQDy4kSkGFHSHhvhVSZJnwGhfyaxZlm0uayu0VavAkd6EZ0wSOpax1QRJbcGFtNQxMMp_VhfrcHZQoKUH8yDqUc9jwPUwvLHCzkdTG_P4XpkhqD1oqDArfOgaE-wSt0cXF3Gp1hX5xdSP9YCC9bIB-24kfBdbADU28xmT5LRvPf97-b2lZcBfVzEaDkyoNy2RzlR-pck-8PV2e5iMW7zNtbNQH_Qy7efZB-m_TE,433323,1713640875824, From 73fa1deb6c5ed5ac6a52082bc51296d1b4cd6579 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 20 Apr 2024 15:34:36 -0400 Subject: [PATCH 04/11] Finished Tracks --- receiptifyv1/public/server.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/receiptifyv1/public/server.js b/receiptifyv1/public/server.js index 4f17a90..78395c5 100644 --- a/receiptifyv1/public/server.js +++ b/receiptifyv1/public/server.js @@ -647,7 +647,6 @@ async function fetchUsers(sessionID, type) { const displayReceipt = (response, stats, state, users_checkbox = []) => { - console.log(response, stats, state, users_checkbox); const scrollPosition = window.scrollY; const type = getType(); const font = getFont(); @@ -730,8 +729,6 @@ const displayReceipt = (response, stats, state, users_checkbox = []) => { } if (getUsersCheckbox() == 0 ) { - console.log('before html: ',users_checkbox); - console.log(sessionID); userProfilePlaceholder.innerHTML = userProfileTemplate({ tracks: tracksFormatted, total: totalFormatted, @@ -945,16 +942,12 @@ function retrieveItems(stats, state) { users = await fetchUsers(sessionID, 'display_name'); var users_checkbox = getUsersCheckbox(); - console.log(users_checkbox); if (users_checkbox.length == 0){ response_edited = { items: [] } displayReceipt(response_edited, stats, state, users_checkbox); } - // - - //console.log('Fetched Tokens', tokens); $('#search-form').hide(); $('#custom-name').hide(); $('#options').show(); @@ -1277,10 +1270,8 @@ if (error) { displayName = response.display_name.toUpperCase(); username = response.id; showReceipt(); - //console.log(1); showCheckbox(); retrieveItems(); - //displayReceipt({items: []}); }, }); From 607dd2908adce6d93732200deefefaaced8483ed Mon Sep 17 00:00:00 2001 From: Nina Perone Date: Sun, 21 Apr 2024 17:28:00 -0400 Subject: [PATCH 05/11] retrieveStats + displayStats --- receiptifyv1/public/server.js | 75 ++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/receiptifyv1/public/server.js b/receiptifyv1/public/server.js index 78395c5..4437402 100644 --- a/receiptifyv1/public/server.js +++ b/receiptifyv1/public/server.js @@ -845,6 +845,11 @@ function displayStats(response, artists, tracks) { const popularity = getAvgPopularity(artists).toFixed(2); const trackIDs = tracks.map(({ id }) => id); const age = getAvgAge(tracks); + /*console.log("artists: ", artists); + console.log("tracks: ", tracks); + console.log("popularity: ", popularity); + console.log("trackIDs: ", trackIDs); + console.log("age: ", age);*/ $.ajax({ url: `${SPOTIFY_ROOT}/audio-features?ids=${trackIDs.join(',')}`, headers: { @@ -866,6 +871,7 @@ function displayStats(response, artists, tracks) { displayReceipt(response, statsArr); }, }); + } function mostPlayedSongs(recentlyPlayedSongs) { @@ -1125,24 +1131,72 @@ function retrieveItems(stats, state) { function retrieveStats() { const timeRangeSlug = getPeriod(); const limit = 50; - $.ajax({ - url: `${SPOTIFY_ROOT}/me/top/artists?limit=${limit}&time_range=${timeRangeSlug}`, - headers: { - Authorization: 'Bearer ' + access_token, - }, - success: (response) => { - const artists = response?.items; + var users_checkbox = getUsersCheckbox(); + const promises_artists = []; + const promises_tracks = []; + let combined_artists = []; + let combined_tracks = []; + if (users_checkbox[0].token == null || users_checkbox[0].user == null) { + + displayReceipt([], stats, state, users_checkbox); + } + for (var i = 0; i < users_checkbox.length; i++) { + const artistPromise = new Promise((resolve, reject) => { + // start ajax for artists + $.ajax({ + url: `${SPOTIFY_ROOT}/me/top/artists?limit=${limit}&time_range=${timeRangeSlug}`, + headers: { + Authorization: 'Bearer ' + users_checkbox[i].token, + }, + success: (response) => { + // handle artsts + const artists = response?.items; + //console.log("Top Artists (stats): ", artists); + combined_artists = combined_artists.concat(artists); + resolve(artists); // Resolve the promise when AJAX succeeds + }, + error: function(error) { + reject(error); + console.error("Error: ", error); + } + }); + }); + + const trackPromise = new Promise((resolve, reject) => { + // start ajax for tracks $.ajax({ url: `${SPOTIFY_ROOT}/me/top/tracks?limit=${limit}&time_range=${timeRangeSlug}`, headers: { - Authorization: 'Bearer ' + access_token, + Authorization: 'Bearer ' + users_checkbox[i].token, }, success: (response) => { + // handle tracks const tracks = response?.items; - displayStats(response, artists, tracks); + //console.log("Top Tracks (stats): ", tracks); + combined_tracks = combined_tracks.concat(tracks); + resolve(tracks); // Resolve the promise when AJAX succeeds }, + error: function(error) { + reject(error); + console.error("Error: ", error); + } }); - }, + }); + + // Push promises into respective arrays + promises_artists.push(artistPromise); + promises_tracks.push(trackPromise); + } + + // pass artists + tracks to displayStats + Promise.all([Promise.all(promises_artists), Promise.all(promises_tracks)]).then((results) => { + const [artists, tracks] = results; + const artists_array = [].concat(...artists); + const tracks_array = [].concat(...tracks); + displayStats(response_edited, artists_array, tracks_array); + }) + .catch((errors) => { + console.error('Errors:', errors); // Handle any errors }); } @@ -1325,4 +1379,3 @@ document }); $('#logout-btn').hide(); - From 0106711ee592b364796a7ce0debb668ff1ae5eaa Mon Sep 17 00:00:00 2001 From: Arianna Reischer Date: Sun, 21 Apr 2024 23:45:26 -0400 Subject: [PATCH 06/11] added basic algorithm in place of shuffle. working on bug that occurs when a person has less than the max number of top tracks --- receiptifyv1/app.js | 4 +- receiptifyv1/public/server.js | 102 ++++++++++++++++++++++++++++++---- receiptifyv1/users.csv | 5 +- 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/receiptifyv1/app.js b/receiptifyv1/app.js index aa59f28..17e2490 100644 --- a/receiptifyv1/app.js +++ b/receiptifyv1/app.js @@ -27,8 +27,8 @@ const cors = require('cors'); require('dotenv').config(); -const client_id = '035844db2ccb4d0698ab8e14bb12f27a'; -const client_secret = '8bfd5a9fa7a44aedbf8bf8f513236b4f'; +const client_id = '792207d6524f4255a1730e478d8b66f6'; +const client_secret = 'fd5c90696d984ca7a65a54853f340c70'; //const privateKey = fs.readFileSync('AuthKey_A8FKGGUQP3.p8').toString(); const teamId = process.env.teamId; const keyId = process.env.keyId; diff --git a/receiptifyv1/public/server.js b/receiptifyv1/public/server.js index 78395c5..9b0f18b 100644 --- a/receiptifyv1/public/server.js +++ b/receiptifyv1/public/server.js @@ -930,8 +930,81 @@ async function nRecentlyPlayed(n, music) { return recentlyPlayedSongs.flat(); } -function shuffleArray(array){ - return [...array].sort(() => Math.random() - 0.5); +function shuffleArray(array, numPerPerson){ + console.log(`array.length: ${array.length}`); + let numPeople = numPerPerson.length; + console.log(`Num People: ${numPeople}`); + + for (let i = 0; i < array.length; i++) { + console.log(array[i]); + } + var artists = new Map(); + let curListeners; + let artistInfo; + let personOffset = 0; + let currentPerson = 1; + for (let i = 0; i < array.length; i++) { + //personOffset++; + if (!artists.has(array[i].id)) + { + console.log("THE ITEM ISN'T IN THE ARRAY"); + console.log(`Num people: ${numPeople}`); + curListeners = new Array(numPeople).fill(0); + artistInfo = + { + item: array[i], + listeners: curListeners, + numListeners: 1, + score: 0 + }; + artists.set(array[i].id, artistInfo); + } + else + { + artists.get(array[i].id).numListeners++; + } + let currentPerson = Math.floor(i / numTop); + let currentScore = numTop - ((i%numTop)); + for (let j = 1; j < numPeople; j++) + { + if (j === currentPerson) + { + artists.get(array[i].id).listeners[currentPerson] = currentScore; + } + } + artists.get(array[i].id).score += currentScore; + } + + console.log("THE NEXT THING WE ARE LOGGING IS THE ARTIST THING"); + console.log(artists); + var artistsCombined = new Map(); + var artistsAlone = new Map(); + + + for (const info of artists.values()) { + console.log(`info.numlisteners : ${info.numListeners}`); + if (info.numListeners > 1) + { + artistsCombined.set(info.item, info.score); + } + else + { + artistsAlone.set(info.item, info.score); + } + } + + console.log("pringing"); + // console.log(artistsCombined); + // console.log(artistsAlone); + + const sortedCombined = new Map([...artistsCombined.entries()].sort((a, b) => b[1] - a[1])); + // console.log(sortedCombined); + const sortedAlone = new Map([...artistsAlone.entries()].sort((a, b) => b[1] - a[1])); + //console.log(sortedAlone); + + let newArr = [...sortedCombined.keys(), ...sortedAlone.keys()]; + console.log(newArr); + return newArr;//[...array].sort(() => Math.random() - 0.5); } function retrieveItems(stats, state) { @@ -978,7 +1051,8 @@ function retrieveItems(stats, state) { const selectedType = type === 'genres' ? 'artists' : type; const timeRangeSlug = getPeriod(); const limit = num; - + let numPerPerson = []; + if ( type === 'artists') { const promises = []; let combined = []; @@ -998,6 +1072,9 @@ function retrieveItems(stats, state) { const artists = response?.items; console.log("Top Artists: ", artists); combined = combined.concat(artists); + numPerPerson.push(combined.length); + + console.log('Concat: ', combined); }, error: function(error) { @@ -1011,14 +1088,16 @@ function retrieveItems(stats, state) { Promise.all(promises).then((artistData) => { const combined = [].concat(...artistData); // Combine all artists data console.log('concat final: ', combined); - const shuffledCombined = shuffleArray(combined); - console.log('shuffled: ', shuffledCombined); + console.log(`NUM per person = ${numPerPerson}`); + + const shuffledCombined = shuffleArray(combined, numPerPerson); + //console.log('shuffled: ', shuffledCombined); // Shuffle the combined data shuffledCombined.splice(num); - console.log('spliced: ', shuffledCombined); + //console.log('spliced: ', shuffledCombined); response_edited = { items: shuffledCombined - }; + }; displayReceipt(response_edited, stats, state, users_checkbox); }) .catch((errors) => { @@ -1071,6 +1150,8 @@ function retrieveItems(stats, state) { const tracks = response?.items; console.log("Top Tracks: ", tracks); combined = combined.concat(tracks); + numPerPerson.push(combined.length); + console.log('Concat: ', combined); }, error: function(error) { @@ -1084,11 +1165,12 @@ function retrieveItems(stats, state) { Promise.all(promises).then((trackData) => { const combined = [].concat(...trackData); // Combine all artists data console.log('concat final: ', combined); - const shuffledCombined = shuffleArray(combined); - console.log('shuffled: ', shuffledCombined); + console.log(`num per person: '${numPerPerson}'`); + const shuffledCombined = shuffleArray(combined, numPerPerson); + //console.log('shuffled: ', shuffledCombined); // Shuffle the combined data shuffledCombined.splice(num); - console.log('spliced: ', shuffledCombined); + //console.log('spliced: ', shuffledCombined); response_edited = { items: shuffledCombined }; diff --git a/receiptifyv1/users.csv b/receiptifyv1/users.csv index c762448..7539ae7 100644 --- a/receiptifyv1/users.csv +++ b/receiptifyv1/users.csv @@ -1,3 +1,4 @@ -Martin Duong,BQBq4YqB7OXfUT2ptOYDxZJgVhvLz6PLMnZOQgN1S09N_gJYD0iFZ3_Un9n2r3MTYLg5S-i8KSXgln3iN2ub3j3N9a4TPLk_MWnFBr7JiVKV9tPO1QoLZnnsPaZl0axOBfZA1zBU47FIkn7sKbDSayFpZy5rRdB6xJAgl5mHrFP7R1O1gAJL_CAaud2s5DtpmaqmjD8fr1XiCMWX1PTvVOoCMqOMeWig3P3dJBo,433323,1713640868202, -✧ jizzica ✧,BQDy4kSkGFHSHhvhVSZJnwGhfyaxZlm0uayu0VavAkd6EZ0wSOpax1QRJbcGFtNQxMMp_VhfrcHZQoKUH8yDqUc9jwPUwvLHCzkdTG_P4XpkhqD1oqDArfOgaE-wSt0cXF3Gp1hX5xdSP9YCC9bIB-24kfBdbADU28xmT5LRvPf97-b2lZcBfVzEaDkyoNy2RzlR-pck-8PV2e5iMW7zNtbNQH_Qy7efZB-m_TE,433323,1713640875824, +Ari,BQC1iZOnuD6lt_NR_IAbaqQ6JZ0mIwfT9XMDaAgveZW7ILLrLZBywqU3cQjTFcHpXPcG0vOnG4SR8cCmKwnFthEhlK256La5uSjrFnxblBU0p1cG2bKf82pbXFcKLa3PMH_i26L_dcFRKQ9gW_AKC0oTcDUVpr1J1mWVA5dwU3tJ5BGEZTCM4k85JBNQU7BBBWetC6KgkTFGtgoSm5vej7PHx9WkroiNVLkz_Eji4M2H55hUzkBWend2,816997,1713756931249, +Ari,BQCx7lOsW-3lBruP5FaUcyO3tD7DfYMKgJ6e_dVkNhTBEt-3ZAIznLPJeD2UGCjqKSxfUo_ess80w_iBGEYA75iNDBEzIHD19pJGk-M8RnPtmEoE9OJYgoxx9DdYzh8nkgkwFr-Ge6npJqCJOMZ1o21I0hG7Sqh83687UVx4kflEbSxz4oT8USEntUxb7jGsrhRn1KwzBSk7tiqLRFSD_H85F7NoSbDTK6Gxkq_uKPaN3y-IdIIxQI_a,720354,1713756959545, +Ari,BQDHhNov_AXTW5GsLE8EI0FAZw1qA-5vPtGzUaXqJApfFVgMLo0DSTwvuBN53RX3S2PEk9clGEukh7_NpNW89V2oN2tGP-ETXQEimpaKxMuLIY46ia4sZ5SvWPtO08pF9VtylTD9KLnEYCFIbgMb_0moVwnWKGArc_1umLLH-KD9jLPDtsCPcztOKc2McEtql5UQMfQmP68ZSBWMnQxAxCPttZYsBeIfb_J8r7KYRwI0ntSLAN2SjT7V,720354,1713757053594, From aa011f10fcd0fa82679c801b3edb0b5d8ea8a751 Mon Sep 17 00:00:00 2001 From: Arianna Reischer Date: Mon, 22 Apr 2024 04:54:57 -0400 Subject: [PATCH 07/11] accounts for different numbers of tracks under limit --- receiptifyv1/public/server.js | 41 ++++++++++++++++++++++------------- receiptifyv1/users.csv | 11 +++++++--- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/receiptifyv1/public/server.js b/receiptifyv1/public/server.js index 9b0f18b..d0ac1cd 100644 --- a/receiptifyv1/public/server.js +++ b/receiptifyv1/public/server.js @@ -938,17 +938,32 @@ function shuffleArray(array, numPerPerson){ for (let i = 0; i < array.length; i++) { console.log(array[i]); } + var artists = new Map(); let curListeners; let artistInfo; - let personOffset = 0; - let currentPerson = 1; + let currentPerson = 0; + let personOffset = numPerPerson[currentPerson]; + let posInPerson = 0; + for (let i = 0; i < array.length; i++) { - //personOffset++; + + console.log(`i: ${i}, current person: ${currentPerson}, person offset: ${personOffset}, pos in person: ${posInPerson}`); + // update the current person based on the number of songs that each person has in the array + if (i >= (personOffset)) + { + console.log("NEW PERSON"); + currentPerson++; + personOffset = numPerPerson[currentPerson]; + numPerPerson[currentPerson] = numPerPerson[currentPerson-1]; + posInPerson = 0; + } + + posInPerson++; + if (!artists.has(array[i].id)) { - console.log("THE ITEM ISN'T IN THE ARRAY"); - console.log(`Num people: ${numPeople}`); + //console.log("THE ITEM ISN'T IN THE ARRAY"); curListeners = new Array(numPeople).fill(0); artistInfo = { @@ -963,9 +978,10 @@ function shuffleArray(array, numPerPerson){ { artists.get(array[i].id).numListeners++; } - let currentPerson = Math.floor(i / numTop); - let currentScore = numTop - ((i%numTop)); - for (let j = 1; j < numPeople; j++) + + let currentScore = (numPerPerson[currentPerson] - posInPerson) / (parseFloat(numPerPerson[currentPerson])); + + for (let j = 0; j < numPeople; j++) { if (j === currentPerson) { @@ -980,7 +996,6 @@ function shuffleArray(array, numPerPerson){ var artistsCombined = new Map(); var artistsAlone = new Map(); - for (const info of artists.values()) { console.log(`info.numlisteners : ${info.numListeners}`); if (info.numListeners > 1) @@ -993,18 +1008,14 @@ function shuffleArray(array, numPerPerson){ } } - console.log("pringing"); - // console.log(artistsCombined); - // console.log(artistsAlone); + console.log("printing"); const sortedCombined = new Map([...artistsCombined.entries()].sort((a, b) => b[1] - a[1])); - // console.log(sortedCombined); const sortedAlone = new Map([...artistsAlone.entries()].sort((a, b) => b[1] - a[1])); - //console.log(sortedAlone); let newArr = [...sortedCombined.keys(), ...sortedAlone.keys()]; console.log(newArr); - return newArr;//[...array].sort(() => Math.random() - 0.5); + return newArr; } function retrieveItems(stats, state) { diff --git a/receiptifyv1/users.csv b/receiptifyv1/users.csv index 7539ae7..0549aff 100644 --- a/receiptifyv1/users.csv +++ b/receiptifyv1/users.csv @@ -1,4 +1,9 @@ -Ari,BQC1iZOnuD6lt_NR_IAbaqQ6JZ0mIwfT9XMDaAgveZW7ILLrLZBywqU3cQjTFcHpXPcG0vOnG4SR8cCmKwnFthEhlK256La5uSjrFnxblBU0p1cG2bKf82pbXFcKLa3PMH_i26L_dcFRKQ9gW_AKC0oTcDUVpr1J1mWVA5dwU3tJ5BGEZTCM4k85JBNQU7BBBWetC6KgkTFGtgoSm5vej7PHx9WkroiNVLkz_Eji4M2H55hUzkBWend2,816997,1713756931249, -Ari,BQCx7lOsW-3lBruP5FaUcyO3tD7DfYMKgJ6e_dVkNhTBEt-3ZAIznLPJeD2UGCjqKSxfUo_ess80w_iBGEYA75iNDBEzIHD19pJGk-M8RnPtmEoE9OJYgoxx9DdYzh8nkgkwFr-Ge6npJqCJOMZ1o21I0hG7Sqh83687UVx4kflEbSxz4oT8USEntUxb7jGsrhRn1KwzBSk7tiqLRFSD_H85F7NoSbDTK6Gxkq_uKPaN3y-IdIIxQI_a,720354,1713756959545, -Ari,BQDHhNov_AXTW5GsLE8EI0FAZw1qA-5vPtGzUaXqJApfFVgMLo0DSTwvuBN53RX3S2PEk9clGEukh7_NpNW89V2oN2tGP-ETXQEimpaKxMuLIY46ia4sZ5SvWPtO08pF9VtylTD9KLnEYCFIbgMb_0moVwnWKGArc_1umLLH-KD9jLPDtsCPcztOKc2McEtql5UQMfQmP68ZSBWMnQxAxCPttZYsBeIfb_J8r7KYRwI0ntSLAN2SjT7V,720354,1713757053594, +Ari,BQBSh8hEt_hWXp94VJrttZ7M6yIAqOqhPKZ8Guc6ag-rQ-__FGnE4mElwvBSaabbAq34yZOY9nrArkmnoK-uYgwlicns04JVO3t6WC7mCN2y9phRFC4fuKBRiisnORL_I2YFR_40pQQte4clBHdrRBamwdpaHKHyjzANgBmXr-dHl-WtQFjHhprTan_LvnyClSUqdi9UjG1vflfoaTqNG8XfE4xHEdYPeEV1oU3AGLI7jopvE_ttIlLN,970627,1713774732983, +Ari,BQCZI-sKKh-gDadBh62bMk_zumYhLNqdWCmvFZXBB9wYL0azlLePjBjwzFLloHai6okQ81TvzD4DDx3AaWGjaHSLNDTUcZ0eM0H5x4c0aMO_g7rB92eUvB1zsQ5LxSt52i71gZDLQAVgX61auwduagqLcXr_x-Fi_kwg6tv8Bx9N4_VLdiJY84SDpwtv8aN8MjO9IAFjOCtXh48uItrMoDbwWmU42EO7hsP7zD3Aqe3ZZSqothgDEtSJ,970627,1713774753056, +Ari,BQCpaZNCDAqh_cWPDS2cDkaxy4oldQz5KKQM-pwcmI8c84fEocb3bH_5QalZO3RHFf2Qnrt7sxjrewJQRGDMmLs5aVapE9R9C1FA3zh9F0NjmMA7aZpW6md_yJrAnTfPMLYnbz6-BQg5DPGWWH0x1hpu2javEiIue3QDPEG3DxMUj9_jW2b-rboe7d0KxtWsLvyeTQ5vUWvPfS92nFErxCvOKwTdlrqIwVUXxqyd0iz0Vipc0VPbSgF9,305354,1713775210560, +Ari,BQCk3oYBW0uMdXsUG0vmyUh_3iEkrQg_CPmQ_4ckFXaCePWkeh10eVbvv77UwhBm4xFrbPRhAhlkNtZrvbWAClh8ZAOwqET-L_gFJ-5x9VetWZFnKxAgTdcPwk2JY94H7SFdG4rVYjMj_1tnQEXLeNUtCISvL1Oo8N4dXCdIIrvi9SdmPOwZqDv4yDnk75PFmZ82qytyR6lVqi7ktYWDSuV3AwBifEGDHAsinUMvw5nKF4jFklNqso2k,305354,1713775318947, +Ari,BQC0WKlrB-dnk0JtAoEdC-Wf3KjXty3jM6viclicnaRZPgiKMU8Cm_tuqCFTfSGr8BXCBVdPi5aOksBLVtrQ2kPixHdYkmUs9A086jeDLhE8ufzXbrzt5uj5tEbQ35cqbY_vILsfHSqPrnuRnhmBSjACKDnRSS25ef7y1JoLD5UFXW7pEYQ8T4csYFS4KA23N_HSR6iw2P5pl7o-19hpN8XFIA5z9EPDH3qHXcVPnCUOPgGGb_85-IGY,485407,1713775825015, +Ari,BQDv8U9NVWjnZPv-lfh11IYvYinMrhitxg6H4hNG_uBC7lcMAQ_D0-3JOZxyJHO2T4sr8rzY68LjLPaAtLEuqcTbYGdXYGbBiY96bVRYoDsj3wJiYP9Uo-XqaHuuGpsU_IQLMuqG2m8tYhwYiKsdooiuaojMjfGEsxaTqZWIDWff76dyobaQ95lD6og5B-NsLA4VJixv7EsbZ06VID78XYH5L6oP99kGCrpEFl6DK1upMN6H6PpBlkdT,485407,1713775838900, +Ari,BQDTJvPxPBeRwZphJjwW_TI-QmzHI44oQeUiXvm0Ts9mGOK-qzElIZu_bOHXSxEfFWUHJ_E-D_3zSgcPgafZb4hLDTv17TIjP1R-TmjEuoSnAScrG-2T1xcsGkuPAi1-p6uusZaKo2a4oOesV7K8pzQhvjm7NbD2Q59UN3efMOsrXHcyN131E8cLR3kIUPWVuMkbjeDsWZVpJUQchppiFnFc6xCeQFvqfa4uTPmAlF_eK3vs40r8rtSX,447349,1713775928502, +Ari,BQBB2BAXDryIOXSm9b44wq-d09HrRl7dugEug19UIz1YE_nUds9r80ftkj9Srr3A58ZCvrDyHuPACY1jSbS0wwKzcbjhBxkGX0aMTZ1QWq9feT9imYqTWBE-K5pfFebn0tx2CEgSkvtqehE35WRZFcd2P7rl0Um8AxcZDDnh7-9_4CHpozXHetV7FvwLN4szJA9uujXJfwjNh8OwV1_W5pfkrUCOPYUDN0SYKlqPL0C1Gv9wsDFmwGq1,447349,1713775944233, From 1310aaf585e526567594c088c9ad9ac0866e1646 Mon Sep 17 00:00:00 2001 From: Martin Duong Date: Mon, 22 Apr 2024 14:01:36 -0400 Subject: [PATCH 08/11] CSS for checkbox --- receiptifyv1/app.js | 4 ++-- receiptifyv1/public/index.html | 2 +- receiptifyv1/public/server.js | 2 ++ receiptifyv1/public/styles.css | 21 +++++++++++++++++++++ receiptifyv1/users.csv | 10 ++-------- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/receiptifyv1/app.js b/receiptifyv1/app.js index 17e2490..aa59f28 100644 --- a/receiptifyv1/app.js +++ b/receiptifyv1/app.js @@ -27,8 +27,8 @@ const cors = require('cors'); require('dotenv').config(); -const client_id = '792207d6524f4255a1730e478d8b66f6'; -const client_secret = 'fd5c90696d984ca7a65a54853f340c70'; +const client_id = '035844db2ccb4d0698ab8e14bb12f27a'; +const client_secret = '8bfd5a9fa7a44aedbf8bf8f513236b4f'; //const privateKey = fs.readFileSync('AuthKey_A8FKGGUQP3.p8').toString(); const teamId = process.env.teamId; const keyId = process.env.keyId; diff --git a/receiptifyv1/public/index.html b/receiptifyv1/public/index.html index fdb9a97..a78b974 100644 --- a/receiptifyv1/public/index.html +++ b/receiptifyv1/public/index.html @@ -232,7 +232,7 @@

Top Track Generator

- +

Customize Receipt

diff --git a/receiptifyv1/public/server.js b/receiptifyv1/public/server.js index d0ac1cd..f514463 100644 --- a/receiptifyv1/public/server.js +++ b/receiptifyv1/public/server.js @@ -1306,6 +1306,7 @@ function showCheckbox() { const userCheckboxTitle = document.createElement('p'); userCheckboxTitle.textContent = "Select Users"; + userCheckboxTitle.id = "user-checkbox-title"; userCheckbox.appendChild(userCheckboxTitle); for (let i = 0; i < users.length; i++) { @@ -1323,6 +1324,7 @@ function showCheckbox() { }; const label = document.createElement('label'); + label.id = "user-checkbox-label"; label.textContent = users[i]; label.htmlFor = checkbox.id; diff --git a/receiptifyv1/public/styles.css b/receiptifyv1/public/styles.css index 8439984..3fb8b36 100644 --- a/receiptifyv1/public/styles.css +++ b/receiptifyv1/public/styles.css @@ -54,6 +54,27 @@ h2 { p { font-family: Helvetica, Geneva, Tahoma, sans-serif; } + +#user-checkbox { + margin-bottom: 2rem; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + margin-left: 2rem; +} + +#user-checkbox-title { + font-family: Inter, 'Helvetica Neue', sans-serif; + line-height: 1.2; + margin-left: -2rem; +} + +#user-checkbox-label { + padding-left: 1rem; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: black !important; + font-size: 18px !important; +} + + .logo { font-family: 'Helvetica Neue', Helvetica, sans-serif; font-weight: 600; diff --git a/receiptifyv1/users.csv b/receiptifyv1/users.csv index 0549aff..f89444a 100644 --- a/receiptifyv1/users.csv +++ b/receiptifyv1/users.csv @@ -1,9 +1,3 @@ -Ari,BQBSh8hEt_hWXp94VJrttZ7M6yIAqOqhPKZ8Guc6ag-rQ-__FGnE4mElwvBSaabbAq34yZOY9nrArkmnoK-uYgwlicns04JVO3t6WC7mCN2y9phRFC4fuKBRiisnORL_I2YFR_40pQQte4clBHdrRBamwdpaHKHyjzANgBmXr-dHl-WtQFjHhprTan_LvnyClSUqdi9UjG1vflfoaTqNG8XfE4xHEdYPeEV1oU3AGLI7jopvE_ttIlLN,970627,1713774732983, -Ari,BQCZI-sKKh-gDadBh62bMk_zumYhLNqdWCmvFZXBB9wYL0azlLePjBjwzFLloHai6okQ81TvzD4DDx3AaWGjaHSLNDTUcZ0eM0H5x4c0aMO_g7rB92eUvB1zsQ5LxSt52i71gZDLQAVgX61auwduagqLcXr_x-Fi_kwg6tv8Bx9N4_VLdiJY84SDpwtv8aN8MjO9IAFjOCtXh48uItrMoDbwWmU42EO7hsP7zD3Aqe3ZZSqothgDEtSJ,970627,1713774753056, -Ari,BQCpaZNCDAqh_cWPDS2cDkaxy4oldQz5KKQM-pwcmI8c84fEocb3bH_5QalZO3RHFf2Qnrt7sxjrewJQRGDMmLs5aVapE9R9C1FA3zh9F0NjmMA7aZpW6md_yJrAnTfPMLYnbz6-BQg5DPGWWH0x1hpu2javEiIue3QDPEG3DxMUj9_jW2b-rboe7d0KxtWsLvyeTQ5vUWvPfS92nFErxCvOKwTdlrqIwVUXxqyd0iz0Vipc0VPbSgF9,305354,1713775210560, -Ari,BQCk3oYBW0uMdXsUG0vmyUh_3iEkrQg_CPmQ_4ckFXaCePWkeh10eVbvv77UwhBm4xFrbPRhAhlkNtZrvbWAClh8ZAOwqET-L_gFJ-5x9VetWZFnKxAgTdcPwk2JY94H7SFdG4rVYjMj_1tnQEXLeNUtCISvL1Oo8N4dXCdIIrvi9SdmPOwZqDv4yDnk75PFmZ82qytyR6lVqi7ktYWDSuV3AwBifEGDHAsinUMvw5nKF4jFklNqso2k,305354,1713775318947, -Ari,BQC0WKlrB-dnk0JtAoEdC-Wf3KjXty3jM6viclicnaRZPgiKMU8Cm_tuqCFTfSGr8BXCBVdPi5aOksBLVtrQ2kPixHdYkmUs9A086jeDLhE8ufzXbrzt5uj5tEbQ35cqbY_vILsfHSqPrnuRnhmBSjACKDnRSS25ef7y1JoLD5UFXW7pEYQ8T4csYFS4KA23N_HSR6iw2P5pl7o-19hpN8XFIA5z9EPDH3qHXcVPnCUOPgGGb_85-IGY,485407,1713775825015, -Ari,BQDv8U9NVWjnZPv-lfh11IYvYinMrhitxg6H4hNG_uBC7lcMAQ_D0-3JOZxyJHO2T4sr8rzY68LjLPaAtLEuqcTbYGdXYGbBiY96bVRYoDsj3wJiYP9Uo-XqaHuuGpsU_IQLMuqG2m8tYhwYiKsdooiuaojMjfGEsxaTqZWIDWff76dyobaQ95lD6og5B-NsLA4VJixv7EsbZ06VID78XYH5L6oP99kGCrpEFl6DK1upMN6H6PpBlkdT,485407,1713775838900, -Ari,BQDTJvPxPBeRwZphJjwW_TI-QmzHI44oQeUiXvm0Ts9mGOK-qzElIZu_bOHXSxEfFWUHJ_E-D_3zSgcPgafZb4hLDTv17TIjP1R-TmjEuoSnAScrG-2T1xcsGkuPAi1-p6uusZaKo2a4oOesV7K8pzQhvjm7NbD2Q59UN3efMOsrXHcyN131E8cLR3kIUPWVuMkbjeDsWZVpJUQchppiFnFc6xCeQFvqfa4uTPmAlF_eK3vs40r8rtSX,447349,1713775928502, -Ari,BQBB2BAXDryIOXSm9b44wq-d09HrRl7dugEug19UIz1YE_nUds9r80ftkj9Srr3A58ZCvrDyHuPACY1jSbS0wwKzcbjhBxkGX0aMTZ1QWq9feT9imYqTWBE-K5pfFebn0tx2CEgSkvtqehE35WRZFcd2P7rl0Um8AxcZDDnh7-9_4CHpozXHetV7FvwLN4szJA9uujXJfwjNh8OwV1_W5pfkrUCOPYUDN0SYKlqPL0C1Gv9wsDFmwGq1,447349,1713775944233, +✧ jizzica ✧,BQBgPzh3R_Kro573KV7alDS0O74nCpx4WW8Xgj18Hp1AQE_ijZFkXsAneOIMF08SuHgfc2Ml_KrfykOjZ9Vxw_n8wc1wTwaqEGd358S21EXMo07-4WdlX3EPDyGqWoFQBcerzJ1hIyKBYb5HqH92WyaAi_laxxZSxkWaOTcgxVulWxVly-4XMvaI9VV3KuHt_JIZjbS8ontGZ3G35PDOLiFB6q5TawNbuTsBR48,261818,1713808836632, +✧ jizzica ✧,BQCrWoS_r3XRI3QaFaZ8lu-zR8W5RRxhLTlnNNJSVuYTyyc_LfZ1GfXqznB7iLb2sEhMr2TH28fcFW7R_pwas8147CwjxJcN5DYOdM41Pf2pazAlLUd1sls0trEuThcC9u8mJIb01RvAOFtVJFhHpB-DfCORDUVZykLrwwSs-V_yQ-9uDbo8vdjBlfLZnQo98BVvRvfc1yQOTMPbhqsbzSRW89tciuY-4LF6dW0,261818,1713808847899, From 5a40bde5dd3f2052d0d84b67f51d8afb82ff6340 Mon Sep 17 00:00:00 2001 From: Nina Perone Date: Mon, 22 Apr 2024 14:35:51 -0400 Subject: [PATCH 09/11] removed unused buttons --- receiptifyv1/public/index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/receiptifyv1/public/index.html b/receiptifyv1/public/index.html index fdb9a97..4d82c4d 100644 --- a/receiptifyv1/public/index.html +++ b/receiptifyv1/public/index.html @@ -257,10 +257,10 @@

Top Track Generator

- -

- Made by Michelle Liu + Inspired by Receiptify by Michelle Liu

Home | About | From 7d14e989f67fdb9d7ed9f433524e1319f3c67f97 Mon Sep 17 00:00:00 2001 From: nina-perone <143619402+nina-perone@users.noreply.github.com> Date: Mon, 22 Apr 2024 15:29:34 -0400 Subject: [PATCH 10/11] Update README.md updated project functionality --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b025ab..8cb8256 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Once you have created your app, change the `client_id` and `client_secret` value In order to run the app, open the folder, and run its `app.js` file: + $ cd receiptifyv1 $ node app.js Then, open `http://localhost:3000` in a browser. @@ -45,7 +46,9 @@ A user on the same network the app is hosted on can put the host's IP and port n The first person will click the "Create Session" button and log into their Spotify account. A Session ID will appear on the top of their receipt. -Other users can then click "Join Session" and after entering the shared Session ID, they can log into their Spotify accounts and view the receipt. After refreshing the page, checkboxes will appear next to each joined user's name indicating which Spotify accounts data will be included. (CURRENTLY ONLY WORKS FOR TOP ARTISTS) +Other users can then click "Join Session" and after entering the shared Session ID, they can log into their Spotify accounts and view the receipt. + +After refreshing the page, checkboxes will appear next to each joined user's name indicating which Spotify accounts data will be included. You can pick from viewing Top Tracks, Top Artists, Stats, and Top Genres (CURRENTLY ONLY WORKS FOR TOP ARTISTS, TRACKS, AND STATS). You can also change the time period data is drawn from and length of receipt. Under the receipt, you can download the image or open it in a new tab. Screenshot 2024-04-17 at 9 45 04 AM From 5e27709f8cc49b3465368ef350d619bd1edaa23f Mon Sep 17 00:00:00 2001 From: Nina Perone Date: Mon, 22 Apr 2024 19:31:43 -0400 Subject: [PATCH 11/11] changed track amount --- receiptifyv1/public/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receiptifyv1/public/server.js b/receiptifyv1/public/server.js index f9b3a83..4003409 100644 --- a/receiptifyv1/public/server.js +++ b/receiptifyv1/public/server.js @@ -1223,7 +1223,7 @@ function retrieveItems(stats, state) { function retrieveStats() { const timeRangeSlug = getPeriod(); - const limit = 50; + const limit = 10; // changed from 50 to handle more users var users_checkbox = getUsersCheckbox(); const promises_artists = []; const promises_tracks = [];