Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions task-1/com.hyfacademy/Main.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.hyfacademy;

import com.hyfacademy.service.PlatformService;

public class Main {
static void main(String[] args) {
System.out.println("Hello World!");
public static void main(String[] args) {
PlatformService platformService = new PlatformService();
platformService.run();
}
}
13 changes: 12 additions & 1 deletion task-1/com.hyfacademy/exception/AlreadyEnrolledException.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
package com.hyfacademy.exception;

public class AlreadyEnrolledException {
public class AlreadyEnrolledException extends EnrolmentException {
private final String studentName;
private final String courseName;

public AlreadyEnrolledException(String studentName, String courseName){
super(String.format("%s is already enrolled in '%s'", studentName, courseName));
this.studentName = studentName;
this.courseName = courseName;
}

public String getStudentName(){return studentName;}
public String getCourseName(){return courseName;}
}
13 changes: 12 additions & 1 deletion task-1/com.hyfacademy/exception/CourseFullException.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
package com.hyfacademy.exception;

public class CourseFullException {
public class CourseFullException extends EnrolmentException{
private final String courseName;
private final int maxCapacity;

public CourseFullException(String courseName, int maxCapacity){
super(String.format("Course '%s' is full (max: %d students)", courseName, maxCapacity));
this.courseName = courseName;
this.maxCapacity = maxCapacity;
}

public String getCourseName(){return courseName;}
public int getMaxCapacity(){return maxCapacity;}
}
5 changes: 4 additions & 1 deletion task-1/com.hyfacademy/exception/EnrolmentException.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
package com.hyfacademy.exception;

public class EnrolmentException {
public class EnrolmentException extends RuntimeException {
public EnrolmentException(String message){
super(message);
}
}
14 changes: 12 additions & 2 deletions task-1/com.hyfacademy/exception/InvalidProgressException.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
package com.hyfacademy.exception;

public class InvalidProgressException {
}
public class InvalidProgressException extends EnrolmentException{
private final int attemptedValue;

public InvalidProgressException(int attemptedValue){
super(String.format("Progress must be between 0 and 100, but received: %d", attemptedValue));
this.attemptedValue = attemptedValue;
}

public int getAttemptedValue(){return attemptedValue;}


}
141 changes: 140 additions & 1 deletion task-1/com.hyfacademy/model/Course.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,143 @@
package com.hyfacademy.model;

public class Course {
import com.hyfacademy.exception.AlreadyEnrolledException;
import com.hyfacademy.exception.CourseFullException;
import com.hyfacademy.exception.EnrolmentException;
import com.hyfacademy.exception.InvalidProgressException;
import com.hyfacademy.service.Enrollable;

public abstract class Course implements Enrollable {
private final String courseName;
private final String courseId;
private final int maxStudents;
private final int[] studentProgress;
private final Student[] enrolledStudent;

private int enrolledCount = 0;
private static int courseCounter = 0;

private static final int BAR_BLOCKS = 10;
public static final int MIN_PROGRESS = 0;
public static final int MAX_PROGRESS = 100;



public Course(String courseName, int maxStudents){
this.courseName = courseName;
this.maxStudents = maxStudents;
this.courseId = generateCourseId();

this.studentProgress = new int[maxStudents];
this.enrolledStudent = new Student[maxStudents];
}

public String getCourseName(){return courseName;}
public int getMaxStudents(){return maxStudents;}
public String getCourseId(){return courseId;}
public int getEnrolledCount(){return enrolledCount;}
public Student[] getEnrolledStudent(){return enrolledStudent;}

public abstract String getCourseType();
public abstract String getScheduleInfo();

@Override
public String toString(){
return String.format("[%s] %s (%s) | Enrolled: %d/%d",
courseId, courseName, getCourseType(), enrolledCount, maxStudents );
}

public void enrol(Student student){
if(isFull()){
throw new CourseFullException(courseName, maxStudents);
}

for(Course c : student.getCourses()){
if(c !=null && c.equals(this)){
throw new AlreadyEnrolledException(student.getName(), courseName);
}
}

student.enrol(this);

enrolledStudent[enrolledCount] = student;
studentProgress[enrolledCount] = 0;

enrolledCount ++;
}

public void updateProgress(Student student, int progress){
if(progress < MIN_PROGRESS || progress > MAX_PROGRESS){
throw new InvalidProgressException(progress);
}

for ( int i = 0; i < enrolledCount; i++){
if(enrolledStudent[i].getUserId().equals(student.getUserId())){
studentProgress[i] = progress;
return;
}
}
throw new EnrolmentException(String.format(
"%s doesn't enroll in course %s", student.getName(), courseName));
}

public int getStudentProgress(Student student) {
for (int i = 0; i < enrolledCount; i++) {
if (enrolledStudent[i].getUserId().equals(student.getUserId())) {
return studentProgress[i];
}
}
throw new EnrolmentException(String.format(
"%s doesn't enroll in course %s", student.getName(), courseName));
}

public boolean isFull(){
return enrolledCount == maxStudents;
}

public String getProgressBar(Student student){
int filledBlocks = (int) Math.round((float) getStudentProgress(student) / BAR_BLOCKS);

StringBuilder bar = new StringBuilder();

for(int i=0; i < BAR_BLOCKS; i++){
if(i < filledBlocks){
bar.append("█");
} else {
bar.append("░");
}
}
return bar.toString();
}

public String studentReportListProgress(){
StringBuilder sb = new StringBuilder();

for (int i=0; i < getEnrolledCount(); i++){
Student s = getEnrolledStudent()[i];
int progress = getStudentProgress(s);

sb.append(String.format(" %-6s %-13s %3d%% %s%n",
s.getUserId(), s.getName(), progress, getProgressBar(s)));
}

return sb.toString();
}

public double getAverageCourseProgress(){
int totalStudentsProgress = 0;

if (getEnrolledCount() == 0) return 0;

Student[] students = getEnrolledStudent();
for(int i=0; i < getEnrolledCount(); i++){
totalStudentsProgress += getStudentProgress(students[i]);
}

return (double) totalStudentsProgress / getEnrolledCount();
}

public static String generateCourseId(){
courseCounter ++;
return String.format("CRS-%03d", courseCounter);
};
}
57 changes: 56 additions & 1 deletion task-1/com.hyfacademy/model/LiveCohortCourse.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,59 @@
package com.hyfacademy.model;

public class LiveCohortCourse {
import com.hyfacademy.service.Reportable;

public class LiveCohortCourse extends Course implements Reportable {
private final String startDate;
private final String endDate;
private Mentor mentor;

public LiveCohortCourse(String courseName, int maxStudents, String startDate, String endDate){
super(courseName, maxStudents);
this.startDate = startDate;
this.endDate = endDate;
}

public String getStartDate(){return startDate;}
public String getEndDate(){return endDate;}
public Mentor getMentor(){return mentor;}

@Override
public String getCourseType() {
return "Live Cohort";
}

@Override
public String getScheduleInfo(){
return String.format("%s to %s | Mentor: %s",
startDate, endDate, mentor != null? mentor.getName() : "TBA");
}

public void assignMentor(Mentor mentor){
this.mentor = mentor;
mentor.assignToCourse(this);
}

@Override
public String generateReport() {
StringBuilder sb = new StringBuilder();

sb.append("══════════════════════════════════════════\n");
sb.append(" COURSE REPORT — Live Cohort\n");
sb.append("══════════════════════════════════════════\n");
sb.append(String.format(" %-12s : %s%n", "ID", getCourseId()));
sb.append(String.format(" %-12s : %s%n", "Name", getCourseName()));
sb.append(String.format(" %-12s : %s to %s%n", "Schedule", startDate, endDate));
sb.append(String.format(" %-12s : %s%n", "Mentor", mentor != null? mentor.getName() : "TBA" ));
sb.append(String.format(" %-12s : %s%n", "Capacity", capacityStatus()));
sb.append("──────────────────────────────────────────\n");
sb.append(" STUDENT PROGRESS\n");
sb.append("──────────────────────────────────────────\n");
sb.append(studentReportListProgress());
sb.append("──────────────────────────────────────────\n");
sb.append(String.format(" %-10s : %.0f%%%n", "Avg Progress", getAverageCourseProgress()));
sb.append("══════════════════════════════════════════\n");

return sb.toString();
}

}
44 changes: 43 additions & 1 deletion task-1/com.hyfacademy/model/Mentor.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,46 @@
package com.hyfacademy.model;

public class Mentor {
import com.hyfacademy.exception.EnrolmentException;

public class Mentor extends User {
private static final int MAX_ASSIGNED_COURSES = 3;
private final String expertise;
private final Course[] assignedCourses = new Course[MAX_ASSIGNED_COURSES];

private int courseCounter = 0;
private static int mentorCounter = 0;

public Mentor(String name, String email, String expertise){
super(name, email, generateMentorId());
this.expertise = expertise;
}

public String getExpertise(){return expertise;}
public Course[] getAssignedCourses(){return assignedCourses;}

@Override
public String getRole(){return "MENTOR";}

public void assignToCourse(Course course){
if(courseCounter == MAX_ASSIGNED_COURSES){
throw new EnrolmentException(
String.format("Mentor %s cannot be assigned to more than 3 courses", getName())
);
}

for(Course c : assignedCourses){
if(c!=null && c.equals(course)){
throw new EnrolmentException(
String.format("Mentor %s has already been assigned to %s course", getName(), course.getCourseName()));
}
}

assignedCourses[courseCounter] = course;
courseCounter++;
}

public static String generateMentorId(){
mentorCounter ++;
return String.format("COA-%03d", mentorCounter);
}
}
45 changes: 44 additions & 1 deletion task-1/com.hyfacademy/model/SelfPacedCourse.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,47 @@
package com.hyfacademy.model;

public class SelfPacedCourse {
import com.hyfacademy.service.Reportable;

public class SelfPacedCourse extends Course implements Reportable {
private final int estimatedHours;

public SelfPacedCourse(String courseName, int maxStudents, int estimateHours){
super(courseName, maxStudents);
this.estimatedHours = estimateHours;
}

public int getEstimateHours(){return estimatedHours;}

@Override
public String getCourseType(){
return "Self-Paced";
};

@Override
public String getScheduleInfo(){
return String.format("Estimated: %d hours — complete at your own pace", estimatedHours);
};

@Override
public String generateReport() {
StringBuilder sb = new StringBuilder();

sb.append("══════════════════════════════════════════\n");
sb.append(" COURSE REPORT — Self-Paced\n");
sb.append("══════════════════════════════════════════\n");
sb.append(String.format(" %-12s : %s%n", "ID", getCourseId()));
sb.append(String.format(" %-12s : %s%n", "Name", getCourseName()));
sb.append(String.format(" %-12s : %s%n", "Capacity", capacityStatus()));
sb.append(String.format(" %-12s : %s%n", "Est. Hours", estimatedHours));
sb.append("──────────────────────────────────────────\n");
sb.append(" STUDENT PROGRESS\n");
sb.append("──────────────────────────────────────────\n");
sb.append(studentReportListProgress());
sb.append("──────────────────────────────────────────\n");

sb.append(String.format(" %-10s : %.2f%%%n", "Avg Progress", getAverageCourseProgress()));
sb.append("══════════════════════════════════════════\n");

return sb.toString();
}
}
Loading