From 2c7e3c8fb279f20da3d1b4f5610e65dc43a22ac2 Mon Sep 17 00:00:00 2001 From: Florrie Date: Sat, 11 Jul 2020 16:22:01 -0300 Subject: support queue controls over socket clients --- playlist-utils.js | 128 +++++++++++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 58 deletions(-) (limited to 'playlist-utils.js') diff --git a/playlist-utils.js b/playlist-utils.js index f58a9e8..7c742ae 100644 --- a/playlist-utils.js +++ b/playlist-utils.js @@ -187,15 +187,30 @@ export function flattenGrouplike(grouplike) { // levels in the group tree and returns them as a new group containing those // tracks. - return { - items: grouplike.items.map(item => { - if (isGroup(item)) { - return flattenGrouplike(item).items - } else { - return [item] - } - }).reduce((a, b) => a.concat(b), []) - } + return {items: getFlatTrackList(grouplike)} +} + +export function getFlatTrackList(grouplike) { + // Underlying function for flattenGrouplike. Can be used if you just want to + // get an array and not a grouplike, too. + + return grouplike.items.map(item => { + if (isGroup(item)) { + return getFlatTrackList(item) + } else { + return [item] + } + }).reduce((a, b) => a.concat(b), []) +} + +export function getFlatGroupList(grouplike) { + // Analogue of getFlatTrackList for groups instead of tracks. Returns a flat + // array of all the groups in each level of the provided grouplike. + + return grouplike.items + .filter(isGroup) + .map(item => [item, ...getFlatGroupList(item)]) + .reduce((a, b) => a.concat(b), []) } export function countTotalTracks(item) { @@ -847,20 +862,17 @@ export function getPathScore(path1, path2) { return scores.reduce((a, b) => a < b ? a : b) } -export function findTrackObject(referenceData, sourcePlaylist, flattenedSourcePlaylist = null) { - // Finds the track object in the source playlist which most closely resembles +export function findItemObject(referenceData, possibleChoices) { + // Finds the item object in the provided choices which most closely resembles // the provided reference data. This is used for maintaining the identity of - // track objects when reloading a playlist (see serialized-backend.js). It's - // also usable in synchronizing the identity of tracks across linked clients + // item objects when reloading a playlist (see serialized-backend.js). It's + // also usable in synchronizing the identity of items across linked clients // (see socket.js). - // - // NB: This function is many times more efficient if you pass a preemptively - // flattened version of the source playlist in as well! - // Reference data includes track NAME, track SOURCE (downloaderArg), and - // track PATH (names of parent groups). Specifics of how existing track - // objects are determined to resemble this data are laid out next to the - // relevant implementation code. + // Reference data includes item NAME, item SOURCE (downloaderArg), and item + // PATH (names of parent groups). Specifics of how existing item objects are + // determined to resemble this data are laid out next to the relevant + // implementation code. // // TODO: Should track number be considered here? // TODO: Should track "metadata" (duration, md5?) be considered too? @@ -868,41 +880,37 @@ export function findTrackObject(referenceData, sourcePlaylist, flattenedSourcePl // tracks *is*, and in considering those I lean towards "no" here, but // it's probably worth looking at more in the future. (TM.) - function getTrackPathScore(track) { + function getItemPathScore(item) { if (!referenceData.path) { return null } const path1 = referenceData.path.slice() - const path2 = getItemPath(track).slice(0, -1).map(group => group.name) + const path2 = getItemPath(item).slice(0, -1).map(group => group.name) return getPathScore(path1, path2) } - if (!flattenedSourcePlaylist) { - flattenedSourcePlaylist = flattenGrouplike(sourcePlaylist) - } - - // The only tracks which will be considered at all are those which match at + // The only items which will be considered at all are those which match at // least one of the reference name/source. - const baselineResemble = flattenedSourcePlaylist.items.filter(track => - track.name === referenceData.name || - track.downloaderArg === referenceData.downloaderArg) + const baselineResemble = possibleChoices.filter(item => + item.name === referenceData.name || + item.downloaderArg && item.downloaderArg === referenceData.downloaderArg) - // If no track matches the baseline conditions for resemblance at all, + // If no item matches the baseline conditions for resemblance at all, // return null. It's up to the caller to decide what to do in this case, - // e.g. reporting that no track was found, or creating a new track object + // e.g. reporting that no item was found, or creating a new item object // from the reference data altogether. if (!baselineResemble.length) { return null } - // Find the "reasons" these tracks resemble the reference data; these will - // be used as the factors in calculating which track resembles closest. - const reasons = baselineResemble.map(track => ({ - track, - nameMatches: track.name === referenceData.name, - sourceMatches: track.downloaderArg === referenceData.downloaderArg, - pathScore: getTrackPathScore(track) + // Find the "reasons" these items resemble the reference data; these will + // be used as the factors in calculating which item resembles closest. + const reasons = baselineResemble.map(item => ({ + item, + nameMatches: item.name === referenceData.name, + sourceMatches: item.downloaderArg && item.downloaderArg === referenceData.downloaderArg, + pathScore: getItemPathScore(item) })) // TODO: The algorithm for determining which track matches closest is @@ -933,7 +941,7 @@ export function findTrackObject(referenceData, sourcePlaylist, flattenedSourcePl mostResembles = reasons[0] } - return mostResembles.track + return mostResembles.item } /* @@ -941,23 +949,27 @@ console.log(getPathScore(['A', 'B', 'C'], ['A', 'B', 'C'])) console.log(getPathScore(['A', 'B', 'C'], ['A', 'B', 'C', 'D'])) console.log(getPathScore(['A', 'B', 'C', 'E'], ['A', 'B', 'C'])) console.log(getPathScore(['W', 'X'], ['Y', 'Z'])) -console.log(findTrackObject( - {name: 'T', downloaderArg: 'foo', path: ['A', 'B', 'C']}, - updateGroupFormat({items: [ - {id: 1, name: 'T'}, - {id: 2, name: 'T'}, - {id: 3, name: 'T'}, - // {id: 4, name: 'T', downloaderArg: 'foo'}, - {id: 5, name: 'T'}, - {id: 6, name: 'Y', downloaderArg: 'foo'}, - // {name: 'A', items: [ - // {name: 'B', items: [ - // {name: 'C', items: [ - // {name: 'T'} - // ]}, - // {name: 'T'} - // ]} - // ]} - ]}) +console.log(findItemObject( + // {name: 'T', downloaderArg: 'foo', path: ['A', 'B', 'C']}, + {name: 'B'}, + // getFlatTrackList( + getFlatGroupList( + updateGroupFormat({items: [ + {id: 1, name: 'T'}, + {id: 2, name: 'T'}, + {id: 3, name: 'T'}, + // {id: 4, name: 'T', downloaderArg: 'foo'}, + {id: 5, name: 'T'}, + {id: 6, name: 'Y', downloaderArg: 'foo'}, + {name: 'A', items: [ + {name: 'B', items: [ + {name: 'C', items: [ + {name: 'T'} + ]}, + {name: 'T'} + ]} + ]} + ]}) + ) )) */ -- cgit 1.3.0-6-gf8a5