update Group model - add grades field, add set grade for group endpoint for coordinator view

This commit is contained in:
dominik24c 2023-01-16 01:12:15 +01:00
parent 527612d63e
commit 191c68acf4
6 changed files with 93 additions and 51 deletions

View File

@ -10,10 +10,11 @@ from ..schemas.groups import (
GroupCreateSchema, GroupCreateSchema,
GroupEditSchema, GroupEditSchema,
GroupQuerySchema, GroupQuerySchema,
GroupSetGradeSchema,
GroupsPaginationSchema, GroupsPaginationSchema,
) )
from ..schemas.students import DetailGroupSchema from ..schemas.students import DetailGroupSchema
from ..utils import attach_points_for_first_and_second_term_to_group_models from ..utils import attach_grade_to_group_models
bp = APIBlueprint("groups", __name__, url_prefix="/groups") bp = APIBlueprint("groups", __name__, url_prefix="/groups")
@ -28,10 +29,8 @@ def list_groups(year_group_id: int, query: dict) -> dict:
groups_query = Group.search_by_name(year_group_id, search_name) groups_query = Group.search_by_name(year_group_id, search_name)
data = paginate_models(page, groups_query, per_page) data = paginate_models(page, groups_query, per_page)
items = data["items"] items = data["items"]
attach_points_for_first_and_second_term_to_group_models(items) attach_grade_to_group_models(items)
return {"groups": items, "max_pages": data["max_pages"]} return {"groups": items, "max_pages": data["max_pages"]}
@ -93,7 +92,7 @@ def detail_group(group_id: int) -> Group:
group = Group.query.filter_by(id=group_id).first() group = Group.query.filter_by(id=group_id).first()
if group is None: if group is None:
abort(404, "Not found group!") abort(404, "Not found group!")
attach_points_for_first_and_second_term_to_group_models([group]) attach_grade_to_group_models([group])
return group return group
@ -146,3 +145,22 @@ def edit_group(group_id: int, data: dict) -> dict:
db.session.commit() db.session.commit()
return {"message": "Group was updated!"} return {"message": "Group was updated!"}
@bp.put("/<int:group_id>/set-grades/")
@bp.input(GroupSetGradeSchema)
@bp.output(MessageSchema)
def set_grade_for_group(group_id: int, data: dict) -> dict:
if not data:
abort(400, "You have passed empty data!")
group_query = Group.query.filter_by(id=group_id)
group = group_query.first()
if group is None:
abort(404, "Not found group!")
group_query.update(data)
db.session.commit()
return {"message": "Grade was updated!"}

View File

@ -28,3 +28,8 @@ class GroupEditSchema(Schema):
class GroupIdSchema(Schema): class GroupIdSchema(Schema):
group_id = fields.Integer(required=True) group_id = fields.Integer(required=True)
class GroupSetGradeSchema(Schema):
grade_for_first_term = fields.Float()
grade_for_second_term = fields.Float()

View File

