Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

My Search Feature #34

Merged
merged 18 commits into from
May 2, 2024
Merged

My Search Feature #34

merged 18 commits into from
May 2, 2024

Conversation

DasMoge124
Copy link
Collaborator

@DasMoge124 DasMoge124 commented Apr 18, 2024

My Feature Overall

  • What this project essentially does is that it can display all students on this website and it searches for the most relevant student. Here is a demo for the display function:
    image
    Here is the display for searching for most students:
  • What I input:
    image
  • The output:
    image

Adding a New Student

Input:

image

Output:

image

Frontend Code:

---
layout: default
title: Student Search
hide: true
permalink: /search/
---
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Student Selection</title>
    <!-- Include jQuery -->
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }

        h1, h2 {
            margin-bottom: 10px;
        }

        form {
            margin-bottom: 20px;
        }

        label {
            display: inline-block;
            width: 150px;
            margin-bottom: 5px;
        }

        input[type="text"], input[type="number"] {
            width: 300px;
            padding: 5px;
        }

        button {
            padding: 8px 15px;
            cursor: pointer;
        }

        #studentList {
            margin-top: 10px;
            list-style-type: none;
            padding-left: 0;
        }

        #studentList li {
            margin-bottom: 5px;
        }
    </style>
</head>
<body>
    <h1>Student Selection</h1>
    <h2>Add New Student</h2>
    <form id="addStudentForm">
        <label for="name">Name:</label>
        <input type="text" id="name" name="name" required><br><br>
        <label for="subjects">Subjects Known (comma-separated):</label>
        <input type="text" id="subjects" name="subjects" required><br><br>
        <label for="location">Preferred Location:</label>
        <input type="text" id="location" name="location" required><br><br>
        <label for="internship">Internship Preferred:</label>
        <input type="checkbox" id="internship" name="internship"><br><br>
        <button type="button" onclick="addStudent()">Add Student</button>
    </form>
    <h2>Find Most Relevant Student</h2>
    <form id="findMostRelevantStudentForm">
        <label for="newStudentName">Name:</label>
        <input type="text" id="newStudentName" required><br><br>
        <label for="newStudentSubjects">Subjects Known (comma-separated):</label>
        <input type="text" id="newStudentSubjects" required><br><br>
        <label for="newStudentLocation">Preferred Location:</label>
        <input type="text" id="newStudentLocation" required><br><br>
        <label for="newStudentInternship">Internship Preferred:</label>
        <input type="checkbox" id="newStudentInternship"><br><br>
        <button type="button" onclick="findMostRelevantStudent()">Find Most Relevant Student</button>
    </form>
    <h2>Display All Students</h2>
    <button type="button" onclick="getAllStudents()">Get All Students</button>
    <ul id="studentList"></ul>
    <div id="result"></div>

    <script>
        // Function to add a new student
        function addStudent() {
            const studentData = {
                name: $('#name').val(),
                subjectsKnown: $('#subjects').val().split(',').map(subject => subject.trim()),
                preferredLocation: $('#location').val(),
                internshipPreferred: $('#internship').is(':checked')
            };

            fetch('http://localhost:8911/api/student/add', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(studentData),
            })
            .then(response => response.text())
            .then(message => alert(message))
            .catch(error => console.error('Error:', error));
        }

        // Function to find the most relevant student
        function findMostRelevantStudent() {
            const newStudentData = {
                name: $('#newStudentName').val(),
                subjectsKnown: $('#newStudentSubjects').val().split(',').map(subject => subject.trim()),
                preferredLocation: $('#newStudentLocation').val(),
                internshipPreferred: $('#newStudentInternship').is(':checked')
            };

            fetch('http://localhost:8911/api/student/findMostRelevant?k=3', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(newStudentData),
            })
            .then(response => response.json())
            .then(data => {
                $('#result').text(`Most relevant student: ${data.name}`);
            })
            .catch(error => {
                console.error('Error:', error);
                $('#result').text('Error finding the most relevant student.');
            });
        }

        // Function to fetch all students and display them
        function getAllStudents() {
            fetch('http://localhost:8911/api/student/allStudents')
            .then(response => {
                if (!response.ok) {
                    throw new Error('Network response was not ok');
                }
                return response.json();
            })
            .then(data => {
                const studentList = $('#studentList');
                // Clear previous list items if any
                studentList.empty();
                data.forEach(student => {
                    studentList.append(`<li>Name: ${student.name}, Subjects: ${student.subjectsKnown.join(', ')}, Location: ${student.preferredLocation}</li>`);
                });
            })
            .catch(error => {
                console.error('Error fetching students:', error);
                alert('Error fetching students. Please try again.');
            });
        }
    </script>
