source: pycodeshooter/trunk/score/score.cgi @ 132

Revision 132, 2.7 KB checked in by atzm, 12 years ago (diff)
  • add score board
  • Property svn:executable set to *
  • Property svn:keywords set to Id
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4#  Copyright (C) 2012 by Atzm WATANABE <atzm@atzm.org>
5#
6#  This program is free software; you can redistribute it and/or modify it
7#  under the terms of the GNU General Public License (version 2) as
8#  published by the Free Software Foundation.  It is distributed in the
9#  hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
10#  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11#  PURPOSE.  See the GNU General Public License for more details.
12#
13# $Id$
14#
15
16from __future__ import with_statement
17
18import os.path
19import sys
20import cgi
21import json
22import fcntl
23import urllib
24import ConfigParser
25
26
27class ScoreBoard(object):
28    def __init__(self, path, limit):
29        self._path = path
30        self._limit = limit
31        self._data = []
32        self._fp = None
33
34    def get(self):
35        return self._data[:]
36
37    def open(self, mode='a+', lock=fcntl.LOCK_EX):
38        self._fp = open(self._path, mode)
39        fcntl.flock(self._fp, lock)
40        return self
41
42    def close(self):
43        self._fp.close()
44        return self
45
46    def read(self):
47        self._fp.seek(0, 0)
48        raw = self._fp.read()
49        if raw:
50            self._data = json.loads(raw)
51        return self
52
53    def write(self):
54        raw = json.dumps(self._data, ensure_ascii=False).encode('utf-8')
55        self._fp.seek(0, 0)
56        self._fp.truncate(0)
57        self._fp.write(raw + '\n')
58        return self
59
60    def insert(self, name, value, stime, etime):
61        self._data.append({
62            'name':  name,
63            'value': value,
64            'stime': stime,
65            'etime': etime,
66        })
67
68        self.sort()
69
70        if self._limit < len(self._data):
71            self._data.pop(-1)
72
73        return self
74
75    def sort(self):
76        self._data.sort(lambda a, b: cmp(a['value'], b['value']), reverse=True)
77        return self
78
79
80def main():
81    config = ConfigParser.SafeConfigParser()
82    config.read('score.conf')
83
84    path = os.path.abspath(os.path.expanduser(config.get('DEFAULT', 'path')))
85    limit = config.getint('DEFAULT', 'limit')
86    board = ScoreBoard(path, limit)
87
88    form = cgi.FieldStorage()
89
90    try:
91        stime = int(form.getfirst('stime'))
92        etime = int(form.getfirst('etime'))
93        score = int(form.getfirst('value'))
94        name = urllib.unquote(form.getfirst('name')).decode('utf-8')
95        if 20 < len(name):
96            raise ValueError('name is too long')
97        board.open().read().insert(name, score, stime, etime).write().close()
98    except:
99        board.open().read().close()
100
101    sys.stdout.write('Content-type: application/json; charset=UTF-8\r\n\r\n')
102    print(json.dumps(board.get(), ensure_ascii=False).encode('utf-8'))
103
104
105if __name__ == '__main__':
106    main()
Note: See TracBrowser for help on using the repository browser.