Skip to content
Open
105 changes: 105 additions & 0 deletions Team116-EduQuest/CourseController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.example.demo.controller;

import com.example.demo.service.CourseSearcher;
import com.example.demo.model.CourseInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.example.demo.service.CourseService;

import java.util.List;

@RestController
@RequestMapping("/api/courses")


public class CourseController {
@Autowired
private CourseService courseService;

@Autowired
private CourseSearcher courseSearcher;



// Endpoint to get all courses
@GetMapping("/all")
public List<CourseInfo> getAllCourses() {
return courseSearcher.getAllCourses();
}

// Endpoint to search courses by name using Trie


// Endpoint to get ranked courses by rating (Ranking)
@GetMapping("/ranked")
public List<CourseInfo> getRankedCourses() {
return courseSearcher.getRankedCourses();
}

// Endpoint to get sorted courses by duration (Sorting)
@GetMapping("/sorted")
public List<CourseInfo> getSortedCoursesByDuration() {
return courseSearcher.getSortedCoursesByDuration();
}

// Endpoint to get courses that have prerequisites
@GetMapping("/prerequisites")
public List<CourseInfo> getCoursesWithPrerequisites() {
return courseSearcher.getCoursesWithPrerequisites();
}

// Endpoint to add prerequisites for a course
@PostMapping("/prerequisite")
public String addPrerequisite(@RequestParam String courseId, @RequestParam String prerequisiteId) {
courseSearcher.addPrerequisite(courseId, prerequisiteId);
return "Prerequisite added!";
}

// Admin Endpoint to add a new course
@PostMapping("/add")
public String addCourse(@RequestBody CourseInfo course) {
boolean success = courseSearcher.addCourse(course);
if(success) {
return "Course added successfully!";
} else {
return "Error adding course!";
}
}

// Admin Endpoint to update an existing course
@PutMapping("/update/{courseId}")
public String updateCourse(@PathVariable String courseId, @RequestBody CourseInfo course) {
boolean success = courseSearcher.updateCourse(courseId, course);
if(success) {
return "Course updated successfully!";
} else {
return "Error updating course!";
}
}

// Admin Endpoint to delete a course
@DeleteMapping("/delete/{courseId}")
public String deleteCourse(@PathVariable String courseId) {
boolean success = courseSearcher.deleteCourse(courseId);
if(success) {
return "Course deleted successfully!";
} else {
return "Error deleting course!";
}
}

// Endpoint to get courses sorted by duration
@GetMapping("/sortedByDuration")
public List<CourseInfo> getCoursegetSortedCoursesByDuration() {
return courseSearcher.getSortedCoursesByDuration();
}

@GetMapping("/search")
public List<CourseInfo> search(
@RequestParam(required = false) String title,
@RequestParam(required = false) String minRating,
@RequestParam(required = false) String maxRating
) {
return courseService.searchAndFilterCourses(title, minRating, maxRating);
}
}
12 changes: 12 additions & 0 deletions Team116-EduQuest/CourseMatchApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // This annotation marks the main entry point of the Spring Boot application
public class CourseMatchApplication {

public static void main(String[] args) {
SpringApplication.run(CourseMatchApplication.class, args); // This starts the Spring Boot application
}
}
290 changes: 290 additions & 0 deletions Team116-EduQuest/CourseSearcher.java

Large diffs are not rendered by default.

129 changes: 129 additions & 0 deletions Team116-EduQuest/CourseService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package com.example.demo.service;

