Files

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 },
]);
});