|
|
|
|
1
|
-#!/usr/bin/env perl
|
|
|
2
|
-# encoding: UTF-8
|
|
|
|
|
1
|
+#!/usr/bin/env python
|
3
|
|
2
|
|
4
|
# Ruokalistaparseri
|
3
|
# Ruokalistaparseri
|
5
|
# Copyright (c) 2016 Toni Fadjukoff
|
4
|
# Copyright (c) 2016 Toni Fadjukoff
|
|
|
|
|
9
|
# 2011-2016 Toni Fadjukoff
|
8
|
# 2011-2016 Toni Fadjukoff
|
10
|
# This is Public Domain
|
9
|
# This is Public Domain
|
11
|
|
10
|
|
|
|
11
|
+import sys
|
|
|
12
|
+print(sys.version)
|
|
|
13
|
+
|
12
|
day_names = [ "Maanantai", "Tiistai", "Keskiviikko", "Torstai",
|
14
|
day_names = [ "Maanantai", "Tiistai", "Keskiviikko", "Torstai",
|
13
|
"Perjantai", "Lauantai", "Sunnuntai" ]
|
15
|
"Perjantai", "Lauantai", "Sunnuntai" ]
|
14
|
|
16
|
|
|
|
|
|
79
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fi" lang="fi">
|
81
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fi" lang="fi">
|
80
|
<head>
|
82
|
<head>
|
81
|
<title>Ruokalistat</title>
|
83
|
<title>Ruokalistat</title>
|
82
|
- <link rel="stylesheet" type="text/css" href="{global_prefix}/ruoka.css" />
|
|
|
|
|
84
|
+ <link rel="stylesheet" type="text/css" href="{resources_prefix}ruoka.css" />
|
83
|
</head>
|
85
|
</head>
|
84
|
<body>
|
86
|
<body>
|
85
|
|
87
|
|
|
|
|
|
88
|
</div>
|
90
|
</div>
|
89
|
|
91
|
|
90
|
<form method="get" action="/cgi-bin/food.cgi">
|
92
|
<form method="get" action="/cgi-bin/food.cgi">
|
91
|
-'''.format(global_prefix=global_prefix)
|
|
|
|
|
93
|
+'''
|
92
|
|
94
|
|
93
|
file_footer = """
|
95
|
file_footer = """
|
94
|
- <div class="footer">Päivitetty {stamp}"
|
|
|
|
|
96
|
+ <div class="footer">Päivitetty {stamp}
|
95
|
<input type="submit\" value=\"Päivitä nyt\" />
|
97
|
<input type="submit\" value=\"Päivitä nyt\" />
|
96
|
- / Palaute <a href=\"mailto:lamperi+pna\@gmail.com\">lamperi+pna\@gmail.com</a>
|
|
|
97
|
- / <a href="{global_prefix}/code.html\">Koodit täältä</a>
|
|
|
98
|
- / <a href="{global_prefix}/pna.html\">Mikä on PNA?</a>
|
|
|
|
|
98
|
+ / Palaute <a href=\"mailto:lamperi+pna@gmail.com\">lamperi+pna@gmail.com</a>
|
|
|
99
|
+ / <a href="{{resources_prefix}}code.html\">Koodit täältä</a>
|
|
|
100
|
+ / <a href="{{resources_prefix}}pna.html\">Mikä on PNA?</a>
|
99
|
</div>
|
101
|
</div>
|
100
|
</form>
|
102
|
</form>
|
101
|
</body>
|
103
|
</body>
|
102
|
</html>
|
104
|
</html>
|
103
|
-""".format(global_prefix=global_prefix, stamp=time.strftime("%d.%m.%Y %H:%M:%S"))
|
|
|
|
|
105
|
+""".format(stamp=time.strftime("%d.%m.%Y %H:%M:%S"))
|
|
|
106
|
+print(file_footer)
|
104
|
|
107
|
|
105
|
def find_last_day_with_foods(restaurants):
|
108
|
def find_last_day_with_foods(restaurants):
|
106
|
last_day = 0
|
109
|
last_day = 0
|
|
|
|
|
124
|
fout.write("<a href=\"table.html\">Taulukko</a>")
|
127
|
fout.write("<a href=\"table.html\">Taulukko</a>")
|
125
|
fout.write("</span>\n")
|
128
|
fout.write("</span>\n")
|
126
|
|
129
|
|
127
|
-def write_prefix_header(fout, prefix, day):
|
|
|
|
|
130
|
+def write_prefix_header(fout, prefix, day, resources_prefix):
|
128
|
day = "table" if day == 0 else day
|
131
|
day = "table" if day == 0 else day
|
129
|
fout.write("<span class=\"location\">")
|
132
|
fout.write("<span class=\"location\">")
|
130
|
if prefix == "":
|
133
|
if prefix == "":
|
131
|
fout.write("Kaikki ")
|
134
|
fout.write("Kaikki ")
|
132
|
else:
|
135
|
else:
|
133
|
- fout.write("<a href=\"{global_prefix}/{day}.html\">Kaikki</a> ".format(global_prefix=global_prefix, day=day))
|
|
|
|
|
136
|
+ fout.write("<a href=\"{resources_prefix}{day}.html\">Kaikki</a> ".format(resources_prefix=resources_prefix, day=day))
|
134
|
if prefix == "tay/":
|
137
|
if prefix == "tay/":
|
135
|
fout.write("TaY ")
|
138
|
fout.write("TaY ")
|
136
|
else:
|
139
|
else:
|
137
|
- fout.write("<a href=\"{global_prefix}/tay/{day}.html\">TaY</a> ".format(global_prefix=global_prefix, day=day))
|
|
|
|
|
140
|
+ fout.write("<a href=\"{resources_prefix}tay/{day}.html\">TaY</a> ".format(resources_prefix=resources_prefix, day=day))
|
138
|
if prefix == "tays/":
|
141
|
if prefix == "tays/":
|
139
|
fout.write("TAYS ")
|
142
|
fout.write("TAYS ")
|
140
|
else:
|
143
|
else:
|
141
|
- fout.write("<a href=\"{global_prefix}/tays/{day}.html\">TAYS</a> ".format(global_prefix=global_prefix, day=day))
|
|
|
|
|
144
|
+ fout.write("<a href=\"{resources_prefix}tays/{day}.html\">TAYS</a> ".format(resources_prefix=resources_prefix, day=day))
|
142
|
if prefix == "tty/":
|
145
|
if prefix == "tty/":
|
143
|
fout.write("TTY ")
|
146
|
fout.write("TTY ")
|
144
|
else:
|
147
|
else:
|
145
|
- fout.write("<a href=\"{global_prefix}/tty/{day}.html\">TTY</a> ".format(global_prefix=global_prefix, day=day))
|
|
|
|
|
148
|
+ fout.write("<a href=\"{resources_prefix}tty/{day}.html\">TTY</a> ".format(resources_prefix=resources_prefix, day=day))
|
146
|
fout.write("</span>\n")
|
149
|
fout.write("</span>\n")
|
147
|
|
150
|
|
148
|
-def write_day(day, header, outfname, last_day, restaurants, prefix):
|
|
|
149
|
- with open(outfname, "w") as fout:
|
|
|
150
|
- fout.write("{file_header}<h1>{header}</h1>\n".format(file_header=file_header, header=header))
|
|
|
|
|
151
|
+def write_day(day, header, outfname, last_day, restaurants, prefix, resources_prefix):
|
|
|
152
|
+ with open(outfname, "w", encoding="utf-8") as fout:
|
|
|
153
|
+ import types
|
|
|
154
|
+ def write(self, writable):
|
|
|
155
|
+ print("Writing {}: {}".format(type(writable), writable))
|
|
|
156
|
+ self.write_orig(writable)
|
|
|
157
|
+ fout.write_orig = fout.write
|
|
|
158
|
+ fout.write = types.MethodType(write, fout)
|
|
|
159
|
+ fout.write(file_header.format(resources_prefix=resources_prefix))
|
|
|
160
|
+ fout.write("<h1>{header}</h1>\n".format(header=header))
|
151
|
# print weekday links
|
161
|
# print weekday links
|
152
|
fout.write("<div class=\"title\">\n")
|
162
|
fout.write("<div class=\"title\">\n")
|
153
|
write_days_header(fout, day, last_day)
|
163
|
write_days_header(fout, day, last_day)
|
|
|
|
|
156
|
fout.write("<input type=\"checkbox\" name=\"allergy_{a}\" id=\"allergy_{a}\" onclick=\"highlight()\" />".format(a=a))
|
166
|
fout.write("<input type=\"checkbox\" name=\"allergy_{a}\" id=\"allergy_{a}\" onclick=\"highlight()\" />".format(a=a))
|
157
|
fout.write("<span title=\"{allergy_description}\">{a}</span>".format(allergy_description=allergy_descriptions[a], a=a))
|
167
|
fout.write("<span title=\"{allergy_description}\">{a}</span>".format(allergy_description=allergy_descriptions[a], a=a))
|
158
|
fout.write("</span>\n")
|
168
|
fout.write("</span>\n")
|
159
|
- write_prefix_header(fout, prefix, day+1);
|
|
|
|
|
169
|
+ write_prefix_header(fout, prefix, day+1, resources_prefix);
|
160
|
fout.write("</div>\n")
|
170
|
fout.write("</div>\n")
|
161
|
|
171
|
|
162
|
# print foods
|
172
|
# print foods
|
|
|
|
|
167
|
eatable_food_numbers[a] = []
|
177
|
eatable_food_numbers[a] = []
|
168
|
maybe_eatable_food_numbers[a] = []
|
178
|
maybe_eatable_food_numbers[a] = []
|
169
|
css_class = "left"
|
179
|
css_class = "left"
|
170
|
- fout.write("div class=\"foods\"><div class=\"{css_class}\">\n".format(css_class=css_class))
|
|
|
|
|
180
|
+ fout.write("<div class=\"foods\"><div class=\"{css_class}\">\n".format(css_class=css_class))
|
171
|
for r in restaurants:
|
181
|
for r in restaurants:
|
172
|
title, open_hours, week, week_foods, info = r
|
182
|
title, open_hours, week, week_foods, info = r
|
173
|
title2, url, lazy_allergies, info_class = info[0:4]
|
183
|
title2, url, lazy_allergies, info_class = info[0:4]
|
|
|
|
|
192
|
continue
|
202
|
continue
|
193
|
fout.write("<ul class=\"food\">\n")
|
203
|
fout.write("<ul class=\"food\">\n")
|
194
|
for food in week_foods[day]:
|
204
|
for food in week_foods[day]:
|
195
|
- output = ""
|
|
|
|
|
205
|
+ output = []
|
196
|
total_allergies = {}
|
206
|
total_allergies = {}
|
197
|
maybe_allergies = {}
|
207
|
maybe_allergies = {}
|
198
|
for a in allergies:
|
208
|
for a in allergies:
|
|
|
|
|
232
|
allergy = re.sub("[, ]+$", "", allergy)
|
242
|
allergy = re.sub("[, ]+$", "", allergy)
|
233
|
part = "{food} ({allergy})".format(food=food, allergy=allergy)
|
243
|
part = "{food} ({allergy})".format(food=food, allergy=allergy)
|
234
|
|
244
|
|
235
|
- if output != "" and not fries:
|
|
|
236
|
- output += "<br />\n"
|
|
|
|
|
245
|
+ if output and not fries:
|
|
|
246
|
+ output.append("<br />\n")
|
237
|
|
247
|
|
238
|
match = re.search("Saatavana myös: (.*)", part)
|
248
|
match = re.search("Saatavana myös: (.*)", part)
|
239
|
if match:
|
249
|
if match:
|
|
|
|
|
250
|
text = match.group(1)
|
260
|
text = match.group(1)
|
251
|
allergy = match.group(2)
|
261
|
allergy = match.group(2)
|
252
|
if fries:
|
262
|
if fries:
|
253
|
- output += ", {text}".format(text=text)
|
|
|
|
|
263
|
+ output.append(", {text}".format(text=text))
|
254
|
else:
|
264
|
else:
|
255
|
- output += "{text} <span class=\"allergy\">{allergy}</span>".format(text=text, allergy=allergy)
|
|
|
|
|
265
|
+ output.append("{text} <span class=\"allergy\">{allergy}</span>".format(text=text, allergy=allergy))
|
256
|
allergy = re.sub(r"^\((.*)\)$", r"\1", allergy)
|
266
|
allergy = re.sub(r"^\((.*)\)$", r"\1", allergy)
|
257
|
allergy = re.sub(" *eriks: ", "", allergy)
|
267
|
allergy = re.sub(" *eriks: ", "", allergy)
|
258
|
this_allergies = set()
|
268
|
this_allergies = set()
|
|
|
|
|
277
|
for a in allergies:
|
287
|
for a in allergies:
|
278
|
maybe_allergies[a] += 1
|
288
|
maybe_allergies[a] += 1
|
279
|
|
289
|
|
280
|
- output += part
|
|
|
|
|
290
|
+ output.append(part)
|
281
|
allergy_output = ""
|
291
|
allergy_output = ""
|
282
|
for a in allergies:
|
292
|
for a in allergies:
|
283
|
if total_allergies[a] == part_count:
|
293
|
if total_allergies[a] == part_count:
|
284
|
eatable_food_numbers[a].append(foodnum)
|
294
|
eatable_food_numbers[a].append(foodnum)
|
285
|
elif maybe_allergies[a]== part_count:
|
295
|
elif maybe_allergies[a]== part_count:
|
286
|
maybe_eatable_food_numbers[a].append(foodnum)
|
296
|
maybe_eatable_food_numbers[a].append(foodnum)
|
287
|
- fout.write(" <li id=\"f{foodnum}\">{output}</li>\n".format(foodnum=foodnum, output=output))
|
|
|
|
|
297
|
+ fout.write(" <li id=\"f{foodnum}\">{output}</li>\n".format(foodnum=foodnum, output="".join(output)))
|
288
|
foodnum += 1
|
298
|
foodnum += 1
|
289
|
fout.write("</ul>\n")
|
299
|
fout.write("</ul>\n")
|
290
|
# write allergy scripts
|
300
|
# write allergy scripts
|
291
|
- fout.write('<script type="text/javascript" src="{global_prefix}/ruoka.js"></script>'.format(global_prefix=global_prefix))
|
|
|
292
|
- fout.write('<script type="text/javascript">')
|
|
|
293
|
- fout.write("var eatable_foods = [];")
|
|
|
294
|
- fout.write("var maybe_eatable_foods = [];")
|
|
|
|
|
301
|
+ fout.write('<script type="text/javascript" src="{resources_prefix}ruoka.js"></script>'.format(resources_prefix=resources_prefix))
|
|
|
302
|
+ fout.write('<script type="text/javascript">\n')
|
|
|
303
|
+ fout.write("var eatable_foods = [];\n")
|
|
|
304
|
+ fout.write("var maybe_eatable_foods = [];\n")
|
295
|
for a in allergies:
|
305
|
for a in allergies:
|
296
|
fout.write("eatable_foods[\"{a}\"] = [{eatable_food_number}];\n".format(a=a, eatable_food_number=",".join(str(e) for e in eatable_food_numbers[a])))
|
306
|
fout.write("eatable_foods[\"{a}\"] = [{eatable_food_number}];\n".format(a=a, eatable_food_number=",".join(str(e) for e in eatable_food_numbers[a])))
|
297
|
fout.write("maybe_eatable_foods[\"{a}\"] = [{maybe_eatable_food_number}];\n".format(a=a, maybe_eatable_food_number=",".join(str(e) for e in maybe_eatable_food_numbers[a])))
|
307
|
fout.write("maybe_eatable_foods[\"{a}\"] = [{maybe_eatable_food_number}];\n".format(a=a, maybe_eatable_food_number=",".join(str(e) for e in maybe_eatable_food_numbers[a])))
|
|
|
|
|
300
|
fout.write("var food_count = $foodnum;\n")
|
310
|
fout.write("var food_count = $foodnum;\n")
|
301
|
fout.write("window.onload = function() { set_allergies(); show_warning(); };\n")
|
311
|
fout.write("window.onload = function() { set_allergies(); show_warning(); };\n")
|
302
|
fout.write("</script>\n")
|
312
|
fout.write("</script>\n")
|
303
|
- fout.write("</div></div>{file_footer}".format(file_footer=file_footer))
|
|
|
|
|
313
|
+ fout.write("</div></div>{file_footer}".format(file_footer=file_footer.format(resources_prefix=resources_prefix)))
|
304
|
|
314
|
|
305
|
-def write_all_days(restaurants, prefix, title):
|
|
|
|
|
315
|
+def write_all_days(restaurants, prefix, title, resources_prefix):
|
306
|
try:
|
316
|
try:
|
307
|
os.mkdir(prefix)
|
317
|
os.mkdir(prefix)
|
308
|
except OSError as err:
|
318
|
except OSError as err:
|
|
|
|
|
318
|
continue
|
328
|
continue
|
319
|
header = "{day_name} - {title} vko {max_week}{max_week_daterange}".format(day_name=day_names[day], title=title,
|
329
|
header = "{day_name} - {title} vko {max_week}{max_week_daterange}".format(day_name=day_names[day], title=title,
|
320
|
max_week=max_week, max_week_daterange=max_week_daterange)
|
330
|
max_week=max_week, max_week_daterange=max_week_daterange)
|
321
|
- write_day(day, header, outfname, last_day, restaurants, prefix)
|
|
|
|
|
331
|
+ write_day(day, header, outfname, last_day, restaurants, prefix, resources_prefix)
|
322
|
|
332
|
|
323
|
-def write_table(restaurants, prefix, title):
|
|
|
|
|
333
|
+def write_table(restaurants, prefix, title, resources_prefix):
|
324
|
last_day = find_last_day_with_foods(restaurants);
|
334
|
last_day = find_last_day_with_foods(restaurants);
|
325
|
outfname = "{prefix}table.html".format(prefix=prefix)
|
335
|
outfname = "{prefix}table.html".format(prefix=prefix)
|
326
|
with open(outfname, "w") as fout:
|
336
|
with open(outfname, "w") as fout:
|
|
|
|
|
329
|
fout.write("<div class=\"title\">\n")
|
339
|
fout.write("<div class=\"title\">\n")
|
330
|
|
340
|
|
331
|
write_days_header(fout, -1, last_day)
|
341
|
write_days_header(fout, -1, last_day)
|
332
|
- write_prefix_header(fout, prefix, 0)
|
|
|
|
|
342
|
+ write_prefix_header(fout, prefix, 0, resources_prefix)
|
333
|
fout.write("</div><table border=\"1\"><tr><th>Päivä</th>")
|
343
|
fout.write("</div><table border=\"1\"><tr><th>Päivä</th>")
|
334
|
for r in restaurants:
|
344
|
for r in restaurants:
|
335
|
(title, open_hours, week, week_foods, info) = r
|
345
|
(title, open_hours, week, week_foods, info) = r
|
|
|
|
|
349
|
else:
|
359
|
else:
|
350
|
fout.write("<td></td>\n")
|
360
|
fout.write("<td></td>\n")
|
351
|
fout.write("</tr\n")
|
361
|
fout.write("</tr\n")
|
352
|
- fout.write("</table>{file_footer}".format(file_footer=file_footer))
|
|
|
|
|
362
|
+ fout.write("</table>{file_footer}".format(file_footer=file_footer.format(resources_prefix=resources_prefix)))
|
353
|
|
363
|
|
354
|
def get_restaurants_sorted(restaurants):
|
364
|
def get_restaurants_sorted(restaurants):
|
355
|
# consider writing comparator
|
365
|
# consider writing comparator
|
|
|
|
|
361
|
if r[4][3] == "right":
|
371
|
if r[4][3] == "right":
|
362
|
out.append(r)
|
372
|
out.append(r)
|
363
|
for r in restaurants:
|
373
|
for r in restaurants:
|
364
|
- if r[4][3] == "middle" and not re.search("TAMK", r[4][1]):
|
|
|
|
|
374
|
+ if r[4][3] == "middle" and not re.search("TAMK", r[4][0]):
|
365
|
out.append(r)
|
375
|
out.append(r)
|
366
|
for r in restaurants:
|
376
|
for r in restaurants:
|
367
|
- if r[4][3] == "middle" and re.search("TAMK", r[4][1]):
|
|
|
|
|
377
|
+ if r[4][3] == "middle" and re.search("TAMK", r[4][0]):
|
368
|
out.append(r)
|
378
|
out.append(r)
|
369
|
return out
|
379
|
return out
|
370
|
|
380
|
|
371
|
def get_restaurants_with_prefix(prefix, restaurants):
|
381
|
def get_restaurants_with_prefix(prefix, restaurants):
|
372
|
out = []
|
382
|
out = []
|
373
|
for r in restaurants:
|
383
|
for r in restaurants:
|
374
|
- if re.search(prefix, r[4][1]):
|
|
|
|
|
384
|
+ if re.search(prefix, r[4][0]):
|
375
|
out.append(r)
|
385
|
out.append(r)
|
376
|
return get_restaurants_sorted(out)
|
386
|
return get_restaurants_sorted(out)
|
377
|
|
387
|
|
378
|
-tty_title = "TTY:n ruokalistat";
|
|
|
379
|
-tty = get_restaurants_with_prefix("TTY", unordered);
|
|
|
380
|
-write_all_days(tty, "tty/", tty_title);
|
|
|
381
|
-write_table(tty, "tty/", tty_title);
|
|
|
|
|
388
|
+tty_title = "TTY:n ruokalistat"
|
|
|
389
|
+tty = get_restaurants_with_prefix("TTY", unordered)
|
|
|
390
|
+write_all_days(tty, "tty/", tty_title, "../")
|
|
|
391
|
+write_table(tty, "tty/", tty_title, "../")
|
382
|
|
392
|
|
383
|
-tay_title = "Tampereen yliopiston ruokalistat";
|
|
|
384
|
-tay = get_restaurants_with_prefix("TaY", unordered);
|
|
|
385
|
-write_all_days(tay, "tay/", tay_title);
|
|
|
386
|
-write_table(tay, "tay/", tay_title);
|
|
|
|
|
393
|
+tay_title = "Tampereen yliopiston ruokalistat"
|
|
|
394
|
+tay = get_restaurants_with_prefix("TaY", unordered)
|
|
|
395
|
+write_all_days(tay, "tay/", tay_title, "../")
|
|
|
396
|
+write_table(tay, "tay/", tay_title, "../")
|
387
|
|
397
|
|
388
|
-tays_title = "TAYS:n ruokalistat";
|
|
|
389
|
-tays = get_restaurants_with_prefix("TAYS", unordered);
|
|
|
390
|
-write_all_days(tays, "tays/", tays_title);
|
|
|
391
|
-write_table(tays, "tays/", tays_title);
|
|
|
|
|
398
|
+tays_title = "TAYS:n ruokalistat"
|
|
|
399
|
+tays = get_restaurants_with_prefix("TAYS", unordered)
|
|
|
400
|
+write_all_days(tays, "tays/", tays_title, "../")
|
|
|
401
|
+write_table(tays, "tays/", tays_title, "../")
|
392
|
|
402
|
|
393
|
for r in unordered:
|
403
|
for r in unordered:
|
394
|
if re.search(r"^\(TaY\)", r[0]):
|
404
|
if re.search(r"^\(TaY\)", r[0]):
|
|
|
|
|
404
|
#fusion = splice(@all_restaurants, 1, 1);
|
414
|
#fusion = splice(@all_restaurants, 1, 1);
|
405
|
#splice(@all_restaurants, 4, 0, @fusion);
|
415
|
#splice(@all_restaurants, 4, 0, @fusion);
|
406
|
|
416
|
|
407
|
-write_all_days(all_restaurants, "", all_title);
|
|
|
408
|
-write_table(all_restaurants, "", all_title);
|
|
|
|
|
417
|
+write_all_days(all_restaurants, "", all_title, "");
|
|
|
418
|
+write_table(all_restaurants, "", all_title, "");
|