get team information

This commit is contained in:
Michael Zhang 2016-01-16 00:53:35 -06:00
parent 19a475199a
commit f6fb0cb00a
6 changed files with 136 additions and 35 deletions

View file

@ -48,8 +48,6 @@ def api_wrapper(f):
return response return response
return wrapper return wrapper
import user # Must go below api_wrapper to prevent import loops
def login_required(f): def login_required(f):
@wraps(f) @wraps(f)
def decorated_function(*args, **kwargs): def decorated_function(*args, **kwargs):
@ -58,6 +56,8 @@ def login_required(f):
return f(*args, **kwargs) return f(*args, **kwargs)
return decorated_function return decorated_function
import user # Must go below api_wrapper to prevent import loops
def admins_only(f): def admins_only(f):
@wraps(f) @wraps(f)
def decorated_function(*args, **kwargs): def decorated_function(*args, **kwargs):

View file

@ -1,5 +1,7 @@
from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.sqlalchemy import SQLAlchemy
import time import time
import traceback
import utils import utils
db = SQLAlchemy() db = SQLAlchemy()
@ -33,11 +35,14 @@ class Teams(db.Model):
teamname_lower = db.Column(db.String(64), unique=True) teamname_lower = db.Column(db.String(64), unique=True)
school = db.Column(db.Text) school = db.Column(db.Text)
owner = db.Column(db.Integer) owner = db.Column(db.Integer)
observer = db.Column(db.Boolean)
def __init__(self, teamname, owner): def __init__(self, teamname, school, owner, observer):
self.teamname = teamname self.teamname = teamname
self.teamname_lower = teamname.lower() self.teamname_lower = teamname.lower()
self.school = school
self.owner = owner self.owner = owner
self.observer = observer
def get_members(self): def get_members(self):
members = [ ] members = [ ]
@ -47,6 +52,25 @@ class Teams(db.Model):
}) })
return members return members
def points(self):
score = db.func.sum(Problems.value).label("score")
team = db.session.query(Solves.tid, score).join(Teams).join(Problems).filter(Teams.tid==self.tid).group_by(Solves.tid).first()
if team:
return team.score
else:
return 0
def place(self):
score = db.func.sum(Problems.value).label("score")
quickest = db.func.max(Solves.date).label("quickest")
teams = db.session.query(Solves.tid).join(Teams).join(Problems).filter().group_by(Solves.tid).order_by(score.desc(), quickest).all()
try:
i = teams.index((self.tid,)) + 1
k = i % 10
return (i, "%d%s" % (i, "tsnrhtdd"[(i / 10 % 10 != 1) * (k < 4) * k::4]))
except ValueError:
return (-1, "--")
class Problems(db.Model): class Problems(db.Model):
pid = db.Column(db.Integer, primary_key=True) pid = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128)) name = db.Column(db.String(128))
@ -77,13 +101,19 @@ class Files(db.Model):
class Solves(db.Model): class Solves(db.Model):
sid = db.Column(db.Integer, primary_key=True) sid = db.Column(db.Integer, primary_key=True)
pid = db.Column(db.Integer) pid = db.Column(db.Integer, db.ForeignKey("problems.pid"))
tid = db.Column(db.Integer) tid = db.Column(db.Integer, db.ForeignKey("teams.tid"))
date = db.Column(db.Integer, default=utils.get_time_since_epoch()) date = db.Column(db.Integer, default=utils.get_time_since_epoch())
team = db.relationship("Teams", foreign_keys="Solves.tid", lazy="joined")
prob = db.relationship("Problems", foreign_keys="Solves.pid", lazy="joined")
correct = db.Column(db.Boolean)
flag = db.Column(db.Text)
def __init__(self, pid, tid): def __init__(self, pid, tid, flag, correct):
self.pid = pid self.pid = pid
self.tid = tid self.tid = tid
self.flag = flag
self.correct = correct
########## ##########
# TOKENS # # TOKENS #

View file

