From f4921ca797953ddab6b35786864b2dd523190503 Mon Sep 17 00:00:00 2001
From: Radek Czajka
Date: Wed, 8 Jun 2011 15:03:59 +0200
Subject: [PATCH] teh legendary `Publish' button, oh yeah! authorization to
WLAPI through OAuth, marking revisions for publication
---
apps/apiclient/__init__.py | 46 ++++++++
.../migrations/0001_initial.py} | 65 ++++-------
apps/apiclient/migrations/__init__.py | 0
apps/apiclient/models.py | 20 ++++
apps/apiclient/settings.py | 15 +++
apps/apiclient/tests.py | 23 ++++
apps/apiclient/urls.py | 6 ++
apps/apiclient/views.py | 60 +++++++++++
apps/dvcs/migrations/0001_initial.py | 33 ++++++
apps/dvcs/models.py | 5 +-
apps/wiki/forms.py | 14 ++-
...unique_chunk_book_number__add_unique_ch.py | 13 +++
.../0004_auto__add_field_book__list_html.py | 102 ------------------
apps/wiki/models.py | 16 +--
apps/wiki/templates/wiki/book_detail.html | 15 ++-
.../wiki/templates/wiki/document_details.html | 1 +
apps/wiki/templates/wiki/pubmark_dialog.html | 19 ++++
.../templates/wiki/tabs/history_view.html | 6 +-
apps/wiki/urls.py | 3 +-
apps/wiki/views.py | 58 ++++++----
redakcja/settings/common.py | 3 +-
redakcja/settings/compress.py | 1 +
redakcja/static/css/filelist.css | 27 +++++
redakcja/static/img/angel-left.png | Bin 0 -> 43913 bytes
redakcja/static/img/angel-right.png | Bin 0 -> 41705 bytes
redakcja/static/js/wiki/dialog_pubmark.js | 61 +++++++++++
redakcja/static/js/wiki/view_history.js | 16 +++
redakcja/static/js/wiki/wikiapi.js | 43 ++++++++
redakcja/urls.py | 1 +
requirements.txt | 2 +
30 files changed, 489 insertions(+), 185 deletions(-)
create mode 100644 apps/apiclient/__init__.py
rename apps/{dvcs/migrations/0002_auto__add_tag.py => apiclient/migrations/0001_initial.py} (50%)
create mode 100644 apps/apiclient/migrations/__init__.py
create mode 100644 apps/apiclient/models.py
create mode 100755 apps/apiclient/settings.py
create mode 100644 apps/apiclient/tests.py
create mode 100755 apps/apiclient/urls.py
create mode 100644 apps/apiclient/views.py
delete mode 100644 apps/wiki/migrations/0004_auto__add_field_book__list_html.py
create mode 100755 apps/wiki/templates/wiki/pubmark_dialog.html
create mode 100644 redakcja/static/img/angel-left.png
create mode 100644 redakcja/static/img/angel-right.png
create mode 100755 redakcja/static/js/wiki/dialog_pubmark.js
diff --git a/apps/apiclient/__init__.py b/apps/apiclient/__init__.py
new file mode 100644
index 00000000..7913ac3c
--- /dev/null
+++ b/apps/apiclient/__init__.py
@@ -0,0 +1,46 @@
+import urllib
+
+from django.utils import simplejson
+import oauth2
+
+from apiclient.models import OAuthConnection
+from apiclient.settings import WL_CONSUMER_KEY, WL_CONSUMER_SECRET, WL_API_URL
+
+
+if WL_CONSUMER_KEY and WL_CONSUMER_SECRET:
+ wl_consumer = oauth2.Consumer(WL_CONSUMER_KEY, WL_CONSUMER_SECRET)
+else:
+ wl_consumer = None
+
+
+class ApiError(BaseException):
+ pass
+
+
+class NotAuthorizedError(BaseException):
+ pass
+
+
+def api_call(user, path, data=None):
+ # what if not verified?
+ conn = OAuthConnection.get(user)
+ if not conn.access:
+ raise NotAuthorizedError("No WL authorization for user %s." % user)
+ token = oauth2.Token(conn.token, conn.token_secret)
+ client = oauth2.Client(wl_consumer, token)
+ if data is not None:
+ resp, content = client.request(
+ "%s%s.json" % (WL_API_URL, path),
+ method="POST",
+ body=urllib.urlencode(data))
+ else:
+ resp, content = client.request(
+ "%s%s.json" % (WL_API_URL, path))
+ status = resp['status']
+ if status == '200':
+ return simplejson.loads(content)
+ elif status.startswith('2'):
+ return
+ else:
+ raise ApiError("WL API call error")
+
diff --git a/apps/dvcs/migrations/0002_auto__add_tag.py b/apps/apiclient/migrations/0001_initial.py
similarity index 50%
rename from apps/dvcs/migrations/0002_auto__add_tag.py
rename to apps/apiclient/migrations/0001_initial.py
index 7f5b9a3e..4af28a52 100644
--- a/apps/dvcs/migrations/0002_auto__add_tag.py
+++ b/apps/apiclient/migrations/0001_initial.py
@@ -8,34 +8,32 @@ class Migration(SchemaMigration):
def forwards(self, orm):
- # Adding model 'Tag'
- db.create_table('dvcs_tag', (
+ # Adding model 'OAuthConnection'
+ db.create_table('apiclient_oauthconnection', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=64)),
- ('slug', self.gf('django.db.models.fields.SlugField')(db_index=True, max_length=64, unique=True, null=True, blank=True)),
- ('ordering', self.gf('django.db.models.fields.IntegerField')()),
+ ('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)),
+ ('access', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ('token', self.gf('django.db.models.fields.CharField')(max_length=64, null=True, blank=True)),
+ ('token_secret', self.gf('django.db.models.fields.CharField')(max_length=64, null=True, blank=True)),
))
- db.send_create_signal('dvcs', ['Tag'])
-
- # Adding M2M table for field tags on 'Change'
- db.create_table('dvcs_change_tags', (
- ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
- ('change', models.ForeignKey(orm['dvcs.change'], null=False)),
- ('tag', models.ForeignKey(orm['dvcs.tag'], null=False))
- ))
- db.create_unique('dvcs_change_tags', ['change_id', 'tag_id'])
+ db.send_create_signal('apiclient', ['OAuthConnection'])
def backwards(self, orm):
- # Deleting model 'Tag'
- db.delete_table('dvcs_tag')
-
- # Removing M2M table for field tags on 'Change'
- db.delete_table('dvcs_change_tags')
+ # Deleting model 'OAuthConnection'
+ db.delete_table('apiclient_oauthconnection')
models = {
+ 'apiclient.oauthconnection': {
+ 'Meta': {'object_name': 'OAuthConnection'},
+ 'access': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'token': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}),
+ 'token_secret': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
+ },
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
@@ -71,34 +69,7 @@ class Migration(SchemaMigration):
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- 'dvcs.change': {
- 'Meta': {'ordering': "('created_at',)", 'unique_together': "(['tree', 'revision'],)", 'object_name': 'Change'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
- 'author_desc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
- 'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'merge_parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'merge_children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
- 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
- 'patch': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'revision': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['dvcs.Tag']", 'symmetrical': 'False'}),
- 'tree': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dvcs.Document']"})
- },
- 'dvcs.document': {
- 'Meta': {'object_name': 'Document'},
- 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
- 'head': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['dvcs.Change']", 'null': 'True', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- 'dvcs.tag': {
- 'Meta': {'ordering': "['ordering']", 'object_name': 'Tag'},
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'ordering': ('django.db.models.fields.IntegerField', [], {}),
- 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
- complete_apps = ['dvcs']
+ complete_apps = ['apiclient']
diff --git a/apps/apiclient/migrations/__init__.py b/apps/apiclient/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/apiclient/models.py b/apps/apiclient/models.py
new file mode 100644
index 00000000..d3c8f620
--- /dev/null
+++ b/apps/apiclient/models.py
@@ -0,0 +1,20 @@
+from django.db import models
+from django.contrib.auth.models import User
+
+
+class OAuthConnection(models.Model):
+ user = models.OneToOneField(User)
+ access = models.BooleanField(default=False)
+ token = models.CharField(max_length=64, null=True, blank=True)
+ token_secret = models.CharField(max_length=64, null=True, blank=True)
+
+ @classmethod
+ def get(cls, user):
+ try:
+ return cls.objects.get(user=user)
+ except cls.DoesNotExist:
+ o = cls(user=user)
+ o.save()
+ return o
+
+
diff --git a/apps/apiclient/settings.py b/apps/apiclient/settings.py
new file mode 100755
index 00000000..5fbf18ee
--- /dev/null
+++ b/apps/apiclient/settings.py
@@ -0,0 +1,15 @@
+from django.conf import settings
+
+
+WL_CONSUMER_KEY = getattr(settings, 'APICLIENT_WL_CONSUMER_KEY', None)
+WL_CONSUMER_SECRET = getattr(settings, 'APICLIENT_WL_CONSUMER_SECRET', None)
+
+WL_API_URL = getattr(settings, 'APICLIENT_WL_API_URL',
+ 'http://www.wolnelektury.pl/api/')
+
+WL_REQUEST_TOKEN_URL = getattr(settings, 'APICLIENT_WL_REQUEST_TOKEN_URL',
+ WL_API_URL + 'oauth/request_token/')
+WL_ACCESS_TOKEN_URL = getattr(settings, 'APICLIENT_WL_ACCESS_TOKEN_URL',
+ WL_API_URL + 'oauth/access_token/')
+WL_AUTHORIZE_URL = getattr(settings, 'APICLIENT_WL_AUTHORIZE_URL',
+ WL_API_URL + 'oauth/authorize/')
diff --git a/apps/apiclient/tests.py b/apps/apiclient/tests.py
new file mode 100644
index 00000000..2247054b
--- /dev/null
+++ b/apps/apiclient/tests.py
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/apps/apiclient/urls.py b/apps/apiclient/urls.py
new file mode 100755
index 00000000..5e54965e
--- /dev/null
+++ b/apps/apiclient/urls.py
@@ -0,0 +1,6 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('apiclient.views',
+ url(r'^oauth/$', 'oauth', name='users_oauth'),
+ url(r'^oauth_callback/$', 'oauth_callback', name='users_oauth_callback'),
+)
diff --git a/apps/apiclient/views.py b/apps/apiclient/views.py
new file mode 100644
index 00000000..f8515904
--- /dev/null
+++ b/apps/apiclient/views.py
@@ -0,0 +1,60 @@
+import cgi
+
+from django.contrib.auth.decorators import login_required
+from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect, HttpResponse
+import oauth2
+
+from apiclient.models import OAuthConnection
+from apiclient import wl_consumer
+from apiclient.settings import (WL_REQUEST_TOKEN_URL, WL_ACCESS_TOKEN_URL,
+ WL_AUTHORIZE_URL)
+
+
+@login_required
+def oauth(request):
+ if wl_consumer is None:
+ return HttpResponse("OAuth consumer not configured.")
+
+ client = oauth2.Client(wl_consumer)
+ resp, content = client.request(WL_REQUEST_TOKEN_URL)
+ if resp['status'] != '200':
+ raise Exception("Invalid response %s." % resp['status'])
+
+ request_token = dict(cgi.parse_qsl(content))
+
+ conn = OAuthConnection.get(request.user)
+ # this might reset existing auth!
+ conn.access = False
+ conn.token = request_token['oauth_token']
+ conn.token_secret = request_token['oauth_token_secret']
+ conn.save()
+
+ url = "%s?oauth_token=%s&oauth_callback=%s" % (
+ WL_AUTHORIZE_URL,
+ request_token['oauth_token'],
+ request.build_absolute_uri(reverse("users_oauth_callback")),
+ )
+
+ return HttpResponseRedirect(url)
+
+
+@login_required
+def oauth_callback(request):
+ if wl_consumer is None:
+ return HttpResponse("OAuth consumer not configured.")
+
+ oauth_verifier = request.GET.get('oauth_verifier')
+ conn = OAuthConnection.get(request.user)
+ token = oauth2.Token(conn.token, conn.token_secret)
+ token.set_verifier(oauth_verifier)
+ client = oauth2.Client(wl_consumer, token)
+ resp, content = client.request(WL_ACCESS_TOKEN_URL, method="POST")
+ access_token = dict(cgi.parse_qsl(content))
+
+ conn.access = True
+ conn.token = access_token['oauth_token']
+ conn.token_secret = access_token['oauth_token_secret']
+ conn.save()
+
+ return HttpResponseRedirect('/')
diff --git a/apps/dvcs/migrations/0001_initial.py b/apps/dvcs/migrations/0001_initial.py
index 7510e8ad..d9f0984c 100644
--- a/apps/dvcs/migrations/0001_initial.py
+++ b/apps/dvcs/migrations/0001_initial.py
@@ -8,6 +8,15 @@ class Migration(SchemaMigration):
def forwards(self, orm):
+ # Adding model 'Tag'
+ db.create_table('dvcs_tag', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=64)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(db_index=True, max_length=64, unique=True, null=True, blank=True)),
+ ('ordering', self.gf('django.db.models.fields.IntegerField')()),
+ ))
+ db.send_create_signal('dvcs', ['Tag'])
+
# Adding model 'Change'
db.create_table('dvcs_change', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
@@ -20,12 +29,21 @@ class Migration(SchemaMigration):
('merge_parent', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='merge_children', null=True, blank=True, to=orm['dvcs.Change'])),
('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)),
('created_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now, db_index=True)),
+ ('publishable', self.gf('django.db.models.fields.BooleanField')(default=False)),
))
db.send_create_signal('dvcs', ['Change'])
# Adding unique constraint on 'Change', fields ['tree', 'revision']
db.create_unique('dvcs_change', ['tree_id', 'revision'])
+ # Adding M2M table for field tags on 'Change'
+ db.create_table('dvcs_change_tags', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('change', models.ForeignKey(orm['dvcs.change'], null=False)),
+ ('tag', models.ForeignKey(orm['dvcs.tag'], null=False))
+ ))
+ db.create_unique('dvcs_change_tags', ['change_id', 'tag_id'])
+
# Adding model 'Document'
db.create_table('dvcs_document', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
@@ -40,9 +58,15 @@ class Migration(SchemaMigration):
# Removing unique constraint on 'Change', fields ['tree', 'revision']
db.delete_unique('dvcs_change', ['tree_id', 'revision'])
+ # Deleting model 'Tag'
+ db.delete_table('dvcs_tag')
+
# Deleting model 'Change'
db.delete_table('dvcs_change')
+ # Removing M2M table for field tags on 'Change'
+ db.delete_table('dvcs_change_tags')
+
# Deleting model 'Document'
db.delete_table('dvcs_document')
@@ -94,7 +118,9 @@ class Migration(SchemaMigration):
'merge_parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'merge_children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
'patch': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'publishable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['dvcs.Tag']", 'symmetrical': 'False'}),
'tree': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dvcs.Document']"})
},
'dvcs.document': {
@@ -102,6 +128,13 @@ class Migration(SchemaMigration):
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['dvcs.Change']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'dvcs.tag': {
+ 'Meta': {'ordering': "['ordering']", 'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'ordering': ('django.db.models.fields.IntegerField', [], {}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
diff --git a/apps/dvcs/models.py b/apps/dvcs/models.py
index dddbf3ad..262472a3 100644
--- a/apps/dvcs/models.py
+++ b/apps/dvcs/models.py
@@ -66,6 +66,7 @@ class Change(models.Model):
description = models.TextField(blank=True, default='')
created_at = models.DateTimeField(editable=False, db_index=True,
default=datetime.now)
+ publishable = models.BooleanField(default=False)
tags = models.ManyToManyField(Tag)
@@ -245,8 +246,8 @@ class Document(models.Model):
else:
return self.head
- def last_tagged(self, tag):
- changes = tag.change_set.filter(tree=self).order_by('-created_at')[:1]
+ def publishable(self):
+ changes = self.change_set.filter(publishable=True).order_by('-created_at')[:1]
if changes.count():
return changes[0]
else:
diff --git a/apps/wiki/forms.py b/apps/wiki/forms.py
index fb0f958a..55b1e544 100644
--- a/apps/wiki/forms.py
+++ b/apps/wiki/forms.py
@@ -20,6 +20,17 @@ class DocumentTagForm(forms.Form):
revision = forms.IntegerField(widget=forms.HiddenInput)
+class DocumentPubmarkForm(forms.Form):
+ """
+ Form for marking revisions for publishing.
+ """
+
+ id = forms.CharField(widget=forms.HiddenInput)
+ publishable = forms.BooleanField(required=False, initial=True,
+ label=_('Publishable'))
+ revision = forms.IntegerField(widget=forms.HiddenInput)
+
+
class DocumentCreateForm(forms.ModelForm):
"""
Form used for creating new documents.
@@ -180,7 +191,8 @@ class BookAppendForm(forms.Form):
It means moving all chunks from book A to book B and deleting A.
"""
- append_to = forms.ModelChoiceField(queryset=Book.objects.all())
+ append_to = forms.ModelChoiceField(queryset=Book.objects.all(),
+ label=_("Append to"))
class BookForm(forms.ModelForm):
diff --git a/apps/wiki/migrations/0003_auto__add_book__add_chunk__add_unique_chunk_book_number__add_unique_ch.py b/apps/wiki/migrations/0003_auto__add_book__add_chunk__add_unique_chunk_book_number__add_unique_ch.py
index 229825d2..010ed2a6 100644
--- a/apps/wiki/migrations/0003_auto__add_book__add_chunk__add_unique_chunk_book_number__add_unique_ch.py
+++ b/apps/wiki/migrations/0003_auto__add_book__add_chunk__add_unique_chunk_book_number__add_unique_ch.py
@@ -151,6 +151,8 @@ class Migration(SchemaMigration):
('gallery', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
('parent', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='children', null=True, to=orm['wiki.Book'])),
('parent_number', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)),
+ ('last_published', self.gf('django.db.models.fields.DateTimeField')(null=True)),
+ ('_list_html', self.gf('django.db.models.fields.TextField')(null=True)),
))
db.send_create_signal('wiki', ['Book'])
@@ -235,7 +237,9 @@ class Migration(SchemaMigration):
'merge_parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'merge_children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
'patch': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'publishable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['dvcs.Tag']", 'symmetrical': 'False'}),
'tree': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dvcs.Document']"})
},
'dvcs.document': {
@@ -244,10 +248,19 @@ class Migration(SchemaMigration):
'head': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['dvcs.Change']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
+ 'dvcs.tag': {
+ 'Meta': {'ordering': "['ordering']", 'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'ordering': ('django.db.models.fields.IntegerField', [], {}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'})
+ },
'wiki.book': {
'Meta': {'ordering': "['parent_number', 'title']", 'object_name': 'Book'},
+ '_list_html': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'gallery': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_published': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['wiki.Book']"}),
'parent_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
diff --git a/apps/wiki/migrations/0004_auto__add_field_book__list_html.py b/apps/wiki/migrations/0004_auto__add_field_book__list_html.py
deleted file mode 100644
index a09dc90e..00000000
--- a/apps/wiki/migrations/0004_auto__add_field_book__list_html.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# 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 field 'Book._list_html'
- db.add_column('wiki_book', '_list_html', self.gf('django.db.models.fields.TextField')(null=True), keep_default=False)
-
-
- def backwards(self, orm):
-
- # Deleting field 'Book._list_html'
- db.delete_column('wiki_book', '_list_html')
-
-
- models = {
- 'auth.group': {
- 'Meta': {'object_name': 'Group'},
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- 'auth.permission': {
- 'Meta': {'ordering': "('content_type__app_label', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- 'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- 'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- 'dvcs.change': {
- 'Meta': {'ordering': "('created_at',)", 'unique_together': "(['tree', 'revision'],)", 'object_name': 'Change'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
- 'author_desc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
- 'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'merge_parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'merge_children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
- 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
- 'patch': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'revision': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'tree': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dvcs.Document']"})
- },
- 'dvcs.document': {
- 'Meta': {'object_name': 'Document'},
- 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
- 'head': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['dvcs.Change']", 'null': 'True', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- 'wiki.book': {
- 'Meta': {'ordering': "['parent_number', 'title']", 'object_name': 'Book'},
- '_list_html': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- 'gallery': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['wiki.Book']"}),
- 'parent_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- 'wiki.chunk': {
- 'Meta': {'ordering': "['number']", 'unique_together': "[['book', 'number'], ['book', 'slug']]", 'object_name': 'Chunk', '_ormbases': ['dvcs.Document']},
- 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['wiki.Book']"}),
- 'comment': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'document_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['dvcs.Document']", 'unique': 'True', 'primary_key': 'True'}),
- 'number': ('django.db.models.fields.IntegerField', [], {}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'})
- },
- 'wiki.theme': {
- 'Meta': {'ordering': "('name',)", 'object_name': 'Theme'},
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'})
- }
- }
-
- complete_apps = ['wiki']
diff --git a/apps/wiki/models.py b/apps/wiki/models.py
index 4dc70173..7887e5da 100644
--- a/apps/wiki/models.py
+++ b/apps/wiki/models.py
@@ -28,6 +28,7 @@ class Book(models.Model):
parent = models.ForeignKey('self', null=True, blank=True, verbose_name=_('parent'), related_name="children")
parent_number = models.IntegerField(_('parent number'), null=True, blank=True, db_index=True)
+ last_published = models.DateTimeField(null=True, editable=False)
_list_html = models.TextField(editable=False, null=True)
@@ -78,18 +79,14 @@ class Book(models.Model):
self.save(reset_list_html=False)
return mark_safe(self._list_html)
- @staticmethod
- def publish_tag():
- return dvcs_models.Tag.get('publish')
-
- def materialize(self, tag=None):
+ def materialize(self, publishable=True):
"""
Get full text of the document compiled from chunks.
Takes the current versions of all texts
- or versions most recently tagged by a given tag.
+ or versions most recently tagged for publishing.
"""
- if tag:
- changes = [chunk.last_tagged(tag) for chunk in self]
+ if publishable:
+ changes = [chunk.publishable() for chunk in self]
else:
changes = [chunk.head for chunk in self]
if None in changes:
@@ -183,9 +180,6 @@ class Chunk(dvcs_models.Document):
return "%s, %s (%d/%d)" % (self.book.title, self.comment,
self.number, len(self.book))
- def publishable(self):
- return self.last_tagged(Book.publish_tag())
-
def split(self, slug, comment='', creator=None):
""" Create an empty chunk after this one """
self.book.chunk_set.filter(number__gt=self.number).update(
diff --git a/apps/wiki/templates/wiki/book_detail.html b/apps/wiki/templates/wiki/book_detail.html
index 26f52145..f4b15a9e 100755
--- a/apps/wiki/templates/wiki/book_detail.html
+++ b/apps/wiki/templates/wiki/book_detail.html
@@ -62,6 +62,8 @@
{% trans "Append to other book" %}
+{% trans "Last published" %}: {{ book.last_published }}
+
{% if book.publishable %}
{% trans "Full XML" %}
@@ -73,7 +75,18 @@
{% endcomment %}
-
+
+
{% else %}
{% trans "This book cannot be published yet" %}
{% endif %}
diff --git a/apps/wiki/templates/wiki/document_details.html b/apps/wiki/templates/wiki/document_details.html
index 934a8ac6..d95603f6 100644
--- a/apps/wiki/templates/wiki/document_details.html
+++ b/apps/wiki/templates/wiki/document_details.html
@@ -43,4 +43,5 @@
{% include "wiki/save_dialog.html" %}
{% include "wiki/revert_dialog.html" %}
{% include "wiki/tag_dialog.html" %}
+ {% include "wiki/pubmark_dialog.html" %}
{% endblock %}
diff --git a/apps/wiki/templates/wiki/pubmark_dialog.html b/apps/wiki/templates/wiki/pubmark_dialog.html
new file mode 100755
index 00000000..93a98563
--- /dev/null
+++ b/apps/wiki/templates/wiki/pubmark_dialog.html
@@ -0,0 +1,19 @@
+{% load i18n %}
+
diff --git a/apps/wiki/templates/wiki/tabs/history_view.html b/apps/wiki/templates/wiki/tabs/history_view.html
index 60c59a95..db207bb1 100644
--- a/apps/wiki/templates/wiki/tabs/history_view.html
+++ b/apps/wiki/templates/wiki/tabs/history_view.html
@@ -5,6 +5,8 @@
data-enabled-when="2" disabled="disabled">{% trans "Compare versions" %}
+
,
-
+ |
+
+
|
diff --git a/apps/wiki/urls.py b/apps/wiki/urls.py
index 393afa5e..c7da6ef8 100644
--- a/apps/wiki/urls.py
+++ b/apps/wiki/urls.py
@@ -43,11 +43,12 @@ urlpatterns = patterns('wiki.views',
url(r'^revert/(?P[^/]+)/(?:(?P[^/]+)/)?$',
'revert', name='wiki_revert'),
- #url(r'^(?P[^/]+)/publish$', 'publish', name="wiki_publish"),
+ url(r'^book/(?P[^/]+)/publish$', 'publish', name="wiki_publish"),
#url(r'^(?P[^/]+)/publish/(?P\d+)$', 'publish', name="wiki_publish"),
url(r'^diff/(?P[^/]+)/(?:(?P[^/]+)/)?$', 'diff', name="wiki_diff"),
url(r'^tag/(?P[^/]+)/(?:(?P[^/]+)/)?$', 'add_tag', name="wiki_add_tag"),
+ url(r'^pubmark/(?P[^/]+)/(?:(?P[^/]+)/)?$', 'pubmark', name="wiki_pubmark"),
url(r'^book/(?P[^/]+)/$', 'book', name="wiki_book"),
url(r'^book/(?P[^/]+)/xml$', 'book_xml', name="wiki_book_xml"),
diff --git a/apps/wiki/views.py b/apps/wiki/views.py
index 3739c90d..a68fa35d 100644
--- a/apps/wiki/views.py
+++ b/apps/wiki/views.py
@@ -7,6 +7,7 @@ from lxml import etree
from django.conf import settings
+from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
from django.views.decorators.http import require_POST, require_GET
from django.core.urlresolvers import reverse
@@ -27,6 +28,7 @@ from django.middleware.gzip import GZipMiddleware
import librarian.html
import librarian.text
from wiki import xml_tools
+from apiclient import api_call
#
# Quick hack around caching problems, TODO: use ETags
@@ -82,6 +84,7 @@ def editor(request, slug, chunk=None, template_name='wiki/document_details.html'
"text_save": forms.DocumentTextSaveForm(prefix="textsave"),
"text_revert": forms.DocumentTextRevertForm(prefix="textrevert"),
"add_tag": forms.DocumentTagForm(prefix="addtag"),
+ "pubmark": forms.DocumentPubmarkForm(prefix="pubmark"),
},
'REDMINE_URL': settings.REDMINE_URL,
})
@@ -254,7 +257,7 @@ def text(request, slug, chunk=None):
@never_cache
def book_xml(request, slug):
- xml = get_object_or_404(Book, slug=slug).materialize(Book.publish_tag())
+ xml = get_object_or_404(Book, slug=slug).materialize()
response = http.HttpResponse(xml, content_type='application/xml', mimetype='application/wl+xml')
response['Content-Disposition'] = 'attachment; filename=%s.xml' % slug
@@ -263,7 +266,7 @@ def book_xml(request, slug):
@never_cache
def book_txt(request, slug):
- xml = get_object_or_404(Book, slug=slug).materialize(Book.publish_tag())
+ xml = get_object_or_404(Book, slug=slug).materialize()
output = StringIO()
# errors?
librarian.text.transform(StringIO(xml), output)
@@ -275,7 +278,7 @@ def book_txt(request, slug):
@never_cache
def book_html(request, slug):
- xml = get_object_or_404(Book, slug=slug).materialize(Book.publish_tag())
+ xml = get_object_or_404(Book, slug=slug).materialize()
output = StringIO()
# errors?
librarian.html.transform(StringIO(xml), output, parse_dublincore=False,
@@ -391,6 +394,7 @@ def history(request, slug, chunk=None):
"description": change.description,
"author": change.author_str(),
"date": change.created_at,
+ "publishable": "Publishable\n" if change.publishable else "",
"tag": ',\n'.join(unicode(tag) for tag in change.tags.all()),
})
return JSONResponse(changes)
@@ -581,32 +585,50 @@ def add_tag(request, slug, chunk=None):
raise Http404
tag = form.cleaned_data['tag']
- revision = revision=form.cleaned_data['revision']
+ revision = form.cleaned_data['revision']
doc.at_revision(revision).tags.add(tag)
return JSONResponse({"message": _("Tag added")})
else:
return JSONFormInvalid(form)
-"""
-import wlapi
-
-
@require_POST
-@ajax_require_permission('wiki.can_publish')
-def publish(request, name):
- name = normalize_name(name)
+@ajax_require_permission('wiki.can_pubmark')
+def pubmark(request, slug, chunk=None):
+ form = forms.DocumentPubmarkForm(request.POST, prefix="pubmark")
+ if form.is_valid():
+ try:
+ doc = Chunk.get(slug, chunk)
+ except (Chunk.MultipleObjectsReturned, Chunk.DoesNotExist):
+ raise Http404
- storage = getstorage()
- document = storage.get_by_tag(name, "ready_to_publish")
+ revision = form.cleaned_data['revision']
+ publishable = form.cleaned_data['publishable']
+ change = doc.at_revision(revision)
+ print publishable, change.publishable
+ if publishable != change.publishable:
+ change.publishable = publishable
+ change.save()
+ return JSONResponse({"message": _("Revision marked")})
+ else:
+ return JSONResponse({"message": _("Nothing changed")})
+ else:
+ return JSONFormInvalid(form)
- api = wlapi.WLAPI(**settings.WL_API_CONFIG)
+@require_POST
+@login_required
+def publish(request, slug):
+ book = get_object_or_404(Book, slug=slug)
try:
- return JSONResponse({"result": api.publish_book(document)})
- except wlapi.APICallException, e:
- return JSONServerError({"message": str(e)})
-"""
+ ret = api_call(request.user, "books", {"book_xml": book.materialize()})
+ except BaseException, e:
+ return http.HttpResponse(e)
+ else:
+ book.last_published = datetime.now()
+ book.save()
+ return http.HttpResponseRedirect(book.get_absolute_url())
+
def themes(request):
prefix = request.GET.get('q', '')
diff --git a/redakcja/settings/common.py b/redakcja/settings/common.py
index 587374be..f5e90de3 100644
--- a/redakcja/settings/common.py
+++ b/redakcja/settings/common.py
@@ -117,10 +117,11 @@ INSTALLED_APPS = (
'south',
'sorl.thumbnail',
'filebrowser',
- 'dvcs',
+ 'dvcs',
'wiki',
'toolbar',
+ 'apiclient',
)
FILEBROWSER_URL_FILEBROWSER_MEDIA = STATIC_URL + 'filebrowser/'
diff --git a/redakcja/settings/compress.py b/redakcja/settings/compress.py
index 8bade8d0..5554aca8 100644
--- a/redakcja/settings/compress.py
+++ b/redakcja/settings/compress.py
@@ -45,6 +45,7 @@ COMPRESS_JS = {
'js/wiki/dialog_save.js',
'js/wiki/dialog_revert.js',
'js/wiki/dialog_addtag.js',
+ 'js/wiki/dialog_pubmark.js',
# views
'js/wiki/view_history.js',
diff --git a/redakcja/static/css/filelist.css b/redakcja/static/css/filelist.css
index 91323c0f..f6f55d7a 100644
--- a/redakcja/static/css/filelist.css
+++ b/redakcja/static/css/filelist.css
@@ -116,3 +116,30 @@ td {
.chunk-wl-broken a {color: red;}
.chunk-wl a {color: green;}
.chunk-wl-fix a {color: black;}
+
+
+/* Big cheesy publish button */
+#publish-button {
+ color: black;
+ border: 2px solid black;
+ border-radius: 20px;
+ box-shadow: 0px 0px 15px #88f;
+ /*moz-border-radius: 20px;
+ -moz-box-shadow: 10px 10px 5px #888;*/
+ font-size:1.5em;
+ padding: 1em;
+ background: -moz-linear-gradient(top, #fff, #44f);
+ -moz-transition: all 0.5s ease-in-out;
+ margin: 20px;
+}
+
+#publish-button:hover {
+ -moz-transition: all 0.5s ease-in-out;
+ -moz-transform: scale(1.1);
+ background: -moz-linear-gradient(top, #fff, #88f);
+ -moz-box-shadow: 0px 0px 30px #ff8;
+}
+
+#publish-button:active {
+ background: -moz-linear-gradient(top, #88f, #fff);
+}
diff --git a/redakcja/static/img/angel-left.png b/redakcja/static/img/angel-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..7744103dabeb188e94de36e92db96a7285af029d
GIT binary patch
literal 43913
zcmV)*K#9MJP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007bV*G`2ipb+
z2q6?^j|(LL000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}001BWNkl2)oy2h}5D1%vrDcH)OJE7GU}u4ag%B1(
zAS4??dMCw+;}Z97NtWayS-nrw^j`1thx0pUdG>eqx98a(kbThmoH?2!>CU}#@8@+t
zb-p7K1c7$NNL1vI#aVEMc}(&-+J*dHnS=OuJn8
zrai1!y_~hztmfG1ljPzNWThql<^7DzjtKbzJoVdG&=~Cm10lQtH*>BaCX1d;Yd26{
zQN@Mxmj#7biGMDMK_5q9v~cH!1x&i(__=OeKHq+oT1`VuHPs6ruAqBpA8
zyLUIqNSfPj-A*
zgUgo(n3|qMlut1^e2Jg`_+K{bOvVHM&ue--e&NRt|A49*C&^SAr?rx~K$LJOOjCUm
zg?x@cEP~G;#Zg{^MrT4P1CvFM+cn48lc&h%BUnrp7A{&z)4~?4MLM2-_Dx)~ZiYuk
zu{%nz71?QQXyPL`F5>m$<6IfO%=)$MR1{k%QO|psd075`)TO~mAurLQR2Z>1#pHpb
z2fMg^<5CVCAL9AvUZbYD4wX(yB<#gzv6IUQD3wa0p&+Bf{W$GKeEn-*`UAtJ
z-o0<5(-%=%T|y#KV9mPKwAI=hGwFqQyHop77o0>54YP-Rb?}??rEAAH}b1r
zJdD|3MkZGf@dsGGWD$vgkMDfvtA7AWz#9zQwEb3-#bIT}H;viu;F_gtaoURc)o&i5
zp}vk~%a^mJV=Li|i2i987Dq8Aoso1lMaUZ^6Y^3~qQhp>@!G4ekrxtJY-I%e0UB#-
zFTUo%iR6(yP2KxQ^=&z8)Pi0vx??NEaqYPKUUwRX<=cD
zlM4eW92H7_`^@vKy>=@anSz7w@1fLLib}0#eA34qAM0RnBtX~E!<1E)lgXtJWiq_}
z{Ih)H{;#m4ZNVSFGBPwQeD(fsQr%olnk0Ys#rx>)?C0pgi)`4?fkL4q6!CC*>A!q|`noFWs!bx@d>-?m(Eq3#*SIGnsElU12SbG7
zVV-#66>7?=2+g^8;rVB2s%=86)-g0PM8~xqTsZG%cEU?>X(fY0WAya&u>0M&*nI7}
z{{RZWqmMj7`-&ATT(k_CM91om?Y#QN5t`c;BT}iD^tg%UQ$!O1&Ye37nFtroognwY
z_6zK=q1{Ghl@p`Ez~Q4u5Q#)2;t7r)JW6OTOeUU2BU6)1r8sr&92%{POft*GOP6@)
zJD+CB!UY^Ve26tGm*AT9(LWdve4%XTys6H6mj8O_b)rjf1rwxlA|lBYQp7|fK^p4n
znV6kGiX3N28TMi``XUR_bPlshi5T$v6X=X;`Yv^Gsq+-y`Pvu%11N)omxbq^eu;{z
zM&ueZkxY*F_nl%x$97uUYnYiDV{&?cwuQ}1OpG%&HjB|vL^7PAthR)<#R~|`C5Qxq
zc-(`8qkhzC9pOZnGP?t@AR!UUlTN3pYgvHH?;{)vQdLud6cuA*qbL<>wp_QFci-Dj
zXJ;o5|MUUg+joLWhYhREOpVhrpZL$i@}KMeZ~VQmYWel3Ol6qL9h4NA7`rqE1#pD}
zNJV)nsw!z~wlOplWO&q#*=(V;#m3l7mUCU*6sc?+J@gJ6H&n8H^NoLCbje(l2k!rt
zu&8Abr@Q-*81*b%x{Q`ZZP<-=4!n05g~32t3~IH4sLw}WdIB{Pdb+#udt5AEzMSQ&
zR?^wq!}#PRE{})y_Qj|z8q^9c*+iCNdpSzAmbq{cgHex8ry~}K&|K4sYt~Ko<%<~1
zMoR4^T)foJ>C6V*O>ja#|4$LM!3#;t&!2Fr?p>Il_KR+mJ*zg%T)-^E~g`6_a
zJA2y?}%-eCAWUK03ytmV;I$13fVM9ot>)cDpWcXzIcL+D8yjE
zgUFzysIdZ-2&U%7xZ}<(?6|dqM;?6?twxJ^!v>O(06Mu;s4AWJFn`VG1`|kiDY64-Q9h{FMs*7o!#9%J3XENA|xC*cnE!wiEG!dr>de7N0F5x
zt(I^kkK5&;vAT}Q!G6jeHZBZa}CUQpPOhlO-3SNE*8gFT1th%ir3?zuDY5?IE>fhrT0<~u~dTVcicpD
z&d=dPNAL%u96WFse<-oDs-|w2LN;%}^RRrNL#KxXz1>3pcmShWMab(V6bRw+PV%|C
zcc3=dsjYJo7lT}^qC~GD5zKSu_;L2_eTTCnv!rAt%*G`QT$*5JW|EC7TX*^Vv%+n+
z-p2a%9dvf~5{b@{$)=Gjm7M81OD2<{wyK(#KgQ(H6h^zA`npOw&m2dJfJ~{t7mhKP
z%uwD^gWMoPVYV?dJH>l@-(&UKc2=%f&biL>ghNR>R={C{OsX}cB<6!
zor_vqcg>seUpOoS!%@NJEM|COl43_Gxm22bJO_e^cq+l~-+Y~0wyYyB200Lz%k$P-
z2T1{+{L~FBUb=xo0j9@%obEcuw#{o0XGJvDSa-el+RHnKhelDU6iiG^b7kl}zJQlp
zE{#f~W^`lV0?0fvprqdi|ve$k0O%GvDqCYA}OQ_3(L#(!~_}EA{&UM
zG}cuUjfYXn)yz!#Sy)%jij}K)cmIAG7cE7s(6MBZ69e$@!%vY)hFP&}A!0GiOu0$M
z;`qa13StS4GA9a$iJ55^rKM#QJImR6{bpJhEI=lRXl|^XhvhFh!4F2*WYTls^d+B=
zlZbImP80LaQe9a^L8>O6Nb~fw|AtzfM{0zB`11W^3kJ*%B@W<}A987ED}g`^blR&w
zkGyk=8#k>84h@|$ed@37;huZ`nxjWgGc<}+Vr
z^VY5W+i#y>d}0Kr-9}N7m5Q21N41Q_FvuunbQGgxU(TD3Il|ot^!UEo^P#rB~i1
z?3rQ9^_v*=x=G|D6k95o934U;%d>m$@39xx;Eu+)cGDJ0%j!u+B5YV)0$I2;7Gz7K
ziI;ZwBBX*WUFu}}wyhKu*~nxB=H@&IVi5|Z5{t#apWKQQn8`usX+QbgG%r8@J5C?zX7%#roIUwI
zci(dxO-=RWWh#=$v05E0Sh^6DaIDLZ&+Vb1vYgE=T8{O4kgKH}J$e|s(?ZM_Mu7;Q
zXO2~C*AR?EQ6NUEP_ke_b(htsSoWWt*GMG7@1A~MNT*XQU$%^njy3Z|g8#|Yuv8A@
zdOZ=KySx9fb*q|q=7o2uthO^JmC)5QgrHNfZAS;*Y1p>XjyDGtE!SXF$w)`MtX*US
zpl?D(u^4;`Xlpbvk%oLO#~Z(Yn~&c95G^eWxNxD5LP3VnqQM`Cpx0}Nhoh`+U(LkS
z3<|lHvpxNIV;Qz@y%kAPOw{Fqc!I1d$H>@a48^5*CPsMk&Aoi~<}H*;!BeZ|oj1?(
zuRr-IY7tDkVm$tcmaIR9f82}FT1iPsJtY;D_`EP3^3c|7XHqR<@0+h8%Uy@lVL>Dk
zsIRZWqPLKhNASC5nT;oyo*c(nT}3L9U}S0(nOInAS>61fc9`{gJ#*0@g@S-mujjzA
zX{mB@`SKt`BO}~$>sEg7(BsrKHnZXS
z)lB&kl$5GbN9c3h>nwcz^S9AEktBzR@$qS-g&e!S^;No0zQg&h
z)7)_5O|0wKLhr@PsMHd|VJ~U&+euDfnx`?ggS{3DD^UZAe6
z4RCVx=&$PVi7wW!UP`C{d-q;OYqTO$=W&OosgRp^?akd3#7Rm@OR?KanRQLFVo3)|
zg_z+B187WgKDuMWe`@ptLnFeoFTTv$b=T0{eTH~6$@$JcmM&e)gWvtfd0_shz!FV?
zN(pB!cm%seM_>18%myo3y@?ZD-Hc7UxZ(QiS-YYFCEx`TNqFboV^mf*vb@boCee1j@yHA-~}BDs-#){9;pMX9VtY&L&zCTxKA1N1W={LVyQqK%U#VW*NDQ)FV|H0^cyZVIJ-guF&3rET4;~2DM
zc&1b6^jccms_>2ZdGPzYD5?Aqc$nOnFgtVvquzwN^yUv0z#p10YTh}fuXeOOakQ4ckNV6Y?K%5hYUZthB46z_0H+EQ%R;?G!!}9NR3K_=6C%Cb_o`E2|fAlZ0%~&Q8DY+?qJ9}i`GbkV$AT+x3`j#T1v6n6hG-V7FEA
z@GqXg`t~3GTf6ZnmwdXE*>3^VJCdf$#p3
zx`t}jUbB{km0AY;5Duh}N=3*ES=wu~yzLV}SX!DxV)nL%E9_E}_dF+yHUGLd9#b_SJ7MJ$;lok)OKjz+Dew4#c9T0|fe
zL?Tw8*Ju!DLU{5?DjZI9c`=U4D#B_l_k8+Z=B~_gqUQh;<7e?t`6zSNv2n{L#>WGk
zIo?G!>n0(Sv3B+CtXg#gib5W%zJSRn!BJvGkU&fXz7WW@piw~2`6w?x^#poZj%$|J
zA<`6>ot+~R@DmQXsH$?}_4qh*@+<)1m><1PjX{%T?TR`Yt4q)uR9MVvkR~w69T*LI
zBvL72oepF&kZJ%EpaRr@JP2Ad$hf*Zh=i-p|I2|kkoh6xKMOw7RRHXwt6ee$iNI;W
zb?zPXiUi_<0fkBpIT6~nO`u&Q`iqC90EA;~3dh+mkY;FjkcPTue!qJkO|5N|)jLq>
z!7jdfxqk55cUZM@1xlq7Yq1WC5=OjW(nH9f$2~PgG#sR%rk3u`bJSNk+5i52GIFRY
zD@CVK@Z4`6VWLozjX5
zY*iLgIR(p>Y$cT}P`b=Xg9^IFqNGzPxn61YAjC!7z4*jjEb*UU~63-u?Y+w6CfrC(|%BJWjw9z^KY$&`Ho}
zK&w+wTw07tB}1pxqgAQU8FdsgX%td{Y%Yynr$sGGfsjS4QlT{HQEByPbw;#WHBz+#
zlv=JDz2pNgp!oo>G?0MY9ON=U_NpTj0TL%*y!v-c%$#{1A~PTbl~RLLtR$aEU}&mG
z?6_O>7axYDb1**b*`F?eUaw~Hk_9~d%Ou0|qJAeG9H2~uK-7)q6jSU5&O0EJ46SR$vXrkO-MO(GJ;Y_=d0
zNidoWgr?l23K^s_J(q|3DFC^gfJh`FD~01nj&T2dUtxH7oYRMnvN*aFnbt_E*3Zgo
z7LbfWUIk5MI`ZhqL_r7yklQWvjRlytsOZ?-NFoYd=SNu3Qp2=&l3zUf0N;7=NnU*Z
zIX-pQr#SB&Lai=CYczngfXbx9RAfe@)}oV(=uKYzD6?3l!|nBub;T%)TPZKECot~g
zrfsX)a>s4|(J&Jb4UP+5{}icYn1nBnZze%LIYT<*BNmUK*2vIn)BwmtatuZbYQt4v
zq$H3^We9mtYLtjIDo~`LAY3IUIz=wjONFBhq@t^-mr_YECq*nX%_sP$PYnr1TQP{G
zXe??}N)`7%@Xy?N%WZ7xsOSA-BiyjIhVG#V5B~Ha9{T59IE`@N>^OeU9DC0Wuw_Lf
zp)8cDuD+3Q*oV2u!MX7iu6T@^MT@xRy3NQGc}B-)5Q{X_)-J&{+Dj^{KrCoTM6#$v
zGNckIQmL41DvnvHVlEnkf`V)&OCp?RQA-1InSnsegIuCUE>dB)D3}Wb&=y-L1VSX!
zDdvJ3c7%}N>96NQ8NzWBr(@88=J*&mCCi6$br!ft$#Ac!)M%OYe7s1M>C?dR>cU*h4PKSr?;_MDxixw(>WHQvu%w|<=dkKKhvZNQiCATm~=jrhifqP7fiL%DDSe
zpJUaE#h7(kBJmW}O$$+|^(f>b>dVWKNmRIoub|hOdGyH_kf<&6_Fd$f_Ei)W>9AN7
z*rgB#bij?Pt|5|$^V$nB(wO;KY#nz{fp<8GETwi2GQu;=YVJoUTZ{r4}d-gH2$H;MFIt;Lo8Z$bCq
zz(rwXu%BU{3%Ojl$^-@4^{f6Jq_Phll_E@)AF4jfpJkBp(DBa4S{F6aKRQCQ!_4l(
zmnbruxqWRtt`vN8=a0ECI!i8>=L`3Ko#t{eXNOaiSDLWtAen|QedacvdHEgg{qjdp
zNXxlpLj@jJh_dn$>WWmjBj7Bt5e@q}c(R8=EJ;O)gG=YTxOB0bKq!bpqsCV30Hv90
zw{7E6e?PHA5{XnwELK3Hwb9tHh{l#WJiZ7st~oS11K~&vtzJze=p&hklP8Hvr$nli
zArew}J+oAnm(tyNnU(Er^z`(i)+so8qMM~{>*(t1!DzK`WpIMA$#JqN5nun(?bIz?
zLjRS^965fRR6NP@rHyoU`f#Q5RGAh0=A}b)clB`ltsBwlt-Sum8yq=um|HfjqGLlF
zBNJi%>A~-_apQV)8WsEYy^YCiAeIo&>n!Mu4vI@__?vq^k5zBx)X@|4_4e|`FMp0}
zuV3{?&I?3XitM}U8d`TPShQ$Y&>z|v3ItKel{D6BcOonP&<}+E$zkyY3!Np-(vnyv
z&AF~#CVd&yA}zOHTTk~)ls8`MrM0e|E!(eQ#_vN{WWf^=V=>8TFkD?UAe4Y)9+Ig%
z?;SkL>h{HGwD8v-zn7&gi&$7!Oe6^tW8;htk7876QOlI<+r68;d-tGHNr*(kcs+9@
z<7p}vF2rE9GCkuXn#f`=u3`1M>sYs8E5;%lBB=yHq(rJR5=mv5a7|OlX3=Wome2l(AC|4^*$+6;c>ZUdToIP7
zsHUy4l22}3PfV<2))m2Aq{pn&@z#6CC?qp%yKx(j{^}Xx$pm-aaWf{PfrlP{kvliG
z)3U0SWy?14z^?CN(5vX_>p~>TA(9lZ6qizv%LqjhT)EiG_>~JBJG7tM?%2V-U%cl}
zoIuMcuWa1ax_Hg5px?Jsf*hTt;zJM1pR^j5&qE~1rYyYNKj}94{a#kDUC8WonwMUD
zgGe;V7ykAh7TDm`Q!@mD5tc1$A{x!2Qp%_-z1oKJcnX9gVHVYy`0;P{;vX9%5{_{0
z{ns%VOl-ON7K%y@xV?TVoi#MJv=I)3NJIk+4qT@1{5d9vhe^dUG}blXT(_7d%}bC-
z1pBTqIIf}ZF!CIun=bofc$Px?&8SKBv
zy`TLY-}=t?*!|9Hoas7;XMB!|S{of(KE|ahbNC~E^p+wL(KHoK2U|BR!V`c~y%)G}
zHJ>1>{9kBeL`O?%q{zV;8_pl@K5?Kj=R
z4Tf&|1z$zUWBwChuwkMQASRxB$-M3+;^0qzKOi2>Iqn#sbv0w4gRwDYe5lzVl1Qr^l$Tt)g$}5*yatgh^|}
z=lAo8J8#5bhEyINe_}VDnQ4CX;OFV;cJr$zpXJJxQM&d&%ImKk=G$NWG|QJXkk85q
z#$rTsX&hDyGb1A`U$BrTo_+2^W1zv{j9@aAisoSfCfqZ^?gPg-c=AOoD4RE}VQO}m
zk&72FnT_amdJ1wG1%-qQ?;j^47PIlDn>p7zL|xMY%8M`t?zmaW@w
zVbStRD(zC5EFxk`1F^gqtMckMbwy(ZmM?2XBocujrL0tjN(5plq*LJW1~Hj6EU`m8
z4;nfA&F4OkI-O-YHbqZY4+EFRXkOli*=RtcQsQ;FkV=#+UbYIAv51>)T8cby5OkBaW
z+iv8hbv2B5Vgy4WW~XP6$(3j=CTz}PI@+(}Tz@YPXEoPty_q?`50`s_feU@a!$Eqx
zIyu$dMc=?MRW&u#RMfGo*}{|$lqxXWti)3pvbh{n(_V~4CR8dY*FvUXptG+VhqD|c
z5?WizvFi1__2w%$EE>WAAB92|i9$j;l_D>Z@#ODb!DiBb2y=uF_o4!SveNN4zj?1{
z%#EP4K{x_~?g$3Go~0#HW>Q!CzOTL6#V2oHiUJ7cptEa`Kv2y!OX`RxU}kcLjY~_B
z0{v02>EP+7U%+ZJ6AJh_KYI@Ha+Wl#BQ2yThziWjdGM!Gs2wU=+v_NmUcG+_S$J>H
zyZmU^{e0xs4GauSqEb6C?)DM(Ckgw92}Mds#8Qlnjj?6NQVMx3cB_{Dfh7A6A7@cR3u6K_)|XILeLJ%*
zH&&AjhY{ZKPJt-P+?*SOMnfVgkW1vqrNz`YFJpKtN{N$ACK(5q*MC`mk`*a0cyhv#
zGd@A4fQvmrN{vuv(R1?f5mZ2_5>8%Dv3BWFbU-u=SdlIZzT1p-`
zGZKR={OqA$^X9WpU=gK|sRLA5tI*`M)YTUuP6mm3{Df1`QeMZIg9qt5JpPhC|F$v}X-UQBJvVhlztHN`q2;~vhR?B;w=
z554^pjQiYZ)LND_HWT&FQCCw+OO2Y%i_9!pvXskxA(~3A0^ZV8&Nc08xHvpO-69i$
z8vGfs6+8IFqrV{smvN6EiHW)bs9XA2pSA
z%udgdmFwBuYDEe3&BS>9t=(K6n__Hq6z}XX)zwZM4jWpd8Bsxl+3En5hNgyvWC3eQ
z3HD+ukNxH;8k(0OmgSI$^SCF+i1=KDLjp}T&15qL&YtP#+{x3V(@_j&1%p!;8J!4Y
zw%BN>Z(w?IkcdCd;LsR3k$}i-N1*^E5KYU8`Gcf|08*p~GO(36sIIAIVq%z!7cNp#
zWJ9OdqSNXa9vZ=HvCz_3M=Ts8oyjrjnjjL3QPo(C*q#%{ztgJ+BEv3j(#Gc>3h0UNrD1cI_B%X=WSXE1z8p3&y3KC-R3^IwB
zWIB&Tp~5v6qO{12N~T0ElOd4`1n1_k6%|ocRZTXX!8PNe*inpYb{367gFhPOL}x#5
zy|<6Q`P4mJw{Zo#{^eobKYWf=D_2vHK&3^B&0(ge%gtTaIB-@p(^gl5YkG{=UV0XX
z$v`+1MwAmkr9z=JbN{X%u)IpaYsXGumKzxz9wo0d@3b2v^T7PMVJQINymDt?E{IGn
zp`=trPJA`^a|gkpf@597*z8thas#mf96f%D)vMbnF4o|2L!$+5+_Z!*J@7ETV3alO
zYxvs7HxMkC={noZX(_3A8gr2iwaG|LZ5@|J#+ZtP`P)zKpvu|A
zkG}UH_EICSz4R-C|`MpezPoq%lsj6Rq!CJxk<>ja?gu^N3
z0!cR2*(opAq6CJ<{4B23@})2TJvv2!bRvaLsYfix@WgaLOsVpx({{nS&71-=8R5#SHc+mn*
zo$f*;t0h3P3geT30b9k1{
z3j@M?$1m>G8ZAssO|fQiF+-DH9CkA%ImCgdpWBU6q2#7jb;y7#ZWtbMQC(d{wOxTo
z3l7GU;&SS9J7#el6ZIOk97{)^oNrWgavU2a2zQ{ul|C}r1{Zu-Nu@sk(MS^eE
z&6?HgShQ?8Th?!2S!)}5xq_+j0W3v&{60VFe1-xFjCwP+A}dHhq7joVh$yH_n4XHT
z(yk;1{LA;A#sh2SCUH;UtWM!tE_Of#3f*wjsN+>rf
zD6#42>Y1dr)WEQ(fJ$Yiwyu$aN={UOuAV_YaYHjRfjoMvj6xo6x%)w+GC3=jv@sV=
zFg`s_N?~N7MaI#~vzV-Au3KQo9S8UHEZrB+v7n)mvf_HGs_M||bmY;HFXS<3wbWM_
znVOhlVBkC|m6U7&-0o@Y#SZGL%ZLR7$RrYsMk5Cgz0b)bhiIsBaQ4^jsTXE>2$q3#UIJ9u_!UV$u
zm+^SKSj;A>YRU+QW1PR#i!UCIvbdWJ`WEUVHnn^K@N
zTd1fkrLnbkY?$++=n|FA`p*(0>YsH2ECP77^XBvaDfJ~g@)RFTjb#@Zr3>i<9
z$ixii&m5!U+SMcqNiGau=HNSfS!jnchmJ#iX=Z`E4mPcB;*FpFD_2f;V$rBkNW>(B
z0&%Gr36P5g$yXcMvA%`%w|$gn51e7(qKiZt91alVF&s)LvqC{E!CqcU&(O#`6@Lm?
znkwv~HOrbs)lTE*L?RhF89e;6uW_NbpLfrUGch>H9XD@4C|n(E=<1xsW;bC0Hm$ZW
zGB|(-c=)lW(CVxlal@=X%ka=RE1T75jCvBlowwcwQYCxOPV?1!uH)p%V?6wehtXLy
z=p+(EnK(wHj{5p~3W*p(BEfraz0KRNzDdyU!RPTXF*Siouc3AELaM9FQK{4<;wfY@
z8MYz=dYu}z#(5v*?k@M5I%3e112w
ze2z+oofn^cl3zdkFkk%Q1H^#WUfIL!$^^DV4TT4q_
z9d*^^STqX!vs2WTmlK$sV#T6n4(!{(-`v(tj?sO05&R*uw6+a<~nLQ^jP+i~3BftDL*=!PT$j{jHBx;?CoRDS4J&9Sb
zMz4|5*K>}D+e5KIkJYGV
zez5Za&Ye3$O-U(Qm5Ppa>v?bAd#F`17S)teX$C*=`M>!%Car`>B!UzfQkk4wDn~jR
z1tf@73ItJ}pFDdI0a)vlaQ8>=;`tZe;;Cm|AR5h~lYm_cRW(|YSpkj4Lb4#|x3BD<
z2j-8Fv&0fPM#kME!HBR^rdDECQEE1@%j3`PlpAFH;@8i!v~3l&Rc7=?_{EdY(A?0(
z+9f8EImy*wK`Gq-)o*d%x4+MpCM8-uq%$ChVCmv!kb+DO0|Qa=fLF1Q824YRc_+rY4veA0nU4k`b&vqrvMnpwq9{?cvZzQ=q9|q(fdokqIn5wU&NH2Jtm>-!
z0lMq;y}S2ly?cEuS?`BFr#`*UIraYf3H7|s|HB{oFk5%s#r?niex@#6<}d!_&v@5;
zZzq*a5>G4>Zf|C0X@xZd!z|4&q9_)!nFQHn3Pm<36|;=2U(33Y0lFh$^0^Gr)fmxe
znn2J`EE(mQXP=~2EmGIY*sNBpc00oZLlm|-BC
zOUDVh+~jH{)LIQufO55j-DaVzYFK<;9{kdm`N8*JKouapsFf(d;$)ceOWN#
z=_DtPj&t*Ew=*>8Lo~z8QkioX$GB?SRa7;JkO!ixOT6!`cN6IuW@!5^2ue_gbP`M=
ztZx7mNS5I7pT5YO@7c;i4BA2>@wpfeedy%yrC|aQK3py>yW?M_$2hwqo_#n3$Zw
z<+PEG$H-?BOpITmu2yIW_*j^kWo-N`Z+i2c?7Ds%nM{UwJje9>Jjp_lOg7Gu{rmah
zSHH~5&pp8h-g_@Soe}02=J9%bP=j!|lYF57=)-7f~?da=K{^wXhP+vADWOAmF2#
zOY-c~k8}CLD0Z7fy{1t^LsPH7qSsXn!9bH`B7;MCoObSi?>o3Oo*->9qt>i+wn^M|
z=N-KJ{U2xN_8s*4B%V8Tj8LeF^*u7HS%Gw+#O!o*Z*PbHH_870DOeWbX`@gTkYpET
zr-|j23=IvIeLmRty(jnY%@=B1yRG{dbBT|T%B9(J)6E#FhQlNwXz*7bxfiusw!~a^K>@4`RW7z$jaq0Fsp=`T4;|9
z(9#p(nr%Bcu>T-~>qjt~?L=3WDHXDeo<2#fR>5jEV;BZrkC&y`JTJcZJe5*~b?dit
z$L()r_ntR%acY&*=ckbCHTrsb*|c#JgF}NHI(nQE5`zQ7eEF;2;JxpDKQ@aUlOS?_
zY>dH?HJBX=%du5r@fe%d4l_17#>rDBu_!iHR##cKVLc5YKMS+7EX8A(6*G!i!Rrm6
zR_d6|RxD=gmC9C4qocEh6GxBooo_q@S`nkJQY>Yut0HBsfL_tj3>}j!pw{Y$z7WN#
ziDE3zjo018&6^wf*`W)Jj*T%e*hQZeHtf8K-@X4s_(R>;trl+F7-pdac87qdxR_p;
zL40LU%#%+%&I6y>hdEc~jyvDN`XN8hO+hA|qqVJ#<<%U+&9J67$lMYfe(o%<
zzy3N^U`$cml0LW!+6-ArOR&6=S#l!|4tnJi#J
zmSr%BRMi@)uF>B$z)UwZhT8JnEuYhV2)&%AJ$-}}qI;hJ0CNXyVB
z&Mzi;;oLa)yyyL3^>EdWU3}}i-=VFg1*_FccUKRefAA~V%r5@;zx+9BUL&@e=Kb&c
zFmJg1Z5Sqr9oJutV$q2w=9rkefE^LH*-SB>rjp8V`N9~wV4xZm3~F@v?L7bUNBO}I
zzC%;ULp~F~;z>*fCRwCX$f2q=bP+VeAdxMwY2&s0!zUl$>7TsByWe>qN#GCPypgTj
zui~+v9|ho=7I@_A5A#o7e30j!e~B6(=n$}hE~s?%brNWd@X(K+`c3}wzvEe^mR5}m
z`QSrT
zau;wKHde9*8UGsYTnDv?(S})@kPSjewNdV{P2mV`0e-JMYy#MwO*xMDG|%(ak#v^?d}`UasuS4qzW+<
zS)o`c(9js9Qm*jq^DnSzc#!Q^ZRM#apXKbCF*4Z-ZkLN>dYM!vN+P++-0Un4$&OI3
zQ_dA>X>CJC#OiXganlBp*)*fCyvkByj)B1;E{~n0QbIL%fDeAzqq(pv4ub~sMpQRO^q?q
z*~05%abHC6ehV*~|(88ZL_!K{F9c#gObS)?c%W
zHA7oioJ#TbH{MHE#~`OKE>fzSSYAqFw>OZ_tNhs?zZbs*wgwO1ee?-DjSVOP7pg_4
zDwufd-S=_o=mmcM_>A6D;Z0P0SONY=ZX~xc-!6Zpw)G;&xlgU8SOjOL^q(-?^VB4-c
z8Qi!NHDIM&6Ihv9Mq8fc$j`n*Fwo77>)L2va~0ou_&Mea8E)Lt#vM0r;lb}c&BSDy
z_uaIH7hgZe9Xp4?1lgK}!xzr6v^c$YZEw%M-@x*}upWQ$m|=Fhs8ow+YL(vRCKSIL
z*=gqck37R$@4A^#BOE?D!RU!mI!Aix=;))-VdlkWALHa|UrS%R6#C0;#nkaxcA4Qvbw9DDTwkACYx0s#xzN|8)m#pQ6|
z_BRmj=)@#hDI4GmHPYVR&doQjp;!{w|IG8Wh8w9Ba;z*ZVX>JJ1PM*6;c`1!SV<8M
zHFL)s-$ZP6g)^5f^T|(qn8-+kS6)8H$hx)6EG)8P=XNS}8OaVyGbz+^furY7)6vn+
z#tm0<P8XGP*Kcg
zY#tBqde8ePl~f*k^l3i)!4L7scfQ8><#CK^6;-WLEfo+1FbokX=(4}>HV)E*_^BmyJ_s-!i)P4
zb8$Jvhu?7{Nevd4z%Z2=9vmSy7boZs?seLweZPU_msn37I$>yniH3$&hDMr5Br3>g
zSgmf3k1o;H+(SB@WNn*=^D}8SZrwmfZx~!qU(7T0;@9x|tE37=>Zv>qlbuD~!@$Pt
zXm0gkcbX~WGdO}_8r<;J2Or>_?|&z&vllu3+AI9yUw#yqsf^WPP^(q(_?ieb26215
zm}DD)KnT0XODvmV)4EQoMd=1$t%yEuCM
zD88T**$j8T;chg|#CN{;By+RN4EFc2x&Z1x6~DT`YIL4(ILyl85|S!V){A(3ewG(j
z`GY_F6VmxIFTZk>```OPBozMsuQ&Cq(EtD-07*naRR59T@@dv!5qf?agX+ljNo_q2!DoGRF1D(9%
z)^$Aajh{2NoTa_Jm5<)NkuQGxMP7LIEN{ADJyj9xRx5s=KsHn7;K7%fTaN7=?(5k1
z8(987K{;lWHJxyK4|DTT`~g4Fr36J)qmU~xvL=kT!NDs>k5SPaj7`q5W=A{ck1kSC
zGracWFR&>9et(ejm#0{_c7VlrhO6$lkN!2?JpR+C>FaJM7E5#D*l8Yr^ilrczPFK1
z%<;7^e3FYt4`NZvgc^NFvO%^~U}R`L;r4bqBArCK`tSvtXbd+KX^ViN;Pp$KKQT@w
zox~y=T)1!whfPFN%cOE?Y<4$_B;axdDOWTs4j1js?L;EIw6`}iJ6$1NtKx155cI*L
zPn^T5m|0ngqStlWIyyLW>MW&-hFP+Z&t-AgEX>T!A{a93hBwpIxeghLu?rU|S4t$4
zX*#<)NhT8H3k5;}FZpbNHN)$1`$CMKy~xcs+{ES$8~E$L`CFFfFC)tmf?!aq)lgLx
zK@iY&k!rPyDCt;SR{Fa7sM-TuyLCNwV02#eRJnvW@=Y?u|$sB&Q<%C%d2$fqDv(rFC)dFHA8+;P{fr0Y>kXbnG2UM
z5^8B69-X6@Pok+cWQ&Djxr*QGqfn~g^92~{>tkVQ2E|k-66r**<#9KAXbX${^yjY-
zU!0_;t%-Cpia+4NP(*?*Kdp^TEY3~g^E)|p>NulkN4b9cPE<`rR||aLeK(_34W_53
z@%nsVG7(S2Xl-qxlFLynYV`CBQ7o3Yddp_+xb+tP{7?Uw7oL8CfZKsd1gqJMR#TD9
z3Wi}I$O57XY(5{o-96lT&$z&SQ5UAJdh&C%`
z*+iqq$^7&L&+mVp<&_u%1HDwWDibr~7&VoAHcPdlqG~F;ZrqLE8=zV#qN#a)^5bvt
z!|#2I^QR6X)biN$0t*+2-rbN1+A>Xj^8wr=6O-+P$n4*ryQ
zY#N7EBEGuBY$gqS{1e|H(%H)3`gN2_DW3h-14NI$
z#7MV;mhK*$4Pnx$6#>G=FQ&^n9s->`rX%upFHaFAT
zzm}9*p|QK0NLN3zsYg44P~{)
z>nG3A(AdiQk*&P`((8z-j@7DAu4ZXzX{V#JjmsA?b_zomX>M*|?eGYf$Hw{e-~Bc5LKdAWcieU>S6{uA11}xm)Y&sU`p7pp
zaNuPWvxVuoS)fj+F@#u$L~NC|aEL;!g1e!Ca7P=4ByjlPK_W(Ez^q6p
ziWyDQkj(Lr#}mJkh%Lx-Lr;I?w`;9)A%u%XfuYGo<8LSsjm&W;|s
zy4yfjNM>SK%y#CN7AY0WxWnCS+q#)tsz_orO|fR;JKuSP6UR>DwkUK&B3ymVHm>XU
zfdn=g`kP#|v)bMKy&HwaTajKBN|KMw9zT)$Tkt`lUO@8v_Dnrd?
zKL4f186NB>nozmpu3;`DRQCP;KKB0UM`<4M^3u^M3iD@R;s`@NFH*ak_SQ}+6`g!;
z9_khj9Ui4@N)u{PC|pV~wYZ4YEMcjt_-$@VdWE7|=h_{&QK?plt3|pttYc*HDylMAs#HVKX
z*dPB6qMXL+F(D};(WN*7GU0F&sZ@$|I!CRb)7I95#b&|R-GOGekk>UjT03yr?5you
zODdVgD_V&sqior{o@jK1nb~P7WtA6SKFBS%+|1?Cangwuj=X-Djz}v*gZ(sy0u+-`
zTow~qp^n|@VI`9xwh~1s*T^QL`28UgnKVZaA4ZZTTy_VIO##%pMzvDLZZp%`-iF^)
zVYyO5)IqIlq!T6DB13Gxc{k^dzQoQA_pmCK`JLbW?SCZ$acSl>Pd@enW}BUSN#Wvb
zf}J<*!fLfLdiE?cvtu+gDxf)79$)3JKKnVsVMu3SDGiBSfd-d@oe_9tGQ$I(`WTNq
z^f^H`N&k5~O9jY@<`X8R6-_r0ZugPR$Jx~4;@rH(cYpFI!<(+*?%iFSUw}hTzR0^j
zbUy`MCgK*EJMc8d{AogA7jjzzO%08h9TK7D7NXG_ORIT`#TX542M)zUa%mQa*^bxh
z#p?`^)60}=DjTo4mT+e~mPQ8+!A68SRBAOUYK598Qr0xAW)o-5oyHxWb=7mJ$Q&$p5M<6H}B@HH>~B6{V(vgJ2zq;*vP}*`ZCSd0zSn|u4-Ym93vK;
zr?<0@TkpAtn%mEt-+Mpnw_nY=^&1dt2De^w18vSGl&Xh#DvL8*BiuE_$qVO5=gWNd
z3lDMp>=Aa~u#-wrqh2m>+g-O2>FVRIyWhe}BEjj4r_oTU=pxoY6DCc@WU`>>B5V4F
zm_9#_AP7`SIqtZ1H}84ZM;II&WF;13esPI>x`3=|^mc{W(BF+Iou{Xv88jWcV#ePP
zAQp>r`_|pOY1dnj96IHd7`wM^`ET#|!q`bp96iRx^K+~j80O;a6wMtW%H=4T_!7BP
z0h`TFLu((A{t{ilIt
z|Ep6*p=QVJlNo5U5KGrN@Y2hy<_x~~!|(CM&;BV0GB3P*ile8G@H=n6llke3Jn_@7
zurP59u`*4-s}O1q<8rxim~FI2Iw+N^q>}{%QACyn%oY=BsX{52!fLi+=mP0n3Y){l
z;Kp^dv~?hw%`|m&u^f#fm=t>Y2T7&U6slD!)f($IZeg%*n8n37itM1K8VF{EVycE(
zEFfq_=BAeU{O2B^V6yR%54?@37zDfxgzO*?mm(c`#1c3wKTpPf5*<8V1yPA#!GvB(HQxBmTlXv#_6y#dTx|(xS4h9*O5+SIDYa3ZS5UY
z)GC)JE^_YTE3Dht%Y$F~EH=B$JMX=hx4-3WL^^t~+3b|dc`9`cizwrf6&h>`lnWHJ
z0->%Z_UyTpt^XY;AOF}VdGe{JICbhYiA0Y6jUyP6!u0GMFCBh~>v!y8%i1k0EU!?k
zmPsX2XljjmT_qlk|ztX>ISmUwc?81+cn&
zd%N2trk7J(m|Q}unK*dx2xcqXd+*zjC6Og)-$*j)qW}d@)Bb9Hx745N|k4
zV@n&6-ae+6R>>Ahw0HL6_5>K8ougc;(Apj$)X>7+ci%%cU14f^k@l`m@+A#LbYT`G
zv|1jg<;qv`=b!p1kN)T|FHihYGX(N{|F*7qyCKILE8>F?hlVn-q`di<~V?X*n
zVj_k!+>BzeU{)l?E}WrME78)@L9SdwaX5JVXFsL0t&K{phGyWLKEdpj?^@-m8I!|m}92sKeH
zmGStzluBi`ZrwspZ#P$O-bSQn5Svw_QcTm-(uyPCqfjnmQOro1j?HGHfKLDB4Rp2j
zUJ0$!OZ>q{{+!PK5psnJ^_mqys*x@f5lssDS_xT{(KQ{jWF?-=P%W2Hb%AOzPd=5#
zYO~_?d(d@>LOMsKm?xQt(G+T6B^pOJs#q*$4jg`c?=_p({#pU^{|YWgFP$*lO%X25
zi5x%nGVxRftI)(Be)t2peDL?5{wHE{DcYM|c+8Moyi9I>iM8zwyeZO
zFv&!Edcf=?K6{>eO(!zgfmSytR|?n^nYs>Me~6Zj2!bRNZf_;r)`89ECKzg^qUtCP
zCu`QW(%msA96NE;h^;1YIGjY{IC;M>``=Vt!y)BnUf?te4m^Oum9C0fEETs}X^N{NaFvSFi~FJU!b
z(FKi07=Y`NG1tiO9O^U
z#VY8ixfH9>IErW@UC6RH6QarIXL9x;EzQkTO9nUIai8(SZ+`~AHzfR8!m?@8CgHC>
z{J&}EK04bQ5!@0J7fw(sq*=Rh
z6DU?(K_4xx&0w{Dpq^g+O1%yPgTuIdKIUd7C|1e{f{0?ba@AGWfuLhp%(&bh8d_Sg
zJ3XkPgxRj(Fx%;Di`)bjTn-0ztA(Df2+d7RfKIlMrBuqH*nK2&Mee+ACl22-v*Twe
zlHt^W=cubtDiyKW>}(iX!-ZqVxbL1f@!1C+;*+2F1n+pq2N2zUaM}>^Dyy?|*pwid
zN|m}$p;XF|ipObbX`xgxXbgpD>FQu?Vwzo>uHg$`{71%*pCFl!lUy9)nV&pPA+KVR
z>}=k#iKdn?jyXh8w_~Re(vlm}x>xMxx%PEe(ehguU0hs9M=s;FvTs9lj
zRb-Q$v*%AxF4qV*v{BXmMVi4ITFa(TKQoi3`N`u?@c1+Pu?1R)*aAqR&SQ`KoOEg)
z9SMg!!1U5Z+B*k1a^wu9+6r1ppdP4EDipCRCaS3tMGgFs27C>6>~F8s4WC&lNk>$l{x(4kyJ#Oqy
zFS6D30ZB7D5ls(=8(XGC(e)xgp-^CWc$jtT)=?@J&^f01sAlC#+3HYtcnFyuTrWO7~XOXB}3%7Bd>Dby>FykGH7Y-(>wP>gzwi?{1@BuAvq(Xu5$~sS)&gnVq@7sk2!kZ9RCs0rG_m
z7D*%-TjsN${xm8ALu&>Q%_5Q{psE$hg%WP7lcx3#5(_ytY}ms2lLz>VKl>PW+txW)xe5v*or_f*sDmI<$mfVB5?B-qb(4Tuu`<0li!PXuOgfdaMptBz<@t-`
zD1+HdMH5LRmIy}Lhzxh~hTCr8_0hB3a^p>`%&wBj#z{tFxIJb7W|!i0_13UhB`UQd
zHk*U#nHknJ`A}p9U%QESf8?WtnjA=yKwXtF%XWOB25#!<=I=l8w|w~beuutZiPh*b
zxm=csiAnCdWdj4Fns^GoStk?z!(hBrB(grIU!7%9_3bp8WY^eCYQ+1i;bL
zr+E6=160Z-6tl#sQzs~uH2iiK{>DaDqX{CM%l7u3z5zUsYHVFCy!ti
z>a@1B5L=m}QmbOMIOzOgnFs|#tlzMnp0-xdinKQR8EEfDRPE%_Dt4!XngFU%L$ryk#1`>3
zxM**0TwWlT9pB%EXx-KTj@}WYfqnBLn@IMUiYiLrZHDHoFyv
z%g*B50VSil3%P4`x?DxFT?_AW61AGfDDW{^ihL2_BGq4`X)yYeVFQP2hX@
z%9H&6Fzt#Wl-utUf{l$gRjLLKr%#Y1GZvE>NwCn=+{nnt0A9t6mdR4dB+<1heQSpJ
zt#`i%cc6(}TBY3|#NlvKGr2I~M9Nm_?rdb{+%(TV|5Idtg+e_^EH;OrD`0ED=9JL1
zD&FVI22fs*a04F$km$(wnXp-T4-tO
zr7kNdejAp69lR2Cw+(MgGsreQUyR6Lb!Bp&^rrW=TYIMAOSuO=)aOGZ)S-
zQY{wa(1!JnhXU*6rCtM}I%7tIK$;5=Ra`$2;Hqo?l5|eu>_&3e|Gu
zN2*Z|%aRE}SE-b9%+5|@62R_opg4T=3=bpQ8-*(eTl&Remk|-t|2olE?@f(>Cjo(7H_J3%niNGg*hmoKt)%Vt(qSE*DgGz0>~;;RU;FiDWB!Su39tz2PoW}eRO9#&SDP<4%t))vb7Dpdij
zio(*uJRPkqSgdBg{_RHy_lO2#`!ADHcn3JzhFGyI5LTAslWdoiET7YNAvuGSb^eDPQE!%ZCZI
zcaTmMx&6AeEM^5lE(>SQougJR5eNjBo0;Xz}$->O!9B#K0kJrxlf-^NRapTq8OQdf0Cp+-!CfZy$A{L%%Y%kx;AA+Cu8uv(#7lNf2c
z;#*5VxdfH6fUZ@sStMjd$Ln>_)EH)IK8hsU=;)1b+m;Saou6i6W{T#PHb&MC(cRTa
zV`GqkH6siSj_~TylL(TP;k9ci6iOUAc$j=LLzBx($mhrBZXlB_QYzLseQFe+H$Z1c
z7t!c4vaF!0DpuJ-wOq#OaIz9xrCzVo+R@JR_#~R45)3p@tyU=%3Yg7ia``-JtwuJN
zBNAyRz7ogj_R!qaOg@t%SIiNxIcN-qc>cK;u-l!4TU$9dF~d!}x8MsoIDdAW*0wfI
zojOUaTEXx0Ff%>HnbGrm@3`&ueZTs!)Kv<_+=*JL*s0d*I4tH1W>F7UivPDS(I!(Q9
zP}g;O+S{3&yok*rpvVUCM3!_3@;L(u1IcOz`HDY`C4g#%_{tomY>EblmuyCbx`^BF
zb|sE`m*s
z%uHXIr{;3G@Or(7qKITNQ7)BGBnh+CMkbSGxPJ`@plKTUWSaJtCKB-&>3o)s?g+Xh
zGZ$TE*RCx%L^yo>65F?5&9M_F(90zZUB~HkaB2K9p2pzbk%7T|ztXU1l_H8sde|`P
zdu2hy=Cn80E2X`$)nyD_q`k8X*=on_@ufwp?^FMdCL@RjnpW#9mrAM0%a@s+m_avm
zOoqVx;tHCkVzt?jMFmN=Qq}8tJRT~QGUv~p1*4AJc
zgxBQ;LBQj5lSyYN7K^N|u23kIc;g%Ipd-?8rEHr^Gd?-S>9ON1FHK^x88nA|L^_)Z
z1nl?&jR=Z_qA2Ks3E5=2Qm{~DY;GTCPo1Ktw~MKX338b%nx;{yR4A9rD2jq4Nu*LK
zJT4cKVqsvQmqa>4G8V;bkuX~%qVXjPYLVOSzKc{Q%TjEW>#yB}4OmUpSdPYMZ*S(c
zSB|0pk}Toyc{q9IEbqMc-d~Afe*aTg3{AzPC@6OGKC|7u59*Zi*}Ybqla}u8Pnqog
z9TtaspD4RO_3v%8h=gP^(&=<+@7S4hXqt{Fg2Uw|mCBLLW{_nQvekjh=0&nuu$mR@
zio)3Wvp^j|)G&!69*+;3O+hhBL?WGJk|}bT98RkZyV=6j_+_^2*g-Jh=gFTxjagP$
zm|wzScTiXB1e$I}asU7z07*naRD3=H4OTpE8v_GfcwBbk$yJ^^@B+z1l8JS4kABE?+pcD4Z~#%aQm$zv601ZLOPoD>oD;`i|Ap*d5v$WhFyJHD*hr+g
z8IRY2Vo|7zBEDdNMz5c$s#475C>5`SUztn>!!VE}3pSetMNx3MT$ltCBkR_3X>1hT
zWKb@Z(dt!JVvB^^TFK`MG&hHtTUuc2wvChln?1nk(J?k|+{D<}D8*C?5inU4W}_>#
zx3%pZ>iv)3OZGp2MWIUb}oT60D
z%oX!#shS;%vI}?{L^NEk`qaomD$Mt(a
zk}&FZ%7qeE(Se$)u@YTjX>pN@qvu&%TA+~2P^siGi8`_*a^tQW>FVjFTB+i&Sh;S;
z4#q~$5|77mI2;rT1xzLhNzf5Y60$5~GAVdG9%g1{sMN|7O9iso5|S*^5cE+ls<@qQ
zWJ#oMm|4ly8Em(6er%S$fk6T;4==xTm~dl&I&~DgjZ!YpowwZbs|bsLB*~bq_D_kj
z^`vAr?bFrj{n>Kqj01nYWC96HB2xV
z!RKqEsi}wU+jsNo(X*VKm}0}`4Yag3M`XgU`Ic$=M6sxN|%Gy(1
zNt8+z{C+pf3rpk*dHVYL0FihqN>$S^nM7KG%{UxZR86I`IYM$Jj#{tb^#}2IgLJqh
z#uw9=M420Rts}7%XX4T*P0cM7Yh@G^?zsD|ee$n<=~zaPtS9Yu*FK*oxKEKS>3?0~
zHT`>;`rr06o8^7Lt8SF*!l
z!o^Eu3k6P|c!dokLu}r>opX~jtY#A^HZzhSg9ehQW3fr((s>HG5_PpkJRYUJDNHH5
zgoersFTO%oa|E}`%3?Z)s)=Z7l47YywN|HGR%vf<0aVh-1od(WhgreuZp31?VG<;Y
zl_Hs19*fJ1$!0?kbk;Tbm@At|FBjO>=SOKD;m1Gw83C(|MUgN$J!H$}y<67&$4>PB
z7pA-XN9s~AFm!!d5(KK%^4^*83EWN#CbNiMhiWE=DwL=z7J`9JeBm&HV4zqf=4TfP
zhng8!Glt0jrE^G9%iZ_}ctfyl#?316zX|o70PIbs(A)UVHrnM_xP0^vn_i10z_S
zPJCW3l~RsZ55LC1&^m6r^LFy3EMw=+B1tle$%Y^aWHUJ&4mX-+02&UPgTaA*V#xxk
zny0Qpq_dN{sZ6<8r&`c4$WbZPu-lygL?Rv3YAVTOnnEr|O;vFQf(-T#u&^*sv0O$F
zWY!F=L)Yu16DeAIJ5lQrr_P*XU~Ly80W;ZxgVA%N6iXF~dY$!Khp6bby={U2xT?v&
zlJ`GF1OyQzlZ?Y|!(o+4#+UILF2pJ*CMXm$v=3~cniEK^ln~`BI+YEfPAZtVFfod5
zlvs_Xd-?X)
z%lR>o9mS3k7oBw+^Zm2enl*dvAMbmw`ziNxKN7O8gBT)(5-CL{Gmxd#D)U>v@o(6&
zVG~zv-pcOluV>ee2}Xto(9&7lI7UvT$@b*Q7evmUzRa1KIv@G5pJChBICkKnm5PjR
zE|8TV1Uwf!8|G)BT3Mt~KTFn-7%+Q@!Wc=HG0hCqmu8S;ouB;l&rohQ2_%vI@4APu
z)uL73%enJs`O+W!CvLgz7T$IDee~pec;>MuaN0JekwG;*l0+g1JbXW9Zf=^fu`zPF
z40F>KJ$(h#TnbqmB%SghmvCXOOFq+&Wm#l084M#uxx9j|>ntzZ7>PimQAf`hNU}`e
z$86uUg~0bgP^hewIsW=3Hf`TTAowKG+9d7|f9!o6eC{A|r$)Qg!L@4m4s?Lb+hF+z
zrbJN!Q9x5w`bP$so2=n`U6NSDG}DZ4zMdH?rrT;U(l0n$@@GdQsDHPIV)D-Im
z*K^*?V|6S{T?0uajANoCCLODYl7QQGh=75<5~?a8f3vwma)AAavXWY)GGbc)re$cgT1bY+#<2-PNnmPaiETUfQ~CC*=*#?Uh~%XLaagVbs@+VwgU
zC0MODD6$5Y(Gq;*!yo0}|KFb{TM}8haG7`R>*1TvpG`h`V7u@(SpEU~_=2!jTu?O`
zJ(Fg1WQ?xYq*7aD`|f=#S{idR^Yjl7a{kO4q_h%;r>80O8HBFKaNjW7w`^kbru8gu
z-_09uyiU*!2-TQG6o^R(Nsto(J#EskyA;D1P0x}}OYA80Q(KtFOB_}fr!X~
7}nWK9AD@;yCVwR1aTL&My(?`#-N=)Fv6-or)6|!`tS-!w&G&F@DNL>&lK+1PnD5JK@Bc4O6!`?c
z_v5N0owcmaEm8=5eR;C^97m5{BGHDq{|>~
zuxC`^%*k^+^2I;lpMU1pdF0=Ijf^BQx_*$ISMA}NeRpvE{&$gCH^k-}wz6@4|dO*1|^%J}9@
ztkx>zNK=FOyOTeC@*6BoRoS#-9qae(<;myY
zV#n5X_oXBr`S0)ji(mY5QtTUhsF>Fuew$hTmjo}-TAH6E8$?-rZn(eyGiA%dFeDs5
z;P~+q+`s(*$B)0o#WSZ!Wg=cb^bA?kpwU|7%&~xl8}DYv)?J)A{}LDG6-S4`egU`Lj5C6OU#>{tg*U$#Oqt~7dZ)SPHVzse~nJQq{8??%E%wIgm!DkQh^~atgRmfl%
z2F>aUci(v@Kl+JJa^%P{j-PsydZS7d#)MHs*RCT;61oVFJn~!Id+$g1KYr%t`OSwv
zL)WVjh|rf!;f4-z1Yr~)OA47x3eW8zYbn0^^{=vP&t5ic-i|0m#EC@Yx#*cR9-!DQ
zYEzfFT-?aUD=%-`n8>~NeTXN2|LYuj`DJ$Bau*vmujk;2nZ570c0B3-Zz@YCk6unL
zv%CUwxcg4(vd6k
zfPe9851}LxhHPNlHlAy7-3@z5XVX0X)MJc{^&pA?$KQMdSr!R=mn4qXHfTvILi|;c^-TES$_E!e}VJIPq8pxrZil{c0GD~`q;Q}Gc!v|q)QnRz)%(X
z2FEapSz=Qs)mLEC#1=Mhogh{O=9lNWbnF?NdXuxKPf%~ydH9z<$7g@`qwL>4LP~>+
zz^NL{dl0Em6QL2W6*9KuRSJVe+Lpn>l1ryrr<5si%f17=_k$m1WMl)9AkwNeSX@}Z
zP<6I%-%hco$jZthi`5D}r8Ghu;dDKE(s{bR&qCed$3OXQ>MJ29&K^cpBXSuX5(Q$3
zYGWD4?ji^pPUN8)DqY9n(xr=xZ`#DBiOsYv3)c|9$s2(B>&;x{T4PhJ)8RZ!Fvwy
zXMg_kLx-L@_R!V)wm$qeSpKH&ec%!%;RX>J0tu2JOvy>|kl(0K?o`>jWfxC;`$fL~
z#FLB^dKlcW1-D+Ku{zEAfdcQn>sGdn_fXPI-g@PArkBsqpUoj8A*v`61|B{hUKoI^
zBM1sY;#16*_>-@Horiw?S2=Uy7~gpGalZI_UtoTz!m;D8ksavc+}sR%Z@P(6zMsX5
z^AH8toeu4Wi=H*vxN9f7cJE=RXNb8o7diawvz&SDSt`vYp_H&`^G3FA-h^wnSy-v@
z=GiGuotx$Ig(bqSha%{xD98dR63oxTiK!-U9hzfhc@~u>gM)b{wrybN-U(vSXXiCr
zxc#;px%HOox#7C&SZ!F$lq(F34KT53J!-u$P_ic>t
z+{=lxhd6&}iBf)$;r;=1O~C3nIQE)75`whm_wQUSTXWw-<@ScxU3?Jfsql?=^V1GF}8UprD74^?J#>`nIMb^Ll4tPBZ>mMCVDZHKHfO=DyNRTO1)lZ
zdTy4brDfVyi>8o(ACgl|TsI_&V+#2cciwm%H{N^)FCRR}>f$1Wf{ATgR9ENe>&fy*
zfAsJ8*Z<}}uyfNkQi;Um`O|D2A4O6nR8=L4JVYfy2_w2r7b7L&TU{0#WuATV>+HVa
zdPrBrYFZ8lJJx#5-#Nneysg^rz-n9PhoaKMaEEY&2ny8>@8b&rJ5IH{{C&}-%
z8%=g!zlZzZdq4l>&mZN`(Kos7&fEFn&;BCi#W^lpKBteL#i`c0@#?)uJsIL!3#F-`
zswz$#BdIbf3PBta#35kx6Ol78wBB+dxuEQ`DeBZ@&J?7^Zc;&)T9{<);ShmBq9Xr`D
zzL}e^yOW{80oDx-qvlH-KYohJ@*;`?eFH_RBU*)xzzR5M)x3F<&fTh`4mMbl;zG@5AT8&FH)9A7YiG(bQIIT8jN<%gTUOMTkWB4I=`)+trkt=mcZmz9-r&fg=Q(@gO}_T^uTXWmeER4A8UOsD
zhxwsT+|Lbn+{F5c-K^iTk*jv~(KDRpmc1LfJ^=2qQCyFR2Xn7rAcl
z)lAP$F+aP2q3MJOXo|_%(`VUx&2CTx!YJax#VKyS^;ViKi-p;Fd@sNeWK1K4sK|(_
z072Yg#Wh#oz{JQ1FFgG%E=-<9kz*txG)+ZxJv>)o*XDJ|d4bhR!r0IdCl4K=
z+w7of;+kJV&vNS6QJU2Xx+-(w^l5Io
z@hbWYDskYFHuIQ9ntG#w?N|^eXo^MYTj-^bEg(l4
za-w605XTAY){QYdJjlik>)E(z0|Xw6^V1wZ_B!8w_9;%EI?CM41v>3Ag}lk7ix)6b
z5;tGFk6hXSNhVAT7ME%Su7iMpWdX88%LP?~Km#|DDHU_13PmzK1y*Jkh$7g#XD^mz
zae00T$MO&r2_bR`G?ij+51F1G-a34g&0Dup%%(Yh>^5*Rh2Ld5k-+^v$;W%q=qC(
z|2V-C1RhZwYzX6MucoR~k|+WqNf=ODTKu_)7+KZOO_M@zk%P}ZO|icpPY5xJ8da~%
z=}RYh@Z<02-S^x~r82kXb(JZh8z$vim3E^}7zF6Df+&eZag1Q3@dFP*1XDARBpE|f
zIrQeM>_2cD^A{(PWPx19B=S7sFd&sSc;UGhdE>3u*}QcFKlQ0kG2A!K!g7O)bBlOHnG=5kpw)i%ZU>w
zD3_~DY}|^|4XC%;v|ART7qDaN7V;T`S6_Y!O-RV9X^JVCSb?Gl!)fTtLa`*_MH-$f
z({0<>ZHK|30TfwezPya43&^UEWE9Ed3YbQQ@=6)kwYl}yeZ27Uvs5Yz7^;XWgCv3~
z3#4@uMHIpD5t4w&v6-5lVzp8sa9oClhcR`N&<_cdh}CvX(lgH9357V_N9_8jVaTz!
zUSWOD2(y(HO2rboodN!N?tR|~dp64RVX^0$J-A>(YHz^DhNSSFQMW(l>hx_04Za(}&Kf?ao
zZsWc8zmrdV_y>gt-hcmnL;d-oh1p3$+rvP|3u07F$8jB8yGz#8QDqTXQV?a4mgQ0^
zlrS{|P1jLGiO_fP1DE-k8LruLHOG&iM3N*D0W@7f6cS23MeMfCBhUU3lauGT^|k|i
z@ckcV$5p#IckV2YKK6B*)m4@!XL#j>mw5V#CwTL`NHo%LQ0qEI$ahPXK@ihE3ncKn5#pj
z1?@JpIwJ46sl=^&H}d=oN12_u$k5m@zUMP}?gY9T(e3&S_Vv(TC@@&+=P$ncHST`b
z-MFsLp`%AoB@InC5k(azOps+2Rn?G)krE#%5tv_`!*Lv1EHA8}$Pzd2z54r74U=X0
zFM;xp4lIV5`uy5hfQT$#agY&J3`2Yvr}L0z7-V{S8i5-aUDqLR=IA&+S=0Qyk&<_a
zV)pY$qUCw=W^V0_q}Z2
zdKJfxp5*MCFW`qReZ4)XvVyMYn0gK&mcSDcd=Eu22*U)|@faK3z?O+^q|5^S`C)o>
z1;0@v=(LzQdz{yvdjip_Fn!_}y{3Uc%1W}tL@>thDNFkS_>v%MqU3Trgf!7b6ASNNwQz%BBf$X0)P!t7CH)uOu)IcPq#)wId13OCSr6O;fnq>QR
z*RkS(yS$9=brAv|QH;qKQxx)f#@1~>5F+aJ+C#1zJhZY>d1#>j`?pN#AFbTwyUj6F
zJTZPK*V88;7C*0O(!)VFc*u_<3c7@>s}GB^{CO}NvXr1}@XrelgS}OGG{JcVC(iRY+66g;`}0=jzuBg
zgX{WOoeqBFpz0dwLV-%P##2u{#Y^9QmeG-Q{J{G@z{J)uCNE!NX>|$RFxRF#1BW;c
z2_m0Z5{ZNm-*f0XZT9TBn(fI)4SIWf)(j_Pky@ip$F;HA
z9qd{QLlViS(l{N5%2Jiq(kidL{B4$37ZK%%R@=o7VzL<#EhRBCJ&T!1vs|qsiwZs2
z9`gNtJoWm^Jow!3VhWjyoA%zYZtx$Z9E~j>DPL=SaeYM2HcE
z1jh;J?;oPSw+BL>mepl`et|%AF@}cu?JxW`S6#J@Pu_Pk>v!J3;ZrB6%r}V*nbDDT
z^b8JAi7h(S4v#ZnAaTPJGM5^W5uv
zp8x>We;Uhf@$!o=Gj;hg`BH(vk9qey?`8Wn
zSM$f;e1d!Keizqm-N`E_4>MHCv9hp4E?dIL_t5FIs4raP@WCf}_2@BrdkZw1O;lAU
zj$vS6fNQV47Q;|kuK6??HR|m;q9pUd2S3U``{_?{bh6G@zwsnjU$d9lD)?~ae!0K2CQB358
zbOd`1AW=x8S-&D<(IF9uqZmP4b51#T?i@WmC3f%Ly;fD4yS!Eu&{O2|IaF1{4;{k5
zC-famLk7X;=&@s5IDe5nSM6fchK;DI%JlR!zVBn2Ccf`7zch!T>tr(NwRPU2geVCF
zen1d=)aw;gO~UH5iNcs>v%$*30z?r}oDldPR-=k%cUf7Oqh4NQb!m=fZG~>VPP4K|
zwX%%e?2^l6NW=t1k|_-gQClvvTCI^X(pL8FHx^Y&}VmFgrWTzx5Co)BYm&;Y)k0TQ1VO^;wgD)lb5v_pBuPXPb!1IN6eWtqB8H*U=~!s8jHF1o
zEgMajKvj`25o8Tjkub6uhWbZ{M1d!s`4&sd3-qN-Cbmy-*ZuG1=_j9MUEcudLYg3k
z)zvb~%d42G!Ku?{NF;&1*YCsYR9Tvtrq!-vwVL>Th@vP=OiXa&jn~mt3%Fjuw(VE5
zW&3XOeM7u@=m?=CFfzIh#df&;z*Z(tmYH6d1KB0CS2=!Zn(=`F?mh5fJl|t-@*>Up
zGN1bByWeJ(zmph2mZwxzdw9()Q~7J((M-M^#>vlxaYX35L`g&t`pB9_;Mj)ov0-0ZAOA
z>L$8w;0F=e_B
z3w-9GhiP|3HgDd=&DUScO1X^P?hr>Ik|YrXYc{cxq|m7c%*?HF+nslF{r+8y_b6Py
zbBs+}M`^7_%%8qYP8nn4?lcpdhqyH7Vns6R`nEB?X%FXTPBNI+*)`h7JNA9=5X|{+
zUO}Z&Ih;zR9{DH8EZ;k)aoqNuhW?$L<-58!K#1M0B;}Q5YRk*i8x_JJpgOleyIREw
zCAxN-R<}bOC-`27Ac!Oq1VMl;#I)OOnwE{On}AH$?vl+G{_^*uD5lx!P^;Al!+7*RmM^!%C$3GIDHbUvBDd#y?_`exUNUGm?xLZv32v+1ggp15BwmXxPKoa
zYXVE<%IClO+?Q!J>kRB($EQB}0s4R?VD_ZPt7nf=DhT|@-TS^LNZvepHc6BerM@AS
z<`=Nrb^h=Rzs;Y0?T>}G!SdJRF}^zti?3AFA|NERtoZF$3(Q@b#BprGZim|Z
z64iDGH*oMh8$~hbI3CqXl_W_pvnd2o#t#BkmKRY}jQ{~jma%PzB#uyY9XE0qVXOLBemDMt;rlTnemSd4gr^#f}=vs|C!NDE4E)d`j%-9xKoBHs+oHFxpE!z1XVUZ!jL>d(
zsZ^Fo>uDrOKv5-R8B{$*;L4QxdRRBHiEK|E#qoIjtB=ufx(tnsVk!o;u19D!QRIZO
z7jx5nAL2tF|1lcn241bfv)}qtVz0~LHxF|8^a=V(1(GDfNUu%X@4W5+1M5eL4V`-*
zcprNvHWL8lMUU7IIQ;SpJn`r^$o8r9rc1ov
z1gMIN7q)3On@EaGUvCfje1WBG>Jl
z(8EYn;s89yMo|q?W*Sj~D1fP%8LBHwWDJdBAx|8I2vSUhPlP}^RluM_wYf~Kyh`G9
zF%^-?ne(KxX`H|!bUO5G9OWJF{U8-DWb=kGin$!aV?&%@o+qr-xOnM2zTF|0k|7DO
zIvtFRj&5k=B!Pi^4muXy`6ZN4pgFh7^2KwUeCt(GvPP{|MXuFJNg;2%@+}TN{~T}D
z+SFx(og*b~**?V3_HpJbT@JqbIvcj`W^8>A*K8SNaJ0Y+FCFGfzxz9!I`Rrq%l~?z;L^FX$<*1i2#$rRz*KD+$Fd2!4((QprrlZd0(M=JI3bEX
z6h*`L0yaU*jEg|B~eCJL_`S!&u4geoJ=-_)#*|wISXzR>#~5EflgGL9uG{(DFZ{l+u&|KiaycQB
z$-E7gzin;<5=3oIzV$}ZUS1^dExL}w>e3>bD3Qn_cM
ziFYUxMEuUcHj{PF#wvPAczWn;3EhL
zdM1Y=s&pKWBnc5kSY28Lz)yVgxe~4yFfcg8%{SjfZ*LEcxdvw@FL3tkIohojNs?fg
z28N`N%jGDJ3=l;D)#@sa+eXneOnuElHcnzZ*QM0kLl6XHQdun9qE)vDf{0u$$Hq4Qk~Y)Gl8UCKuq=ygHicz%k!2Crcd#0D9LFV}G4Xtt&<_za1*)|&hHjuJItO9xCN3nxK+I5koz_Y#Cq2
z7k~42*uHxcsa%Fz_uq=+xj3#(yImtrVr;8JE|o&lG`by&(06gVU2NOJwcAuG%Or73
z7`nufhpGu6MkJz)>xHD!c|<`&lQmLlgS0LY1|Dfy$8CG$%p$(;Q!m%h%nZN&xnJW~
ze)U)WTAm_`^4rYv_hFfZ%g2*5$B$4lbUJpMj@6>xsbM=7j$@P9F1jF5w`_D>qh4=N
ztyD>;GK675Z*MP(qJih(dM*MI5eZhuMo}az*CG~u5=X>!9YjsWi$dZsArwJT3;;|q
zMX@K38@Vi%S8&}BKamh*6*mGgNDw8FSdb6|k&f+P+cxQR8c7jA67YinBa>lpaF|lD
zM2twSUgPMoV=PZjQ|!&LZft~NDM#o#)M`~kK}A#6`ZMWt3XpL9fNt9cAfGRy>nbPC
zoa2t$?;`LMMn~2o8zylG$4(t(X>p04`1FtAc>(kD^Q>RLp4F9A4nFe?)zx{*%gbyU
z--xWqD5^pn2Um*v0*>P$ioz8K&4@7Z3Gqo{fs~QOb^-`Rl0-yS1YF-n5kQheL{UKz
z6=p9lvHz}peDae&$(?r|_*OKPs1;)om2}6&i<_fmmp}D+5RyR=u
zk+$s;#Sy;e5(W|Ta|p63%dE^)lZ_HN{&YcfG#6U8xxq9KVYaV#Lp0j}o}
z`2w-DHoO;vA&%|v%fIq3_@$ru`G1fm<=bHSpPX`KHkm(k2;z_=c4@R5_<@V#biwg(
zyIpL@L047Umc1rv@jW{2HkoV|$F@O|@O_U|CWB)+BuRqRZ6hlQf*9dDYmd>79L!W2
z*KvuH7*V`Zsfk5IS)}XO1SCXZh#!I*2oOuu{SILiBF7SDDhshd6hhbTk}`FgUWBSB
z$clXB;YAP&*g-%(mt)=77!x~pG1$MJ$#a)^=DFvXK7SF-kSOF*D2j+-7>Htmrl~ky
z7prZfX&Re1Z{zI6vs9~fc1-MK-MV#5PF}}%@r)#l({RSHKI!*#X;G(G-Vgiz^(r&d7@ezfXNEENk
zYjlxi8Q=2|6%j#Lv!`_&5JYjU1TDrSM8si87$mqJgo%LXxip(?By@sUKon)vl#cKF
zSV@GUCG2vKAi-&@OZ06Zta
z4M0{*=9iZ6qJT^;O&F|=VFPR7pr(+-;+5Z(3FCxV04oext~Uu2i5m~x#qIm=Vq|2D
z<)u0oFP&w6@e;4S{vwsi(iQz#AGhs4z`AWaIeYF5hhKb!T|2guQe~R;`q~P0H$>Gl
zRBNk1h?&vxJQo3({Wl-Lwq1^$If)?1)SGP*F(OJ_wr!hWd~6&+lySNZhDSCqGCD!M
zZ6k>ir_Y{ZX=NJEcUZb~3CHPBtF5AnYd+YfnWDGUho+e%aX{0tnOj<>N;`gB9MR}5F`OYs36Nafd_&pplbp_
z>=Sq%hzfD!6NjKED!v~f$tsrZ;5rT=5{~1csTxrnVB0oPv{oYb;}AvE@Dra%09n>S
zGw>sk%QJI$NrYzVY#Z3XrY#ffzUErIP@r0Fa_G<@UVYAD`Foewy9Z5!9W4VLehA|S9TNxNMmN&?cVfhbCJJ)0nQ
zrTJM7z4AI+wr%Iyy?Y4}NHhgaQ?MFsoUYC4;v&^@71wu=4TbRyV{}4`!-q~#nXk~X
z+q9Z>tX3UKF)0nLqiCkkG?PN1$okQZjBXwWG34y|GgPZfv=`^_9iPC0j^!Y0DuTG?
zL7ml9N<+h}pV&&z$S4`JM9N6vwcGsCFa7l2DsOokEPq?Lgf^AhauT=}Su;nrw;#J*
zMpZSEB*yc6!YHKMZDSfH>2#VXiq;rL5J-}Q;7TbuNfI2#A?dpKp+~)5#kOr?+osW~
z;dC8PWYUCqeuyd?xUProb&yH09h)eONM{YAC?fU)qA(^1)_`f4DHKJ=?sidClQ<4>
z9gjr3BJ+s?!Z5(LEFi}59ISR1RY?(s;Kv|KGO?cE1s<|$uu^MMS*2}2j@?Hfc%mxyDT=4zeIo5%Uh-~83L!Sek+wp06Dy|(%pQPvOz
z8OyFv%oi}t6z&yqWUJjGlS*TnYnJhfqI^D#!q33k1N1x>QIrUy5GM@Ku6O|Wo{fx1
zM62}3uEaP+?JljT;fgoJdm5DM@9MNaQ5X>}c0G?wO3!p^E}L~!3RI|A>RMM2WTWRXHNaU?VW9mT-SNu
zf9KwN=H5GVXJ%ixey}JBu$GJFhb>}X^gZkg`f$V
zZ&Hgk1)9JWQ3OGN0D(UR?Uyv78@LW+sS#sIv1O4Vm(+5}<#2arXYSm&Z|9tQ^5L!`
z7f$2Eu-q!Xzb`v`cXk%LGyi$^dCv3vpH;TEQmzkf;>es!U;h(^+dGT~L;7CE*48Z?
zze5=I=?86OOY)%)ALHl$`Dq?`@G;Sd<-Mwo<-^l)yz@fX?lPTbRCY=?s)aF0CU~C5
z)^MAd{tRIlqRNuM_s?r>PFlcm9j3{YFbt7WqLqT(N)@&ubR`H2Wl81KrBR&PSkP)s
zmX;`;lTW8)X~JN*#b`Vx9mP!31S&;7Ns&^L7a6W=>s~cgA-w=mS;{oQ>JnXPtg&^w
zhhJf|!S#F)Ep%xy#!!}ZRNRTDY;J8)nu?Ye;)Ve#HyF2|SV!lW$8q~O}%CdnwJ
zg9K+5V{?Lb#B@4g&z=SL?%m6t#r@39&e8HL?d}}i{ya&RGc!9&mS$YJe2ME<)_CpW
zc}$wqYqycoXKro|&udW{O=qUh!;d`4{-Yn})Tcf{23)_9Gq`qzosBDG@h!69gk*e+
zx369$EvHN-6FecAo$2#KPe0A$k3Pxa!-quVH)44YQ0(jsEC|}|_Nh48deL(|q9~#$
z3q053+WHzZGqZG~F0SkB02ouvdY*f}EX$KwmeFpv>ven;q-nZ)^6V1G7T5}%P7$7q
zi2CG3$}~-h+FgXGho|y9t$WLagEktYHKTY;l@;vljHpz`IF2c%o9NOoolJ1F#rHfs
z0|G;qr`WRY%+AUfrE;VU&U=qJSbd;0lJrVf{EkK$_%Cl9VFL2-+Q#DhX%i
zNXmjZoziM`h~p9QxS%C{=Jzgul!Toge!ES7W`=%$hAc}NjYizq9I~~!$!IiYvNc4N
zIW5OQ_S|}byyLKMet{&(2-`h8&m)N1MDw>3&2(72?EpXd<3GjycP;|(jTqjzc!lxx
z0eTwaI5|a{uzBkiZV)opo8z9lKgwJ`V(rQ$e&pkii$*N(Ni$4LJWA~B%z}s~8&+#Y
zyWPR_>M?+~uU#c-cj)(L2z>t(fHwL$$92zE#+MoyB!MjL}q;0Z*b-g_Qo$Bug%*>4e!{AA`knJ*>6(fqx2Pm$cT;S*2zt;}MqH
zR736dT@_hIo+;wt2sKSf(;ZL>;aW^-Fj^x-9gzw(!D@#*H)x}4Cs64Tgg%pTN~K_u
zPKnc`wsTDj!l;jKIVe@(A(-STTf-^2G33UQs{%(jRJNj2waGYu>-y|$51HxriJ}h0
zG{^5aL{WzuH*S#Unu7-q(&=>YJde3vA31jb&&`?bw6KN4sVDwED?j>one9OeTpGd4
zU-}By*WP0P!d{e8TwS}$?fY+I|Gq^oTzs7e@4J_$9($w_%X=xALQR%jVNQ?7qcg@>
z+U*cex@>Q6(}_CtdVRLHw^*3pFTg>Y>8oW~o)khLblnW81!%1a+a2;e!>hoxFqur4
z+qW02QxBhb)F<Qc8Ux%ciq_P@lp0L4fCa&kIMa+R83frdpA*yIdh~sFy%F
z1Q=3=qp>ZDoIEWU-MEC#rfhEwP-TYD6L1FU(FNhGW0Iwa=?X~&fM~?H*;~(e1
z;SbW^C;7eK`=5;0-{#JvcktL_5A(-g{VL!1+8Y#U!b6Wdz*G0%|84V@Ml9b2!KCSy
zHOAn&F0Si6Z;U>(wKX7$y1VWy1!35EUdrfMD9MYdEz5#VCwks>!e{d$w!#s3Rh{_u
z+8u-=D2tL%N-Ec-&?SBlVzj}i3R<$xfoz4PPVy@QQPepKkf!P7b~_SE=R>2#s_VLE
zU019EIF7eFUhSc^LX?Shr97W!$;q7|z##v@Mr!2Qg%I&39FF0QR{_lbKbCJ8V7!53M+_da^A^rOewyKs;!nE<+O7R?py
zZkIgIxZ}p1SYT&XVz*V_SkF6e~2Z7u0@
z2$)*!F{WYc+FVUUv
zVQo$ZkQU^5PCMu#{VrKH#n&ZHrOC65c3aZ5ZF+&AQkH2}k>#4$tw?i)GL~p}95vIzXt15LydcjffR_n*NK#4NNim;FlwqAVw_1Ed|
znITJd7~L8mw4p3ZCetypB~V$8q3#qY^O9_5hf0^A%ld$}tT41FDodQD6iGp$6uRXy
zNfT1zGB>}-UH2@rF}TGWufE2{V8He3n>?`m5KlezG&eQ|{KHTG1V8t${v}~o^TcCM
zuxEA;8-s0fEyzm4{>4SEu3q89iM!d^9`oOR|9|j{pZ!HVEdTk}{sVK7&u2dKPj}5Z
zJbv_tKPj5X^1kESZKLwO>8X47b|B}Uediugo872pR(nynYs}!`z^d=*v)W{|+OoDr
zvZXau_MB4r8Q}=PoUS8ev09H>OB~ld=OXFt-E(T`LwCM-@X!ZDI^MQh8|zp{pp|B0
z;~G>JZ3?ENn4R&6UZ+Ld?bcldwm_AN>2yMA!PN%Qa!~CSN^8dPHafI~!ehMsHZT9-
z0BcEkF
z@rU`^zKAb>@g;ugmw$!-{s%Aejkn(9`CtAl$!LSmfBrZ4`kQZ1DMeaL_`ydX9?tgm
z&NX8BzQyHR9ZWntw>D^SJdoW`K#A*jo_+Uw#9u@#P`G&YHB+s$WC*ULJ-0_33Vcft
zJcH9dd-V7+DvPZt6xLd#w{*O9&iFvdNIQF1*1LKX{V$s~1SNH+k#LKjo1JA7bs#
zF7nDt|BKre_weRhZ}9TVU!p2g)~>8_?aC@nRdUC%V;nmC0Y3JzCs@Akfu?la@K=%T
zilW-hfBw2?VwEx38CsL4SZgWEq8_CV+bC0zmjzNvr038z9%(i~VM&UNty^0RH?Fb0
zb)BkI6!Dah+GxU9!*H5lsAuoT+d~SikY0;4Eh*E2w5UDX{5?Ic+*s%6(GMbY#oFrI
zR5*O#&bx@?9nvf&41I8XCh@LoP1wdka_rb$9653X$MN{gPydr=dg0vJMl22QAq7bq
zzp9Gzr0cpAMaIlb|Cv0`U+_F{M+mWMtz8On&!USncn*kqz-^jLN%IL;FJ9pKrK?Pe
zDS4Vf=
zp65O5dF^xPYze9rJn!tg#fv&0s`4#sCnc9xFEWfrY;A2a9j9c)l+D2ns5EmkJsb;L
z!&{VDJ+6@DIc2H91yMN+rwLX_G=g}Vvc0`crV5nObb^p+o-;qYmrf_5)$);kn@2zP
zB%l5H&o#qe4gYV@W`g6oI0QgRMTIp6FiTLaxUO@~m}*5-=CmXIWvb#;obEFD&_V@T
zlcy!u*Vp;RTW|8GUwe&XhZfO!L0+b$qcKv3Y;SGWW#=qI7?<2AWUIq=oPZ|?qYe{Q
zFrCD-J)g+$(3|Pw`yIR>;O-MA_~eiM#Hm33WoGe>SQ@@}lHo5ev}V-jHqP!x3zSRX
zt^!b{77MtoQ{?4~SJ$rc$FKZv%w$5EO>im=rotGF5Q0*bB*}y_o{*(ELbiz0TC90x
zC`~~x>ft*rtT2Q!L{ahNQ-6;qKlu*?^!`S_RZ}`{cn|o$y{y7-5tT6|t{VV3IQ~&o
zei>V>5QL)B>)Q_>KMuNL8jp#0w#lb4)A0yT`lLyWsVrUTk#!VhSrSDdE#HHx-jYye
z848D}UmvhKK}e?;K#^Jeo@m6<@V*h1>qe_}qzQq16&dZmfF+&YEC>8Hv$J~zn)(6;d>l~93a}gZGZ~b^`2KMK2u+_OH`WnzWwKqcKatiDOta^#`g9mMPA~WfUp~p
zWhr6QA(TGWR7lyv^8&P^@Y<5wj~rp|!9)DbO65(?((t|@*%eV%i%6HJalEtX<_%lw
zjMdduhF33OU59jTStOV_+=!*&`x8^#
z8tQa9yE#}RO%f_0$np}S>QU_jiwCf-0O2ur;E;GXS~X&6_`XC#F|hcp^WdH>lF196
z=i>$)L8VTEa}KAq3hnRsCp2Pd_*+K3s{K2ub~Oop!}l4IceYS}w`n3vL&IMar}+~!
zG&EvqXlTUJ(9npbp`j5=Lqj8$hK5Eg4Gj&ASQ;7{u{1O^Vrgh-#M02vh^3*S5lcfu
tBbJ7ShDIz64UJeD8XB=QH2nX^p99(SOkLC8i9!GX002ovPDHLkV1lA%K=uFt
literal 0
HcmV?d00001
diff --git a/redakcja/static/img/angel-right.png b/redakcja/static/img/angel-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..df85d33aab70b18cdc2921e68af2d750ccc6e48c
GIT binary patch
literal 41705
zcmV*fKv2JlP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007bV*G`2ipb+
z2q7QwUDB-p000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}001BWNklq^=^U%Nx+~{g`~JX}d$`YeuI=kY==Wd!sI{MGt?ymmihB#9
zD6-8qzsX3pt6-aL3AXu-C0ByYNJ@+(%8&mh*MqP<9Qw^;@cOtoKD!2TDaAqwp`t`0
zl~C82((NEdA?=Z;Z7|k{`8WWTR6h;eT0aOYBfh7C7
zJ;HB7oyfMs;x~(D{^40Vx_ihMGmMWfA_#IcY6Dh_8