Skip to content

Commit

Permalink
Tweak in API making each project of implicit cat appear a certain times
Browse files Browse the repository at this point in the history
  • Loading branch information
mmahdigh committed Sep 30, 2024
1 parent 69b4f42 commit b4ab3f5
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 32 deletions.
51 changes: 32 additions & 19 deletions src/flow/flow.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { PrismaService } from 'src/prisma.service';
import {
getPairwiseCombinations,
shuffleArraySeeded,
sortCombinationsByImplicitCategoryAndOccurance,
} from 'src/utils';
import {
Expand Down Expand Up @@ -699,8 +700,6 @@ export class FlowService {
(a.implicitCategory || '').localeCompare(b.implicitCategory || ''),
);

console.log(allProjects.slice(0, 10).map((item) => item.implicitCategory));

const projectStars = allStars.filter(
(item) => !projectCoIs.find((el) => el.projectId === item.projectId),
);
Expand Down Expand Up @@ -751,24 +750,36 @@ export class FlowService {

const allIds = allProjects.map((child) => child.id);

const projectIdOccurencesRanking = this.determineIdRanking(votedIds);

// ascending id rankings (i.e., the last element has been voted the most)
let idRanking: number[] = [];
let idRanking = this.determineIdRanking(votedIds);

for (let i = 0; i < allIds.length; i++) {
const value = allIds[i];
if (!projectIdOccurencesRanking.includes(value)) idRanking.push(value);
if (!(value in idRanking)) idRanking = { ...idRanking, [value]: 0 };
}

idRanking = [...idRanking, ...projectIdOccurencesRanking];
const getProjectOccurances = (id: number) =>
id in idRanking ? idRanking[id] : 0;

// idRanking = [...idRanking, ...projectIdOccurencesRanking];

const combinations = getPairwiseCombinations(allIds);

const implicitCategoryPriorities = Array.from(
new Set(allProjects.map((item) => item.implicitCategory)),
).map((cat, index) => ({ name: cat, priority: index * 2 }));

console.log(shuffleArraySeeded(implicitCategoryPriorities, userId));

const getImplicitCatScore = (cat: string) =>
shuffleArraySeeded(implicitCategoryPriorities, userId).find(
(el) => el.name === cat,
)?.priority || 0;

const sortedCombinations = sortCombinationsByImplicitCategoryAndOccurance(
combinations,
idRanking,
getProjectOccurances,
getProjectImplicitCatById,
getImplicitCatScore,
);

const result = [];
Expand Down Expand Up @@ -1090,7 +1101,7 @@ export class FlowService {

private determineIdRanking = (
ids: number[],
order: 'ASC' | 'DSC' = 'ASC',
// order: 'ASC' | 'DSC' = 'ASC',
) => {
// Function to count the occurrences of an element in an array
const countOccurrences = (arr: number[], val: number) =>
Expand All @@ -1100,17 +1111,19 @@ export class FlowService {
const frequencyMap: Record<number, number> = {};
ids.forEach((i) => (frequencyMap[i] = countOccurrences(ids, i)));

// Create an array of unique elements
const uniqueElements = [...new Set(ids)];
return frequencyMap;

// Sort the unique elements array based on the frequency of each element
uniqueElements.sort((a, b) =>
order === 'ASC'
? frequencyMap[a] - frequencyMap[b]
: frequencyMap[b] - frequencyMap[a],
);
// // Create an array of unique elements
// const uniqueElements = [...new Set(ids)];

// // Sort the unique elements array based on the frequency of each element
// uniqueElements.sort((a, b) =>
// order === 'ASC'
// ? frequencyMap[a] - frequencyMap[b]
// : frequencyMap[b] - frequencyMap[a],
// );

return uniqueElements;
// return uniqueElements;
};

private validateVote = async (
Expand Down
58 changes: 45 additions & 13 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,33 +105,65 @@ export const sortCombinationsByImplicitCategory = (
// and least occurance (same sub-category is the first differentiator though)
export const sortCombinationsByImplicitCategoryAndOccurance = (
combinations: number[][],
order: number[],
getProjectOccurances: (id: number) => number,
getImplicitCat: (id: number) => string,
getImplicitCatScore: (cat: string) => number,
) => {
const getImplicitCatScore = (id1: number, id2: number) =>
getImplicitCat(id1) === getImplicitCat(id2) ? 3 : -3;

const getOccuranceScore = (item: number) =>
order.findIndex((el) => el === item);
const compareImplicitCat = (id1: number, id2: number) =>
getImplicitCat(id1) === getImplicitCat(id2) ? 1 : -1;

const sorted = [...combinations];

sorted.sort((c1, c2) => {
const c1Score =
getImplicitCatScore(c1[0], c1[1]) -
getOccuranceScore(c1[0]) -
getOccuranceScore(c1[1]);
getImplicitCatScore(getImplicitCat(c1[0])) +
getImplicitCatScore(getImplicitCat(c1[1])) +
compareImplicitCat(c1[0], c1[1]) -
getProjectOccurances(c1[0]) -
getProjectOccurances(c1[1]);
const c2Score =
getImplicitCatScore(c2[0], c2[1]) -
getOccuranceScore(c2[0]) -
getOccuranceScore(c2[1]);

getImplicitCatScore(getImplicitCat(c2[0])) +
getImplicitCatScore(getImplicitCat(c2[1])) +
compareImplicitCat(c2[0], c2[1]) -
getProjectOccurances(c2[0]) -
getProjectOccurances(c2[1]);

console.log('score of', c1, '=', c1Score);
console.log('score of', c2, '=', c2Score);
return c2Score - c1Score;
});

return sorted;
};

// Seeded random number generator
class SeededRandom {
private seed: number;

constructor(seed: number) {
this.seed = seed;
}

// Generate a random number between 0 and 1
random(): number {
const x = Math.sin(this.seed++) * 10000;
return x - Math.floor(x);
}
}

// Fisher-Yates shuffle algorithm
export function shuffleArraySeeded<T>(array: T[], seed: number): T[] {
const shuffled = [...array];
const random = new SeededRandom(seed);

for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(random.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}

return shuffled;
}

export const sortProjectId = (
project1Id: number,
project2Id: number,
Expand Down

0 comments on commit b4ab3f5

Please sign in to comment.