Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
calvin-laurenson committed Oct 27, 2023
2 parents dc1bd48 + 520a961 commit 9acb683
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 38 deletions.
1 change: 1 addition & 0 deletions backend/classsync/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class AttendanceEvent(Base):
student: Mapped["Student"] = relationship()
time: Mapped[str] = mapped_column() # TODO: Make datetime
inputType: Mapped[str] = mapped_column()
tardy: Mapped[bool] = mapped_column()


class Timer(Base):
Expand Down
115 changes: 79 additions & 36 deletions backend/classsync/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from fastapi import FastAPI, HTTPException, File
from pydantic import BaseModel
from sqlalchemy import delete, select
from fastapi import FastAPI, File
from classsync.db import (
Student,
Timer,
Expand All @@ -20,9 +18,7 @@
from fastapi.middleware.cors import CORSMiddleware


print("Initiating API")
app = FastAPI()
print("Initiating Models")
model = Models()

app.add_middleware(
Expand Down Expand Up @@ -76,30 +72,26 @@ async def add_timer(timing: int, teacher_id: int):

# Post for image transfer from camera
@app.post("/add_image")
async def add_image(image_file: Annotated[bytes, File()], time: str):
async def add_image(image_file: Annotated[bytes, File()], time: str, tardy: bool):
image = Image.open(BytesIO(image_file))
faces = model.find_faces(image)
with Session(engine) as session:
for face in faces:
student = (
session.query(Student)
.order_by(Student.face_embedding.cosine_distance(face))
.first()
)
entry = AttendanceEvent(student=student, time=time, inputType="image")
student = session.query(Student).order_by(Student.face_embedding.cosine_distance(face)).first()
entry = AttendanceEvent(student=student, time=time, inputType="image", tardy=tardy)
session.add(entry)
session.commit()
return {"error": None, "face count": len(faces)}


@app.post("/add_attendance")
async def add_attendance(student_id, time):
async def add_attendance(student_id: int, time: str, tardy: bool):
with Session(engine) as session:
student_query = session.query(Student).filter(Student.id == student_id)
if len(student_query.all()) != 1:
return {"error": f"student not found for {student_id=}"}
student = student_query[0]
entry = AttendanceEvent(student=student, time=time, inputType="manual")
entry = AttendanceEvent(student=student, time=time, inputType = "manual", tardy=tardy)
session.add(entry)
session.commit()
return {"error": None}
Expand Down Expand Up @@ -143,49 +135,55 @@ async def add_student_to_class(face_img: Annotated[bytes, File()], student_id: i
session.refresh(student)
return {"error": None}

# Delete

# Get section for students, plagiarism, timers
@app.delete("/clear_db")
async def clear_db():
with Session(engine) as session:
session.expunge_all()
session.commit()

# Get

@app.get("/get_plagiarized")
async def get_plagiarized(writing1: str, writing2: str):
return {"error": None, "similarity": float(cosine_similarity(sbert.encode(writing1), sbert.encode(writing2)))}


@app.get("/get_attendance")
async def get_attendance():
@app.get("/get_timers")
async def get_timer():
with Session(engine) as session:
attendance_query = session.query(AttendanceEvent)
return attendance_query.all()
timer_query = session.query(Timer)
return timer_query.all()


@app.get("/get_teachers")
async def get_teachers():
with Session(engine) as session:
teacher_query = session.query(Teacher)
return teacher_query.all()

@app.get("/get_classes")
async def get_periodclasses():
with Session(engine) as session:
periodclass_query = session.query(PeriodClass)
return periodclass_query.all()


@app.get("/get_students")
async def get_student():
with Session(engine) as session:
student_query = session.query(Student)
return student_query.all()


@app.get("/get_timers")
async def get_timer():
with Session(engine) as session:
timer_query = session.query(Timer)
return timer_query.all()
students = student_query.all()
for s in students:
if s.face_embedding:
s.face_embedding = True
return students


@app.get("/get_teachers")
async def get_teachers():
@app.get("/get_attendance")
async def get_attendance():
with Session(engine) as session:
teacher_query = session.query(Teacher)
return teacher_query.all()

attendance_query = session.query(AttendanceEvent)
return attendance_query.all()

@app.get("/get_students_in_class")
async def get_students_in_class(class_id: int):
Expand All @@ -197,10 +195,9 @@ async def get_students_in_class(class_id: int):
return {"error": f"periodclass not found for {class_id=}"}
print("debug: returning students")
students = periodclass_query.all()[0].students
student_ids = [s.id for s in students]
student_ids = [s.name for s in students]
return student_ids


@app.get("/get_student_attendance")
async def get_student_attendance(student_id: int):
with Session(engine) as session:
Expand All @@ -212,6 +209,52 @@ async def get_student_attendance(student_id: int):
)
return attendance_events

@app.get("/get_class_attendance")
async def get_class_attendance(class_id: int, start_time: str):
with Session(engine) as session:
class_query = session.query(PeriodClass)
periodclass = class_query.filter(PeriodClass.id==class_id).all()
if len(periodclass) != 1:
return {"error": f"couldn't find {class_id=}"}
students=periodclass[0].students
student_attendance: dict[int, str] = dict()
attendance_query = session.query(AttendanceEvent).filter(AttendanceEvent.time>=start_time).order_by(AttendanceEvent.time)
for student in students:
attendance = attendance_query.filter(AttendanceEvent.student_id==student.id).first()
if attendance == None:
student_attendance[student.name] = "absent"
elif attendance.tardy:
student_attendance[student.name] = "tardy"
else:
student_attendance[student.name] = "present"
return student_attendance

@app.get("/get_student_id_by_name")
async def get_student_id_by_name(student_name: str):
with Session(engine) as session:
student_query = session.query(Student)
student = student_query.filter(Student.name==student_name).all()
if len(student) != 1:
return {"error": f"didn't find one {student_name=}"}
return {"error": None, "id": student[0].id}

@app.get("/get_student_name_by_id")
async def get_student_name_by_id(student_id: int):
with Session(engine) as session:
student_query = session.query(Student)
student = student_query.filter(Student.id==student_id).all()
if len(student) != 1:
return {"error": f"didn't find one {student_id=}"}
return {"error": None, "id": student[0].name}

@app.get("/get_class_name_by_id")
async def get_class_name_by_id(class_id: str):
with Session(engine) as session:
class_query = session.query(PeriodClass)
periodclasses = class_query.filter(PeriodClass.id==class_id).all()
if len(periodclasses) != 1:
return {"error": f"didn't find one {class_id=}"}
return {"error": None, "id": periodclasses[0].name}

if __name__ == "__main__":
uvicorn.run("main:app", port=8000)
5 changes: 3 additions & 2 deletions backend/classsync/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

class Models:
def __init__(self):
self.detector = scrfd.SCRFD(model_file="./scrfd-10g-kps.onnx")
self.pfc = partial_fc.PartialFC("pfc.onnx")
print("Initiating facial recognition models")
self.detector = scrfd.SCRFD(model_file="./backend/scrfd-10g-kps.onnx")
self.pfc = partial_fc.PartialFC("./backend/pfc.onnx")

def find_faces(self, image: Image.Image):
faces = self.detector.detect(image, 0.6, (640, 640))
Expand Down

0 comments on commit 9acb683

Please sign in to comment.