Replies: 3 comments
-
Крепкий среднячокfunction updateStrongMiddle() {
const PLAYED_COUNT = { min: 3, max: 15 }
const FULL_DIFF = { min: 90, max: 111 }
const SKIP_DIFF = { min: 0, max: 60 }
const SKIP_THRESHOLD = 5
const SKIP_DAYS_REL = 14
let tracks = getRecentTracks()
calcDiff()
skipRecentDays()
reduceDiff()
filter()
Playlist.saveWithReplace({
name: 'Крепкий среднячок',
tracks: Selector.sliceRandom(tracks, 15)
})
function getRecentTracks() {
let recentTracks = Combiner.push([], Cache.read('SpotifyRecentTracks'), Cache.read('LastfmRecentTracks'))
let grouped = Object.values(recentTracks.reduce((acc, track) => {
acc[track.id] = acc[track.id] || []
acc[track.id].push(track)
return acc
}, {}))
let deduped = grouped.map(tracks => {
Order.sort(tracks, 'meta.played_at', 'desc')
for (let i = 1; i < tracks.length; i++) {
let xTime = new Date(tracks[i - 1])
let yTime = new Date(tracks[i])
if (xTime - yTime <= 10000) {
i--
tracks.splice(i, 1)
}
}
return tracks
}).flat(1)
Order.sort(deduped, 'meta.played_at', 'asc')
return deduped
}
function calcDiff() {
for (let i = 1; i < tracks.length; i++) {
let aEnd = new Date(tracks[i - 1].played_at).getTime()
let bEnd = new Date(tracks[i].played_at).getTime()
let delta = bEnd - aEnd
tracks[i].diffProcent = 100 * delta / tracks[i].duration_ms
}
}
function skipRecentDays() {
let recentTracks = RecentTracks.get()
Filter.rangeDateRel(recentTracks, SKIP_DAYS_REL, 0)
Filter.removeTracks(tracks, recentTracks)
}
function reduceDiff() {
tracks = Object.values(tracks.reduce((acc, track) => {
acc[track.id] = acc[track.id] || track
acc[track.id].diffGroup = acc[track.id].diffGroup || []
acc[track.id].diffGroup.push(track.diffProcent)
return acc
}, {}))
}
function filter() {
tracks = tracks.filter(t => {
t.fullPlayedCount = reduce(t, FULL_DIFF.min, FULL_DIFF.max)
t.skipCount = reduce(t, SKIP_DIFF.min, SKIP_DIFF.max)
return t.skipCount <= SKIP_THRESHOLD && (t.fullPlayedCount >= PLAYED_COUNT.min && t.fullPlayedCount <= PLAYED_COUNT.max)
})
function reduce(track, min, max) {
return track.diffGroup.reduce((acc, value) => {
let int = Math.round(value)
return int >= min && int <= max ? ++acc : acc
}, 0)
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Соединил некоторые части алгоритмов Крепкого середнячка и Лучшего времени суток. Добавил константу пересечения - то есть сколько раз трек играл в определенное время суток. В моем случае получилось забавно, среди найденных треков постоянно много лайков, но не все. Если также будет у вас, то похоже на паттерн вылавливания претендентов на лайки) Предполагается триггер на каждый час. Clerk обновит плейлист 4 раза за день. Чтобы подобрать оптимальные значения констант, можно запустить функцию несколько раз не дожидаясь триггера. let targetPeriod = 'morning';
// Clerk.runOnceAfter('00:00', function nightStrongPls() { onSetDayPeriod() });
// Clerk.runOnceAfter('06:00', function morningStrongPls() { onSetDayPeriod() });
// Clerk.runOnceAfter('12:00', function dayStrongPls() { onSetDayPeriod() });
// Clerk.runOnceAfter('18:00', function eveningStrongPls() { onSetDayPeriod() });
// if (targetPeriod.length == 0) {
// return;
// } Претенденты на лайкиfunction updateStrongMiddleWithPeriods() {
const PLAYED_COUNT = { min: 9, max: 90 }
const FULL_DIFF = { min: 60, max: 112 }
const SKIP_DIFF = { min: 0, max: 51 }
const SKIP_THRESHOLD = 20
const SKIP_DAYS_REL = 8
const MIN_CROSS_COUNT = 5
const PERIODS = [
{ period: 'night', from: 0, to: 5 },
{ period: 'morning', from: 6, to: 11 },
{ period: 'day', from: 12, to: 17 },
{ period: 'evening', from: 18, to: 23 },
];
let targetPeriod = '';
Clerk.runOnceAfter('00:00', function nightStrongPls() { onSetDayPeriod() });
Clerk.runOnceAfter('06:00', function morningStrongPls() { onSetDayPeriod() });
Clerk.runOnceAfter('12:00', function dayStrongPls() { onSetDayPeriod() });
Clerk.runOnceAfter('18:00', function eveningStrongPls() { onSetDayPeriod() });
if (targetPeriod.length == 0) {
return;
}
let tracks = getRecentTracks()
calcDiff()
skipRecentDays()
reduceDiff()
filter()
Playlist.saveWithReplace({
name: 'Претенденты на лайки',
tracks: Selector.sliceRandom(tracks, 30)
})
function getRecentTracks() {
let recentTracks = Combiner.push([], Cache.read('SpotifyRecentTracks'), Cache.read('LastfmRecentTracks'))
let grouped = Object.values(recentTracks.reduce((acc, track) => {
acc[track.id] = acc[track.id] || []
acc[track.id].push(track)
return acc
}, {}))
let deduped = grouped.map(tracks => {
Order.sort(tracks, 'meta.played_at', 'desc')
for (let i = 1; i < tracks.length; i++) {
let xTime = new Date(tracks[i - 1])
let yTime = new Date(tracks[i])
if (xTime - yTime <= 10000) {
i--
tracks.splice(i, 1)
}
}
return tracks
}).flat(1)
Order.sort(deduped, 'meta.played_at', 'asc')
return deduped
}
function calcDiff() {
for (let i = 1; i < tracks.length; i++) {
let aEnd = new Date(tracks[i - 1].played_at).getTime()
let bEnd = new Date(tracks[i].played_at).getTime()
let delta = bEnd - aEnd
tracks[i].diffProcent = 100 * delta / tracks[i].duration_ms
}
}
function skipRecentDays() {
let recentTracks = RecentTracks.get()
Filter.rangeDateRel(recentTracks, SKIP_DAYS_REL, 0)
Filter.removeTracks(tracks, recentTracks)
}
function reduceDiff() {
tracks = Object.values(tracks.reduce((acc, track) => {
acc[track.id] = acc[track.id] || track
acc[track.id].diffGroup = acc[track.id].diffGroup || []
acc[track.id].diffGroup.push(track.diffProcent)
acc[track.id].periods = acc[track.id].periods || []
acc[track.id].periods.push(track.played_at || track.added_at)
return acc
}, {})).map((t, i) => {
t.crossPeriodCount = t.periods.filter(p => isDayPeriod(new Date(p), targetPeriod)).length
return t
})
}
function filter() {
tracks = tracks.filter(t => {
t.fullPlayedCount = reduce(t, FULL_DIFF.min, FULL_DIFF.max)
t.skipCount = reduce(t, SKIP_DIFF.min, SKIP_DIFF.max)
return t.skipCount <= SKIP_THRESHOLD && t.crossPeriodCount >= MIN_CROSS_COUNT
&& (t.fullPlayedCount >= PLAYED_COUNT.min && t.fullPlayedCount <= PLAYED_COUNT.max)
})
function reduce(track, min, max) {
return track.diffGroup.reduce((acc, value) => {
let int = Math.round(value)
return int >= min && int <= max ? ++acc : acc
}, 0)
}
}
function onSetDayPeriod() {
let nowHours = new Date().getHours();
targetPeriod = PERIODS.find(item => nowHours >= item.from && nowHours <= item.to).period;
}
function isDayPeriod(date, period) {
let hours = date.getHours();
return PERIODS.some(item => period == item.period && hours >= item.from && hours <= item.to);
}
} |
Beta Was this translation helpful? Give feedback.
-
при выполнении создаётся пустой плейлист |
Beta Was this translation helpful? Give feedback.
-
Наверное не ошибусь, если скажу, что большинство скриптов преследует цель убирать историю прослушиваний. Пойдя от обратного, попробовал ответить на вопрос: как найти крепкий среднячок, который не успел надоесть, редко пропускается, не попадает в топы? Меня результат приятно удивил. Интересно услышать ваши результаты.
Плейлисты
Описание констант
Beta Was this translation helpful? Give feedback.
All reactions