We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
dynamic challenges not work when using user mode

**Environment**:

  - CTFd Version/Commit:`2bd310b5d99f4305f8b61076f9af3b7e3c91ba8f`
  - Operating System: `ubuntu 16.04`
  - Web Browser and Version: `Chrome`

when using user mode , `solve_count` always get 0 

https://github.com/CTFd/CTFd/blob/master/CTFd/plugins/dynamic_challenges/__init__.py#L95
```
        solve_count = Solves.query \
            .join(Teams, Solves.team_id == Teams.id) \
            .filter(Solves.challenge_id == challenge.id, Teams.banned == False) \
            .count()
```


--- 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/plugins/dynamic_challenges/__init__.py`
Content:
```
1 from __future__ import division  # Use floating point for math calculations
2 from CTFd.plugins.challenges import BaseChallenge, CHALLENGE_CLASSES
3 from CTFd.plugins import register_plugin_assets_directory
4 from CTFd.plugins.flags import get_flag_class
5 from CTFd.models import db, Solves, Fails, Flags, Challenges, ChallengeFiles, Tags, Teams, Hints
6 from CTFd import utils
7 from CTFd.utils.migrations import upgrade
8 from CTFd.utils.user import get_ip
9 from CTFd.utils.uploads import upload_file, delete_file
10 from flask import Blueprint
11 import math
12 
13 
14 class DynamicValueChallenge(BaseChallenge):
15     id = "dynamic"  # Unique identifier used to register challenges
16     name = "dynamic"  # Name of a challenge type
17     templates = {  # Handlebars templates used for each aspect of challenge editing & viewing
18         'create': '/plugins/dynamic_challenges/assets/create.html',
19         'update': '/plugins/dynamic_challenges/assets/update.html',
20         'view': '/plugins/dynamic_challenges/assets/view.html',
21     }
22     scripts = {  # Scripts that are loaded when a template is loaded
23         'create': '/plugins/dynamic_challenges/assets/create.js',
24         'update': '/plugins/dynamic_challenges/assets/update.js',
25         'view': '/plugins/dynamic_challenges/assets/view.js',
26     }
27     # Route at which files are accessible. This must be registered using register_plugin_assets_directory()
28     route = '/plugins/dynamic_challenges/assets/'
29     # Blueprint used to access the static_folder directory.
30     blueprint = Blueprint('dynamic_challenges', __name__, template_folder='templates', static_folder='assets')
31 
32     @staticmethod
33     def create(request):
34         """
35         This method is used to process the challenge creation request.
36 
37         :param request:
38         :return:
39         """
40         data = request.form or request.get_json()
41         challenge = DynamicChallenge(**data)
42 
43         db.session.add(challenge)
44         db.session.commit()
45 
46         return challenge
47 
48     @staticmethod
49     def read(challenge):
50         """
51         This method is in used to access the data of a challenge in a format processable by the front end.
52 
53         :param challenge:
54         :return: Challenge object, data dictionary to be returned to the user
55         """
56         challenge = DynamicChallenge.query.filter_by(id=challenge.id).first()
57         data = {
58             'id': challenge.id,
59             'name': challenge.name,
60             'value': challenge.value,
61             'initial': challenge.initial,
62             'decay': challenge.decay,
63             'minimum': challenge.minimum,
64             'description': challenge.description,
65             'category': challenge.category,
66             'state': challenge.state,
67             'max_attempts': challenge.max_attempts,
68             'type': challenge.type,
69             'type_data': {
70                 'id': DynamicValueChallenge.id,
71                 'name': DynamicValueChallenge.name,
72                 'templates': DynamicValueChallenge.templates,
73                 'scripts': DynamicValueChallenge.scripts,
74             }
75         }
76         return data
77 
78     @staticmethod
79     def update(challenge, request):
80         """
81         This method is used to update the information associated with a challenge. This should be kept strictly to the
82         Challenges table and any child tables.
83 
84         :param challenge:
85         :param request:
86         :return:
87         """
88         data = request.form or request.get_json()
89         data['initial'] = float(data.get('initial', 0))
90         data['minimum'] = float(data.get('minimum', 0))
91         data['decay'] = float(data.get('decay', 0))
92         for attr, value in data.items():
93             setattr(challenge, attr, value)
94 
95         solve_count = Solves.query \
96             .join(Teams, Solves.team_id == Teams.id) \
97             .filter(Solves.challenge_id == challenge.id, Teams.banned == False) \
98             .count()
99 
100         # It is important that this calculation takes into account floats.
101         # Hence this file uses from __future__ import division
102         value = (((challenge.minimum - challenge.initial) / (challenge.decay ** 2)) * (solve_count ** 2)) + challenge.initial
103 
104         value = math.ceil(value)
105 
106         if value < challenge.minimum:
107             value = challenge.minimum
108 
109         challenge.value = value
110 
111         db.session.commit()
112         return challenge
113 
114     @staticmethod
115     def delete(challenge):
116         """
117         This method is used to delete the resources used by a challenge.
118 
119         :param challenge:
120         :return:
121         """
122         Fails.query.filter_by(challenge_id=challenge.id).delete()
123         Solves.query.filter_by(challenge_id=challenge.id).delete()
124         Flags.query.filter_by(challenge_id=challenge.id).delete()
125         files = ChallengeFiles.query.filter_by(challenge_id=challenge.id).all()
126         for f in files:
127             delete_file(f.id)
128         ChallengeFiles.query.filter_by(challenge_id=challenge.id).delete()
129         Tags.query.filter_by(challenge_id=challenge.id).delete()
130         Hints.query.filter_by(challenge_id=challenge.id).delete()
131         DynamicChallenge.query.filter_by(id=challenge.id).delete()
132         Challenges.query.filter_by(id=challenge.id).delete()
133         db.session.commit()
134 
135     @staticmethod
136     def attempt(challenge, request):
137         """
138         This method is used to check whether a given input is right or wrong. It does not make any changes and should
139         return a boolean for correctness and a string to be shown to the user. It is also in charge of parsing the
140         user's input from the request itself.
141 
142         :param challenge: The Challenge object from the database
143         :param request: The request the user submitted
144         :return: (boolean, string)
145         """
146         data = request.form or request.get_json()
147         submission = data['submission'].strip()
148         flags = Flags.query.filter_by(challenge_id=challenge.id).all()
149         for flag in flags:
150             if get_flag_class(flag.type).compare(flag, submission):
151                 return True, 'Correct'
152         return False, 'Incorrect'
153 
154     @staticmethod
155     def solve(user, team, challenge, request):
156         """
157         This method is used to insert Solves into the database in order to mark a challenge as solved.
158 
159         :param team: The Team object from the database
160         :param chal: The Challenge object from the database
161         :param request: The request the user submitted
162         :return:
163         """
164         chal = DynamicChallenge.query.filter_by(id=challenge.id).first()
165         data = request.form or request.get_json()
166         submission = data['submission'].strip()
167 
168         solve_count = Solves.query\
169             .join(Teams, Solves.team_id == Teams.id)\
170             .filter(Solves.challenge_id == chal.id, Teams.banned == False)\
171             .count()
172 
173         # It is important that this calculation takes into account floats.
174         # Hence this file uses from __future__ import division
175         value = (
176             (
177                 (chal.minimum - chal.initial) / (chal.decay**2)
178             ) * (solve_count**2)
179         ) + chal.initial
180 
181         value = math.ceil(value)
182 
183         if value < chal.minimum:
184             value = chal.minimum
185 
186         chal.value = value
187 
188         solve = Solves(
189             user_id=user.id,
190             team_id=team.id if team else None,
191             challenge_id=challenge.id,
192             ip=get_ip(req=request),
193             provided=submission
194         )
195         db.session.add(solve)
196         db.session.commit()
197         db.session.close()
198 
199     @staticmethod
200     def fail(user, team, challenge, request):
201         """
202         This method is used to insert Fails into the database in order to mark an answer incorrect.
203 
204         :param team: The Team object from the database
205         :param challenge: The Challenge object from the database
206         :param request: The request the user submitted
207         :return:
208         """
209         data = request.form or request.get_json()
210         submission = data['submission'].strip()
211         wrong = Fails(
212             user_id=user.id,
213             team_id=team.id if team else None,
214             challenge_id=challenge.id,
215             ip=get_ip(request),
216             provided=submission
217         )
218         db.session.add(wrong)
219         db.session.commit()
220         db.session.close()
221 
222 
223 class DynamicChallenge(Challenges):
224     __mapper_args__ = {'polymorphic_identity': 'dynamic'}
225     id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True)
226     initial = db.Column(db.Integer)
227     minimum = db.Column(db.Integer)
228     decay = db.Column(db.Integer)
229 
230     def __init__(self, *args, **kwargs):
231         super(DynamicChallenge, self).__init__(**kwargs)
232         self.initial = kwargs['value']
233 
234 
235 def load(app):
236     # upgrade()
237     app.db.create_all()
238     CHALLENGE_CLASSES['dynamic'] = DynamicValueChallenge
239     register_plugin_assets_directory(app, base_path='/plugins/dynamic_challenges/assets/')
240
```
--- 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/plugins/dynamic_challenges/__init__.py b/CTFd/plugins/dynamic_challenges/__init__.py
--- a/CTFd/plugins/dynamic_challenges/__init__.py
+++ b/CTFd/plugins/dynamic_challenges/__init__.py
@@ -7,6 +7,7 @@
 from CTFd.utils.migrations import upgrade
 from CTFd.utils.user import get_ip
 from CTFd.utils.uploads import upload_file, delete_file
+from CTFd.utils.modes import get_model
 from flask import Blueprint
 import math
 
@@ -92,9 +93,11 @@
         for attr, value in data.items():
             setattr(challenge, attr, value)
 
+        Model = get_model()
+
         solve_count = Solves.query \
-            .join(Teams, Solves.team_id == Teams.id) \
-            .filter(Solves.challenge_id == challenge.id, Teams.banned == False) \
+            .join(Model, Solves.account_id == Model.id) \
+            .filter(Solves.challenge_id == challenge.id, Model.hidden == False, Model.banned == False) \
             .count()
 
         # It is important that this calculation takes into account floats.
@@ -165,9 +168,11 @@
         data = request.form or request.get_json()
         submission = data['submission'].strip()
 
-        solve_count = Solves.query\
-            .join(Teams, Solves.team_id == Teams.id)\
-            .filter(Solves.challenge_id == chal.id, Teams.banned == False)\
+        Model = get_model()
+
+        solve_count = Solves.query \
+            .join(Model, Solves.account_id == Model.id) \
+            .filter(Solves.challenge_id == challenge.id, Model.hidden == False, Model.banned == False) \
             .count()
 
         # It is important that this calculation takes into account floats.

{"golden_diff": "diff --git a/CTFd/plugins/dynamic_challenges/__init__.py b/CTFd/plugins/dynamic_challenges/__init__.py\n--- a/CTFd/plugins/dynamic_challenges/__init__.py\n+++ b/CTFd/plugins/dynamic_challenges/__init__.py\n@@ -7,6 +7,7 @@\n from CTFd.utils.migrations import upgrade\n from CTFd.utils.user import get_ip\n from CTFd.utils.uploads import upload_file, delete_file\n+from CTFd.utils.modes import get_model\n from flask import Blueprint\n import math\n \n@@ -92,9 +93,11 @@\n         for attr, value in data.items():\n             setattr(challenge, attr, value)\n \n+        Model = get_model()\n+\n         solve_count = Solves.query \\\n-            .join(Teams, Solves.team_id == Teams.id) \\\n-            .filter(Solves.challenge_id == challenge.id, Teams.banned == False) \\\n+            .join(Model, Solves.account_id == Model.id) \\\n+            .filter(Solves.challenge_id == challenge.id, Model.hidden == False, Model.banned == False) \\\n             .count()\n \n         # It is important that this calculation takes into account floats.\n@@ -165,9 +168,11 @@\n         data = request.form or request.get_json()\n         submission = data['submission'].strip()\n \n-        solve_count = Solves.query\\\n-            .join(Teams, Solves.team_id == Teams.id)\\\n-            .filter(Solves.challenge_id == chal.id, Teams.banned == False)\\\n+        Model = get_model()\n+\n+        solve_count = Solves.query \\\n+            .join(Model, Solves.account_id == Model.id) \\\n+            .filter(Solves.challenge_id == challenge.id, Model.hidden == False, Model.banned == False) \\\n             .count()\n \n         # It is important that this calculation takes into account floats.\n", "issue": "dynamic challenges not work when using user mode\n\r\n**Environment**:\r\n\r\n  - CTFd Version/Commit:`2bd310b5d99f4305f8b61076f9af3b7e3c91ba8f`\r\n  - Operating System: `ubuntu 16.04`\r\n  - Web Browser and Version: `Chrome`\r\n\r\nwhen using user mode , `solve_count` always get 0 \r\n\r\nhttps://github.com/CTFd/CTFd/blob/master/CTFd/plugins/dynamic_challenges/__init__.py#L95\r\n```\r\n        solve_count = Solves.query \\\r\n            .join(Teams, Solves.team_id == Teams.id) \\\r\n            .filter(Solves.challenge_id == challenge.id, Teams.banned == False) \\\r\n            .count()\r\n```\r\n\n", "before_files": [{"content": "from __future__ import division  # Use floating point for math calculations\nfrom CTFd.plugins.challenges import BaseChallenge, CHALLENGE_CLASSES\nfrom CTFd.plugins import register_plugin_assets_directory\nfrom CTFd.plugins.flags import get_flag_class\nfrom CTFd.models import db, Solves, Fails, Flags, Challenges, ChallengeFiles, Tags, Teams, Hints\nfrom CTFd import utils\nfrom CTFd.utils.migrations import upgrade\nfrom CTFd.utils.user import get_ip\nfrom CTFd.utils.uploads import upload_file, delete_file\nfrom flask import Blueprint\nimport math\n\n\nclass DynamicValueChallenge(BaseChallenge):\n    id = \"dynamic\"  # Unique identifier used to register challenges\n    name = \"dynamic\"  # Name of a challenge type\n    templates = {  # Handlebars templates used for each aspect of challenge editing & viewing\n        'create': '/plugins/dynamic_challenges/assets/create.html',\n        'update': '/plugins/dynamic_challenges/assets/update.html',\n        'view': '/plugins/dynamic_challenges/assets/view.html',\n    }\n    scripts = {  # Scripts that are loaded when a template is loaded\n        'create': '/plugins/dynamic_challenges/assets/create.js',\n        'update': '/plugins/dynamic_challenges/assets/update.js',\n        'view': '/plugins/dynamic_challenges/assets/view.js',\n    }\n    # Route at which files are accessible. This must be registered using register_plugin_assets_directory()\n    route = '/plugins/dynamic_challenges/assets/'\n    # Blueprint used to access the static_folder directory.\n    blueprint = Blueprint('dynamic_challenges', __name__, template_folder='templates', static_folder='assets')\n\n    @staticmethod\n    def create(request):\n        \"\"\"\n        This method is used to process the challenge creation request.\n\n        :param request:\n        :return:\n        \"\"\"\n        data = request.form or request.get_json()\n        challenge = DynamicChallenge(**data)\n\n        db.session.add(challenge)\n        db.session.commit()\n\n        return challenge\n\n    @staticmethod\n    def read(challenge):\n        \"\"\"\n        This method is in used to access the data of a challenge in a format processable by the front end.\n\n        :param challenge:\n        :return: Challenge object, data dictionary to be returned to the user\n        \"\"\"\n        challenge = DynamicChallenge.query.filter_by(id=challenge.id).first()\n        data = {\n            'id': challenge.id,\n            'name': challenge.name,\n            'value': challenge.value,\n            'initial': challenge.initial,\n            'decay': challenge.decay,\n            'minimum': challenge.minimum,\n            'description': challenge.description,\n            'category': challenge.category,\n            'state': challenge.state,\n            'max_attempts': challenge.max_attempts,\n            'type': challenge.type,\n            'type_data': {\n                'id': DynamicValueChallenge.id,\n                'name': DynamicValueChallenge.name,\n                'templates': DynamicValueChallenge.templates,\n                'scripts': DynamicValueChallenge.scripts,\n            }\n        }\n        return data\n\n    @staticmethod\n    def update(challenge, request):\n        \"\"\"\n        This method is used to update the information associated with a challenge. This should be kept strictly to the\n        Challenges table and any child tables.\n\n        :param challenge:\n        :param request:\n        :return:\n        \"\"\"\n        data = request.form or request.get_json()\n        data['initial'] = float(data.get('initial', 0))\n        data['minimum'] = float(data.get('minimum', 0))\n        data['decay'] = float(data.get('decay', 0))\n        for attr, value in data.items():\n            setattr(challenge, attr, value)\n\n        solve_count = Solves.query \\\n            .join(Teams, Solves.team_id == Teams.id) \\\n            .filter(Solves.challenge_id == challenge.id, Teams.banned == False) \\\n            .count()\n\n        # It is important that this calculation takes into account floats.\n        # Hence this file uses from __future__ import division\n        value = (((challenge.minimum - challenge.initial) / (challenge.decay ** 2)) * (solve_count ** 2)) + challenge.initial\n\n        value = math.ceil(value)\n\n        if value < challenge.minimum:\n            value = challenge.minimum\n\n        challenge.value = value\n\n        db.session.commit()\n        return challenge\n\n    @staticmethod\n    def delete(challenge):\n        \"\"\"\n        This method is used to delete the resources used by a challenge.\n\n        :param challenge:\n        :return:\n        \"\"\"\n        Fails.query.filter_by(challenge_id=challenge.id).delete()\n        Solves.query.filter_by(challenge_id=challenge.id).delete()\n        Flags.query.filter_by(challenge_id=challenge.id).delete()\n        files = ChallengeFiles.query.filter_by(challenge_id=challenge.id).all()\n        for f in files:\n            delete_file(f.id)\n        ChallengeFiles.query.filter_by(challenge_id=challenge.id).delete()\n        Tags.query.filter_by(challenge_id=challenge.id).delete()\n        Hints.query.filter_by(challenge_id=challenge.id).delete()\n        DynamicChallenge.query.filter_by(id=challenge.id).delete()\n        Challenges.query.filter_by(id=challenge.id).delete()\n        db.session.commit()\n\n    @staticmethod\n    def attempt(challenge, request):\n        \"\"\"\n        This method is used to check whether a given input is right or wrong. It does not make any changes and should\n        return a boolean for correctness and a string to be shown to the user. It is also in charge of parsing the\n        user's input from the request itself.\n\n        :param challenge: The Challenge object from the database\n        :param request: The request the user submitted\n        :return: (boolean, string)\n        \"\"\"\n        data = request.form or request.get_json()\n        submission = data['submission'].strip()\n        flags = Flags.query.filter_by(challenge_id=challenge.id).all()\n        for flag in flags:\n            if get_flag_class(flag.type).compare(flag, submission):\n                return True, 'Correct'\n        return False, 'Incorrect'\n\n    @staticmethod\n    def solve(user, team, challenge, request):\n        \"\"\"\n        This method is used to insert Solves into the database in order to mark a challenge as solved.\n\n        :param team: The Team object from the database\n        :param chal: The Challenge object from the database\n        :param request: The request the user submitted\n        :return:\n        \"\"\"\n        chal = DynamicChallenge.query.filter_by(id=challenge.id).first()\n        data = request.form or request.get_json()\n        submission = data['submission'].strip()\n\n        solve_count = Solves.query\\\n            .join(Teams, Solves.team_id == Teams.id)\\\n            .filter(Solves.challenge_id == chal.id, Teams.banned == False)\\\n            .count()\n\n        # It is important that this calculation takes into account floats.\n        # Hence this file uses from __future__ import division\n        value = (\n            (\n                (chal.minimum - chal.initial) / (chal.decay**2)\n            ) * (solve_count**2)\n        ) + chal.initial\n\n        value = math.ceil(value)\n\n        if value < chal.minimum:\n            value = chal.minimum\n\n        chal.value = value\n\n        solve = Solves(\n            user_id=user.id,\n            team_id=team.id if team else None,\n            challenge_id=challenge.id,\n            ip=get_ip(req=request),\n            provided=submission\n        )\n        db.session.add(solve)\n        db.session.commit()\n        db.session.close()\n\n    @staticmethod\n    def fail(user, team, challenge, request):\n        \"\"\"\n        This method is used to insert Fails into the database in order to mark an answer incorrect.\n\n        :param team: The Team object from the database\n        :param challenge: The Challenge object from the database\n        :param request: The request the user submitted\n        :return:\n        \"\"\"\n        data = request.form or request.get_json()\n        submission = data['submission'].strip()\n        wrong = Fails(\n            user_id=user.id,\n            team_id=team.id if team else None,\n            challenge_id=challenge.id,\n            ip=get_ip(request),\n            provided=submission\n        )\n        db.session.add(wrong)\n        db.session.commit()\n        db.session.close()\n\n\nclass DynamicChallenge(Challenges):\n    __mapper_args__ = {'polymorphic_identity': 'dynamic'}\n    id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True)\n    initial = db.Column(db.Integer)\n    minimum = db.Column(db.Integer)\n    decay = db.Column(db.Integer)\n\n    def __init__(self, *args, **kwargs):\n        super(DynamicChallenge, self).__init__(**kwargs)\n        self.initial = kwargs['value']\n\n\ndef load(app):\n    # upgrade()\n    app.db.create_all()\n    CHALLENGE_CLASSES['dynamic'] = DynamicValueChallenge\n    register_plugin_assets_directory(app, base_path='/plugins/dynamic_challenges/assets/')\n", "path": "CTFd/plugins/dynamic_challenges/__init__.py"}], "after_files": [{"content": "from __future__ import division  # Use floating point for math calculations\nfrom CTFd.plugins.challenges import BaseChallenge, CHALLENGE_CLASSES\nfrom CTFd.plugins import register_plugin_assets_directory\nfrom CTFd.plugins.flags import get_flag_class\nfrom CTFd.models import db, Solves, Fails, Flags, Challenges, ChallengeFiles, Tags, Teams, Hints\nfrom CTFd import utils\nfrom CTFd.utils.migrations import upgrade\nfrom CTFd.utils.user import get_ip\nfrom CTFd.utils.uploads import upload_file, delete_file\nfrom CTFd.utils.modes import get_model\nfrom flask import Blueprint\nimport math\n\n\nclass DynamicValueChallenge(BaseChallenge):\n    id = \"dynamic\"  # Unique identifier used to register challenges\n    name = \"dynamic\"  # Name of a challenge type\n    templates = {  # Handlebars templates used for each aspect of challenge editing & viewing\n        'create': '/plugins/dynamic_challenges/assets/create.html',\n        'update': '/plugins/dynamic_challenges/assets/update.html',\n        'view': '/plugins/dynamic_challenges/assets/view.html',\n    }\n    scripts = {  # Scripts that are loaded when a template is loaded\n        'create': '/plugins/dynamic_challenges/assets/create.js',\n        'update': '/plugins/dynamic_challenges/assets/update.js',\n        'view': '/plugins/dynamic_challenges/assets/view.js',\n    }\n    # Route at which files are accessible. This must be registered using register_plugin_assets_directory()\n    route = '/plugins/dynamic_challenges/assets/'\n    # Blueprint used to access the static_folder directory.\n    blueprint = Blueprint('dynamic_challenges', __name__, template_folder='templates', static_folder='assets')\n\n    @staticmethod\n    def create(request):\n        \"\"\"\n        This method is used to process the challenge creation request.\n\n        :param request:\n        :return:\n        \"\"\"\n        data = request.form or request.get_json()\n        challenge = DynamicChallenge(**data)\n\n        db.session.add(challenge)\n        db.session.commit()\n\n        return challenge\n\n    @staticmethod\n    def read(challenge):\n        \"\"\"\n        This method is in used to access the data of a challenge in a format processable by the front end.\n\n        :param challenge:\n        :return: Challenge object, data dictionary to be returned to the user\n        \"\"\"\n        challenge = DynamicChallenge.query.filter_by(id=challenge.id).first()\n        data = {\n            'id': challenge.id,\n            'name': challenge.name,\n            'value': challenge.value,\n            'initial': challenge.initial,\n            'decay': challenge.decay,\n            'minimum': challenge.minimum,\n            'description': challenge.description,\n            'category': challenge.category,\n            'state': challenge.state,\n            'max_attempts': challenge.max_attempts,\n            'type': challenge.type,\n            'type_data': {\n                'id': DynamicValueChallenge.id,\n                'name': DynamicValueChallenge.name,\n                'templates': DynamicValueChallenge.templates,\n                'scripts': DynamicValueChallenge.scripts,\n            }\n        }\n        return data\n\n    @staticmethod\n    def update(challenge, request):\n        \"\"\"\n        This method is used to update the information associated with a challenge. This should be kept strictly to the\n        Challenges table and any child tables.\n\n        :param challenge:\n        :param request:\n        :return:\n        \"\"\"\n        data = request.form or request.get_json()\n        data['initial'] = float(data.get('initial', 0))\n        data['minimum'] = float(data.get('minimum', 0))\n        data['decay'] = float(data.get('decay', 0))\n        for attr, value in data.items():\n            setattr(challenge, attr, value)\n\n        Model = get_model()\n\n        solve_count = Solves.query \\\n            .join(Model, Solves.account_id == Model.id) \\\n            .filter(Solves.challenge_id == challenge.id, Model.hidden == False, Model.banned == False) \\\n            .count()\n\n        # It is important that this calculation takes into account floats.\n        # Hence this file uses from __future__ import division\n        value = (((challenge.minimum - challenge.initial) / (challenge.decay ** 2)) * (solve_count ** 2)) + challenge.initial\n\n        value = math.ceil(value)\n\n        if value < challenge.minimum:\n            value = challenge.minimum\n\n        challenge.value = value\n\n        db.session.commit()\n        return challenge\n\n    @staticmethod\n    def delete(challenge):\n        \"\"\"\n        This method is used to delete the resources used by a challenge.\n\n        :param challenge:\n        :return:\n        \"\"\"\n        Fails.query.filter_by(challenge_id=challenge.id).delete()\n        Solves.query.filter_by(challenge_id=challenge.id).delete()\n        Flags.query.filter_by(challenge_id=challenge.id).delete()\n        files = ChallengeFiles.query.filter_by(challenge_id=challenge.id).all()\n        for f in files:\n            delete_file(f.id)\n        ChallengeFiles.query.filter_by(challenge_id=challenge.id).delete()\n        Tags.query.filter_by(challenge_id=challenge.id).delete()\n        Hints.query.filter_by(challenge_id=challenge.id).delete()\n        DynamicChallenge.query.filter_by(id=challenge.id).delete()\n        Challenges.query.filter_by(id=challenge.id).delete()\n        db.session.commit()\n\n    @staticmethod\n    def attempt(challenge, request):\n        \"\"\"\n        This method is used to check whether a given input is right or wrong. It does not make any changes and should\n        return a boolean for correctness and a string to be shown to the user. It is also in charge of parsing the\n        user's input from the request itself.\n\n        :param challenge: The Challenge object from the database\n        :param request: The request the user submitted\n        :return: (boolean, string)\n        \"\"\"\n        data = request.form or request.get_json()\n        submission = data['submission'].strip()\n        flags = Flags.query.filter_by(challenge_id=challenge.id).all()\n        for flag in flags:\n            if get_flag_class(flag.type).compare(flag, submission):\n                return True, 'Correct'\n        return False, 'Incorrect'\n\n    @staticmethod\n    def solve(user, team, challenge, request):\n        \"\"\"\n        This method is used to insert Solves into the database in order to mark a challenge as solved.\n\n        :param team: The Team object from the database\n        :param chal: The Challenge object from the database\n        :param request: The request the user submitted\n        :return:\n        \"\"\"\n        chal = DynamicChallenge.query.filter_by(id=challenge.id).first()\n        data = request.form or request.get_json()\n        submission = data['submission'].strip()\n\n        Model = get_model()\n\n        solve_count = Solves.query \\\n            .join(Model, Solves.account_id == Model.id) \\\n            .filter(Solves.challenge_id == challenge.id, Model.hidden == False, Model.banned == False) \\\n            .count()\n\n        # It is important that this calculation takes into account floats.\n        # Hence this file uses from __future__ import division\n        value = (\n            (\n                (chal.minimum - chal.initial) / (chal.decay**2)\n            ) * (solve_count**2)\n        ) + chal.initial\n\n        value = math.ceil(value)\n\n        if value < chal.minimum:\n            value = chal.minimum\n\n        chal.value = value\n\n        solve = Solves(\n            user_id=user.id,\n            team_id=team.id if team else None,\n            challenge_id=challenge.id,\n            ip=get_ip(req=request),\n            provided=submission\n        )\n        db.session.add(solve)\n        db.session.commit()\n        db.session.close()\n\n    @staticmethod\n    def fail(user, team, challenge, request):\n        \"\"\"\n        This method is used to insert Fails into the database in order to mark an answer incorrect.\n\n        :param team: The Team object from the database\n        :param challenge: The Challenge object from the database\n        :param request: The request the user submitted\n        :return:\n        \"\"\"\n        data = request.form or request.get_json()\n        submission = data['submission'].strip()\n        wrong = Fails(\n            user_id=user.id,\n            team_id=team.id if team else None,\n            challenge_id=challenge.id,\n            ip=get_ip(request),\n            provided=submission\n        )\n        db.session.add(wrong)\n        db.session.commit()\n        db.session.close()\n\n\nclass DynamicChallenge(Challenges):\n    __mapper_args__ = {'polymorphic_identity': 'dynamic'}\n    id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True)\n    initial = db.Column(db.Integer)\n    minimum = db.Column(db.Integer)\n    decay = db.Column(db.Integer)\n\n    def __init__(self, *args, **kwargs):\n        super(DynamicChallenge, self).__init__(**kwargs)\n        self.initial = kwargs['value']\n\n\ndef load(app):\n    # upgrade()\n    app.db.create_all()\n    CHALLENGE_CLASSES['dynamic'] = DynamicValueChallenge\n    register_plugin_assets_directory(app, base_path='/plugins/dynamic_challenges/assets/')\n", "path": "CTFd/plugins/dynamic_challenges/__init__.py"}]}