Strategická: Vizualizátko + drobnosti
This commit is contained in:
parent
2227b559c3
commit
c76f21fc3b
9 changed files with 392 additions and 41 deletions
|
@ -9,12 +9,12 @@ from sqlalchemy import exc, update
|
||||||
ses = db.get_session()
|
ses = db.get_session()
|
||||||
|
|
||||||
mode = "occupy"
|
mode = "occupy"
|
||||||
teams_count = 6
|
teams_count = 16
|
||||||
configuration = {
|
configuration = {
|
||||||
"teams_width": 2,
|
"teams_width": 4,
|
||||||
"teams_height": 3,
|
"teams_height": 4,
|
||||||
"width_per_team": 10,
|
"width_per_team": 30,
|
||||||
"height_per_team": 10,
|
"height_per_team": 30,
|
||||||
}
|
}
|
||||||
g = db.Game(game_mode=mode, configuration=configuration, teams_count=teams_count)
|
g = db.Game(game_mode=mode, configuration=configuration, teams_count=teams_count)
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,9 @@ class User(Base):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<User %r>' % self.username
|
return '<User %r>' % self.username
|
||||||
|
|
||||||
|
def print(self):
|
||||||
|
return self.username + (" (org)" if self.org else "")
|
||||||
|
|
||||||
class Game(Base):
|
class Game(Base):
|
||||||
__tablename__ = 'games'
|
__tablename__ = 'games'
|
||||||
|
|
||||||
|
@ -69,8 +72,8 @@ class Game(Base):
|
||||||
working_on_next_state = Column(Boolean, nullable=False, default=True)
|
working_on_next_state = Column(Boolean, nullable=False, default=True)
|
||||||
current_round = Column(Integer, default=-1)
|
current_round = Column(Integer, default=-1)
|
||||||
|
|
||||||
def current_state(self) -> Optional['State']:
|
def current_state(self, none_if_working=True) -> Optional['State']:
|
||||||
if self.working_on_next_state is True:
|
if none_if_working and self.working_on_next_state is True:
|
||||||
return None
|
return None
|
||||||
return get_session().query(State).filter_by(game_id=self.game_id, round=self.current_round).order_by(State.round.desc()).first()
|
return get_session().query(State).filter_by(game_id=self.game_id, round=self.current_round).order_by(State.round.desc()).first()
|
||||||
|
|
||||||
|
@ -82,6 +85,9 @@ class Game(Base):
|
||||||
ses.expire_all()
|
ses.expire_all()
|
||||||
return ses.query(Game).filter_by(game_id=self.game_id).with_for_update().first()
|
return ses.query(Game).filter_by(game_id=self.game_id).with_for_update().first()
|
||||||
|
|
||||||
|
def print(self):
|
||||||
|
return f"{self.game_id}: <name>"
|
||||||
|
|
||||||
|
|
||||||
class Team(Base):
|
class Team(Base):
|
||||||
__tablename__ = 'base'
|
__tablename__ = 'base'
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
import bcrypt
|
import bcrypt
|
||||||
|
from time import time
|
||||||
|
|
||||||
def hash_passwd(a):
|
def hash_passwd(a):
|
||||||
salt = b'$2b$12$V2aIKSJC/uozaodwYnQX3e'
|
salt = b'$2b$12$V2aIKSJC/uozaodwYnQX3e'
|
||||||
hashed = bcrypt.hashpw(a.encode('utf-8'), salt)
|
hashed = bcrypt.hashpw(a.encode('utf-8'), salt)
|
||||||
return hashed.decode('us-ascii')
|
return hashed.decode('us-ascii')
|
||||||
|
|
||||||
|
def timer_func(func):
|
||||||
|
def wrap_func(*args, **kwargs):
|
||||||
|
t1 = time()
|
||||||
|
result = func(*args, **kwargs)
|
||||||
|
t2 = time()
|
||||||
|
print(f'Function {func.__name__!r} executed in {(t2-t1):.4f}s')
|
||||||
|
return result
|
||||||
|
return wrap_func
|
||||||
|
|
|
@ -70,7 +70,7 @@ def api_action():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return json.dumps({
|
return json.dumps({
|
||||||
"error": "error",
|
"error": "error",
|
||||||
"description": str(e)
|
"description": f"{type(e).__name__}: {e}"
|
||||||
})
|
})
|
||||||
|
|
||||||
db.get_session().expire_all()
|
db.get_session().expire_all()
|
||||||
|
|
101
server/hra/web/game.py
Normal file
101
server/hra/web/game.py
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
from flask import Flask, redirect, flash, session, g, request, get_flashed_messages, Markup
|
||||||
|
from wtforms import Form, BooleanField, StringField, PasswordField, validators, SubmitField, IntegerField, DateTimeField
|
||||||
|
from wtforms.validators import ValidationError
|
||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from flask_bootstrap import Bootstrap
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from sqlalchemy import exc, update
|
||||||
|
import werkzeug.exceptions
|
||||||
|
import wtforms
|
||||||
|
from wtforms.fields import EmailField
|
||||||
|
from wtforms.widgets import NumberInput
|
||||||
|
from typing import Optional, Any
|
||||||
|
|
||||||
|
import hra.config as config
|
||||||
|
import hra.web.html as html
|
||||||
|
import hra.db as db
|
||||||
|
from hra.web import app
|
||||||
|
import hra.web.jinja_mac as jinja_mac
|
||||||
|
from hra.util import hash_passwd
|
||||||
|
from hra.web.pages import BasePage
|
||||||
|
|
||||||
|
|
||||||
|
wlogic_by_mode = {}
|
||||||
|
|
||||||
|
def add_wlogic(cls):
|
||||||
|
wlogic_by_mode[cls.__name__.lower()] = cls
|
||||||
|
|
||||||
|
def get_wlogic(game):
|
||||||
|
if game.game_mode in wlogic_by_mode:
|
||||||
|
cls = wlogic_by_mode[game.game_mode]
|
||||||
|
else:
|
||||||
|
cls = WLogic
|
||||||
|
return cls(game)
|
||||||
|
|
||||||
|
|
||||||
|
class WLogic:
|
||||||
|
def __init__(self, game):
|
||||||
|
self.game = game
|
||||||
|
self.logic = game.get_logic()
|
||||||
|
|
||||||
|
|
||||||
|
@add_wlogic
|
||||||
|
class Occupy(WLogic):
|
||||||
|
def view(self, state: db.State, team: Optional[db.Team]):
|
||||||
|
s = state.state
|
||||||
|
if team is not None:
|
||||||
|
s = self.logic.personalize_state(s, team.team_id, state.round)
|
||||||
|
b = BasePage()
|
||||||
|
b.h2(f"Hra {self.game.print()} kolo {state.round}")
|
||||||
|
with b.table(_class="game_table"):
|
||||||
|
for i, row in enumerate(s["map"]):
|
||||||
|
with b.tr():
|
||||||
|
for j, x in enumerate(row):
|
||||||
|
occupied_by_team = x["occupied_by_team"]
|
||||||
|
home_for_team = x["home_for_team"]
|
||||||
|
members = x["members"]
|
||||||
|
with b.td():
|
||||||
|
classes = []
|
||||||
|
with b.a(href=f"#cell_{i}_{j}"):
|
||||||
|
if x["hill"]:
|
||||||
|
classes.append("game_hill")
|
||||||
|
b(Markup(" "))
|
||||||
|
else:
|
||||||
|
if home_for_team is not None:
|
||||||
|
classes.append(f'game_home')
|
||||||
|
if occupied_by_team is not None:
|
||||||
|
classes.append(f'game_occupied')
|
||||||
|
classes.append(f'game_occupied_by_{occupied_by_team}')
|
||||||
|
if len(members):
|
||||||
|
b(len(members))
|
||||||
|
else:
|
||||||
|
b(Markup(" "))
|
||||||
|
b(_class=" ".join(classes))
|
||||||
|
|
||||||
|
for i, row in enumerate(s["map"]):
|
||||||
|
for j, x in enumerate(row):
|
||||||
|
occupied_by_team = x["occupied_by_team"]
|
||||||
|
home_for_team = x["home_for_team"]
|
||||||
|
members = x["members"]
|
||||||
|
with b.div(id=f"cell_{i}_{j}", _class="game_tab"):
|
||||||
|
b.h4(f"Políčko {i} {j}")
|
||||||
|
if x["hill"]:
|
||||||
|
b.p().b("Pohoří")
|
||||||
|
else:
|
||||||
|
if occupied_by_team is not None:
|
||||||
|
b.p(_class=f"game_team_{occupied_by_team}").b(f"Obsazeno týmem: {occupied_by_team}")
|
||||||
|
if home_for_team is not None:
|
||||||
|
b.p(_class=f"game_team_{home_for_team}").b(f"Domov týmu: {home_for_team}")
|
||||||
|
b.p().b(f"Počet osob: {len(members)}")
|
||||||
|
with b.ul():
|
||||||
|
for m in members:
|
||||||
|
b.li(_class=f"game_team_{home_for_team}")(f"Voják {m['id']} týmu {m['team']}")
|
||||||
|
|
||||||
|
|
||||||
|
b.wrap(
|
||||||
|
limited_size=False,
|
||||||
|
sticky_head=False,
|
||||||
|
head=lambda x:x.link(rel="stylesheet", href=app.url_for('static', filename='occupy.css'), type='text/css', media="all")
|
||||||
|
)
|
||||||
|
return b.print_file()
|
|
@ -116,7 +116,7 @@ class Tag(Bucket):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.attributes = attributes
|
self.attributes = attributes
|
||||||
|
|
||||||
def add_attribute(k, v):
|
def add_attribute(self, k, v):
|
||||||
self.attributes.append((k, v))
|
self.attributes.append((k, v))
|
||||||
|
|
||||||
def format_attributes(self):
|
def format_attributes(self):
|
||||||
|
@ -202,24 +202,25 @@ def remove_leading_underscore(s):
|
||||||
class WrapAfterBuilder(Builder):
|
class WrapAfterBuilder(Builder):
|
||||||
def __init__(self, f):
|
def __init__(self, f):
|
||||||
super().__init__(Bucket(self))
|
super().__init__(Bucket(self))
|
||||||
self._wrap_done = False
|
self.wrap_done = False
|
||||||
self._wrap_function = f
|
self.wrap_function = f
|
||||||
|
|
||||||
def _wrap(self, *arg, **kvarg):
|
def wrap(self, *arg, **kvarg):
|
||||||
if self._wrap_done:
|
if self.wrap_done:
|
||||||
return
|
return
|
||||||
self._wrap_done = True
|
self.wrap_done = True
|
||||||
content = self.root_tag.content
|
content = self.root_tag.content
|
||||||
self.root_tag = None
|
self.root_tag = None
|
||||||
self.current_tag = None
|
self.current_tag = None
|
||||||
self.root_tag = self._wrap_function(self, content, *arg, **kvarg) or self.root_tag
|
self.root_tag = self.wrap_function(self, content, *arg, **kvarg) or self.root_tag
|
||||||
|
return self
|
||||||
|
|
||||||
def print(self, *arg, **kvarg):
|
def print(self, *arg, **kvarg):
|
||||||
self._wrap()
|
self.wrap()
|
||||||
return super().print(*arg, **kvarg)
|
return super().print(*arg, **kvarg)
|
||||||
|
|
||||||
def print_file(self, *arg, **kvarg):
|
def print_file(self, *arg, **kvarg):
|
||||||
self._wrap()
|
self.wrap()
|
||||||
return super().print_file(*arg, **kvarg)
|
return super().print_file(*arg, **kvarg)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,7 @@ from flask_wtf import FlaskForm
|
||||||
from flask_bootstrap import Bootstrap
|
from flask_bootstrap import Bootstrap
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
|
||||||
from sqlalchemy import exc, update
|
from sqlalchemy import exc, update
|
||||||
import hashlib
|
|
||||||
import bcrypt
|
|
||||||
import os
|
|
||||||
import werkzeug.exceptions
|
import werkzeug.exceptions
|
||||||
import wtforms
|
import wtforms
|
||||||
from wtforms.fields import EmailField
|
from wtforms.fields import EmailField
|
||||||
|
@ -22,8 +18,9 @@ from hra.web import app
|
||||||
import hra.web.jinja_mac as jinja_mac
|
import hra.web.jinja_mac as jinja_mac
|
||||||
from hra.util import hash_passwd
|
from hra.util import hash_passwd
|
||||||
|
|
||||||
|
|
||||||
@html.WrapAfterBuilder_decorator
|
@html.WrapAfterBuilder_decorator
|
||||||
def BasePage(b, content):
|
def BasePage(b, content, head=lambda x:None, limited_size=True, sticky_head=True):
|
||||||
b.current_tag = html.Tag(b, "html", [])
|
b.current_tag = html.Tag(b, "html", [])
|
||||||
b.root_tag = b.current_tag
|
b.root_tag = b.current_tag
|
||||||
with b.head():
|
with b.head():
|
||||||
|
@ -33,13 +30,14 @@ def BasePage(b, content):
|
||||||
b.link(rel="stylesheet", href=app.url_for('static', filename='ksp-mhd.css'), type='text/css', media="all")
|
b.link(rel="stylesheet", href=app.url_for('static', filename='ksp-mhd.css'), type='text/css', media="all")
|
||||||
b.link(rel="icon", type="image/png", sizes="16x16", href="static/favicon.ico")
|
b.link(rel="icon", type="image/png", sizes="16x16", href="static/favicon.ico")
|
||||||
b.link(rel="shortcut icon", href=app.url_for('static', filename='img/favicon.ico'))
|
b.link(rel="shortcut icon", href=app.url_for('static', filename='img/favicon.ico'))
|
||||||
|
b(head)
|
||||||
with b.body() as body:
|
with b.body() as body:
|
||||||
with b.header(_class=f"flavor-{config.WEB_FLAVOR}"):
|
with b.header(_class=f"flavor-{config.WEB_FLAVOR}"):
|
||||||
with b.div(_class="content"):
|
with b.div(_class="content content_limited" if limited_size else "content"):
|
||||||
with b.a(href="/", title="Na hlavní stránku"):
|
with b.a(href="/", title="Na hlavní stránku"):
|
||||||
b.img(src=app.url_for('static', filename='hippo.png'), style="width: 60px;height: auto;", alt="KSP")
|
b.img(src=app.url_for('static', filename='hippo.png'), style="width: 60px;height: auto;", alt="KSP")
|
||||||
b.h1()("Hra na soustředění KSP")
|
b.h1()("Hra na soustředění KSP")
|
||||||
with b.div(id="nav-wrapper"):
|
with b.div(id="nav-wrapper", _class="nav-wrapper-sticky" if sticky_head else ""):
|
||||||
with b.nav(id="main-menu", _class="content"):
|
with b.nav(id="main-menu", _class="content"):
|
||||||
for item in g.menu:
|
for item in g.menu:
|
||||||
b.a(href=item.url)(item.name)
|
b.a(href=item.url)(item.name)
|
||||||
|
@ -78,11 +76,36 @@ def user_link(user):
|
||||||
b("-")
|
b("-")
|
||||||
else:
|
else:
|
||||||
if g.org:
|
if g.org:
|
||||||
b.a(href=app.url_for(web_org_user.__name__, user_id=user.id))(user.username)
|
b.a(href=app.url_for(web_org_user.__name__, user_id=user.id))(user.print())
|
||||||
else:
|
else:
|
||||||
b(user.username)
|
b(user.print())
|
||||||
|
return b.root_tag
|
||||||
|
|
||||||
|
|
||||||
|
def right_for_game(game):
|
||||||
|
if g.org:
|
||||||
|
return True
|
||||||
|
if g.user is None:
|
||||||
|
return False
|
||||||
|
return db.get_session().query(db.Team).filter_by(game_id=game_id, user=g.user.id).one_or_none() is not None
|
||||||
|
|
||||||
|
|
||||||
|
def right_for_team(team):
|
||||||
|
if g.org:
|
||||||
|
return True
|
||||||
|
if g.user is None:
|
||||||
|
return False
|
||||||
|
return team.user_id == g.user.id
|
||||||
|
|
||||||
|
|
||||||
|
def game_link(game):
|
||||||
|
b = html.Builder()
|
||||||
|
with b.line():
|
||||||
|
if game is None:
|
||||||
|
b("-")
|
||||||
|
else:
|
||||||
|
b.a(href=app.url_for(web_game.__name__, game_id=game.game_id))(game.print())
|
||||||
return b.root_tag
|
return b.root_tag
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RegistrationForm(FlaskForm):
|
class RegistrationForm(FlaskForm):
|
||||||
|
@ -175,9 +198,22 @@ def print_time(t):
|
||||||
@app.route("/", methods=['GET', 'POST'])
|
@app.route("/", methods=['GET', 'POST'])
|
||||||
def web_index():
|
def web_index():
|
||||||
b = BasePage()
|
b = BasePage()
|
||||||
|
|
||||||
if g.user:
|
if g.user:
|
||||||
with b.p():
|
teams = db.get_session().query(db.Team).filter_by(user_id=g.user.id).order_by(db.Team.game_id).all()
|
||||||
b(f"Váš token je: {g.user.token}")
|
games = []
|
||||||
|
for t in teams:
|
||||||
|
if len(games) == 0 or games[-1].game_id != t.game_id:
|
||||||
|
games.append(t.game)
|
||||||
|
|
||||||
|
b.line().h3("Token")
|
||||||
|
b.line().p().b(f"Váš token je: {g.user.token}")
|
||||||
|
b.line().h3("Vaše hry")
|
||||||
|
for game in games:
|
||||||
|
b.line().p(game_link(game))
|
||||||
|
else:
|
||||||
|
b.line().p("Přihlaste se, prosím.")
|
||||||
|
|
||||||
return b.print_file()
|
return b.print_file()
|
||||||
|
|
||||||
@app.route("/game/<int:game_id>", methods=['GET'])
|
@app.route("/game/<int:game_id>", methods=['GET'])
|
||||||
|
@ -187,30 +223,66 @@ def web_game(game_id):
|
||||||
teams = ses.query(db.Team).filter_by(game_id=game_id).order_by(db.Team.team_id).all()
|
teams = ses.query(db.Team).filter_by(game_id=game_id).order_by(db.Team.team_id).all()
|
||||||
if game is None:
|
if game is None:
|
||||||
raise werkzeug.exceptions.NotFound()
|
raise werkzeug.exceptions.NotFound()
|
||||||
|
if not right_for_game(game):
|
||||||
|
raise werkzeug.exceptions.Forbidden()
|
||||||
|
|
||||||
b = BasePage()
|
b = BasePage()
|
||||||
|
b.h2("Hra ", game.print())
|
||||||
with b.p().table(_class="data full"):
|
with b.p().table(_class="data full"):
|
||||||
with b.thead():
|
with b.thead():
|
||||||
b.line().th()("Id")
|
b.line().th()("Id")
|
||||||
b.line().th()("User")
|
b.line().th()("User")
|
||||||
if g.org:
|
b.line().th()("Akce")
|
||||||
b.line().th()("Akce")
|
|
||||||
for team in teams:
|
for team in teams:
|
||||||
with b.tr():
|
with b.tr():
|
||||||
b.line().td()(team.team_id)
|
b.line().td()(team.team_id)
|
||||||
b.line().td()(user_link(team.user),": ", team.name)
|
b.line().td()(user_link(team.user),": ", team.name)
|
||||||
if g.org:
|
with b.td():
|
||||||
with b.td():
|
with b.div(_class="btn-group", role="group"):
|
||||||
with b.div(_class="btn-group", role="group"):
|
if right_for_team(team):
|
||||||
b.a(_class="btn btn-xs btn-primary", href=app.url_for(web_org_game_userchange.__name__, game_id=game.game_id, team_id=team.team_id))("Změnit uživatele")
|
b.a(_class="btn btn-xs btn-primary", href=app.url_for(web_game_view.__name__, game_id=game.game_id, team_id=team.team_id))("Zobrazit hru")
|
||||||
#b.a(_class="btn btn-xs btn-primary", href=app.url_for(web_game.__name__, game_id=g.game_id))("Detail")
|
if g.org:
|
||||||
|
b.a(_class="btn btn-xs btn-default", href=app.url_for(web_org_game_userchange.__name__, game_id=game.game_id, team_id=team.team_id))("Změnit uživatele")
|
||||||
|
|
||||||
return b.print_file()
|
return b.print_file()
|
||||||
|
|
||||||
|
@app.route("/game/<int:game_id>/view", methods=['GET'])
|
||||||
|
@app.route("/game/<int:game_id>/view/<int:team_id>", methods=['GET'])
|
||||||
|
def web_game_view(game_id, team_id=None):
|
||||||
|
ses = db.get_session()
|
||||||
|
game = ses.query(db.Game).filter_by(game_id=game_id).one_or_none()
|
||||||
|
if game is None:
|
||||||
|
raise werkzeug.exceptions.NotFound()
|
||||||
|
if not right_for_game(game):
|
||||||
|
raise werkzeug.exceptions.Forbidden()
|
||||||
|
if team_id is not None:
|
||||||
|
team = ses.query(db.Team).filter_by(game_id=game_id, team_id=team_id).one_or_none()
|
||||||
|
if game is None:
|
||||||
|
raise werkzeug.exceptions.NotFound()
|
||||||
|
if not right_for_team(team):
|
||||||
|
raise werkzeug.exceptions.Forbidden()
|
||||||
|
else:
|
||||||
|
team = None
|
||||||
|
|
||||||
|
wl = get_wlogic(game)
|
||||||
|
state = game.current_state()
|
||||||
|
|
||||||
|
if not hasattr(wl, "view"):
|
||||||
|
raise werkzeug.exceptions.NotFound()
|
||||||
|
|
||||||
|
if state is None:
|
||||||
|
raise werkzeug.exceptions.NotFound()
|
||||||
|
|
||||||
|
return wl.view(state, team)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/org/games")
|
@app.route("/org/games")
|
||||||
def web_org_games():
|
def web_org_games():
|
||||||
games = db.get_session().query(db.Game).order_by(db.Game.game_id).all()
|
games = db.get_session().query(db.Game).order_by(db.Game.game_id).all()
|
||||||
b = BasePage()
|
b = BasePage()
|
||||||
|
b.h2("Hry")
|
||||||
with b.p().table(_class="data full"):
|
with b.p().table(_class="data full"):
|
||||||
with b.thead():
|
with b.thead():
|
||||||
b.line().th()("Id")
|
b.line().th()("Id")
|
||||||
|
@ -294,7 +366,13 @@ def web_org_game_userchange(game_id, team_id):
|
||||||
@app.route("/org/users")
|
@app.route("/org/users")
|
||||||
def web_org_users():
|
def web_org_users():
|
||||||
users = db.get_session().query(db.User).order_by(db.User.id).all()
|
users = db.get_session().query(db.User).order_by(db.User.id).all()
|
||||||
|
teams = db.get_session().query(db.Team).all()
|
||||||
|
games_for_user = {u.id: set() for u in users}
|
||||||
|
for t in teams:
|
||||||
|
if t.user_id is not None:
|
||||||
|
games_for_user[t.user_id].add(t.game)
|
||||||
b = BasePage()
|
b = BasePage()
|
||||||
|
b.h2("Uživatelé")
|
||||||
with b.p().table(_class="data full"):
|
with b.p().table(_class="data full"):
|
||||||
with b.thead():
|
with b.thead():
|
||||||
b.line().th()("Username")
|
b.line().th()("Username")
|
||||||
|
@ -302,8 +380,10 @@ def web_org_users():
|
||||||
b.line().th()("Akce")
|
b.line().th()("Akce")
|
||||||
for u in users:
|
for u in users:
|
||||||
with b.tr():
|
with b.tr():
|
||||||
b.line().td()(u.username)
|
b.line().td()(user_link(u))
|
||||||
b.line().td()
|
with b.td().ul():
|
||||||
|
for g in games_for_user[u.id]:
|
||||||
|
b.line().li(game_link(g))
|
||||||
with b.td():
|
with b.td():
|
||||||
with b.div(_class="btn-group", role="group"):
|
with b.div(_class="btn-group", role="group"):
|
||||||
b.a(_class="btn btn-xs btn-primary", href=app.url_for(web_org_user.__name__, user_id=u.id))("Detail")
|
b.a(_class="btn btn-xs btn-primary", href=app.url_for(web_org_user.__name__, user_id=u.id))("Detail")
|
||||||
|
@ -314,11 +394,23 @@ def web_org_user(user_id):
|
||||||
user = db.get_session().query(db.User).filter_by(id=user_id).one_or_none()
|
user = db.get_session().query(db.User).filter_by(id=user_id).one_or_none()
|
||||||
if not user:
|
if not user:
|
||||||
raise werkzeug.exceptions.NotFound()
|
raise werkzeug.exceptions.NotFound()
|
||||||
|
teams = db.get_session().query(db.Team).filter_by(user_id=user_id).order_by(db.Team.game_id).all()
|
||||||
b = BasePage()
|
b = BasePage()
|
||||||
b.line().h2("Uživatel ", user.username)
|
b.line().h2("Uživatel ", user.print())
|
||||||
with b.div(_class="btn-group", role="group"):
|
with b.div(_class="btn-group", role="group"):
|
||||||
with b.form(method="POST", _class="btn-group", action=app.url_for(web_org_user_su.__name__, user_id=user.id)):
|
with b.form(method="POST", _class="btn-group", action=app.url_for(web_org_user_su.__name__, user_id=user.id)):
|
||||||
b.button(_class="btn btn-default", type="submit", name="su", value="yes")("Převtělit")
|
b.button(_class="btn btn-default", type="submit", name="su", value="yes")("Převtělit")
|
||||||
|
b.h3("Týmy")
|
||||||
|
with b.p().table(_class="data full"):
|
||||||
|
with b.thead():
|
||||||
|
b.line().th()("Hra")
|
||||||
|
b.line().th()("Jméno z pohledu týmu")
|
||||||
|
b.line().th()("Číslo týmu")
|
||||||
|
for team in teams:
|
||||||
|
with b.tr():
|
||||||
|
b.line().td()(game_link(team.game))
|
||||||
|
b.line().td()(team.name)
|
||||||
|
b.line().td()(team.team_id)
|
||||||
return b.print_file()
|
return b.print_file()
|
||||||
|
|
||||||
@app.route("/org/user/<int:user_id>/su", methods=['POST'])
|
@app.route("/org/user/<int:user_id>/su", methods=['POST'])
|
||||||
|
@ -327,3 +419,5 @@ def web_org_user_su(user_id):
|
||||||
session['uid'] = user.id
|
session['uid'] = user.id
|
||||||
flash("Uživatel vtělen!")
|
flash("Uživatel vtělen!")
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
||||||
|
from hra.web.game import get_wlogic, wlogic_by_mode
|
||||||
|
|
|
@ -11,10 +11,13 @@ body {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
max-width: 1000px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content_limited, main {
|
||||||
|
max-width: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
padding: 10px 0px;
|
padding: 10px 0px;
|
||||||
}
|
}
|
||||||
|
@ -39,8 +42,10 @@ header img { height: 60px; }
|
||||||
|
|
||||||
header h1 { margin: auto 20px 0px; color: #222; }
|
header h1 { margin: auto 20px 0px; color: #222; }
|
||||||
|
|
||||||
#nav-wrapper {
|
.nav-wrapper-sticky {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
|
}
|
||||||
|
#nav-wrapper {
|
||||||
top: 0;
|
top: 0;
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
border: 1px #222 solid;
|
border: 1px #222 solid;
|
||||||
|
|
135
server/static/occupy.css
Normal file
135
server/static/occupy.css
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
|
||||||
|
|
||||||
|
table.game_table, table.game_table tr, table.game_table tr td {
|
||||||
|
border: thin solid black;
|
||||||
|
border-collapse: collapse;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.game_table tr td {
|
||||||
|
width: 10pt;
|
||||||
|
height: 10px;
|
||||||
|
font-size: 8px;
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.game_home {
|
||||||
|
border: 4pt solid black;
|
||||||
|
}
|
||||||
|
td.game_hill {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
td.game_occupied {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_0 {
|
||||||
|
background-color: #A50000;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_1 {
|
||||||
|
background-color: #00A6A6;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_2 {
|
||||||
|
background-color: #53A600;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_3 {
|
||||||
|
background-color: #5300A6;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_4 {
|
||||||
|
background-color: #A67D00;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_5 {
|
||||||
|
background-color: #002AA6;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_6 {
|
||||||
|
background-color: #00A62A;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_7 {
|
||||||
|
background-color: #A6007D;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_8 {
|
||||||
|
background-color: #A63D00;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_9 {
|
||||||
|
background-color: #0069A6;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_10 {
|
||||||
|
background-color: #16A600;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_11 {
|
||||||
|
background-color: #9000A6;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_12 {
|
||||||
|
background-color: #93A600;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_13 {
|
||||||
|
background-color: #1300A6;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_14 {
|
||||||
|
background-color: #00A667;
|
||||||
|
}
|
||||||
|
td.game_occupied_by_15 {
|
||||||
|
background-color: #A60040;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game_team_0 {
|
||||||
|
color: #A50000;
|
||||||
|
}
|
||||||
|
.game_team_1 {
|
||||||
|
color: #00A6A6;
|
||||||
|
}
|
||||||
|
.game_team_2 {
|
||||||
|
color: #53A600;
|
||||||
|
}
|
||||||
|
.game_team_3 {
|
||||||
|
color: #5300A6;
|
||||||
|
}
|
||||||
|
.game_team_4 {
|
||||||
|
color: #A67D00;
|
||||||
|
}
|
||||||
|
.game_team_5 {
|
||||||
|
color: #002AA6;
|
||||||
|
}
|
||||||
|
.game_team_6 {
|
||||||
|
color: #00A62A;
|
||||||
|
}
|
||||||
|
.game_team_7 {
|
||||||
|
color: #A6007D;
|
||||||
|
}
|
||||||
|
.game_team_8 {
|
||||||
|
color: #A63D00;
|
||||||
|
}
|
||||||
|
.game_team_9 {
|
||||||
|
color: #0069A6;
|
||||||
|
}
|
||||||
|
.game_team_10 {
|
||||||
|
color: #16A600;
|
||||||
|
}
|
||||||
|
.game_team_11 {
|
||||||
|
color: #9000A6;
|
||||||
|
}
|
||||||
|
.game_team_12 {
|
||||||
|
color: #93A600;
|
||||||
|
}
|
||||||
|
.game_team_13 {
|
||||||
|
color: #1300A6;
|
||||||
|
}
|
||||||
|
.game_team_14 {
|
||||||
|
color: #00A667;
|
||||||
|
}
|
||||||
|
.game_team_15 {
|
||||||
|
color: #A60040;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game_tab {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.game_tab:target {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.game_table tr td a, table.game_table tr td a:hover, table.game_table tr td a:visited, table.game_table tr td a:active {
|
||||||
|
display:block;
|
||||||
|
text-decoration:none;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
Loading…
Reference in a new issue