Last active
August 29, 2015 14:09
-
-
Save petr-kalinin/aa6ac178edceaa8d6d64 to your computer and use it in GitHub Desktop.
Расчет шоколадок для школьников
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# -*- coding: utf-8 -*- | |
import sys,codecs | |
import urllib.request | |
import re | |
sys.stdout = codecs.getwriter('cp866')(sys.stdout.buffer, 'replace') | |
url = 'http://informatics.mccme.ru/course/view.php?id=526' | |
cookies = '' | |
def readUrl(url): | |
print('Retrieving %s...' % url, end=''); | |
sys.stdout.flush() | |
headers = {'Cookie': cookies} | |
req = urllib.request.Request(url, None, headers) | |
response = urllib.request.urlopen(req) | |
res = str(response.read(), encoding='utf-8', errors='replace') | |
print('Done') | |
return res | |
def getProbNum(monitor): | |
mainTable = re.search(r'<table class="BlueTable".*</table>', monitor, re.DOTALL) | |
assert(mainTable) | |
contests = mainTable.group(0).split('<tr class="Caption">') | |
result = [] | |
for contest in contests: | |
nc = contest.count("<tr>") | |
if nc > 0: | |
result.append(nc) | |
return result | |
def getProbNumNew(monitor): | |
mainTable = re.search(r'<table align=center class="BlueTable".*?</table>', monitor, re.DOTALL) | |
assert(mainTable) | |
contests = re.findall(r'<td colspan=(\d+)>', mainTable.group(0)) | |
#print("contests: ",contests) | |
result = list(map(int, contests)) | |
return result | |
def convertPoints(points): | |
result = [] | |
for tmp, bg, sc in points: | |
if (bg == 'ffff00'): | |
result.append(sc) | |
elif (bg == 'e1ffe2'): | |
result.append('*') | |
elif (bg == 'e10000'): | |
result.append('I') | |
elif (sc == ' '): | |
result.append('.') | |
else: | |
result.append('-') | |
return result | |
def getChildren(monitor): | |
mainTable = re.search(r'<table align=center class="BlueTable".*</table>', monitor, re.DOTALL) | |
assert(mainTable) | |
children = re.findall(r'<tr>\s*<td>[0-9-]+\s*<td><a href="/user/.*?</tr>', mainTable.group(0), re.DOTALL) | |
result = {} | |
for child in children: | |
name = re.search(r'<a href="/user/view.php\?id=\d+">([^<]*)</a>', child) | |
assert(name) | |
name = name.group(1) | |
points = re.findall(r'<td width="25"( bgcolor="#([0-9a-fA-F]*)")? >([-+0-9]*| )</td>',child) | |
if (name in result.keys()): | |
print('Contestant %s duplicates!' % name) | |
exit(1) | |
result[name] = convertPoints(points) | |
return result | |
def appendData(data, probNum, children): | |
for name, res in children.items(): | |
if (not name in data.keys()): | |
data[name] = [] | |
probI = 0 | |
groupI = 0 | |
add = [] | |
#print(name) | |
#print(probNum) | |
#print(res) | |
#print(len(res)) | |
#print(sum(probNum)) | |
for prob in res: | |
probI = probI + 1 | |
add.append(prob) | |
if (probI == probNum[groupI]): | |
#print("switch: ", add) | |
data[name].append(add) | |
probI = 0 | |
add = [] | |
groupI = groupI + 1 | |
#print(groupI) | |
assert(groupI == len(probNum)) | |
def parseContests(monitor, data): | |
probNum = getProbNumNew(monitor) | |
children = getChildren(monitor) | |
appendData(data, probNum, children) | |
def calcFull(cont): | |
result = 0 | |
for c in cont: | |
ok = True | |
for p in c: | |
if (p[0] != '+'): | |
ok = False | |
if ok: | |
result = result + 1 | |
fullCont = result | |
if (result > 0): | |
result = result // 3 + 1 | |
return (result, 'full%d' % fullCont) | |
def calcClear(cont): | |
result = 0 | |
for c in cont: | |
ok = True | |
for p in c: | |
if (p != '+'): | |
ok = False | |
if ok: | |
result = result + 1 | |
return (result, 'clear%d' % result) | |
def calcSemiClear(cont): | |
result = 0 | |
for c in cont: | |
ok = True | |
was1 = False | |
for p in c: | |
if (p == '+'): | |
pass | |
elif (p == '+1'): | |
was1 = True | |
else: | |
ok = False | |
if ok and was1: | |
result = result + 1 | |
choco = result // 2 | |
return (choco, 'semi%d' % result) | |
chocoFunc = [calcFull, calcClear, calcSemiClear] | |
def calcChocoForCont(cont): | |
result = [] | |
for func in chocoFunc: | |
result.append(func(cont)) | |
return result | |
def calcChoco(data): | |
choco = {} | |
totalChoco = [] | |
for name, cont in data.items(): | |
choco[name] = calcChocoForCont(cont) | |
total = 0 | |
for func in choco[name]: | |
total = total + func[0] | |
totalChoco.append((total, name)) | |
totalChoco.sort(reverse = True) | |
return choco, totalChoco | |
mainPage = readUrl(url) | |
monList = re.findall(r'"(http://informatics.mccme.ru/mod/monitor/view.php\?id=\d+)"', mainPage) | |
data = {} | |
for monPage in monList: | |
monitor = readUrl(monPage) | |
parseContests(monitor, data) | |
choco, totalChoco = calcChoco(data) | |
for tmp, name in totalChoco: | |
s = "%30s|" % name | |
t = '' | |
total = 0 | |
for func in choco[name]: | |
total = total + func[0] | |
t = t + '%d(%s) ' % func | |
s = s + '%d=%s|' % (total, t) | |
for c in data[name]: | |
for p in c: | |
if (p[0]=='+'): | |
if (len(p)>2): | |
s = s + 'Z' | |
else: | |
s = s + p[-1] | |
else: | |
s = s + p | |
s = s + '|' | |
print(s) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment