Skip to content

Commit

Permalink
AC-2 essential changes (#1640)
Browse files Browse the repository at this point in the history
* Implemented suggested changes in AC-2
- Important Validations
- Random elective allocation algo implementation in utils
- New page for starting allocation process

* migrations for previous changes

* field changes in random allocation algo and start allocation form

* Implemented the preregistration algorithm

* Added allocated course viewing page
- fixed bugs in algo

* Restricted scope of the algo to only Open electives

---------

Co-authored-by: ChallaBharadwajReddy <[email protected]>
  • Loading branch information
ramG-reddy and ChallaBharadwajReddy authored Oct 24, 2024
1 parent 0c55dfc commit 0e6b1f0
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 6 deletions.
135 changes: 135 additions & 0 deletions FusionIIIT/applications/academic_information/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
from applications.academic_information.models import (Calendar, Student,Curriculum_Instructor, Curriculum,
Student_attendance)
from ..academic_procedures.models import (BranchChange, CoursesMtech, InitialRegistration, StudentRegistrationChecks,
Register, Thesis, FinalRegistration, ThesisTopicProcess,
Constants, FeePayments, TeachingCreditRegistration, SemesterMarks,
MarkSubmissionCheck, Dues,AssistantshipClaim, MTechGraduateSeminarReport,
PhDProgressExamination,CourseRequested, course_registration, MessDue, Assistantship_status , backlog_course,)

from applications.programme_curriculum.models import(Course,CourseSlot,Batch,Semester)
from django.http import HttpResponse, JsonResponse
from django.utils import timezone
from django.core import serializers
from django.db.models import Q
import datetime
import random
from django.db import transaction
time = timezone.now()
def check_for_registration_complete (request):
batch = int(request.POST.get('batch'))
sem = int(request.POST.get('sem'))
year = request.POST.get('year')


date = time.date()

try:

pre_registration_date = Calendar.objects.all().filter(description=f"Pre Registration {sem} {year}").first()
prd_start_date = pre_registration_date.from_date
prd_end_date = pre_registration_date.to_date

if date<prd_start_date :
return JsonResponse({'status':-2 , 'message': "registration didn't start"})
if date>=prd_start_date and date<=prd_end_date:
return JsonResponse({'status':-1 , "message":"registration is under process"})

if course_registration.objects.filter(Q(semester_id__semester_no = sem) & Q(student_id__batch = batch)).exists() :
return JsonResponse({'status':2,"message":"courses already allocated"})

return JsonResponse({"status":1 , "message" : "courses not yet allocated"})
except :
return JsonResponse({"status":-3, "message" : "No such registration found"})

@transaction.atomic
def random_algo(batch,sem,year,course_slot) :
unique_course = InitialRegistration.objects.filter(Q(semester_id__semester_no = sem) & Q( course_slot_id__name = course_slot ) & Q(student_id__batch = batch)).values_list('course_id',flat=True).distinct()
max_seats={}
seats_alloted = {}
present_priority = {}
next_priority = {}
total_seats = 0
for course in unique_course :
max_seats[course] = Course.objects.get(id=course).max_seats
total_seats+=max_seats[course]
seats_alloted[course] = 0
present_priority[course] = []
next_priority[course] = []

priority_1 = InitialRegistration.objects.filter(Q(semester_id__semester_no = sem) & Q( course_slot_id__name = course_slot ) & Q(student_id__batch = batch) & Q(priority=1))
rem=len(priority_1)
if rem > total_seats :
return -1

for p in priority_1 :
present_priority[p.course_id.id].append([p.student_id.id.id,p.course_slot_id.id])
with transaction.atomic() :
p_priority = 1
while rem > 0 :
for course in present_priority :
while(len(present_priority[course])) :
random_student_selected = random.choice(present_priority[course])

present_priority[course].remove(random_student_selected)

if seats_alloted[course] < max_seats[course] :
stud = Student.objects.get(id__id = random_student_selected[0])
curriculum_object = Student.objects.get(id__id = random_student_selected[0]).batch_id.curriculum
course_object = Course.objects.get(id=course)
course_slot_object = CourseSlot.objects.get(id = random_student_selected[1])
semester_object = Semester.objects.get(Q(semester_no = sem) & Q(curriculum = curriculum_object))
course_registration.objects.create(
student_id = stud,
working_year = year,
semester_id = semester_object,
course_id = course_object,
course_slot_id = course_slot_object
)
seats_alloted[course] += 1
rem-=1
else :
next = InitialRegistration.objects.get(Q(student_id__id__id = random_student_selected[0]) & Q( course_slot_id__name = course_slot ) & Q(semester_id__semester_no = sem) & Q(student_id__batch = batch) & Q(priority=p_priority+1))
next_priority[next.course_id.id].append([next.student_id.id.id,next.course_slot_id.id])
p_priority+=1
present_priority = next_priority
next_priority = {course : [] for course in unique_course}

return 1

@transaction.atomic
def allocate(request) :
batch = request.POST.get('batch')
sem = request.POST.get('sem')
year = request.POST.get('year')
unique_course_slot = InitialRegistration.objects.filter(Q(semester_id__semester_no = sem) & Q(student_id__batch = batch)).values_list('course_slot_id',flat=True).distinct()
unique_course_name = []
try:
with transaction.atomic() :
for course_slot in unique_course_slot :
course_slot_object = CourseSlot.objects.get(id=course_slot)
if course_slot_object.type == "Professional Elective": # Runs only for open elective course slots
if course_slot_object.name not in unique_course_name:
stat = random_algo(batch,sem,year,course_slot_object.name)
unique_course_name.append(course_slot_object.name)
if(stat == -1) :
raise Exception("seats not enough for course_slot"+str(course_slot_object.name))

return JsonResponse({'status': 1 , 'message' : "course allocation successful"})
except:
return JsonResponse({'status': -1 , 'message' : "seats not enough for course_slot"+str(course_slot_object.name) })


def view_alloted_course(request) :
batch = request.POST.get('batch')
sem = request.POST.get('sem')
year = request.POST.get('year')
course = request.POST.get('course')

registrations = course_registration.objects.filter(Q(student_id__batch = batch) & Q(working_year = year) & Q(semester_id__semester_no = sem) & Q(course_id__code = course))
return_list = []
for registration in registrations:
obj = {
'student':registration.student_id.id.id
}
return_list.append(obj)
return JsonResponse({'status':1 , 'student_list':return_list })
10 changes: 9 additions & 1 deletion FusionIIIT/applications/academic_information/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from applications.academic_procedures.views import acad_proced_global_context , get_sem_courses
from applications.programme_curriculum.models import Batch
from django.db.models import Q
from .utils import check_for_registration_complete,allocate,view_alloted_course


@login_required
Expand Down Expand Up @@ -214,7 +215,14 @@ def homepage(request):
"""
if user_check(request):
return HttpResponseRedirect('/academic-procedures/')


if request.method == "POST":
if 'check_allocation' in request.POST :
return check_for_registration_complete(request)
if 'start_allocation' in request.POST :
return allocate(request)
if 'view_allocation' in request.POST :
return view_alloted_course(request)
context = get_context(request)

return render(request, "ais/ais.html", context)
Expand Down
4 changes: 1 addition & 3 deletions FusionIIIT/applications/academic_procedures/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,8 +605,7 @@ class InitialRegistration(models.Model):

class Meta:
db_table = 'InitialRegistration'



class FinalRegistration(models.Model):
'''
Current Purpose : stores information regarding the process of final(complete) registration of a student for a course
Expand Down Expand Up @@ -690,7 +689,6 @@ def __str__(self):
class Meta:
db_table = 'course_registration'


class backlog_course(models.Model):
'''
Current Purpose : stores information regarding the backlog courses of a student (purpose is unclear and is open to interpretations)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.1.5 on 2024-10-23 00:20

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('programme_curriculum', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='course',
name='max_seats',
field=models.IntegerField(default=90),
),
]
2 changes: 1 addition & 1 deletion FusionIIIT/applications/programme_curriculum/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ class Course(models.Model):
working_course = models.BooleanField(default=True)
disciplines = models.ManyToManyField(Discipline, blank=True)
latest_version = models.BooleanField(default=True)

max_seats = models.IntegerField(default=90)
class Meta:
unique_together = ('code', 'version')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@
</table>
<div class="extra content">
<div class="" style="text-align: center;">
<button class="ui primary button">Register</button>
<button id="register-button" class="ui primary button">Register</button>
</div>
</div>
</form>
Expand Down Expand Up @@ -291,6 +291,8 @@
var inp = document.getElementsByClassName("Prechoices");
var count = 0;

document.getElementById('register-button').style.display = 'none';

let course_slots = document.getElementsByName("course_slot");
let credits = document.getElementsByClassName("credit_values");

Expand All @@ -303,6 +305,7 @@
// // console.log("course_priority-" + course_slot_id , course_priority[j].value )
if ((!(course_slot_type.startsWith("Optional") && course_slot_type != "Optional Elective") && !course_slot_type.startsWith("Swayam") )&& course_priority[j].value == "NULL") {
alert("Please select all choices for " + parseInt(i + 1) + " " + course_slot_type + " slot");
document.getElementById('register-button').style = "text-allign:center;";
return false;
}
let selected_course = course_priority[j].value.split("-");
Expand Down
10 changes: 10 additions & 0 deletions FusionIIIT/templates/ais/ais.html
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@
Student Dashboard
<i class="right floated chevron right icon"></i>
</a>
<a class="item" data-tab="start-elective">
Start elective assignment
<i class="right floated chevron right icon"></i>
</a>

<!-- <a class="item" disabled="disabled" href="/aims">
Manage Student Profile
Expand Down Expand Up @@ -225,6 +229,12 @@
{% include 'ais/student_dashboard.html' %}
{% endblock %}
</div>

<div class="ui tab segment" data-tab="start-elective">
{% block start_elective_allocation %}
{% include 'ais/start_elective_allocation.html' %}
{% endblock %}
</div>

<div class="ui tab segment" data-tab="allot_swayam">
{% block allot_swayam %}
Expand Down
Loading

0 comments on commit 0e6b1f0

Please sign in to comment.