learnhouse/src/services/activity.py
2023-03-01 00:11:43 +01:00

164 lines
5.8 KiB
Python

from cmath import log
from datetime import datetime
import json
from typing import List, Literal, Optional
from uuid import uuid4
from fastapi import HTTPException, Request, status
from pydantic import BaseModel
from src.services.courses.chapters import get_coursechapters_meta
from src.services.users import PublicUser
#### Classes ####################################################
class Activity(BaseModel):
course_id: str
status: Optional[Literal['ongoing', 'done', 'closed']] = 'ongoing'
masked: Optional[bool] = False
lectures_marked_complete: Optional[List[str]] = []
lectures_data: Optional[List[dict]] = []
class ActivityInDB(Activity):
activity_id: str
user_id: str
org_id: str
creationDate: str = datetime.now().isoformat()
updateDate: str = datetime.now().isoformat()
#### Classes ####################################################
async def create_activity(request: Request, user: PublicUser, activity_object: Activity):
activities = request.app.db["activities"]
# find if the user has already started the course
isActivityAlreadCreated = await activities.find_one(
{"course_id": activity_object.course_id, "user_id": user.user_id})
if isActivityAlreadCreated:
if isActivityAlreadCreated['status'] == 'closed':
activity_object.status = 'ongoing'
await activities.update_one(
{"activity_id": isActivityAlreadCreated['activity_id']}, {"$set": activity_object.dict()})
return activity_object
else:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Activity already created")
# create activity id
activity_id = f"activity_{uuid4()}"
# create activity
activity = ActivityInDB(**activity_object.dict(),activity_id=activity_id,
user_id=user.user_id, org_id=activity_object.course_id)
await activities.insert_one(activity.dict())
return activity
async def get_user_activities(request: Request, user: PublicUser, org_id: str):
activities = request.app.db["activities"]
courses = request.app.db["courses"]
coursechapters = request.app.db["coursechapters"]
activities_metadata = []
user_activities = activities.find(
{"user_id": user.user_id}, {'_id': 0})
if not user_activities:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="No activities found")
for activity in await user_activities.to_list(length=100):
# get number of lectures in the course
coursechapters = await get_coursechapters_meta(request, activity['course_id'], user)
# calculate progression using the number of lectures marked complete and the total number of lectures
progression = round(
len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2)
course = await courses.find_one({"course_id": activity['course_id']}, {'_id': 0})
# add progression to the activity
one_activity = {"course": course, "activitydata": activity, "progression": progression}
activities_metadata.append(one_activity)
return activities_metadata
async def get_user_activities_orgslug(request: Request, user: PublicUser, org_slug: str):
activities = request.app.db["activities"]
courses = request.app.db["courses"]
coursechapters = request.app.db["coursechapters"]
activities_metadata = []
user_activities = activities.find(
{"user_id": user.user_id}, {'_id': 0})
if not user_activities:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="No activities found")
for activity in await user_activities.to_list(length=100):
# get number of lectures in the course
coursechapters = await get_coursechapters_meta(request, activity['course_id'], user)
# calculate progression using the number of lectures marked complete and the total number of lectures
progression = round(
len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2)
course = await courses.find_one({"course_id": activity['course_id']}, {'_id': 0})
# add progression to the activity
one_activity = {"course": course, "activitydata": activity, "progression": progression}
activities_metadata.append(one_activity)
return activities_metadata
async def add_lecture_to_activity(request: Request, user: PublicUser, org_id: str, course_id: str, lecture_id: str):
activities = request.app.db["activities"]
course_id = f"course_{course_id}"
lecture_id = f"lecture_{lecture_id}"
activity = await activities.find_one(
{"course_id": course_id,
"user_id": user.user_id
}, {'_id': 0})
if lecture_id not in activity['lectures_marked_complete']:
activity['lectures_marked_complete'].append(str(lecture_id))
await activities.update_one(
{"activity_id": activity['activity_id']}, {"$set": activity})
return activity
if not activity:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Activity not found")
else:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Lecture already marked complete")
async def close_activity(request: Request, user: PublicUser, activity_id: str, org_id: str,):
activities = request.app.db["activities"]
activity = await activities.find_one(
{"activity_id": activity_id, "user_id": user.user_id})
if not activity:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Activity not found")
activity['status'] = 'closed'
await activities.update_one(
{"activity_id": activity['activity_id']}, {"$set": activity})
activity = ActivityInDB(**activity)
return activity