andrade-soulseek-downloader
Version:
Simple, safe Soulseek download library with built-in rate limiting to prevent bans
113 lines • 4.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrackSelectionService = void 0;
/**
* Domain service for track selection and prioritization.
* Implements quality-first download strategy with progressive fallback.
*/
class TrackSelectionService {
/**
* Groups tracks by bitrate for quality-tiered download attempts.
* @param tracks - Array of available tracks
* @returns Map of bitrate to tracks
*/
groupByBitrate(tracks) {
const groups = new Map();
tracks.forEach(track => {
const bitrate = track.getBitrate().getValue();
if (!groups.has(bitrate)) {
groups.set(bitrate, []);
}
groups.get(bitrate).push(track);
});
return groups;
}
/**
* Sorts tracks by quality within a bitrate group.
* Prioritizes slot availability, then quality score.
* @param tracks - Tracks to sort
* @returns Sorted tracks (best first)
*/
sortByQuality(tracks) {
return [...tracks].sort((a, b) => {
// First priority: available slots
if (a.hasAvailableSlots() !== b.hasAvailableSlots()) {
return a.hasAvailableSlots() ? -1 : 1;
}
// Second: quality score
return b.calculateQualityScore() - a.calculateQualityScore();
});
}
/**
* @param groups - Bitrate groups map
* @returns Bitrates sorted from highest to lowest
*/
getOrderedBitrates(groups) {
return Array.from(groups.keys()).sort((a, b) => b - a);
}
/**
* Selects best tracks using quality-first strategy.
* @param tracks - All available tracks
* @param maxPerBitrate - Max tracks to select per bitrate tier
* @returns Ordered list of best tracks to attempt
*/
selectBestTracks(tracks, maxPerBitrate = 5) {
const groups = this.groupByBitrate(tracks);
const orderedBitrates = this.getOrderedBitrates(groups);
const selected = [];
for (const bitrate of orderedBitrates) {
const tracksInGroup = groups.get(bitrate);
const sorted = this.sortByQuality(tracksInGroup);
selected.push(...sorted.slice(0, maxPerBitrate));
}
return selected;
}
/**
* Filters out tracks below minimum bitrate threshold.
* @param tracks - Tracks to filter
* @param minBitrate - Minimum acceptable bitrate
* @returns Tracks meeting minimum quality
*/
filterByMinimumQuality(tracks, minBitrate) {
return tracks.filter(track => track.getBitrate().getValue() >= minBitrate.getValue());
}
/**
* Filters out tracks above maximum bitrate threshold.
* @param tracks - Tracks to filter
* @param maxBitrate - Maximum acceptable bitrate
* @returns Tracks not exceeding maximum quality
*/
filterByMaximumQuality(tracks, maxBitrate) {
return tracks.filter(track => track.getBitrate().getValue() <= maxBitrate.getValue());
}
/**
* Filters tracks by bitrate range.
* @param tracks - Tracks to filter
* @param minBitrate - Minimum acceptable bitrate
* @param maxBitrate - Maximum acceptable bitrate (optional)
* @returns Tracks within quality range
*/
filterByQualityRange(tracks, minBitrate, maxBitrate) {
let filtered = this.filterByMinimumQuality(tracks, minBitrate);
if (maxBitrate) {
filtered = this.filterByMaximumQuality(filtered, maxBitrate);
}
return filtered;
}
/**
* Validates if track meets quality standards.
* @param track - Track to validate
* @param minBitrate - Minimum bitrate requirement
* @param maxBitrate - Maximum bitrate requirement (optional)
* @returns True if track meets all quality criteria
*/
meetsQualityStandards(track, minBitrate, maxBitrate) {
const trackBitrate = track.getBitrate().getValue();
const meetsMinimum = trackBitrate >= minBitrate.getValue();
const meetsMaximum = !maxBitrate || trackBitrate <= maxBitrate.getValue();
const meetsMatchScore = track.getMatchScore() > 0.2;
return meetsMinimum && meetsMaximum && meetsMatchScore;
}
}
exports.TrackSelectionService = TrackSelectionService;
//# sourceMappingURL=track-selection-service.js.map