Skip to content
This repository has been archived by the owner on Jul 16, 2022. It is now read-only.

Demo function in Python for calculating user rankings #302 #303

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions python/calculate_leaderboard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## Introduction
This functions is created to build the leaderboard of the fitness challenge app available in (here)[https://github.com/gireeshp/fitness_challenge]. Please refer to the app read me for more details about the features and DB collections.

* This function gets triggered when the 'health_last_sync' field is updated in the 'users' collection
* It then sums up activities of all users captured in the "user_activities" collection
* It then loops through all defined challenges and identifies the measurement unit for that challenge (calories or steps), looks for all users participates in that challenge, takes in their scores and calculates the rank
* It finally update the leaderboard with each user rank

## Steps
* Run below code to:
* Point PIP target to .appwrite directory in the current working directory
* Install appwrite library from requirements.txt
```
PIP_TARGET=./.appwrite pip3 install -r ./requirements.txt --upgrade --ignore-installed
```
* Run below command to create the tar file
tar -zcvf code.tar.gz calculate_leaderboard
* Go to appwrite console and generate a new API key. Provide scopes collections.read, collections.write, documents.read, documents.write & users.read (the same API key will be used for other functions in this example - hence wider scope)
* In the appwrite console, create a new function. Choose python runtime
* Go to settings tab of the newly created function and select event "account.create"
* In the same settings tab, add the following environment variables
* APPWRITE_ENDPOINT ==> If you are running appwrite on localhost, you may want to use ngrok to create a public URL
* APPWRITE_FUNCTION_PROJECT_ID ==> Your appwrite project id
* APPWRITE_API_KEY ==> The secret from the new API key generated in first step
* In the Overview tab of the new function, click on "Deploy tag", go to "Manual" tab and provide "python main.py" as Command and upload the tar file.
91 changes: 91 additions & 0 deletions python/calculate_leaderboard/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import os
import json

from appwrite.client import Client
from appwrite.services.database import Database

user_collection_id = "617497ffb09f7"
challenges_collection_id = "617872e12c3d8"
user_activities_collection_id = "6174984332af8"
leaderboard_collection_id = "617873ddacaec"


def init_client():
# Initialize the Appwrite client
client = Client()
client.set_endpoint(os.getenv("APPWRITE_ENDPOINT"))
client.set_project(os.getenv("APPWRITE_FUNCTION_PROJECT_ID"))
client.set_key(os.getenv("APPWRITE_API_KEY"))

return client

def main():

client = init_client()
database = Database(client)

# Get all users and calculate their activity scores
userActivityScores = dict()
print (f"user collection id: {user_collection_id}")
res1 = database.list_documents(user_collection_id)
for userDoc in res1["documents"]:

userId = userDoc["user_id"]
# Calculate activity score for the user
activityScores = dict()

res2 = database.list_documents(user_activities_collection_id, filters=[f"user_id={userId}"])
for activityDoc in res2["documents"]:
activityType = activityDoc["measure_type"][len("HealthDataType."):]
value = activityDoc["value"]
if activityType in activityScores:
activityScores[activityType] += value
else:
activityScores[activityType] = value

userActivityScores[userId] = activityScores

print (userActivityScores)

# Get all unique challenge ids
res3 = database.list_documents(challenges_collection_id)
for challengeDoc in res3["documents"]:
challengeId = challengeDoc["challenge_id"]
measureType = challengeDoc["measure_type"][len("MeasureType."):].upper()
challengeName = challengeDoc["challenge_name"]
print ("---------------------------------")
print (f'ChallengeID: {challengeId}')
print (f'MeasureType: {measureType}')
print (f'ChallengeName: {challengeName}')
print ("---------------------------------")

# Now list of users participating in that challenge
leaderboardDict = dict()
res4 = database.list_documents(leaderboard_collection_id, filters=[f"challenge_id={challengeId}"])
for userDoc in res4["documents"]:
userId = userDoc["user_id"]
print (userId)
if userId in userActivityScores:
userActivityScoreDict = userActivityScores[userId]
if measureType in userActivityScoreDict:
leaderboardDict[userId] = userActivityScores[userId][measureType]

print ("Leaderboard looks like:")
print (leaderboardDict)

sorted_leaderboard = sorted(leaderboardDict.items(), key=lambda x: x[1], reverse=True)
print ("Leaderboard after sorting looks like:")
print(sorted_leaderboard)

# Now update the rank of the users in the challenge
rank = 0
for leader in sorted_leaderboard:
rank += 1
res5 = database.list_documents(leaderboard_collection_id, filters=[f"user_id={leader[0]}", f"challenge_id={challengeId}"], limit=1)
docId = res5["documents"][0]["$id"]
database.update_document(leaderboard_collection_id, docId, {"rank": rank})

print("All done")

if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions python/calculate_leaderboard/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
appwrite