import com.example.demo.model.CourseInfo;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CourseService {

// Fetch courses from the CourseSearcher class

List<CourseInfo> allCourses = getAllCourses();
// Method to search and filter courses

// Method to search and filter courses
public List<CourseInfo> searchAndFilterCourses(String name, String minDuration, String maxDuration) {
List<CourseInfo> filteredCourses = new ArrayList<>();

// If the user provided no filters, return all courses
if ((minDuration == null || minDuration.isEmpty() || Integer.parseInt(minDuration) == 0) &&
(maxDuration == null || maxDuration.isEmpty() || Integer.parseInt(maxDuration) == 0)) {

// If no valid duration filters, just filter by name if given
return searchAndFilterCourses(name);
}

// Filter based on name and duration if provided
for (CourseInfo course : allCourses) {
boolean matches = true;

// Filter by course name if provided
if (name != null && !name.isEmpty() && !course.getCourseName().toLowerCase().contains(name.toLowerCase())) {
matches = false;
}

// If minDuration is provided and valid, filter by duration
if (minDuration != null && !minDuration.isEmpty() && Integer.parseInt(minDuration) > 0) {
try {
int minDur = Integer.parseInt(minDuration);
if (Integer.parseInt(course.getDuration()) < minDur) {
matches = false;
}
} catch (NumberFormatException e) {
matches = false;
}
}

// If maxDuration is provided and valid, filter by duration
if (maxDuration != null && !maxDuration.isEmpty() && Integer.parseInt(maxDuration) > 0) {
try {
int maxDur = Integer.parseInt(maxDuration);
if (Integer.parseInt(course.getDuration()) > maxDur) {
matches = false;
}
} catch (NumberFormatException e) {
matches = false;
}
}

// If the course matches all filters, add it to the result
if (matches) {
filteredCourses.add(course);
}
}

return filteredCourses;
}

// Function to handle searching only by name (overloading)
public List<CourseInfo> searchAndFilterCourses(String name) {
List<CourseInfo> filteredCourses = new ArrayList<>();
for (CourseInfo course : allCourses) {
if (name != null && !name.isEmpty() && course.getCourseName().toLowerCase().contains(name.toLowerCase())) {
filteredCourses.add(course);
}
}
return filteredCourses;
}



private List<CourseInfo> courseList = new ArrayList<>();

// Fetch all courses
public List<CourseInfo> getAllCourses() {
return courseList;
}

// Add a new course
public void addCourse(CourseInfo course) {
courseList.add(course);
}

// Update an existing course
public void updateCourse(CourseInfo updatedCourse) {
for (CourseInfo course : courseList) {
if (course.getCourseId().equals(updatedCourse.getCourseId())) {
course.setCourseName(updatedCourse.getCourseName());
course.setDuration(updatedCourse.getDuration());
course.setCostStatus(updatedCourse.getCostStatus());
course.setLevel(updatedCourse.getLevel());
course.setRating(updatedCourse.getRating());
course.setReview(updatedCourse.getReview());
}
}
}

// Delete a course by ID
public void deleteCourse(String courseId) {
courseList.removeIf(course -> course.getCourseId().equals(courseId));
}

// Rank courses by rating
public List<CourseInfo> getRankedCourses() {
return courseList.stream()
.sorted((course1, course2) -> Double.compare(course2.getRating(), course1.getRating())) // Sort by rating in descending order
.collect(Collectors.toList());
}

// Sort courses by duration
public List<CourseInfo> getCoursesSortedByDuration() {
return courseList.stream()
.sorted((course1, course2) -> Integer.compare(Integer.parseInt(course1.getDuration()), Integer.parseInt(course2.getDuration())))
.collect(Collectors.toList());
}
}
Empty file.
10 changes: 10 additions & 0 deletions Team116-EduQuest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Problem Statement: With the growing demand for continuous learning and skill development, individuals often turn to online courses(MOOKs platforms) to advance their knowledge. However, the sheer volume of available courses makes it difficult to identify the ones that truly align with a learner’s specific needs. Traditional course discovery methods are often generic and lack personalization, resulting in time-consuming searches and courses that may not match the user’s goals, prior experience, available time, or budget.
To address this challenge,we have derived a solution that simplifies the course selection process by providing personalized recommendations. By considering user inputs such as time commitment, financial constraints, current knowledge level, and learning objectives, the platform can help optimize the learning journey and enhance overall user satisfaction.

Data structures & Algorithms used:
1. List : Stores all courses for filtering, searching, and sorting operations.
2. HashMap: Maps each courseId to its corresponding CourseInfo object.
3. Priority queue : Maintains a priority-based ordering of courses by rating (highest to lowest)
4. Regex (Pattern & Matcher) Algorithm: Keyword highlighting

Video link:https://drive.google.com/file/d/1fncFvNRGg9BiybZTaVhQWsYIbZ9OWqzg/view?usp=sharing
21 changes: 21 additions & 0 deletions Team116-EduQuest/UserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.demo.controller;

import com.example.demo.model.User; // Import the User model
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/auth")
public class UserController {

@PostMapping("/login")
public String login(@RequestBody User user) {
// Hardcoded credentials for student and admin (to be replaced with a database later)
if (user.getId().equals("student") && user.getPassword().equals("student123")) {
return "student"; // For student
} else if (user.getId().equals("admin") && user.getPassword().equals("admin123")) {
return "admin"; // For admin
} else {
return "invalid"; // Invalid login credentials
}
}
}
68 changes: 68 additions & 0 deletions Team116-EduQuest/admin_dashboard.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Dashboard</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<div class="dashboard-container">
<header class="header">
<div class="header-logo">
<h1>PathFinder</h1>
</div>
<div class="header-nav">
<button onclick="logout()">Logout</button>
</div>
</header>

<div class="sidebar">
<h3>Welcome Admin</h3>
<button onclick="location.href='/admin/manage-courses.html'">Manage Courses</button>
<button onclick="location.href='/admin/settings.html'">Settings</button>
</div>

<section class="course-section">
<h2>Admin Overview</h2>
<div id="admin-info">Admin-specific information will go here.</div>
</section>
</div>

<script src="/js/script.js"></script>

<script>
window.onload = function() {
const userType = localStorage.getItem('userType');
if (userType !== 'admin') {
window.location.href = 'login.html'; // Redirect to login if the user is not an admin
return;
}

// Additional admin-specific data can be fetched and displayed here, e.g., number of courses
fetchAdminInfo();
};

function fetchAdminInfo() {
// Example: fetch data from your backend to show the number of courses or other info
// You can replace this with actual API calls to get data
fetch('/api/courses/all')
.then(response => response.json())
.then(data => {
document.getElementById('admin-info').innerHTML = `
<p>Total Courses: ${data.length}</p>
<p>More admin-specific data here...</p>
`;
})
.catch(error => {
console.error('Error fetching admin info:', error);
});
}

function logout() {
localStorage.removeItem('userType');
window.location.href = 'login.html'; // Redirect to login on logout
}
</script>
</body>
</html>
Loading