@ -272,13 +272,10 @@ def grade_in_percentage(term_key: str, term_points: dict) -> str:
def calculate_points_for_both_terms( def calculate_points_for_both_terms(
weights: dict, project_grade_sheets: List[ProjectGradeSheet] weights: dict, project_grade_sheet: ProjectGradeSheet
) -> list: ) -> Tuple[float, float]:
terms = [] if project_grade_sheet is None:
for pgs in project_grade_sheets: return 0.0, 0.0
if pgs is None:
terms.append((0, 0))
continue
first_term_points = { first_term_points = {
"presentation": {"gained_points": 0, "all_points": 0}, "presentation": {"gained_points": 0, "all_points": 0},
"documentation": {"gained_points": 0, "all_points": 0}, "documentation": {"gained_points": 0, "all_points": 0},
@ -289,35 +286,49 @@ def calculate_points_for_both_terms(
second_term_points = copy.deepcopy(first_term_points) second_term_points = copy.deepcopy(first_term_points)
for weight_key, weight_value in weights.items(): for weight_key, weight_value in weights.items():
points = ( points = first_term_points if weight_key.endswith("1") else second_term_points
first_term_points if weight_key.endswith("1") else second_term_points
)
criterion = get_criterion_by_weight_key(weight_key) criterion = get_criterion_by_weight_key(weight_key)
try: try:
attribute_value = getattr(pgs, weight_key) attribute_value = getattr(project_grade_sheet, weight_key)
except AttributeError: except AttributeError:
attribute_value = 0 attribute_value = 0
points[criterion]["gained_points"] += attribute_value / 4 * weight_value points[criterion]["gained_points"] += attribute_value / 4 * weight_value
points[criterion]["all_points"] += weight_value points[criterion]["all_points"] += weight_value
points_1 = round(grade_in_percentage("FIRST_TERM", first_term_points) * 100, 1) points_1 = round(grade_in_percentage("FIRST_TERM", first_term_points) * 100, 1)
points_2 = round( points_2 = round(grade_in_percentage("SECOND_TERM", second_term_points) * 100, 1)
grade_in_percentage("SECOND_TERM", second_term_points) * 100, 1 return points_1, points_2
)
terms.append((points_1, points_2))
return terms
def attach_points_for_first_and_second_term_to_group_models(items: List[Group]) -> None: def attach_points_for_first_and_second_term_to_group(group: Group) -> None:
weights = load_weight_for_project_grade_sheet() weights = load_weight_for_project_grade_sheet()
pgs = [] pgs = group.project_grade_sheet
for g in items: if len(pgs) == 0:
if len(g.project_grade_sheet) == 0: pgs = None
pgs.append(None)
else: else:
pgs.append(g.project_grade_sheet[0]) pgs = pgs[0]
calculated_points = calculate_points_for_both_terms(weights, pgs) points = calculate_points_for_both_terms(weights, pgs)
for group, points in zip(items, calculated_points):
group.points_for_first_term = points[0] group.points_for_first_term = points[0]
group.points_for_second_term = points[1] group.points_for_second_term = points[1]
def get_term_grade(point: float) -> float:
if point >= 91.0:
return 5
if point >= 81.0:
return 4.5
if point >= 71.0:
return 4
if point >= 61.0:
return 3.5
if point >= 51.0:
return 3
return 2
def attach_grade_to_group_models(groups: List[Group]) -> None:
for group in groups:
if group.grade_for_first_term == 0:
group.grade_for_first_term = get_term_grade(group.points_for_first_term)
if group.grade_for_second_term == 0:
group.grade_for_second_term = get_term_grade(group.points_for_second_term)

View File

@ -1,11 +1,14 @@
from flask import abort from flask import abort
from ...coordinator.utils import attach_points_for_first_and_second_term_to_group
from ...dependencies import db from ...dependencies import db
from ...students.models import Group, ProjectGradeSheet from ...students.models import Group, ProjectGradeSheet
from ..models import ProjectSupervisor from ..models import ProjectSupervisor
def update_project_grade_sheet(group_id: int, query: dict, data: dict) -> None: def update_project_grade_sheet(
group_id: int, query: dict, data: dict
) -> ProjectGradeSheet:
project_supervisor_id = query.get("id") project_supervisor_id = query.get("id")
project_supervisor = ProjectSupervisor.query.filter( project_supervisor = ProjectSupervisor.query.filter(
ProjectSupervisor.id == project_supervisor_id ProjectSupervisor.id == project_supervisor_id
@ -28,4 +31,5 @@ def update_project_grade_sheet(group_id: int, query: dict, data: dict) -> None:
abort(404, "Not found project grade sheet!") abort(404, "Not found project grade sheet!")
pgs_query.update(data) pgs_query.update(data)
attach_points_for_first_and_second_term_to_group(group)
db.session.commit() db.session.commit()

View File

@ -40,6 +40,8 @@ class Group(Base):
year_group = db.relationship("YearGroup", backref="groups", lazy="joined") year_group = db.relationship("YearGroup", backref="groups", lazy="joined")
points_for_first_term = db.Column(db.Float, default=0, nullable=False) points_for_first_term = db.Column(db.Float, default=0, nullable=False)
points_for_second_term = db.Column(db.Float, default=0, nullable=False) points_for_second_term = db.Column(db.Float, default=0, nullable=False)
grade_for_first_term = db.Column(db.Float, default=0, nullable=False)
grade_for_second_term = db.Column(db.Float, default=0, nullable=False)
students = db.relationship( students = db.relationship(
"Student", secondary=students_groups, back_populates="groups" "Student", secondary=students_groups, back_populates="groups"
) )

View File

@ -1,15 +1,15 @@
"""empty message """empty message
Revision ID: e0e58661131a Revision ID: 5f2f440d05e2
Revises: Revises:
Create Date: 2023-01-15 23:21:20.996214 Create Date: 2023-01-15 23:52:36.927007
""" """
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op from alembic import op
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = "e0e58661131a" revision = "5f2f440d05e2"
down_revision = None down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None
@ -106,6 +106,8 @@ def upgrade():
sa.Column("year_group_id", sa.Integer(), nullable=True), sa.Column("year_group_id", sa.Integer(), nullable=True),
sa.Column("points_for_first_term", sa.Float(), nullable=False), sa.Column("points_for_first_term", sa.Float(), nullable=False),
sa.Column("points_for_second_term", sa.Float(), nullable=False), sa.Column("points_for_second_term", sa.Float(), nullable=False),
sa.Column("grade_for_first_term", sa.Float(), nullable=False),
sa.Column("grade_for_second_term", sa.Float(), nullable=False),
sa.ForeignKeyConstraint( sa.ForeignKeyConstraint(
["project_supervisor_id"], ["project_supervisor_id"],
["project_supervisors.id"], ["project_supervisors.id"],