--- /dev/null
+localsettings.py
+*.db
+*.db-journal
+*~
+
+# Python garbage
+*.pyc
+.coverage
+pip-log.txt
+nosetests.xml
+
+# Mac OS X garbage
+.DS_Store
+
+# Windows garbage
+thumbs.db
+
+# Eclipse
+.project
+.settings
+.pydevproject
+.tmp_*
+
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding model 'Poet'
+ db.create_table('poetry_poet', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=50)),
+ ('path', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50, db_index=True)),
+ ('author', self.gf('django.db.models.fields.CharField')(max_length=128, blank=True)),
+ ('url', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
+ ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+ ('first_line_title', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ('skip_first_lines', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ))
+ db.send_create_signal('poetry', ['Poet'])
+
+ # Adding model 'Poem'
+ db.create_table('poetry_poem', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50, db_index=True)),
+ ('title', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
+ ('text', self.gf('django.db.models.fields.TextField')()),
+ ('poet', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['poetry.Poet'])),
+ ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, db_index=True, blank=True)),
+ ('seen_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ('view_count', self.gf('django.db.models.fields.IntegerField')(default=1)),
+ ('for_contest', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ('in_contest', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ))
+ db.send_create_signal('poetry', ['Poem'])
+
+
+ def backwards(self, orm):
+
+ # Deleting model 'Poet'
+ db.delete_table('poetry_poet')
+
+ # Deleting model 'Poem'
+ db.delete_table('poetry_poem')
+
+
+ models = {
+ 'poetry.poem': {
+ 'Meta': {'object_name': 'Poem'},
+ 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'for_contest': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'in_contest': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'poet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['poetry.Poet']"}),
+ 'seen_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'view_count': ('django.db.models.fields.IntegerField', [], {'default': '1'})
+ },
+ 'poetry.poet': {
+ 'Meta': {'object_name': 'Poet'},
+ 'author': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'first_line_title': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'path': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'skip_first_lines': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}),
+ 'url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['poetry']
--- /dev/null
+# -*- coding: utf-8 -*-
+import os
+import subprocess
+from django.db import models
+from django.core.urlresolvers import reverse
+from poetry.utils import get_hash
+
+
+class Poet(models.Model):
+ name = models.CharField(max_length=50)
+ path = models.CharField(max_length=255)
+ slug = models.SlugField(max_length=50, unique=True, db_index=True)
+ author = models.CharField(max_length=128, blank=True)
+ url = models.CharField(max_length=255, blank=True)
+ description = models.TextField(blank=True)
+ first_line_title = models.BooleanField(default=False)
+ skip_first_lines = models.IntegerField(default=0)
+
+ def __unicode__(self):
+ return self.name
+
+ def get_absolute_url(self):
+ return reverse('poetry_poet', kwargs={'slug': self.slug})
+
+ def write(self):
+ curdir = os.getcwd()
+ os.chdir(os.path.dirname(self.path))
+ text = subprocess.check_output(self.path).decode("utf-8")
+ os.chdir(curdir)
+ text = text[:1000]
+ slug = get_hash(text)
+ title = ''
+ if self.first_line_title:
+ title, text = text.split('\n', 1)
+ if self.skip_first_lines:
+ text = text.split('\n', self.skip_first_lines)[-1]
+ text = text.strip('\n')
+ poem = self.poem_set.create(
+ slug=slug,
+ text=text,
+ title=title
+ )
+ return poem
+
+
+class Poem(models.Model):
+ slug = models.SlugField(max_length=50, db_index=True)
+ title = models.CharField(max_length=255, null=True, blank=True)
+ text = models.TextField()
+ poet = models.ForeignKey(Poet)
+ created_at = models.DateTimeField(auto_now_add=True, editable=False, db_index=True)
+ seen_at = models.DateTimeField(auto_now_add=True, editable=False)
+ view_count = models.IntegerField(default=1)
+
+ for_contest = models.BooleanField(default=False)
+ in_contest = models.BooleanField(default=False)
+
+ def __unicode__(self):
+ oneliner = u"%s, %s" % (self.poet.name, self.pretty_title())
+ if not self.title:
+ oneliner += u" [%s…]" % self.text[:20]
+ return oneliner
+
+ def get_absolute_url(self):
+ return reverse('poetry_poem', kwargs={'slug': self.slug})
+
+ def pretty_title(self):
+ return self.title or "***"
+
+ def visit(self):
+ self.view_count += 1
+ self.seen_at = datetime.now()
+ self.save()
--- /dev/null
+body {
+ font-size: 16px;
+ font: Georgia, "Times New Roman", serif;
+ line-height: 1.5em;
+ margin: 0;
+}
+
+a {
+ color: blue;
+ text-decoration: none;
+}
+
+a:hover {
+ border-bottom: 1px dotted;
+}
+
+#book-text {
+ margin: 3em;
+ max-width: 36em;
+}
+
+/* ================================== */
+/* = Header with logo and menu = */
+/* ================================== */
+#header {
+ margin: 3.4em 0 0 1.4em;
+}
+
+img {
+ border: none;
+}
+
+
+#menu {
+ position: fixed;
+ left: 0em;
+ top: 0em;
+ width: 100%;
+ height: 1.5em;
+ background: #333;
+ color: #FFF;
+ opacity: 0.9;
+ z-index: 99;
+}
+
+#menu a.menu-link {
+ display: block;
+ float: left;
+ height: 1.5em;
+ margin-left: 0.5em;
+ text-align: center;
+ color: #FFF;
+}
+#menu span {
+ color: #888;
+ font-style: italic;
+ font-size: .75em;
+ margin-right: 0.5em;
+}
+
+
+/* =================================================== */
+/* = Common elements: headings, paragraphs and lines = */
+/* =================================================== */
+h1 {
+ font-size: 3em;
+ margin: 1.5em 0;
+ text-align: center;
+ line-height: 1.5em;
+ font-weight: bold;
+}
+
+h2 {
+ font-size: 2em;
+ margin: 1.5em 0 0;
+ font-weight: bold;
+ line-height: 1.5em;
+}
+
+h3 {
+ font-size: 1.5em;
+ margin: 1.5em 0 0;
+ font-weight: normal;
+ line-height: 1.5em;
+}
+
+h4 {
+ font-size: 1em;
+ margin: 1.5em 0 0;
+ line-height: 1.5em;
+}
+
+p {
+ margin: 0;
+}
+
+
+#footnotes {
+ margin-top: 3em;
+ margin-left: 2.5em;
+ font-size: 0.875em;
+}
+
+#footnotes p, #footnotes ul {
+ margin: 1.5em 0;
+}
+
+#footnotes .permalink {
+ font-size: .75em;
+}
+
+/* =================== */
+/* = Custom elements = */
+/* =================== */
+span.author {
+ font-size: 0.5em;
+ display: block;
+ line-height: 1.5em;
+ margin-bottom: 0.25em;
+}
+
+span.author a {
+ color: inherit;
+}
+
+span.author a {
+ color: inherit;
+}
+
+
+/* =================================== */
+/* = Hide some elements for printing = */
+/* =================================== */
+
+@media print {
+ #menu {display: none;}
+}
--- /dev/null
+{% extends "base.html" %}
+{% load url from future %}
+
+{% block "body" %}
+
+<h1>
+<a href='/'><img src="{{ STATIC_URL }}img/turniej-maly.png" style='float:left; margin-right: 10px; margin-top: -13px' /></a>
+Turniej Elektrybałtów</h1>
+{% comment %}
+<div class="social">
+<span style="position:relative; top: -5px;" >
+ <div class="fb-like" data-href="http://turniej.wolnelektury.pl" data-send="false" data-layout="button_count" data-width="150" data-show-faces="false"></div>
+</span>
+<g:plusone annotation="bubble" href="http://turniej.wolnelektury.pl"></g:plusone>
+<script>
+ new nk_fajne({
+ url: "http://turniej.wolnelektury.pl",
+ type: 4,
+ color: 0,
+ title: "Turniej Elektrybałtów",
+ image: "http://turniej.wolnelektury.pl/turniej.png",
+ description: "Turniej Elektrybałtów - otwarty konkurs na najlepszego automatycznego poetę."
+ });
+</script>
+</div>
+{% endcomment %}
+<h2>Uczestnicy:</h2>
+<ul class='poet-list'>
+{% for poet in poets %}
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+ <li><a href="{{ poet.get_absolute_url }}">{{ poet }}</a>
+ (<a href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>)</li>
+{% endfor %}
+</ul>
+
+<div style='clear: both'></div>
+
+<a class='tworz' href="{% url 'poetry_new' %}">Twórz-że się!</a>
+
+<h2>Ostatnio opublikowane utwory:</h2>
+<ul class='plain'>
+{% for poem in last %}
+ <li><a href="{{ poem.get_absolute_url }}">{{ poem }}</a></li>
+{% endfor %}
+</ul>
+
+{% endblock %}
--- /dev/null
+{% load url from future %}
+<!doctype html>
+<html>
+<head>
+ <title>Turniej Elektrybałtów: {{ poem.poet.name }}</title>
+ <meta charset="utf-8" />
+
+ <link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico" />
+ <style type="text/css">
+ @import "{{ STATIC_URL }}poetry/poem.css";
+ </style>
+</head>
+
+<body>
+
+<div id="fb-root"></div>
+<script>(function(d, s, id) {
+ var js, fjs = d.getElementsByTagName(s)[0];
+ if (d.getElementById(id)) {return;}
+ js = d.createElement(s); js.id = id;
+ js.src = "//connect.facebook.net/pl_PL/all.js#xfbml=1";
+ fjs.parentNode.insertBefore(js, fjs);
+}(document, 'script', 'facebook-jssdk'));</script>
+<script src="http://0.s-nk.pl/script/nk_widgets/nk_widget_fajne_embed"></script>
+
+ <div id="menu">
+ <a href='{% url "poetry_new" %}' class='menu-link'>Twórzże się jeszcze raz!</a>
+ <span style='float: right'>Turniej Elektrybałtów</a>
+ </div>
+
+ <div id="header">
+ <div id="logo">
+ <a href="/"><img src="{{ STATIC_URL }}img/turniej-maly.png" alt="logo Turnieju Elektrybałtów" /></a>
+ </div>
+ </div>
+
+ <div id="book-text">
+ <h1>
+ <span class="author"><a href="{{ poem.poet.get_absolute_url }}">{{ poem.poet.name }}</a></span>
+ <span class="title">{% if poem.title %}{{ poem.title }}{% else %}***{% endif %}</span>
+ </h1>
+ {{ poem.text|linebreaksbr }}
+ <div id="footnotes" >
+ <h3>O utworze</h3>
+ <p>Autor: <a href="{{ poem.poet.get_absolute_url }}">{{ poem.poet.name }}</a> (<a href="{% url 'poetry_main' %}">wszyscy autorzy</a>).
+ <br/>Zobacz <a href="{% url 'poetry_new' poem.poet.slug %}">nowy wiersz</a> tego autora,
+ albo <a href="{% url 'poetry_new' %}">nowy wiersz dowolnego autora</a>.</p>
+
+
+
+<div>
+<h3>Podziel się wierszem!</h3>
+<span style="position:relative; top: -5px;" >
+ <div class="fb-like" data-href="http://turniej.wolnelektury.pl{{ poem.get_absolute_url }}" data-send="false" data-layout="button_count" data-width="150" data-show-faces="false"></div>
+</span>
+<g:plusone annotation="bubble" href="http://turniej.wolnelektury.pl{{ poem.get_absolute_url }}"></g:plusone>
+
+<script>
+ new nk_fajne({
+ url: "http://turniej.wolnelektury.pl{{ poem.get_absolute_url }}",
+ type: 4,
+ color: 0,
+ title: "wiersz",
+ image: "http://turniej.wolnelektury.pl/turniej.png",
+ description: "{{ poem }}"
+ });
+</script>
+ <br/>
+ albo użyj linku:<br/>
+ <a class="permalink" href="{{ poem.get_absolute_url }}">http://turniej.wolnelektury.pl{{ poem.get_absolute_url }}</a>
+</div>
+
+
+
+
+ </div>
+
+<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
+ {lang: 'pl'}
+</script>
+</body>
+
+
+</html>
+
+
--- /dev/null
+{% extends "base.html" %}
+{% load url from future %}
+
+{% block "body" %}
+
+<h1>
+<a href='/'><img src="{{ STATIC_URL }}img/turniej-maly.png" style='float:left; margin-right: 10px; margin-top: -13px' /></a>
+{{ poet.name }}</h1>
+
+<div>
+<span style="position:relative; top: -5px;" >
+ <div class="fb-like" data-send="false" data-layout="button_count" data-width="150" data-show-faces="false"></div>
+</span>
+<g:plusone annotation="bubble"></g:plusone>
+<script>
+ new nk_fajne({
+ url: "{{ request.build_absolute_uri }}",
+ type: 4,
+ color: 0,
+ title: "{{ poet.name }}",
+ image: "http://turniej.wolnelektury.pl/turniej.png",
+ description: "Turniej Elektrybałtów - konkurs na najlepszego automatycznego poetę."
+ });
+</script>
+</div>
+
+<p><a href="{% url 'poetry_main' %}">Zobacz wszystkich autorów.</a></p>
+
+<p>Autor programu: <strong>{{ poet.author }}</strong></p>
+
+<p>{{ poet.description }}</p>
+
+<p>Kod źródłowy: <strong>{{ poet.url }}</strong></p>
+
+<a class="tworz" href="{% url 'poetry_new' poet.slug %}">Twórz-że!</a>
+
+<p>Ostatnio opublikowane utwory:</p>
+<ul class='plain'>
+{% for poem in last %}
+ <li><a href="{{ poem.get_absolute_url }}">{{ poem }}</a></li>
+{% endfor %}
+</ul>
+
+{% endblock %}
--- /dev/null
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('poetry.views',
+ url(r'^wiersz/(?P<slug>[a-zA-Z0-9-]+)/$', 'poem', name='poetry_poem'),
+
+ url(r"^$", "main", name="poetry_main"),
+ url(r"^nowy/$", 'new', name="poetry_new"),
+ url(r"^(?P<slug>[a-zA-Z0-9-]+)/$", "poet", name="poetry_poet"),
+ url(r"^(?P<slug>[a-zA-Z0-9-]+)/nowy/$", 'new', name="poetry_new"),
+
+)
--- /dev/null
+import time
+
+from base64 import urlsafe_b64encode
+from django.utils.hashcompat import sha_constructor
+
+
+def get_hash(seed):
+ sha_digest = sha_constructor('%s%s' %
+ (time.time(), unicode(seed).encode('utf-8', 'replace'))).digest()
+ return urlsafe_b64encode(sha_digest).replace('=', '').replace('_', '-').lower()
--- /dev/null
+from django.shortcuts import render, get_object_or_404
+from poetry.models import Poet, Poem
+
+
+def new(request, slug=None):
+ if slug is not None:
+ poet = get_object_or_404(Poet, slug=slug)
+ else:
+ poet = Poet.objects.order_by('?')[0]
+
+ poem = poet.write()
+ return render(request, "poetry/poem.html", locals())
+
+
+def poem(request, slug):
+ poem = get_object_or_404(Poem, slug=slug)
+ return render(request, "poetry/poem.html", locals())
+
+
+def poet(request, slug):
+ poet = get_object_or_404(Poet, slug=slug)
+ last = poet.poem_set.order_by('-created_at')[:20]
+ return render(request, "poetry/poet.html", locals())
+
+
+def main(request):
+ poets = Poet.objects.all().order_by('?')
+ last = Poem.objects.all().order_by('-created_at')[:20]
+ return render(request, "poetry/main.html", locals())
--- /dev/null
+from __future__ import with_statement # needed for python 2.5
+from fabric.api import *
+from fabric.contrib import files
+
+import os
+
+
+# ==========
+# = Config =
+# ==========
+# Globals
+env.project_name = 'turniej'
+env.use_south = True
+
+# Servers
+def giewont():
+ env.hosts = ['giewont.icm.edu.pl']
+ env.user = 'lektury'
+ env.path = '/srv/turniej.wolnelektury.pl'
+ env.virtualenv = '/usr/bin/virtualenv'
+ # This goes to VHost configuration
+ env.server_name = 'turniej.wolnelektury.pl'
+ env.server_admin = 'Radoslaw Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>'
+ # /var/log/apache2/* logs
+ env.access_log = 'turniej.log'
+ env.error_log = 'turniej-errors.log'
+
+
+servers = [giewont]
+
+# =========
+# = Tasks =
+# =========
+def test():
+ "Run the test suite and bail out if it fails"
+ require('hosts', 'path', provided_by=servers)
+ require('python', provided_by=[find_python])
+ result = run('cd %(path)s/%(project_name)s; %(python)s manage.py test' % env)
+
+def setup():
+ """
+ Setup a fresh virtualenv as well as a few useful directories, then run
+ a full deployment. virtualenv with pip should be already installed.
+ """
+ require('hosts', 'path', 'virtualenv', provided_by=servers)
+
+ run('mkdir -p %(path)s; cd %(path)s; %(virtualenv)s ve;' % env, pty=True)
+ run('cd %(path)s; mkdir releases; mkdir packages;' % env, pty=True)
+ run('cd %(path)s/releases; ln -s . current; ln -s . previous' % env, pty=True)
+ upload_default_localsettings()
+ deploy()
+
+def deploy():
+ """
+ Deploy the latest version of the site to the servers,
+ install any required third party modules,
+ install the virtual host and then restart the webserver
+ """
+
+ import time
+ env.release = time.strftime('%Y-%m-%dT%H%M')
+
+ upload_tar_from_git()
+ find_python()
+ upload_wsgi_script()
+ upload_vhost_sample()
+ install_requirements()
+ copy_localsettings()
+ symlink_current_release()
+ collectstatic()
+ migrate()
+ restart_webserver()
+
+def deploy_version(version):
+ "Specify a specific version to be made live"
+ require('hosts', 'path', provided_by=servers)
+ env.version = version
+ with cd(env.path):
+ run('rm releases/previous; mv releases/current releases/previous;', pty=True)
+ run('ln -s %(version)s releases/current' % env, pty=True)
+ restart_webserver()
+
+def rollback():
+ """
+ Limited rollback capability. Simple loads the previously current
+ version of the code. Rolling back again will swap between the two.
+ """
+ require('hosts', 'path', provided_by=servers)
+ with cd(env.path):
+ run('mv releases/current releases/_previous;', pty=True)
+ run('mv releases/previous releases/current;', pty=True)
+ run('mv releases/_previous releases/previous;', pty=True)
+ restart_webserver()
+
+
+# =====================================================================
+# = Helpers. These are called by other functions rather than directly =
+# =====================================================================
+def upload_tar_from_git():
+ "Create an archive from the current Git branch and upload it"
+ print '>>> upload tar from git'
+ require('path', provided_by=servers)
+ require('release', provided_by=[deploy])
+ local('/bin/bash lib/git-archive-all.sh --format tar %(release)s.tar' % env)
+ local('gzip %(release)s.tar' % env)
+ run('mkdir -p %(path)s/releases/%(release)s' % env, pty=True)
+ run('mkdir -p %(path)s/packages' % env, pty=True)
+ put('%(release)s.tar.gz' % env, '%(path)s/packages/' % env)
+ run('cd %(path)s/releases/%(release)s && tar zxf ../../packages/%(release)s.tar.gz' % env, pty=True)
+ local('rm %(release)s.tar.gz' % env)
+
+def find_python():
+ "Finds where virtualenv Python stuff is"
+ print ">>> find Python paths"
+ require('path', provided_by=servers)
+ env.python = '%(path)s/ve/bin/python' % env
+ env.pip = '%(path)s/ve/bin/pip' % env
+ env.site_packages = run('%(python)s -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"' % env)
+
+def upload_vhost_sample():
+ "Create and upload Apache virtual host configuration sample"
+ print ">>> upload vhost sample"
+ require('path', 'project_name', 'user', provided_by=servers)
+ require('access_log', 'error_log', 'server_admin', 'server_name', provided_by=servers)
+ require('site_packages', provided_by=[find_python])
+ files.upload_template('%(project_name)s.vhost.template' % env, '%(path)s/%(project_name)s.vhost' % env, context=env)
+
+def upload_wsgi_script():
+ "Create and upload a wsgi script sample"
+ print ">>> upload wsgi script sample"
+ require('path', 'project_name', provided_by=servers)
+ require('python', 'site_packages', provided_by=[find_python])
+ files.upload_template('%(project_name)s.wsgi.template' % env, '%(path)s/%(project_name)s.wsgi' % env, context=env)
+ run('chmod ug+x %(path)s/%(project_name)s.wsgi' % env)
+
+def install_requirements():
+ "Install the required packages from the requirements file using pip"
+ print '>>> install requirements'
+ require('path', provided_by=servers)
+ require('release', provided_by=[deploy])
+ require('pip', provided_by=[find_python])
+ run('%(pip)s install -r %(path)s/releases/%(release)s/requirements.txt' % env, pty=True)
+
+def secret_key():
+ """Generates a new SECRET_KEY."""
+ from random import Random
+ import string
+
+ r = Random()
+ return "".join(r.choice(string.printable) for i in range(64))
+
+def upload_default_localsettings():
+ "Uploads localsettings.py with media paths and stuff"
+ print ">>> upload default localsettings.py"
+ require('path', provided_by=servers)
+
+ env.secret_key = secret_key()
+ files.upload_template('%(project_name)s/localsettings.py.template' % env, '%(path)s/localsettings.py' % env, context=env)
+
+def copy_localsettings():
+ "Copy localsettings.py from root directory to release directory (if this file exists)"
+ print ">>> copy localsettings"
+ require('path', 'project_name', provided_by=servers)
+ require('release', provided_by=[deploy])
+
+ with settings(warn_only=True):
+ run('cp %(path)s/localsettings.py %(path)s/releases/%(release)s/%(project_name)s' % env)
+
+def symlink_current_release():
+ "Symlink our current release"
+ print '>>> symlink current release'
+ require('path', provided_by=servers)
+ require('release', provided_by=[deploy])
+ with cd(env.path):
+ run('rm releases/previous; mv releases/current releases/previous')
+ run('ln -s %(release)s releases/current' % env)
+
+def collectstatic():
+ """Runs collectstatic management command from Django staticfiles."""
+ print '>>> collectstatic'
+ require('path', 'project_name', provided_by=servers)
+ require('python', provided_by=[find_python])
+ with cd('%(path)s/releases/current/%(project_name)s' % env):
+ run('%(python)s manage.py collectstatic --noinput' % env, pty=True)
+
+def migrate():
+ "Update the database"
+ print '>>> migrate'
+ require('path', 'project_name', provided_by=servers)
+ require('python', provided_by=[find_python])
+ with cd('%(path)s/releases/current/%(project_name)s' % env):
+ run('%(python)s manage.py syncdb --noinput' % env, pty=True)
+ if env.use_south:
+ run('%(python)s manage.py migrate' % env, pty=True)
+
+def restart_webserver():
+ "Restart the web server"
+ print '>>> restart webserver'
+ require('path', 'project_name', provided_by=servers)
+ run('touch %(path)s/%(project_name)s.wsgi' % env)
--- /dev/null
+#!/bin/bash -
+#
+# File: git-archive-all.sh
+#
+# Description: A utility script that builds an archive file(s) of all
+# git repositories and submodules in the current path.
+# Useful for creating a single tarfile of a git super-
+# project that contains other submodules.
+#
+# Examples: Use git-archive-all.sh to create archive distributions
+# from git repositories. To use, simply do:
+#
+# cd $GIT_DIR; git-archive-all.sh
+#
+# where $GIT_DIR is the root of your git superproject.
+#
+# License: GPL3
+#
+###############################################################################
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+###############################################################################
+
+# DEBUGGING
+set -e
+set -C # noclobber
+
+# TRAP SIGNALS
+trap 'cleanup' QUIT EXIT
+
+# For security reasons, explicitly set the internal field separator
+# to newline, space, tab
+OLD_IFS=$IFS
+IFS='
+ '
+
+function cleanup () {
+ rm -f $TMPFILE
+ rm -f $TOARCHIVE
+ IFS="$OLD_IFS"
+}
+
+function usage () {
+ echo "Usage is as follows:"
+ echo
+ echo "$PROGRAM <--version>"
+ echo " Prints the program version number on a line by itself and exits."
+ echo
+ echo "$PROGRAM <--usage|--help|-?>"
+ echo " Prints this usage output and exits."
+ echo
+ echo "$PROGRAM [--format <fmt>] [--prefix <path>] [--separate|-s] [output_file]"
+ echo " Creates an archive for the entire git superproject, and its submodules"
+ echo " using the passed parameters, described below."
+ echo
+ echo " If '--format' is specified, the archive is created with the named"
+ echo " git archiver backend. Obviously, this must be a backend that git archive"
+ echo " understands. The format defaults to 'tar' if not specified."
+ echo
+ echo " If '--prefix' is specified, the archive's superproject and all submodules"
+ echo " are created with the <path> prefix named. The default is to not use one."
+ echo
+ echo " If '--separate' or '-s' is specified, individual archives will be created"
+ echo " for each of the superproject itself and its submodules. The default is to"
+ echo " concatenate individual archives into one larger archive."
+ echo
+ echo " If 'output_file' is specified, the resulting archive is created as the"
+ echo " file named. This parameter is essentially a path that must be writeable."
+ echo " When combined with '--separate' ('-s') this path must refer to a directory."
+ echo " Without this parameter or when combined with '--separate' the resulting"
+ echo " archive(s) are named with a dot-separated path of the archived directory and"
+ echo " a file extension equal to their format (e.g., 'superdir.submodule1dir.tar')."
+}
+
+function version () {
+ echo "$PROGRAM version $VERSION"
+}
+
+# Internal variables and initializations.
+readonly PROGRAM=`basename "$0"`
+readonly VERSION=0.2
+
+OLD_PWD="`pwd`"
+TMPDIR=${TMPDIR:-/tmp}
+TMPFILE=`mktemp "$TMPDIR/$PROGRAM.XXXXXX"` # Create a place to store our work's progress
+TOARCHIVE=`mktemp "$TMPDIR/$PROGRAM.toarchive.XXXXXX"`
+OUT_FILE=$OLD_PWD # assume "this directory" without a name change by default
+SEPARATE=0
+
+FORMAT=tar
+PREFIX=
+TREEISH=HEAD
+
+# RETURN VALUES/EXIT STATUS CODES
+readonly E_BAD_OPTION=254
+readonly E_UNKNOWN=255
+
+# Process command-line arguments.
+while test $# -gt 0; do
+ case $1 in
+ --format )
+ shift
+ FORMAT="$1"
+ shift
+ ;;
+
+ --prefix )
+ shift
+ PREFIX="$1"
+ shift
+ ;;
+
+ --separate | -s )
+ shift
+ SEPARATE=1
+ ;;
+
+ --version )
+ version
+ exit
+ ;;
+
+ -? | --usage | --help )
+ usage
+ exit
+ ;;
+
+ -* )
+ echo "Unrecognized option: $1" >&2
+ usage
+ exit $E_BAD_OPTION
+ ;;
+
+ * )
+ break
+ ;;
+ esac
+done
+
+if [ ! -z "$1" ]; then
+ OUT_FILE="$1"
+ shift
+fi
+
+# Validate parameters; error early, error often.
+if [ $SEPARATE -eq 1 -a ! -d $OUT_FILE ]; then
+ echo "When creating multiple archives, your destination must be a directory."
+ echo "If it's not, you risk being surprised when your files are overwritten."
+ exit
+elif [ `git config -l | grep -q '^core\.bare=false'; echo $?` -ne 0 ]; then
+ echo "$PROGRAM must be run from a git working copy (i.e., not a bare repository)."
+ exit
+fi
+
+# Create the superproject's git archive
+git archive --format=$FORMAT --prefix="$PREFIX" $TREEISH > $TMPDIR/$(basename $(pwd)).$FORMAT
+echo $TMPDIR/$(basename $(pwd)).$FORMAT >| $TMPFILE # clobber on purpose
+superfile=`head -n 1 $TMPFILE`
+
+# find all '.git' dirs, these show us the remaining to-be-archived dirs
+find . -name '.git' -type d -print | sed -e 's/^\.\///' -e 's/\.git$//' | (grep -v '^$' || echo -n) >> $TOARCHIVE
+
+while read path; do
+ TREEISH=$(git submodule | grep "^ .*${path%/} " | cut -d ' ' -f 2) # git submodule does not list trailing slashes in $path
+ cd "$path"
+ git archive --format=$FORMAT --prefix="${PREFIX}$path" ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT
+ if [ $FORMAT == 'zip' ]; then
+ # delete the empty directory entry; zipped submodules won't unzip if we don't do this
+ zip -d "$(tail -n 1 $TMPFILE)" "${PREFIX}${path%/}" >/dev/null # remove trailing '/'
+ fi
+ echo "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT >> $TMPFILE
+ cd "$OLD_PWD"
+done < $TOARCHIVE
+
+# Concatenate archives into a super-archive.
+if [ $SEPARATE -eq 0 ]; then
+ if [ $FORMAT == 'tar' ]; then
+ sed -e '1d' $TMPFILE | while read file; do
+ tar --concatenate -f "$superfile" "$file" && rm -f "$file"
+ done
+ elif [ $FORMAT == 'zip' ]; then
+ sed -e '1d' $TMPFILE | while read file; do
+ # zip incorrectly stores the full path, so cd and then grow
+ cd `dirname "$file"`
+ zip -g "$superfile" `basename "$file"` && rm -f "$file"
+ done
+ cd "$OLD_PWD"
+ fi
+
+ echo "$superfile" >| $TMPFILE # clobber on purpose
+fi
+
+while read file; do
+ mv "$file" "$OUT_FILE"
+done < $TMPFILE
--- /dev/null
+django-debug-toolbar
--- /dev/null
+# Django basics
+django>=1.3,<1.4
+South>=0.7
+
+piwik
--- /dev/null
+<VirtualHost *:80>
+ ServerName "%(server_name)s"
+ ServerAdmin "%(server_admin)s"
+
+ WSGIDaemonProcess %(project_name)s user=%(user)s group=%(user)s processes=2 threads=15 display-name=%%{GROUP} python-path=%(site_packages)s
+ WSGIProcessGroup %(project_name)s
+
+ WSGIScriptAlias / %(path)s/%(project_name)s.wsgi
+ <Directory %(path)s>
+ Order allow,deny
+ allow from all
+ </Directory>
+
+ Alias /media %(path)s/media
+ <Directory %(path)s/media>
+ Options Indexes
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ Alias /static %(path)s/releases/current/%(project_name)s/static
+ <Directory %(path)s/releases/current/%(project_name)s/static>
+ Options Indexes
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ LogLevel warn
+ ErrorLog /var/log/apache2/%(error_log)s
+ CustomLog /var/log/apache2/%(access_log)s combined
+</VirtualHost>
--- /dev/null
+#!%(python)s
+import site
+site.addsitedir('%(site_packages)s')
+
+import os
+from os.path import abspath, dirname, join
+import sys
+
+# Redirect sys.stdout to sys.stderr for bad libraries like geopy that use
+# print statements for optional import exceptions.
+sys.stdout = sys.stderr
+
+# Add apps and lib directories to PYTHONPATH
+sys.path = [
+ '%(path)s/releases/current/%(project_name)s',
+ '%(path)s/releases/current',
+ '%(path)s/releases/current/apps',
+ '%(path)s/releases/current/lib',
+ # add paths to submodules here
+] + sys.path
+
+# Run Django
+os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
+
+from django.core.handlers.wsgi import WSGIHandler
+application = WSGIHandler()
--- /dev/null
+# This template is uploaded by `fab setup`.
+# You should fill out the details in the version deployed on the server.
+
+
+ADMINS = (
+ #('Name', 'E-mail'),
+)
+
+MANAGERS = (
+ #('Name', 'E-mail'),
+)
+
+# on
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': '', # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+
+SECRET_KEY = %(secret_key)r
+MEDIA_ROOT = '%(path)s/media/'
--- /dev/null
+#!/usr/bin/env python
+import os.path
+import sys
+
+ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+# Add apps and lib directories to PYTHONPATH
+sys.path = [
+ os.path.join(ROOT, 'apps'),
+ os.path.join(ROOT, 'lib'),
+ # add /lib/* paths here for submodules
+] + sys.path
+
+from django.core.management import execute_manager
+import imp
+try:
+ imp.find_module('settings') # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
+ sys.exit(1)
+
+import settings
+
+if __name__ == "__main__":
+ execute_manager(settings)
--- /dev/null
+# -*- coding: utf-8 -*-
+# Django settings for turniej project.
+import os.path
+
+PROJECT_DIR = os.path.abspath(os.path.dirname(__file__))
+
+DEBUG = False
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = [
+ # ('Your Name', 'your_email@domain.com'),
+]
+
+MANAGERS = ADMINS
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': os.path.join(PROJECT_DIR, 'dev.db'), # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = None
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+#LANGUAGE_CODE = 'pl'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+#USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale
+#USE_L10N = True
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/media/"
+MEDIA_ROOT = os.path.join(PROJECT_DIR, '../media')
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash.
+# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
+MEDIA_URL = '/media/'
+
+# Absolute path to the directory static files should be collected to.
+# Don't put anything in this directory yourself; store your static files
+# in apps' "static/" subdirectories and in STATICFILES_DIRS.
+# Example: "/home/media/media.lawrence.com/static/"
+STATIC_ROOT = os.path.join(PROJECT_DIR, '../static')
+
+# URL prefix for static files.
+# Example: "http://media.lawrence.com/static/"
+STATIC_URL = '/static/'
+
+# URL prefix for admin static files -- CSS, JavaScript and images.
+# Make sure to use a trailing slash.
+# Examples: "http://foo.com/static/admin/", "/static/admin/".
+ADMIN_MEDIA_PREFIX = '/static/admin/'
+
+# Additional locations of static files
+STATICFILES_DIRS = (
+ # Put strings here, like "/home/html/static" or "C:/www/django/static".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+
+ os.path.join(PROJECT_DIR, 'static'),
+)
+
+# List of finder classes that know how to find static files in
+# various locations.
+STATICFILES_FINDERS = (
+ 'django.contrib.staticfiles.finders.FileSystemFinder',
+ 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
+)
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = [
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+# 'django.template.loaders.eggs.Loader',
+]
+
+MIDDLEWARE_CLASSES = [
+ 'django.middleware.common.CommonMiddleware',
+ #'django.contrib.sessions.middleware.SessionMiddleware',
+ #'django.middleware.csrf.CsrfViewMiddleware',
+ #'django.contrib.auth.middleware.AuthenticationMiddleware',
+ #'django.contrib.messages.middleware.MessageMiddleware',
+]
+
+ROOT_URLCONF = 'turniej.urls'
+
+TEMPLATE_DIRS = [
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ os.path.join(PROJECT_DIR, 'templates'),
+]
+
+INSTALLED_APPS = [
+ #'django.contrib.auth',
+ #'django.contrib.contenttypes',
+ #'django.contrib.sessions',
+ #'django.contrib.sites',
+ #'django.contrib.messages',
+ 'django.contrib.staticfiles',
+
+ # 'django.contrib.admin',
+ # 'django.contrib.admindocs',
+
+ 'south',
+
+ 'poetry',
+]
+
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error.
+# See http://docs.djangoproject.com/en/dev/topics/logging for
+# more details on how to customize your logging configuration.
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': False,
+ 'handlers': {
+ 'mail_admins': {
+ 'level': 'ERROR',
+ 'class': 'django.utils.log.AdminEmailHandler'
+ }
+ },
+ 'loggers': {
+ 'django.request': {
+ 'handlers': ['mail_admins'],
+ 'level': 'ERROR',
+ 'propagate': True,
+ },
+ }
+}
+
+# Load localsettings, if they exist
+try:
+ from localsettings import *
+except ImportError:
+ pass
--- /dev/null
+html {
+ margin: 0;
+}
+
+body {
+ margin: 0;
+ padding: 1em;
+ color: #2F4110;
+ background: url("http://static.wolnelektury.pl/img/bg.png") repeat-x scroll 0 0 #FFFFFF;
+
+ font-size: .75em;
+ font-family: Verdana,Arial,Helvetica,sans-serif;
+}
+
+
+#body {
+ max-width: 900px;
+ margin:auto;
+
+}
+
+
+#content {
+ width: 420px;
+ margin-top: 2em;
+}
+
+
+
+h1 {
+ font: bold 2.2em Arial,sans-serif;
+ padding-top: .7em;
+ margin-bottom: .2em;
+}
+
+
+h2 {
+ font-size: 1.1em;
+ margin:0;
+}
+
+a {
+ color: #295158;
+ text-decoration: none;
+}
+a:hover {
+ border-bottom: 1px dotted;
+}
+
+
+.plain li {
+ list-style: none;
+}
+
+li {
+ margin: 1em;
+}
+
+#termin-wrap {
+ margin-top: 3em;
+}
+
+
+.clr {
+ clear: both;
+}
+
+#footer {
+ border-top: 1px solid #ddd;
+ margin-top: 7em;
+ clear: both;
+
+}
+#footer img {
+ margin: 30px 13px;
+ vertical-align: middle;
+}
+
+
+blockquote {
+ font-size: .9em;
+ font-style: italic;
+ margin-left: 350px;
+ margin-right: 50px;
+ margin-bottom: 4em;
+}
+blockquote p {
+ margin: .5em 0 0 0;
+}
+
+.more {
+ text-align: right;
+}
+
+.uwaga {
+ border: 1px solid #ddd;
+ padding: 1em;
+ background-color: #ff8;
+}
+
+.social {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+
+.tworz {
+ font-size: 1.5em;
+ padding: .8em;
+ background: #555;
+ color: white;
+ margin: 1em auto;
+ display: block;
+ width: 10em;
+ text-align: center;
+ border: 1px solid #000;
+ border-radius: 1em;
+}
+.tworz:hover {
+ border: 1px solid #000;
+ background: #666;
+}
+
+.last {
+ list-style: none;
+ padding: 0;
+}
+.last li {
+ margin-left: 0;
+}
+
+.poet-list {
+ padding: 0;
+ margin: 1em 0;
+}
+.poet-list li {
+ float: left;
+ width: 30%;
+ list-style: none;
+ padding: .8em 0;
+ border: 1px solid #888;
+ background: #eee;
+ border-radius: 1em;
+ text-align: center;
+}
+.poet-list li:before {
+ content: "» ";
+}
--- /dev/null
+{% extends "base.html" %}
+
+{% block "body" %}
+<h1>Nie znaleziono strony</h1>
+
+<p>Nie ma tu żadnej strony. Przejdź do <a href='/'>strony głównej</a>.</p>
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block "body" %}
+<h1>Błąd</h1>
+
+<p>Wystąpił błąd serwera. Przepraszamy!</p>
+
+{% endblock %}
--- /dev/null
+<!doctype html>
+<html>
+<head>
+ <title>Turniej Elektrybałtów</title>
+ <meta charset="utf-8" />
+
+ <link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico" />
+ <style type="text/css">
+ @import "{{ STATIC_URL }}style.css";
+ </style>
+</head>
+
+<body>
+
+<div id="fb-root"></div>
+<script>(function(d, s, id) {
+ var js, fjs = d.getElementsByTagName(s)[0];
+ if (d.getElementById(id)) {return;}
+ js = d.createElement(s); js.id = id;
+ js.src = "//connect.facebook.net/pl_PL/all.js#xfbml=1";
+ fjs.parentNode.insertBefore(js, fjs);
+}(document, 'script', 'facebook-jssdk'));</script>
+<script src="http://0.s-nk.pl/script/nk_widgets/nk_widget_fajne_embed"></script>
+
+<div id="body">
+{% block "body" %}{% endblock %}
+</div>
+
+
+<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
+ {lang: 'pl'}
+</script>
+</body>
+
+
+</html>
--- /dev/null
+{% extends "base.html" %}
+{% load url from future %}
+
+{% block "body" %}
+
+<div style="float:right">
+<img src="{{ STATIC_URL }}img/turniej.png" style='float:right; margin-bottom: 2em;' alt="logo Turnieju Elektrybałtów: frontalny widok maszynki do mielenia mięsa" />
+<h2>Ostatnie wiersze:</h2>
+<ul class="last">
+{% for poem in last %}
+ <li><a href="{{ poem.get_absolute_url }}">{{ poem }}</a></li>
+{% endfor %}
+</ul>
+
+</div>
+
+<div id="content">
+<h1>Turniej Elektrybałtów</h1>
+<h2>Konkurs automatycznej poezji</h2>
+
+<div class="social">
+<span style="position:relative; top: -5px;" >
+ <div class="fb-like" data-href="http://turniej.wolnelektury.pl" data-send="false" data-layout="button_count" data-width="150" data-show-faces="false"></div>
+</span>
+<g:plusone annotation="bubble" href="http://turniej.wolnelektury.pl"></g:plusone>
+<script>
+ new nk_fajne({
+ url: "http://turniej.wolnelektury.pl",
+ type: 4,
+ color: 0,
+ title: "Turniej Elektrybałtów",
+ image: "http://turniej.wolnelektury.pl/turniej.png",
+ description: "Turniej Elektrybałtów - otwarty konkurs na najlepszego automatycznego poetę."
+ });
+</script>
+</div>
+
+
+<p>Znacie <a href="http://www.wolnelektury.pl/lesmianator/">Leśmianatora</a>?
+To niewielki skrypt miksujący na życzenie wiersze z
+<a href="http://www.wolnelektury.pl">Wolnych Lektur</a>.
+Powstał jako żart, a niechcący
+<a href="http://www.ha.art.pl/felietony/1515-mariusz-pisarski-piekit-siezyca-lesmianator.html">
+„odciął się od dosłownie rozumianego dziedzictwa dadaizmu i surrealizmu”</a>.
+Idziemy dalej – ogłaszamy <strong>otwarty konkurs na najlepszego automatycznego poetę</strong>!</p>
+
+<p>Konkurs wystartował 12 września 2011 roku – z okazji <strong>90 rocznicy urodzin
+Stanisława Lema</strong>. Termin nadsyłania prac upłynął
+10 listopada 2011 roku.
+Prezentujemy nadesłane prace w akcji.
+Kliknij przycisk, a jeden
+z <a href="{% url 'poetry_main' %}">programów-uczestników</a> napisze dla Ciebie wiersz:</p>
+
+<a style="margin: 1em auto;" class="tworz" href="{% url 'poetry_new' %}">Twórz-że się!</a>
+
+<p>Zobacz <a href="{% url 'poetry_main' %}">wszystkie programy</a>. Ich kod źródłowy
+<a href="https://github.com/turniej">jest dostępny</a> na wolnej licencji
+– nic więc nie stoi na przeszkodzie, by rozwijać je dalej.</p>
+
+<p>Do zabawy zapraszamy wszystkich – i tych, którzy świetnie programują, i tych, którzy
+programować dopiero się uczą. Tych, którzy nie rozstają się z tomikiem
+wierszy, i tych, którzy na ten widok dostają gęsiej skórki. Chcemy wybrać
+program, który będzie w najciekawszy i najbardziej twórczy sposób miksował
+dostępną w Wolnych Lekturach literaturę. W tej konkurencji liczy się przede
+wszystkim wyobraźnia, pomysł i chęć do twórczej zabawy.</p>
+
+<p>Więcej informacji:</p>
+
+<ul class='plain'>
+ <li><a href='wiecej/'>Przebieg konkursu</a> – czyli jakie będą kolejne etapy
+ i co jest nagrodą?</li>
+
+ <li><a href='technikalia/'>Technikalia</a> – czyli co i jak trzeba zrobić,
+ żeby wziąć udział.</li>
+
+ <li><a href='regulamin/'>Regulamin</a> – czyli trochę koniecznych formalności.</li>
+</ul>
+
+<p>Wszelkiego rodzaju pytania i wątpliwości proszę kierować na adres
+<a href="mailto:radoslaw.czajka@nowoczesnapolska.org.pl">radoslaw.czajka@nowoczesnapolska.org.pl</a></p>
+
+<div class='clr'></div>
+</div>
+
+
+<div id="footer">
+<a target='_blank' href='http://nowoczesnapolska.org.pl'><img src='{{ STATIC_URL }}img/fnp.png' alt='Fundacja Nowoczesna Polska' title='Fundacja Nowoczesna Polska' /></a>
+<a target='_blank' href='http://www.wolnelektury.pl'><img src='{{ STATIC_URL }}img/wl.png' alt='Wolne Lektury' title='Wolne Lektury' /></a>
+<a target='_blank' href='http://koed.org.pl'><img src='{{ STATIC_URL }}img/koed.png' alt='Koalicja Otwartej Edukacji' title='Koalicja Otwartej Edukacji' /></a>
+<a target='_blank' href='http://centrumcyfrowe.pl'><img src='{{ STATIC_URL }}img/cc.png' alt='Centrum Cyfrowe' title='Centrum Cyfrowe' /></a>
+<a target='_blank' href='http://di.com.pl'><img src='{{ STATIC_URL }}img/di.png' alt='Dziennik Internautów' title='Dziennik Internautów' /></a>
+<a target='_blank' href='http://solaris.lem.pl'><img src='{{ STATIC_URL }}img/lempl.png' alt='Lem.pl' title='Lem.pl' /></a>
+
+</div>
+
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block "body" %}
+
+<h1>
+<a href='/'><img src="{{ STATIC_URL }}img/turniej-maly.png" style='float:left; margin-right: 10px; margin-top: -13px' /></a>
+Turniej Elektrybałtów</h1>
+<h2>
+Konkurs automatycznej poezji</h2>
+
+<blockquote>
+ <p>Gdy wskaźniki amplifikacyjne pokazały, że moc liryczna dochodzi
+ do maksimum, Trurl nieznacznie tylko drżącą ręką przerzucił wielki
+ wyłącznik i niemal natychmiast głosem lekko ochrypłym, lecz emanującym
+ dziwnie sugestywnym czarem, maszyna rzekła:</p>
+
+ <p>– Chrzęskrzyboczek pacionkociewiczarokrzysztofoniczmy.</p>
+ <p>– Czy to już wszystko? – spytał po dłuższej chwili niezwykle uprzejmy
+ Klapaucjusz.</p>
+ <p>(Stanisław Lem, „Cyberiada”, „Wyprawa pierwsza A, czyli Elektrybałt Trurla”)</p>
+</blockquote>
+
+
+
+<p>Konkurs startuje 12 września 2011 roku – z okazji <strong>90 rocznicy urodzin
+Stanisława Lema</strong>. Termin nadsyłania prac upływa <del>z końcem października</del> <ins>10 listopada</ins> 2011 roku.
+Powinno być dość czasu na dopracowanie swoich pomysłów.</p>
+
+<p>Konkurs będzie wyglądał następująco:</p>
+
+<ul>
+ <li>Do <del>końca października</del> <ins>10 listopada</ins> czekamy na zgłoszenia w postaci programów.
+ Warunkiem dopuszczalności jest udostępnienie kodu źródłowego na wolnej
+ licencji <a href="http://www.gnu.org/licenses/agpl.html">GNU AGPL</a>
+ (<a href="http://www.gnu.org/licenses/gpl-howto.pl.html">jak to zrobić?)</a>.
+ Szerzej o tym, czym powinno być złoszenie –
+ w dziale <a href='../technikalia/'>Technikalia</a>.</li>
+
+ <li>Użycie wolnej licencji nie oznacza, że kod źródłowy musi być
+ od razu publicznie dostępny. Programy zostaną przez nas
+ upublicznione – ale dopiero po upłynięciu terminu nadsyłania zgłoszeń.
+ Uczestnik może oczywiście samodzielnie upublicznić swoje zgłoszenie
+ wcześniej – odradzamy to jednak ze względu na komplikacje w przypadku
+ plagiatu.</li>
+
+ <li>Po uruchomieniu nadesłanych przez uczestników programów dla każdego
+ uczestnika wygenerujemy <strong>20</strong> wierszy, które odeślemy autorowi
+ programu. Wybierze on <strong>3</strong> z nich, które następnie zostaną
+ poddane ocenie jury. W składzie jury znajdą się zarówno osoby związane
+ z programowaniem, jak i przedstawiciele świata kultury.</li>
+
+ <li>Główną nagrodą jest 16-tomowa kolekcja książek Stanisława Lema.
+ W ramach dodatkowej nagrody podczas zakończenia konkursu
+ odbędzie się próba odczytania zwycięskich wierszy na głos.</li>
+
+</ul>
+
+<p>Programy biorące udział w konkursie zostaną też uruchomione
+<a href="http://turniej.wolnelektury.pl">na stronie Turnieju</a> –
+internauci będą więc mieli możliwość samodzielnego „wyklikania” sobie własnego
+wiersza przy użyciu każdego z nich.</p>
+
+<p class='more'><a href="/">Powrót do strony głównej</a></p>
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block "body" %}
+
+
+<h1>
+<a href='..'><img src="{{ STATIC_URL }}img/turniej-maly.png" style='float:left; margin-right: 10px; margin-top: -13px' /></a>
+Turniej Elektrybałtów</h1>
+<h2>Konkurs automatycznej poezji</h2>
+
+<blockquote>
+ <p>Ustaliwszy, w czym rzecz, zwierzchność żeglugi kosmicznej zwróciła się
+ oficjalnie do Trurla z żądaniem natychmiastowej likwidacji należącego doń
+ urządzenia, które zakłócało liryką spokój publiczny i zagrażało zdrowiu
+ pasażerów.</p>
+
+ <p>(Stanisław Lem, „Cyberiada”, „Wyprawa pierwsza A, czyli Elektrybałt Trurla”)</p>
+</blockquote>
+
+
+
+<h3>Regulamin konkursu</h3>
+
+
+
+
+<ul>
+ <li>Organizatorem konkursu jest fundacja Nowoczesna Polska. </li>
+
+ <li>Przedmiotem konkursu jest program komputerowy tworzący remiksy literackie
+ na podstawie utworów znajdujących się w bilbiotece internetowej Wolne Lektury.
+ Program biorący udział w konkursie musi być udostępniony na wolnej
+ licencji <a href="http://www.gnu.org/licenses/agpl.html">GNU AGPL</a>
+ (<a href="http://www.gnu.org/licenses/gpl-howto.pl.html">jak to zrobić?)</a>.</li>
+
+ <li>Konkurs trwa od 12 września do <del>31 października</del> <ins>10 listopada</ins> 2011 roku.
+ Konkurs ma charakter otwarty. Aby wziąć w nim udział udział,
+ należy wysłać gotowy program na adres
+ <a href="mailto:radoslaw.czajka@nowoczesnapolska.org.pl">radoslaw.czajka@nowoczesnapolska.org.pl</a>
+
+ z klauzulą:
+ <cite>Zgłaszam się do konkursu „Turniej Elektrybałtów” i oświadczam, że
+ znam i akceptuję jego regulamin</cite>.</li>
+
+ <li>Nagrodą główną jest 16-tomowa kolekcja dzieł Stanisława Lema. Nie ma
+ możliwości zamiany nagrody na jej równowartość pieniężną.</li>
+
+ <li>Organizator może odwołać konkurs w każdym czasie, bez podawania
+ przyczyny. W takim przypadku uczestnikom konkursu nie przysługuje żadna
+ rekompensata. Uczestnicy zgłaszając swój udział w konkursie automatycznie
+ wyrażają zgodę na publikację ich twórczości w internecie oraz wyrażają
+ zgodę na wykorzystanie wizerunku w materiałach promocyjnych konkursu
+ oraz materiałach promocyjnych Fundacji Nowoczesna Polska.</li>
+
+ <li>Organizator zastrzega sobie prawo do odrzucenia zgłoszenia programu,
+ którego działanie może zagrażać stabilności, responsywności albo bezpieczeństwu
+ serwera, a także takich, których poprawne uruchomienie okaże się niemożliwe
+ lub poważnie utrudnione.</li>
+
+ <li>Organizator konkursu nie ponosi odpowiedzialności za wszelkie
+ roszczenia osób trzecich wynikające z tytułu wykorzystania materiałów
+ zgłoszonych przez uczestników konkursu jako własnych. Prace naruszające
+ prawa autorskie będą dyskwalifikowane.</li>
+
+ <li>Organizator zatrzega sobie prawo wprowadzenia zmian w regulaminie
+ konkursu.</li>
+</ul>
+
+
+
+
+<p class='more'><a href="/">Powrót do strony głównej</a></p>
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block "body" %}
+
+<h1>
+<a href='..'><img src="{{ STATIC_URL }}img/turniej-maly.png" style='float:left; margin-right: 10px; margin-top: -13px' /></a>
+Turniej Elektrybałtów</h1>
+<h2>Konkurs automatycznej poezji</h2>
+
+<blockquote>
+ <p>Gdy atoli, z lekka kulejąc, zbliżył się do maszyny, ta,
+ na widok obcęgów w jego dłoni i błysków desperacji w oku, buchnęła taką
+ namiętną liryką błagając o łaskę, że rozszlochany Trurl cisnął narzędzia
+ i wrócił do siebie, brnąc po kolana w nowych utworach elektroducha, które
+ sięgały mu do pół piersi, zaścielając szemrzącym oceanem papieru całą halę.</p>
+
+ <p>(Stanisław Lem, „Cyberiada”, „Wyprawa pierwsza A, czyli Elektrybałt Trurla”)</p>
+</blockquote>
+
+
+
+<h3>Wymogi wobec zgłaszanych programów</h3>
+
+<ul>
+ <li>Nie nakładamy ograniczeń na wybór języka programowania. Program
+ powinien dać się jednak uruchomić w środowisku GNU/Linux przy użyciu
+ wolnodostępnych narzędzi.</li>
+
+ <li>Warunkiem dopuszczalności jest udostępnienie kodu źródłowego na wolnej
+ licencji <a href="http://www.gnu.org/licenses/agpl.html">GNU AGPL</a>
+
+ (<a href="http://www.gnu.org/licenses/gpl-howto.pl.html">jak to zrobić?)</a>
+ Programy zostaną upublicznione – ale dopiero po upłynięciu terminu
+ nadsyłania zgłoszeń. Warunek ten oznacza w szczególności, że zgłoszenie
+ musi zawierać kod źródłowy. Nie wchodzą w grę żadne skompilowane, pośrednie,
+ zaciemnione wersje – kod powinien zostać udostępniony w takiej postaci,
+ nad jaką normalnie pracuje programista.</li>
+
+ <li>Program przy tworzeniu wierszy musi w istotny sposób korzystać
+ z zasobów Wolnych Lektur. Elementy wynikowych tekstów nie mogą być
+ zaszyte w treści samego programu. Program nie może też korzystać
+ podczas pracy z innych źródeł informacji – musi być jasne, że program
+ <em>naprawdę</em> miksuje dostarczoną mu literaturę, a nie odtwarza nagraną
+ uprzednio taśmę. Nie jest wymagane korzystanie z wszystkich utworów –
+ program może miksować np. tylko poezję romantyczną albo tylko fragmenty
+ oznaczone wybranymi motywami literackimi.</li>
+
+ <li>Generowanie wiersza nie powinno trwać więcej niż kilka sekund.
+ W ramach procesu instalacji programu dopuszczalne (i wskazane!) jest
+ natomiast uprzednie zgromadzenie niezbędnych informacji wynikających
+ z analizy tekstów źródłowych. Najlepiej więc dostarczyć dwa programy
+ (albo jeden z różnymi opcjami uruchomienia) – jeden pobierający utwory,
+ analizujący je i zapisujący efekty tej analizy, a drugi generujący
+ wiersze na podstawie zgromadzonej uprzednio informacji. Sądzimy, że
+ ok. 10MiB powinno wystarczyć każdemu
+ <a href="http://en.wikiquote.org/wiki/Talk:Bill_Gates#640K.2F1MB">[sic!]</a>,
+ ale w razie potrzeby będziemy się starali być elastyczni.</li>
+
+ <li>Program powinien wypisać wiersz na standardowe wyjście w postaci
+ czystego tekstu, najlepiej używając kodowania UTF-8 (czyli tego samego,
+ które jest używane w plikach źródłowych).</li>
+
+ <li>Maksymalna długość wiersza wynosi 1000 znaków – dalsze znaki zostaną
+ odcięte. Poza tym ograniczeniem długość i forma wiersza pozostaje w gestii
+ autora i jego programu.</li>
+
+ <li>Odrzucone zostana programy, które będą usiłowały w jakikolwiek
+ sposób zagrozić stabilności lub bezpieczeństwu serwera.</li>
+</ul>
+
+
+<h3>W jaki sposób pobierać utwory?</h3>
+
+<p>Źródłowe utwory można pobierać na kilka sposobów:</p>
+
+<ul>
+ <li>Korzystając z <a href="http://www.wolnelektury.pl/api/">API Wolnych Lektur</a>.</li>
+
+ <li>Pobierając <a href="http://www.wolnelektury.pl/media/packs/xml-all.zip">
+ paczkę źródłowych plików XML</a> i pracując z nimi bądź to samodzielnie,
+ bądź korzystając
+ z <a href="https://github.com/fnp/librarian">narzędzi stworzonych na potrzeby Wolnych Lektur</a>.</li>
+
+ <li>Pobierając paczkę plików tekstowych. Przygotowaliśmy do wyboru dwie:
+ <a href="http://www.wolnelektury.pl/media/packs/txt-all.zip">ze wszystkimi utworami</a>
+ oraz <a href="http://www.wolnelektury.pl/media/packs/txt-liryka.zip">tylko z liryką</a>.</li>
+</ul>
+
+<p>Wszystkie pliki źródłowe są zapisane przy użyciu kodowania UTF-8.</p>
+
+<p>Przykładowy program (napisany w Pythonie), obrazujący wykorzystanie
+każdego z tych sposobów, można znaleźć
+<a href="https://github.com/fnp/lesmianator">w naszym repozytorium na GitHubie</a>.
+Jest to po prostu Leśmianator – w wersji przygotowanej zgodnie z warunkami
+turnieju.</p>
+
+
+<h3>Gdzie wysyłać zgłoszenia?</h3>
+
+<p>Zgłoszenia, a także wszelkiego rodzaju pytania i wątpliwości prosimy kierować na adres
+<a href="mailto:radoslaw.czajka@nowoczesnapolska.org.pl">radoslaw.czajka@nowoczesnapolska.org.pl</a>.
+Prosimy też o dołączenie do każdego zgłoszenia klauzuli o treści:
+<cite>Zgłaszam się do konkursu „Turniej Elektrybałtów” i oświadczam, że
+znam i akceptuję jego <a href="{% url rules_page %}">regulamin</a></cite>.
+
+</p>
+
+
+
+
+<p class='more'><a href="{% url main_page %}">Powrót do strony głównej</a></p>
+
+
+{% endblock %}
+
--- /dev/null
+from django.conf.urls.defaults import patterns, include, url
+from django.views.generic.simple import direct_to_template
+
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('',
+ url(r'^$', 'turniej.views.home', name='main_page'),
+
+ url(r'^regulamin/$', direct_to_template, {'template': 'pages/rules.html'},
+ name='rules_page'),
+ url(r'^wiecej/$', direct_to_template, {'template': 'pages/more.html'},
+ name='more_page'),
+ url(r'^technikalia/$', direct_to_template, {'template': 'pages/technical.html'},
+ name='technical_page'),
+
+ url(r'^poezja/', include('poetry.urls')),
+
+ # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+ # url(r'^admin/', include(admin.site.urls)),
+)
--- /dev/null
+from django.shortcuts import render
+from poetry.models import Poem
+
+def home(request):
+ last = Poem.objects.all().order_by('-created_at')[:10]
+ return render(request, "home.html", locals())