Skip to content

feat: add room capacity tolerance (10% for lecture rooms), fix teache…#7

Open
iamajaykr06 wants to merge 3 commits intomainfrom
fix/room-capacity-and-summary
Open

feat: add room capacity tolerance (10% for lecture rooms), fix teache…#7
iamajaykr06 wants to merge 3 commits intomainfrom
fix/room-capacity-and-summary

Conversation

@iamajaykr06
Copy link
Copy Markdown
Owner

Description

This PR implements room capacity tolerance for lecture classrooms and fixes the teacher-wise summary API issue.

Changes Made:

  1. Room Capacity Tolerance (10% for Lecture Rooms)

    • Modified can_accommodate() in scheduler_new/models.py
    • Lecture rooms: Allow 10% over-capacity (45-seat room accepts 50 students)
    • Lab rooms: Strict check - no tolerance (can't create extra workstations)
  2. Fix Teacher-wise Summary API

    • Added missing getSummary() method to workloadService
    • Endpoint: GET /workload/summary
    • Now loads teacher workload data in the Summary tab

Why These Changes:

  • Room Capacity: Real universities accept 5-10% over-capacity in lecture halls (extra chairs, shared seating), but labs need strict limits (fixed equipment)
  • Teacher Summary: Frontend was calling a method that didn't exist, causing the summary tab to fail

Fixes # (room capacity mismatch issues)
Fixes # (teacher-wise summary not loading)

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement

Changes Made

List the specific files and changes made:

  • backend/app/scheduler_new/models.py

    • Updated can_accommodate() to apply 10% tolerance only for non-lab rooms
    • Labs use strict capacity check (no tolerance)
  • frontend/src/services/resources.service.ts

    • Added getSummary() method to workloadService
    • Added rebalanceAll() method to workloadService
  • frontend/src/pages/WorkloadPage.tsx

    • Added rebalance button and handler (subsequently removed per user preference)
    • Added summary loading functionality
  • .github/PULL_REQUEST_TEMPLATE.md

    • Updated checklist with more comprehensive items

Testing

Describe the tests you ran to verify your changes:

  • Tested locally (backend + frontend)
  • All existing tests pass
  • Added new tests for new functionality

Test Scenarios:

  1. Room capacity: 50 students in 45-seat lecture room → ✅ Accepted (45 + 10% = 49.5, allows 50)
  2. Room capacity: 50 students in 45-seat lab room → ❌ Rejected (strict check)
  3. Teacher summary: WorkloadPage Summary tab → ✅ Loads teacher workload data correctly

Screenshots (if applicable)

N/A - Backend logic changes

Checklist

  • My code follows the project's code style
  • I have performed a self-review of my code
  • I have commented my code where necessary
  • I have updated the documentation accordingly
  • My changes generate no new warnings
  • I have added tests that prove my fix/feature works

Additional Notes

Room Capacity Logic:

  • Lecture rooms: effective_capacity = capacity * 1.10 → allows 10% over-capacity
  • Lab rooms: effective_capacity = capacity → strict limit, no tolerance

API Changes:

  • New method: workloadService.getSummary() → calls GET /workload/summary
  • Returns: Array of teacher objects with course count, total hours, and assignments

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

AIPCSS Bot Reviewer Report

Status: Issues Found - Action Required


AI Logic Review

null


Backend Report

Issues Found

Bandit Security

[main]	INFO	profile include tests: None
[main]	INFO	profile exclude tests: None
[main]	INFO	cli include tests: None
[main]	INFO	cli exclude tests: None
[main]	INFO	running on Python 3.11.15
[manager]	WARNING	Test in comment: Font is not a test name or id, ignoring
[manager]	WARNING	Test in comment: loading is not a test name or id, ignoring
[manager]	WARNING	Test in comment: failure is not a test name or id, ignoring
[manager]	WARNING	Test in comment: is is not a test name or id, ignoring
[manager]	WARNING	Test in comment: non is not a test name or id, ignoring
[manager]	WARNING	Test in comment: critical is not a test name or id, ignoring
[tester]	WARNING	nosec encountered (B110), but no failed test on file ./backend/app/routes/pdf_export.py:103
[manager]	WARNING	Test in comment: Malformed is not a test name or id, ignoring
[manager]	WARNING	Test in comment: break is not a test name or id, ignoring
[manager]	WARNING	Test in comment: data is not a test name or id, ignoring
[manager]	WARNING	Test in comment: should is not a test name or id, ignoring
[manager]	WARNING	Test in comment: be is not a test name or id, ignoring
[manager]	WARNING	Test in comment: skipped is not a test name or id, ignoring
[tester]	WARNING	nosec encountered (B112), but no failed test on file ./backend/app/scheduler_new/data_loader.py:342
Run started:2026-05-06 18:44:33.370375+00:00

Test results:
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:163:18
162	        for _ in range(max_samples):
163	            opt = random.choice(domain)
164	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:171:29
170	            else:
171	                faculty_id = random.choice(opt["faculties"])
172	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:174:59
173	            samples.append(
174	                DomainValue(faculty_id=faculty_id, room_id=random.choice(opt["rooms"]), timeslot=opt["timeslot"])
175	            )

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:331:65
330	                        fixed[i] = DomainValue(
331	                            faculty_id=assigned_teacher, room_id=random.choice(opt["rooms"]), timeslot=opt["timeslot"]
332	                        )

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:360:26
359	                if valid_opts:
360	                    opt = random.choice(valid_opts)
361	                    individual.append(

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:363:65
362	                        DomainValue(
363	                            faculty_id=assigned_teacher, room_id=random.choice(opt["rooms"]), timeslot=opt["timeslot"]
364	                        )

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:371:22
370	                # First occurrence - randomly select and record teacher
371	                opt = random.choice(domain)
372	                teacher = random.choice(opt["faculties"])

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:372:26
371	                opt = random.choice(domain)
372	                teacher = random.choice(opt["faculties"])
373	                section_course_faculty[sc_key] = teacher

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:375:60
374	                individual.append(
375	                    DomainValue(faculty_id=teacher, room_id=random.choice(opt["rooms"]), timeslot=opt["timeslot"])
376	                )

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:386:16
385	            return list(parent1), list(parent2)
386	        point = random.randint(1, len(self.variables) - 1)
387	        child1 = parent1[:point] + parent2[point:]

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:397:17
396	            return self._crossover_single_point(parent1, parent2)
397	        point1 = random.randint(1, len(self.variables) - 2)
398	        point2 = random.randint(point1 + 1, len(self.variables) - 1)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:398:17
397	        point1 = random.randint(1, len(self.variables) - 2)
398	        point2 = random.randint(point1 + 1, len(self.variables) - 1)
399	        child1 = parent1[:point1] + parent2[point1:point2] + parent1[point2:]

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:410:15
409	        for i in range(len(self.variables)):
410	            if random.random() < 0.5:
411	                child1.append(parent1[i])

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:422:19
421	        """Adaptive crossover: randomly select operator"""
422	        operator = random.choice(["single", "two_point", "uniform"])
423	        if operator == "single":

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:444:15
443	        for i, var in enumerate(self.variables):
444	            if random.random() < self.current_mutation_rate:
445	                sc_key = (var.section_id, var.course_id)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:450:44
449	                if sampled:
450	                    if len(sampled) > 1 and random.random() < 0.5:
451	                        current_val = mutated[i]

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:454:41
453	                        if available:
454	                            mutated[i] = random.choice(available)
455	                    else:

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:456:37
455	                    else:
456	                        mutated[i] = random.choice(sampled)
457	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:724:45
723	                # Apply local search to elite individuals
724	                if self.use_local_search and random.random() < 0.3:
725	                    elite = self._local_search_hill_climbing(elite, self.local_search_intensity // 2)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:731:30
730	                # Tournament selection
731	                tournament1 = random.sample(fitness_scores, min(self.tournament_size, len(fitness_scores)))
732	                tournament2 = random.sample(fitness_scores, min(self.tournament_size, len(fitness_scores)))

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:732:30
731	                tournament1 = random.sample(fitness_scores, min(self.tournament_size, len(fitness_scores)))
732	                tournament2 = random.sample(fitness_scores, min(self.tournament_size, len(fitness_scores)))
733	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:743:19
742	                # Apply repair to offspring
743	                if random.random() < 0.2:
744	                    child1 = self._repair_individual(child1)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/genetic_engine.py:745:19
744	                    child1 = self._repair_individual(child1)
745	                if random.random() < 0.2:
746	                    child2 = self._repair_individual(child2)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/ortools_engine.py:163:46
162	                        for ts_idx in f_slots:
163	                            f_selected.extend(random.sample(f_by_slot[ts_idx], min(len(f_by_slot[ts_idx]), f_per_slot)))
164	                        if len(f_selected) < min_per_faculty:

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/ortools_engine.py:166:46
165	                            rem = [c for c in f_combos if c not in f_selected]
166	                            f_selected.extend(random.sample(rem, min(len(rem), min_per_faculty - len(f_selected))))
167	                        selected.extend(f_selected)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b311-random
   Location: ./backend/app/scheduler_new/ortools_engine.py:170:39
169	                if len(selected) > MAX_COMBINATIONS_PER_CLASS:
170	                    all_combinations = random.sample(selected, MAX_COMBINATIONS_PER_CLASS)
171	                else:

--------------------------------------------------

Code scanned:
	Total lines of code: 6873
	Total lines skipped (#nosec): 0
	Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 26
		Medium: 0
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 0
		Medium: 0
		High: 26
Files skipped (0):

No frontend changes.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot Reviewer: Please fix the issues mentioned in the report.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot Reviewer: Please fix the issues mentioned in the report.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot Reviewer: Please fix the issues mentioned in the report.

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.

1 participant