@ -4,9 +4,9 @@ from voluptuous import Schema, Length, Required
from models import db, Teams, Users from models import db, Teams, Users
from decorators import api_wrapper, login_required, WebException from decorators import api_wrapper, login_required, WebException
from user import in_team, get_user, is_logged_in
from schemas import verify_to_schema, check from schemas import verify_to_schema, check
import user
import utils import utils
blueprint = Blueprint("team", __name__) blueprint = Blueprint("team", __name__)
@ -20,18 +20,19 @@ blueprint = Blueprint("team", __name__)
@login_required @login_required
def team_create(): def team_create():
params = utils.flat_multi(request.form) params = utils.flat_multi(request.form)
user = get_user().first() _user = user.get_user().first()
if user.tid is not None or user.tid >= 0 or get_team(owner=user.uid).first() is not None: if _user.tid is not None or _user.tid >= 0 or get_team(owner=_user.uid).first() is not None:
raise WebException("You're already in a team!") raise WebException("You're already in a team!")
verify_to_schema(TeamSchema, params) verify_to_schema(TeamSchema, params)
teamname = params.get("teamname") teamname = params.get("teamname")
school = params.get("school")
team = Teams(teamname, user.uid) team = Teams(teamname, school, _user.uid, _user.utype != 1)
with app.app_context(): with app.app_context():
db.session.add(team) db.session.add(team)
db.session.commit() db.session.commit()
Users.query.filter_by(uid=user.uid).update({ "tid": team.tid }) Users.query.filter_by(uid=_user.uid).update({ "tid": team.tid })
db.session.commit() db.session.commit()
return { "success": 1, "message": "Success!" } return { "success": 1, "message": "Success!" }
@ -39,7 +40,7 @@ def team_create():
@blueprint.route("/info", methods=["GET"]) @blueprint.route("/info", methods=["GET"])
@api_wrapper @api_wrapper
def team_info(): def team_info():
logged_in = is_logged_in() logged_in = user.is_logged_in()
me = False me = False
teamname = utils.flat_multi(request.args).get("teamname") teamname = utils.flat_multi(request.args).get("teamname")
if logged_in: if logged_in:
@ -57,7 +58,8 @@ def team_info():
raise WebException("Team not found.") raise WebException("Team not found.")
teamdata = { teamdata = {
"teamname": team.teamname "teamname": team.teamname,
"school": team.school
} }
teamdata["in_team"] = me teamdata["in_team"] = me
return { "success": 1, "team": teamdata } return { "success": 1, "team": teamdata }
@ -74,8 +76,25 @@ TeamSchema = Schema({
([utils.__check_ascii], "Please only use ASCII characters in your teamname."), ([utils.__check_ascii], "Please only use ASCII characters in your teamname."),
([__check_teamname], "This teamname is taken, did you forget your password?") ([__check_teamname], "This teamname is taken, did you forget your password?")
), ),
Required("school"): check(
([str, Length(min=4, max=60)], "Your school name should be between 4 and 60 characters long."),
([utils.__check_ascii], "Please only use ASCII characters in your school name."),
),
}, extra=True) }, extra=True)
def get_team_info(tid=None, teamname=None, teamname_lower=None, owner=None):
team = get_team(tid=tid, teamname=teamname, teamname_lower=teamname_lower, owner=owner).first()
place_number, place = team.place()
result = {
"tid": team.tid,
"teamname": team.teamname,
"school": team.school,
"place": place,
"place_number": place_number,
"points": team.points()
}
return result
def get_team(tid=None, teamname=None, teamname_lower=None, owner=None): def get_team(tid=None, teamname=None, teamname_lower=None, owner=None):
match = {} match = {}
if teamname != None: if teamname != None:
@ -86,10 +105,10 @@ def get_team(tid=None, teamname=None, teamname_lower=None, owner=None):
match.update({ "tid": tid }) match.update({ "tid": tid })
elif owner != None: elif owner != None:
match.update({ "owner": owner }) match.update({ "owner": owner })
elif is_logged_in(): elif user.is_logged_in():
user = get_user().first() _user = user.get_user().first()
if user.tid is not None: if _user.tid is not None:
match.update({ "tid": user.tid }) match.update({ "tid": _user.tid })
with app.app_context(): with app.app_context():
result = Teams.query.filter_by(**match) result = Teams.query.filter_by(**match)
return result return result

View file

@ -10,6 +10,7 @@ import datetime
import logger import logger
import re import re
import requests import requests
import team
import utils import utils
############### ###############
@ -100,6 +101,7 @@ def user_info():
raise WebException("User not found.") raise WebException("User not found.")
show_email = me if logged_in else False show_email = me if logged_in else False
user_in_team = in_team(user)
userdata = { userdata = {
"user_found": True, "user_found": True,
"name": user.name, "name": user.name,
@ -108,10 +110,13 @@ def user_info():
"admin": user.admin, "admin": user.admin,
"registertime": datetime.datetime.fromtimestamp(user.registertime).isoformat() + "Z", "registertime": datetime.datetime.fromtimestamp(user.registertime).isoformat() + "Z",
"me": me, "me": me,
"show_email": show_email "show_email": show_email,
"in_team": user_in_team
} }
if show_email: if show_email:
userdata["email"] = user.email userdata["email"] = user.email
if user_in_team:
userdata["team"] = team.get_team_info(tid=user.tid)
return { "success": 1, "user": userdata } return { "success": 1, "user": userdata }
################## ##################

