initial commit
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Tue, 15 Nov 2011 11:23:04 +0000 (12:23 +0100)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Tue, 15 Nov 2011 11:29:46 +0000 (12:29 +0100)
41 files changed:
.gitignore [new file with mode: 0644]
apps/poetry/__init__.py [new file with mode: 0644]
apps/poetry/migrations/0001_initial.py [new file with mode: 0644]
apps/poetry/migrations/__init__.py [new file with mode: 0644]
apps/poetry/models.py [new file with mode: 0644]
apps/poetry/static/poetry/poem.css [new file with mode: 0644]
apps/poetry/templates/poetry/main.html [new file with mode: 0644]
apps/poetry/templates/poetry/poem.html [new file with mode: 0644]
apps/poetry/templates/poetry/poet.html [new file with mode: 0644]
apps/poetry/urls.py [new file with mode: 0644]
apps/poetry/utils.py [new file with mode: 0644]
apps/poetry/views.py [new file with mode: 0644]
fabfile.py [new file with mode: 0644]
lib/git-archive-all.sh [new file with mode: 0644]
requirements-dev.txt [new file with mode: 0644]
requirements.txt [new file with mode: 0644]
turniej.vhost.template [new file with mode: 0644]
turniej.wsgi.template [new file with mode: 0644]
turniej/__init__.py [new file with mode: 0644]
turniej/localsettings.py.template [new file with mode: 0644]
turniej/manage.py [new file with mode: 0755]
turniej/settings.py [new file with mode: 0644]
turniej/static/img/cc.png [new file with mode: 0644]
turniej/static/img/di.png [new file with mode: 0644]
turniej/static/img/favicon.ico [new file with mode: 0644]
turniej/static/img/fnp.png [new file with mode: 0644]
turniej/static/img/koed.png [new file with mode: 0644]
turniej/static/img/lempl.png [new file with mode: 0644]
turniej/static/img/turniej-maly.png [new file with mode: 0644]
turniej/static/img/turniej.png [new file with mode: 0644]
turniej/static/img/wl.png [new file with mode: 0644]
turniej/static/style.css [new file with mode: 0644]
turniej/templates/404.html [new file with mode: 0644]
turniej/templates/500.html [new file with mode: 0644]
turniej/templates/base.html [new file with mode: 0644]
turniej/templates/home.html [new file with mode: 0644]
turniej/templates/pages/more.html [new file with mode: 0644]
turniej/templates/pages/rules.html [new file with mode: 0644]
turniej/templates/pages/technical.html [new file with mode: 0644]
turniej/urls.py [new file with mode: 0644]
turniej/views.py [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d1146e9
--- /dev/null
@@ -0,0 +1,23 @@
+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_*
+
diff --git a/apps/poetry/__init__.py b/apps/poetry/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/poetry/migrations/0001_initial.py b/apps/poetry/migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..c6bfda3
--- /dev/null
@@ -0,0 +1,78 @@
+# 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']
diff --git a/apps/poetry/migrations/__init__.py b/apps/poetry/migrations/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/poetry/models.py b/apps/poetry/models.py
new file mode 100644 (file)
index 0000000..39f3e05
--- /dev/null
@@ -0,0 +1,73 @@
+# -*- 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()
diff --git a/apps/poetry/static/poetry/poem.css b/apps/poetry/static/poetry/poem.css
new file mode 100644 (file)
index 0000000..e2f6f01
--- /dev/null
@@ -0,0 +1,137 @@
+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;}
+}
diff --git a/apps/poetry/templates/poetry/main.html b/apps/poetry/templates/poetry/main.html
new file mode 100644 (file)
index 0000000..76fdf09
--- /dev/null
@@ -0,0 +1,62 @@
+{% 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 %}
diff --git a/apps/poetry/templates/poetry/poem.html b/apps/poetry/templates/poetry/poem.html
new file mode 100644 (file)
index 0000000..55bf749
--- /dev/null
@@ -0,0 +1,86 @@
+{% 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>
+
+
diff --git a/apps/poetry/templates/poetry/poet.html b/apps/poetry/templates/poetry/poet.html
new file mode 100644 (file)
index 0000000..053dce5
--- /dev/null
@@ -0,0 +1,44 @@
+{% 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 %}
diff --git a/apps/poetry/urls.py b/apps/poetry/urls.py
new file mode 100644 (file)
index 0000000..8d0baeb
--- /dev/null
@@ -0,0 +1,11 @@
+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"),
+
+)
diff --git a/apps/poetry/utils.py b/apps/poetry/utils.py
new file mode 100644 (file)
index 0000000..76dce25
--- /dev/null
@@ -0,0 +1,10 @@
+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()
diff --git a/apps/poetry/views.py b/apps/poetry/views.py
new file mode 100644 (file)
index 0000000..06c95a2
--- /dev/null
@@ -0,0 +1,29 @@
+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())
diff --git a/fabfile.py b/fabfile.py
new file mode 100644 (file)
index 0000000..eb30a2f
--- /dev/null
@@ -0,0 +1,200 @@
+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)
diff --git a/lib/git-archive-all.sh b/lib/git-archive-all.sh
new file mode 100644 (file)
index 0000000..95e8582
--- /dev/null
@@ -0,0 +1,208 @@
+#!/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
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644 (file)
index 0000000..aec394f
--- /dev/null
@@ -0,0 +1 @@
+django-debug-toolbar
diff --git a/requirements.txt b/requirements.txt
new file mode 100644 (file)
index 0000000..2e16d22
--- /dev/null
@@ -0,0 +1,5 @@
+# Django basics
+django>=1.3,<1.4
+South>=0.7
+
+piwik
diff --git a/turniej.vhost.template b/turniej.vhost.template
new file mode 100644 (file)
index 0000000..3caae7f
--- /dev/null
@@ -0,0 +1,31 @@
+<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>
diff --git a/turniej.wsgi.template b/turniej.wsgi.template
new file mode 100644 (file)
index 0000000..af1781c
--- /dev/null
@@ -0,0 +1,26 @@
+#!%(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()
diff --git a/turniej/__init__.py b/turniej/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/turniej/localsettings.py.template b/turniej/localsettings.py.template
new file mode 100644 (file)
index 0000000..3765080
--- /dev/null
@@ -0,0 +1,27 @@
+# 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/'
diff --git a/turniej/manage.py b/turniej/manage.py
new file mode 100755 (executable)
index 0000000..eb91c2d
--- /dev/null
@@ -0,0 +1,26 @@
+#!/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)
diff --git a/turniej/settings.py b/turniej/settings.py
new file mode 100644 (file)
index 0000000..62a66e5
--- /dev/null
@@ -0,0 +1,158 @@
+# -*- 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
diff --git a/turniej/static/img/cc.png b/turniej/static/img/cc.png
new file mode 100644 (file)
index 0000000..1de9d62
Binary files /dev/null and b/turniej/static/img/cc.png differ
diff --git a/turniej/static/img/di.png b/turniej/static/img/di.png
new file mode 100644 (file)
index 0000000..8136626
Binary files /dev/null and b/turniej/static/img/di.png differ
diff --git a/turniej/static/img/favicon.ico b/turniej/static/img/favicon.ico
new file mode 100644 (file)
index 0000000..89067a8
Binary files /dev/null and b/turniej/static/img/favicon.ico differ
diff --git a/turniej/static/img/fnp.png b/turniej/static/img/fnp.png
new file mode 100644 (file)
index 0000000..fe75e2d
Binary files /dev/null and b/turniej/static/img/fnp.png differ
diff --git a/turniej/static/img/koed.png b/turniej/static/img/koed.png
new file mode 100644 (file)
index 0000000..6bcce17
Binary files /dev/null and b/turniej/static/img/koed.png differ
diff --git a/turniej/static/img/lempl.png b/turniej/static/img/lempl.png
new file mode 100644 (file)
index 0000000..51c9b9e
Binary files /dev/null and b/turniej/static/img/lempl.png differ
diff --git a/turniej/static/img/turniej-maly.png b/turniej/static/img/turniej-maly.png
new file mode 100644 (file)
index 0000000..b11f0d6
Binary files /dev/null and b/turniej/static/img/turniej-maly.png differ
diff --git a/turniej/static/img/turniej.png b/turniej/static/img/turniej.png
new file mode 100644 (file)
index 0000000..dbcbda4
Binary files /dev/null and b/turniej/static/img/turniej.png differ
diff --git a/turniej/static/img/wl.png b/turniej/static/img/wl.png
new file mode 100644 (file)
index 0000000..1d6cb6a
Binary files /dev/null and b/turniej/static/img/wl.png differ
diff --git a/turniej/static/style.css b/turniej/static/style.css
new file mode 100644 (file)
index 0000000..f26fe8e
--- /dev/null
@@ -0,0 +1,148 @@
+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: "» ";
+}
diff --git a/turniej/templates/404.html b/turniej/templates/404.html
new file mode 100644 (file)
index 0000000..5bfd7f8
--- /dev/null
@@ -0,0 +1,8 @@
+{% 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 %}
diff --git a/turniej/templates/500.html b/turniej/templates/500.html
new file mode 100644 (file)
index 0000000..0940a22
--- /dev/null
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+
+{% block "body" %}
+<h1>Błąd</h1>
+
+<p>Wystąpił błąd serwera. Przepraszamy!</p>
+
+{% endblock %}
diff --git a/turniej/templates/base.html b/turniej/templates/base.html
new file mode 100644 (file)
index 0000000..4b28f18
--- /dev/null
@@ -0,0 +1,36 @@
+<!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>
diff --git a/turniej/templates/home.html b/turniej/templates/home.html
new file mode 100644 (file)
index 0000000..d0eb78e
--- /dev/null
@@ -0,0 +1,97 @@
+{% 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="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#114;&#97;&#100;&#111;&#115;&#108;&#97;&#119;&#46;&#99;&#122;&#97;&#106;&#107;&#97;&#64;&#110;&#111;&#119;&#111;&#99;&#122;&#101;&#115;&#110;&#97;&#112;&#111;&#108;&#115;&#107;&#97;&#46;&#111;&#114;&#103;&#46;&#112;&#108;">&#114;&#97;&#100;&#111;&#115;&#108;&#97;&#119;&#46;&#99;&#122;&#97;&#106;&#107;&#97;&#64;&#110;&#111;&#119;&#111;&#99;&#122;&#101;&#115;&#110;&#97;&#112;&#111;&#108;&#115;&#107;&#97;&#46;&#111;&#114;&#103;&#46;&#112;&#108;</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 %}
diff --git a/turniej/templates/pages/more.html b/turniej/templates/pages/more.html
new file mode 100644 (file)
index 0000000..c60db14
--- /dev/null
@@ -0,0 +1,65 @@
+{% 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 %}
diff --git a/turniej/templates/pages/rules.html b/turniej/templates/pages/rules.html
new file mode 100644 (file)
index 0000000..8dce0f5
--- /dev/null
@@ -0,0 +1,74 @@
+{% 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="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#114;&#97;&#100;&#111;&#115;&#108;&#97;&#119;&#46;&#99;&#122;&#97;&#106;&#107;&#97;&#64;&#110;&#111;&#119;&#111;&#99;&#122;&#101;&#115;&#110;&#97;&#112;&#111;&#108;&#115;&#107;&#97;&#46;&#111;&#114;&#103;&#46;&#112;&#108;">&#114;&#97;&#100;&#111;&#115;&#108;&#97;&#119;&#46;&#99;&#122;&#97;&#106;&#107;&#97;&#64;&#110;&#111;&#119;&#111;&#99;&#122;&#101;&#115;&#110;&#97;&#112;&#111;&#108;&#115;&#107;&#97;&#46;&#111;&#114;&#103;&#46;&#112;&#108;</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 %}
diff --git a/turniej/templates/pages/technical.html b/turniej/templates/pages/technical.html
new file mode 100644 (file)
index 0000000..d236dcf
--- /dev/null
@@ -0,0 +1,115 @@
+{% 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="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#114;&#97;&#100;&#111;&#115;&#108;&#97;&#119;&#46;&#99;&#122;&#97;&#106;&#107;&#97;&#64;&#110;&#111;&#119;&#111;&#99;&#122;&#101;&#115;&#110;&#97;&#112;&#111;&#108;&#115;&#107;&#97;&#46;&#111;&#114;&#103;&#46;&#112;&#108;">&#114;&#97;&#100;&#111;&#115;&#108;&#97;&#119;&#46;&#99;&#122;&#97;&#106;&#107;&#97;&#64;&#110;&#111;&#119;&#111;&#99;&#122;&#101;&#115;&#110;&#97;&#112;&#111;&#108;&#115;&#107;&#97;&#46;&#111;&#114;&#103;&#46;&#112;&#108;</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 %}
+    
diff --git a/turniej/urls.py b/turniej/urls.py
new file mode 100644 (file)
index 0000000..2a2a2f1
--- /dev/null
@@ -0,0 +1,21 @@
+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)),
+)
diff --git a/turniej/views.py b/turniej/views.py
new file mode 100644 (file)
index 0000000..3fe0a87
--- /dev/null
@@ -0,0 +1,6 @@
+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())