205 lines
7.5 KiB
Python
205 lines
7.5 KiB
Python
#encoding: utf8
|
|
|
|
from flask import request, abort
|
|
from flask.ext.admin import BaseView, expose
|
|
from bson.objectid import ObjectId
|
|
import sys
|
|
import random
|
|
from operator import attrgetter
|
|
sys.path.append('..')
|
|
from game_record.models import GameRecord
|
|
from game.models import Game
|
|
from namelist.models import NameList
|
|
from forms import BallotForm, RankForm
|
|
import json
|
|
|
|
class Team:
|
|
def __init__(self, namelist):
|
|
self.namelist = namelist
|
|
self.total_score = 0
|
|
self.total_sscore = 0
|
|
self.total_diff = 0
|
|
self.againsts = []
|
|
|
|
def get_company(self):
|
|
return self.namelist.company.strip()
|
|
|
|
def has_competed_with(self, against):
|
|
if against in self.againsts:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def add_score(self, score):
|
|
self.total_score += score
|
|
|
|
def add_diff(self, diff):
|
|
self.total_diff += diff
|
|
|
|
def add_against(self, against):
|
|
self.againsts.append(against)
|
|
|
|
def compute_sscore(self):
|
|
for a in self.againsts:
|
|
#计算小分时,弃权所得负分不影响对手小分
|
|
if a.total_score >= 0:
|
|
self.total_sscore += a.total_score
|
|
|
|
class Company:
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.teams = []
|
|
self.total_score = 0
|
|
self.total_sscore = 0
|
|
self.total_diff = 0
|
|
|
|
def add_team(self, team):
|
|
self.teams.append(team)
|
|
|
|
def compute_score(self):
|
|
for team in self.teams:
|
|
self.total_score += team.total_score
|
|
self.total_sscore += team.total_sscore
|
|
self.total_diff += team.total_diff
|
|
|
|
class BallotView(BaseView):
|
|
round = 0
|
|
@expose('/', methods=['GET', 'POST'])
|
|
def index(self):
|
|
form = BallotForm(request.form)
|
|
form.game.choices = [(str(Game.objects(name=x).first().id), x) for x in Game.objects.distinct('name')]
|
|
if request.method == 'POST' and form.validate():
|
|
game = form.game.data
|
|
ballot_type = form.ballot_type.data
|
|
results = self.ballot(game, ballot_type)
|
|
self._template_args['ballot_results'] = results
|
|
self._template_args['round'] = self.round
|
|
return self.render('ballot.html', form=form)
|
|
|
|
|
|
def first_stage(self, game, ballot_type):
|
|
"""首轮抽签"""
|
|
results = []
|
|
teams = list(NameList.objects(game=game).order_by('no').all())
|
|
team_count = len(teams) / 2 * 2
|
|
if ballot_type == 'sequence':
|
|
for i in range(0, team_count, 2):
|
|
result = dict(desk_no=i/2+1, red=teams[i], blue=teams[i+1])
|
|
results.append(result)
|
|
return results
|
|
else:
|
|
return self.ballot_by_score(game, ballot_type)
|
|
|
|
def ballot_by_score(self, game, ballot_type):
|
|
"""按照比分抽签"""
|
|
results = []
|
|
teams = RankView.get_ranked_teams(game)
|
|
while len(teams) > 1:
|
|
#处理后四名出现同一个单位的情况
|
|
if len(teams) == 4 and (teams[0].get_company() == teams[1].get_company() or teams[2].get_company() == teams[3].get_company()):
|
|
results.append(dict(desk_no=len(results)+1, red=teams[0].namelist, blue=teams[2].namelist))
|
|
results.append(dict(desk_no=len(results)+1, red=teams[1].namelist, blue=teams[3].namelist))
|
|
break
|
|
t1 = teams[0]
|
|
for t2 in teams[1:]:
|
|
#找到不同单位并且没有比赛过的对手
|
|
if t1.get_company() != t2.get_company() and not t1.has_competed_with(t2):
|
|
break
|
|
results.append(dict(desk_no=len(results)+1, red=t1.namelist, blue=t2.namelist))
|
|
teams.remove(t1)
|
|
teams.remove(t2)
|
|
return results
|
|
|
|
def ballot(self, game, ballot_type):
|
|
"""抽签算法"""
|
|
if GameRecord.objects(game=game).count() == 0:
|
|
self.round = 1
|
|
return self.first_stage(game, ballot_type)
|
|
else:
|
|
self.round = max(GameRecord.objects(game=game).distinct('round')) + 1
|
|
return self.ballot_by_score(game, ballot_type)
|
|
|
|
class RankView(BaseView):
|
|
@expose('/', methods=['GET', 'POST'])
|
|
def index(self):
|
|
form = RankForm(request.form)
|
|
form.game.choices = [(str(Game.objects(name=x).first().id), x) for x in Game.objects.distinct('name')]
|
|
return self.render('rank.html', form=form)
|
|
|
|
@expose('/team_rank_ajax')
|
|
def team_rank_ajax(self):
|
|
results = []
|
|
game = request.args.get('game', '')
|
|
ranked_teams = self.get_ranked_teams(game)
|
|
for index, team in enumerate(ranked_teams):
|
|
record = {}
|
|
record['rank'] = index + 1
|
|
record['rank_type'] = unicode(team.namelist)
|
|
record['total_score'] = team.total_score
|
|
record['total_sscore'] = team.total_sscore
|
|
record['total_diff'] = team.total_diff
|
|
results.append(record)
|
|
|
|
return json.dumps(results)
|
|
|
|
@expose('/company_rank_ajax')
|
|
def company_rank_ajax(self):
|
|
game = request.args.get('game', '')
|
|
ranked_companys = self.get_ranked_companys(game)
|
|
results = []
|
|
for index, c in enumerate(ranked_companys):
|
|
record = {}
|
|
record['rank'] = index + 1
|
|
record['rank_type'] = c.name
|
|
record['total_score'] = c.total_score
|
|
record['total_sscore'] = c.total_sscore
|
|
record['total_diff'] = c.total_diff
|
|
results.append(record)
|
|
return json.dumps(results)
|
|
|
|
@staticmethod
|
|
def get_ranked_teams(game):
|
|
teams = {x:Team(x) for x in NameList.objects(game=game)}
|
|
for record in GameRecord.objects(game=game):
|
|
if record.result == u'红方胜':
|
|
teams[record.red].add_score(2)
|
|
teams[record.red].add_diff(record.diff)
|
|
teams[record.blue].add_diff(0 - record.diff)
|
|
elif record.result == u'蓝方胜':
|
|
teams[record.blue].add_score(2)
|
|
teams[record.blue].add_diff(record.diff)
|
|
teams[record.red].add_diff(0 - record.diff)
|
|
elif record.result == u'平局':
|
|
teams[record.blue].add_score(1)
|
|
teams[record.red].add_score(1)
|
|
elif record.result == u'红方弃权':
|
|
teams[record.red].add_score(-1)
|
|
teams[record.red].add_diff(-6)
|
|
teams[record.blue].add_score(2)
|
|
teams[record.blue].add_diff(6)
|
|
elif record.result == u'蓝方弃权':
|
|
teams[record.blue].add_score(-1)
|
|
teams[record.blue].add_diff(-6)
|
|
teams[record.red].add_score(2)
|
|
teams[record.red].add_diff(6)
|
|
teams[record.red].add_against(teams[record.blue])
|
|
teams[record.blue].add_against(teams[record.red])
|
|
|
|
for team in teams.values():
|
|
team.compute_sscore()
|
|
|
|
team_list = teams.values()
|
|
random.shuffle(team_list)
|
|
return sorted(team_list, key=attrgetter('total_score', 'total_sscore', 'total_diff'), reverse=True)
|
|
|
|
@staticmethod
|
|
def get_ranked_companys(game):
|
|
companys = {}
|
|
for team in RankView.get_ranked_teams(game):
|
|
company_name = team.get_company()
|
|
if company_name not in companys:
|
|
companys[company_name] = Company(company_name)
|
|
companys[company_name].add_team(team)
|
|
|
|
[c.compute_score() for c in companys.values()]
|
|
return sorted(companys.values(), key=attrgetter('total_score', 'total_sscore', 'total_diff'), reverse=True) |