diff --git a/server/hra/db.py b/server/hra/db.py index 5c9307c..7e0c998 100644 --- a/server/hra/db.py +++ b/server/hra/db.py @@ -170,6 +170,9 @@ class Team(Base): return f"{self.team_id}: -" return f"{self.team_id}: {self.user.username}" + def get_move(self, round_id): + return get_session().query(Move).filter_by(game_id=self.game_id, round=round_id, team_id=self.team_id).one_or_none() + class State(Base): __tablename__ = 'states' diff --git a/server/hra/web/api.py b/server/hra/web/api.py index d8cab77..f6f4728 100644 --- a/server/hra/web/api.py +++ b/server/hra/web/api.py @@ -12,9 +12,11 @@ import hra.lib as lib def json_endpoint(f): def l(*arg, **kvarg): x = f(*arg, **kvarg) - response = e.get_response() - response.content_type = "application/json" - response.data = json.dumps(x) + response = app.response_class( + response=json.dumps(x), + status=200, + mimetype='application/json' + ) return response l.__name__ = f.__name__ return l @@ -46,26 +48,33 @@ def get_context(): @app.route("/api/state", methods=['GET']) @json_endpoint def api_state(): + ses = db.get_session() team = get_context() game = team.game + game = game.lock() team_id = team.team_id min_round = args_get("min_round", int, True) t = datetime.now() state = game.current_state() if state is None: - return json.dumps({ + ses.commit() + return { "status": "working", "wait": 1.0, - }) + } if game.step_mode == db.StepMode.automatic: time_to_end = max(1, game.step_every_s - (t - state.create_time).total_seconds()) else: time_to_end = None if min_round is not None and min_round > game.current_round: - return json.dumps({ + ses.commit() + return { "status": "too_early", "wait": time_to_end + 1.0 if time_to_end is not None else 3.0, - }) + } + move = team.get_move(state.round) + move.reads_count += 1 + ses.commit() return { "status": "ok", "round": state.round, @@ -77,10 +86,11 @@ def api_state(): @app.route("/api/action", methods=['POST']) @json_endpoint def api_action(): + ses = db.get_session() def to_late(): - return json.dumps({ + return { "status": "too_late", - }) + } team = get_context() game = team.game team_id = team.team_id @@ -95,6 +105,10 @@ def api_action(): try: warnings = game.get_logic().validate_move(state.get_state(), team_id, j, round_id) except Exception as e: + game = game.lock() + move = team.get_move(state.round_id) + move.err_pushs_count += 1 + ses.commit() return { "status": "error", "description": f"{type(e).__name__}: {e}" @@ -107,14 +121,16 @@ def api_action(): db.get_session().commit() return to_late() - move = db.get_session().query(db.Move).filter_by(game_id=game.game_id, team_id=team_id, round=round_id).one_or_none() - if move is None: - move = db.Move(game_id=game.game_id, team_id=team_id, round=round_id) - db.get_session().add(move) + move = team.get_move(state.round) move.move = db.new_big_data(j) - db.get_session().commit() + if warnings is None: + move.ok_pushs_count += 1 + else: + move.warnings_pushs_count += 1 + + ses.commit() if warnings is not None: return warnings diff --git a/server/hra/web/pages.py b/server/hra/web/pages.py index 7845c94..9326732 100644 --- a/server/hra/web/pages.py +++ b/server/hra/web/pages.py @@ -268,6 +268,8 @@ def web_game(game_id): if right_for_step(game): with b.form(method="POST", _class="btn-group", action=app.url_for(web_game_step.__name__, game_id=game_id)): b.button(_class="btn btn-primary", type="submit", name="su", value="yes")("Krok") + if g.org: + b.a(_class="btn btn-default", href=app.url_for(web_org_game_round_inspect.__name__, game_id=game_id))("Inspekce kola") if g.org: b.h3("Aktuální konfigurace") @@ -347,6 +349,46 @@ class GameUserchangeForm(FlaskForm): submit_no_change = wtforms.SubmitField("Bez změny", render_kw={"style": "display: none"}) +@app.route("/org/game//round_inspect", methods=['GET']) +@app.route("/org/game//round_inspect/", methods=['GET']) +def web_org_game_round_inspect(game_id, round_id=None): + ses = db.get_session() + game = ses.query(db.Game).filter_by(game_id=game_id).one_or_none() + if round_id is None: + round_id = game.current_round + teams = ses.query(db.Team).filter_by(game_id=game_id).order_by(db.Team.team_id).all() + moves = ses.query(db.Move).filter_by(game_id=game_id, round=round_id).order_by(db.Move.team_id).all() + assert len(teams) == len(moves) + + if game is None: + raise werkzeug.exceptions.NotFound() + if not right_for_game(game): + raise werkzeug.exceptions.Forbidden() + + b = BasePage() + b.h2(f"Inspekce kola {round_id} hry {game.print()}") + with b.line().p("Aktuální kolo: "): + if game.working_on_next_state: + b.b()(game.current_round, "++") + else: + b(game.current_round) + with b.p().table(_class="data full"): + with b.thead(): + b.line().th()("Id") + b.line().th()("User") + b.line().th()("Bodů") + b.line().th()("Stažení") + b.line().th()("Nahrání") + for team, move in zip(teams, moves): + with b.tr(): + b.line().td()(team.team_id) + b.line().td()(user_link(team.user),": ", team.name) + b.line().td()(move.points) + b.line().td()(move.reads_count) + b.line().td()(f"{move.ok_pushs_count} {move.warnings_pushs_count} {move.err_pushs_count}") + return b.print_file() + + @app.route("/org/game//team//change_user", methods=['GET', 'POST']) def web_org_game_userchange(game_id, team_id): ses = db.get_session()