View file

@ -3,7 +3,7 @@
<div class="col-sm-3 col-xs-12"> <div class="col-sm-3 col-xs-12">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-body"> <div class="panel-body">
<img src="//www.gravatar.com/avatar/?size=512" id="avatar" style="max-width:100%;" /> <img src="//www.gravatar.com/avatar/?size=512" id="avatar" style="width:100%;max-width:100%;" />
<small style="display:block;text-align:right;" ng-show="user['me']==true"><a href="http://en.gravatar.com/emails/" target="_blank">Edit Picture</a></small> <small style="display:block;text-align:right;" ng-show="user['me']==true"><a href="http://en.gravatar.com/emails/" target="_blank">Edit Picture</a></small>
<h2 style="margin:0px;font-weight:bold;font-size:2em;">{{ user.name }}</h2> <h2 style="margin:0px;font-weight:bold;font-size:2em;">{{ user.name }}</h2>
<small style="display:block;font-size:1.5em;color:#999;">@{{ user.username }}</small> <small style="display:block;font-size:1.5em;color:#999;">@{{ user.username }}</small>
@ -38,13 +38,29 @@
<div class="panel-heading"> <div class="panel-heading">
<h4 class="panel-title">Team Information</h4> <h4 class="panel-title">Team Information</h4>
</div> </div>
<div class="panel-body"> <div class="table-responsive" ng-show="user['in_team']==true">
<div ng-show="user['in_team']==true"> <table class="table table-bordered">
</div> <tr>
<div ng-show="user['in_team']!=true"> <th>Team Name</th>
<p>{{ user['me']==true ? "You're" : "This user is" }} not a part of a team.</p> <td>{{ user.team['teamname'] }}</td>
<a href="/team" class="btn btn-primary" ng-show="user['me']==true">Join or create one now &raquo;</a> </tr>
</div> <tr>
<th>School</th>
<td>{{ user.team['school'] }}</td>
</tr>
<tr>
<th>Points</th>
<td>{{ user.team['points'] }}</td>
</tr>
<tr>
<th>Rank</th>
<td>{{ user.team['place'] }}</td>
</tr>
</table>
</div>
<div class="panel-body" ng-show="user['in_team']!=true">
<p>{{ user['me']==true ? "You're" : "This user is" }} not a part of a team.</p>
<a href="/team" class="btn btn-primary" ng-show="user['me']==true">Join or create one now &raquo;</a>
</div> </div>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">

View file

@ -45,13 +45,44 @@
<div id="create_team_msg"></div> <div id="create_team_msg"></div>
</fieldset> </fieldset>
<fieldset class="container-fluid"> <fieldset class="container-fluid">
<div class="row"> <div class="col-md-6 col-md-offset-3 col-sm-10 col-sm-offset-1">
<div class="input-group"> <div class="panel panel-default">
<input class="form-control input-lg" type="text" required name="teamname" id="teamname" placeholder="Choose a team name..." autocomplete="off" /> <div class="panel-heading">
<span class="input-group-btn"> <h2 class="panel-title">Create a Team</h2>
<input type="hidden" id="_csrf" value="{{ csrf_token }}" /> </div>
<input type="submit" class="btn btn-success btn-lg" value="Create Team" /> <div class="panel-body">
</span> <form class="form-horizontal" onsubmit="login_form(); return false;" id="login_form">
<fieldset>
<div id="login_msg"></div>
</fieldset>
<fieldset class="container-fluid">
<div class="row">
<div class="col-sm-12 form-group">
<label class="col-sm-12" for="teamname"><small>Team Name</small></label>
<div class="col-sm-12">
<input class="form-control" type="text" required name="teamname" id="teamname" placeholder="Create a team name..." autocomplete="off" />
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 form-group">
<label class="col-sm-12" for="school"><small>School Name</small></label>
<div class="col-sm-12">
<input class="form-control" type="text" required name="school" id="school" placeholder="School Name" autocomplete="off" />
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 form-group">
<center>
<input type="hidden" id="_csrf" value="{{ csrf_token }}" />
<input type="submit" class="btn btn-success btn-lg" value="Create Team" />
</center>
</div>
</div>
</fieldset>
</form>
</div>
</div> </div>
</div> </div>
</fieldset> </fieldset>