Jiří Kalvoda
2 years ago
8 changed files with 191 additions and 19 deletions
@ -0,0 +1,22 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
import hra.db as db |
||||
|
import hra.lib as lib |
||||
|
from hra.util import hash_passwd |
||||
|
|
||||
|
import argparse |
||||
|
from sqlalchemy import exc, update |
||||
|
import sys |
||||
|
|
||||
|
g = db.Game(game_mode="", configuration={}, teams_count=1) |
||||
|
|
||||
|
parser = argparse.ArgumentParser() |
||||
|
parser.add_argument("game_id") |
||||
|
parser.add_argument("--step", action="store_true") |
||||
|
parser.add_argument("--restore", action="store_true") |
||||
|
|
||||
|
args = parser.parse_args() |
||||
|
|
||||
|
if args.restore: |
||||
|
lib.game_restore_broken(args.game_id) |
||||
|
if args.step: |
||||
|
lib.game_step(args.game_id) |
@ -0,0 +1,25 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
from hra.game import logic_by_mode |
||||
|
import hra.db as db |
||||
|
import hra.lib as lib |
||||
|
|
||||
|
import sys |
||||
|
from sqlalchemy import exc, update |
||||
|
|
||||
|
|
||||
|
mode = "occupy" |
||||
|
teams_count = 6 |
||||
|
configuration = {} |
||||
|
g = db.Game(game_mode=mode, configuration=configuration, teams_count=teams_count) |
||||
|
|
||||
|
db.get_session().add(g) |
||||
|
db.get_session().commit() |
||||
|
|
||||
|
s = db.State(game_id=g.game_id, round=0, state=g.get_logic().zero_state()) |
||||
|
|
||||
|
db.get_session().add(s) |
||||
|
g.current_round = 0 |
||||
|
g.working_on_next_state = False |
||||
|
db.get_session().commit() |
||||
|
|
||||
|
print(f"Přidána hra {g.game_id}. ") |
@ -0,0 +1,50 @@ |
|||||
|
import json |
||||
|
import hra.config as config |
||||
|
import hra.db as db |
||||
|
|
||||
|
class DuplicitMakeStep(Exception): |
||||
|
pass |
||||
|
|
||||
|
def game_step(game_id: int): |
||||
|
ses = db.get_session() |
||||
|
|
||||
|
ses.expire_all() |
||||
|
game = ses.query(db.Game).filter_by(game_id=game_id).with_for_update().one_or_none() |
||||
|
assert game is not None |
||||
|
if game.working_on_next_state: |
||||
|
ses.commit() |
||||
|
raise DuplicitMakeStep() |
||||
|
game.working_on_next_state = True |
||||
|
ses.commit() |
||||
|
|
||||
|
old_round_id = game.current_round |
||||
|
new_round_id = old_round_id + 1 |
||||
|
old_state = ses.query(db.State).filter_by(game_id=game.game_id, round=old_round_id).one_or_none() |
||||
|
|
||||
|
moves = [None for _ in range(game.teams_count)] |
||||
|
for i in ses.query(db.Move).filter_by(game_id=game.game_id, round=old_round_id).all(): |
||||
|
moves[i.team_id] = i.move |
||||
|
|
||||
|
ses.commit() |
||||
|
|
||||
|
x, points = game.get_logic().step(old_state.state, moves, old_round_id) |
||||
|
|
||||
|
new_state = db.State(game_id=game.game_id, round=new_round_id, state=x) |
||||
|
ses.add(new_state) |
||||
|
|
||||
|
ses.expire_all() |
||||
|
game = ses.query(db.Game).filter_by(game_id=game_id).with_for_update().one_or_none() |
||||
|
assert game is not None |
||||
|
assert game.working_on_next_state |
||||
|
game.current_round = new_round_id |
||||
|
game.working_on_next_state = False |
||||
|
ses.commit() |
||||
|
|
||||
|
def game_restore_broken(game_id: int) -> None: |
||||
|
ses = db.get_session() |
||||
|
ses.expire_all() |
||||
|
game = ses.query(db.Game).filter_by(game_id=game_id).with_for_update().one_or_none() |
||||
|
game.working_on_next_state = False |
||||
|
ses.commit() |
||||
|
|
||||
|
|
@ -1,32 +1,94 @@ |
|||||
from flask import Flask, redirect, flash, render_template, session, g, request, get_flashed_messages |
from flask import Flask, redirect, flash, render_template, session, g, request, get_flashed_messages |
||||
import werkzeug.exceptions |
import werkzeug.exceptions |
||||
import time |
|
||||
from datetime import datetime |
|
||||
import json |
import json |
||||
|
|
||||
import hra.config as config |
import hra.config as config |
||||
import hra.web.html as html |
|
||||
import hra.db as db |
import hra.db as db |
||||
from hra.web import app, NeedLoginError |
from hra.web import app, NeedLoginError |
||||
import hra.web.jinja_mac as jinja_mac |
import hra.web.jinja_mac as jinja_mac |
||||
|
|
||||
|
def args_get(name, type, optional=False, default=None): |
||||
|
v = request.args.get(name) |
||||
|
if v is None: |
||||
|
if optional: |
||||
|
return default |
||||
|
else: |
||||
|
raise werkzeug.exceptions.BadRequest(f"Missing mandatory option {name}.") |
||||
|
try: |
||||
|
return type(v) |
||||
|
except ValueError: |
||||
|
raise werkzeug.exceptions.BadRequest(f"Option {name} have wrong type.") |
||||
|
|
||||
|
|
||||
def get_context(): |
def get_context(): |
||||
if g.user is None: |
if g.user is None: |
||||
raise NeedLoginError |
raise NeedLoginError |
||||
game_id = request.args.get('game') or 1 |
game_id = args_get("game", int, True, 1) |
||||
team_id = request.args.get('team') or 0 |
team_id = args_get('team', int, True, 0) |
||||
game = db.get_session().query(db.Game).filter_by(game_id=game_id).first() |
game = db.get_session().query(db.Game).filter_by(game_id=game_id).first() |
||||
print(game_id, game, team_id) |
|
||||
if game is None: |
if game is None: |
||||
raise werkzeug.exceptions.NotFound("No such game") |
raise werkzeug.exceptions.NotFound("No such game") |
||||
return game, team_id |
return game, team_id |
||||
|
|
||||
|
|
||||
@app.route("/api/state", methods=['GET']) |
@app.route("/api/state", methods=['GET']) |
||||
def api_state(): |
def api_state(): |
||||
game, team_id = get_context() |
game, team_id = get_context() |
||||
state = game.current_state() |
state = game.current_state() |
||||
|
if state is None: |
||||
|
return json.dumps({ |
||||
|
"status": "working", |
||||
|
"wait": 1.0, |
||||
|
}) |
||||
return json.dumps({ |
return json.dumps({ |
||||
|
"status": "ok", |
||||
"round": state.round, |
"round": state.round, |
||||
"state": state.state, |
"team_id": team_id, |
||||
|
"state": game.get_logic().personalize_state(state.state, team_id, state.round), |
||||
|
}) |
||||
|
|
||||
|
@app.route("/api/action", methods=['POST']) |
||||
|
def api_action(): |
||||
|
def to_late(): |
||||
|
return json.dumps({ |
||||
|
"status": "too-late", |
||||
|
}) |
||||
|
|
||||
|
game, team_id = get_context() |
||||
|
j = request.get_json() |
||||
|
state = game.current_state() |
||||
|
round_id = args_get('round', int) |
||||
|
if round_id < 0 or round_id > game.current_round: |
||||
|
raise werkzeug.exceptions.BadRequest("Wrong round.") |
||||
|
if game.working_on_next_state or round_id < game.current_round: |
||||
|
return to_late() |
||||
|
|
||||
|
try: |
||||
|
warnings = game.get_logic().validate_move(state.state, team_id, j, round_id) |
||||
|
except Exception as e: |
||||
|
return json.dumps({ |
||||
|
"error": "error", |
||||
|
"description": str(e) |
||||
}) |
}) |
||||
|
|
||||
|
db.get_session().expire_all() |
||||
|
game = game.lock() |
||||
|
|
||||
|
if game.working_on_next_state or round_id < game.current_round: |
||||
|
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.move = j |
||||
|
|
||||
|
db.get_session().commit() |
||||
|
|
||||
|
if warnings is not None: |
||||
|
return json.dumps(warnings) |
||||
|
return json.dumps({ |
||||
|
"status": "ok", |
||||
|
}) |
||||
|
Loading…
Reference in new issue