</body>
</html>

Backend Code

package com.nighthawk.spring_portfolio.mvc.search;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class KNNStudentSelection {

    // KNN algorithm for student selection
    public static Student findMostRelevantStudent(List<Student> students, Student newStudent, int k) {
        Map<Double, Student> distanceMap = new HashMap<>();

        // Calculate Euclidean distance for each student
        for (Student student : students) {
            double distance = calculateDistance(student, newStudent);
            distanceMap.put(distance, student);
        }

        // Sort distances and get the top k neighbors
        List<Double> distances = new ArrayList<>(distanceMap.keySet());
        Collections.sort(distances);

        // Return the most relevant student
        return distanceMap.get(distances.get(0));
    }

    private static double calculateDistance(Student student1, Student student2) {
        // Simple distance calculation based on preferences
        double subjectDistance = calculateSubjectDistance(student1.getSubjectsKnown(), student2.getSubjectsKnown());
        double locationDistance = student1.getPreferredLocation().equals(student2.getPreferredLocation()) ? 0 : 1;

        // Euclidean distance
        return Math.sqrt(Math.pow(subjectDistance, 2) + Math.pow(locationDistance, 2));
    }

    private static double calculateSubjectDistance(List<String> subjects1, List<String> subjects2) {
        // Jaccard similarity for subject distance
        List<String> union = new ArrayList<>(subjects1);
        union.addAll(subjects2);

        List<String> intersection = new ArrayList<>(subjects1);
        intersection.retainAll(subjects2);

        return 1 - ((double) intersection.size() / union.size());
    }
}

Student

package com.nighthawk.spring_portfolio.mvc.search;

import java.util.List;

public class Student {
    private String name;
    private List<String> subjectsKnown;
    private String preferredLocation;
    private boolean internshipPreferred;

    // Constructors (including a no-arg constructor)

    public Student() {
    }

    public Student(String name, List<String> subjectsKnown, String preferredLocation,
            boolean internshipPreferred) {
        this.name = name;
        this.subjectsKnown = subjectsKnown;
        this.preferredLocation = preferredLocation;
        this.internshipPreferred = internshipPreferred;
    }

    // Getters and Setters

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<String> getSubjectsKnown() {
        return subjectsKnown;
    }

    public void setSubjectsKnown(List<String> subjectsKnown) {
        this.subjectsKnown = subjectsKnown;
    }

    public String getPreferredLocation() {
        return preferredLocation;
    }

    public void setPreferredLocation(String preferredLocation) {
        this.preferredLocation = preferredLocation;
    }

    public boolean isInternshipPreferred() {
        return internshipPreferred;
    }

    public void setInternshipPreferred(boolean internshipPreferred) {
        this.internshipPreferred = internshipPreferred;
    }
}

Student Controller

package com.nighthawk.spring_portfolio.mvc.search;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/student")
@CrossOrigin(origins = "https://rik-csa.github.io/")
public class StudentController {

    private List<Student> students = new ArrayList<>();

    public StudentController() {
        // Initialize your student list
    }

    @PostMapping("/add")
    public ResponseEntity<String> addStudent(@RequestBody Student newStudent) {
        students.add(newStudent);
        return ResponseEntity.ok("Student added successfully");
    }

    @PostMapping("/findMostRelevant")
    public ResponseEntity<Student> findMostRelevantStudent(@RequestBody Student newStudent,
            @RequestParam int k) {
        Student mostRelevantStudent = KNNStudentSelection.findMostRelevantStudent(students, newStudent, k);
        return ResponseEntity.ok(mostRelevantStudent);
    }

    @GetMapping("/allStudents")
    public ResponseEntity<List<Student>> getAllStudents() {
        return ResponseEntity.ok(students);
    }
}```

@DasMoge124 DasMoge124 merged commit 2933fac into search_feature May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants