Spaces:
Running
Running
added a fix to leaderboard
Browse files- app.py +58 -18
- gamification/objects.py +3 -3
- gamification/pointLogic.py +14 -8
- gamification/routes.py +7 -3
app.py
CHANGED
@@ -23,7 +23,8 @@ from pydantic import BaseModel
|
|
23 |
from datetime import datetime
|
24 |
from bson import ObjectId
|
25 |
import os
|
26 |
-
|
|
|
27 |
|
28 |
|
29 |
load_dotenv()
|
@@ -439,6 +440,7 @@ def create_leaderboard_ranking( document: LeaderBoardRanking) -> bool:
|
|
439 |
collection = db['LeaderBoard']
|
440 |
# Insert the document
|
441 |
result= collection.find_one_and_replace(filter={"userId":document.userId},replacement=document.model_dump())
|
|
|
442 |
if result==None:
|
443 |
result = collection.insert_one(document.model_dump())
|
444 |
print("correctly inserted new document for",document.firstName)
|
@@ -484,6 +486,52 @@ def get_user_id_from_docKey(dockId):
|
|
484 |
client = MongoClient(MONGO_URI)
|
485 |
db = client.crayonics
|
486 |
collection = db['Points']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
|
488 |
# A function to handle changes
|
489 |
def handle_change(change=None,new_point=None):
|
@@ -494,23 +542,15 @@ def handle_change(change=None,new_point=None):
|
|
494 |
if new_point!=None:
|
495 |
collections = db.list_collection_names()
|
496 |
logger.info(f"Extra info: {new_point}")
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
tempDreamJob = get_dream_job(userId=str(user['_id']))
|
504 |
-
dreamJob = tempDreamJob if type(tempDreamJob)==str else "IncompleteProfile"
|
505 |
-
create_leaderboard_ranking(LeaderBoardRanking(userId=str(user['_id']),firstName=user['first_name'],lastName=user['last_name'],totalpoints=points.totalpoints,lastUpdated=datetime.now(),careerPath=dreamJob,))
|
506 |
-
else:
|
507 |
-
|
508 |
-
user_id =new_point.get('userId')
|
509 |
-
leveleduser = get_all_users(userId=user_id)
|
510 |
-
points = get_all_simple_points_func(userId=user_id)
|
511 |
-
tempDreamJob = get_dream_job(userId=user_id)
|
512 |
dreamJob = tempDreamJob if type(tempDreamJob)==str else "IncompleteProfile"
|
513 |
-
create_leaderboard_ranking(LeaderBoardRanking(userId=
|
|
|
514 |
|
515 |
|
516 |
elif new_point==None and change!=None:
|
@@ -553,7 +593,7 @@ def handle_change(change=None,new_point=None):
|
|
553 |
create_leaderboard_ranking(LeaderBoardRanking(userId=user_id,firstName=leveleduser['first_name'],lastName=leveleduser['last_name'],totalpoints=points.totalpoints,lastUpdated=datetime.now(),careerPath=dreamJob,))
|
554 |
|
555 |
|
556 |
-
|
557 |
|
558 |
# Function to run the change stream in a separate thread (non-blocking)
|
559 |
def watch_change_stream():
|
|
|
23 |
from datetime import datetime
|
24 |
from bson import ObjectId
|
25 |
import os
|
26 |
+
from concurrent.futures import ThreadPoolExecutor
|
27 |
+
executor = ThreadPoolExecutor(max_workers=5)
|
28 |
|
29 |
|
30 |
load_dotenv()
|
|
|
440 |
collection = db['LeaderBoard']
|
441 |
# Insert the document
|
442 |
result= collection.find_one_and_replace(filter={"userId":document.userId},replacement=document.model_dump())
|
443 |
+
print(result)
|
444 |
if result==None:
|
445 |
result = collection.insert_one(document.model_dump())
|
446 |
print("correctly inserted new document for",document.firstName)
|
|
|
486 |
client = MongoClient(MONGO_URI)
|
487 |
db = client.crayonics
|
488 |
collection = db['Points']
|
489 |
+
import logging
|
490 |
+
from datetime import datetime
|
491 |
+
logging.basicConfig(level=logging.INFO)
|
492 |
+
logger = logging.getLogger(__name__)
|
493 |
+
|
494 |
+
def handle_change2(new_point):
|
495 |
+
logger.info(f"Extra info: {new_point}")
|
496 |
+
print("No leaderboard so creating one now")
|
497 |
+
|
498 |
+
users = get_all_users()
|
499 |
+
|
500 |
+
for user in users:
|
501 |
+
user_id = str(user['_id'])
|
502 |
+
print("Inserting user", f"User ID: {user_id}")
|
503 |
+
|
504 |
+
# Handle points retrieval safely
|
505 |
+
try:
|
506 |
+
points = get_all_simple_points_func(userId=user_id)
|
507 |
+
print("Points:", points)
|
508 |
+
except Exception as e:
|
509 |
+
logger.error(f"Error processing points for user {user_id}: {e}")
|
510 |
+
points = None # Default value to prevent errors
|
511 |
+
|
512 |
+
# Handle dream job retrieval safely
|
513 |
+
tempDreamJob = None
|
514 |
+
try:
|
515 |
+
tempDreamJob = get_dream_job(userId=user_id)
|
516 |
+
except Exception as e:
|
517 |
+
logger.error(f"Error retrieving dream job for user {user_id}: {e}")
|
518 |
+
|
519 |
+
# Assign default value if tempDreamJob is invalid
|
520 |
+
dreamJob = tempDreamJob if isinstance(tempDreamJob, str) else "IncompleteProfile"
|
521 |
+
|
522 |
+
# Try inserting into leaderboard
|
523 |
+
try:
|
524 |
+
create_leaderboard_ranking(LeaderBoardRanking(
|
525 |
+
userId=user_id,
|
526 |
+
firstName=user.get('first_name', 'Unknown'), # Safer dict access
|
527 |
+
lastName=user.get('last_name', 'Unknown'),
|
528 |
+
totalpoints=points.totalpoints if points else 0, # Prevent NoneType error
|
529 |
+
lastUpdated=datetime.now(),
|
530 |
+
careerPath=dreamJob,
|
531 |
+
))
|
532 |
+
except Exception as e:
|
533 |
+
logger.error(f"Error adding user {user_id} to leaderboard: {e}")
|
534 |
+
|
535 |
|
536 |
# A function to handle changes
|
537 |
def handle_change(change=None,new_point=None):
|
|
|
542 |
if new_point!=None:
|
543 |
collections = db.list_collection_names()
|
544 |
logger.info(f"Extra info: {new_point}")
|
545 |
+
print("No leaderboard so creating one now")
|
546 |
+
users = get_all_users()
|
547 |
+
for user in users:
|
548 |
+
print("inserting user",f"user id {user['_id']}")
|
549 |
+
points = get_all_simple_points_func(userId=str(user['_id']))
|
550 |
+
tempDreamJob = get_dream_job(userId=str(user['_id']))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
551 |
dreamJob = tempDreamJob if type(tempDreamJob)==str else "IncompleteProfile"
|
552 |
+
create_leaderboard_ranking(LeaderBoardRanking(userId=str(user['_id']),firstName=user['first_name'],lastName=user['last_name'],totalpoints=points.totalpoints,lastUpdated=datetime.now(),careerPath=dreamJob,))
|
553 |
+
|
554 |
|
555 |
|
556 |
elif new_point==None and change!=None:
|
|
|
593 |
create_leaderboard_ranking(LeaderBoardRanking(userId=user_id,firstName=leveleduser['first_name'],lastName=leveleduser['last_name'],totalpoints=points.totalpoints,lastUpdated=datetime.now(),careerPath=dreamJob,))
|
594 |
|
595 |
|
596 |
+
logger.info(f"Change detected: {dumps(change)}")
|
597 |
|
598 |
# Function to run the change stream in a separate thread (non-blocking)
|
599 |
def watch_change_stream():
|
gamification/objects.py
CHANGED
@@ -268,9 +268,9 @@ class IndividualUserLevel(BaseModel):
|
|
268 |
|
269 |
class SimpleIndividualUserLevel(BaseModel):
|
270 |
totalpoints:float
|
271 |
-
levelName:str
|
272 |
-
maxPoints:float
|
273 |
-
minPoints:float
|
274 |
|
275 |
class Config:
|
276 |
json_encoders = {
|
|
|
268 |
|
269 |
class SimpleIndividualUserLevel(BaseModel):
|
270 |
totalpoints:float
|
271 |
+
levelName:Optional[str]=None
|
272 |
+
maxPoints:Optional[float]=None
|
273 |
+
minPoints:Optional[float]=None
|
274 |
|
275 |
class Config:
|
276 |
json_encoders = {
|
gamification/pointLogic.py
CHANGED
@@ -29,7 +29,6 @@ def get_dream_job(userId):
|
|
29 |
|
30 |
|
31 |
def create_points_func(document:UserPoints)->bool:
|
32 |
-
from app import handle_change
|
33 |
db_uri = MONGO_URI
|
34 |
db_name = "crayonics"
|
35 |
collection_name="Points"
|
@@ -42,7 +41,7 @@ def create_points_func(document:UserPoints)->bool:
|
|
42 |
doc = document.model_dump()
|
43 |
doc['earnedAt']=datetime.now()
|
44 |
result = collection.insert_one(doc)
|
45 |
-
|
46 |
return True
|
47 |
else:
|
48 |
client.close()
|
@@ -98,16 +97,23 @@ def get_all_simple_points_func(userId) -> SimpleIndividualUserLevel:
|
|
98 |
point_cursor = collection.find({"userId": userId}) # This returns a cursor to the documents
|
99 |
|
100 |
# Convert the cursor to a list so we can reuse it
|
101 |
-
|
|
|
102 |
|
103 |
# Calculate the total points
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
|
108 |
# Create the IndividualUserLevel object with totalPoints and individualPoints
|
109 |
-
|
110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
return points
|
112 |
|
113 |
|
|
|
29 |
|
30 |
|
31 |
def create_points_func(document:UserPoints)->bool:
|
|
|
32 |
db_uri = MONGO_URI
|
33 |
db_name = "crayonics"
|
34 |
collection_name="Points"
|
|
|
41 |
doc = document.model_dump()
|
42 |
doc['earnedAt']=datetime.now()
|
43 |
result = collection.insert_one(doc)
|
44 |
+
|
45 |
return True
|
46 |
else:
|
47 |
client.close()
|
|
|
97 |
point_cursor = collection.find({"userId": userId}) # This returns a cursor to the documents
|
98 |
|
99 |
# Convert the cursor to a list so we can reuse it
|
100 |
+
try:
|
101 |
+
points_list = list(point_cursor)
|
102 |
|
103 |
# Calculate the total points
|
104 |
+
totalPoints = sum([point['numOfPoints'] for point in points_list])
|
105 |
+
particularLevelInfo = get_particular_level(dreamJob=dreamJob,totalPoints=totalPoints)
|
106 |
+
# Create the individual points list
|
107 |
|
108 |
# Create the IndividualUserLevel object with totalPoints and individualPoints
|
109 |
+
points = SimpleIndividualUserLevel(totalpoints=totalPoints)
|
110 |
+
except:
|
111 |
+
totalPoints = 0
|
112 |
+
# Create the individual points list
|
113 |
+
|
114 |
+
# Create the IndividualUserLevel object with totalPoints and individualPoints
|
115 |
+
points = SimpleIndividualUserLevel(totalpoints=totalPoints)
|
116 |
+
|
117 |
return points
|
118 |
|
119 |
|
gamification/routes.py
CHANGED
@@ -124,14 +124,18 @@ def delete_level(levelId):
|
|
124 |
except Exception as e:
|
125 |
raise HTTPException(status_code=500,detail=f"{e}")
|
126 |
|
127 |
-
|
128 |
@gamification.get("/get-top-30",tags=["user","admin"])
|
129 |
-
def get_leaderboard()->List[Ranker]:
|
|
|
130 |
try:
|
131 |
list_of_rankers = []
|
132 |
result = get_top_30()
|
|
|
|
|
|
|
133 |
list_of_rankers = [Ranker(**ranker) for ranker in result]
|
134 |
-
|
135 |
return list_of_rankers
|
136 |
except Exception as e:
|
137 |
raise HTTPException(status_code=500,detail=f"{e}")
|
|
|
124 |
except Exception as e:
|
125 |
raise HTTPException(status_code=500,detail=f"{e}")
|
126 |
|
127 |
+
from fastapi import BackgroundTasks
|
128 |
@gamification.get("/get-top-30",tags=["user","admin"])
|
129 |
+
def get_leaderboard(background_tasks: BackgroundTasks)->List[Ranker]:
|
130 |
+
from app import handle_change2
|
131 |
try:
|
132 |
list_of_rankers = []
|
133 |
result = get_top_30()
|
134 |
+
background_tasks.add_task(handle_change2, 2)
|
135 |
+
# executor.submit(handle_change2,2)
|
136 |
+
|
137 |
list_of_rankers = [Ranker(**ranker) for ranker in result]
|
138 |
+
# handle_change(new_point="userId")
|
139 |
return list_of_rankers
|
140 |
except Exception as e:
|
141 |
raise HTTPException(status_code=500,detail=f"{e}")
|