forked from Keelrleek/SoulStream
87 lines
4.2 KiB
JavaScript
87 lines
4.2 KiB
JavaScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { rankPeople, reasonText, reasonParts, WEIGHTS, CAPS } from "../../src/lib/discover.js";
|
|
|
|
const overlapOf = (username, albums, gaps = 0, artists = 0) => ({
|
|
username,
|
|
albums_in_common_count: albums,
|
|
gaps_count: gaps,
|
|
artists_in_common_count: artists,
|
|
});
|
|
|
|
test("one list across the shelves, every card naming where it came from", () => {
|
|
const ranked = rankPeople({
|
|
me: "zoocone",
|
|
rooms: {
|
|
ambient: { users: [{ username: "aphex" }, { username: "zoocone" }, { username: "boc" }] },
|
|
idm: { users: [{ username: "boc" }] },
|
|
},
|
|
activeRoom: "ambient",
|
|
downloads: [{ username: "aphex" }, { username: "aphex" }],
|
|
uploads: [{ username: "autechre" }],
|
|
similar: [{ username: "boc", rating: 3 }, { username: "aphex", rating: 1 }],
|
|
overlap: [overlapOf("autechre", 4, 2), overlapOf("aphex", 0, 0, 0)],
|
|
space: { name: "Late Night Ambient", members: [{ username: "boc" }, { username: null }, { username: "zoocone", is_me: true }] },
|
|
});
|
|
assert.deepEqual(
|
|
ranked.map((p) => p.username),
|
|
["autechre", "boc", "aphex"],
|
|
);
|
|
const [autechre, boc, aphex] = ranked;
|
|
// autechre: 4 albums in common + 2 gaps, one upload
|
|
assert.equal(autechre.score, 4 * WEIGHTS.albumInCommon + 2 * WEIGHTS.gap + WEIGHTS.transfer);
|
|
assert.deepEqual(autechre.reasons.map(reasonText), ["shares 4 albums you own · 2 you lack", "you sent them 1"]);
|
|
// boc: 3 likes, in the active room and one other, a seat in the Space
|
|
assert.equal(boc.score, 3 * WEIGHTS.like + WEIGHTS.activeRoom + WEIGHTS.room + WEIGHTS.spaceMember);
|
|
assert.deepEqual(boc.reasons.map(reasonText), [
|
|
"shares 3 of your declared likes",
|
|
"in #ambient now · also in #idm",
|
|
"with you in Late Night Ambient",
|
|
]);
|
|
// aphex: a browse with nothing in common scores nothing and is not a
|
|
// reason; the three that remain tie at two points each and keep the
|
|
// signal order (likes, rooms, transfers)
|
|
assert.equal(aphex.score, WEIGHTS.activeRoom + 2 * WEIGHTS.transfer + WEIGHTS.like);
|
|
assert.deepEqual(aphex.reasons.map(reasonText), ["shares 1 of your declared likes", "in #ambient now", "sent you 2 files"]);
|
|
// we never list ourselves, and a member without a Soulseek name has no card
|
|
assert.ok(!ranked.some((p) => p.username === "zoocone"));
|
|
});
|
|
|
|
test("contacts and friends are someone else's shelf, and a cap keeps one browse honest", () => {
|
|
const ranked = rankPeople({
|
|
me: "zoocone",
|
|
skip: (u) => u === "buddy",
|
|
overlap: [overlapOf("buddy", 40, 40), overlapOf("hoarder", 40, 40, 40), overlapOf("thin", 0, 3, 2)],
|
|
similar: [{ username: "buddy", rating: 9 }],
|
|
});
|
|
assert.deepEqual(ranked.map((p) => p.username), ["hoarder", "thin"]);
|
|
assert.equal(ranked[0].score, CAPS.albums * WEIGHTS.albumInCommon + CAPS.gaps * WEIGHTS.gap);
|
|
// artists only count when no album is in common
|
|
assert.equal(ranked[1].score, 3 * WEIGHTS.gap + 2 * WEIGHTS.artistInCommon);
|
|
assert.equal(reasonText(ranked[1].reasons[0]), "2 artists in common · 3 albums you lack");
|
|
});
|
|
|
|
test("ties break toward fewer, stronger reasons, then by name; the limit holds", () => {
|
|
const ranked = rankPeople({
|
|
me: "",
|
|
similar: [{ username: "b", rating: 2 }, { username: "a", rating: 2 }],
|
|
downloads: [{ username: "c" }, { username: "c" }, { username: "c" }, { username: "c" }],
|
|
limit: 2,
|
|
});
|
|
// c: 4 transfers = 4 points; a and b: 2 likes = 4 points each, one reason each
|
|
assert.deepEqual(ranked.map((p) => p.username), ["a", "b"]);
|
|
assert.deepEqual(rankPeople({ me: "", similar: [] }), []);
|
|
assert.equal(reasonText({ kind: "rooms", active: null, others: ["x", "y"] }), "in 2 rooms with you");
|
|
// the numbers and names are what the card bolds
|
|
assert.deepEqual(
|
|
reasonParts({ kind: "transfers", from: 2, to: 1 }).filter((s) => s.b).map((s) => s.t),
|
|
["2", "1"],
|
|
);
|
|
assert.deepEqual(reasonParts({ kind: "rooms", active: "idm", others: [] }), [
|
|
{ t: "in ", b: false },
|
|
{ t: "#idm", b: true },
|
|
{ t: " now", b: false },
|
|
]);
|
|
});
|