diff --git a/subsites/lunchuman-apache b/subsites/lunchuman-apache
new file mode 100644
index 0000000..93b6eaf
--- /dev/null
+++ b/subsites/lunchuman-apache
@@ -0,0 +1,30 @@
+
+
+ ServerName datalosjen.metanohi.name
+ ServerAlias www.datalosjen.metanohi.name datalosjen.lcl
+ ServerAdmin ns@metanohi.name
+
+ DocumentRoot /home/niels/www/meta/subsites/lunchuman
+
+ Alias /robots.txt /home/niels/www/meta/subsites/lunchuman/robots.txt
+ Alias /favicon.ico /home/niels/www/meta/subsites/lunchuman/favicon.ico
+ Alias /favicon.png /home/niels/www/meta/subsites/lunchuman/favicon.png
+ Alias /static /home/niels/www/meta/subsites/lunchuman/static
+ Alias /lunchuman.wsgi /home/niels/www/meta/subsites/films/lunchuman.wsgi
+ Alias /apache-config-template /home/niels/www/meta/subsites/lunchuman/apache-config-template
+
+
+ Order allow,deny
+ Allow from all
+
+
+ WSGIDaemonProcess lunchuman.metanohi.name processes=1 threads=1 display-name=%{GROUP}
+ WSGIProcessGroup lunchuman.metanohi.name
+
+ WSGIScriptAlias / /home/niels/www/meta/subsites/lunchuman/lunchuman.wsgi
+
+ LogLevel warn
+ ErrorLog /var/log/apache2/lunchuman.metanohi.name-error.log
+ CustomLog /var/log/apache2/lunchuman.metanohi.name-access.log combined
+
+
\ No newline at end of file
diff --git a/subsites/lunchuman/.gitignore b/subsites/lunchuman/.gitignore
new file mode 100644
index 0000000..b18461c
--- /dev/null
+++ b/subsites/lunchuman/.gitignore
@@ -0,0 +1,3 @@
+/.dynamicsettings
+/.old
+/lunchuman.sqlite
\ No newline at end of file
diff --git a/subsites/lunchuman/apache-config-template b/subsites/lunchuman/apache-config-template
new file mode 100644
index 0000000..c434db8
--- /dev/null
+++ b/subsites/lunchuman/apache-config-template
@@ -0,0 +1,30 @@
+
+
+ ServerName lunchuman.example.org
+ ServerAlias www.lunchuman.example.org
+ ServerAdmin webmaster@example.org
+
+ DocumentRoot /path/to/dir/of/lunchuman
+
+ Alias /robots.txt /path/to/dir/of/lunchuman/robots.txt
+ Alias /favicon.ico /path/to/dir/of/lunchuman/favicon.ico
+ Alias /favicon.png /path/to/dir/of/lunchuman/favicon.png
+ Alias /static /path/to/dir/of/lunchuman/static
+ Alias /lunchuman.wsgi /path/to/dir/of/lunchuman/lunchuman.wsgi
+ Alias /apache-config-template /path/to/dir/of/lunchuman/apache-config-template
+
+
+ Order allow,deny
+ Allow from all
+
+
+ WSGIDaemonProcess lunchuman.example.org processes=2 threads=15 display-name=%{GROUP}
+ WSGIProcessGroup lunchuman.example.org
+
+ WSGIScriptAlias / /path/to/dir/of/lunchuman/lunchuman.wsgi
+
+ LogLevel warn
+ ErrorLog /var/log/apache2/lunchuman.example.org-error.log
+ CustomLog /var/log/apache2/lunchuman.example.org-access.log combined
+
+
diff --git a/subsites/lunchuman/frontpage.html b/subsites/lunchuman/frontpage.html
new file mode 100644
index 0000000..64bfafb
--- /dev/null
+++ b/subsites/lunchuman/frontpage.html
@@ -0,0 +1,37 @@
+
Add user
+
+
+
+
+
Update user data
+
+
+
+
+
FAQ
+
+
Question: The words "foods" and "moneys" are incorrect. Why
+ do you use them?
+
Answer: In the domain of this lunch club, they are correct.
+
+
+Tihs is not a typo.
+
diff --git a/subsites/lunchuman/lunchuman.config b/subsites/lunchuman/lunchuman.config
new file mode 100644
index 0000000..54fa3d3
--- /dev/null
+++ b/subsites/lunchuman/lunchuman.config
@@ -0,0 +1,4 @@
+[lunchuman]
+
+name = Datalosjen
+
diff --git a/subsites/lunchuman/lunchuman.wsgi b/subsites/lunchuman/lunchuman.wsgi
new file mode 100644
index 0000000..4478c39
--- /dev/null
+++ b/subsites/lunchuman/lunchuman.wsgi
@@ -0,0 +1,183 @@
+#!/usr/bin/env python3
+
+# lunchuman.wsgi: a WSGI script for managing a simple lunch club
+# Copyright (C) 2012 Niels G. W. Serup
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License along with this program. If not, see
+# .
+
+## Version: 0.1.0
+## Maintainer: Niels G. W. Serup
+## Temporary website: http://datalosjen.metanohi.name/static/source/lunchuman
+
+import sys
+import os
+import bottle
+from bottle import route, abort, error, request, redirect
+import sqlite3
+import threading
+import itertools
+import atexit
+import pickle
+import configparser
+import locale
+import traceback
+
+_preferred_encoding = 'utf-8' # locale.getpreferredencoding() # fail
+_absfile = os.path.abspath(__file__)
+_filedir = os.path.dirname(_absfile)
+_configfile_name = 'lunchuman.config'
+
+def start_bottle():
+ global application
+ application = bottle.default_app()
+
+def block():
+ threading.Event().wait()
+
+with open(os.path.join(_filedir, '.dynamicsettings'), 'rb') as f:
+ dynamic_settings = pickle.load(f)
+
+if dynamic_settings['status'] == 'stop':
+ start_bottle()
+ block()
+
+
+class LunchumanDatabase:
+ def __init__(self, fname):
+ self.dbfile = fname
+
+ def load(self):
+ self.conn = sqlite3.connect(self.dbfile)
+ self.cursor = self.conn.cursor()
+ self._create()
+
+ def close(self):
+ self.conn.close()
+
+ def _create(self):
+ self.cursor.execute('''
+create table if not exists users (
+id integer primary key autoincrement,
+name text,
+moneys int,
+foods int
+)
+''')
+ self.conn.commit()
+
+ def get_users(self):
+ self.cursor.execute('select * from users order by moneys / foods desc')
+ return self.cursor.fetchall()
+
+ def add_user(self, name):
+ self.cursor.execute('insert into users values (NULL, ?, 0, 0)', (name,))
+ self.conn.commit()
+
+ def update_user_data(self, *users):
+ for id, new_name, moneys_incr, foods_incr in users:
+ self.cursor.execute('''
+update users set name=?, moneys=moneys + (?), foods=foods + (?)
+where id=?
+''', (new_name, moneys_incr, foods_incr, id))
+ self.conn.commit()
+
+def add_settings_from_file(fname, settings):
+ cfg = configparser.SafeConfigParser(settings)
+ cfg.add_section('lunchuman')
+ cfg.read(os.path.join(_filedir, fname))
+ return {name: value for name, value in cfg.items('lunchuman')}
+
+def dictpair(*ds):
+ return {key: val for key, val
+ in itertools.chain(*(d.items() for d in ds))}
+
+def read_file(locpath):
+ with open(os.path.join(_filedir, locpath), 'rb') as f:
+ return f.read().decode(_preferred_encoding)
+
+def get_seq_input(d, base_key):
+ i = 0
+ xs = []
+ while True:
+ try:
+ xs.append(d['{}[{}]'.format(base_key, i)])
+ except KeyError:
+ break
+ i += 1
+ return xs
+
+settings = add_settings_from_file(
+ _configfile_name, {
+ 'name': 'Lunchuman',
+ 'dbfile': 'lunchuman.sqlite',
+ 'template': 'template.html',
+ 'frontpage': 'frontpage.html'
+ })
+
+_template = read_file(settings['template'])
+_userdata_template = '''
+
+
+