forked from Kattis/problemtools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.py
117 lines (97 loc) · 4.42 KB
/
template.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import os
import re
import os.path
import glob
import tempfile
import shutil
# For backwards compatibility, remove in bright and shiny future.
def detect_version(problemdir, problemtex):
# Check for 0.1 - lack of \problemname
if open(problemtex).read().find('\problemname') < 0:
return '0.1'
return '' # Current
class Template:
filename = None
problemset_cls = None
copy_cls = True
def __init__(self, problemdir, language='',
title='Problem Title', force_copy_cls=False):
if not os.path.isdir(problemdir):
raise Exception('%s is not a directory' % problemdir)
if problemdir[-1] == '/':
problemdir = problemdir[:-1]
stmtdir = os.path.join(problemdir, 'problem_statement')
langs = []
if glob.glob(os.path.join(stmtdir, 'problem.tex')):
langs.append('')
for f in glob.glob(os.path.join(stmtdir, 'problem.[a-z][a-z].tex')):
langs.append(re.search("problem.([a-z][a-z]).tex$", f).group(1))
if len(langs) == 0:
raise Exception('No problem statements available')
dotlang = ''
# If language unspec., use first available one (will be
# problem.tex if exists)
if language == '':
language = langs[0]
if language != '':
if len(language) != 2 or not language.isalpha():
raise Exception('Invalid language code "%s"' % language)
if language not in langs:
raise Exception('No problem statement for language "%s" available' % language)
dotlang = '.' + language
# Used in the template.tex variable substitution.
language = dotlang
problemtex = os.path.join(stmtdir, 'problem' + dotlang + '.tex')
if not os.path.isfile(problemtex):
raise Exception('Unable to find problem statement, was looking for "%s"' % problemtex)
templatefile = 'template.tex'
clsfile = 'problemset.cls'
timelim = 1 # Legacy for compatibility with v0.1
version = detect_version(problemdir, problemtex)
if version != '':
print 'Note: problem is in an old version (%s) of problem format, you should consider updating it' % version
templatefile = 'template_%s.tex' % version
clsfile = 'problemset_%s.cls' % version
templatepaths = [os.path.join(os.path.dirname(__file__), 'templates/latex'),
'/usr/local/kattis/data/templates/latex']
templatepath = None
for p in templatepaths:
if os.path.isdir(p) and os.path.isfile(os.path.join(p, templatefile)):
templatepath = p
break
if templatepath == None:
raise Exception('Could not find directory with latex template "%s"' % templatefile)
basedir = os.path.dirname(problemdir)
shortname = os.path.basename(problemdir)
samples = [os.path.splitext(os.path.basename(f))[0] for f in sorted(glob.glob(os.path.join(problemdir, 'data', 'sample', '*.in')))]
self.problemset_cls = os.path.join(basedir, 'problemset.cls')
if os.path.isfile(self.problemset_cls) and not force_copy_cls:
print '%s exists, will not copy it -- in case of weirdness this is likely culprit' % self.problemset_cls
self.copy_cls = False
if self.copy_cls:
shutil.copyfile(os.path.join(templatepath, clsfile), self.problemset_cls)
(templout, self.filename) = tempfile.mkstemp(suffix='.tex', dir=basedir)
templin = open(os.path.join(templatepath, templatefile))
for line in templin:
try:
out = line % locals()
os.write(templout, out)
except:
# This is a bit ugly I guess
for sample in samples:
out = line % locals()
os.write(templout, out)
os.close(templout)
templin.close()
def get_file_name(self):
assert os.path.isfile(self.filename)
return self.filename
def cleanup(self):
if self.problemset_cls is not None and self.copy_cls and os.path.isfile(self.problemset_cls):
os.remove(self.problemset_cls)
if self.filename is not None:
for f in glob.glob(os.path.splitext(self.filename)[0] + '.*'):
if os.path.isfile(f):
os.remove(f)
def __del__(self):
self.cleanup()