We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
get_standings should return more flexible data
get_standings is a little inflexible because the data is constrained. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `CTFd/utils/scores/__init__.py`
Content:
```
1 from sqlalchemy.sql.expression import union_all
2 
3 from CTFd.cache import cache
4 from CTFd.models import Awards, Challenges, Solves, Teams, Users, db
5 from CTFd.utils import get_config
6 from CTFd.utils.dates import unix_time_to_utc
7 from CTFd.utils.modes import get_model
8 
9 
10 @cache.memoize(timeout=60)
11 def get_standings(count=None, admin=False):
12     """
13     Get standings as a list of tuples containing account_id, name, and score e.g. [(account_id, team_name, score)].
14 
15     Ties are broken by who reached a given score first based on the solve ID. Two users can have the same score but one
16     user will have a solve ID that is before the others. That user will be considered the tie-winner.
17 
18     Challenges & Awards with a value of zero are filtered out of the calculations to avoid incorrect tie breaks.
19     """
20     Model = get_model()
21 
22     scores = (
23         db.session.query(
24             Solves.account_id.label("account_id"),
25             db.func.sum(Challenges.value).label("score"),
26             db.func.max(Solves.id).label("id"),
27             db.func.max(Solves.date).label("date"),
28         )
29         .join(Challenges)
30         .filter(Challenges.value != 0)
31         .group_by(Solves.account_id)
32     )
33 
34     awards = (
35         db.session.query(
36             Awards.account_id.label("account_id"),
37             db.func.sum(Awards.value).label("score"),
38             db.func.max(Awards.id).label("id"),
39             db.func.max(Awards.date).label("date"),
40         )
41         .filter(Awards.value != 0)
42         .group_by(Awards.account_id)
43     )
44 
45     """
46     Filter out solves and awards that are before a specific time point.
47     """
48     freeze = get_config("freeze")
49     if not admin and freeze:
50         scores = scores.filter(Solves.date < unix_time_to_utc(freeze))
51         awards = awards.filter(Awards.date < unix_time_to_utc(freeze))
52 
53     """
54     Combine awards and solves with a union. They should have the same amount of columns
55     """
56     results = union_all(scores, awards).alias("results")
57 
58     """
59     Sum each of the results by the team id to get their score.
60     """
61     sumscores = (
62         db.session.query(
63             results.columns.account_id,
64             db.func.sum(results.columns.score).label("score"),
65             db.func.max(results.columns.id).label("id"),
66             db.func.max(results.columns.date).label("date"),
67         )
68         .group_by(results.columns.account_id)
69         .subquery()
70     )
71 
72     """
73     Admins can see scores for all users but the public cannot see banned users.
74 
75     Filters out banned users.
76     Properly resolves value ties by ID.
77 
78     Different databases treat time precision differently so resolve by the row ID instead.
79     """
80     if admin:
81         standings_query = (
82             db.session.query(
83                 Model.id.label("account_id"),
84                 Model.oauth_id.label("oauth_id"),
85                 Model.name.label("name"),
86                 Model.hidden,
87                 Model.banned,
88                 sumscores.columns.score,
89             )
90             .join(sumscores, Model.id == sumscores.columns.account_id)
91             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
92         )
93     else:
94         standings_query = (
95             db.session.query(
96                 Model.id.label("account_id"),
97                 Model.oauth_id.label("oauth_id"),
98                 Model.name.label("name"),
99                 sumscores.columns.score,
100             )
101             .join(sumscores, Model.id == sumscores.columns.account_id)
102             .filter(Model.banned == False, Model.hidden == False)
103             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
104         )
105 
106     """
107     Only select a certain amount of users if asked.
108     """
109     if count is None:
110         standings = standings_query.all()
111     else:
112         standings = standings_query.limit(count).all()
113 
114     return standings
115 
116 
117 @cache.memoize(timeout=60)
118 def get_team_standings(count=None, admin=False):
119     scores = (
120         db.session.query(
121             Solves.team_id.label("team_id"),
122             db.func.sum(Challenges.value).label("score"),
123             db.func.max(Solves.id).label("id"),
124             db.func.max(Solves.date).label("date"),
125         )
126         .join(Challenges)
127         .filter(Challenges.value != 0)
128         .group_by(Solves.team_id)
129     )
130 
131     awards = (
132         db.session.query(
133             Awards.team_id.label("team_id"),
134             db.func.sum(Awards.value).label("score"),
135             db.func.max(Awards.id).label("id"),
136             db.func.max(Awards.date).label("date"),
137         )
138         .filter(Awards.value != 0)
139         .group_by(Awards.team_id)
140     )
141 
142     freeze = get_config("freeze")
143     if not admin and freeze:
144         scores = scores.filter(Solves.date < unix_time_to_utc(freeze))
145         awards = awards.filter(Awards.date < unix_time_to_utc(freeze))
146 
147     results = union_all(scores, awards).alias("results")
148 
149     sumscores = (
150         db.session.query(
151             results.columns.team_id,
152             db.func.sum(results.columns.score).label("score"),
153             db.func.max(results.columns.id).label("id"),
154             db.func.max(results.columns.date).label("date"),
155         )
156         .group_by(results.columns.team_id)
157         .subquery()
158     )
159 
160     if admin:
161         standings_query = (
162             db.session.query(
163                 Teams.id.label("team_id"),
164                 Teams.oauth_id.label("oauth_id"),
165                 Teams.name.label("name"),
166                 Teams.hidden,
167                 Teams.banned,
168                 sumscores.columns.score,
169             )
170             .join(sumscores, Teams.id == sumscores.columns.team_id)
171             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
172         )
173     else:
174         standings_query = (
175             db.session.query(
176                 Teams.id.label("team_id"),
177                 Teams.oauth_id.label("oauth_id"),
178                 Teams.name.label("name"),
179                 sumscores.columns.score,
180             )
181             .join(sumscores, Teams.id == sumscores.columns.team_id)
182             .filter(Teams.banned == False)
183             .filter(Teams.hidden == False)
184             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
185         )
186 
187     if count is None:
188         standings = standings_query.all()
189     else:
190         standings = standings_query.limit(count).all()
191 
192     return standings
193 
194 
195 @cache.memoize(timeout=60)
196 def get_user_standings(count=None, admin=False):
197     scores = (
198         db.session.query(
199             Solves.user_id.label("user_id"),
200             db.func.sum(Challenges.value).label("score"),
201             db.func.max(Solves.id).label("id"),
202             db.func.max(Solves.date).label("date"),
203         )
204         .join(Challenges)
205         .filter(Challenges.value != 0)
206         .group_by(Solves.user_id)
207     )
208 
209     awards = (
210         db.session.query(
211             Awards.user_id.label("user_id"),
212             db.func.sum(Awards.value).label("score"),
213             db.func.max(Awards.id).label("id"),
214             db.func.max(Awards.date).label("date"),
215         )
216         .filter(Awards.value != 0)
217         .group_by(Awards.user_id)
218     )
219 
220     freeze = get_config("freeze")
221     if not admin and freeze:
222         scores = scores.filter(Solves.date < unix_time_to_utc(freeze))
223         awards = awards.filter(Awards.date < unix_time_to_utc(freeze))
224 
225     results = union_all(scores, awards).alias("results")
226 
227     sumscores = (
228         db.session.query(
229             results.columns.user_id,
230             db.func.sum(results.columns.score).label("score"),
231             db.func.max(results.columns.id).label("id"),
232             db.func.max(results.columns.date).label("date"),
233         )
234         .group_by(results.columns.user_id)
235         .subquery()
236     )
237 
238     if admin:
239         standings_query = (
240             db.session.query(
241                 Users.id.label("user_id"),
242                 Users.oauth_id.label("oauth_id"),
243                 Users.name.label("name"),
244                 Users.hidden,
245                 Users.banned,
246                 sumscores.columns.score,
247             )
248             .join(sumscores, Users.id == sumscores.columns.user_id)
249             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
250         )
251     else:
252         standings_query = (
253             db.session.query(
254                 Users.id.label("user_id"),
255                 Users.oauth_id.label("oauth_id"),
256                 Users.name.label("name"),
257                 sumscores.columns.score,
258             )
259             .join(sumscores, Users.id == sumscores.columns.user_id)
260             .filter(Users.banned == False, Users.hidden == False)
261             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
262         )
263 
264     if count is None:
265         standings = standings_query.all()
266     else:
267         standings = standings_query.limit(count).all()
268 
269     return standings
270
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/CTFd/utils/scores/__init__.py b/CTFd/utils/scores/__init__.py
--- a/CTFd/utils/scores/__init__.py
+++ b/CTFd/utils/scores/__init__.py
@@ -8,7 +8,7 @@
 
 
 @cache.memoize(timeout=60)
-def get_standings(count=None, admin=False):
+def get_standings(count=None, admin=False, fields=[]):
     """
     Get standings as a list of tuples containing account_id, name, and score e.g. [(account_id, team_name, score)].
 
@@ -86,6 +86,7 @@
                 Model.hidden,
                 Model.banned,
                 sumscores.columns.score,
+                *fields,
             )
             .join(sumscores, Model.id == sumscores.columns.account_id)
             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
@@ -97,6 +98,7 @@
                 Model.oauth_id.label("oauth_id"),
                 Model.name.label("name"),
                 sumscores.columns.score,
+                *fields,
             )
             .join(sumscores, Model.id == sumscores.columns.account_id)
             .filter(Model.banned == False, Model.hidden == False)
@@ -115,7 +117,7 @@
 
 
 @cache.memoize(timeout=60)
-def get_team_standings(count=None, admin=False):
+def get_team_standings(count=None, admin=False, fields=[]):
     scores = (
         db.session.query(
             Solves.team_id.label("team_id"),
@@ -166,6 +168,7 @@
                 Teams.hidden,
                 Teams.banned,
                 sumscores.columns.score,
+                *fields,
             )
             .join(sumscores, Teams.id == sumscores.columns.team_id)
             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
@@ -177,6 +180,7 @@
                 Teams.oauth_id.label("oauth_id"),
                 Teams.name.label("name"),
                 sumscores.columns.score,
+                *fields,
             )
             .join(sumscores, Teams.id == sumscores.columns.team_id)
             .filter(Teams.banned == False)
@@ -193,7 +197,7 @@
 
 
 @cache.memoize(timeout=60)
-def get_user_standings(count=None, admin=False):
+def get_user_standings(count=None, admin=False, fields=[]):
     scores = (
         db.session.query(
             Solves.user_id.label("user_id"),
@@ -244,6 +248,7 @@
                 Users.hidden,
                 Users.banned,
                 sumscores.columns.score,
+                *fields,
             )
             .join(sumscores, Users.id == sumscores.columns.user_id)
             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)
@@ -255,6 +260,7 @@
                 Users.oauth_id.label("oauth_id"),
                 Users.name.label("name"),
                 sumscores.columns.score,
+                *fields,
             )
             .join(sumscores, Users.id == sumscores.columns.user_id)
             .filter(Users.banned == False, Users.hidden == False)

{"golden_diff": "diff --git a/CTFd/utils/scores/__init__.py b/CTFd/utils/scores/__init__.py\n--- a/CTFd/utils/scores/__init__.py\n+++ b/CTFd/utils/scores/__init__.py\n@@ -8,7 +8,7 @@\n \n \n @cache.memoize(timeout=60)\n-def get_standings(count=None, admin=False):\n+def get_standings(count=None, admin=False, fields=[]):\n     \"\"\"\n     Get standings as a list of tuples containing account_id, name, and score e.g. [(account_id, team_name, score)].\n \n@@ -86,6 +86,7 @@\n                 Model.hidden,\n                 Model.banned,\n                 sumscores.columns.score,\n+                *fields,\n             )\n             .join(sumscores, Model.id == sumscores.columns.account_id)\n             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n@@ -97,6 +98,7 @@\n                 Model.oauth_id.label(\"oauth_id\"),\n                 Model.name.label(\"name\"),\n                 sumscores.columns.score,\n+                *fields,\n             )\n             .join(sumscores, Model.id == sumscores.columns.account_id)\n             .filter(Model.banned == False, Model.hidden == False)\n@@ -115,7 +117,7 @@\n \n \n @cache.memoize(timeout=60)\n-def get_team_standings(count=None, admin=False):\n+def get_team_standings(count=None, admin=False, fields=[]):\n     scores = (\n         db.session.query(\n             Solves.team_id.label(\"team_id\"),\n@@ -166,6 +168,7 @@\n                 Teams.hidden,\n                 Teams.banned,\n                 sumscores.columns.score,\n+                *fields,\n             )\n             .join(sumscores, Teams.id == sumscores.columns.team_id)\n             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n@@ -177,6 +180,7 @@\n                 Teams.oauth_id.label(\"oauth_id\"),\n                 Teams.name.label(\"name\"),\n                 sumscores.columns.score,\n+                *fields,\n             )\n             .join(sumscores, Teams.id == sumscores.columns.team_id)\n             .filter(Teams.banned == False)\n@@ -193,7 +197,7 @@\n \n \n @cache.memoize(timeout=60)\n-def get_user_standings(count=None, admin=False):\n+def get_user_standings(count=None, admin=False, fields=[]):\n     scores = (\n         db.session.query(\n             Solves.user_id.label(\"user_id\"),\n@@ -244,6 +248,7 @@\n                 Users.hidden,\n                 Users.banned,\n                 sumscores.columns.score,\n+                *fields,\n             )\n             .join(sumscores, Users.id == sumscores.columns.user_id)\n             .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n@@ -255,6 +260,7 @@\n                 Users.oauth_id.label(\"oauth_id\"),\n                 Users.name.label(\"name\"),\n                 sumscores.columns.score,\n+                *fields,\n             )\n             .join(sumscores, Users.id == sumscores.columns.user_id)\n             .filter(Users.banned == False, Users.hidden == False)\n", "issue": "get_standings should return more flexible data\nget_standings is a little inflexible because the data is constrained. \n", "before_files": [{"content": "from sqlalchemy.sql.expression import union_all\n\nfrom CTFd.cache import cache\nfrom CTFd.models import Awards, Challenges, Solves, Teams, Users, db\nfrom CTFd.utils import get_config\nfrom CTFd.utils.dates import unix_time_to_utc\nfrom CTFd.utils.modes import get_model\n\n\n@cache.memoize(timeout=60)\ndef get_standings(count=None, admin=False):\n    \"\"\"\n    Get standings as a list of tuples containing account_id, name, and score e.g. [(account_id, team_name, score)].\n\n    Ties are broken by who reached a given score first based on the solve ID. Two users can have the same score but one\n    user will have a solve ID that is before the others. That user will be considered the tie-winner.\n\n    Challenges & Awards with a value of zero are filtered out of the calculations to avoid incorrect tie breaks.\n    \"\"\"\n    Model = get_model()\n\n    scores = (\n        db.session.query(\n            Solves.account_id.label(\"account_id\"),\n            db.func.sum(Challenges.value).label(\"score\"),\n            db.func.max(Solves.id).label(\"id\"),\n            db.func.max(Solves.date).label(\"date\"),\n        )\n        .join(Challenges)\n        .filter(Challenges.value != 0)\n        .group_by(Solves.account_id)\n    )\n\n    awards = (\n        db.session.query(\n            Awards.account_id.label(\"account_id\"),\n            db.func.sum(Awards.value).label(\"score\"),\n            db.func.max(Awards.id).label(\"id\"),\n            db.func.max(Awards.date).label(\"date\"),\n        )\n        .filter(Awards.value != 0)\n        .group_by(Awards.account_id)\n    )\n\n    \"\"\"\n    Filter out solves and awards that are before a specific time point.\n    \"\"\"\n    freeze = get_config(\"freeze\")\n    if not admin and freeze:\n        scores = scores.filter(Solves.date < unix_time_to_utc(freeze))\n        awards = awards.filter(Awards.date < unix_time_to_utc(freeze))\n\n    \"\"\"\n    Combine awards and solves with a union. They should have the same amount of columns\n    \"\"\"\n    results = union_all(scores, awards).alias(\"results\")\n\n    \"\"\"\n    Sum each of the results by the team id to get their score.\n    \"\"\"\n    sumscores = (\n        db.session.query(\n            results.columns.account_id,\n            db.func.sum(results.columns.score).label(\"score\"),\n            db.func.max(results.columns.id).label(\"id\"),\n            db.func.max(results.columns.date).label(\"date\"),\n        )\n        .group_by(results.columns.account_id)\n        .subquery()\n    )\n\n    \"\"\"\n    Admins can see scores for all users but the public cannot see banned users.\n\n    Filters out banned users.\n    Properly resolves value ties by ID.\n\n    Different databases treat time precision differently so resolve by the row ID instead.\n    \"\"\"\n    if admin:\n        standings_query = (\n            db.session.query(\n                Model.id.label(\"account_id\"),\n                Model.oauth_id.label(\"oauth_id\"),\n                Model.name.label(\"name\"),\n                Model.hidden,\n                Model.banned,\n                sumscores.columns.score,\n            )\n            .join(sumscores, Model.id == sumscores.columns.account_id)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n    else:\n        standings_query = (\n            db.session.query(\n                Model.id.label(\"account_id\"),\n                Model.oauth_id.label(\"oauth_id\"),\n                Model.name.label(\"name\"),\n                sumscores.columns.score,\n            )\n            .join(sumscores, Model.id == sumscores.columns.account_id)\n            .filter(Model.banned == False, Model.hidden == False)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n\n    \"\"\"\n    Only select a certain amount of users if asked.\n    \"\"\"\n    if count is None:\n        standings = standings_query.all()\n    else:\n        standings = standings_query.limit(count).all()\n\n    return standings\n\n\n@cache.memoize(timeout=60)\ndef get_team_standings(count=None, admin=False):\n    scores = (\n        db.session.query(\n            Solves.team_id.label(\"team_id\"),\n            db.func.sum(Challenges.value).label(\"score\"),\n            db.func.max(Solves.id).label(\"id\"),\n            db.func.max(Solves.date).label(\"date\"),\n        )\n        .join(Challenges)\n        .filter(Challenges.value != 0)\n        .group_by(Solves.team_id)\n    )\n\n    awards = (\n        db.session.query(\n            Awards.team_id.label(\"team_id\"),\n            db.func.sum(Awards.value).label(\"score\"),\n            db.func.max(Awards.id).label(\"id\"),\n            db.func.max(Awards.date).label(\"date\"),\n        )\n        .filter(Awards.value != 0)\n        .group_by(Awards.team_id)\n    )\n\n    freeze = get_config(\"freeze\")\n    if not admin and freeze:\n        scores = scores.filter(Solves.date < unix_time_to_utc(freeze))\n        awards = awards.filter(Awards.date < unix_time_to_utc(freeze))\n\n    results = union_all(scores, awards).alias(\"results\")\n\n    sumscores = (\n        db.session.query(\n            results.columns.team_id,\n            db.func.sum(results.columns.score).label(\"score\"),\n            db.func.max(results.columns.id).label(\"id\"),\n            db.func.max(results.columns.date).label(\"date\"),\n        )\n        .group_by(results.columns.team_id)\n        .subquery()\n    )\n\n    if admin:\n        standings_query = (\n            db.session.query(\n                Teams.id.label(\"team_id\"),\n                Teams.oauth_id.label(\"oauth_id\"),\n                Teams.name.label(\"name\"),\n                Teams.hidden,\n                Teams.banned,\n                sumscores.columns.score,\n            )\n            .join(sumscores, Teams.id == sumscores.columns.team_id)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n    else:\n        standings_query = (\n            db.session.query(\n                Teams.id.label(\"team_id\"),\n                Teams.oauth_id.label(\"oauth_id\"),\n                Teams.name.label(\"name\"),\n                sumscores.columns.score,\n            )\n            .join(sumscores, Teams.id == sumscores.columns.team_id)\n            .filter(Teams.banned == False)\n            .filter(Teams.hidden == False)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n\n    if count is None:\n        standings = standings_query.all()\n    else:\n        standings = standings_query.limit(count).all()\n\n    return standings\n\n\n@cache.memoize(timeout=60)\ndef get_user_standings(count=None, admin=False):\n    scores = (\n        db.session.query(\n            Solves.user_id.label(\"user_id\"),\n            db.func.sum(Challenges.value).label(\"score\"),\n            db.func.max(Solves.id).label(\"id\"),\n            db.func.max(Solves.date).label(\"date\"),\n        )\n        .join(Challenges)\n        .filter(Challenges.value != 0)\n        .group_by(Solves.user_id)\n    )\n\n    awards = (\n        db.session.query(\n            Awards.user_id.label(\"user_id\"),\n            db.func.sum(Awards.value).label(\"score\"),\n            db.func.max(Awards.id).label(\"id\"),\n            db.func.max(Awards.date).label(\"date\"),\n        )\n        .filter(Awards.value != 0)\n        .group_by(Awards.user_id)\n    )\n\n    freeze = get_config(\"freeze\")\n    if not admin and freeze:\n        scores = scores.filter(Solves.date < unix_time_to_utc(freeze))\n        awards = awards.filter(Awards.date < unix_time_to_utc(freeze))\n\n    results = union_all(scores, awards).alias(\"results\")\n\n    sumscores = (\n        db.session.query(\n            results.columns.user_id,\n            db.func.sum(results.columns.score).label(\"score\"),\n            db.func.max(results.columns.id).label(\"id\"),\n            db.func.max(results.columns.date).label(\"date\"),\n        )\n        .group_by(results.columns.user_id)\n        .subquery()\n    )\n\n    if admin:\n        standings_query = (\n            db.session.query(\n                Users.id.label(\"user_id\"),\n                Users.oauth_id.label(\"oauth_id\"),\n                Users.name.label(\"name\"),\n                Users.hidden,\n                Users.banned,\n                sumscores.columns.score,\n            )\n            .join(sumscores, Users.id == sumscores.columns.user_id)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n    else:\n        standings_query = (\n            db.session.query(\n                Users.id.label(\"user_id\"),\n                Users.oauth_id.label(\"oauth_id\"),\n                Users.name.label(\"name\"),\n                sumscores.columns.score,\n            )\n            .join(sumscores, Users.id == sumscores.columns.user_id)\n            .filter(Users.banned == False, Users.hidden == False)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n\n    if count is None:\n        standings = standings_query.all()\n    else:\n        standings = standings_query.limit(count).all()\n\n    return standings\n", "path": "CTFd/utils/scores/__init__.py"}], "after_files": [{"content": "from sqlalchemy.sql.expression import union_all\n\nfrom CTFd.cache import cache\nfrom CTFd.models import Awards, Challenges, Solves, Teams, Users, db\nfrom CTFd.utils import get_config\nfrom CTFd.utils.dates import unix_time_to_utc\nfrom CTFd.utils.modes import get_model\n\n\n@cache.memoize(timeout=60)\ndef get_standings(count=None, admin=False, fields=[]):\n    \"\"\"\n    Get standings as a list of tuples containing account_id, name, and score e.g. [(account_id, team_name, score)].\n\n    Ties are broken by who reached a given score first based on the solve ID. Two users can have the same score but one\n    user will have a solve ID that is before the others. That user will be considered the tie-winner.\n\n    Challenges & Awards with a value of zero are filtered out of the calculations to avoid incorrect tie breaks.\n    \"\"\"\n    Model = get_model()\n\n    scores = (\n        db.session.query(\n            Solves.account_id.label(\"account_id\"),\n            db.func.sum(Challenges.value).label(\"score\"),\n            db.func.max(Solves.id).label(\"id\"),\n            db.func.max(Solves.date).label(\"date\"),\n        )\n        .join(Challenges)\n        .filter(Challenges.value != 0)\n        .group_by(Solves.account_id)\n    )\n\n    awards = (\n        db.session.query(\n            Awards.account_id.label(\"account_id\"),\n            db.func.sum(Awards.value).label(\"score\"),\n            db.func.max(Awards.id).label(\"id\"),\n            db.func.max(Awards.date).label(\"date\"),\n        )\n        .filter(Awards.value != 0)\n        .group_by(Awards.account_id)\n    )\n\n    \"\"\"\n    Filter out solves and awards that are before a specific time point.\n    \"\"\"\n    freeze = get_config(\"freeze\")\n    if not admin and freeze:\n        scores = scores.filter(Solves.date < unix_time_to_utc(freeze))\n        awards = awards.filter(Awards.date < unix_time_to_utc(freeze))\n\n    \"\"\"\n    Combine awards and solves with a union. They should have the same amount of columns\n    \"\"\"\n    results = union_all(scores, awards).alias(\"results\")\n\n    \"\"\"\n    Sum each of the results by the team id to get their score.\n    \"\"\"\n    sumscores = (\n        db.session.query(\n            results.columns.account_id,\n            db.func.sum(results.columns.score).label(\"score\"),\n            db.func.max(results.columns.id).label(\"id\"),\n            db.func.max(results.columns.date).label(\"date\"),\n        )\n        .group_by(results.columns.account_id)\n        .subquery()\n    )\n\n    \"\"\"\n    Admins can see scores for all users but the public cannot see banned users.\n\n    Filters out banned users.\n    Properly resolves value ties by ID.\n\n    Different databases treat time precision differently so resolve by the row ID instead.\n    \"\"\"\n    if admin:\n        standings_query = (\n            db.session.query(\n                Model.id.label(\"account_id\"),\n                Model.oauth_id.label(\"oauth_id\"),\n                Model.name.label(\"name\"),\n                Model.hidden,\n                Model.banned,\n                sumscores.columns.score,\n                *fields,\n            )\n            .join(sumscores, Model.id == sumscores.columns.account_id)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n    else:\n        standings_query = (\n            db.session.query(\n                Model.id.label(\"account_id\"),\n                Model.oauth_id.label(\"oauth_id\"),\n                Model.name.label(\"name\"),\n                sumscores.columns.score,\n                *fields,\n            )\n            .join(sumscores, Model.id == sumscores.columns.account_id)\n            .filter(Model.banned == False, Model.hidden == False)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n\n    \"\"\"\n    Only select a certain amount of users if asked.\n    \"\"\"\n    if count is None:\n        standings = standings_query.all()\n    else:\n        standings = standings_query.limit(count).all()\n\n    return standings\n\n\n@cache.memoize(timeout=60)\ndef get_team_standings(count=None, admin=False, fields=[]):\n    scores = (\n        db.session.query(\n            Solves.team_id.label(\"team_id\"),\n            db.func.sum(Challenges.value).label(\"score\"),\n            db.func.max(Solves.id).label(\"id\"),\n            db.func.max(Solves.date).label(\"date\"),\n        )\n        .join(Challenges)\n        .filter(Challenges.value != 0)\n        .group_by(Solves.team_id)\n    )\n\n    awards = (\n        db.session.query(\n            Awards.team_id.label(\"team_id\"),\n            db.func.sum(Awards.value).label(\"score\"),\n            db.func.max(Awards.id).label(\"id\"),\n            db.func.max(Awards.date).label(\"date\"),\n        )\n        .filter(Awards.value != 0)\n        .group_by(Awards.team_id)\n    )\n\n    freeze = get_config(\"freeze\")\n    if not admin and freeze:\n        scores = scores.filter(Solves.date < unix_time_to_utc(freeze))\n        awards = awards.filter(Awards.date < unix_time_to_utc(freeze))\n\n    results = union_all(scores, awards).alias(\"results\")\n\n    sumscores = (\n        db.session.query(\n            results.columns.team_id,\n            db.func.sum(results.columns.score).label(\"score\"),\n            db.func.max(results.columns.id).label(\"id\"),\n            db.func.max(results.columns.date).label(\"date\"),\n        )\n        .group_by(results.columns.team_id)\n        .subquery()\n    )\n\n    if admin:\n        standings_query = (\n            db.session.query(\n                Teams.id.label(\"team_id\"),\n                Teams.oauth_id.label(\"oauth_id\"),\n                Teams.name.label(\"name\"),\n                Teams.hidden,\n                Teams.banned,\n                sumscores.columns.score,\n                *fields,\n            )\n            .join(sumscores, Teams.id == sumscores.columns.team_id)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n    else:\n        standings_query = (\n            db.session.query(\n                Teams.id.label(\"team_id\"),\n                Teams.oauth_id.label(\"oauth_id\"),\n                Teams.name.label(\"name\"),\n                sumscores.columns.score,\n                *fields,\n            )\n            .join(sumscores, Teams.id == sumscores.columns.team_id)\n            .filter(Teams.banned == False)\n            .filter(Teams.hidden == False)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n\n    if count is None:\n        standings = standings_query.all()\n    else:\n        standings = standings_query.limit(count).all()\n\n    return standings\n\n\n@cache.memoize(timeout=60)\ndef get_user_standings(count=None, admin=False, fields=[]):\n    scores = (\n        db.session.query(\n            Solves.user_id.label(\"user_id\"),\n            db.func.sum(Challenges.value).label(\"score\"),\n            db.func.max(Solves.id).label(\"id\"),\n            db.func.max(Solves.date).label(\"date\"),\n        )\n        .join(Challenges)\n        .filter(Challenges.value != 0)\n        .group_by(Solves.user_id)\n    )\n\n    awards = (\n        db.session.query(\n            Awards.user_id.label(\"user_id\"),\n            db.func.sum(Awards.value).label(\"score\"),\n            db.func.max(Awards.id).label(\"id\"),\n            db.func.max(Awards.date).label(\"date\"),\n        )\n        .filter(Awards.value != 0)\n        .group_by(Awards.user_id)\n    )\n\n    freeze = get_config(\"freeze\")\n    if not admin and freeze:\n        scores = scores.filter(Solves.date < unix_time_to_utc(freeze))\n        awards = awards.filter(Awards.date < unix_time_to_utc(freeze))\n\n    results = union_all(scores, awards).alias(\"results\")\n\n    sumscores = (\n        db.session.query(\n            results.columns.user_id,\n            db.func.sum(results.columns.score).label(\"score\"),\n            db.func.max(results.columns.id).label(\"id\"),\n            db.func.max(results.columns.date).label(\"date\"),\n        )\n        .group_by(results.columns.user_id)\n        .subquery()\n    )\n\n    if admin:\n        standings_query = (\n            db.session.query(\n                Users.id.label(\"user_id\"),\n                Users.oauth_id.label(\"oauth_id\"),\n                Users.name.label(\"name\"),\n                Users.hidden,\n                Users.banned,\n                sumscores.columns.score,\n                *fields,\n            )\n            .join(sumscores, Users.id == sumscores.columns.user_id)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n    else:\n        standings_query = (\n            db.session.query(\n                Users.id.label(\"user_id\"),\n                Users.oauth_id.label(\"oauth_id\"),\n                Users.name.label(\"name\"),\n                sumscores.columns.score,\n                *fields,\n            )\n            .join(sumscores, Users.id == sumscores.columns.user_id)\n            .filter(Users.banned == False, Users.hidden == False)\n            .order_by(sumscores.columns.score.desc(), sumscores.columns.id)\n        )\n\n    if count is None:\n        standings = standings_query.all()\n    else:\n        standings = standings_query.limit(count).all()\n\n    return standings\n", "path": "CTFd/utils/scores/__init__.py"}]}