mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-09 21:17:15 +03:00
Make reputation take into account self downvotes
This commit is contained in:
@@ -173,8 +173,8 @@ function getWeightedRandomChoice<T extends VotableObject>(choices: T[], amountOf
|
|||||||
|
|
||||||
//The 3 makes -2 the minimum votes before being ignored completely
|
//The 3 makes -2 the minimum votes before being ignored completely
|
||||||
//this can be changed if this system increases in popularity.
|
//this can be changed if this system increases in popularity.
|
||||||
const weight = Math.exp(choice.votes * Math.min(1, choice.reputation + 1) + 3 + boost);
|
const weight = Math.exp(choice.votes * Math.max(1, choice.reputation + 1) + 3 + boost);
|
||||||
totalWeight += weight;
|
totalWeight += Math.max(weight, 0);
|
||||||
|
|
||||||
return {...choice, weight};
|
return {...choice, weight};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { reputationKey } from "./redisKeys";
|
|||||||
interface ReputationDBResult {
|
interface ReputationDBResult {
|
||||||
totalSubmissions: number,
|
totalSubmissions: number,
|
||||||
downvotedSubmissions: number,
|
downvotedSubmissions: number,
|
||||||
|
nonSelfDownvotedSubmissions: number,
|
||||||
upvotedSum: number,
|
upvotedSum: number,
|
||||||
lockedSum: number,
|
lockedSum: number,
|
||||||
oldUpvotedSubmissions: number
|
oldUpvotedSubmissions: number
|
||||||
@@ -17,10 +18,15 @@ export async function getReputation(userID: UserID): Promise<number> {
|
|||||||
const fetchFromDB = () => db.prepare("get",
|
const fetchFromDB = () => db.prepare("get",
|
||||||
`SELECT COUNT(*) AS "totalSubmissions",
|
`SELECT COUNT(*) AS "totalSubmissions",
|
||||||
SUM(CASE WHEN "votes" < 0 THEN 1 ELSE 0 END) AS "downvotedSubmissions",
|
SUM(CASE WHEN "votes" < 0 THEN 1 ELSE 0 END) AS "downvotedSubmissions",
|
||||||
|
SUM(CASE WHEN "votes" < 0 AND "videoID" NOT IN
|
||||||
|
(SELECT b."videoID" FROM "sponsorTimes" as b
|
||||||
|
WHERE b."userID" = ?
|
||||||
|
AND b."votes" > 0 AND b."category" = "a"."category" AND b."videoID" = "a"."videoID" LIMIT 1)
|
||||||
|
THEN 1 ELSE 0 END) AS "nonSelfDownvotedSubmissions",
|
||||||
SUM(CASE WHEN "votes" > 0 AND "timeSubmitted" > 1596240000000 THEN "votes" ELSE 0 END) AS "upvotedSum",
|
SUM(CASE WHEN "votes" > 0 AND "timeSubmitted" > 1596240000000 THEN "votes" ELSE 0 END) AS "upvotedSum",
|
||||||
SUM(locked) AS "lockedSum",
|
SUM(locked) AS "lockedSum",
|
||||||
SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "oldUpvotedSubmissions"
|
SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "oldUpvotedSubmissions"
|
||||||
FROM "sponsorTimes" WHERE "userID" = ?`, [pastDate, userID]) as Promise<ReputationDBResult>;
|
FROM "sponsorTimes" as "a" WHERE "userID" = ?`, [userID, pastDate, userID]) as Promise<ReputationDBResult>;
|
||||||
|
|
||||||
const result = await QueryCacher.get(fetchFromDB, reputationKey(userID));
|
const result = await QueryCacher.get(fetchFromDB, reputationKey(userID));
|
||||||
|
|
||||||
@@ -31,7 +37,12 @@ export async function getReputation(userID: UserID): Promise<number> {
|
|||||||
|
|
||||||
const downvoteRatio = result.downvotedSubmissions / result.totalSubmissions;
|
const downvoteRatio = result.downvotedSubmissions / result.totalSubmissions;
|
||||||
if (downvoteRatio > 0.3) {
|
if (downvoteRatio > 0.3) {
|
||||||
return convertRange(downvoteRatio, 0.3, 1, -0.5, -1.5);
|
return convertRange(Math.min(downvoteRatio, 0.7), 0.3, 0.7, -0.5, -2.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonSelfDownvoteRatio = result.nonSelfDownvotedSubmissions / result.totalSubmissions;
|
||||||
|
if (nonSelfDownvoteRatio > 0.05) {
|
||||||
|
return convertRange(Math.min(nonSelfDownvoteRatio, 0.4), 0.05, 0.4, -0.5, -2.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.oldUpvotedSubmissions < 3 || result.upvotedSum < 5) {
|
if (result.oldUpvotedSubmissions < 3 || result.upvotedSum < 5) {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ describe('getUserInfo', () => {
|
|||||||
done('Returned incorrect segmentCount "' + data.segmentCount + '"');
|
done('Returned incorrect segmentCount "' + data.segmentCount + '"');
|
||||||
} else if (data.ignoredSegmentCount !== 2) {
|
} else if (data.ignoredSegmentCount !== 2) {
|
||||||
done('Returned incorrect ignoredSegmentCount "' + data.ignoredSegmentCount + '"');
|
done('Returned incorrect ignoredSegmentCount "' + data.ignoredSegmentCount + '"');
|
||||||
} else if (Math.abs(data.reputation - -0.928) > 0.001) {
|
} else if (data.reputation !== -2) {
|
||||||
done('Returned incorrect reputation "' + data.reputation + '"');
|
done('Returned incorrect reputation "' + data.reputation + '"');
|
||||||
} else if (data.lastSegmentID !== "uuid000005") {
|
} else if (data.lastSegmentID !== "uuid000005") {
|
||||||
done('Returned incorrect last segment "' + data.lastSegmentID + '"');
|
done('Returned incorrect last segment "' + data.lastSegmentID + '"');
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { getReputation } from '../../src/utils/reputation';
|
|||||||
|
|
||||||
const userIDLowSubmissions = "reputation-lowsubmissions" as UserID;
|
const userIDLowSubmissions = "reputation-lowsubmissions" as UserID;
|
||||||
const userIDHighDownvotes = "reputation-highdownvotes" as UserID;
|
const userIDHighDownvotes = "reputation-highdownvotes" as UserID;
|
||||||
|
const userIDHighNonSelfDownvotes = "reputation-highnonselfdownvotes" as UserID;
|
||||||
const userIDNewSubmissions = "reputation-newsubmissions" as UserID;
|
const userIDNewSubmissions = "reputation-newsubmissions" as UserID;
|
||||||
const userIDLowSum = "reputation-lowsum" as UserID;
|
const userIDLowSum = "reputation-lowsum" as UserID;
|
||||||
const userIDHighRepBeforeManualVote = "reputation-oldhighrep" as UserID;
|
const userIDHighRepBeforeManualVote = "reputation-oldhighrep" as UserID;
|
||||||
@@ -29,6 +30,17 @@ describe('reputation', () => {
|
|||||||
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, -1, 0, 'reputation-1-uuid-5', '${getHash(userIDHighDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, -1, 0, 'reputation-1-uuid-5', '${getHash(userIDHighDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-uuid-6', '${getHash(userIDHighDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-uuid-6', '${getHash(userIDHighDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-uuid-7', '${getHash(userIDHighDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-uuid-7', '${getHash(userIDHighDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
|
||||||
|
// Each downvote is on a different video (ie. they didn't resubmit to fix their downvote)
|
||||||
|
await db.prepare("run", startOfQuery + `('${videoID}A', 1, 11, 2, 0, 'reputation-1-1-uuid-0', '${getHash(userIDHighNonSelfDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
// Different category, same video
|
||||||
|
await db.prepare("run", startOfQuery + `('${videoID}A', 1, 11, -2, 0, 'reputation-1-1-uuid-1', '${getHash(userIDHighNonSelfDownvotes)}', 1606240000000, 50, 'intro', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-1-uuid-2', '${getHash(userIDHighNonSelfDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-1-uuid-3', '${getHash(userIDHighNonSelfDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-1-uuid-4', '${getHash(userIDHighNonSelfDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, -1, 0, 'reputation-1-1-uuid-5', '${getHash(userIDHighNonSelfDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-1-uuid-6', '${getHash(userIDHighNonSelfDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 0, 0, 'reputation-1-1-uuid-7', '${getHash(userIDHighNonSelfDownvotes)}', 1606240000000, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
|
|
||||||
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 2, 0, 'reputation-2-uuid-0', '${getHash(userIDNewSubmissions)}', ${Date.now()}, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 2, 0, 'reputation-2-uuid-0', '${getHash(userIDNewSubmissions)}', ${Date.now()}, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 2, 0, 'reputation-2-uuid-1', '${getHash(userIDNewSubmissions)}', ${Date.now()}, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
await db.prepare("run", startOfQuery + `('${videoID}', 1, 11, 2, 0, 'reputation-2-uuid-1', '${getHash(userIDNewSubmissions)}', ${Date.now()}, 50, 'sponsor', 'YouTube', 100, 0, 0, '${getHash(videoID, 1)}')`);
|
||||||
@@ -81,7 +93,11 @@ describe('reputation', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("user with high downvote ratio", async () => {
|
it("user with high downvote ratio", async () => {
|
||||||
assert.strictEqual(await getReputation(getHash(userIDHighDownvotes)), -0.9642857142857144);
|
assert.strictEqual(await getReputation(getHash(userIDHighDownvotes)), -2.125);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("user with high non self downvote ratio", async () => {
|
||||||
|
assert.strictEqual(await getReputation(getHash(userIDHighNonSelfDownvotes)), -1.6428571428571428);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("user with mostly new submissions", async () => {
|
it("user with mostly new submissions", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user