"use client"; import React, { useState, useEffect } from 'react'; //import top_tags from "@/data/top_tags.json"; import positions from "@/data/positions.json"; import server_matrix from "@/data/server_matrix.json"; import server_names from "@/data/server_names.json"; import tag_names from "@/data/tag_names.json"; interface Tag { index: number; tag: string; } // Read from data/top_tags.json FILE //const tags: Tag[] = const selected_tags = [ "politics", "gardening", "art", "nature", "pride", "cycling", "climate", "programming", "dogs", "privacy", "cats", "gaming", "education", "science", "music", "movies", "food", "books", "lgbtq", "python", "emacs", "gay", "trans", "furry", "photography", "cooking", "literature", "television" ]; function dotProduct(a: number[], b: number[]): number { return a.map((x, i) => x * b[i]).reduce((sum, current) => sum + current, 0); } function magnitude(arr: number[]): number { return Math.sqrt(arr.map(x => x * x).reduce((sum, current) => sum + current, 0)); } function cosineSimilarity(arr1: number[], arr2: number[]): number { if (arr1.length !== arr2.length) { throw new Error("Arrays must have the same length"); } const dotProd = dotProduct(arr1, arr2); const magnitudeProd = magnitude(arr1) * magnitude(arr2); if (magnitudeProd === 0) { return 0; } return dotProd / magnitudeProd; } function averageOfArrays(arr: number[][]): number[] { // Get the length of the first sub-array const length = arr[0].length; // Initialize an array to store the sums const sums = Array(length).fill(0); // Loop over each sub-array for (let i = 0; i < arr.length; i++) { // Loop over each element in the sub-array for (let j = 0; j < arr[i].length; j++) { // Add the element to the corresponding sum sums[j] += arr[i][j]; } } // Divide each sum by the number of arrays to get the average const averages = sums.map(sum => sum / arr.length); return averages; } const TagSelector: React.FC = () => { //const top_tags: Tag[] = []; const all_tags: Tag[] = tag_names.map((tag: string, index: number) => ({index, tag})) const tags: Tag[] = all_tags.filter((tag: Tag) => selected_tags.includes(tag.tag)); //top_tags.filter((tag) => selected_tags.includes(tag.tag)); // State to keep track of selected tag IDs. const [selectedTagIds, setSelectedTagIds] = useState([]); const [suggestedTagIds, setSuggestedTagIds] = useState([]); const [topServerIds, setTopServerIds] = useState([]); // Function to handle tag selection toggling. const toggleTag = (tagId: number) => { setSelectedTagIds((currentTagIds) => currentTagIds.includes(tagId) ? currentTagIds.filter((id) => id !== tagId) : [...currentTagIds, tagId], ) }; function find_most_similar_tags(all_tags: Tag[], selectedTagIds: number[], positions: number[][]) { let most_similar: Tag[] = []; // get the average position of all selected tags if (selectedTagIds.length > 0) { // loop through all selected tags and get their positions const selected_positions = selectedTagIds.map((tagId) => positions[tagId]); for (let i = 0; i < selected_positions.length; i++) { let tag_similarity = positions.map((row) => cosineSimilarity(selected_positions[i], row)); let tag_rank = tag_similarity.map((similarity, index) => ({index, similarity})).sort((a, b) => b.similarity - a.similarity).map((item, index) => ({index: item.index, similarity: item.similarity, name: tag_names[item.index]})); console.log(tag_rank.slice(0, 10)); let topServerIds = tag_rank.slice(0, 10).map((item) => item.index); for (let tagId of all_tags.filter((tag) => topServerIds.includes(tag.index))) { if (!selectedTagIds.includes(tagId.index) && !most_similar.includes(tagId)) { most_similar.push(tagId); } } } } return most_similar; } useEffect(() => { // get the average position of all selected tags if (selectedTagIds.length > 0) { let selected_positions = selectedTagIds.map((tagId) => positions[tagId]); // get the average of selected positions let average_position = averageOfArrays(selected_positions); // loop through each row of the server_matrix and calculate the cosine similarity const server_similarity = server_matrix.map((row) => cosineSimilarity(average_position, row)); const server_rank = server_similarity.map((similarity, index) => ({index, similarity})).sort((a, b) => b.similarity - a.similarity).map((item, index) => ({index: item.index, similarity: item.similarity, name: server_names[item.index]})); setTopServerIds(server_rank.slice(0, 10).map((item) => item.index)); // Find the most similar tags among all tags const tag_similarity = all_tags.map((tag) => ({t: tag, sim: cosineSimilarity(average_position, positions[tag.index])})).sort((a, b) => b.sim - a.sim); const most_similar = find_most_similar_tags(all_tags, selectedTagIds, positions); //tag_similarity.slice(0, 50).map((item) => item.t); console.log(most_similar); setSuggestedTagIds(most_similar.map((tag) => tag.index)); console.log(suggestedTagIds); } }, [selectedTagIds]); return (

Selected

{all_tags.filter((tag) => selectedTagIds.includes(tag.index)).map((tag) => ( ))}

Categories

{tags.filter((tag) => !selectedTagIds.includes(tag.index)).map((tag) => ( ))}

Suggested Tags ({suggestedTagIds.filter((tag) => !selectedTagIds.includes(tag)).length})

{all_tags.filter((tag) => suggestedTagIds.includes(tag.index)).filter((tag) => !selectedTagIds.includes(tag.index)).map((tag) => ( ))}
    {topServerIds.map((id) => (
  • {server_names[id]}
  • ))}
); }; export default function Home() { return (
); }