diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000000000000000000000000000000000000..8384876b2c2f668ec20eee63486e21c0b7142b57
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,57 @@
+# This has to be set to any good enough random string. E.g. something that
+# `pwgen -s 32 1` would print out. If you want to know more about this go to
+# https://docs.djangoproject.com/en/3.2/ref/settings/#secret-key
+# (mandatory setting)
+SECRET_KEY=put-something-awesomely-random-here
+
+# A comma-separated list of hostnames/IPs Django should listen to. For a
+# production setup this will be something like aura.example.org, for a dev
+# setup you might just use the default settings.
+# Important: do not put spaces between commas and values!
+# (default: 127.0.0.1,localhost)
+#ALLOWED_HOSTS=
+
+# A comma-separated list of URIs where the webclients live that should be able
+# to access the steering API. In particular the dashboard. Might not be needed
+# in a production setup if steering and dashboard share the same domain. In
+# a dev setup the defaults might be just fine.
+# Important: do not put spaces between commas and values!
+# (default: http://127.0.0.1:8080,http://localhost:8080)
+#CORS_ORIGIN_WHITELIST=
+
+# The database settings.
+# if you use a dev environment where django is not running inside a docker
+# container, but you use the postgres container for the db and map its port,
+# then use localhost as the database hostname
+# (default host: steering-postgres ; or if RUN_IN_DOCKER is False: localhost)
+# (default port: 5432)
+# (default name: steering)
+# (default user: steering)
+# (pass is a mandatory setting)
+#DBHOST=
+#DBPORT=
+#DBNAME=
+#DBUSER=
+DBPASS=change-to-something-secure
+
+# The timezone of this server. For a list of all available tz database names see
+# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
+# (default: Europe/Vienna)
+#TIME_ZONE=
+
+# The language code for the localization of this server. For a list of available
+# codes see http://www.i18nguy.com/unicode/language-identifiers.html
+# (default: de)
+#LANGUAGE_CODE=
+
+# If steering is run inside a docker container. This will be de default for a
+# production deployment. In a dev scenario you might still want to have the
+# database in its container, but run the steering dev server directly on your
+# host. In this case make this False.
+# (default: True)
+#RUN_IN_DOCKER=
+
+# This should be turned on only for your development environment unless you
+# know exactly what you are doing and what the consequences are.
+# (default: False)
+#DEBUG=
diff --git a/.gitignore b/.gitignore
index 5a5266d6a03d8fa52292d10572d6e443e02a28f2..3705dd8a5180b4bdb017e7406ab9f8027473a10d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,17 @@
 *.pyc
 dev_data.sqlite
 static/
-pv/local_settings.py
-pv/site_media/buttons/b-*.png
-pv/site_media/buttons/s-*.png
-pv/site_media/buttons/r-*.png
-pv/site_media/show_images/*
-pv/site_media/note_images/*
-pv/site_media/host_images/*
-pv/site_media/__sized__/*
-pv/cache/*
-pv/mysql.cnf
-pv/postgresql.cnf
+steering/local_settings.py
+steering/site_media/buttons/b-*.png
+steering/site_media/buttons/s-*.png
+steering/site_media/buttons/r-*.png
+steering/site_media/show_images/*
+steering/site_media/note_images/*
+steering/site_media/host_images/*
+steering/site_media/__sized__/*
+steering/cache/*
+steering/mysql.cnf
+steering/postgresql.cnf
 venv/
+python/
+.env
diff --git a/Dockerfile b/Dockerfile
index f95a8b3d108aa9d1413b771f7a7e2a94d97686c8..dabbbfdeff11a67a4a770972ddb4fcb98edbd63f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,11 +1,21 @@
-FROM python:3.6
+FROM python:3.8 AS base
 
-COPY requirements.txt /tmp/
+ENV PYTHONUNBUFFERED=1
 
-RUN pip install --no-cache-dir -r /tmp/requirements.txt
+WORKDIR /aura
+COPY requirements.txt .
+RUN pip install --no-cache-dir -r requirements.txt
 
-#RUN python /tmp/manage.py migrate
-#ENTRYPOINT ["/tmp/entrypoint.sh"]
+EXPOSE 8000
 
-# Superuser parameters are --username USERNAME and --email EMAIL but there is no password
-# RUN python /tmp/manage.py createsuperuser
+
+FROM base AS dev
+
+#VOLUME .
+CMD ["python", "manage.py", "runserver", "0.0.0.0:8000" ]
+
+
+FROM base AS prod
+
+COPY . .
+CMD ["sh", "-c", "gunicorn -b 0.0.0.0:8000 -w $(nproc) steering.wsgi"]
diff --git a/LICENSE b/LICENSE
index ecde97c640ad5ad94a051c0bf19e4a266736b690..accb24cd4ce56a277a3ab6fbe2d520a6bd469f6c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,27 +1,681 @@
-Copyright (c) 2011-2014, Ernesto Rico-Schmidt
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this
-list of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of the author nor the names of its contributors may be
-used to endorse or promote products derived from this software without specific
-prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<https://www.gnu.org/licenses/>.
diff --git a/README.rst b/README.rst
index fcbe942f4bb0943bf224bc247e2ecde575525339..7fd1d23c9d209bfcb9ca35e2566dce015db2a118 100644
--- a/README.rst
+++ b/README.rst
@@ -5,31 +5,31 @@ AURA Steering: Program Scheduler
 Installation
 ------------
 
-If you have a working Docker environment, do::
+If you want to have quick dev server and already have the *steering-postgres*
+container of the *aura-web* repository running, follow the steps outlined in the
+*Setting up the configuration* section and do::
 
-    $ docker build -t pv_container .
-    $ docker run -p 8000:8000 -d pv_container:latest
+    $ docker build -t steering-django --target dev .
+    $ docker run --rm -v $(pwd):/aura --network auraweb_auranet steering-django:latest python manage.py migrate
+    $ docker run -it --rm -v $(pwd):/aura --network auraweb_auranet steering-django:latest python manage.py createsuperuser
+    $ docker run --rm -p 8000:8000 -v $(pwd):/aura --network auraweb_auranet steering-django:latest
 
-and log into it at http://127.0.0.1:8000/admin/ with username "admin" and password "admin". Full setup without Docker is done as described below.
+and log into it at http://127.0.0.1:8000/admin/ with the credentials you have
+set in the ``createsuperuser`` step. Once this is done, every other time you
+want to start a *steering-django* container, you will only have to use the
+last command.
 
+**Full setup without Docker** is done as described below.
 
 To get setup you must have the following installed:
 
- * PostgresSQL or MySQL-Client Development libraries
- * JPEG library development files
- * Python 3.5 including Development files
- * virtualenv 1.11
+* PostgresSQL (except you are using the aura-web docker container *steering-postgres* for it)
+* JPEG library development files
+* Python 3.8 or later including development files
 
 In Debian or Ubuntu (or derivatives) you should be able to achieve this with this command::
 
-Using PostgreSQL:
-
-    $ sudo apt-get install postgresql postgresql-contrib libjpeg-dev python3.6 virtualenv
-
-
-Using MySQL:
-
-    $ sudo apt-get install default-libmysqlclient-dev libjpeg-dev python3.6 virtualenv
+    $ sudo apt-get install postgresql postgresql-contrib libjpeg-dev python3 python3-dev
 
 
 Setting up the environment
@@ -37,84 +37,40 @@ Setting up the environment
 
 Create a virtual environment where the dependencies will live::
 
-    $ virtualenv -p python3.6 python
+    $ python3 -m venv python
     $ source python/bin/activate
     (python)$
 
 Change into the base directory of this software and install the project dependencies::
 
-    (python)$ pip3 install -r requirements.txt
+    (python)$ pip install -r requirements.txt
 
 Setting up the configuration
------------------------
-
-By default the project is set up to run on a SQLite database.
-
-Create a file pv/local_settings.py and add at least the following line::
-
-    SECRET_KEY = 'secret key'
-
-(obviously replacing "secret key" with a key of your choice).
-
-
-Setting up PostgreSQL
-----------------
-
-We recommend using PostgreSQL in order to be able to use the collation utf8mb64_unicode_ci and thus being able to display all languages.
-
-To use PostgreSQL, add the following to your local_settings.py (before migrating) and add your credentials::
-
-    DATABASES = {
-        'default': {
-            'ENGINE': 'django.db.backends.postgresql',
-            'NAME': '',
-            'USER': '',
-            'PASSWORD': '',
-            'HOST': 'localhost',
-            'PORT': '5432'
-        }
-    }
-
+----------------------------
 
-Setting up MySQL
-----------------
+Copy the ``.env.example`` file to ``.env`` and change the values accordingly.
+You have to at least provide the ``SECRET_KEY`` and the ``DBPASS`` values
+for Django to start. The file provides extensive comments on all the settings.
+For a developments environment the defaults should be just fine if you use the
+*steering-postgres* docker container from the *aura-web* repository. If you
+want to create your own database on you local machine, you will have to use
+*steering* as the database and user name, or adopt the ``DB*`` values
+accordingly.
 
-**Note:** When adding your database, make sure you **don't** use the collation utf8mb4_unicode_ci or you will get a key length error during migration. (use e.g. utf8_general_ci instead).
-
-To use MySQL, add the following to your local_settings.py (before migrating)::
-
-    DATABASES = {
-        'default': {
-            'ENGINE': 'django.db.backends.mysql',
-            'OPTIONS': {
-                'read_default_file': os.path.join(PROJECT_DIR, 'mysql.cnf'),
-            },
-        }
-    }
-
-Create a file pv/mysql.cnf and give your MySQL credentials::
-
-    [client]
-    database =
-    host = localhost
-    port = 3306
-    user =
-    password =
-    default-character-set = utf8
+Also be aware that there is a ``RUN_IN_DOCKER`` setting that is ``True`` by
+default. This should be fine for a production environment where Django is
+run inside a container. If you follow these steps here to create your own
+development environment you have to set this setting to ``False``. You also
+might want to set ``DEBUG`` to ``True`` for your development environment.
 
 
 Setting up the database
-----------------
+-----------------------
 
 Then run::
 
     (python)$ python manage.py migrate
-    (python)$ python manage.py loaddata program/fixtures/*.yaml
-
-Open pv/local_settings.py again and add the line::
-
-    USE_TZ = False
-
+    (python)$ python manage.py loaddata fixtures/*/*.json
 
 Adding an admin user
 --------------------
@@ -123,7 +79,6 @@ In order to create an admin user (which you will need to login to the webinterfa
 
     (python)$ python manage.py createsuperuser
 
-
 Running a web server
 --------------------
 
@@ -132,6 +87,30 @@ In development you should run::
     (python)$ python manage.py runserver
 
 
-After this you can open http://127.0.0.1:8000/admin in your browser and log in with username "admin" and password "admin".
+After this you can open http://127.0.0.1:8000/admin in your browser and log in
+with the credentials you have chosen in the ``createsuperuser`` command.
+
+If you are using some placeholder credentials, make sure to change your password
+by visiting http://127.0.0.1:8000/admin/auth/user/1/password/
+
+Configuring OpenID Connect clients
+----------------------------------
+
+To make AuRa usable, you have to set up OpenID Connect (OIDC) clients for the
+*dashboard* and *tank*, so they can make authenticated requests on behalf of
+the user against the *steering* API.
+
+To do so, you can either visit the Django admin interface and create an RSA key
+as well as two clients, or do so programmatically by running::
+
+    (python)$ python manage.py creatersakey
+    (python)$ python manage.py create_oidc_client dashboard public -r "id_token token" -u https://aura-test.o94.at/oidc_callback.html -u https://aura-test.o94.at/oidc_callback_silentRenew.html -p https://aura-test.o94.at/
+    (python)$ python manage.py create_oidc_client tank confidential -r "code" -u https://aura-test.o94.at/tank/auth/oidc/callback
+
+In these examples you will have to *https://aura-test.o94.at* and
+*https://aura-test.o94.at/tank_with* with wherever *dashboard* and *tank* are
+running in your setup. In a local development environment this might be
+something like *http://localhost:8080* and *http://localhost:4000* respectively.
 
-Make sure to change your password by visiting http://127.0.0.1:8000/admin/auth/user/1/password/
\ No newline at end of file
+The client id and in case of the tank also the client secret are then needed for
+the configuration of those components.
diff --git a/build.sh b/build.sh
index 263476c355626b81e6d51940af34cbf847f5c104..85728be446d8988c5d46406d9f4086aba3041835 100755
--- a/build.sh
+++ b/build.sh
@@ -1,3 +1,3 @@
 #!/bin/bash
 
-exec sudo docker build -t aura/pv .
+exec sudo docker build -t steering-django .
diff --git a/cleanup.sh b/cleanup.sh
index da119306e4e507effbb89626800d3b8f960b8ff6..fed7ec0987dcc5ed7297fe330a9db654b74d0cd3 100755
--- a/cleanup.sh
+++ b/cleanup.sh
@@ -1,4 +1,4 @@
 #!/bin/bash
 BASE_D=$(realpath "${BASH_SOURCE%/*}/")
 
-rm -f "$BASE_D/pv/dev_data.sqlite"
+rm -f "$BASE_D/steering/dev_data.sqlite"
diff --git a/entrypoint.sh b/entrypoint.sh
index a09fd6f84f1f914ee2527112f1371e33f63e3901..c0948323402586401260305233056221ad28ab8a 100644
--- a/entrypoint.sh
+++ b/entrypoint.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 set -e
 
-python /tmp/manage.py loaddata /tmp/program/fixtures/*.yaml
+python /tmp/manage.py loaddata /tmp/fixtures/*/*.json
 python /tmp/manage.py runserver 0.0.0.0:8000
 
 exec "$@"
diff --git a/fixtures/auth/group.json b/fixtures/auth/group.json
new file mode 100644
index 0000000000000000000000000000000000000000..06dbacd7e25d17fe967c3abda8d2d0c46df9132a
--- /dev/null
+++ b/fixtures/auth/group.json
@@ -0,0 +1,10 @@
+[
+  {
+    "model": "auth.group",
+    "pk": 1,
+    "fields": {
+      "name": "ProgrammmacherInnen",
+      "permissions": []
+    }
+  }
+]
diff --git a/fixtures/auth/group_permissions.json b/fixtures/auth/group_permissions.json
new file mode 100644
index 0000000000000000000000000000000000000000..c2b8e7c683df387460ce633b4a523b45f1c27a56
--- /dev/null
+++ b/fixtures/auth/group_permissions.json
@@ -0,0 +1,50 @@
+[
+  {
+    "model": "auth.group_permissions",
+    "pk": 1,
+    "fields": {
+      "group": 1,
+      "permission": 35
+    }
+  },
+  {
+    "model": "auth.group_permissions",
+    "pk": 2,
+    "fields": {
+      "group": 1,
+      "permission": 28
+    }
+  },
+  {
+    "model": "auth.group_permissions",
+    "pk": 3,
+    "fields": {
+      "group": 1,
+      "permission": 29
+    }
+  },
+  {
+    "model": "auth.group_permissions",
+    "pk": 4,
+    "fields": {
+      "group": 1,
+      "permission": 30
+    }
+  },
+  {
+    "model": "auth.group_permissions",
+    "pk": 5,
+    "fields": {
+      "group": 1,
+      "permission": 8
+    }
+  },
+  {
+    "model": "auth.group_permissions",
+    "pk": 6,
+    "fields": {
+      "group": 1,
+      "permission": 23
+    }
+  }
+]
diff --git a/fixtures/auth/user.json b/fixtures/auth/user.json
new file mode 100644
index 0000000000000000000000000000000000000000..59c9850cb3a9158320ee38a2d7b79256db34ce8b
--- /dev/null
+++ b/fixtures/auth/user.json
@@ -0,0 +1,38 @@
+[
+  {
+    "model": "auth.user",
+    "pk": 1,
+    "fields": {
+      "password": "pbkdf2_sha256$36000$uMBrNYea7vcc$6599RKSDzRkpoO8lcOjOQI/O1ufPXphIYh10VNqZcYU=",
+      "last_login": null,
+      "is_superuser": true,
+      "username": "admin",
+      "first_name": "",
+      "last_name": "",
+      "email": "",
+      "is_staff": true,
+      "is_active": true,
+      "date_joined": "2017-12-31T22:00:00Z",
+      "groups": [],
+      "user_permissions": []
+    }
+  },
+  {
+    "model": "auth.user",
+    "pk": 2,
+    "fields": {
+      "password": "pbkdf2_sha256$36000$VVSM5LeZfBZM$w0XSHCrucEb7Oj1Qpjdy1SKq5KelpXSPiUXbxh3rWpM=",
+      "last_login": null,
+      "is_superuser": false,
+      "username": "pm1",
+      "first_name": "",
+      "last_name": "",
+      "email": "",
+      "is_staff": true,
+      "is_active": true,
+      "date_joined": "2017-12-31T22:00:00Z",
+      "groups": [],
+      "user_permissions": []
+    }
+  }
+]
diff --git a/fixtures/auth/user_groups.json b/fixtures/auth/user_groups.json
new file mode 100644
index 0000000000000000000000000000000000000000..ca3a1e2715920725a31c694012f76d093ae48bea
--- /dev/null
+++ b/fixtures/auth/user_groups.json
@@ -0,0 +1,10 @@
+[
+  {
+    "model": "auth.user_groups",
+    "pk": 1,
+    "fields": {
+      "user": 2,
+      "group": 1
+    }
+  }
+]
diff --git a/fixtures/program/category.json b/fixtures/program/category.json
new file mode 100644
index 0000000000000000000000000000000000000000..f0c3aa28952d75511f0ed9b6691ec2be33f12fda
--- /dev/null
+++ b/fixtures/program/category.json
@@ -0,0 +1,122 @@
+[
+  {
+    "model": "program.category",
+    "pk": 1,
+    "fields": {
+      "category": "Interkulturell",
+      "abbrev": "I",
+      "slug": "interkulturell",
+      "is_active": true,
+      "color": "",
+      "description": "",
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.category",
+    "pk": 2,
+    "fields": {
+      "category": "Lokalbezug",
+      "abbrev": "L",
+      "slug": "lokalbezug",
+      "is_active": true,
+      "color": "",
+      "description": "",
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.category",
+    "pk": 3,
+    "fields": {
+      "category": "Minderheiten",
+      "abbrev": "Mi",
+      "slug": "minderheiten",
+      "is_active": true,
+      "color": "",
+      "description": "",
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.category",
+    "pk": 4,
+    "fields": {
+      "category": "Wiederholung",
+      "abbrev": "W",
+      "slug": "wiederholung",
+      "is_active": true,
+      "color": "",
+      "description": "",
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.category",
+    "pk": 5,
+    "fields": {
+      "category": "Mehr-/Fremdsprachig",
+      "abbrev": "M",
+      "slug": "mehr-fremdsprachig",
+      "is_active": true,
+      "color": "",
+      "description": "",
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.category",
+    "pk": 6,
+    "fields": {
+      "category": "Frauenschwerpunkt",
+      "abbrev": "F",
+      "slug": "frauenschwerpunkt",
+      "is_active": true,
+      "color": "",
+      "description": "",
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.category",
+    "pk": 7,
+    "fields": {
+      "category": "Österreichische Musik",
+      "abbrev": "Ö",
+      "slug": "osterreichische-musik",
+      "is_active": true,
+      "color": "",
+      "description": "",
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.category",
+    "pk": 8,
+    "fields": {
+      "category": "Sendungsübernahme",
+      "abbrev": "U",
+      "slug": "sendungsubernahme",
+      "is_active": true,
+      "color": "",
+      "description": "",
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  }
+]
diff --git a/fixtures/program/fundingcategory.json b/fixtures/program/fundingcategory.json
new file mode 100644
index 0000000000000000000000000000000000000000..72d5a68984564fbd51cf2c3ab62585753d82fa88
--- /dev/null
+++ b/fixtures/program/fundingcategory.json
@@ -0,0 +1,12 @@
+[
+  {
+    "model": "program.fundingcategory",
+    "pk": 1,
+    "fields": {
+      "fundingcategory": "Standard",
+      "abbrev": "S",
+      "slug": "standard",
+      "is_active": true
+    }
+  }
+]
diff --git a/fixtures/program/host.json b/fixtures/program/host.json
new file mode 100644
index 0000000000000000000000000000000000000000..5faf6b88ba49e4e44012965952a625cb6c09fcda
--- /dev/null
+++ b/fixtures/program/host.json
@@ -0,0 +1,24 @@
+[
+  {
+    "model": "program.host",
+    "pk": 1,
+    "fields": {
+      "name": "Musikredaktion",
+      "is_active": true,
+      "email": "",
+      "website": "",
+      "biography": null,
+      "googleplus_url": "",
+      "facebook_url": "",
+      "twitter_url": "",
+      "linkedin_url": "",
+      "youtube_url": "",
+      "dorftv_url": "",
+      "cba_url": "",
+      "ppoi": "0.5x0.5",
+      "height": null,
+      "width": null,
+      "image": ""
+    }
+  }
+]
diff --git a/fixtures/program/language.json b/fixtures/program/language.json
new file mode 100644
index 0000000000000000000000000000000000000000..a1b5447bccc8e0af6e7b9c3b0ca3dd2ea2974183
--- /dev/null
+++ b/fixtures/program/language.json
@@ -0,0 +1,386 @@
+[
+  {
+    "model": "program.language",
+    "pk": 1,
+    "fields": {
+      "name": "Deutsch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 2,
+    "fields": {
+      "name": "Englisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 3,
+    "fields": {
+      "name": "Spanisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 4,
+    "fields": {
+      "name": "Polnisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 5,
+    "fields": {
+      "name": "Farsi",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 6,
+    "fields": {
+      "name": "Französisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 7,
+    "fields": {
+      "name": "Slowenisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 8,
+    "fields": {
+      "name": "Persisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 9,
+    "fields": {
+      "name": "Arabisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 10,
+    "fields": {
+      "name": "Türkisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 11,
+    "fields": {
+      "name": "Japanisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 12,
+    "fields": {
+      "name": "Italienisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 13,
+    "fields": {
+      "name": "Tschechisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 14,
+    "fields": {
+      "name": "Russisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 15,
+    "fields": {
+      "name": "Chinesisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 16,
+    "fields": {
+      "name": "Ungarisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 17,
+    "fields": {
+      "name": "Serbisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 18,
+    "fields": {
+      "name": "Portugiesisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 19,
+    "fields": {
+      "name": "Kroatisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 20,
+    "fields": {
+      "name": "Albanisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 21,
+    "fields": {
+      "name": "Dari",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 22,
+    "fields": {
+      "name": "Bosnisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 23,
+    "fields": {
+      "name": "Kurdisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 24,
+    "fields": {
+      "name": "Aserbaidschanisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 25,
+    "fields": {
+      "name": "Slowakisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 26,
+    "fields": {
+      "name": "Niederländisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 27,
+    "fields": {
+      "name": "Bulgarisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 28,
+    "fields": {
+      "name": "Somali",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 29,
+    "fields": {
+      "name": "Tschetschenisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 30,
+    "fields": {
+      "name": "Dänisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 31,
+    "fields": {
+      "name": "Rumänisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 32,
+    "fields": {
+      "name": "Thai",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 33,
+    "fields": {
+      "name": "Finnisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 34,
+    "fields": {
+      "name": "Romanes",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 35,
+    "fields": {
+      "name": "Griechisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 36,
+    "fields": {
+      "name": "Singhalesisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 37,
+    "fields": {
+      "name": "Urdu",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 38,
+    "fields": {
+      "name": "Estnisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 39,
+    "fields": {
+      "name": "Mazedonisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 40,
+    "fields": {
+      "name": "Hebräisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 41,
+    "fields": {
+      "name": "Schwedisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 42,
+    "fields": {
+      "name": "Lithauisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 43,
+    "fields": {
+      "name": "Jiddisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 44,
+    "fields": {
+      "name": "Isländisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 45,
+    "fields": {
+      "name": "Litauisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 46,
+    "fields": {
+      "name": "Amharisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 47,
+    "fields": {
+      "name": "Norwegisch",
+      "is_active": true
+    }
+  },
+  {
+    "model": "program.language",
+    "pk": 48,
+    "fields": {
+      "name": "Koreanisch",
+      "is_active": true
+    }
+  }
+]
diff --git a/fixtures/program/musicfocus.json b/fixtures/program/musicfocus.json
new file mode 100644
index 0000000000000000000000000000000000000000..d301e40375071864ea6b212586e22cabe55512cc
--- /dev/null
+++ b/fixtures/program/musicfocus.json
@@ -0,0 +1,132 @@
+[
+  {
+    "model": "program.musicfocus",
+    "pk": 1,
+    "fields": {
+      "focus": "Jazz",
+      "abbrev": "J",
+      "slug": "jazz",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 2,
+    "fields": {
+      "focus": "Volksmusik/Folk",
+      "abbrev": "V",
+      "slug": "volksmusik-folk",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 3,
+    "fields": {
+      "focus": "Experimentelle Musik",
+      "abbrev": "Ex",
+      "slug": "expermentelle-musik",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 4,
+    "fields": {
+      "focus": "Rock/Indie",
+      "abbrev": "R",
+      "slug": "rock-indie",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 5,
+    "fields": {
+      "focus": "Metal/Hardrock",
+      "abbrev": "M",
+      "slug": "metal-hardrock",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 6,
+    "fields": {
+      "focus": "Electronic",
+      "abbrev": "E",
+      "slug": "electronic",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 7,
+    "fields": {
+      "focus": "Klassik",
+      "abbrev": "K",
+      "slug": "klassik",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 8,
+    "fields": {
+      "focus": "Oldies",
+      "abbrev": "O",
+      "slug": "oldies",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 9,
+    "fields": {
+      "focus": "Reggae/Ska",
+      "abbrev": "Re",
+      "slug": "reggae-ska",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.musicfocus",
+    "pk": 10,
+    "fields": {
+      "focus": "Hiphop",
+      "abbrev": "H",
+      "slug": "hiphop",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  }
+]
diff --git a/fixtures/program/rrule.json b/fixtures/program/rrule.json
new file mode 100644
index 0000000000000000000000000000000000000000..7b4f0fdc8fa7224db482b9d139b3de1c73649903
--- /dev/null
+++ b/fixtures/program/rrule.json
@@ -0,0 +1,145 @@
+[
+  {
+    "model": "program.rrule",
+    "pk": 1,
+    "fields": {
+      "name": "einmalig",
+      "freq": 0,
+      "interval": 1,
+      "bysetpos": null,
+      "count": 1
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 2,
+    "fields": {
+      "name": "täglich",
+      "freq": 3,
+      "interval": 1,
+      "bysetpos": null,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 3,
+    "fields": {
+      "name": "werktäglich",
+      "freq": 3,
+      "interval": 1,
+      "bysetpos": null,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 4,
+    "fields": {
+      "name": "wöchentlich",
+      "freq": 2,
+      "interval": 1,
+      "bysetpos": null,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 5,
+    "fields": {
+      "name": "zweiwöchentlich",
+      "freq": 2,
+      "interval": 2,
+      "bysetpos": null,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 6,
+    "fields": {
+      "name": "vierwöchentlich",
+      "freq": 2,
+      "interval": 4,
+      "bysetpos": null,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 7,
+    "fields": {
+      "name": "gerade Kalenderwoche",
+      "freq": 2,
+      "interval": 1,
+      "bysetpos": null,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 8,
+    "fields": {
+      "name": "ungerade Kalenderwoche",
+      "freq": 2,
+      "interval": 1,
+      "bysetpos": null,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 9,
+    "fields": {
+      "name": "Jede 1. Woche im Monat",
+      "freq": 1,
+      "interval": 1,
+      "bysetpos": 1,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 10,
+    "fields": {
+      "name": "Jede 2. Woche im Monat",
+      "freq": 1,
+      "interval": 1,
+      "bysetpos": 2,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 11,
+    "fields": {
+      "name": "Jede 3. Woche im Monat",
+      "freq": 1,
+      "interval": 1,
+      "bysetpos": 3,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 12,
+    "fields": {
+      "name": "Jede 4. Woche im Monat",
+      "freq": 1,
+      "interval": 1,
+      "bysetpos": 4,
+      "count": null
+    }
+  },
+  {
+    "model": "program.rrule",
+    "pk": 13,
+    "fields": {
+      "name": "Jede 5. Woche im Monat",
+      "freq": 1,
+      "interval": 1,
+      "bysetpos": 5,
+      "count": null
+    }
+  }
+]
diff --git a/fixtures/program/show.json b/fixtures/program/show.json
new file mode 100644
index 0000000000000000000000000000000000000000..cb9c561c20d2b7d6a10d101b29bd8d24d649b595
--- /dev/null
+++ b/fixtures/program/show.json
@@ -0,0 +1,36 @@
+[
+  {
+    "model": "program.show",
+    "pk": 1,
+    "fields": {
+      "predecessor": null,
+      "type": 3,
+      "fundingcategory": 1,
+      "name": "Musikprogramm",
+      "slug": "musikprogramm",
+      "ppoi": "0.5x0.5",
+      "height": null,
+      "width": null,
+      "image": "",
+      "logo": "",
+      "short_description": "Unmoderiertes Musikprogramm",
+      "description": "Unmoderiertes Musikprogramm",
+      "email": "musikredaktion@helsinki.at",
+      "website": null,
+      "cba_series_id": null,
+      "default_id": null,
+      "created": "1969-12-31T22:00:00Z",
+      "last_updated": "1969-12-31T22:00:00Z",
+      "is_active": true,
+      "is_public": false,
+      "hosts": [
+        1
+      ],
+      "owners": [],
+      "language": [],
+      "category": [],
+      "topic": [],
+      "musicfocus": []
+    }
+  }
+]
diff --git a/fixtures/program/topic.json b/fixtures/program/topic.json
new file mode 100644
index 0000000000000000000000000000000000000000..93ce5e19a85ae2eca4fa1638211330efb375d25c
--- /dev/null
+++ b/fixtures/program/topic.json
@@ -0,0 +1,67 @@
+[
+  {
+    "model": "program.topic",
+    "pk": 1,
+    "fields": {
+      "topic": "Politik/Gesellschaft",
+      "abbrev": "P",
+      "slug": "politik-gesellschaft",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.topic",
+    "pk": 2,
+    "fields": {
+      "topic": "Natur/Klima/Tiere",
+      "abbrev": "N",
+      "slug": "natur-klima-tiere",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.topic",
+    "pk": 3,
+    "fields": {
+      "topic": "Kultur/Kunst",
+      "abbrev": "K",
+      "slug": "kultur-kunst",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.topic",
+    "pk": 4,
+    "fields": {
+      "topic": "Soziales",
+      "abbrev": "S",
+      "slug": "soziales",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  },
+  {
+    "model": "program.topic",
+    "pk": 5,
+    "fields": {
+      "topic": "Wissenschaft/Philosophie",
+      "abbrev": "W",
+      "slug": "wissenschaft-philosophie",
+      "is_active": true,
+      "button": "",
+      "button_hover": "",
+      "big_button": ""
+    }
+  }
+]
diff --git a/fixtures/program/type.json b/fixtures/program/type.json
new file mode 100644
index 0000000000000000000000000000000000000000..e7492c21c588c57b07bc7b2fc04f68447f6f050a
--- /dev/null
+++ b/fixtures/program/type.json
@@ -0,0 +1,79 @@
+[
+  {
+    "model": "program.type",
+    "pk": 1,
+    "fields": {
+      "type": "Talk",
+      "slug": "talk",
+      "is_active": true,
+      "color": "#ffffff",
+      "text_color": "#000000"
+    }
+  },
+  {
+    "model": "program.type",
+    "pk": 2,
+    "fields": {
+      "type": "Musiksendung",
+      "slug": "musiksendung",
+      "is_active": true,
+      "color": "#ffffff",
+      "text_color": "#000000"
+    }
+  },
+  {
+    "model": "program.type",
+    "pk": 3,
+    "fields": {
+      "type": "Unmoderiertes Musikprogramm",
+      "slug": "unmoderiertes-musikprogramm",
+      "is_active": true,
+      "color": "#ffffff",
+      "text_color": "#000000"
+    }
+  },
+  {
+    "model": "program.type",
+    "pk": 4,
+    "fields": {
+      "type": "Feature/Magazin",
+      "slug": "feature-magazin",
+      "is_active": true,
+      "color": "#ffffff",
+      "text_color": "#000000"
+    }
+  },
+  {
+    "model": "program.type",
+    "pk": 5,
+    "fields": {
+      "type": "Experimentell",
+      "slug": "experimentell",
+      "is_active": true,
+      "color": "#ffffff",
+      "text_color": "#000000"
+    }
+  },
+  {
+    "model": "program.type",
+    "pk": 6,
+    "fields": {
+      "type": "Hörspiel/Literatur",
+      "slug": "horspiel-literatur",
+      "is_active": true,
+      "color": "#ffffff",
+      "text_color": "#000000"
+    }
+  },
+  {
+    "model": "program.type",
+    "pk": 7,
+    "fields": {
+      "type": "Vortrag/Diskussion",
+      "slug": "vortrag-diskussion",
+      "is_active": true,
+      "color": "#ffffff",
+      "text_color": "#000000"
+    }
+  }
+]
diff --git a/frapp/urls.py b/frapp/urls.py
index f6b7814ef0938be9abf7c9a8d3bb6745b2ee0f53..96c24ba63ce35562d6ab8bd74540006f08929f54 100644
--- a/frapp/urls.py
+++ b/frapp/urls.py
@@ -1,8 +1,26 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2017-2018, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
 from django.conf.urls import url
+
 from .views import json_frapp
 
 urlpatterns = [
     url(r'^frapp/$', json_frapp),
-]
\ No newline at end of file
+]
diff --git a/frapp/views.py b/frapp/views.py
index ceda81a6c83c7f5234d5178588b5de573f372c51..178dc494b15b423f579f65a1146969eef134b7f4 100644
--- a/frapp/views.py
+++ b/frapp/views.py
@@ -1,14 +1,32 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2017-2018, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
 import json
 from datetime import date, datetime, time
 
-from django.db.models import Q
+from django.contrib.sites.shortcuts import get_current_site
 from django.core.exceptions import ObjectDoesNotExist
+from django.db.models import Q
 from django.http import HttpResponse
-from django.contrib.sites.shortcuts import get_current_site
+from django.utils.translation import ugettext_lazy as _
 
-from program.models import Note, Show, Category, TimeSlot, Host, Schedule
+from program.models import Note, Category, TimeSlot, Schedule
 
 
 def generate_frapp_broadcastinfos(schedule):
@@ -23,32 +41,33 @@ def generate_frapp_broadcastinfos(schedule):
     broadcasttime = schedule.tstart.strftime('%H:%M') + ' - ' + schedule.tend.strftime('%H:%M') + ' Uhr;'
     broadcastinfos = ''
 
-    if schedule.rrule_id == 1: # Once
-        broadcastinfos = 'Am ' + weekdays[schedule.byweekday] + ', ' + schedule.dstart.strftime('%d.%m.%Y') + ', ' + broadcasttime
-    if schedule.rrule_id == 2: # Daily
+    if schedule.rrule_id == 1:  # Once
+        broadcastinfos = 'Am ' + weekdays[schedule.byweekday] + ', ' + schedule.dstart.strftime(
+            '%d.%m.%Y') + ', ' + broadcasttime
+    if schedule.rrule_id == 2:  # Daily
         broadcastinfos = 'täglich, ' + broadcasttime
-    if schedule.rrule_id == 3: # Business days
+    if schedule.rrule_id == 3:  # Business days
         broadcastinfos = 'werktags, ' + broadcasttime
-    if schedule.rrule_id == 4: # Weekly
+    if schedule.rrule_id == 4:  # Weekly
         broadcastinfos = 'Jeden ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
-    if schedule.rrule_id == 5: # Bi-weekly
+    if schedule.rrule_id == 5:  # Bi-weekly
         print("Not supported by FRAPP yet")
-    if schedule.rrule_id == 6: # Every four weeks
+    if schedule.rrule_id == 6:  # Every four weeks
         print("Not supported by FRAPP yet")
-    if schedule.rrule_id == 7: # Even calendar weeks
-       broadcastinfos = 'Jeden geraden ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
-    if schedule.rrule_id == 8: # Odd calendar weeks
-       broadcastinfos = 'Jeden ungeraden ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
-    if schedule.rrule_id == 9: # Every 1st week
-       broadcastinfos = 'Jeden 1. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
-    if schedule.rrule_id == 10: # Every 2nd week
-       broadcastinfos = 'Jeden 2. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
-    if schedule.rrule_id == 11: # Every 3rd week
-       broadcastinfos = 'Jeden 3. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
-    if schedule.rrule_id == 12: # Every 4th week
-       broadcastinfos = 'Jeden 4. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
-    if schedule.rrule_id == 13: # Every 5th week
-       broadcastinfos = 'Jeden 5. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
+    if schedule.rrule_id == 7:  # Even calendar weeks
+        broadcastinfos = 'Jeden geraden ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
+    if schedule.rrule_id == 8:  # Odd calendar weeks
+        broadcastinfos = 'Jeden ungeraden ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
+    if schedule.rrule_id == 9:  # Every 1st week
+        broadcastinfos = 'Jeden 1. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
+    if schedule.rrule_id == 10:  # Every 2nd week
+        broadcastinfos = 'Jeden 2. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
+    if schedule.rrule_id == 11:  # Every 3rd week
+        broadcastinfos = 'Jeden 3. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
+    if schedule.rrule_id == 12:  # Every 4th week
+        broadcastinfos = 'Jeden 4. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
+    if schedule.rrule_id == 13:  # Every 5th week
+        broadcastinfos = 'Jeden 5. ' + weekdays[schedule.byweekday] + ', ' + broadcasttime
 
     return broadcastinfos
 
@@ -62,19 +81,18 @@ def json_frapp(request):
         - series: A list of shows for the given date
         - shows: A list of timeslots for the given date including notes
     """
-    from pv.settings import MEDIA_URL
+    from steering.settings import MEDIA_URL
 
-    if request.GET.get('date') == None:
+    if request.GET.get('date') is None:
         start = datetime.combine(date.today(), time(0, 0))
     else:
-        start = datetime.combine( datetime.strptime(request.GET.get('date'), '%Y-%m-%d').date(), time(0, 0))
+        start = datetime.combine(datetime.strptime(request.GET.get('date'), '%Y-%m-%d').date(), time(0, 0))
 
     end = datetime.combine(start, time(23, 59))
 
-    timeslots = TimeSlot.objects.filter(start__gte=start,start__lte=end).select_related('show').order_by('start')
+    timeslots = TimeSlot.objects.filter(start__gte=start, start__lte=end).select_related('show').order_by('start')
 
-
-    '''Generate categories object for output'''
+    # Generate categories object for output
 
     categories = Category.objects.all()
     categories_output = []
@@ -94,34 +112,30 @@ def json_frapp(request):
     for ts in timeslots:
         series.add(ts.show)
 
-
-    '''Generate series object for output'''
+    # Generate series object for output
 
     series_output = []
 
     for s in series:
-        metainfos = []
-        metainfos.append({ 'key': 'ProduzentIn', 'value': ', '.join(ts.show.hosts.values_list('name', flat=True)) })
-        metainfos.append({ 'key': 'E-Mail', 'value': ', '.join(ts.show.hosts.values_list('email', flat=True)) })
+        metainfos = [{'key': 'ProduzentIn', 'value': ', '.join(ts.show.hosts.values_list('name', flat=True))},
+                     {'key': 'E-Mail', 'value': ', '.join(ts.show.hosts.values_list('email', flat=True))}]
 
-        image = '' if s.image.name == None or s.image.name == '' else str(get_current_site(request)) + MEDIA_URL + s.image.name
-        url = '' if s.website == None or s.website == '' else s.website
+        image = '' if s.image.name is None or s.image.name == '' else str(get_current_site(request)) + MEDIA_URL + s.image.name
+        url = '' if s.website is None or s.website == '' else s.website
 
         # Get active schedules for the given date
         # But include upcoming single timeslots (with rrule_id=1)
-        schedules = Schedule.objects.filter( Q(show=s.id,is_repetition=False) &
-                                             (
-                                               Q(rrule_id__gt=1,dstart__lte=start,until__gte=start) |
-                                               Q(rrule_id=1,dstart__gte=start)
-                                             )
-                                           )
-
-        schedules_repetition = Schedule.objects.filter( Q(show=s.id,is_repetition=True) &
-                                             (
-                                               Q(rrule_id__gt=1,dstart__lte=start,until__gte=start) |
-                                               Q(rrule_id=1,dstart__gte=start)
-                                             )
-                                           )
+        schedules = Schedule.objects.filter(Q(show=s.id, is_repetition=False) &
+                                            (
+                                                    Q(rrule_id__gt=1, dstart__lte=start, until__gte=start) |
+                                                    Q(rrule_id=1, dstart__gte=start)
+                                            ))
+
+        schedules_repetition = Schedule.objects.filter(Q(show=s.id, is_repetition=True) &
+                                                       (
+                                                               Q(rrule_id__gt=1, dstart__lte=start, until__gte=start) |
+                                                               Q(rrule_id=1, dstart__gte=start)
+                                                       ))
 
         broadcastinfos = ''
 
@@ -150,14 +164,13 @@ def json_frapp(request):
 
         series_output.append(s_entry)
 
-
-    '''Generate shows object for output'''
+    # Generate shows object for output
 
     shows_output = []
 
     for ts in timeslots:
 
-        is_repetition = ' ' + _('REP') if ts.schedule.is_repetition is 1 else ''
+        is_repetition = ' ' + _('REP') if ts.schedule.is_repetition == 1 else ''
         namedisplay = ts.show.name + is_repetition
         description = ts.show.description
         url = str(get_current_site(request)) + '/shows/' + ts.show.slug
@@ -186,10 +199,7 @@ def json_frapp(request):
 
         shows_output.append(ts_entry)
 
-    output = {}
-    output['categories'] = categories_output
-    output['series'] = series_output
-    output['shows'] = shows_output
+    output = {'categories': categories_output, 'series': series_output, 'shows': shows_output}
 
     return HttpResponse(json.dumps(output, ensure_ascii=False).encode('utf8'),
-                        content_type="application/json; charset=utf-8")
\ No newline at end of file
+                        content_type="application/json; charset=utf-8")
diff --git a/manage.py b/manage.py
index 3c5acb083e042e5d9db5abe4140450c0d5842ed0..37038e2a1d4bb3d0135d4a4154628a61e21822c2 100755
--- a/manage.py
+++ b/manage.py
@@ -5,8 +5,8 @@ import os
 import sys
 
 if __name__ == "__main__":
-    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pv.settings")
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "steering.settings")
 
     from django.core.management import execute_from_command_line
 
-    execute_from_command_line(sys.argv)
\ No newline at end of file
+    execute_from_command_line(sys.argv)
diff --git a/manage.sh b/manage.sh
index 3ab4863692d4880f6e2f1302d824dc5726e27782..7eeaff675cfdc138e1e2c14ab40a8e4ded535093 100755
--- a/manage.sh
+++ b/manage.sh
@@ -1,4 +1,4 @@
 #!/bin/bash
 BASE_D=$(realpath "${BASH_SOURCE%/*}/")
 
-exec sudo docker run --rm -it -u $UID:$GID -p 127.0.0.1:8000:8000 -v "$BASE_D":/srv aura/pv /srv/manage.py $@
+exec sudo docker run --rm -it -u $UID:$GID -p 127.0.0.1:8000:8000 -v "$BASE_D":/srv steering-django /srv/manage.py $@
diff --git a/nop/dbrouter.py b/nop/dbrouter.py
deleted file mode 100644
index 99a42d98fad86c270bfd8b871da1c3697fe1e630..0000000000000000000000000000000000000000
--- a/nop/dbrouter.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- coding: utf-8 -*-
-
-class NopRouter(object):
-    def allow_migrate(self, db, app_label, model_name=None, **hints):
-        if app_label == 'nop':
-            return db == 'nop'
-        return None
\ No newline at end of file
diff --git a/nop/migrations/0001_initial.py b/nop/migrations/0001_initial.py
deleted file mode 100644
index 0285517d2c03fe952c9d40f706b4156089470f4c..0000000000000000000000000000000000000000
--- a/nop/migrations/0001_initial.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-import nop.models
-
-
-class Migration(migrations.Migration):
-
-    app_label = 'nop'
-
-    dependencies = [
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='Master',
-            fields=[
-                ('timestamp', models.BigIntegerField(serialize=False, primary_key=True)),
-                ('cart', models.IntegerField()),
-                ('len', models.IntegerField(null=True, blank=True)),
-                ('showtitle', models.CharField(max_length=765, blank=True)),
-                ('title', models.CharField(max_length=765, blank=True)),
-                ('artist', models.CharField(max_length=765, blank=True)),
-                ('album', models.CharField(max_length=765, blank=True)),
-                ('carttype', nop.models.CartTypeField(max_length=64, blank=True)),
-            ],
-            options={
-                'ordering': ['-timestamp'],
-                'db_table': 'master',
-            },
-        ),
-        migrations.CreateModel(
-            name='Standby',
-            fields=[
-                ('timestamp', models.BigIntegerField(serialize=False, primary_key=True)),
-                ('cart', models.IntegerField()),
-                ('len', models.IntegerField(null=True, blank=True)),
-                ('showtitle', models.CharField(max_length=765, blank=True)),
-                ('title', models.CharField(max_length=765, blank=True)),
-                ('artist', models.CharField(max_length=765, blank=True)),
-                ('album', models.CharField(max_length=765, blank=True)),
-                ('carttype', nop.models.CartTypeField(max_length=64, blank=True)),
-            ],
-            options={
-                'ordering': ['-timestamp'],
-                'db_table': 'standby',
-            },
-        ),
-        migrations.CreateModel(
-            name='State',
-            fields=[
-                ('timestamp', models.BigIntegerField(serialize=False, primary_key=True)),
-                ('state', models.CharField(max_length=96, blank=True)),
-            ],
-            options={
-                'ordering': ['-timestamp'],
-                'db_table': 'state',
-            },
-        ),
-    ]
diff --git a/nop/migrations/__init__.py b/nop/migrations/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/nop/models.py b/nop/models.py
deleted file mode 100644
index 16c09dff0e23160566154bc4ff406e8a6cd47e7a..0000000000000000000000000000000000000000
--- a/nop/models.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from django.db import models
-
-class CartTypeField(models.Field):
-    def __init__(self, *args, **kwargs):
-        self.types = [('show', 'Show'),
-                      ('pool', 'Musicpool'),
-                      ('jingle', 'Jingle'),
-                     ]
-        super(CartTypeField, self).__init__(*args, **kwargs)
-
-    def db_type(self, connection):
-        return "ENUM({})".format(','.join("'{}'".format(col)
-                                          for col, _ in self.types))
-
-class Master(models.Model):
-    timestamp = models.BigIntegerField(primary_key=True)
-    cart = models.IntegerField()
-    len = models.IntegerField(null=True, blank=True)
-    showtitle = models.CharField(max_length=765, blank=True)
-    title = models.CharField(max_length=765, blank=True)
-    artist = models.CharField(max_length=765, blank=True)
-    album = models.CharField(max_length=765, blank=True)
-    carttype = CartTypeField(max_length=64, blank=True)
-
-    class Meta:
-        db_table = 'master'
-        ordering = ['-timestamp']
-
-
-class Standby(models.Model):
-    timestamp = models.BigIntegerField(primary_key=True)
-    cart = models.IntegerField()
-    len = models.IntegerField(null=True, blank=True)
-    showtitle = models.CharField(max_length=765, blank=True)
-    title = models.CharField(max_length=765, blank=True)
-    artist = models.CharField(max_length=765, blank=True)
-    album = models.CharField(max_length=765, blank=True)
-    carttype = CartTypeField(max_length=64, blank=True)
-
-    class Meta:
-        db_table = 'standby'
-        ordering = ['-timestamp']
-
-
-class State(models.Model):
-    timestamp = models.BigIntegerField(primary_key=True)
-    state = models.CharField(max_length=96, blank=True)
-
-    class Meta:
-        db_table = 'state'
-        ordering = ['-timestamp']
\ No newline at end of file
diff --git a/nop/site_media/anytimec.css b/nop/site_media/anytimec.css
deleted file mode 100644
index 2281aec4b12ae8f892e9734183797d908f5e05de..0000000000000000000000000000000000000000
--- a/nop/site_media/anytimec.css
+++ /dev/null
@@ -1,56 +0,0 @@
-/* anytimec.css 4.1112H (anytime.css 4.1112H)
-Copyright 2008-2010 Andrew M. Andrews III (www.AMA3.com). Some Rights
-Reserved. This work licensed under the Creative Commons Attribution-
-Noncommercial-Share Alike 3.0 Unported License except in jurisdicitons
-for which the license has been ported by Creative Commons International,
-where the work is licensed under the applicable ported license instead.
-For a copy of the unported license, visit
-http://creativecommons.org/licenses/by-nc-sa/3.0/
-or send a letter to Creative Commons, 171 Second Street, Suite 300,
-San Francisco, California, 94105, USA.  For ported versions of the
-license, visit http://creativecommons.org/international/
-Any+Time is a trademark of Andrew M. Andrews III. */
-.AnyTime-pkr * {border:0;font: inherit;font-size: x-small;font-style:normal;font-weight:normal;list-style-type:none;margin:0;padding:0;white-space: nowrap}
-div.AnyTime-win {background-color:#F0F0F1;border:3px solid #C0C0C0;font:normal normal normal xx-small/normal sans-serif;padding-bottom:0.2em;-moz-border-radius:6px;-webkit-border-radius:6px}
-.AnyTime-pkr .AnyTime-cloak {background-color:#D7D7D7;opacity:0.7;filter:alpha(opacity=70)}
-.AnyTime-pkr .AnyTime-hdr {background-color:#D0D0D1;color:#606062;font-family:Arial,Helvetica,sans-serif;font-size:medium;font-weight:normal;height:1em;margin:0;padding:0 0 0.4em 0;text-align:center;-moz-border-radius:2px;-webkit-border-radius:2px}
-.AnyTime-pkr .AnyTime-x-btn {background-color:#FCFCFF;border:1px solid #F99;color:#FF9F9F;cursor:default;float:right;margin:0.3em;text-align:center;width:1.5em;-moz-border-radius:0.4em;-webkit-border-radius:0.4em}
-.AnyTime-pkr .AnyTime-btn {background-color:#FCFCFE;border:1px solid #999;color:#606062;cursor:default;float:left;font-family:Arial,Helvetica,sans-serif;height:1.5em;margin-bottom:1px;margin-right:1px;padding-top:0.1em;-moz-border-radius:0.4em;-webkit-border-radius:0.4em}
-.AnyTime-pkr .AnyTime-body {padding:0.5em}
-.AnyTime-pkr .AnyTime-date {float:left;padding:0 0.5em}
-.AnyTime-pkr .AnyTime-lbl {clear:left;color:#606063;font-family:Arial,Helvetica,sans-serif;font-size:100%;font-weight:normal;font-style:normal;height:1.3em;margin:0;padding:0;text-align:center}
-.AnyTime-pkr .AnyTime-yrs {height:2.6em;text-align:center;width:18.6em}
-.AnyTime-pkr .AnyTime-yrs-past-btn {width:2.7em}
-.AnyTime-pkr .AnyTime-yr-prior-btn, .AnyTime-pkr .AnyTime-yr-cur-btn, .AnyTime-pkr .AnyTime-yr-next-btn {width:3.75em}
-.AnyTime-pkr .AnyTime-yrs-ahead-btn {width:2.7em}
-.AnyTime-pkr .AnyTime-mons {height:4.8em;text-align:center;width:18.8em}
-.AnyTime-pkr .AnyTime-mon-btn {width:2.75em}
-.AnyTime-pkr .AnyTime-mon7-btn {clear:left}
-.AnyTime-pkr .AnyTime-dom-table {background-color:#F0F0F1;border:1px solid #E3E3E4;border-spacing:1px;width:18.6em}
-.AnyTime-pkr th.AnyTime-dow {background-color:#C0C0C1;color:white;font-family:Arial,Helvetica,sans-serif;font-size:95%;font-weight:normal;font-style:normal}
-.AnyTime-pkr .AnyTime-dom-btn {float:none;height:1.7em;text-align:right;padding:0 0.5em 0 0}
-.AnyTime-pkr .AnyTime-dom-btn-empty {background-color:#F3F3F4;border:1px solid #C0C0c1}
-.AnyTime-pkr .AnyTime-time {float:left;padding:0 0 0 1em;text-align:center}
-.AnyTime-pkr .AnyTime-hrs {float:left;padding-left:0.5em;padding-right:0.5em;text-align:center;width:7.2em}
-.AnyTime-pkr .AnyTime-hrs-am, .AnyTime-pkr .AnyTime-hrs-pm {float:left;width:3.6em}
-.AnyTime-pkr .AnyTime-hr-btn {text-align:right;padding-right:0.25em;width:3em; }
-.AnyTime-pkr .AnyTime-mins {float:left;padding-left:0.5em;padding-right:0.5em;text-align:center;width:4.7em}
-.AnyTime-pkr .AnyTime-mins-tens, .AnyTime-pkr .AnyTime-mins-ones {float:left;width:2.3em}
-.AnyTime-pkr .AnyTime-min-ten-btn, .AnyTime-pkr .AnyTime-min-one-btn {float:left;text-align:center;width:2em}
-.AnyTime-pkr .AnyTime-min-ten-btn-empty, .AnyTime-pkr .AnyTime-min-one-btn-empty {background-color:#F3F3F4;border:1px solid #C0C0c1}
-.AnyTime-pkr .AnyTime-secs {float:left;padding-left:0.5em;padding-right:0.5em;text-align:center;width:4.7em}
-.AnyTime-pkr .AnyTime-secs-tens, .AnyTime-pkr .AnyTime-secs-ones {float:left;width:2.3em}
-.AnyTime-pkr .AnyTime-sec-ten-btn, .AnyTime-pkr .AnyTime-sec-one-btn {float:left;text-align:center;width:2em}
-.AnyTime-pkr .AnyTime-sec-ten-btn-empty, .AnyTime-pkr .AnyTime-sec-one-btn-empty {background-color:#F3F3F4;border:1px solid #C0C0c1}
-.AnyTime-pkr .AnyTime-offs {clear:left;float:left;padding-left:0.5em;padding-top:0.5em;text-align:center}
-.AnyTime-pkr .AnyTime-off-select-btn {width:1.5em}
-.AnyTime-pkr .AnyTime-body-yr-selector {padding:1em;    }
-.AnyTime-pkr .AnyTime-yr-mil, .AnyTime-pkr .AnyTime-yr-cent, .AnyTime-pkr .AnyTime-yr-dec, .AnyTime-pkr .AnyTime-yr-yr {float:left;width:2.5em}
-.AnyTime-pkr .AnyTime-mil-btn, .AnyTime-pkr .AnyTime-cent-btn, .AnyTime-pkr .AnyTime-dec-btn, .AnyTime-pkr .AnyTime-yr-btn {float:left;text-align:center;width:2em}
-.AnyTime-pkr .AnyTime-yr-era {float:left;padding-left:1em;width:4.1em}
-.AnyTime-pkr .AnyTime-era-btn {text-align:center;width:3em}
-.AnyTime-pkr .AnyTime-body-off-selector {margin:0.5em; }
-.AnyTime-pkr .AnyTime-off-off-btn {clear:left;padding-left:1em;padding-right:1em;text-align:left}
-.AnyTime-pkr .AnyTime-cur-btn {border:1px solid #333334;background-color:#C0C0C1;color:#FCFCFE;font-weight:bold}
-.AnyTime-pkr .AnyTime-out-btn {background-color:#F0F0F1;border:1px solid #C0C0c1}
-.AnyTime-pkr .AnyTime-focus-btn {border:1px dashed black}
diff --git a/nop/site_media/anytimec.js b/nop/site_media/anytimec.js
deleted file mode 100644
index 8229476b569d272034cef8a2df33040d08ad33f5..0000000000000000000000000000000000000000
--- a/nop/site_media/anytimec.js
+++ /dev/null
@@ -1,789 +0,0 @@
-/* anytimec.js 4.1112H (anytime.js 4.1112H)
-Copyright 2008-2010 Andrew M. Andrews III (www.AMA3.com). Some Rights
-Reserved. This work licensed under the Creative Commons Attribution-
-Noncommercial-Share Alike 3.0 Unported License except in jurisdicitons
-for which the license has been ported by Creative Commons International,
-where the work is licensed under the applicable ported license instead.
-For a copy of the unported license, visit
-http://creativecommons.org/licenses/by-nc-sa/3.0/
-or send a letter to Creative Commons, 171 Second Street, Suite 300,
-San Francisco, California, 94105, USA.  For ported versions of the
-license, visit http://creativecommons.org/international/
-Any+Time is a trademark of Andrew M. Andrews III. */
-var AnyTime={pad:function(val,len)
-{var str=String(Math.abs(val));while(str.length<len)
-str='0'+str;if(val<0)
-str='-'+str;return str;}};(function($)
-{var __oneDay=(24*60*60*1000);var __daysIn=[31,28,31,30,31,30,31,31,30,31,30,31];var __iframe=null;var __initialized=false;var __msie6=(navigator.userAgent.indexOf('MSIE 6')>0);var __msie7=(navigator.userAgent.indexOf('MSIE 7')>0);var __pickers=[];jQuery.prototype.AnyTime_picker=function(options)
-{return this.each(function(i){AnyTime.picker(this.id,options);});}
-jQuery.prototype.AnyTime_noPicker=function()
-{return this.each(function(i){AnyTime.noPicker(this.id);});}
-jQuery.prototype.AnyTime_height=function(inclusive)
-{return(__msie6?Number(this.css('height').replace(/[^0-9]/g,'')):this.outerHeight(inclusive));};jQuery.prototype.AnyTime_width=function(inclusive)
-{return(__msie6?(1+Number(this.css('width').replace(/[^0-9]/g,''))):this.outerWidth(inclusive));};jQuery.prototype.AnyTime_current=function(isCurrent,isLegal)
-{if(isCurrent)
-{this.removeClass('AnyTime-out-btn ui-state-default ui-state-disabled ui-state-highlight');this.addClass('AnyTime-cur-btn ui-state-default ui-state-highlight');}
-else
-{this.removeClass('AnyTime-cur-btn ui-state-highlight');if(!isLegal)
-this.addClass('AnyTime-out-btn ui-state-disabled');else
-this.removeClass('AnyTime-out-btn ui-state-disabled');}};jQuery.prototype.AnyTime_clickCurrent=function()
-{this.find('.AnyTime-cur-btn').triggerHandler('click');}
-$(document).ready(function()
-{if(__msie6)
-{__iframe=$('<iframe frameborder="0" scrolling="no"></iframe>');__iframe.src="javascript:'<html></html>';";$(__iframe).css({display:'block',height:'1px',left:'0',top:'0',width:'1px',zIndex:0});$(document.body).append(__iframe);}
-for(var id in __pickers)
-if(!Array.prototype[id])
-__pickers[id].onReady();__initialized=true;});AnyTime.Converter=function(options)
-{var _flen=0;var _longDay=9;var _longMon=9;var _shortDay=6;var _shortMon=3;var _offAl=Number.MIN_VALUE;var _offCap=Number.MIN_VALUE;var _offF=Number.MIN_VALUE;var _offFSI=(-1);var _offP=Number.MIN_VALUE;var _offPSI=(-1);var _captureOffset=false;this.fmt='%Y-%m-%d %T';this.dAbbr=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];this.dNames=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];this.eAbbr=['BCE','CE'];this.mAbbr=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];this.mNames=['January','February','March','April','May','June','July','August','September','October','November','December'];this.baseYear=null;this.dAt=function(str,pos)
-{return((str.charCodeAt(pos)>='0'.charCodeAt(0))&&(str.charCodeAt(pos)<='9'.charCodeAt(0)));};this.format=function(date)
-{var d=new Date(date.getTime());if((_offAl==Number.MIN_VALUE)&&(_offF!=Number.MIN_VALUE))
-d.setTime((d.getTime()+(d.getTimezoneOffset()*60000))+(_offF*60000));var t;var str='';for(var f=0;f<_flen;f++)
-{if(this.fmt.charAt(f)!='%')
-str+=this.fmt.charAt(f);else
-{var ch=this.fmt.charAt(f+1)
-switch(ch)
-{case'a':str+=this.dAbbr[d.getDay()];break;case'B':if(d.getFullYear()<0)
-str+=this.eAbbr[0];break;case'b':str+=this.mAbbr[d.getMonth()];break;case'C':if(d.getFullYear()>0)
-str+=this.eAbbr[1];break;case'c':str+=d.getMonth()+1;break;case'd':t=d.getDate();if(t<10)str+='0';str+=String(t);break;case'D':t=String(d.getDate());str+=t;if((t.length==2)&&(t.charAt(0)=='1'))
-str+='th';else
-{switch(t.charAt(t.length-1))
-{case'1':str+='st';break;case'2':str+='nd';break;case'3':str+='rd';break;default:str+='th';break;}}
-break;case'E':str+=this.eAbbr[(d.getFullYear()<0)?0:1];break;case'e':str+=d.getDate();break;case'H':t=d.getHours();if(t<10)str+='0';str+=String(t);break;case'h':case'I':t=d.getHours()%12;if(t==0)
-str+='12';else
-{if(t<10)str+='0';str+=String(t);}
-break;case'i':t=d.getMinutes();if(t<10)str+='0';str+=String(t);break;case'k':str+=d.getHours();break;case'l':t=d.getHours()%12;if(t==0)
-str+='12';else
-str+=String(t);break;case'M':str+=this.mNames[d.getMonth()];break;case'm':t=d.getMonth()+1;if(t<10)str+='0';str+=String(t);break;case'p':str+=((d.getHours()<12)?'AM':'PM');break;case'r':t=d.getHours()%12;if(t==0)
-str+='12:';else
-{if(t<10)str+='0';str+=String(t)+':';}
-t=d.getMinutes();if(t<10)str+='0';str+=String(t)+':';t=d.getSeconds();if(t<10)str+='0';str+=String(t);str+=((d.getHours()<12)?'AM':'PM');break;case'S':case's':t=d.getSeconds();if(t<10)str+='0';str+=String(t);break;case'T':t=d.getHours();if(t<10)str+='0';str+=String(t)+':';t=d.getMinutes();if(t<10)str+='0';str+=String(t)+':';t=d.getSeconds();if(t<10)str+='0';str+=String(t);break;case'W':str+=this.dNames[d.getDay()];break;case'w':str+=d.getDay();break;case'Y':str+=AnyTime.pad(d.getFullYear(),4);break;case'y':t=d.getFullYear()%100;str+=AnyTime.pad(t,2);break;case'Z':str+=AnyTime.pad(Math.abs(d.getFullYear()),4);break;case'z':str+=Math.abs(d.getFullYear());break;case'%':str+='%';break;case'#':t=(_offAl!=Number.MIN_VALUE)?_offAl:(_offF==Number.MIN_VALUE)?(0-d.getTimezoneOffset()):_offF;if(t>=0)
-str+='+';str+=t;break;case'@':t=(_offAl!=Number.MIN_VALUE)?_offAl:(_offF==Number.MIN_VALUE)?(0-d.getTimezoneOffset()):_offF;if(AnyTime.utcLabel&&AnyTime.utcLabel[t])
-{if((_offFSI>0)&&(_offFSI<AnyTime.utcLabel[t].length))
-str+=AnyTime.utcLabel[t][_offFSI];else
-str+=AnyTime.utcLabel[t][0];break;}
-str+='UTC';ch=':';case'+':case'-':case':':case';':t=(_offAl!=Number.MIN_VALUE)?_offAl:(_offF==Number.MIN_VALUE)?(0-d.getTimezoneOffset()):_offF;if(t<0)
-str+='-';else
-str+='+';t=Math.abs(t);str+=((ch=='+')||(ch==':'))?AnyTime.pad(Math.floor(t/60),2):Math.floor(t/60);if((ch==':')||(ch==';'))
-str+=':';str+=AnyTime.pad(t%60,2);break;case'f':case'j':case'U':case'u':case'V':case'v':case'X':case'x':throw'%'+ch+' not implemented by AnyTime.Converter';default:str+=this.fmt.substr(f,2);}
-f++;}}
-return str;};this.getUtcParseOffsetCaptured=function()
-{return _offCap;};this.getUtcParseOffsetSubIndex=function()
-{return _offPSI;};this.parse=function(str)
-{_offCap=_offP;_offPSI=(-1);var era=1;var time=new Date(4,0,1,0,0,0,0);var slen=str.length;var s=0;var tzSign=1,tzOff=_offP;var i,matched,sub,sublen,temp;for(var f=0;f<_flen;f++)
-{if(this.fmt.charAt(f)=='%')
-{var ch=this.fmt.charAt(f+1);switch(ch)
-{case'a':matched=false;for(sublen=0;s+sublen<slen;sublen++)
-{sub=str.substr(s,sublen);for(i=0;i<12;i++)
-if(this.dAbbr[i]==sub)
-{matched=true;s+=sublen;break;}
-if(matched)
-break;}
-if(!matched)
-throw'unknown weekday: '+str.substr(s);break;case'B':sublen=this.eAbbr[0].length;if((s+sublen<=slen)&&(str.substr(s,sublen)==this.eAbbr[0]))
-{era=(-1);s+=sublen;}
-break;case'b':matched=false;for(sublen=0;s+sublen<slen;sublen++)
-{sub=str.substr(s,sublen);for(i=0;i<12;i++)
-if(this.mAbbr[i]==sub)
-{time.setMonth(i);matched=true;s+=sublen;break;}
-if(matched)
-break;}
-if(!matched)
-throw'unknown month: '+str.substr(s);break;case'C':sublen=this.eAbbr[1].length;if((s+sublen<=slen)&&(str.substr(s,sublen)==this.eAbbr[1]))
-s+=sublen;break;case'c':if((s+1<slen)&&this.dAt(str,s+1))
-{time.setMonth((Number(str.substr(s,2))-1)%12);s+=2;}
-else
-{time.setMonth((Number(str.substr(s,1))-1)%12);s++;}
-break;case'D':if((s+1<slen)&&this.dAt(str,s+1))
-{time.setDate(Number(str.substr(s,2)));s+=4;}
-else
-{time.setDate(Number(str.substr(s,1)));s+=3;}
-break;case'd':time.setDate(Number(str.substr(s,2)));s+=2;break;case'E':sublen=this.eAbbr[0].length;if((s+sublen<=slen)&&(str.substr(s,sublen)==this.eAbbr[0]))
-{era=(-1);s+=sublen;}
-else if((s+(sublen=this.eAbbr[1].length)<=slen)&&(str.substr(s,sublen)==this.eAbbr[1]))
-s+=sublen;else
-throw'unknown era: '+str.substr(s);break;case'e':if((s+1<slen)&&this.dAt(str,s+1))
-{time.setDate(Number(str.substr(s,2)));s+=2;}
-else
-{time.setDate(Number(str.substr(s,1)));s++;}
-break;case'f':s+=6;break;case'H':time.setHours(Number(str.substr(s,2)));s+=2;break;case'h':case'I':time.setHours(Number(str.substr(s,2)));s+=2;break;case'i':time.setMinutes(Number(str.substr(s,2)));s+=2;break;case'k':if((s+1<slen)&&this.dAt(str,s+1))
-{time.setHours(Number(str.substr(s,2)));s+=2;}
-else
-{time.setHours(Number(str.substr(s,1)));s++;}
-break;case'l':if((s+1<slen)&&this.dAt(str,s+1))
-{time.setHours(Number(str.substr(s,2)));s+=2;}
-else
-{time.setHours(Number(str.substr(s,1)));s++;}
-break;case'M':matched=false;for(sublen=_shortMon;s+sublen<=slen;sublen++)
-{if(sublen>_longMon)
-break;sub=str.substr(s,sublen);for(i=0;i<12;i++)
-{if(this.mNames[i]==sub)
-{time.setMonth(i);matched=true;s+=sublen;break;}}
-if(matched)
-break;}
-break;case'm':time.setMonth((Number(str.substr(s,2))-1)%12);s+=2;break;case'p':if(time.getHours()==12)
-{if(str.charAt(s)=='A')
-time.setHours(0);}
-else if(str.charAt(s)=='P')
-time.setHours(time.getHours()+12);s+=2;break;case'r':time.setHours(Number(str.substr(s,2)));time.setMinutes(Number(str.substr(s+3,2)));time.setSeconds(Number(str.substr(s+6,2)));if(time.getHours()==12)
-{if(str.charAt(s)=='A')
-time.setHours(0);}
-else if(str.charAt(s)=='P')
-time.setHours(time.getHours()+12);s+=10;break;case'S':case's':time.setSeconds(Number(str.substr(s,2)));s+=2;break;case'T':time.setHours(Number(str.substr(s,2)));time.setMinutes(Number(str.substr(s+3,2)));time.setSeconds(Number(str.substr(s+6,2)));s+=8;break;case'W':matched=false;for(sublen=_shortDay;s+sublen<=slen;sublen++)
-{if(sublen>_longDay)
-break;sub=str.substr(s,sublen);for(i=0;i<7;i++)
-{if(this.dNames[i]==sub)
-{matched=true;s+=sublen;break;}}
-if(matched)
-break;}
-break;case'w':s+=1;break;case'Y':i=4;if(str.substr(s,1)=='-')
-i++;time.setFullYear(Number(str.substr(s,i)));s+=i;break;case'y':i=2;if(str.substr(s,1)=='-')
-i++;temp=Number(str.substr(s,i));if(typeof(this.baseYear)=='number')
-temp+=this.baseYear;else if(temp<70)
-temp+=2000;else
-temp+=1900;time.setFullYear(temp);s+=i;break;case'Z':time.setFullYear(Number(str.substr(s,4)));s+=4;break;case'z':i=0;while((s<slen)&&this.dAt(str,s))
-i=(i*10)+Number(str.charAt(s++));time.setFullYear(i);break;case'#':if(str.charAt(s++)=='-')
-tzSign=(-1);for(tzOff=0;(s<slen)&&(String(i=Number(str.charAt(s)))==str.charAt(s));s++)
-tzOff=(tzOff*10)+i;tzOff*=tzSign;break;case'@':_offPSI=(-1);if(AnyTime.utcLabel)
-{matched=false;for(tzOff in AnyTime.utcLabel)
-if(!Array.prototype[tzOff])
-{for(i=0;i<AnyTime.utcLabel[tzOff].length;i++)
-{sub=AnyTime.utcLabel[tzOff][i];sublen=sub.length;if((s+sublen<=slen)&&(str.substr(s,sublen)==sub))
-{s+=sublen;matched=true;break;}}
-if(matched)
-break;}
-if(matched)
-{_offPSI=i;tzOff=Number(tzOff);break;}}
-if((s+9<slen)||(str.substr(s,3)!="UTC"))
-throw'unknown time zone: '+str.substr(s);s+=3;ch=':';case'-':case'+':case':':case';':if(str.charAt(s++)=='-')
-tzSign=(-1);tzOff=Number(str.charAt(s));if((ch=='+')||(ch==':')||((s+3<slen)&&(String(Number(str.charAt(s+3)))!==str.charAt(s+3))))
-tzOff=(tzOff*10)+Number(str.charAt(++s));tzOff*=60;if((ch==':')||(ch==';'))
-s++;tzOff=(tzOff+Number(str.substr(++s,2)))*tzSign;s+=2;break;case'j':case'U':case'u':case'V':case'v':case'X':case'x':throw'%'+this.fmt.charAt(f+1)+' not implemented by AnyTime.Converter';case'%':default:throw'%'+this.fmt.charAt(f+1)+' reserved for future use';break;}
-f++;}
-else if(this.fmt.charAt(f)!=str.charAt(s))
-throw str+' is not in "'+this.fmt+'" format';else
-s++;}
-if(era<0)
-time.setFullYear(0-time.getFullYear());if(tzOff!=Number.MIN_VALUE)
-{if(_captureOffset)
-_offCap=tzOff;else
-time.setTime((time.getTime()-(tzOff*60000))-(time.getTimezoneOffset()*60000));}
-return time;};this.setUtcFormatOffsetAlleged=function(offset)
-{var prev=_offAl;_offAl=offset;return prev;};this.setUtcFormatOffsetSubIndex=function(subIndex)
-{var prev=_offFSI;_offFSI=subIndex;return prev;};(function(_this)
-{var i,len;options=jQuery.extend(true,{},options||{});if(options.baseYear)
-_this.baseYear=Number(options.baseYear);if(options.format)
-_this.fmt=options.format;_flen=_this.fmt.length;if(options.dayAbbreviations)
-_this.dAbbr=$.makeArray(options.dayAbbreviations);if(options.dayNames)
-{_this.dNames=$.makeArray(options.dayNames);_longDay=1;_shortDay=1000;for(i=0;i<7;i++)
-{len=_this.dNames[i].length;if(len>_longDay)
-_longDay=len;if(len<_shortDay)
-_shortDay=len;}}
-if(options.eraAbbreviations)
-_this.eAbbr=$.makeArray(options.eraAbbreviations);if(options.monthAbbreviations)
-_this.mAbbr=$.makeArray(options.monthAbbreviations);if(options.monthNames)
-{_this.mNames=$.makeArray(options.monthNames);_longMon=1;_shortMon=1000;for(i=0;i<12;i++)
-{len=_this.mNames[i].length;if(len>_longMon)
-_longMon=len;if(len<_shortMon)
-_shortMon=len;}}
-if(typeof options.utcFormatOffsetImposed!="undefined")
-_offF=options.utcFormatOffsetImposed;if(typeof options.utcParseOffsetAssumed!="undefined")
-_offP=options.utcParseOffsetAssumed;if(options.utcParseOffsetCapture)
-_captureOffset=true;})(this);};AnyTime.noPicker=function(id)
-{if(__pickers[id])
-{__pickers[id].cleanup();delete __pickers[id];}};AnyTime.picker=function(id,options)
-{if(__pickers[id])
-throw'Cannot create another AnyTime picker for "'+id+'"';var _this=null;__pickers[id]={twelveHr:false,ajaxOpts:null,denyTab:true,askEra:false,cloak:null,conv:null,bMinW:0,bMinH:0,dMinW:0,dMinH:0,div:null,dB:null,dD:null,dY:null,dMo:null,dDoM:null,hDoM:null,hMo:null,hTitle:null,hY:null,dT:null,dH:null,dM:null,dS:null,dO:null,earliest:null,fBtn:null,fDOW:0,hBlur:null,hClick:null,hFocus:null,hKeydown:null,hKeypress:null,id:null,inp:null,latest:null,lastAjax:null,lostFocus:false,lX:'X',lY:'Year',lO:'Time Zone',oBody:null,oConv:null,oCur:null,oDiv:null,oLab:null,oListMinW:0,oMinW:0,oSel:null,offMin:Number.MIN_VALUE,offSI:-1,offStr:"",pop:true,time:null,tMinW:0,tMinH:0,url:null,wMinW:0,wMinH:0,yAhead:null,y0XXX:null,yCur:null,yDiv:null,yLab:null,yNext:null,yPast:null,yPrior:null,initialize:function(id)
-{_this=this;this.id='AnyTime--'+id.replace(/[^-_.A-Za-z0-9]/g,'--AnyTime--');options=jQuery.extend(true,{},options||{});options.utcParseOffsetCapture=true;this.conv=new AnyTime.Converter(options);if(options.placement)
-{if(options.placement=='inline')
-this.pop=false;else if(options.placement!='popup')
-throw'unknown placement: '+options.placement;}
-if(options.ajaxOptions)
-{this.ajaxOpts=jQuery.extend({},options.ajaxOptions);if(!this.ajaxOpts.success)
-this.ajaxOpts.success=function(data,status){_this.inp.val(data);};}
-if(options.earliest)
-{if(typeof options.earliest.getTime=='function')
-this.earliest=options.earliest.getTime();else
-this.earliest=this.conv.parse(options.earliest.toString());}
-if(options.firstDOW)
-{if((options.firstDOW<0)||(options.firstDOW>6))
-throw new Exception('illegal firstDOW: '+options.firstDOW);this.fDOW=options.firstDOW;}
-if(options.latest)
-{if(typeof options.latest.getTime=='function')
-this.latest=options.latest.getTime();else
-this.latest=this.conv.parse(options.latest.toString());}
-this.lX=options.labelDismiss||'X';this.lY=options.labelYear||'Year';this.lO=options.labelTimeZone||'Time Zone';var i;var t;var lab;var shownFields=0;var format=this.conv.fmt;if(typeof options.askEra!='undefined')
-this.askEra=options.askEra;else
-this.askEra=(format.indexOf('%B')>=0)||(format.indexOf('%C')>=0)||(format.indexOf('%E')>=0);var askYear=(format.indexOf('%Y')>=0)||(format.indexOf('%y')>=0)||(format.indexOf('%Z')>=0)||(format.indexOf('%z')>=0);var askMonth=(format.indexOf('%b')>=0)||(format.indexOf('%c')>=0)||(format.indexOf('%M')>=0)||(format.indexOf('%m')>=0);var askDoM=(format.indexOf('%D')>=0)||(format.indexOf('%d')>=0)||(format.indexOf('%e')>=0);var askDate=askYear||askMonth||askDoM;this.twelveHr=(format.indexOf('%h')>=0)||(format.indexOf('%I')>=0)||(format.indexOf('%l')>=0)||(format.indexOf('%r')>=0);var askHour=this.twelveHr||(format.indexOf('%H')>=0)||(format.indexOf('%k')>=0)||(format.indexOf('%T')>=0);var askMinute=(format.indexOf('%i')>=0)||(format.indexOf('%r')>=0)||(format.indexOf('%T')>=0);var askSec=((format.indexOf('%r')>=0)||(format.indexOf('%S')>=0)||(format.indexOf('%s')>=0)||(format.indexOf('%T')>=0));if(askSec&&(typeof options.askSecond!='undefined'))
-askSec=options.askSecond;var askOff=((format.indexOf('%#')>=0)||(format.indexOf('%+')>=0)||(format.indexOf('%-')>=0)||(format.indexOf('%:')>=0)||(format.indexOf('%;')>=0)||(format.indexOf('%<')>=0)||(format.indexOf('%>')>=0)||(format.indexOf('%@')>=0));var askTime=askHour||askMinute||askSec||askOff;if(askOff)
-this.oConv=new AnyTime.Converter({format:options.formatUtcOffset||format.match(/\S*%[-+:;<>#@]\S*/g).join(' ')});this.inp=$(document.getElementById(id));this.div=$('<div class="AnyTime-win AnyTime-pkr ui-widget ui-widget-content ui-corner-all" style="width:0;height:0" id="'+this.id+'" aria-live="off"/>');this.inp.after(this.div);this.wMinW=this.div.outerWidth(!$.browser.safari);this.wMinH=this.div.AnyTime_height(true);this.hTitle=$('<h5 class="AnyTime-hdr ui-widget-header ui-corner-top"/>');this.div.append(this.hTitle);this.dB=$('<div class="AnyTime-body" style="width:0;height:0"/>');this.div.append(this.dB);this.bMinW=this.dB.outerWidth(true);this.bMinH=this.dB.AnyTime_height(true);if(options.hideInput)
-this.inp.css({border:0,height:'1px',margin:0,padding:0,width:'1px'});t=null;var xDiv=null;if(this.pop)
-{xDiv=$('<div class="AnyTime-x-btn ui-state-default">'+this.lX+'</div>');this.hTitle.append(xDiv);xDiv.click(function(e){_this.dismiss(e);});}
-lab='';if(askDate)
-{this.dD=$('<div class="AnyTime-date" style="width:0;height:0"/>');this.dB.append(this.dD);this.dMinW=this.dD.outerWidth(true);this.dMinH=this.dD.AnyTime_height(true);if(askYear)
-{this.yLab=$('<h6 class="AnyTime-lbl AnyTime-lbl-yr">'+this.lY+'</h6>');this.dD.append(this.yLab);this.dY=$('<ul class="AnyTime-yrs ui-helper-reset" />');this.dD.append(this.dY);this.yPast=this.btn(this.dY,'<',this.newYear,['yrs-past'],'- '+this.lY);this.yPrior=this.btn(this.dY,'1',this.newYear,['yr-prior'],'-1 '+this.lY);this.yCur=this.btn(this.dY,'2',this.newYear,['yr-cur'],this.lY);this.yCur.removeClass('ui-state-default');this.yCur.addClass('AnyTime-cur-btn ui-state-default ui-state-highlight');this.yNext=this.btn(this.dY,'3',this.newYear,['yr-next'],'+1 '+this.lY);this.yAhead=this.btn(this.dY,'>',this.newYear,['yrs-ahead'],'+ '+this.lY);shownFields++;}
-if(askMonth)
-{lab=options.labelMonth||'Month';this.hMo=$('<h6 class="AnyTime-lbl AnyTime-lbl-month">'+lab+'</h6>');this.dD.append(this.hMo);this.dMo=$('<ul class="AnyTime-mons" />');this.dD.append(this.dMo);for(i=0;i<12;i++)
-{var mBtn=this.btn(this.dMo,this.conv.mAbbr[i],function(event)
-{var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;var mo=event.target.AnyTime_month;var t=new Date(this.time.getTime());if(t.getDate()>__daysIn[mo])
-t.setDate(__daysIn[mo])
-t.setMonth(mo);this.set(t);this.upd(elem);},['mon','mon'+String(i+1)],lab+' '+this.conv.mNames[i]);mBtn[0].AnyTime_month=i;}
-shownFields++;}
-if(askDoM)
-{lab=options.labelDayOfMonth||'Day of Month';this.hDoM=$('<h6 class="AnyTime-lbl AnyTime-lbl-dom">'+lab+'</h6>');this.dD.append(this.hDoM);this.dDoM=$('<table border="0" cellpadding="0" cellspacing="0" class="AnyTime-dom-table"/>');this.dD.append(this.dDoM);t=$('<thead class="AnyTime-dom-head"/>');this.dDoM.append(t);var tr=$('<tr class="AnyTime-dow"/>');t.append(tr);for(i=0;i<7;i++)
-tr.append('<th class="AnyTime-dow AnyTime-dow'+String(i+1)+'">'+this.conv.dAbbr[(this.fDOW+i)%7]+'</th>');var tbody=$('<tbody class="AnyTime-dom-body" />');this.dDoM.append(tbody);for(var r=0;r<6;r++)
-{tr=$('<tr class="AnyTime-wk AnyTime-wk'+String(r+1)+'"/>');tbody.append(tr);for(i=0;i<7;i++)
-this.btn(tr,'x',function(event)
-{var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;var dom=Number(elem.html());if(dom)
-{var t=new Date(this.time.getTime());t.setDate(dom);this.set(t);this.upd(elem);}},['dom'],lab);}
-shownFields++;}}
-if(askTime)
-{var tensDiv,onesDiv;this.dT=$('<div class="AnyTime-time" style="width:0;height:0" />');this.dB.append(this.dT);this.tMinW=this.dT.outerWidth(true);this.tMinH=this.dT.AnyTime_height(true);if(askHour)
-{this.dH=$('<div class="AnyTime-hrs"/>');this.dT.append(this.dH);lab=options.labelHour||'Hour';this.dH.append($('<h6 class="AnyTime-lbl AnyTime-lbl-hr">'+lab+'</h6>'));var amDiv=$('<ul class="AnyTime-hrs-am"/>');this.dH.append(amDiv);var pmDiv=$('<ul class="AnyTime-hrs-pm"/>');this.dH.append(pmDiv);for(i=0;i<12;i++)
-{if(this.twelveHr)
-{if(i==0)
-t='12am';else
-t=String(i)+'am';}
-else
-t=AnyTime.pad(i,2);this.btn(amDiv,t,this.newHour,['hr','hr'+String(i)],lab+' '+t);if(this.twelveHr)
-{if(i==0)
-t='12pm';else
-t=String(i)+'pm';}
-else
-t=i+12;this.btn(pmDiv,t,this.newHour,['hr','hr'+String(i+12)],lab+' '+t);}
-shownFields++;}
-if(askMinute)
-{this.dM=$('<div class="AnyTime-mins"/>');this.dT.append(this.dM);lab=options.labelMinute||'Minute';this.dM.append($('<h6 class="AnyTime-lbl AnyTime-lbl-min">'+lab+'</h6>'));tensDiv=$('<ul class="AnyTime-mins-tens"/>');this.dM.append(tensDiv);for(i=0;i<6;i++)
-this.btn(tensDiv,i,function(event)
-{var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;var t=new Date(this.time.getTime());t.setMinutes((Number(elem.text())*10)+(this.time.getMinutes()%10));this.set(t);this.upd(elem);},['min-ten','min'+i+'0'],lab+' '+i+'0');for(;i<12;i++)
-this.btn(tensDiv,' ',$.noop,['min-ten','min'+i+'0'],lab+' '+i+'0').addClass('AnyTime-min-ten-btn-empty ui-state-default ui-state-disabled');onesDiv=$('<ul class="AnyTime-mins-ones"/>');this.dM.append(onesDiv);for(i=0;i<10;i++)
-this.btn(onesDiv,i,function(event)
-{var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;var t=new Date(this.time.getTime());t.setMinutes((Math.floor(this.time.getMinutes()/10)*10)+Number(elem.text()));this.set(t);this.upd(elem);},['min-one','min'+i],lab+' '+i);for(;i<12;i++)
-this.btn(onesDiv,' ',$.noop,['min-one','min'+i+'0'],lab+' '+i).addClass('AnyTime-min-one-btn-empty ui-state-default ui-state-disabled');shownFields++;}
-if(askSec)
-{this.dS=$('<div class="AnyTime-secs"/>');this.dT.append(this.dS);lab=options.labelSecond||'Second';this.dS.append($('<h6 class="AnyTime-lbl AnyTime-lbl-sec">'+lab+'</h6>'));tensDiv=$('<ul class="AnyTime-secs-tens"/>');this.dS.append(tensDiv);for(i=0;i<6;i++)
-this.btn(tensDiv,i,function(event)
-{var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;var t=new Date(this.time.getTime());t.setSeconds((Number(elem.text())*10)+(this.time.getSeconds()%10));this.set(t);this.upd(elem);},['sec-ten','sec'+i+'0'],lab+' '+i+'0');for(;i<12;i++)
-this.btn(tensDiv,' ',$.noop,['sec-ten','sec'+i+'0'],lab+' '+i+'0').addClass('AnyTime-sec-ten-btn-empty ui-state-default ui-state-disabled');onesDiv=$('<ul class="AnyTime-secs-ones"/>');this.dS.append(onesDiv);for(i=0;i<10;i++)
-this.btn(onesDiv,i,function(event)
-{var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;var t=new Date(this.time.getTime());t.setSeconds((Math.floor(this.time.getSeconds()/10)*10)+Number(elem.text()));this.set(t);this.upd(elem);},['sec-one','sec'+i],lab+' '+i);for(;i<12;i++)
-this.btn(onesDiv,' ',$.noop,['sec-one','sec'+i+'0'],lab+' '+i).addClass('AnyTime-sec-one-btn-empty ui-state-default ui-state-disabled');shownFields++;}
-if(askOff)
-{this.dO=$('<div class="AnyTime-offs" />');this.dT.append(this.dO);this.oMinW=this.dO.outerWidth(true);this.oLab=$('<h6 class="AnyTime-lbl AnyTime-lbl-off">'+this.lO+'</h6>');this.dO.append(this.oLab);var offDiv=$('<ul class="AnyTime-off-list ui-helper-reset" />');this.dO.append(offDiv);this.oCur=this.btn(offDiv,'',this.newOffset,['off','off-cur'],lab);this.oCur.removeClass('ui-state-default');this.oCur.addClass('AnyTime-cur-btn ui-state-default ui-state-highlight');this.oCur.css({overflow:"hidden"});this.oSel=this.btn(offDiv,'±',this.newOffset,['off','off-select'],'+/- '+this.lO);this.oListMinW=this.oCur.outerWidth(true)+this.oSel.outerWidth(true);shownFields++;}}
-if(options.labelTitle)
-this.hTitle.append(options.labelTitle);else if(shownFields>1)
-this.hTitle.append('Select a '+(askDate?(askTime?'Date and Time':'Date'):'Time'));else
-this.hTitle.append('Select');try
-{this.time=this.conv.parse(this.inp.val());this.offMin=this.conv.getUtcParseOffsetCaptured();this.offSI=this.conv.getUtcParseOffsetSubIndex();}
-catch(e)
-{this.time=new Date();}
-this.lastAjax=this.time;if(this.pop)
-{this.div.hide();if(__iframe)
-__iframe.hide();this.div.css('position','absolute');}
-this.inp.blur(this.hBlur=function(e)
-{_this.inpBlur(e);});this.inp.click(this.hClick=function(e)
-{_this.showPkr(e);});this.inp.focus(this.hFocus=function(e)
-{if(_this.lostFocus)
-_this.showPkr(e);_this.lostFocus=false;});this.inp.keydown(this.hKeydown=function(e)
-{_this.key(e);});this.inp.keypress(this.hKeypress=function(e)
-{if($.browser.opera&&_this.denyTab)
-e.preventDefault();});this.div.click(function(e)
-{_this.lostFocus=false;_this.inp.focus();});$(window).resize(function(e)
-{_this.pos(e);});if(__initialized)
-this.onReady();},ajax:function()
-{if(this.ajaxOpts&&(this.time.getTime()!=this.lastAjax.getTime()))
-{try
-{var opts=jQuery.extend({},this.ajaxOpts);if(typeof opts.data=='object')
-opts.data[this.inp[0].name||this.inp[0].id]=this.inp.val();else
-{var opt=(this.inp[0].name||this.inp[0].id)+'='+encodeURI(this.inp.val());if(opts.data)
-opts.data+='&'+opt;else
-opts.data=opt;}
-$.ajax(opts);this.lastAjax=this.time;}
-catch(e)
-{}}
-return;},askOffset:function(event)
-{if(!this.oDiv)
-{this.makeCloak();this.oDiv=$('<div class="AnyTime-win AnyTime-off-selector ui-widget ui-widget-content ui-corner-all" style="position:absolute" />');this.div.append(this.oDiv);var title=$('<h5 class="AnyTime-hdr AnyTime-hdr-off-selector ui-widget-header ui-corner-top" />');this.oDiv.append(title);this.oBody=$('<div class="AnyTime-body AnyTime-body-off-selector" style="overflow:auto;white-space:nowrap" />');this.oDiv.append(this.oBody);var oBHS=this.oBody.AnyTime_height(true);var oBWS=this.oBody.AnyTime_width(true);var oTWS=title.AnyTime_width(true);var xDiv=$('<div class="AnyTime-x-btn ui-state-default">'+this.lX+'</div>');title.append(xDiv);xDiv.click(function(e){_this.dismissODiv(e);});title.append(this.lO);if(__msie6||__msie7)
-title.width(String(this.lO.length*0.8)+"em");var oBW=title.AnyTime_width(true)-oBWS;var cont=$('<ul class="AnyTime-off-off" />');var last=null;this.oBody.append(cont);var useSubIndex=(this.oConv.fmt.indexOf('%@')>=0);var btnW=0;if(AnyTime.utcLabel)
-for(var o=-720;o<720;o++)
-if(AnyTime.utcLabel[o])
-{this.oConv.setUtcFormatOffsetAlleged(o);for(var i=0;i<AnyTime.utcLabel[o].length;i++)
-{this.oConv.setUtcFormatOffsetSubIndex(i);last=this.btn(cont,this.oConv.format(this.time),this.newOPos,['off-off'],o);last[0].AnyTime_offMin=o;last[0].AnyTime_offSI=i;var w=last.width();if(w>btnW)
-btnW=w;if(!useSubIndex)
-break;}}
-if(last)
-last.addClass('AnyTime-off-off-last-btn');this.oBody.find('.AnyTime-off-off-btn').width(btnW);if(last)
-{var lW=last.AnyTime_width(true);if(lW>oBW)
-oBW=lW+1;}
-this.oBody.width(oBW);oBW=this.oBody.AnyTime_width(true);this.oDiv.width(oBW);if(__msie6||__msie7)
-title.width(oBW-oTWS);var oH=this.oDiv.AnyTime_height(true);var oHmax=this.div.height()*0.75;if(oH>oHmax)
-{oH=oHmax;this.oBody.height(oH-(title.AnyTime_height(true)+oBHS));this.oBody.width(this.oBody.width()+20);this.oDiv.width(this.oDiv.width()+20);if(__msie6||__msie7)
-title.width(this.oBody.AnyTime_width(true)-oTWS);}
-if(!__msie7)
-this.oDiv.height(String(oH)+'px');}
-else
-{this.cloak.show();this.oDiv.show();}
-this.pos(event);this.updODiv(null);var f=this.oDiv.find('.AnyTime-off-off-btn.AnyTime-cur-btn:first');if(!f.length)
-f=this.oDiv.find('.AnyTime-off-off-btn:first');this.setFocus(f);},askYear:function(event)
-{if(!this.yDiv)
-{this.makeCloak();this.yDiv=$('<div class="AnyTime-win AnyTime-yr-selector ui-widget ui-widget-content ui-corner-all" style="position:absolute" />');this.div.append(this.yDiv);var title=$('<h5 class="AnyTime-hdr AnyTime-hdr-yr-selector ui-widget-header ui-corner-top" />');this.yDiv.append(title);var xDiv=$('<div class="AnyTime-x-btn ui-state-default">'+this.lX+'</div>');title.append(xDiv);xDiv.click(function(e){_this.dismissYDiv(e);});title.append(this.lY);var yBody=$('<div class="AnyTime-body AnyTime-body-yr-selector" />');var yW=yBody.AnyTime_width(true);var yH=0;this.yDiv.append(yBody);cont=$('<ul class="AnyTime-yr-mil" />');yBody.append(cont);this.y0XXX=this.btn(cont,0,this.newYPos,['mil','mil0'],this.lY+' '+0+'000');for(i=1;i<10;i++)
-this.btn(cont,i,this.newYPos,['mil','mil'+i],this.lY+' '+i+'000');yW+=cont.AnyTime_width(true);if(yH<cont.AnyTime_height(true))
-yH=cont.AnyTime_height(true);cont=$('<ul class="AnyTime-yr-cent" />');yBody.append(cont);for(i=0;i<10;i++)
-this.btn(cont,i,this.newYPos,['cent','cent'+i],this.lY+' '+i+'00');yW+=cont.AnyTime_width(true);if(yH<cont.AnyTime_height(true))
-yH=cont.AnyTime_height(true);cont=$('<ul class="AnyTime-yr-dec" />');yBody.append(cont);for(i=0;i<10;i++)
-this.btn(cont,i,this.newYPos,['dec','dec'+i],this.lY+' '+i+'0');yW+=cont.AnyTime_width(true);if(yH<cont.AnyTime_height(true))
-yH=cont.AnyTime_height(true);cont=$('<ul class="AnyTime-yr-yr" />');yBody.append(cont);for(i=0;i<10;i++)
-this.btn(cont,i,this.newYPos,['yr','yr'+i],this.lY+' '+i);yW+=cont.AnyTime_width(true);if(yH<cont.AnyTime_height(true))
-yH=cont.AnyTime_height(true);if(this.askEra)
-{cont=$('<ul class="AnyTime-yr-era" />');yBody.append(cont);this.btn(cont,this.conv.eAbbr[0],function(event)
-{var t=new Date(this.time.getTime());var year=t.getFullYear();if(year>0)
-t.setFullYear(0-year);this.set(t);this.updYDiv($(event.target));},['era','bce'],this.conv.eAbbr[0]);this.btn(cont,this.conv.eAbbr[1],function(event)
-{var t=new Date(this.time.getTime());var year=t.getFullYear();if(year<0)
-t.setFullYear(0-year);this.set(t);this.updYDiv($(event.target));},['era','ce'],this.conv.eAbbr[1]);yW+=cont.AnyTime_width(true);if(yH<cont.AnyTime_height(true))
-yH=cont.AnyTime_height(true);}
-if($.browser.msie)
-yW+=1;else if($.browser.safari)
-yW+=2;yH+=yBody.AnyTime_height(true);yBody.css('width',String(yW)+'px');if(!__msie7)
-yBody.css('height',String(yH)+'px');if(__msie6||__msie7)
-title.width(yBody.outerWidth(true));yH+=title.AnyTime_height(true);if(title.AnyTime_width(true)>yW)
-yW=title.AnyTime_width(true);this.yDiv.css('width',String(yW)+'px');if(!__msie7)
-this.yDiv.css('height',String(yH)+'px');}
-else
-{this.cloak.show();this.yDiv.show();}
-this.pos(event);this.updYDiv(null);this.setFocus(this.yDiv.find('.AnyTime-yr-btn.AnyTime-cur-btn:first'));},inpBlur:function(event)
-{if(this.oDiv&&this.oDiv.is(":visible"))
-{_this.inp.focus();return;}
-this.lostFocus=true;setTimeout(function()
-{if(_this.lostFocus)
-{_this.div.find('.AnyTime-focus-btn').removeClass('AnyTime-focus-btn ui-state-focus');if(_this.pop)
-_this.dismiss(event);else
-_this.ajax();}},334);},btn:function(parent,text,handler,classes,title)
-{var tagName=((parent[0].nodeName.toLowerCase()=='ul')?'li':'td');var div$='<'+tagName+' class="AnyTime-btn';for(var i=0;i<classes.length;i++)
-div$+=' AnyTime-'+classes[i]+'-btn';var div=$(div$+' ui-state-default">'+text+'</'+tagName+'>');parent.append(div);div.AnyTime_title=title;div.click(function(e)
-{_this.tempFunc=handler;_this.tempFunc(e);});div.dblclick(function(e)
-{var elem=$(this);if(elem.is('.AnyTime-off-off-btn'))
-_this.dismissODiv(e);else if(elem.is('.AnyTime-mil-btn')||elem.is('.AnyTime-cent-btn')||elem.is('.AnyTime-dec-btn')||elem.is('.AnyTime-yr-btn')||elem.is('.AnyTime-era-btn'))
-_this.dismissYDiv(e);else if(_this.pop)
-_this.dismiss(e);});return div;},cleanup:function(event)
-{this.inp.unbind('blur',this.hBlur);this.inp.unbind('click',this.hClick);this.inp.unbind('focus',this.hFocus);this.inp.unbind('keydown',this.hKeydown);this.inp.unbind('keypress',this.hKeypress);this.div.remove();},dismiss:function(event)
-{this.ajax();this.div.hide();if(__iframe)
-__iframe.hide();if(this.yDiv)
-this.dismissYDiv();if(this.oDiv)
-this.dismissODiv();this.lostFocus=true;},dismissODiv:function(event)
-{this.oDiv.hide();this.cloak.hide();this.setFocus(this.oCur);},dismissYDiv:function(event)
-{this.yDiv.hide();this.cloak.hide();this.setFocus(this.yCur);},setFocus:function(btn)
-{if(!btn.hasClass('AnyTime-focus-btn'))
-{this.div.find('.AnyTime-focus-btn').removeClass('AnyTime-focus-btn ui-state-focus');this.fBtn=btn;btn.removeClass('ui-state-default ui-state-highlight');btn.addClass('AnyTime-focus-btn ui-state-default ui-state-highlight ui-state-focus');}
-if(btn.hasClass('AnyTime-off-off-btn'))
-{var oBT=this.oBody.offset().top;var btnT=btn.offset().top;var btnH=btn.AnyTime_height(true);if(btnT-btnH<oBT)
-this.oBody.scrollTop(btnT+this.oBody.scrollTop()-(this.oBody.innerHeight()+oBT)+(btnH*2));else if(btnT+btnH>oBT+this.oBody.innerHeight())
-this.oBody.scrollTop((btnT+this.oBody.scrollTop())-(oBT+btnH));}},key:function(event)
-{var mo;var t=null;var elem=this.div.find('.AnyTime-focus-btn');var key=event.keyCode||event.which;this.denyTab=true;if(key==16)
-{}
-else if((key==10)||(key==13)||(key==27))
-{if(this.oDiv&&this.oDiv.is(':visible'))
-this.dismissODiv(event);else if(this.yDiv&&this.yDiv.is(':visible'))
-this.dismissYDiv(event);else if(this.pop)
-this.dismiss(event);}
-else if((key==33)||((key==9)&&event.shiftKey))
-{if(this.fBtn.hasClass('AnyTime-off-off-btn'))
-{if(key==9)
-this.dismissODiv(event);}
-else if(this.fBtn.hasClass('AnyTime-mil-btn'))
-{if(key==9)
-this.dismissYDiv(event);}
-else if(this.fBtn.hasClass('AnyTime-cent-btn'))
-this.yDiv.find('.AnyTime-mil-btn.AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-dec-btn'))
-this.yDiv.find('.AnyTime-cent-btn.AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-yr-btn'))
-this.yDiv.find('.AnyTime-dec-btn.AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-era-btn'))
-this.yDiv.find('.AnyTime-yr-btn.AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.parents('.AnyTime-yrs').length)
-{if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-mon-btn'))
-{if(this.dY)
-this.yCur.triggerHandler('click');else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-dom-btn'))
-{if((key==9)&&event.shiftKey)
-{this.denyTab=false;return;}
-else
-{t=new Date(this.time.getTime());if(event.shiftKey)
-t.setFullYear(t.getFullYear()-1);else
-{mo=t.getMonth()-1;if(t.getDate()>__daysIn[mo])
-t.setDate(__daysIn[mo])
-t.setMonth(mo);}
-this.keyDateChange(t);}}
-else if(this.fBtn.hasClass('AnyTime-hr-btn'))
-{t=this.dDoM||this.dMo;if(t)
-t.AnyTime_clickCurrent();else if(this.dY)
-this.yCur.triggerHandler('click');else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-min-ten-btn'))
-{t=this.dH||this.dDoM||this.dMo;if(t)
-t.AnyTime_clickCurrent();else if(this.dY)
-this.yCur.triggerHandler('click');else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-min-one-btn'))
-this.dM.AnyTime_clickCurrent();else if(this.fBtn.hasClass('AnyTime-sec-ten-btn'))
-{if(this.dM)
-t=this.dM.find('.AnyTime-mins-ones');else
-t=this.dH||this.dDoM||this.dMo;if(t)
-t.AnyTime_clickCurrent();else if(this.dY)
-this.yCur.triggerHandler('click');else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-sec-one-btn'))
-this.dS.AnyTime_clickCurrent();else if(this.fBtn.hasClass('AnyTime-off-btn'))
-{if(this.dS)
-t=this.dS.find('.AnyTime-secs-ones');else if(this.dM)
-t=this.dM.find('.AnyTime-mins-ones');else
-t=this.dH||this.dDoM||this.dMo;if(t)
-t.AnyTime_clickCurrent();else if(this.dY)
-this.yCur.triggerHandler('click');else if(key==9)
-{this.denyTab=false;return;}}}
-else if((key==34)||(key==9))
-{if(this.fBtn.hasClass('AnyTime-mil-btn'))
-this.yDiv.find('.AnyTime-cent-btn.AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-cent-btn'))
-this.yDiv.find('.AnyTime-dec-btn.AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-dec-btn'))
-this.yDiv.find('.AnyTime-yr-btn.AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-yr-btn'))
-{t=this.yDiv.find('.AnyTime-era-btn.AnyTime-cur-btn');if(t.length)
-t.triggerHandler('click');else if(key==9)
-this.dismissYDiv(event);}
-else if(this.fBtn.hasClass('AnyTime-era-btn'))
-{if(key==9)
-this.dismissYDiv(event);}
-else if(this.fBtn.hasClass('AnyTime-off-off-btn'))
-{if(key==9)
-this.dismissODiv(event);}
-else if(this.fBtn.parents('.AnyTime-yrs').length)
-{t=this.dDoM||this.dMo||this.dH||this.dM||this.dS||this.dO;if(t)
-t.AnyTime_clickCurrent();else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-mon-btn'))
-{t=this.dDoM||this.dH||this.dM||this.dS||this.dO;if(t)
-t.AnyTime_clickCurrent();else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-dom-btn'))
-{if(key==9)
-{t=this.dH||this.dM||this.dS||this.dO;if(t)
-t.AnyTime_clickCurrent();else
-{this.denyTab=false;return;}}
-else
-{t=new Date(this.time.getTime());if(event.shiftKey)
-t.setFullYear(t.getFullYear()+1);else
-{mo=t.getMonth()+1;if(t.getDate()>__daysIn[mo])
-t.setDate(__daysIn[mo])
-t.setMonth(mo);}
-this.keyDateChange(t);}}
-else if(this.fBtn.hasClass('AnyTime-hr-btn'))
-{t=this.dM||this.dS||this.dO;if(t)
-t.AnyTime_clickCurrent();else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-min-ten-btn'))
-this.dM.find('.AnyTime-mins-ones .AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-min-one-btn'))
-{t=this.dS||this.dO;if(t)
-t.AnyTime_clickCurrent();else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-sec-ten-btn'))
-this.dS.find('.AnyTime-secs-ones .AnyTime-cur-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-sec-one-btn'))
-{if(this.dO)
-this.dO.AnyTime_clickCurrent();else if(key==9)
-{this.denyTab=false;return;}}
-else if(this.fBtn.hasClass('AnyTime-off-btn'))
-{if(key==9)
-{this.denyTab=false;return;}}}
-else if(key==35)
-{if(this.fBtn.hasClass('AnyTime-mil-btn')||this.fBtn.hasClass('AnyTime-cent-btn')||this.fBtn.hasClass('AnyTime-dec-btn')||this.fBtn.hasClass('AnyTime-yr-btn')||this.fBtn.hasClass('AnyTime-era-btn'))
-{t=this.yDiv.find('.AnyTime-ce-btn');if(!t.length)
-t=this.yDiv.find('.AnyTime-yr9-btn');t.triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-dom-btn'))
-{t=new Date(this.time.getTime());t.setDate(1);t.setMonth(t.getMonth()+1);t.setDate(t.getDate()-1);if(event.ctrlKey)
-t.setMonth(11);this.keyDateChange(t);}
-else if(this.dS)
-this.dS.find('.AnyTime-sec9-btn').triggerHandler('click');else if(this.dM)
-this.dM.find('.AnyTime-min9-btn').triggerHandler('click');else if(this.dH)
-this.dH.find('.AnyTime-hr23-btn').triggerHandler('click');else if(this.dDoM)
-this.dDoM.find('.AnyTime-dom-btn-filled:last').triggerHandler('click');else if(this.dMo)
-this.dMo.find('.AnyTime-mon12-btn').triggerHandler('click');else if(this.dY)
-this.yAhead.triggerHandler('click');}
-else if(key==36)
-{if(this.fBtn.hasClass('AnyTime-mil-btn')||this.fBtn.hasClass('AnyTime-cent-btn')||this.fBtn.hasClass('AnyTime-dec-btn')||this.fBtn.hasClass('AnyTime-yr-btn')||this.fBtn.hasClass('AnyTime-era-btn'))
-{this.yDiv.find('.AnyTime-mil0-btn').triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-dom-btn'))
-{t=new Date(this.time.getTime());t.setDate(1);if(event.ctrlKey)
-t.setMonth(0);this.keyDateChange(t);}
-else if(this.dY)
-this.yCur.triggerHandler('click');else if(this.dMo)
-this.dMo.find('.AnyTime-mon1-btn').triggerHandler('click');else if(this.dDoM)
-this.dDoM.find('.AnyTime-dom-btn-filled:first').triggerHandler('click');else if(this.dH)
-this.dH.find('.AnyTime-hr0-btn').triggerHandler('click');else if(this.dM)
-this.dM.find('.AnyTime-min00-btn').triggerHandler('click');else if(this.dS)
-this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');}
-else if(key==37)
-{if(this.fBtn.hasClass('AnyTime-dom-btn'))
-this.keyDateChange(new Date(this.time.getTime()-__oneDay));else
-this.keyBack();}
-else if(key==38)
-{if(this.fBtn.hasClass('AnyTime-dom-btn'))
-this.keyDateChange(new Date(this.time.getTime()-(7*__oneDay)));else
-this.keyBack();}
-else if(key==39)
-{if(this.fBtn.hasClass('AnyTime-dom-btn'))
-this.keyDateChange(new Date(this.time.getTime()+__oneDay));else
-this.keyAhead();}
-else if(key==40)
-{if(this.fBtn.hasClass('AnyTime-dom-btn'))
-this.keyDateChange(new Date(this.time.getTime()+(7*__oneDay)));else
-this.keyAhead();}
-else if(((key==86)||(key==118))&&event.ctrlKey)
-{this.inp.val("").change();var _this=this;setTimeout(function(){_this.showPkr(null);},100);return;}
-else
-this.showPkr(null);event.preventDefault();},keyAhead:function()
-{if(this.fBtn.hasClass('AnyTime-mil9-btn'))
-this.yDiv.find('.AnyTime-cent0-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-cent9-btn'))
-this.yDiv.find('.AnyTime-dec0-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-dec9-btn'))
-this.yDiv.find('.AnyTime-yr0-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-yr9-btn'))
-this.yDiv.find('.AnyTime-bce-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-sec9-btn'))
-{}
-else if(this.fBtn.hasClass('AnyTime-sec50-btn'))
-this.dS.find('.AnyTime-sec0-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-min9-btn'))
-{if(this.dS)
-this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-min50-btn'))
-this.dM.find('.AnyTime-min0-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-hr23-btn'))
-{if(this.dM)
-this.dM.find('.AnyTime-min00-btn').triggerHandler('click');else if(this.dS)
-this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-hr11-btn'))
-this.dH.find('.AnyTime-hr12-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-mon12-btn'))
-{if(this.dDoM)
-this.dDoM.AnyTime_clickCurrent();else if(this.dH)
-this.dH.find('.AnyTime-hr0-btn').triggerHandler('click');else if(this.dM)
-this.dM.find('.AnyTime-min00-btn').triggerHandler('click');else if(this.dS)
-this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-yrs-ahead-btn'))
-{if(this.dMo)
-this.dMo.find('.AnyTime-mon1-btn').triggerHandler('click');else if(this.dH)
-this.dH.find('.AnyTime-hr0-btn').triggerHandler('click');else if(this.dM)
-this.dM.find('.AnyTime-min00-btn').triggerHandler('click');else if(this.dS)
-this.dS.find('.AnyTime-sec00-btn').triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-yr-cur-btn'))
-this.yNext.triggerHandler('click');else
-this.fBtn.next().triggerHandler('click');},keyBack:function()
-{if(this.fBtn.hasClass('AnyTime-cent0-btn'))
-this.yDiv.find('.AnyTime-mil9-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-dec0-btn'))
-this.yDiv.find('.AnyTime-cent9-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-yr0-btn'))
-this.yDiv.find('.AnyTime-dec9-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-bce-btn'))
-this.yDiv.find('.AnyTime-yr9-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-yr-cur-btn'))
-this.yPrior.triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-mon1-btn'))
-{if(this.dY)
-this.yCur.triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-hr0-btn'))
-{if(this.dDoM)
-this.dDoM.AnyTime_clickCurrent();else if(this.dMo)
-this.dMo.find('.AnyTime-mon12-btn').triggerHandler('click');else if(this.dY)
-this.yNext.triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-hr12-btn'))
-this.dH.find('.AnyTime-hr11-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-min00-btn'))
-{if(this.dH)
-this.dH.find('.AnyTime-hr23-btn').triggerHandler('click');else if(this.dDoM)
-this.dDoM.AnyTime_clickCurrent();else if(this.dMo)
-this.dMo.find('.AnyTime-mon12-btn').triggerHandler('click');else if(this.dY)
-this.yNext.triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-min0-btn'))
-this.dM.find('.AnyTime-min50-btn').triggerHandler('click');else if(this.fBtn.hasClass('AnyTime-sec00-btn'))
-{if(this.dM)
-this.dM.find('.AnyTime-min9-btn').triggerHandler('click');else if(this.dH)
-this.dH.find('.AnyTime-hr23-btn').triggerHandler('click');else if(this.dDoM)
-this.dDoM.AnyTime_clickCurrent();else if(this.dMo)
-this.dMo.find('.AnyTime-mon12-btn').triggerHandler('click');else if(this.dY)
-this.yNext.triggerHandler('click');}
-else if(this.fBtn.hasClass('AnyTime-sec0-btn'))
-this.dS.find('.AnyTime-sec50-btn').triggerHandler('click');else
-this.fBtn.prev().triggerHandler('click');},keyDateChange:function(newDate)
-{if(this.fBtn.hasClass('AnyTime-dom-btn'))
-{this.set(newDate);this.upd(null);this.setFocus(this.dDoM.find('.AnyTime-cur-btn'));}},makeCloak:function()
-{if(!this.cloak)
-{this.cloak=$('<div class="AnyTime-cloak" style="position:absolute" />');this.div.append(this.cloak);this.cloak.click(function(e)
-{if(_this.oDiv&&_this.oDiv.is(":visible"))
-_this.dismissODiv(e);else
-_this.dismissYDiv(e);});}
-else
-this.cloak.show();},newHour:function(event)
-{var h;var t;var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;if(!this.twelveHr)
-h=Number(elem.text());else
-{var str=elem.text();t=str.indexOf('a');if(t<0)
-{t=Number(str.substr(0,str.indexOf('p')));h=((t==12)?12:(t+12));}
-else
-{t=Number(str.substr(0,t));h=((t==12)?0:t);}}
-t=new Date(this.time.getTime());t.setHours(h);this.set(t);this.upd(elem);},newOffset:function(event)
-{if(event.target==this.oSel[0])
-this.askOffset(event);else
-{this.upd(this.oCur);}},newOPos:function(event)
-{var elem=$(event.target);this.offMin=elem[0].AnyTime_offMin;this.offSI=elem[0].AnyTime_offSI;var t=new Date(this.time.getTime());this.set(t);this.updODiv(elem);},newYear:function(event)
-{var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;var txt=elem.text();if((txt=='<')||(txt=='<'))
-this.askYear(event);else if((txt=='>')||(txt=='>'))
-this.askYear(event);else
-{var t=new Date(this.time.getTime());t.setFullYear(Number(txt));this.set(t);this.upd(this.yCur);}},newYPos:function(event)
-{var elem=$(event.target);if(elem.hasClass("AnyTime-out-btn"))
-return;var era=1;var year=this.time.getFullYear();if(year<0)
-{era=(-1);year=0-year;}
-year=AnyTime.pad(year,4);if(elem.hasClass('AnyTime-mil-btn'))
-year=elem.html()+year.substring(1,4);else if(elem.hasClass('AnyTime-cent-btn'))
-year=year.substring(0,1)+elem.html()+year.substring(2,4);else if(elem.hasClass('AnyTime-dec-btn'))
-year=year.substring(0,2)+elem.html()+year.substring(3,4);else
-year=year.substring(0,3)+elem.html();if(year=='0000')
-year=1;var t=new Date(this.time.getTime());t.setFullYear(era*year);this.set(t);this.updYDiv(elem);},onReady:function()
-{this.lostFocus=true;if(!this.pop)
-this.upd(null);else
-{if(this.div.parent()!=document.body)
-this.div.appendTo(document.body);}},pos:function(event)
-{if(this.pop)
-{var off=this.inp.offset();var bodyWidth=$(document.body).outerWidth(true);var pickerWidth=this.div.outerWidth(true);var left=off.left;if(left+pickerWidth>bodyWidth-20)
-left=bodyWidth-(pickerWidth+20);var top=off.top-this.div.outerHeight(true);if(top<0)
-top=off.top+this.inp.outerHeight(true);this.div.css({top:String(top)+'px',left:String(left<0?0:left)+'px'});}
-var wOff=this.div.offset();if(this.oDiv&&this.oDiv.is(":visible"))
-{var oOff=this.oLab.offset();if(this.div.css('position')=='absolute')
-{oOff.top-=wOff.top;oOff.left=oOff.left-wOff.left;wOff={top:0,left:0};}
-var oW=this.oDiv.AnyTime_width(true);var wW=this.div.AnyTime_width(true);if(oOff.left+oW>wOff.left+wW)
-{oOff.left=(wOff.left+wW)-oW;if(oOff.left<2)
-oOff.left=2;}
-var oH=this.oDiv.AnyTime_height(true);var wH=this.div.AnyTime_height(true);oOff.top+=this.oLab.AnyTime_height(true);if(oOff.top+oH>wOff.top+wH)
-oOff.top=oOff.top-oH;if(oOff.top<wOff.top)
-oOff.top=wOff.top;this.oDiv.css({top:oOff.top+'px',left:oOff.left+'px'});}
-else if(this.yDiv&&this.yDiv.is(":visible"))
-{var yOff=this.yLab.offset();if(this.div.css('position')=='absolute')
-{yOff.top-=wOff.top;yOff.left=yOff.left-wOff.left;wOff={top:0,left:0};}
-yOff.left+=((this.yLab.outerWidth(true)-this.yDiv.outerWidth(true))/2);this.yDiv.css({top:yOff.top+'px',left:yOff.left+'px'});}
-if(this.cloak)
-this.cloak.css({top:wOff.top+'px',left:wOff.left+'px',height:String(this.div.outerHeight(true)-2)+'px',width:String(this.div.outerWidth(!$.browser.safari)-2)+'px'});},set:function(newTime)
-{var t=newTime.getTime();if(this.earliest&&(t<this.earliest))
-this.time=new Date(this.earliest);else if(this.latest&&(t>this.latest))
-this.time=new Date(this.latest);else
-this.time=newTime;},showPkr:function(event)
-{try
-{this.time=this.conv.parse(this.inp.val());this.offMin=this.conv.getUtcParseOffsetCaptured();this.offSI=this.conv.getUtcParseOffsetSubIndex();}
-catch(e)
-{this.time=new Date();}
-this.set(this.time);this.upd(null);fBtn=null;var cb='.AnyTime-cur-btn:first';if(this.dDoM)
-fBtn=this.dDoM.find(cb);else if(this.yCur)
-fBtn=this.yCur;else if(this.dMo)
-fBtn=this.dMo.find(cb);else if(this.dH)
-fBtn=this.dH.find(cb);else if(this.dM)
-fBtn=this.dM.find(cb);else if(this.dS)
-fBtn=this.dS.find(cb);this.setFocus(fBtn);this.pos(event);if(this.pop&&__iframe)
-setTimeout(function()
-{var pos=_this.div.offset();__iframe.css({height:String(_this.div.outerHeight(true))+'px',left:String(pos.left)+'px',position:'absolute',top:String(pos.top)+'px',width:String(_this.div.outerWidth(true))+'px'});__iframe.show();},300);},upd:function(fBtn)
-{var cmpLo=new Date(this.time.getTime());cmpLo.setMonth(0,1);cmpLo.setHours(0,0,0,0);var cmpHi=new Date(this.time.getTime());cmpHi.setMonth(11,31);cmpHi.setHours(23,59,59,999);var current=this.time.getFullYear();if(this.earliest&&this.yPast)
-{cmpHi.setYear(current-2);if(cmpHi.getTime()<this.earliest)
-this.yPast.addClass('AnyTime-out-btn ui-state-disabled');else
-this.yPast.removeClass('AnyTime-out-btn ui-state-disabled');}
-if(this.yPrior)
-{this.yPrior.text(AnyTime.pad((current==1)?(-1):(current-1),4));if(this.earliest)
-{cmpHi.setYear(current-1);if(cmpHi.getTime()<this.earliest)
-this.yPrior.addClass('AnyTime-out-btn ui-state-disabled');else
-this.yPrior.removeClass('AnyTime-out-btn ui-state-disabled');}}
-if(this.yCur)
-this.yCur.text(AnyTime.pad(current,4));if(this.yNext)
-{this.yNext.text(AnyTime.pad((current==-1)?1:(current+1),4));if(this.latest)
-{cmpLo.setYear(current+1);if(cmpLo.getTime()>this.latest)
-this.yNext.addClass('AnyTime-out-btn ui-state-disabled');else
-this.yNext.removeClass('AnyTime-out-btn ui-state-disabled');}}
-if(this.latest&&this.yAhead)
-{cmpLo.setYear(current+2);if(cmpLo.getTime()>this.latest)
-this.yAhead.addClass('AnyTime-out-btn ui-state-disabled');else
-this.yAhead.removeClass('AnyTime-out-btn ui-state-disabled');}
-cmpLo.setFullYear(this.time.getFullYear());cmpHi.setFullYear(this.time.getFullYear());var i=0;current=this.time.getMonth();$('#'+this.id+' .AnyTime-mon-btn').each(function()
-{cmpLo.setMonth(i);cmpHi.setDate(1);cmpHi.setMonth(i+1);cmpHi.setDate(0);$(this).AnyTime_current(i==current,((!_this.earliest)||(cmpHi.getTime()>=_this.earliest))&&((!_this.latest)||(cmpLo.getTime()<=_this.latest)));i++;});cmpLo.setFullYear(this.time.getFullYear());cmpHi.setFullYear(this.time.getFullYear());cmpLo.setMonth(this.time.getMonth());cmpHi.setMonth(this.time.getMonth(),1);current=this.time.getDate();var currentMonth=this.time.getMonth();var dow1=cmpLo.getDay();if(this.fDOW>dow1)
-dow1+=7;var wom=0,dow=0;$('#'+this.id+' .AnyTime-wk').each(function()
-{dow=_this.fDOW;$(this).children().each(function()
-{if(dow-_this.fDOW<7)
-{var td=$(this);if(((wom==0)&&(dow<dow1))||(cmpLo.getMonth()!=currentMonth))
-{td.html(' ');td.removeClass('AnyTime-dom-btn-filled AnyTime-cur-btn ui-state-default ui-state-highlight');td.addClass('AnyTime-dom-btn-empty');if(wom)
-{if((cmpLo.getDate()==1)&&(dow!=0))
-td.addClass('AnyTime-dom-btn-empty-after-filled');else
-td.removeClass('AnyTime-dom-btn-empty-after-filled');if(cmpLo.getDate()<=7)
-td.addClass('AnyTime-dom-btn-empty-below-filled');else
-td.removeClass('AnyTime-dom-btn-empty-below-filled');cmpLo.setDate(cmpLo.getDate()+1);cmpHi.setDate(cmpHi.getDate()+1);}
-else
-{td.addClass('AnyTime-dom-btn-empty-above-filled');if(dow==dow1-1)
-td.addClass('AnyTime-dom-btn-empty-before-filled');else
-td.removeClass('AnyTime-dom-btn-empty-before-filled');}
-td.addClass('ui-state-default ui-state-disabled');}
-else
-{i=cmpLo.getDate();td.text(i);td.removeClass('AnyTime-dom-btn-empty AnyTime-dom-btn-empty-above-filled AnyTime-dom-btn-empty-before-filled '+'AnyTime-dom-btn-empty-after-filled AnyTime-dom-btn-empty-below-filled '+'ui-state-default ui-state-disabled');td.addClass('AnyTime-dom-btn-filled ui-state-default');td.AnyTime_current(i==current,((!_this.earliest)||(cmpHi.getTime()>=_this.earliest))&&((!_this.latest)||(cmpLo.getTime()<=_this.latest)));cmpLo.setDate(i+1);cmpHi.setDate(i+1);}}
-dow++;});wom++;});cmpLo.setFullYear(this.time.getFullYear());cmpHi.setFullYear(this.time.getFullYear());cmpLo.setMonth(this.time.getMonth(),this.time.getDate());cmpHi.setMonth(this.time.getMonth(),this.time.getDate());var not12=!this.twelveHr;var hr=this.time.getHours();$('#'+this.id+' .AnyTime-hr-btn').each(function()
-{var html=this.innerHTML;var i;if(not12)
-i=Number(html);else
-{i=Number(html.substring(0,html.length-2));if(html.charAt(html.length-2)=='a')
-{if(i==12)
-i=0;}
-else if(i<12)
-i+=12;}
-cmpLo.setHours(i);cmpHi.setHours(i);$(this).AnyTime_current(hr==i,((!_this.earliest)||(cmpHi.getTime()>=_this.earliest))&&((!_this.latest)||(cmpLo.getTime()<=_this.latest)));if(i<23)
-cmpLo.setHours(cmpLo.getHours()+1);});cmpLo.setHours(this.time.getHours());cmpHi.setHours(this.time.getHours());var units=this.time.getMinutes();var tens=String(Math.floor(units/10));var ones=String(units%10);$('#'+this.id+' .AnyTime-min-ten-btn:not(.AnyTime-min-ten-btn-empty)').each(function()
-{$(this).AnyTime_current(this.innerHTML==tens,((!_this.earliest)||(cmpHi.getTime()>=_this.earliest))&&((!_this.latest)||(cmpLo.getTime()<=_this.latest)));if(cmpLo.getMinutes()<50)
-{cmpLo.setMinutes(cmpLo.getMinutes()+10);cmpHi.setMinutes(cmpHi.getMinutes()+10);}});cmpLo.setMinutes(Math.floor(this.time.getMinutes()/10)*10);cmpHi.setMinutes(Math.floor(this.time.getMinutes()/10)*10);$('#'+this.id+' .AnyTime-min-one-btn:not(.AnyTime-min-one-btn-empty)').each(function()
-{$(this).AnyTime_current(this.innerHTML==ones,((!_this.earliest)||(cmpHi.getTime()>=_this.earliest))&&((!_this.latest)||(cmpLo.getTime()<=_this.latest)));cmpLo.setMinutes(cmpLo.getMinutes()+1);cmpHi.setMinutes(cmpHi.getMinutes()+1);});cmpLo.setMinutes(this.time.getMinutes());cmpHi.setMinutes(this.time.getMinutes());units=this.time.getSeconds();tens=String(Math.floor(units/10));ones=String(units%10);$('#'+this.id+' .AnyTime-sec-ten-btn:not(.AnyTime-sec-ten-btn-empty)').each(function()
-{$(this).AnyTime_current(this.innerHTML==tens,((!_this.earliest)||(cmpHi.getTime()>=_this.earliest))&&((!_this.latest)||(cmpLo.getTime()<=_this.latest)));if(cmpLo.getSeconds()<50)
-{cmpLo.setSeconds(cmpLo.getSeconds()+10);cmpHi.setSeconds(cmpHi.getSeconds()+10);}});cmpLo.setSeconds(Math.floor(this.time.getSeconds()/10)*10);cmpHi.setSeconds(Math.floor(this.time.getSeconds()/10)*10);$('#'+this.id+' .AnyTime-sec-one-btn:not(.AnyTime-sec-one-btn-empty)').each(function()
-{$(this).AnyTime_current(this.innerHTML==ones,((!_this.earliest)||(cmpHi.getTime()>=_this.earliest))&&((!_this.latest)||(cmpLo.getTime()<=_this.latest)));cmpLo.setSeconds(cmpLo.getSeconds()+1);cmpHi.setSeconds(cmpHi.getSeconds()+1);});if(this.oConv)
-{this.oConv.setUtcFormatOffsetAlleged(this.offMin);this.oConv.setUtcFormatOffsetSubIndex(this.offSI);var tzs=this.oConv.format(this.time);this.oCur.html(tzs);}
-if(fBtn)
-this.setFocus(fBtn);this.conv.setUtcFormatOffsetAlleged(this.offMin);this.conv.setUtcFormatOffsetSubIndex(this.offSI);this.inp.val(this.conv.format(this.time)).change();this.div.show();var d,totH=0,totW=0,dYW=0,dMoW=0,dDoMW=0;if(this.dY)
-{totW=dYW=this.dY.outerWidth(true);totH=this.yLab.AnyTime_height(true)+this.dY.AnyTime_height(true);}
-if(this.dMo)
-{dMoW=this.dMo.outerWidth(true);if(dMoW>totW)
-totW=dMoW;totH+=this.hMo.AnyTime_height(true)+this.dMo.AnyTime_height(true);}
-if(this.dDoM)
-{dDoMW=this.dDoM.outerWidth(true);if(dDoMW>totW)
-totW=dDoMW;if(__msie6||__msie7)
-{if(dMoW>dDoMW)
-this.dDoM.css('width',String(dMoW)+'px');else if(dYW>dDoMW)
-this.dDoM.css('width',String(dYW)+'px');}
-totH+=this.hDoM.AnyTime_height(true)+this.dDoM.AnyTime_height(true);}
-if(this.dD)
-{this.dD.css({width:String(totW)+'px',height:String(totH)+'px'});totW+=this.dMinW;totH+=this.dMinH;}
-var w=0,h=0,timeH=0,timeW=0;if(this.dH)
-{w=this.dH.outerWidth(true);timeW+=w+1;h=this.dH.AnyTime_height(true);if(h>timeH)
-timeH=h;}
-if(this.dM)
-{w=this.dM.outerWidth(true);timeW+=w+1;h=this.dM.AnyTime_height(true);if(h>timeH)
-timeH=h;}
-if(this.dS)
-{w=this.dS.outerWidth(true);timeW+=w+1;h=this.dS.AnyTime_height(true);if(h>timeH)
-timeH=h;}
-if(this.dO)
-{w=this.oMinW;if(timeW<w+1)
-timeW=w+1;timeH+=this.dO.AnyTime_height(true);}
-if(this.dT)
-{this.dT.css({width:String(timeW)+'px',height:String(timeH)+'px'});timeW+=this.tMinW+1;timeH+=this.tMinH;totW+=timeW;if(timeH>totH)
-totH=timeH;if(this.dO)
-{var dOW=this.dT.width()-(this.oMinW+1);this.dO.css({width:String(dOW)+"px"});this.oCur.css({width:String(dOW-(this.oListMinW+4))+"px"});}}
-this.dB.css({height:String(totH)+'px',width:String(totW)+'px'});totH+=this.bMinH;totW+=this.bMinW;totH+=this.hTitle.AnyTime_height(true)+this.wMinH;totW+=this.wMinW;if(this.hTitle.outerWidth(true)>totW)
-totW=this.hTitle.outerWidth(true);this.div.css({height:String(totH)+'px',width:String(totW)+'px'});if(!this.pop)
-this.ajax();},updODiv:function(fBtn)
-{var cur,matched=false,def=null;this.oDiv.find('.AnyTime-off-off-btn').each(function()
-{if(this.AnyTime_offMin==_this.offMin)
-{if(this.AnyTime_offSI==_this.offSI)
-$(this).AnyTime_current(matched=true,true);else
-{$(this).AnyTime_current(false,true);if(def==null)
-def=$(this);}}
-else
-$(this).AnyTime_current(false,true);});if((!matched)&&(def!=null))
-def.AnyTime_current(true,true);this.conv.setUtcFormatOffsetAlleged(this.offMin);this.conv.setUtcFormatOffsetSubIndex(this.offSI);this.inp.val(this.conv.format(this.time)).change();this.upd(fBtn);},updYDiv:function(fBtn)
-{var i,legal;var era=1;var yearValue=this.time.getFullYear();if(yearValue<0)
-{era=(-1);yearValue=0-yearValue;}
-yearValue=AnyTime.pad(yearValue,4);var eY=_this.earliest&&new Date(_this.earliest).getFullYear();var lY=_this.latest&&new Date(_this.latest).getFullYear();i=0;this.yDiv.find('.AnyTime-mil-btn').each(function()
-{legal=(((!_this.earliest)||(era*(i+(era<0?0:999))>=eY))&&((!_this.latest)||(era*(i+(era>0?0:999))<=lY)));$(this).AnyTime_current(this.innerHTML==yearValue.substring(0,1),legal);i+=1000;});i=(Math.floor(yearValue/1000)*1000);this.yDiv.find('.AnyTime-cent-btn').each(function()
-{legal=(((!_this.earliest)||(era*(i+(era<0?0:99))>=eY))&&((!_this.latest)||(era*(i+(era>0?0:99))<=lY)));$(this).AnyTime_current(this.innerHTML==yearValue.substring(1,2),legal);i+=100;});i=(Math.floor(yearValue/100)*100);this.yDiv.find('.AnyTime-dec-btn').each(function()
-{legal=(((!_this.earliest)||(era*(i+(era<0?0:9))>=eY))&&((!_this.latest)||(era*(i+(era>0?0:9))<=lY)));$(this).AnyTime_current(this.innerHTML==yearValue.substring(2,3),legal);i+=10;});i=(Math.floor(yearValue/10)*10);this.yDiv.find('.AnyTime-yr-btn').each(function()
-{legal=(((!_this.earliest)||(era*i>=eY))&&((!_this.latest)||(era*i<=lY)));$(this).AnyTime_current(this.innerHTML==yearValue.substring(3),legal);i+=1;});this.yDiv.find('.AnyTime-bce-btn').each(function()
-{$(this).AnyTime_current(era<0,(!_this.earliest)||(_this.earliest<0));});this.yDiv.find('.AnyTime-ce-btn').each(function()
-{$(this).AnyTime_current(era>0,(!_this.latest)||(_this.latest>0));});this.conv.setUtcFormatOffsetAlleged(this.offMin);this.conv.setUtcFormatOffsetSubIndex(this.offSI);this.inp.val(this.conv.format(this.time)).change();this.upd(fBtn);}};__pickers[id].initialize(id);}})(jQuery);
diff --git a/nop/site_media/dateinput.css b/nop/site_media/dateinput.css
deleted file mode 100644
index fd013e7b7b54a84d6c93df86ac298c821a66802b..0000000000000000000000000000000000000000
--- a/nop/site_media/dateinput.css
+++ /dev/null
@@ -1,151 +0,0 @@
-/* For the details, see: http://flowplayer.org/tools/dateinput/index.html#skinning */
-
-/* the input field */
-.date {
-	border:1px solid #ccc;
-	font-size:18px;
-	padding:4px;
-	text-align:center;
-	width:194px;
-
-	-moz-box-shadow:0 0 10px #eee inset;
-	-webkit-box-shadow:0 0 10px #eee inset;
-}
-
-/* calendar root element */
-#calroot {
-	/* place on top of other elements. set a higher value if nessessary */
-	z-index:10000;
-
-	margin-top:-1px;
-	width:198px;
-	padding:2px;
-	background-color:#fff;
-	font-size:11px;
-	border:1px solid #ccc;
-
-	-moz-border-radius:5px;
-	-webkit-border-radius:5px;
-
-	-moz-box-shadow: 0 0 15px #666;
-	-webkit-box-shadow: 0 0 15px #666;
-}
-
-/* head. contains title, prev/next month controls and possible month/year selectors */
-#calhead {
-	padding:2px 0;
-	height:22px;
-}
-
-#caltitle {
-	font-size:14px;
-	color:#0150D1;
-	float:left;
-	text-align:center;
-	width:155px;
-	line-height:20px;
-	text-shadow:0 1px 0 #ddd;
-}
-
-#calnext, #calprev {
-	display:block;
-	width:20px;
-	height:20px;
-	background:transparent url(prev.gif) no-repeat scroll center center;
-	float:left;
-	cursor:pointer;
-}
-
-#calnext {
-	background-image:url(next.gif);
-	float:right;
-}
-
-#calprev.caldisabled, #calnext.caldisabled {
-	visibility:hidden;
-}
-
-/* year/month selector */
-#caltitle select {
-	font-size:10px;
-}
-
-/* names of the days */
-#caldays {
-	height:14px;
-	border-bottom:1px solid #ddd;
-}
-
-#caldays span {
-	display:block;
-	float:left;
-	width:28px;
-	text-align:center;
-}
-
-/* container for weeks */
-#calweeks {
-	background-color:#fff;
-	margin-top:4px;
-}
-
-/* single week */
-.calweek {
-	clear:left;
-	height:22px;
-}
-
-/* single day */
-.calweek a {
-	display:block;
-	float:left;
-	width:27px;
-	height:20px;
-	text-decoration:none;
-	font-size:11px;
-	margin-left:1px;
-	text-align:center;
-	line-height:20px;
-	color:#666;
-	-moz-border-radius:3px;
-	-webkit-border-radius:3px;
-}
-
-/* different states */
-.calweek a:hover, .calfocus {
-	background-color:#ddd;
-}
-
-/* sunday */
-a.calsun {
-	color:red;
-}
-
-/* offmonth day */
-a.caloff {
-	color:#ccc;
-}
-
-a.caloff:hover {
-	background-color:rgb(245, 245, 250);
-}
-
-
-/* unselecteble day */
-a.caldisabled {
-	background-color:#efefef !important;
-	color:#ccc	!important;
-	cursor:default;
-}
-
-/* current day */
-#calcurrent {
-	background-color:#498CE2;
-	color:#fff;
-}
-
-/* today */
-#caltoday {
-	background-color:#333;
-	color:#fff;
-}
diff --git a/nop/site_media/jquery-1.6.1/jquery.min.js b/nop/site_media/jquery-1.6.1/jquery.min.js
deleted file mode 100644
index b2ac1747f3cbb4fb3f9c2224905daf3f0bef21fd..0000000000000000000000000000000000000000
--- a/nop/site_media/jquery-1.6.1/jquery.min.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.6.1
- * http://jquery.com/
- *
- * Copyright 2011, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2011, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Thu May 12 15:04:36 2011 -0400
- */
-(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!cj[a]){var b=f("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),c.body.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write("<!doctype><html><body></body></html>");b=cl.createElement(a),cl.body.appendChild(b),d=f.css(b,"display"),c.body.removeChild(ck)}cj[a]=d}return cj[a]}function cu(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function ct(){cq=b}function cs(){setTimeout(ct,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bF.test(a)?d(a,e):b_(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bU,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bQ),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bD(a,b,c){var d=b==="width"?bx:by,e=b==="width"?a.offsetWidth:a.offsetHeight;if(c==="border")return e;f.each(d,function(){c||(e-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?e+=parseFloat(f.css(a,"margin"+this))||0:e-=parseFloat(f.css(a,"border"+this+"Width"))||0});return e}function bn(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bm(a){f.nodeName(a,"input")?bl(a):a.getElementsByTagName&&f.grep(a.getElementsByTagName("input"),bl)}function bl(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bk(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bj(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bi(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bh(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function X(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(S.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function W(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function O(a,b){return(a&&a!=="*"?a+".":"")+b.replace(A,"`").replace(B,"&")}function N(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(y,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function L(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function F(){return!0}function E(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function H(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(H,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=d.userAgent,x,y,z,A=Object.prototype.toString,B=Object.prototype.hasOwnProperty,C=Array.prototype.push,D=Array.prototype.slice,E=String.prototype.trim,F=Array.prototype.indexOf,G={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.1",length:0,size:function(){return this.length},toArray:function(){return D.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?C.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(D.apply(this,arguments),"slice",D.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:C,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;y.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!y){y=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",z,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",z),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&H()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):G[A.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!B.call(a,"constructor")&&!B.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||B.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:E?function(a){return a==null?"":E.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?C.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(F)return F.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=D.call(arguments,2),g=function(){return a.apply(c,f.concat(D.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){G["[object "+b+"]"]=b.toLowerCase()}),x=e.uaMatch(w),x.browser&&(e.browser[x.browser]=!0,e.browser.version=x.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?z=function(){c.removeEventListener("DOMContentLoaded",z,!1),e.ready()}:c.attachEvent&&(z=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",z),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g](h)}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r;a.setAttribute("className","t"),a.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};f=c.createElement("select"),g=f.appendChild(c.createElement("option")),h=a.getElementsByTagName("input")[0],j={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},h.checked=!0,j.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,j.optDisabled=!g.disabled;try{delete a.test}catch(s){j.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function b(){j.noCloneEvent=!1,a.detachEvent("onclick",b)}),a.cloneNode(!0).fireEvent("onclick")),h=c.createElement("input"),h.value="t",h.setAttribute("type","radio"),j.radioValue=h.value==="t",h.setAttribute("checked","checked"),a.appendChild(h),k=c.createDocumentFragment(),k.appendChild(a.firstChild),j.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",l=c.createElement("body"),m={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};for(q in m)l.style[q]=m[q];l.appendChild(a),b.insertBefore(l,b.firstChild),j.appendChecked=h.checked,j.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,j.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",j.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",n=a.getElementsByTagName("td"),r=n[0].offsetHeight===0,n[0].style.display="",n[1].style.display="none",j.reliableHiddenOffsets=r&&n[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(i=c.createElement("div"),i.style.width="0",i.style.marginRight="0",a.appendChild(i),j.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(i,null)||{marginRight:0}).marginRight,10)||0)===0),l.innerHTML="",b.removeChild(l);if(a.attachEvent)for(q in{submit:1,change:1,focusin:1})p="on"+q,r=p in a,r||(a.setAttribute(p,"return;"),r=typeof a[p]=="function"),j[q+"Bubbles"]=r;return j}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u=/\:/,v,w;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.addClass(a.call(this,b,c.attr("class")||""))});if(a&&typeof a=="string"){var b=(a||"").split(o);for(var c=0,d=this.length;c<d;c++){var e=this[c];if(e.nodeType===1)if(!e.className)e.className=a;else{var g=" "+e.className+" ",h=e.className;for(var i=0,j=b.length;i<j;i++)g.indexOf(" "+b[i]+" ")<0&&(h+=" "+b[i]);e.className=f.trim(h)}}}return this},removeClass:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.removeClass(a.call(this,b,c.attr("class")))});if(a&&typeof a=="string"||a===b){var c=(a||"").split(o);for(var d=0,e=this.length;d<e;d++){var g=this[d];if(g.nodeType===1&&g.className)if(a){var h=(" "+g.className+" ").replace(n," ");for(var i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){var d=f(this);d.toggleClass(a.call(this,c,d.attr("class"),b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;return(e.value||"").replace(p,"")}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);c=j&&f.attrFix[c]||c,i=f.attrHooks[c],i||(!t.test(c)||typeof d!="boolean"&&d!==b&&d.toLowerCase()!==c.toLowerCase()?v&&(f.nodeName(a,"form")||u.test(c))&&(i=v):i=w);if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j)return i.get(a,c);h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);c=i&&f.propFix[c]||c,h=f.propHooks[c];return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return a[f.propFix[c]||c]?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=b),a.setAttribute(c,c.toLowerCase()));return c}},f.attrHooks.value={get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return a.value},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=Object.prototype.hasOwnProperty,y=/\.(.*)$/,z=/^(?:textarea|input|select)$/i,A=/\./g,B=/ /g,C=/[^\w\s.|`]/g,D=function(a){return a.replace(C,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=E;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=E);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),D).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem
-)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,O(a.origType,a.selector),f.extend({},a,{handler:N,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,O(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?F:E):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=F;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=F;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=F,this.stopPropagation()},isDefaultPrevented:E,isPropagationStopped:E,isImmediatePropagationStopped:E};var G=function(a){var b=a.relatedTarget;a.type=a.data;try{if(b&&b!==c&&!b.parentNode)return;while(b&&b!==this)b=b.parentNode;b!==this&&f.event.handle.apply(this,arguments)}catch(d){}},H=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?H:G,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?H:G)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&f(b).closest("form").length&&L("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&L("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var I,J=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},K=function(c){var d=c.target,e,g;if(!!z.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=J(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:K,beforedeactivate:K,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&K.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&K.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",J(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in I)f.event.add(this,c+".specialChange",I[c]);return z.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return z.test(this.nodeName)}},I=f.event.special.change.filters,I.focus=I.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var M={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||E,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=y.exec(h),k="",j&&(k=j[0],h=h.replace(y,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,M[h]?(a.push(M[h]+k),h=h+k):h=(M[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+O(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+O(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var P=/Until$/,Q=/^(?:parents|prevUntil|prevAll)/,R=/,/,S=/^.[^:#\[\.,]*$/,T=Array.prototype.slice,U=f.expr.match.POS,V={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(X(this,a,!1),"not",a)},filter:function(a){return this.pushStack(X(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=U.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=U.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(W(c[0])||W(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=T.call(arguments);P.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!V[a]?f.unique(e):e,(this.length>1||R.test(d))&&Q.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var Y=/ jQuery\d+="(?:\d+|null)"/g,Z=/^\s+/,$=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,_=/<([\w:]+)/,ba=/<tbody/i,bb=/<|&#?\w+;/,bc=/<(?:script|object|embed|option|style)/i,bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Y,""):null;if(typeof a=="string"&&!bc.test(a)&&(f.support.leadingWhitespace||!Z.test(a))&&!bg[(_.exec(a)||["",""])[1].toLowerCase()]){a=a.replace($,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bh(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bn)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i=b&&b[0]?b[0].ownerDocument||b[0]:c;a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!bc.test(a[0])&&(f.support.checkClone||!bd.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bj(a,d),e=bk(a),g=bk(d);for(h=0;e[h];++h)bj(e[h],g[h])}if(b){bi(a,d);if(c){e=bk(a),g=bk(d);for(h=0;e[h];++h)bi(e[h],g[h])}}return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||
-b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!bb.test(k))k=b.createTextNode(k);else{k=k.replace($,"<$1></$2>");var l=(_.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=ba.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Z.test(k)&&o.insertBefore(b.createTextNode(Z.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bm(k[i]);else bm(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bo=/alpha\([^)]*\)/i,bp=/opacity=([^)]*)/,bq=/-([a-z])/ig,br=/([A-Z]|^ms)/g,bs=/^-?\d+(?:px)?$/i,bt=/^-?\d/,bu=/^[+\-]=/,bv=/[^+\-\.\de]+/g,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB,bC=function(a,b){return b.toUpperCase()};f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0,widows:!0,orphans:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d;if(h==="number"&&isNaN(d)||d==null)return;h==="string"&&bu.test(d)&&(d=+d.replace(bv,"")+parseFloat(f.css(a,c))),h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bq,bC)}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){a.offsetWidth!==0?e=bD(a,b,d):f.swap(a,bw,function(){e=bD(a,b,d)});if(e<=0){e=bz(a,b,b),e==="0px"&&bB&&(e=bB(a,b,b));if(e!=null)return e===""||e==="auto"?"0px":e}if(e<0||e==null){e=a.style[b];return e===""||e==="auto"?"0px":e}return typeof e=="string"?e:e+"px"}},set:function(a,b){if(!bs.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bp.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bo.test(g)?g.replace(bo,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,c){var d,e,g;c=c.replace(br,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bs.test(d)&&bt.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bE=/%20/g,bF=/\[\]$/,bG=/\r?\n/g,bH=/#.*$/,bI=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bJ=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bK=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bL=/^(?:GET|HEAD)$/,bM=/^\/\//,bN=/\?/,bO=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bP=/^(?:select|textarea)/i,bQ=/\s+/,bR=/([?&])_=[^&]*/,bS=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bT=f.fn.load,bU={},bV={},bW,bX;try{bW=e.href}catch(bY){bW=c.createElement("a"),bW.href="",bW=bW.href}bX=bS.exec(bW.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bT)return bT.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bO,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bP.test(this.nodeName)||bJ.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bG,"\r\n")}}):{name:b.name,value:c.replace(bG,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bW,isLocal:bK.test(bX[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bZ(bU),ajaxTransport:bZ(bV),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?ca(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=cb(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bI.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bH,"").replace(bM,bX[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bQ),d.crossDomain==null&&(r=bS.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bX[1]&&r[2]==bX[2]&&(r[3]||(r[1]==="http:"?80:443))==(bX[3]||(bX[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bU,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bL.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bN.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bR,"$1_="+x);d.url=y+(y===d.url?(bN.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bV,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bE,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq,cr=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cv(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cm.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=cn.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this),f.isFunction(d.old)&&d.old.call(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function h(a){return d.step(a)}var d=this,e=f.fx,g;this.startTime=cq||cs(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,h.elem=this.elem,h()&&f.timers.push(h)&&!co&&(cr?(co=1,g=function(){co&&(cr(g),e.tick())},cr(g)):co=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cq||cs(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){return this[0]?parseFloat(f.css(this[0],d,"padding")):null},f.fn["outer"+c]=function(a){return this[0]?parseFloat(f.css(this[0],d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
\ No newline at end of file
diff --git a/nop/site_media/jquerytools-1.2.5/jquery.tools.min.js b/nop/site_media/jquerytools-1.2.5/jquery.tools.min.js
deleted file mode 100644
index 913b943bf8731a6060fa88847f80954409edea6d..0000000000000000000000000000000000000000
--- a/nop/site_media/jquerytools-1.2.5/jquery.tools.min.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * jQuery Tools 1.2.5 - The missing UI library for the Web
- * 
- * [dateinput, rangeinput, validator]
- * 
- * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
- * 
- * http://flowplayer.org/tools/
- * 
- * File generated: Wed Sep 22 06:12:54 GMT 2010
- */
-(function(d){function R(a,c){return 32-(new Date(a,c,32)).getDate()}function S(a,c){a=""+a;for(c=c||2;a.length<c;)a="0"+a;return a}function T(a,c,j){var q=a.getDate(),h=a.getDay(),r=a.getMonth();a=a.getFullYear();var f={d:q,dd:S(q),ddd:B[j].shortDays[h],dddd:B[j].days[h],m:r+1,mm:S(r+1),mmm:B[j].shortMonths[r],mmmm:B[j].months[r],yy:String(a).slice(2),yyyy:a};c=c.replace(X,function(s){return s in f?f[s]:s.slice(1,s.length-1)});return Y.html(c).html()}function v(a){return parseInt(a,10)}function U(a,
-c){return a.getFullYear()===c.getFullYear()&&a.getMonth()==c.getMonth()&&a.getDate()==c.getDate()}function C(a){if(a){if(a.constructor==Date)return a;if(typeof a=="string"){var c=a.split("-");if(c.length==3)return new Date(v(c[0]),v(c[1])-1,v(c[2]));if(!/^-?\d+$/.test(a))return;a=v(a)}c=new Date;c.setDate(c.getDate()+a);return c}}function Z(a,c){function j(b,e,g){n=b;D=b.getFullYear();E=b.getMonth();G=b.getDate();g=g||d.Event("api");g.type="change";H.trigger(g,[b]);if(!g.isDefaultPrevented()){a.val(T(b,
-e.format,e.lang));a.data("date",b);h.hide(g)}}function q(b){b.type="onShow";H.trigger(b);d(document).bind("keydown.d",function(e){if(e.ctrlKey)return true;var g=e.keyCode;if(g==8){a.val("");return h.hide(e)}if(g==27)return h.hide(e);if(d(V).index(g)>=0){if(!w){h.show(e);return e.preventDefault()}var i=d("#"+f.weeks+" a"),t=d("."+f.focus),o=i.index(t);t.removeClass(f.focus);if(g==74||g==40)o+=7;else if(g==75||g==38)o-=7;else if(g==76||g==39)o+=1;else if(g==72||g==37)o-=1;if(o>41){h.addMonth();t=d("#"+
-f.weeks+" a:eq("+(o-42)+")")}else if(o<0){h.addMonth(-1);t=d("#"+f.weeks+" a:eq("+(o+42)+")")}else t=i.eq(o);t.addClass(f.focus);return e.preventDefault()}if(g==34)return h.addMonth();if(g==33)return h.addMonth(-1);if(g==36)return h.today();if(g==13)d(e.target).is("select")||d("."+f.focus).click();return d([16,17,18,9]).index(g)>=0});d(document).bind("click.d",function(e){var g=e.target;if(!d(g).parents("#"+f.root).length&&g!=a[0]&&(!L||g!=L[0]))h.hide(e)})}var h=this,r=new Date,f=c.css,s=B[c.lang],
-k=d("#"+f.root),M=k.find("#"+f.title),L,I,J,D,E,G,n=a.attr("data-value")||c.value||a.val(),m=a.attr("min")||c.min,p=a.attr("max")||c.max,w;if(m===0)m="0";n=C(n)||r;m=C(m||c.yearRange[0]*365);p=C(p||c.yearRange[1]*365);if(!s)throw"Dateinput: invalid language: "+c.lang;if(a.attr("type")=="date"){var N=d("<input/>");d.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(b,e){N.attr(e,a.attr(e))});a.replaceWith(N);a=N}a.addClass(f.input);var H=
-a.add(h);if(!k.length){k=d("<div><div><a/><div/><a/></div><div><div/><div/></div></div>").hide().css({position:"absolute"}).attr("id",f.root);k.children().eq(0).attr("id",f.head).end().eq(1).attr("id",f.body).children().eq(0).attr("id",f.days).end().eq(1).attr("id",f.weeks).end().end().end().find("a").eq(0).attr("id",f.prev).end().eq(1).attr("id",f.next);M=k.find("#"+f.head).find("div").attr("id",f.title);if(c.selectors){var z=d("<select/>").attr("id",f.month),A=d("<select/>").attr("id",f.year);M.html(z.add(A))}for(var $=
-k.find("#"+f.days),O=0;O<7;O++)$.append(d("<span/>").text(s.shortDays[(O+c.firstDay)%7]));d("body").append(k)}if(c.trigger)L=d("<a/>").attr("href","#").addClass(f.trigger).click(function(b){h.show();return b.preventDefault()}).insertAfter(a);var K=k.find("#"+f.weeks);A=k.find("#"+f.year);z=k.find("#"+f.month);d.extend(h,{show:function(b){if(!(a.attr("readonly")||a.attr("disabled")||w)){b=b||d.Event();b.type="onBeforeShow";H.trigger(b);if(!b.isDefaultPrevented()){d.each(W,function(){this.hide()});
-w=true;z.unbind("change").change(function(){h.setValue(A.val(),d(this).val())});A.unbind("change").change(function(){h.setValue(d(this).val(),z.val())});I=k.find("#"+f.prev).unbind("click").click(function(){I.hasClass(f.disabled)||h.addMonth(-1);return false});J=k.find("#"+f.next).unbind("click").click(function(){J.hasClass(f.disabled)||h.addMonth();return false});h.setValue(n);var e=a.offset();if(/iPad/i.test(navigator.userAgent))e.top-=d(window).scrollTop();k.css({top:e.top+a.outerHeight({margins:true})+
-c.offset[0],left:e.left+c.offset[1]});if(c.speed)k.show(c.speed,function(){q(b)});else{k.show();q(b)}return h}}},setValue:function(b,e,g){var i=v(e)>=-1?new Date(v(b),v(e),v(g||1)):b||n;if(i<m)i=m;else if(i>p)i=p;b=i.getFullYear();e=i.getMonth();g=i.getDate();if(e==-1){e=11;b--}else if(e==12){e=0;b++}if(!w){j(i,c);return h}E=e;D=b;g=new Date(b,e,1-c.firstDay);g=g.getDay();var t=R(b,e),o=R(b,e-1),P;if(c.selectors){z.empty();d.each(s.months,function(x,F){m<new Date(b,x+1,-1)&&p>new Date(b,x,0)&&z.append(d("<option/>").html(F).attr("value",
-x))});A.empty();i=r.getFullYear();for(var l=i+c.yearRange[0];l<i+c.yearRange[1];l++)m<=new Date(l+1,-1,1)&&p>new Date(l,0,0)&&A.append(d("<option/>").text(l));z.val(e);A.val(b)}else M.html(s.months[e]+" "+b);K.empty();I.add(J).removeClass(f.disabled);l=!g?-7:0;for(var u,y;l<(!g?35:42);l++){u=d("<a/>");if(l%7===0){P=d("<div/>").addClass(f.week);K.append(P)}if(l<g){u.addClass(f.off);y=o-g+l+1;i=new Date(b,e-1,y)}else if(l>=g+t){u.addClass(f.off);y=l-t-g+1;i=new Date(b,e+1,y)}else{y=l-g+1;i=new Date(b,
-e,y);if(U(n,i))u.attr("id",f.current).addClass(f.focus);else U(r,i)&&u.attr("id",f.today)}m&&i<m&&u.add(I).addClass(f.disabled);p&&i>p&&u.add(J).addClass(f.disabled);u.attr("href","#"+y).text(y).data("date",i);P.append(u)}K.find("a").click(function(x){var F=d(this);if(!F.hasClass(f.disabled)){d("#"+f.current).removeAttr("id");F.attr("id",f.current);j(F.data("date"),c,x)}return false});f.sunday&&K.find(f.week).each(function(){var x=c.firstDay?7-c.firstDay:0;d(this).children().slice(x,x+1).addClass(f.sunday)});
-return h},setMin:function(b,e){m=C(b);e&&n<m&&h.setValue(m);return h},setMax:function(b,e){p=C(b);e&&n>p&&h.setValue(p);return h},today:function(){return h.setValue(r)},addDay:function(b){return this.setValue(D,E,G+(b||1))},addMonth:function(b){return this.setValue(D,E+(b||1),G)},addYear:function(b){return this.setValue(D+(b||1),E,G)},hide:function(b){if(w){b=d.Event();b.type="onHide";H.trigger(b);d(document).unbind("click.d").unbind("keydown.d");if(b.isDefaultPrevented())return;k.hide();w=false}return h},
-getConf:function(){return c},getInput:function(){return a},getCalendar:function(){return k},getValue:function(b){return b?T(n,b,c.lang):n},isOpen:function(){return w}});d.each(["onBeforeShow","onShow","change","onHide"],function(b,e){d.isFunction(c[e])&&d(h).bind(e,c[e]);h[e]=function(g){g&&d(h).bind(e,g);return h}});a.bind("focus click",h.show).keydown(function(b){var e=b.keyCode;if(!w&&d(V).index(e)>=0){h.show(b);return b.preventDefault()}return b.shiftKey||b.ctrlKey||b.altKey||e==9?true:b.preventDefault()});
-C(a.val())&&j(n,c)}d.tools=d.tools||{version:"1.2.5"};var W=[],Q,V=[75,76,38,39,74,72,40,37],B={};Q=d.tools.dateinput={conf:{format:"mm/dd/yy",selectors:false,yearRange:[-5,5],lang:"en",offset:[0,0],speed:0,firstDay:0,min:undefined,max:undefined,trigger:false,css:{prefix:"cal",input:"date",root:0,head:0,title:0,prev:0,next:0,month:0,year:0,days:0,body:0,weeks:0,today:0,current:0,week:0,off:0,sunday:0,focus:0,disabled:0,trigger:0}},localize:function(a,c){d.each(c,function(j,q){c[j]=q.split(",")});
-B[a]=c}};Q.localize("en",{months:"January,February,March,April,May,June,July,August,September,October,November,December",shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",days:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",shortDays:"Sun,Mon,Tue,Wed,Thu,Fri,Sat"});var X=/d{1,4}|m{1,4}|yy(?:yy)?|"[^"]*"|'[^']*'/g,Y=d("<a/>");d.expr[":"].date=function(a){var c=a.getAttribute("type");return c&&c=="date"||!!d(a).data("dateinput")};d.fn.dateinput=function(a){if(this.data("dateinput"))return this;
-a=d.extend(true,{},Q.conf,a);d.each(a.css,function(j,q){if(!q&&j!="prefix")a.css[j]=(a.css.prefix||"")+(q||j)});var c;this.each(function(){var j=new Z(d(this),a);W.push(j);j=j.getInput().data("dateinput",j);c=c?c.add(j):j});return c?c:this}})(jQuery);
-(function(e){function F(d,a){a=Math.pow(10,a);return Math.round(d*a)/a}function q(d,a){if(a=parseInt(d.css(a),10))return a;return(d=d[0].currentStyle)&&d.width&&parseInt(d.width,10)}function C(d){return(d=d.data("events"))&&d.onSlide}function G(d,a){function h(c,b,f,j){if(f===undefined)f=b/k*z;else if(j)f-=a.min;if(s)f=Math.round(f/s)*s;if(b===undefined||s)b=f*k/z;if(isNaN(f))return g;b=Math.max(0,Math.min(b,k));f=b/k*z;if(j||!n)f+=a.min;if(n)if(j)b=k-b;else f=a.max-f;f=F(f,t);var r=c.type=="click";
-if(D&&l!==undefined&&!r){c.type="onSlide";A.trigger(c,[f,b]);if(c.isDefaultPrevented())return g}j=r?a.speed:0;r=r?function(){c.type="change";A.trigger(c,[f])}:null;if(n){m.animate({top:b},j,r);a.progress&&B.animate({height:k-b+m.width()/2},j)}else{m.animate({left:b},j,r);a.progress&&B.animate({width:b+m.width()/2},j)}l=f;H=b;d.val(f);return g}function o(){if(n=a.vertical||q(i,"height")>q(i,"width")){k=q(i,"height")-q(m,"height");u=i.offset().top+k}else{k=q(i,"width")-q(m,"width");u=i.offset().left}}
-function v(){o();g.setValue(a.value!==undefined?a.value:a.min)}var g=this,p=a.css,i=e("<div><div/><a href='#'/></div>").data("rangeinput",g),n,l,u,k,H;d.before(i);var m=i.addClass(p.slider).find("a").addClass(p.handle),B=i.find("div").addClass(p.progress);e.each("min,max,step,value".split(","),function(c,b){c=d.attr(b);if(parseFloat(c))a[b]=parseFloat(c,10)});var z=a.max-a.min,s=a.step=="any"?0:a.step,t=a.precision;if(t===undefined)try{t=s.toString().split(".")[1].length}catch(I){t=0}if(d.attr("type")==
-"range"){var w=e("<input/>");e.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(c,b){w.attr(b,d.attr(b))});w.val(a.value);d.replaceWith(w);d=w}d.addClass(p.input);var A=e(g).add(d),D=true;e.extend(g,{getValue:function(){return l},setValue:function(c,b){o();return h(b||e.Event("api"),undefined,c,true)},getConf:function(){return a},getProgress:function(){return B},getHandle:function(){return m},getInput:function(){return d},step:function(c,
-b){b=b||e.Event();var f=a.step=="any"?1:a.step;g.setValue(l+f*(c||1),b)},stepUp:function(c){return g.step(c||1)},stepDown:function(c){return g.step(-c||-1)}});e.each("onSlide,change".split(","),function(c,b){e.isFunction(a[b])&&e(g).bind(b,a[b]);g[b]=function(f){f&&e(g).bind(b,f);return g}});m.drag({drag:false}).bind("dragStart",function(){o();D=C(e(g))||C(d)}).bind("drag",function(c,b,f){if(d.is(":disabled"))return false;h(c,n?b:f)}).bind("dragEnd",function(c){if(!c.isDefaultPrevented()){c.type=
-"change";A.trigger(c,[l])}}).click(function(c){return c.preventDefault()});i.click(function(c){if(d.is(":disabled")||c.target==m[0])return c.preventDefault();o();var b=m.width()/2;h(c,n?k-u-b+c.pageY:c.pageX-u-b)});a.keyboard&&d.keydown(function(c){if(!d.attr("readonly")){var b=c.keyCode,f=e([75,76,38,33,39]).index(b)!=-1,j=e([74,72,40,34,37]).index(b)!=-1;if((f||j)&&!(c.shiftKey||c.altKey||c.ctrlKey)){if(f)g.step(b==33?10:1,c);else if(j)g.step(b==34?-10:-1,c);return c.preventDefault()}}});d.blur(function(c){var b=
-e(this).val();b!==l&&g.setValue(b,c)});e.extend(d[0],{stepUp:g.stepUp,stepDown:g.stepDown});v();k||e(window).load(v)}e.tools=e.tools||{version:"1.2.5"};var E;E=e.tools.rangeinput={conf:{min:0,max:100,step:"any",steps:0,value:0,precision:undefined,vertical:0,keyboard:true,progress:false,speed:100,css:{input:"range",slider:"slider",progress:"progress",handle:"handle"}}};var x,y;e.fn.drag=function(d){document.ondragstart=function(){return false};d=e.extend({x:true,y:true,drag:true},d);x=x||e(document).bind("mousedown mouseup",
-function(a){var h=e(a.target);if(a.type=="mousedown"&&h.data("drag")){var o=h.position(),v=a.pageX-o.left,g=a.pageY-o.top,p=true;x.bind("mousemove.drag",function(i){var n=i.pageX-v;i=i.pageY-g;var l={};if(d.x)l.left=n;if(d.y)l.top=i;if(p){h.trigger("dragStart");p=false}d.drag&&h.css(l);h.trigger("drag",[i,n]);y=h});a.preventDefault()}else try{y&&y.trigger("dragEnd")}finally{x.unbind("mousemove.drag");y=null}});return this.data("drag",true)};e.expr[":"].range=function(d){var a=d.getAttribute("type");
-return a&&a=="range"||!!e(d).filter("input").data("rangeinput")};e.fn.rangeinput=function(d){if(this.data("rangeinput"))return this;d=e.extend(true,{},E.conf,d);var a;this.each(function(){var h=new G(e(this),e.extend(true,{},d));h=h.getInput().data("rangeinput",h);a=a?a.add(h):h});return a?a:this}})(jQuery);
-(function(e){function t(a,b,c){var k=a.offset().top,f=a.offset().left,l=c.position.split(/,?\s+/),p=l[0];l=l[1];k-=b.outerHeight()-c.offset[0];f+=a.outerWidth()+c.offset[1];if(/iPad/i.test(navigator.userAgent))k-=e(window).scrollTop();c=b.outerHeight()+a.outerHeight();if(p=="center")k+=c/2;if(p=="bottom")k+=c;a=a.outerWidth();if(l=="center")f-=(a+b.outerWidth())/2;if(l=="left")f-=a;return{top:k,left:f}}function y(a){function b(){return this.getAttribute("type")==a}b.key="[type="+a+"]";return b}function u(a,
-b,c){function k(g,d,i){if(!(!c.grouped&&g.length)){var j;if(i===false||e.isArray(i)){j=h.messages[d.key||d]||h.messages["*"];j=j[c.lang]||h.messages["*"].en;(d=j.match(/\$\d/g))&&e.isArray(i)&&e.each(d,function(m){j=j.replace(this,i[m])})}else j=i[c.lang]||i;g.push(j)}}var f=this,l=b.add(f);a=a.not(":button, :image, :reset, :submit");e.extend(f,{getConf:function(){return c},getForm:function(){return b},getInputs:function(){return a},reflow:function(){a.each(function(){var g=e(this),d=g.data("msg.el");
-if(d){g=t(g,d,c);d.css({top:g.top,left:g.left})}});return f},invalidate:function(g,d){if(!d){var i=[];e.each(g,function(j,m){j=a.filter("[name='"+j+"']");if(j.length){j.trigger("OI",[m]);i.push({input:j,messages:[m]})}});g=i;d=e.Event()}d.type="onFail";l.trigger(d,[g]);d.isDefaultPrevented()||q[c.effect][0].call(f,g,d);return f},reset:function(g){g=g||a;g.removeClass(c.errorClass).each(function(){var d=e(this).data("msg.el");if(d){d.remove();e(this).data("msg.el",null)}}).unbind(c.errorInputEvent||
-"");return f},destroy:function(){b.unbind(c.formEvent+".V").unbind("reset.V");a.unbind(c.inputEvent+".V").unbind("change.V");return f.reset()},checkValidity:function(g,d){g=g||a;g=g.not(":disabled");if(!g.length)return true;d=d||e.Event();d.type="onBeforeValidate";l.trigger(d,[g]);if(d.isDefaultPrevented())return d.result;var i=[];g.not(":radio:not(:checked)").each(function(){var m=[],n=e(this).data("messages",m),v=r&&n.is(":date")?"onHide.v":c.errorInputEvent+".v";n.unbind(v);e.each(w,function(){var o=
-this,s=o[0];if(n.filter(s).length){o=o[1].call(f,n,n.val());if(o!==true){d.type="onBeforeFail";l.trigger(d,[n,s]);if(d.isDefaultPrevented())return false;var x=n.attr(c.messageAttr);if(x){m=[x];return false}else k(m,s,o)}}});if(m.length){i.push({input:n,messages:m});n.trigger("OI",[m]);c.errorInputEvent&&n.bind(v,function(o){f.checkValidity(n,o)})}if(c.singleError&&i.length)return false});var j=q[c.effect];if(!j)throw'Validator: cannot find effect "'+c.effect+'"';if(i.length){f.invalidate(i,d);return false}else{j[1].call(f,
-g,d);d.type="onSuccess";l.trigger(d,[g]);g.unbind(c.errorInputEvent+".v")}return true}});e.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","),function(g,d){e.isFunction(c[d])&&e(f).bind(d,c[d]);f[d]=function(i){i&&e(f).bind(d,i);return f}});c.formEvent&&b.bind(c.formEvent+".V",function(g){if(!f.checkValidity(null,g))return g.preventDefault()});b.bind("reset.V",function(){f.reset()});a[0]&&a[0].validity&&a.each(function(){this.oninvalid=function(){return false}});if(b[0])b[0].checkValidity=
-f.checkValidity;c.inputEvent&&a.bind(c.inputEvent+".V",function(g){f.checkValidity(e(this),g)});a.filter(":checkbox, select").filter("[required]").bind("change.V",function(g){var d=e(this);if(this.checked||d.is("select")&&e(this).val())q[c.effect][1].call(f,d,g)});var p=a.filter(":radio").change(function(g){f.checkValidity(p,g)});e(window).resize(function(){f.reflow()})}e.tools=e.tools||{version:"1.2.5"};var z=/\[type=([a-z]+)\]/,A=/^-?[0-9]*(\.[0-9]+)?$/,r=e.tools.dateinput,B=/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,
-C=/^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,h;h=e.tools.validator={conf:{grouped:false,effect:"default",errorClass:"invalid",inputEvent:null,errorInputEvent:"keyup",formEvent:"submit",lang:"en",message:"<div/>",messageAttr:"data-message",messageClass:"error",offset:[0,0],position:"center right",singleError:false,speed:"normal"},messages:{"*":{en:"Please correct this value"}},localize:function(a,b){e.each(b,function(c,k){h.messages[c]=h.messages[c]||{};h.messages[c][a]=k})},
-localizeFn:function(a,b){h.messages[a]=h.messages[a]||{};e.extend(h.messages[a],b)},fn:function(a,b,c){if(e.isFunction(b))c=b;else{if(typeof b=="string")b={en:b};this.messages[a.key||a]=b}if(b=z.exec(a))a=y(b[1]);w.push([a,c])},addEffect:function(a,b,c){q[a]=[b,c]}};var w=[],q={"default":[function(a){var b=this.getConf();e.each(a,function(c,k){c=k.input;c.addClass(b.errorClass);var f=c.data("msg.el");if(!f){f=e(b.message).addClass(b.messageClass).appendTo(document.body);c.data("msg.el",f)}f.css({visibility:"hidden"}).find("p").remove();
-e.each(k.messages,function(l,p){e("<p/>").html(p).appendTo(f)});f.outerWidth()==f.parent().width()&&f.add(f.find("p")).css({display:"inline"});k=t(c,f,b);f.css({visibility:"visible",position:"absolute",top:k.top,left:k.left}).fadeIn(b.speed)})},function(a){var b=this.getConf();a.removeClass(b.errorClass).each(function(){var c=e(this).data("msg.el");c&&c.css({visibility:"hidden"})})}]};e.each("email,url,number".split(","),function(a,b){e.expr[":"][b]=function(c){return c.getAttribute("type")===b}});
-e.fn.oninvalid=function(a){return this[a?"bind":"trigger"]("OI",a)};h.fn(":email","Please enter a valid email address",function(a,b){return!b||B.test(b)});h.fn(":url","Please enter a valid URL",function(a,b){return!b||C.test(b)});h.fn(":number","Please enter a numeric value.",function(a,b){return A.test(b)});h.fn("[max]","Please enter a value smaller than $1",function(a,b){if(b===""||r&&a.is(":date"))return true;a=a.attr("max");return parseFloat(b)<=parseFloat(a)?true:[a]});h.fn("[min]","Please enter a value larger than $1",
-function(a,b){if(b===""||r&&a.is(":date"))return true;a=a.attr("min");return parseFloat(b)>=parseFloat(a)?true:[a]});h.fn("[required]","Please complete this mandatory field.",function(a,b){if(a.is(":checkbox"))return a.is(":checked");return!!b});h.fn("[pattern]",function(a){var b=new RegExp("^"+a.attr("pattern")+"$");return b.test(a.val())});e.fn.validator=function(a){var b=this.data("validator");if(b){b.destroy();this.removeData("validator")}a=e.extend(true,{},h.conf,a);if(this.is("form"))return this.each(function(){var c=
-e(this);b=new u(c.find(":input"),c,a);c.data("validator",b)});else{b=new u(this,this.eq(0).closest("form"),a);return this.data("validator",b)}}})(jQuery);
diff --git a/nop/site_media/nowplaying_form.js b/nop/site_media/nowplaying_form.js
deleted file mode 100644
index ce3d2aabfaf0e96d5319545d27723495f87b96f8..0000000000000000000000000000000000000000
--- a/nop/site_media/nowplaying_form.js
+++ /dev/null
@@ -1,12 +0,0 @@
-jQuery(document).ready(function() {
-    jQuery("#nop_date").dateinput({
-        format: 'yyyy-mm-dd',
-        firstDay: 1
-    });
-    jQuery("#nop_time").AnyTime_picker({
-        format: "%H:%i",
-        labelTitle: "Zeit",
-        labelHour: "Stunde",
-        labelMinute: "Minute"
-    });
-});
diff --git a/nop/templates/nop_form.html b/nop/templates/nop_form.html
deleted file mode 100644
index 2c5cb75092da75df7ed472e2f20e992a7cb9ad86..0000000000000000000000000000000000000000
--- a/nop/templates/nop_form.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<html>
-<head>
-  <title>Now Playing &mdash; Radio Helsinki - Freies Radio Graz</title>
-  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
-  <script type="text/javascript" src="/nop/static/jquery-1.6.1/jquery.min.js"></script>
-  <script type="text/javascript" src="/nop/static/jquerytools-1.2.5/jquery.tools.min.js"></script>
-  <script type="text/javascript" src="/nop/static/anytimec.js"></script>
-  <script type="text/javascript" src="/nop/static/nowplaying_form.js"></script>
-  <link rel="stylesheet" type="text/css" href="/nop/static/dateinput.css"/>
-  <link rel="stylesheet" type="text/css" href="/nop/static/anytimec.css"/>
-</head>
-<body>
-
-  <div id="content-main" class="show-detail">
-    <form action="/nop" method="get">
-      {{ form.as_table }}
-      <input type="submit" value="senden" />
-    </form>
-
-    {% if nowplaying %}
-    <ul class="nowplaying">
-      {% for track in nowplaying %}
-      <li>
-        {% if track.start or track.show %}
-          <span class="meta">
-            {% if track.start %}{{track.start}}{% endif %}
-            {% if track.start and track.show %},{% endif %}
-            {% if track.show %}Sendung {{track.show}}{% endif %}
-            {% if track.artist or track.title or track.album %}:{% endif %}
-          </span><br />
-        {% endif %}
-        {% if track.artist %}
-          <span class="artist">{{track.artist}}</span>
-        {% endif %}
-        <span class="track">
-        {% if track.artist and track.title or track.artist and track.album %}|{% endif %}
-        {% if track.title %}{{track.title}}{% endif %}
-        {% if track.title and track.album %}|{% endif %}
-        {% if track.album %}{{track.album}}{% endif %}
-        </span>
-      </li>
-      {% endfor %}
-    </ul>
-    {% endif %}
-  </div>
-
-</body>
-</html>
diff --git a/nop/urls.py b/nop/urls.py
deleted file mode 100644
index fb6774b804d254927a4d3699e1a6ddc0ff3e14d0..0000000000000000000000000000000000000000
--- a/nop/urls.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from django.conf.urls import url
-from django.views.static import serve
-
-from .views import get, get_current, nop_form
-
-import os
-
-NOP_SITE_MEDIA = os.path.join(os.path.dirname(__file__), 'site_media')
-
-urlpatterns = [
-    url(r'^get_current/?$', get_current),
-    url(r'^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<hour>\d{1,2})/(?P<minute>\d{1,2})/?$', get),
-    url(r'^$', nop_form),
-    url(r'^static/(?P<path>.*)$', serve, {'document_root': NOP_SITE_MEDIA}),
-]
\ No newline at end of file
diff --git a/nop/views.py b/nop/views.py
deleted file mode 100644
index 55a349b0b2e7738d7387e6b7933c27cd8a5fce37..0000000000000000000000000000000000000000
--- a/nop/views.py
+++ /dev/null
@@ -1,141 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from django.conf import settings
-from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
-from django.shortcuts import render_to_response
-from django.http import HttpResponse
-from django import forms
-from .models import Master, Standby, State
-from program.models import TimeSlot
-
-import json
-import time
-from datetime import datetime
-
-DB = 'nop'
-
-class NopForm(forms.Form):
-    date = forms.DateField(
-        required=True,
-        widget=forms.DateInput(
-            format='%Y-%m-%d',
-            attrs={'id': 'nop_date', 'class': 'date'}))
-    time = forms.TimeField(
-        required=True,
-        widget=forms.TimeInput(
-            format='%H:%M',
-            attrs={'id': 'nop_time', 'class': 'date'}))
-
-
-def _dtstring(dt):
-    return time.strftime('%Y-%m-%d %H:%M', dt)
-
-
-def _which(timestamp=None):
-    if timestamp:
-        res = State.objects.using(DB).filter(timestamp__lt=timestamp)[0]
-    else:
-        res = State.objects.using(DB).all()[0]
-    if not res or res.state == 'master':
-        return Master
-    else:
-        return Standby
-
-
-def _get_show(datetime=None):
-    try:
-        if datetime:
-            timeslot = TimeSlot.objects.get(start__lte=datetime,
-                                            end__gt=datetime)
-        else:
-            timeslot = TimeSlot.objects.get_or_create_current()
-    except (ObjectDoesNotExist, MultipleObjectsReturned):
-        return {'start': None, 'id': None, 'name': None}
-    else:
-        try:
-            note = timeslot.note
-        except ObjectDoesNotExist:
-            note = None
-
-        return {'start': _dtstring(timeslot.start.timetuple()),
-                'id': timeslot.show.id,
-                'name': timeslot.show.name,
-                'note': note}
-
-
-def _current():
-    artist = None
-    title = None
-    album = None
-    show = _get_show()
-
-    if show['id'] in settings.MUSIKPROG_IDS \
-            or (show['id'] in settings.SPECIAL_PROGRAM_IDS and not show['note']):
-        result = _which().objects.using(DB).filter(carttype__exact='pool')[0]
-        artist = result.artist
-        title = result.title
-        album = result.album
-
-    return {'show': show['name'],
-            'start': show['start'],
-            'artist': artist,
-            'title': title,
-            'album': album}
-
-
-def _bydate(year=None, month=None, day=None, hour=None, minute=None):
-    show = _get_show(datetime(year, month, day, hour, minute))
-
-    if show['id'] and show['id'] not in settings.MUSIKPROG_IDS:
-        return [{'show': show['name'],
-                 'start': show['start'],
-                 'artist': None,
-                 'title': None,
-                 'album': None}]
-    else:
-        ts = int(time.mktime((int(year), int(month), int(day), int(hour),
-                              int(minute), 0, 0, 0, -1))) * 1000000
-        result = _which(ts).objects.using(DB).filter(carttype__exact='pool').filter(timestamp__lt=ts)[:5]
-        return [{'show': show['name'],
-                 'start': _dtstring(time.localtime(item.timestamp//1000000)),
-                 'artist': item.artist,
-                 'title': item.title,
-                 'album': item.album} for item in result]
-
-
-def get_current(request):
-    response = json.dumps(_current())
-    return HttpResponse(response, content_type='application/json')
-
-
-def get(request, year=None, month=None, day=None, hour=None, minute=None):
-    response = json.dumps(_bydate(year, month, day, hour, minute))
-    return HttpResponse(response, content_type='application/json')
-
-
-def nop_form(request):
-    context = {}
-    date = None
-    time = None
-
-    if request.method == 'GET' \
-            and ('date' in request.GET or 'time' in request.GET):
-        form = NopForm(request.GET)
-
-        if form.is_valid():
-            date = form.cleaned_data['date']
-            time = form.cleaned_data['time']
-    else:
-        form = NopForm(initial={'date': datetime.date(datetime.now()),
-                                'time': datetime.time(datetime.now())})
-
-    if not date:
-        date = datetime.date(datetime.now())
-
-    if not time:
-        time = datetime.time(datetime.now())
-
-    result = _bydate(date.year, date.month, date.day, time.hour, time.minute)
-    context['nowplaying'] = result
-    context['form'] = form
-    return render_to_response('nop_form.html', context)
\ No newline at end of file
diff --git a/prepare.sh b/prepare.sh
index 0542405d178def25161a20c2d115036871794606..1cb3e1ac2616143e4b530dcfd4282657188fc459 100755
--- a/prepare.sh
+++ b/prepare.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 BASE_D=$(realpath "${BASH_SOURCE%/*}/")
 
-sudo docker run --rm -it -u $UID:$GID -v "$BASE_D":/srv aura/pv /srv/manage.py migrate
-sudo docker run --rm -it -u $UID:$GID -v "$BASE_D":/srv aura/pv bash -c "/srv/manage.py loaddata /srv/program/fixtures/*.yaml"
-sudo docker run --rm -it -u $UID:$GID -v "$BASE_D":/srv aura/pv /srv/manage.py createsuperuser --username equinox --email equinox@helsinki.at
-sudo docker run --rm -it -u $UID:$GID -v "$BASE_D":/srv aura/pv /srv/manage.py creatersakey
+sudo docker run --rm -it -u $UID:$GID -v "$BASE_D":/srv steering-django /srv/manage.py migrate
+sudo docker run --rm -it -u $UID:$GID -v "$BASE_D":/srv steering-django bash -c "/srv/manage.py loaddata /srv/fixtures/*/*.json"
+sudo docker run --rm -it -u $UID:$GID -v "$BASE_D":/srv steering-django /srv/manage.py createsuperuser --username equinox --email equinox@helsinki.at
+sudo docker run --rm -it -u $UID:$GID -v "$BASE_D":/srv steering-django /srv/manage.py creatersakey
diff --git a/profile/admin.py b/profile/admin.py
index 9ed1953731cec17bb0c646727bb8c07bd5fc5c1e..909b824e8da36a26f49d9d33e7ba56dfa09f44cc 100644
--- a/profile/admin.py
+++ b/profile/admin.py
@@ -1,4 +1,21 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2017-2018, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
 from django.contrib import admin
 from django.contrib.auth.admin import UserAdmin
@@ -6,6 +23,7 @@ from django.contrib.auth.models import User
 
 from .models import Profile
 
+
 class ProfileInline(admin.StackedInline):
     model = Profile
     can_delete = False
@@ -14,28 +32,29 @@ class ProfileInline(admin.StackedInline):
 
 
 class ProfileUserAdmin(UserAdmin):
-    inlines = (ProfileInline, )
-
+    inlines = (ProfileInline,)
 
     def get_queryset(self, request):
-        '''Let common users only edit their own profile'''
+        """Let common users only edit their own profile"""
         if not request.user.is_superuser:
             return super(UserAdmin, self).get_queryset(request).filter(pk=request.user.id)
 
         return super(UserAdmin, self).get_queryset(request)
 
     def get_readonly_fields(self, request, obj=None):
-        '''Limit field access for common users'''
+        """Limit field access for common users"""
         if not request.user.is_superuser:
-            return ('username', 'is_staff', 'is_superuser', 'is_active', 'date_joined', 'last_login', 'groups', 'user_permissions')
+            return (
+            'username', 'is_staff', 'is_superuser', 'is_active', 'date_joined', 'last_login', 'groups', 'user_permissions')
         return list()
 
     def get_inline_instances(self, request, obj=None):
-        '''Append profile fields to UserAdmin'''
+        """Append profile fields to UserAdmin"""
         if not obj:
             return list()
 
         return super(ProfileUserAdmin, self).get_inline_instances(request, obj)
 
+
 admin.site.unregister(User)
-admin.site.register(User, ProfileUserAdmin)
\ No newline at end of file
+admin.site.register(User, ProfileUserAdmin)
diff --git a/profile/migrations/0001_squashed.py b/profile/migrations/0001_squashed.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0e3632cfc0b65106bc182cc368695102da9a7e7
--- /dev/null
+++ b/profile/migrations/0001_squashed.py
@@ -0,0 +1,31 @@
+# Generated by Django 2.2.12 on 2020-11-21 01:34
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    replaces = [('profile', '0001_initial'), ('profile', '0002_auto_20171129_1828'), ('profile', '0003_auto_20171213_1737')]
+
+    initial = True
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Profile',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('cba_username', models.CharField(blank=True, help_text='Your username in CBA. This is necessary for uploading files to your account.', max_length=60, verbose_name='CBA Username')),
+                ('cba_user_token', models.CharField(blank=True, help_text='The CBA upload token for your account. This is NOT your password which you use to log into CBA!', max_length=255, verbose_name='CBA Token')),
+                ('user', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'db_table': 'profile',
+            },
+        ),
+    ]
diff --git a/profile/models.py b/profile/models.py
index 47ada47fcc55e8c184ecae2cc58f3b26fd9e8f9f..82c5650f13193b758de741e005e029be833db017 100644
--- a/profile/models.py
+++ b/profile/models.py
@@ -1,21 +1,33 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2017-2018, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
-from django.core.exceptions import ObjectDoesNotExist
-from django.db import models
 from django.contrib.auth.models import User
-from django.db.models.signals import post_save
-from django.dispatch import receiver
+from django.db import models
 from django.utils.translation import ugettext_lazy as _
-from versatileimagefield.fields import VersatileImageField, PPOIField
-from django.conf import settings
-import os
 
-from tinymce import models as tinymce_models
 
 class Profile(models.Model):
     user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile', editable=False)
-    cba_username = models.CharField(_("CBA Username"), blank=True, max_length=60, help_text=_("Your username in CBA. This is necessary for uploading files to your account."))
-    cba_user_token = models.CharField(_("CBA Token"), blank=True, max_length=255, help_text=_("The CBA upload token for your account. This is NOT your password which you use to log into CBA!"))
+    cba_username = models.CharField(_("CBA Username"), blank=True, max_length=60,
+                                    help_text=_("Your username in CBA. This is necessary for uploading files to your account."))
+    cba_user_token = models.CharField(_("CBA Token"), blank=True, max_length=255, help_text=_(
+        "The CBA upload token for your account. This is NOT your password which you use to log into CBA!"))
 
     def __str__(self):
         return self.user.username
@@ -24,4 +36,4 @@ class Profile(models.Model):
         db_table = 'profile'
 
     def save(self, *args, **kwargs):
-        super(Profile, self).save(*args, **kwargs)
\ No newline at end of file
+        super(Profile, self).save(*args, **kwargs)
diff --git a/profile/serializers.py b/profile/serializers.py
index 779162a6cd63dd01664fccc2d0d7be599bf90921..377894a8b9f88f3d0213a79e65917f512eb4cc2e 100644
--- a/profile/serializers.py
+++ b/profile/serializers.py
@@ -1,11 +1,28 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2017-2018, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
-from django.contrib.auth.models import User
 from rest_framework import serializers
+
 from profile.models import Profile
 
 
 class ProfileSerializer(serializers.ModelSerializer):
     class Meta:
         model = Profile
-        fields = '__all__'
\ No newline at end of file
+        fields = '__all__'
diff --git a/profile/urls.py b/profile/urls.py
index f5a1005d47036235fd5d9ef8b49584544e56f5d9..80529afe29b5bfcf1f5f49a7381b0afe829e7f95 100644
--- a/profile/urls.py
+++ b/profile/urls.py
@@ -1,11 +1,30 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2017-2018, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
 from django.contrib import admin
 from rest_framework import routers
 
+from program.views import APIUserViewSet
+
 admin.autodiscover()
 
 urlpatterns = []
 
 router = routers.DefaultRouter()
-router.register(r'users', APIUserViewSet)
\ No newline at end of file
+router.register(r'users', APIUserViewSet)
diff --git a/program/admin.py b/program/admin.py
index f69de36fce98db1eaf58d494a5e4fe29a9080061..91fbed9d9d61a8b69f247caf418a1436e5e703ba 100644
--- a/program/admin.py
+++ b/program/admin.py
@@ -1,15 +1,34 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from datetime import date, datetime, timedelta
 
-from django.core.exceptions import ObjectDoesNotExist
+from django.conf import settings
 from django.contrib import admin
-from django.utils.translation import ugettext_lazy as _
+from django.core.exceptions import ObjectDoesNotExist
 from django.shortcuts import render
-from django.conf import settings
+from django.utils import timezone
+from django.utils.translation import ugettext_lazy as _
 
-from .models import Language, Type, MusicFocus, Category, Topic, FundingCategory, Host, Note, RRule, Schedule, Show, TimeSlot
 from .forms import MusicFocusForm
-
-from datetime import date, datetime, time, timedelta
+from .models import Language, Type, MusicFocus, Category, Topic, FundingCategory, Host, Note, RRule, Schedule, Show, TimeSlot
 
 
 class ActivityFilter(admin.SimpleListFilter):
@@ -24,21 +43,21 @@ class ActivityFilter(admin.SimpleListFilter):
     def queryset(self, request, queryset):
         if self.parameter_name == 'has_timeslots':  # active/inactive Schedules
             if self.value() == 'yes':
-                return queryset.filter(until__gt=datetime.now()).distinct()
+                return queryset.filter(until__gt=timezone.now()).distinct()
             if self.value() == 'no':
-                return queryset.filter(until__lt=datetime.now()).distinct()
+                return queryset.filter(until__lt=timezone.now()).distinct()
 
         if self.parameter_name == 'has_schedules_timeslots':  # active/inactive Shows
             if self.value() == 'yes':
-                return queryset.filter(schedules__until__gt=datetime.now()).distinct()
+                return queryset.filter(schedules__until__gt=timezone.now()).distinct()
             if self.value() == 'no':
-                return queryset.filter(schedules__until__lt=datetime.now()).distinct()
+                return queryset.filter(schedules__until__lt=timezone.now()).distinct()
 
         if self.parameter_name == 'has_shows_schedules_timeslots':  # active/inactive Hosts
             if self.value() == 'yes':
-                return queryset.filter(shows__schedules__until__gt=datetime.now()).distinct()
+                return queryset.filter(shows__schedules__until__gt=timezone.now()).distinct()
             if self.value() == 'no':
-                return queryset.filter(shows__schedules__until__lt=datetime.now()).distinct()
+                return queryset.filter(shows__schedules__until__lt=timezone.now()).distinct()
 
 
 class ActiveSchedulesFilter(ActivityFilter):
@@ -84,7 +103,7 @@ class TopicAdmin(admin.ModelAdmin):
 
 
 class FundingCategoryAdmin(admin.ModelAdmin):
-    list_display = ('fundingcategory', 'abbrev', 'is_active' )
+    list_display = ('fundingcategory', 'abbrev', 'is_active')
     list_filter = ('is_active',)
     prepopulated_fields = {'slug': ('fundingcategory',)}
 
@@ -104,16 +123,15 @@ class HostAdmin(admin.ModelAdmin):
 class NoteAdmin(admin.ModelAdmin):
     date_hierarchy = 'start'
     list_display = ('title', 'show', 'start', 'status', 'user')
-    fields = (( 'show', 'timeslot'), 'title', 'slug', 'summary', 'content', 'image', 'host', 'status', 'cba_id')
+    fields = (('show', 'timeslot'), 'title', 'slug', 'summary', 'content', 'image', 'host', 'status', 'cba_id')
     prepopulated_fields = {'slug': ('title',)}
     list_filter = ('status',)
     ordering = ('timeslot',)
     save_as = True
 
     class Media:
-        js = [ settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
-               settings.MEDIA_URL + 'js/note_change.js', ]
-
+        js = [settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
+              settings.MEDIA_URL + 'js/note_change.js', ]
 
     def get_queryset(self, request):
         if request.user.is_superuser:
@@ -124,10 +142,9 @@ class NoteAdmin(admin.ModelAdmin):
 
         return super(NoteAdmin, self).get_queryset(request).filter(show__in=shows)
 
-
     def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
-        four_weeks_ago = datetime.now() - timedelta(weeks=4)
-        in_twelve_weeks = datetime.now() + timedelta(weeks=12)
+        four_weeks_ago = timezone.now() - timedelta(weeks=4)
+        in_twelve_weeks = timezone.now() + timedelta(weeks=12)
 
         if db_field.name == 'timeslot':
             # Adding/Editing a note: load timeslots of the user's shows into the dropdown
@@ -137,16 +154,16 @@ class NoteAdmin(admin.ModelAdmin):
             #
             # How to do this while not constraining the queryset?
             # Saving won't be possible otherwise, if queryset doesn't contain the selectable elements beforehand
-            #kwargs['queryset'] = TimeSlot.objects.filter(show=-1)
+            # kwargs['queryset'] = TimeSlot.objects.filter(show=-1)
 
             # Superusers see every timeslot for every show
             if request.user.is_superuser:
                 kwargs['queryset'] = TimeSlot.objects.filter(start__gt=four_weeks_ago,
-                                                             start__lt=in_twelve_weeks) # note__isnull=True
+                                                             start__lt=in_twelve_weeks)  # note__isnull=True
             # Users see timeslots of shows they own
             else:
                 kwargs['queryset'] = TimeSlot.objects.filter(show__in=request.user.shows.all(), start__gt=four_weeks_ago,
-                                                             start__lt=in_twelve_weeks) # note__isnull=True
+                                                             start__lt=in_twelve_weeks)  # note__isnull=True
 
         if db_field.name == 'show':
             # Adding/Editing a note: load user's shows into the dropdown
@@ -155,7 +172,6 @@ class NoteAdmin(admin.ModelAdmin):
             if not request.user.is_superuser:
                 kwargs['queryset'] = Show.objects.filter(pk__in=request.user.shows.all())
 
-
         if db_field.name == 'host':
             # Common users only see hosts of shows they own
             if not request.user.is_superuser:
@@ -163,7 +179,6 @@ class NoteAdmin(admin.ModelAdmin):
 
         return super(NoteAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
 
-
     def save_model(self, request, obj, form, change):
 
         # Save the creator when adding a note
@@ -184,6 +199,7 @@ class TimeSlotInline(admin.TabularInline):
     model = TimeSlot
     ordering = ('-end',)
 
+
 class TimeSlotAdmin(admin.ModelAdmin):
     model = TimeSlot
 
@@ -191,7 +207,10 @@ class TimeSlotAdmin(admin.ModelAdmin):
 class ScheduleAdmin(admin.ModelAdmin):
     actions = ('renew',)
     inlines = (TimeSlotInline,)
-    fields = (('rrule', 'byweekday'), ('tstart', 'tend'), 'dstart', 'until', 'is_repetition', ('add_days_no', 'add_business_days_only'), 'fallback_id', 'automation_id', )
+    fields = (
+        ('rrule', 'byweekday'), ('tstart', 'tend'), 'dstart', 'until', 'is_repetition',
+        ('add_days_no', 'add_business_days_only'),
+        'default_playlist_id', 'automation_id',)
     list_display = ('get_show_name', 'byweekday', 'rrule', 'tstart', 'tend', 'until')
     list_filter = (ActiveSchedulesFilter, 'byweekday', 'rrule', 'is_repetition')
     ordering = ('byweekday', 'dstart')
@@ -207,10 +226,12 @@ class ScheduleAdmin(admin.ModelAdmin):
         else:
             message = _("%s schedule were renewed until %s") % (renewed, until)
         self.message_user(request, message)
+
     renew.short_description = _("Renew selected schedules")
 
     def get_show_name(self, obj):
         return obj.show.name
+
     get_show_name.admin_order_field = 'show'
     get_show_name.short_description = "Show"
 
@@ -231,16 +252,14 @@ class ShowAdmin(admin.ModelAdmin):
     fields = (
         'predecessor', 'type', 'name', 'slug', 'image', 'logo', 'short_description', 'description',
         'email', 'website', 'hosts', 'owners', 'language', 'category', 'fundingcategory', 'topic',
-        'musicfocus', 'fallback_id', 'cba_series_id', 'is_active', 'is_public'
+        'musicfocus', 'default_playlist_id', 'cba_series_id', 'is_active', 'is_public'
     )
 
-
     class Media:
-        js = [ settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
-               settings.MEDIA_URL + 'js/show_change.js', ]
-
-        css = { 'all': ('/program/styles.css',) }
+        js = [settings.MEDIA_URL + 'js/calendar/lib/moment.min.js',
+              settings.MEDIA_URL + 'js/show_change.js', ]
 
+        css = {'all': ('/program/styles.css',)}
 
     def get_queryset(self, request):
         if request.user.is_superuser:
@@ -252,17 +271,15 @@ class ShowAdmin(admin.ModelAdmin):
 
         return super(ShowAdmin, self).get_queryset(request).filter(pk__in=shows)
 
-
     def get_readonly_fields(self, request, obj=None):
-        '''Limit field access for common users'''
+        """Limit field access for common users"""
 
         if not request.user.is_superuser:
             # TODO: how to set field 'name' readonly although it's required?
-            return ('predecessor', 'type', 'hosts', 'owners', 'language', 'category', 'topic', 'musicfocus', 'fundingcategory')
+            return 'predecessor', 'type', 'hosts', 'owners', 'language', 'category', 'topic', 'musicfocus', 'fundingcategory'
 
         return list()
 
-
     def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
         try:
             show_id = int(request.get_full_path().split('/')[-2])
@@ -280,7 +297,6 @@ class ShowAdmin(admin.ModelAdmin):
 
         return super(ShowAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
 
-
     def formfield_for_manytomany(self, db_field, request, **kwargs):
 
         if db_field.name == 'hosts':
@@ -298,10 +314,8 @@ class ShowAdmin(admin.ModelAdmin):
         if db_field.name == 'musicfocus':
             kwargs["queryset"] = MusicFocus.objects.filter(is_active=True)
 
-
         return super(ShowAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)
 
-
     def save_formset(self, request, form, formset, change):
         """
         Is called after the "save show"-form or collision-form were submitted
@@ -337,7 +351,7 @@ class ShowAdmin(admin.ModelAdmin):
         max_steps = int(len(schedule_instances)) if len(schedule_instances) > 0 else 1
         step = 1
 
-        if request.POST.get('step') == None:
+        if request.POST.get('step') is None:
             # First save-show submit
 
             # Generate thumbnails
@@ -346,7 +360,7 @@ class ShowAdmin(admin.ModelAdmin):
                     thumbnail = form.instance.image.crop[size].name
 
             # Save show data only
-            form.save();
+            form.save()
 
             # Delete schedules (as well as related timeslots and notes) if flagged as such
             for obj in formset.deleted_objects:
@@ -361,10 +375,10 @@ class ShowAdmin(admin.ModelAdmin):
 
             step = int(request.POST.get('step'))
 
-            if request.POST.get('num_inputs') != None and int(request.POST.get('num_inputs')) > 0:
+            if request.POST.get('num_inputs') is not None and int(request.POST.get('num_inputs')) > 0:
                 print("Resolving conflicts...")
 
-                '''Declare and retrieve variables'''
+                # Declare and retrieve variables
 
                 # Either datetimes as string (e.g. '2017-01-01 00:00:00 - 2017-01-01 01:00:00') to create
                 # or ints of colliding timeslots to keep otherwise
@@ -399,32 +413,34 @@ class ShowAdmin(admin.ModelAdmin):
                 tstart = datetime.strptime(request.POST.get('ps_save_tstart'), '%H:%M').time()
                 tend = datetime.strptime(request.POST.get('ps_save_tend'), '%H:%M').time()
                 dstart = datetime.strptime(request.POST.get('ps_save_dstart'), '%Y-%m-%d').date()
-                if dstart < datetime.today().date(): # Create or delete upcoming timeslots only
-                    dstart = datetime.today().date()
+                if dstart < timezone.now().date():  # Create or delete upcoming timeslots only
+                    dstart = timezone.now().date()
                 until = datetime.strptime(request.POST.get('ps_save_until'), '%Y-%m-%d').date()
                 is_repetition = request.POST.get('ps_save_is_repetition')
-                automation_id = int(request.POST.get('ps_save_automation_id')) if request.POST.get('ps_save_automation_id') != 'None' else 0
-                fallback_id = int(request.POST.get('ps_save_fallback_id')) if request.POST.get('ps_save_fallback_id') != 'None' else 0
-                add_days_no = int(request.POST.get('ps_save_add_days_no')) if request.POST.get('ps_save_add_days_no') != 'None' and int(request.POST.get('ps_save_add_days_no')) > 0 else None
+                automation_id = int(request.POST.get('ps_save_automation_id')) if request.POST.get(
+                    'ps_save_automation_id') != 'None' else 0
+                default_playlist_id = int(request.POST.get('ps_save_default_playlist_id')) if request.POST.get(
+                    'ps_save_default_playlist_id') != 'None' else 0
+                add_days_no = int(request.POST.get('ps_save_add_days_no')) if request.POST.get(
+                    'ps_save_add_days_no') != 'None' and int(request.POST.get('ps_save_add_days_no')) > 0 else None
                 add_business_days_only = request.POST.get('ps_save_add_business_days_only')
 
                 # Put timeslot POST vars into lists with same indices
                 for i in range(num_inputs):
                     resolved_ts = request.POST.get('resolved_timeslots[' + str(i) + ']')
-                    if resolved_ts != None:
-                        resolved_timeslots.append( resolved_ts )
-                        create_timeslots.append( request.POST.get('create_timeslots[' + str(i) + ']') ) # May contain None
-                        collisions.append( request.POST.get('collisions[' + str(i) + ']') ) # May contain None
+                    if resolved_ts:
+                        resolved_timeslots.append(resolved_ts)
+                        create_timeslots.append(request.POST.get('create_timeslots[' + str(i) + ']'))  # May contain None
+                        collisions.append(request.POST.get('collisions[' + str(i) + ']'))  # May contain None
                     else:
                         num_inputs -= 1
 
-
-                '''Prepare resolved timeslots'''
+                # Prepare resolved timeslots
 
                 # Separate timeslots to delete from those to create
                 keep_collisions = []
                 for x in range(num_inputs):
-                    if resolved_timeslots[x] == None or resolved_timeslots[x].isdigit():
+                    if resolved_timeslots[x] is None or resolved_timeslots[x].isdigit():
                         # If it's a digit, keep the existing timeslot by preventing the new one from being created
                         create_timeslots[x] = None
                         keep_collisions.append(int(collisions[x]))
@@ -434,12 +450,12 @@ class ShowAdmin(admin.ModelAdmin):
                             delete_timeslots.add(int(collisions[x]))
 
                 # Collect IDs of upcoming timeslots of the same schedule to delete except those in keep_collision
-                if schedule_id != None:
-                    for ts in TimeSlot.objects.filter(start__gte=dstart,end__lte=until,schedule_id=schedule_id).exclude(pk__in=keep_collisions).values_list('id', flat=True):
+                if schedule_id:
+                    for ts in TimeSlot.objects.filter(start__gte=dstart, end__lte=until, schedule_id=schedule_id).exclude(
+                            pk__in=keep_collisions).values_list('id', flat=True):
                         delete_timeslots.add(ts)
 
-
-                '''Save schedule'''
+                # Save schedule
 
                 new_schedule = Schedule(pk=schedule_id,
                                         rrule=rrule,
@@ -451,7 +467,7 @@ class ShowAdmin(admin.ModelAdmin):
                                         until=until,
                                         is_repetition=is_repetition,
                                         automation_id=automation_id,
-                                        fallback_id=fallback_id,
+                                        default_playlist_id=default_playlist_id,
                                         add_days_no=add_days_no,
                                         add_business_days_only=add_business_days_only)
 
@@ -459,13 +475,12 @@ class ShowAdmin(admin.ModelAdmin):
                 if len(resolved_timeslots) > 0:
                     new_schedule.save()
 
-
-                '''Relink notes to existing timeslots and prepare those to be linked'''
+                # Relink notes to existing timeslots and prepare those to be linked
 
                 # Relink notes with existing timeslot ids
                 for i in range(num_ntids):
                     try:
-                        note = Note.objects.get(pk=int(request.POST.get('ntids[' +  str(i) + '][note_id]')))
+                        note = Note.objects.get(pk=int(request.POST.get('ntids[' + str(i) + '][note_id]')))
                         note.timeslot_id = int(request.POST.get('ntids[' + str(i) + '][id]'))
                         note.save(update_fields=["timeslot_id"])
                         print("Rewrote note " + str(note.id) + "...to timeslot_id " + str(note.timeslot_id))
@@ -476,23 +491,24 @@ class ShowAdmin(admin.ModelAdmin):
                 note_indices = []
                 note_ids = []
                 for i in range(num_ntind):
-                    note_indices.append( int(request.POST.get('ntind[' + str(i) + '][id]')) )
-                    note_ids.append( int(request.POST.get('ntind[' +  str(i) + '][note_id]')) )
-
+                    note_indices.append(int(request.POST.get('ntind[' + str(i) + '][id]')))
+                    note_ids.append(int(request.POST.get('ntind[' + str(i) + '][note_id]')))
 
-                '''Database changes for resolved timeslots and relinked notes for newly created'''
+                # Database changes for resolved timeslots and relinked notes for newly created
 
                 for idx, ts in enumerate(create_timeslots):
-                    if ts != None:
+                    if ts:
                         start_end = ts.split(' - ')
                         # Only create upcoming timeslots
-                        if datetime.strptime(start_end[0], "%Y-%m-%d %H:%M:%S") > datetime.today():
-                            timeslot_created = TimeSlot.objects.create(schedule=new_schedule, is_repetition=new_schedule.is_repetition, start=start_end[0], end=start_end[1])
+                        if datetime.strptime(start_end[0], "%Y-%m-%d %H:%M:%S") > timezone.now():
+                            timeslot_created = TimeSlot.objects.create(schedule=new_schedule,
+                                                                       is_repetition=new_schedule.is_repetition,
+                                                                       start=start_end[0], end=start_end[1])
 
                             # Link a note to the new timeslot
                             if idx in note_indices:
-                                note_idx = note_indices.index( idx ) # Get the note_id's index...
-                                note_id = note_ids[note_idx] # ...which contains the note_id to relate to
+                                note_idx = note_indices.index(idx)  # Get the note_id's index...
+                                note_id = note_ids[note_idx]  # ...which contains the note_id to relate to
 
                                 try:
                                     note = Note.objects.get(pk=note_id)
@@ -506,14 +522,10 @@ class ShowAdmin(admin.ModelAdmin):
                 for timeslot_id in delete_timeslots:
                     TimeSlot.objects.filter(pk=timeslot_id).delete()
 
-
         if step > max_steps:
             self.end_reached = True
 
-
-        '''
-        Everything below here is called when a new collision is loaded before being handed over to the client
-        '''
+        # Everything below here is called when a new collision is loaded before being handed over to the client
 
         # Generate timeslots from current schedule
         k = 1
@@ -532,32 +544,30 @@ class ShowAdmin(admin.ModelAdmin):
         notes = []
         for id in collisions:
             try:
-                notes.append( Note.objects.get(timeslot_id=id) )
+                notes.append(Note.objects.get(timeslot_id=id))
             except ObjectDoesNotExist:
                 pass
 
         self.schedule = schedule
         self.timeslots = timeslots
         self.collisions = collisions
-        self.num_collisions = len([ s for s in self.collisions if s != 'None']) # Number of real collisions displayed to the user
+        self.num_collisions = len(
+            [s for s in self.collisions if s != 'None'])  # Number of real collisions displayed to the user
         self.notes = notes
         self.showform = form
         self.schedulesform = formset
-        self.step = step + 1 # Becomes upcoming step
+        self.step = step + 1  # Becomes upcoming step
         self.max_steps = max_steps
 
         # Pass it on to response_add() or response_change()
         return self
 
-
-    def response_add(self, request, obj):
+    def response_add(self, request, obj, post_url_continue=None):
         return ShowAdmin.respond(self, request, obj)
 
-
     def response_change(self, request, obj):
         return ShowAdmin.respond(self, request, obj)
 
-
     def respond(self, request, obj):
         """
         Redirects to the show-change-form if no schedules changed or resolving has been finished (or any other form validation error occured)
@@ -567,14 +577,14 @@ class ShowAdmin(admin.ModelAdmin):
         # Never check for collisions if not superuser
         # Common users can't edit the formset, so save_formset() will never be called thus end_reached wasn't set yet
         if not request.user.is_superuser:
-           self.end_reached = True
+            self.end_reached = True
 
         if self.end_reached:
             return super(ShowAdmin, self).response_change(request, obj)
 
         timeslots_to_collisions = list(zip(self.timeslots, self.collisions))
 
-        return render(request, 'collisions.html', {'self' : self, 'obj': obj, 'request': request,
+        return render(request, 'collisions.html', {'self': self, 'obj': obj, 'request': request,
                                                    'timeslots': self.timeslots,
                                                    'collisions': self.collisions,
                                                    'schedule': self.schedule,
@@ -584,7 +594,7 @@ class ShowAdmin(admin.ModelAdmin):
                                                    'num_inputs': len(self.timeslots),
                                                    'step': self.step,
                                                    'max_steps': self.max_steps,
-                                                   'now': datetime.now(),
+                                                   'now': timezone.now(),
                                                    'num_collisions': self.num_collisions})
 
 
diff --git a/program/auth.py b/program/auth.py
index 958b9a741cfe0667d4faa748cdd203832016705e..17221ae5e93441891efd235cd04a765450babb1e 100644
--- a/program/auth.py
+++ b/program/auth.py
@@ -1,11 +1,28 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
+from oidc_provider.lib.utils.oauth2 import extract_access_token
+from oidc_provider.models import Token
 from rest_framework import authentication
 from rest_framework import exceptions
 
-from oidc_provider.models import Token
-from oidc_provider.lib.utils.oauth2 import extract_access_token
-
 
 class OidcOauth2Auth(authentication.BaseAuthentication):
     def authenticate(self, request):
@@ -23,4 +40,4 @@ class OidcOauth2Auth(authentication.BaseAuthentication):
         if oauth2_token.has_expired():
             raise exceptions.AuthenticationFailed("The oauth2 token has expired")
 
-        return oauth2_token.user, None
\ No newline at end of file
+        return oauth2_token.user, None
diff --git a/program/fixtures/categories.yaml b/program/fixtures/categories.yaml
deleted file mode 100644
index 12d5e59a0a2c9684815674443b80786d12a6d385..0000000000000000000000000000000000000000
--- a/program/fixtures/categories.yaml
+++ /dev/null
@@ -1,48 +0,0 @@
-- model: program.category
-  pk: 1
-  fields:
-    category: Interkulturell
-    abbrev: I
-    slug: interkulturell
-- model: program.category
-  pk: 2
-  fields:
-    category: Lokalbezug
-    abbrev: L
-    slug: lokalbezug
-- model: program.category
-  pk: 3
-  fields:
-    category: Minderheiten
-    abbrev: Mi
-    slug: minderheiten
-- model: program.category
-  pk: 4
-  fields:
-    category: Wiederholung
-    abbrev: W
-    slug: wiederholung
-- model: program.category
-  pk: 5
-  fields:
-    category: Mehr-/Fremdsprachig
-    abbrev: M
-    slug: mehr-fremdsprachig
-- model: program.category
-  pk: 6
-  fields:
-    category: Frauenschwerpunkt
-    abbrev: F
-    slug: frauenschwerpunkt
-- model: program.category
-  pk: 7
-  fields:
-    category: Österreichische Musik
-    abbrev: Ö
-    slug: osterreichische-musik
-- model: program.category
-  pk: 8
-  fields:
-    category: Sendungsübernahme
-    abbrev: U
-    slug: sendungsubernahme
\ No newline at end of file
diff --git a/program/fixtures/fundingcategories.yaml b/program/fixtures/fundingcategories.yaml
deleted file mode 100644
index e015f301502ab197b194e8c9f8f083c20bdb9f53..0000000000000000000000000000000000000000
--- a/program/fixtures/fundingcategories.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-- model: program.fundingcategory
-  pk: 1
-  fields:
-    fundingcategory: Standard
-    abbrev: S
-    slug: standard
\ No newline at end of file
diff --git a/program/fixtures/group_permissions.yaml b/program/fixtures/group_permissions.yaml
deleted file mode 100644
index 95191a376e7c0a0ae4d164f3f7a9feb4c6b0f5f5..0000000000000000000000000000000000000000
--- a/program/fixtures/group_permissions.yaml
+++ /dev/null
@@ -1,42 +0,0 @@
-- model: auth.group_permissions
-  pk: 1
-  fields:
-    id: 1
-    group_id: 1
-    permission_id: 35
-- model: auth.group_permissions
-  pk: 2
-  fields:
-    id: 2
-    group_id: 1
-    permission_id: 28
-- model: auth.group_permissions
-  pk: 3
-  fields:
-    id: 3
-    group_id: 1
-    permission_id: 29
-- model: auth.group_permissions
-  pk: 4
-  fields:
-    id: 4
-    group_id: 1
-    permission_id: 30
-- model: auth.group_permissions
-  pk: 5
-  fields:
-    id: 5
-    group_id: 1
-    permission_id: 8
-- model: auth.group_permissions
-  pk: 6
-  fields:
-    id: 6
-    group_id: 1
-    permission_id: 68
-- model: auth.group_permissions
-  pk: 7
-  fields:
-    id: 6
-    group_id: 1
-    permission_id: 23
\ No newline at end of file
diff --git a/program/fixtures/groups.yaml b/program/fixtures/groups.yaml
deleted file mode 100644
index da482957143e7beec7daf47d2edfee6aa8dec217..0000000000000000000000000000000000000000
--- a/program/fixtures/groups.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-- model: auth.group
-  pk: 1
-  fields:
-    id: 1
-    name: ProgrammmacherInnen
\ No newline at end of file
diff --git a/program/fixtures/hosts.yaml b/program/fixtures/hosts.yaml
deleted file mode 100644
index 4cccf3a45246916764a52b36b3cdc45e70805d61..0000000000000000000000000000000000000000
--- a/program/fixtures/hosts.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-- model: program.host
-  pk: 1
-  fields:
-    name: Musikredaktion
diff --git a/program/fixtures/languages.yaml b/program/fixtures/languages.yaml
deleted file mode 100644
index e34961fb4c2eebab45621ceb3d8b8f073ef961d9..0000000000000000000000000000000000000000
--- a/program/fixtures/languages.yaml
+++ /dev/null
@@ -1,192 +0,0 @@
-- model: program.language
-  pk: 1
-  fields:
-    name: Deutsch
-- model: program.language
-  pk: 2
-  fields:
-    name: Englisch
-- model: program.language
-  pk: 3
-  fields:
-    name: Spanisch
-- model: program.language
-  pk: 4
-  fields:
-    name: Polnisch
-- model: program.language
-  pk: 5
-  fields:
-    name: Farsi
-- model: program.language
-  pk: 6
-  fields:
-    name: Französisch
-- model: program.language
-  pk: 7
-  fields:
-    name: Slowenisch
-- model: program.language
-  pk: 8
-  fields:
-    name: Persisch
-- model: program.language
-  pk: 9
-  fields:
-    name: Arabisch
-- model: program.language
-  pk: 10
-  fields:
-    name: Türkisch
-- model: program.language
-  pk: 11
-  fields:
-    name: Japanisch
-- model: program.language
-  pk: 12
-  fields:
-    name: Italienisch
-- model: program.language
-  pk: 13
-  fields:
-    name: Tschechisch
-- model: program.language
-  pk: 14
-  fields:
-    name: Russisch
-- model: program.language
-  pk: 15
-  fields:
-    name: Chinesisch
-- model: program.language
-  pk: 16
-  fields:
-    name: Ungarisch
-- model: program.language
-  pk: 17
-  fields:
-    name: Serbisch
-- model: program.language
-  pk: 18
-  fields:
-    name: Portugiesisch
-- model: program.language
-  pk: 19
-  fields:
-    name: Kroatisch
-- model: program.language
-  pk: 20
-  fields:
-    name: Albanisch
-- model: program.language
-  pk: 21
-  fields:
-    name: Dari
-- model: program.language
-  pk: 22
-  fields:
-    name: Bosnisch
-- model: program.language
-  pk: 23
-  fields:
-    name: Kurdisch
-- model: program.language
-  pk: 24
-  fields:
-    name: Aserbaidschanisch
-- model: program.language
-  pk: 25
-  fields:
-    name: Slowakisch
-- model: program.language
-  pk: 26
-  fields:
-    name: Niederländisch
-- model: program.language
-  pk: 27
-  fields:
-    name: Bulgarisch
-- model: program.language
-  pk: 28
-  fields:
-    name: Somali
-- model: program.language
-  pk: 29
-  fields:
-    name: Tschetschenisch
-- model: program.language
-  pk: 30
-  fields:
-    name: Dänisch
-- model: program.language
-  pk: 31
-  fields:
-    name: Rumänisch
-- model: program.language
-  pk: 32
-  fields:
-    name: Thai
-- model: program.language
-  pk: 33
-  fields:
-    name: Finnisch
-- model: program.language
-  pk: 34
-  fields:
-    name: Romanes
-- model: program.language
-  pk: 35
-  fields:
-    name: Griechisch
-- model: program.language
-  pk: 36
-  fields:
-    name: Singhalesisch
-- model: program.language
-  pk: 37
-  fields:
-    name: Urdu
-- model: program.language
-  pk: 38
-  fields:
-    name: Estnisch
-- model: program.language
-  pk: 39
-  fields:
-    name: Mazedonisch
-- model: program.language
-  pk: 40
-  fields:
-    name: Hebräisch
-- model: program.language
-  pk: 41
-  fields:
-    name: Schwedisch
-- model: program.language
-  pk: 42
-  fields:
-    name: Lithauisch
-- model: program.language
-  pk: 43
-  fields:
-    name: Jiddisch
-- model: program.language
-  pk: 44
-  fields:
-    name: Isländisch
-- model: program.language
-  pk: 45
-  fields:
-    name: Litauisch
-- model: program.language
-  pk: 46
-  fields:
-    name: Amharisch
-- model: program.language
-  pk: 47
-  fields:
-    name: Norwegisch
-- model: program.language
-  pk: 48
-  fields:
-    name: Koreanisch
\ No newline at end of file
diff --git a/program/fixtures/musicfocus.yaml b/program/fixtures/musicfocus.yaml
deleted file mode 100644
index 90de1490deeced1ff2cd89fbcec78062e039f7a6..0000000000000000000000000000000000000000
--- a/program/fixtures/musicfocus.yaml
+++ /dev/null
@@ -1,60 +0,0 @@
-- model: program.musicfocus
-  pk: 1
-  fields:
-    focus: Jazz
-    abbrev: J
-    slug: jazz
-- model: program.musicfocus
-  pk: 2
-  fields:
-    focus: Volksmusik/Folk
-    abbrev: V
-    slug: volksmusik-folk
-- model: program.musicfocus
-  pk: 3
-  fields:
-    focus: Experimentelle Musik
-    abbrev: Ex
-    slug: expermentelle-musik
-- model: program.musicfocus
-  pk: 4
-  fields:
-    focus: Rock/Indie
-    abbrev: R
-    slug: rock-indie
-- model: program.musicfocus
-  pk: 5
-  fields:
-    focus: Metal/Hardrock
-    abbrev: M
-    slug: metal-hardrock
-- model: program.musicfocus
-  pk: 6
-  fields:
-    focus: Electronic
-    abbrev: E
-    slug: electronic
-- model: program.musicfocus
-  pk: 7
-  fields:
-    focus: Klassik
-    abbrev: K
-    slug: klassik
-- model: program.musicfocus
-  pk: 8
-  fields:
-    focus: Oldies
-    abbrev: O
-    slug: oldies
-- model: program.musicfocus
-  pk: 9
-  fields:
-    focus: Reggae/Ska
-    abbrev: Re
-    slug: reggae-ska
-- model: program.musicfocus
-  pk: 10
-  fields:
-    focus: Hiphop
-    abbrev: H
-    slug: hiphop
\ No newline at end of file
diff --git a/program/fixtures/rrules.yaml b/program/fixtures/rrules.yaml
deleted file mode 100644
index 462185e4e336766903fcc903c0d0eb7c72b45bbf..0000000000000000000000000000000000000000
--- a/program/fixtures/rrules.yaml
+++ /dev/null
@@ -1,81 +0,0 @@
-- model: program.rrule
-  pk: 1
-  fields:
-    name: einmalig
-    freq: 0
-    count: 1
-- model: program.rrule
-  pk: 2
-  fields:
-    name: täglich
-    freq: 3
-- model: program.rrule
-  pk: 3
-  fields:
-    name: werktäglich
-    freq: 3
-- model: program.rrule
-  pk: 4
-  fields:
-    name: wöchentlich
-    freq: 2
-    interval: 1
-- model: program.rrule
-  pk: 5
-  fields:
-    name: zweiwöchentlich
-    freq: 2
-    interval: 2
-- model: program.rrule
-  pk: 6
-  fields:
-    name: vierwöchentlich
-    freq: 2
-    interval: 4
-- model: program.rrule
-  pk: 7
-  fields:
-    name: gerade Kalenderwoche
-    freq: 2
-    interval: 1
-- model: program.rrule
-  pk: 8
-  fields:
-    name: ungerade Kalenderwoche
-    freq: 2
-    interval: 1
-- model: program.rrule
-  pk: 9
-  fields:
-    name: Jede 1. Woche im Monat
-    freq: 1
-    interval: 1
-    bysetpos: 1
-- model: program.rrule
-  pk: 10
-  fields:
-    name: Jede 2. Woche im Monat
-    freq: 1
-    interval: 1
-    bysetpos: 2
-- model: program.rrule
-  pk: 11
-  fields:
-    name: Jede 3. Woche im Monat
-    freq: 1
-    interval: 1
-    bysetpos: 3
-- model: program.rrule
-  pk: 12
-  fields:
-    name: Jede 4. Woche im Monat
-    freq: 1
-    interval: 1
-    bysetpos: 4
-- model: program.rrule
-  pk: 13
-  fields:
-    name: Jede 5. Woche im Monat
-    freq: 1
-    interval: 1
-    bysetpos: 5
\ No newline at end of file
diff --git a/program/fixtures/shows.yaml b/program/fixtures/shows.yaml
deleted file mode 100644
index 83e621f26eeb6158c0c3f72db5ab7476a3e3bd60..0000000000000000000000000000000000000000
--- a/program/fixtures/shows.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-- model: program.show
-  pk: 1
-  fields:
-    hosts: [1]
-    type: 3
-    fundingcategory: 1
-    name: Musikprogramm
-    slug: musikprogramm
-    description: Unmoderiertes Musikprogramm
-    short_description: Unmoderiertes Musikprogramm
-    email: musikredaktion@helsinki.at
-    created: 1970-01-01 00:00:00
-    last_updated: 1970-01-01 00:00:00
\ No newline at end of file
diff --git a/program/fixtures/topics.yaml b/program/fixtures/topics.yaml
deleted file mode 100644
index 7f98dc934d63d5924b24a4658baf205ba4838355..0000000000000000000000000000000000000000
--- a/program/fixtures/topics.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-- model: program.topic
-  pk: 1
-  fields:
-    topic: Politik/Gesellschaft
-    abbrev: P
-    slug: politik-gesellschaft
-- model: program.topic
-  pk: 2
-  fields:
-    topic: Natur/Klima/Tiere
-    abbrev: N
-    slug: natur-klima-tiere
-- model: program.topic
-  pk: 3
-  fields:
-    topic: Kultur/Kunst
-    abbrev: K
-    slug: kultur-kunst
-- model: program.topic
-  pk: 4
-  fields:
-    topic: Soziales
-    abbrev: S
-    slug: soziales
-- model: program.topic
-  pk: 5
-  fields:
-    topic: Wissenschaft/Philosophie
-    abbrev: W
-    slug: wissenschaft-philosophie
\ No newline at end of file
diff --git a/program/fixtures/types.yaml b/program/fixtures/types.yaml
deleted file mode 100644
index 7a9fb4b9cf85a2091a732b263f934d18e508d91e..0000000000000000000000000000000000000000
--- a/program/fixtures/types.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-- model: program.type
-  pk: 1
-  fields:
-    type: Talk
-    slug: talk
-- model: program.type
-  pk: 2
-  fields:
-    type: Musiksendung
-    slug: musiksendung
-- model: program.type
-  pk: 3
-  fields:
-    type: Unmoderiertes Musikprogramm
-    slug: unmoderiertes-musikprogramm
-- model: program.type
-  pk: 4
-  fields:
-    type: Feature/Magazin
-    slug: feature-magazin
-- model: program.type
-  pk: 5
-  fields:
-    type: Experimentell
-    slug: experimentell
-- model: program.type
-  pk: 6
-  fields:
-    type: Hörspiel/Literatur
-    slug: horspiel-literatur
-- model: program.type
-  pk: 7
-  fields:
-    type: Vortrag/Diskussion
-    slug: vortrag-diskussion
\ No newline at end of file
diff --git a/program/fixtures/user_groups.yaml b/program/fixtures/user_groups.yaml
deleted file mode 100644
index 82ce3739ec635d392758dcc485f5e9a4f2abddd3..0000000000000000000000000000000000000000
--- a/program/fixtures/user_groups.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-- model: auth.user_groups
-  pk: 1
-  fields:
-    id: 1
-    user_id: 2
-    group_id: 1
\ No newline at end of file
diff --git a/program/fixtures/users.yaml b/program/fixtures/users.yaml
deleted file mode 100644
index dff429418036ba80c087612bc10061f7cf24705c..0000000000000000000000000000000000000000
--- a/program/fixtures/users.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-- model: auth.user
-  pk: 1
-  fields:
-    id: 1
-    password: pbkdf2_sha256$36000$uMBrNYea7vcc$6599RKSDzRkpoO8lcOjOQI/O1ufPXphIYh10VNqZcYU=
-    last_login: NULL
-    is_superuser: 1
-    username: admin
-    is_staff: 1
-    is_active: 1
-    date_joined: 2018-01-01 00:00:00
-  pk: 2
-  fields:
-    id: 2
-    password: pbkdf2_sha256$36000$VVSM5LeZfBZM$w0XSHCrucEb7Oj1Qpjdy1SKq5KelpXSPiUXbxh3rWpM=
-    last_login: NULL
-    is_superuser: 0
-    username: pm1
-    is_staff: 1
-    is_active: 1
-    date_joined: 2018-01-01 00:00:00
\ No newline at end of file
diff --git a/program/forms.py b/program/forms.py
index e7334a4b2e564077d9c633c6969e3d96d38d32b1..aa3a907d7bbc23009f3a51cb5bce2602db309832 100644
--- a/program/forms.py
+++ b/program/forms.py
@@ -1,8 +1,25 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
-from django import forms
-from django.forms import ModelForm, ValidationError
 from django.core.files.images import get_image_dimensions
+from django.forms import ModelForm, ValidationError
 
 from program.models import MusicFocus, Category, Topic
 
@@ -48,4 +65,4 @@ class CategoryForm(FormWithButton):
 class TopicForm(FormWithButton):
     class Meta:
         model = Topic
-        fields = '__all__'
\ No newline at end of file
+        fields = '__all__'
diff --git a/program/management/commands/cleanup_defaultshow.py b/program/management/commands/cleanup_defaultshow.py
deleted file mode 100644
index f27c4093e31f5838c39799b9eab745e6a94a6a9b..0000000000000000000000000000000000000000
--- a/program/management/commands/cleanup_defaultshow.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from django.core.management.base import NoArgsCommand
-from django.db import transaction
-
-from program.models import Show, TimeSlot, Schedule
-
-
-class Command(NoArgsCommand):
-    help = 'removes default shows without note'
-
-    @transaction.commit_manually
-    def handle_noargs(self, **options):
-
-        default_show = Show.objects.get(pk=1)
-        try:
-            TimeSlot.objects.filter(show=default_show, note__isnull=True).delete()
-            for schedule in Schedule.objects.filter(show=default_show):
-                if schedule.timeslots.count() == 0:
-                    schedule.delete()
-        except:
-            transaction.rollback()
-        else:
-            transaction.commit()
\ No newline at end of file
diff --git a/program/management/commands/create_oidc_client.py b/program/management/commands/create_oidc_client.py
new file mode 100644
index 0000000000000000000000000000000000000000..b60503caf737ae7ca2b30e827ba470d6281aa0d1
--- /dev/null
+++ b/program/management/commands/create_oidc_client.py
@@ -0,0 +1,101 @@
+from django.core.management.base import BaseCommand, CommandError
+import json, sys, random, string
+from oidc_provider.models import Client, ResponseType
+
+
+class Command(BaseCommand):
+    help = 'Sets up an OIDC client / relaying party. For details check out the' + \
+        'section on Relying Parties at https://django-oidc-provider.readthedocs.io'
+
+    def add_arguments(self, parser):
+        parser.add_argument('name', type=str,
+            help='A label that you associate with this client')
+        parser.add_argument('client_type', type=str, choices=['public', 'confidential'],
+            help='The type of client can be either public or confidential')
+        parser.add_argument('--no-require-consent', dest='require_consent', action='store_false',
+            help='By default user consent is required. Use this to skip user consent.')
+        parser.add_argument('--no-reuse-consent', dest='reuse_consent', action='store_false',
+            help='By default user consent will be reused. Use this if the user should provide consent on every login.')
+        parser.set_defaults(require_consent=True, reuse_consent=True)
+        parser.add_argument('-u', '--redirect-uri', type=str, action='append',
+            help='Redirect URI after successful authentication. Can be used more than once.')
+        parser.add_argument('-p', '--post-logout-redirect', type=str, action='append',
+            help='Post logout redirect URI. Can be used more than once.')
+        parser.add_argument('-s', '--scope', type=str, action='append',
+            help='Authorized scope values for this client. Can be used more than once.')
+        parser.add_argument('-r', dest='response_types', action='append',
+            choices=['code', 'id_token', 'id_token token', 'code token', 'code id_token', 'code id_token token'],
+            help='The type of response the client will get.')
+        parser.add_argument('-i', '--id-only', dest='id_only', action='store_true',
+            help='Do not print anything else then the ID of the newly created client '+\
+                 '(and the client secret in case of confidential clients).')
+        parser.set_defaults(id_only=False)
+
+
+    def handle(self, *args, **options):
+        # generate a new client ID and secret
+        client_id = False
+        counter = 0
+        while not client_id:
+            client_id = random.randint(100000, 999999)
+            counter += 1
+            if counter > 10000:
+                raise CommandError('Could not find a free client_id. Already'+\
+                    ' tried 10000 times. There seems to be something seriously'+\
+                    ' wrong with your setup. Please inspect manually.')
+            try:
+                Client.objects.get(client_id=client_id)
+            except Client.DoesNotExist:
+                pass
+            else:
+                client_id = False
+
+        client_secret = ''
+        if options['client_type'] == 'confidential':
+            client_secret = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(32))
+
+        # initialize lists if no option was provided
+        if options['redirect_uri'] is None:
+            options['redirect_uri'] = []
+        if options['post_logout_redirect'] is None:
+            options['post_logout_redirect'] = []
+        if options['scope'] is None:
+            options['scope'] = []
+
+        if not options["id_only"]:
+            self.stdout.write(f'Creating client with name {options["name"]}')
+        try:
+            c = Client(
+                client_id=client_id,
+                client_secret=client_secret,
+                name=options['name'], client_type=options['client_type'],
+                redirect_uris=options['redirect_uri'],
+                require_consent=options['require_consent'],
+                reuse_consent=options['reuse_consent'],
+                post_logout_redirect_uris=options['post_logout_redirect'],
+                scope=options['scope'],
+            )
+            c.save()
+        except:
+            raise CommandError('Could not create an OpenID connect client' +\
+                f' due to the following error: {sys.exc_info()}')
+
+
+        if options['response_types']:
+            try:
+                for r_value in options['response_types']:
+                    r = ResponseType.objects.get(value=r_value)
+                    c.response_types.add(r)
+            except:
+                raise CommandError('Client was stored, but could not set response_types'+\
+                    f' due to the following error: {sys.exc_info()}')
+
+        if options["id_only"]:
+            if options['client_type'] == 'confidential':
+                self.stdout.write(f'{c.client_id} {c.client_secret}')
+            else:
+                self.stdout.write(f'{c.client_id}')
+        else:
+            self.stdout.write(f'Successfully created new OIDC client, with ID: {c.client_id}')
+            if options['client_type'] == 'confidential':
+                self.stdout.write(f'The secret for this confidential client is: {c.client_secret}')
diff --git a/program/management/commands/importhosts.py b/program/management/commands/importhosts.py
deleted file mode 100644
index a0b92923d7f722aaa888edddd8528706dcf82b1e..0000000000000000000000000000000000000000
--- a/program/management/commands/importhosts.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from django.core.management.base import NoArgsCommand
-
-import MySQLdb
-
-from program.models import Host
-
-USER = 'helsinki'
-PASSWD = 'helsinki'
-DB = 'helsinki'
-
-
-class Command(NoArgsCommand):
-    help = 'Import hosts from current program'
-
-    def handle_noargs(self, **options):
-        connection = MySQLdb.connect(user=USER, passwd=PASSWD, db=DB)
-        cursor = connection.cursor()
-
-        cursor.execute("""SELECT DISTINCT macher
-FROM sendungen
-WHERE letzter_termin > current_date AND macher != '' AND titel NOT LIKE 'Musikprogramm'""")
-
-        counter = 0
-
-        for row in cursor.fetchall():
-            for macher in row[0].split(','):
-                host = Host(name=macher.strip())
-                host.save()
-
-                counter += 1
-
-        cursor.close()
-        connection.close()
-
-        self.stdout.write(self.style.SUCCESS, F'{counter} hosts imported')
diff --git a/program/management/commands/importnotes.py b/program/management/commands/importnotes.py
deleted file mode 100644
index 91476e6f9e094fedda2a5bd1f092ab57aae06531..0000000000000000000000000000000000000000
--- a/program/management/commands/importnotes.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, ValidationError
-from django.core.management.base import NoArgsCommand
-from django.utils.html import strip_tags
-
-import MySQLdb
-
-from program.models import Note, Show, TimeSlot
-
-USER = 'helsinki'
-PASSWD = 'helsinki'
-DB = 'helsinki'
-
-
-class Command(NoArgsCommand):
-    help = 'Import notes from current program'
-
-    def handle_noargs(self, **options):
-        connection = MySQLdb.connect(user=USER, passwd=PASSWD, db=DB)
-        cursor = connection.cursor()
-
-        cursor.execute("""SELECT n.titel, n.datum, s.titel, n.notiz
-FROM notizen AS n JOIN sendungen AS s ON n.sendung_id=s.id
-WHERE n.sendung_id in (SELECT id FROM sendungen WHERE letzter_termin > current_date)""")
-
-        counter = 0
-        for ntitel, datum, stitel, notiz in cursor.fetchall():
-            ntitel = strip_tags(ntitel) if ntitel else strip_tags(stitel)
-            stitel = strip_tags(stitel)
-            notiz = strip_tags(notiz)
-
-            if stitel.endswith('(Wiederholung)'):
-                stitel = stitel[:-15]
-
-            if datum:
-                year, month, day = datum.year, datum.month, datum.day
-                try:
-                    show = Show.objects.get(name=stitel)
-                except ObjectDoesNotExist:
-                    self.stdout.write(self.style.WARNING, f'show with name "{stitel}" not found')
-                else:
-                    try:
-                        timeslot = TimeSlot.objects.get(schedule__show=show, start__year=year, start__month=month,
-                                                        start__day=day)
-                    except ObjectDoesNotExist:
-                        self.stdout.write(self.style.WARNING, f'no timeslot found for sendung "{stitel}" and datum "{datum}"')
-                    except MultipleObjectsReturned:
-                        self.stdout.write(self.style.WARNING, f'multiple timeslots found for sendung "{stitel}" and datum "{datum}"')
-                    else:
-                        note = Note(timeslot=timeslot, title=ntitel, content=notiz)
-                        try:
-                            note.validate_unique()
-                        except ValidationError:
-                            self.stdout.write(self.style.WARNING, f'note already imported for show "{stitel}" and datum "{datum}"')
-                        else:
-                            try:
-                                note.save()
-                            except:
-                                self.stdout.write(self.style.ERROR, f'could not save note "{ntitel}" for show "{stitel}" and datum "{datum}"')
-                            else:
-                                counter += 1
-
-        cursor.close()
-        connection.close()
-
-        self.stdout.write(self.style.SUCCESS, f'{counter} notes imported')
diff --git a/program/management/commands/importprogramslots.py b/program/management/commands/importprogramslots.py
deleted file mode 100644
index 8ce8a2bdd80084202bc75e37feedfff5098fea47..0000000000000000000000000000000000000000
--- a/program/management/commands/importprogramslots.py
+++ /dev/null
@@ -1,98 +0,0 @@
-from django.core.exceptions import ObjectDoesNotExist
-from django.core.management.base import NoArgsCommand
-from django.utils.html import strip_tags
-
-from datetime import time
-import MySQLdb
-
-from program.models import Show, Schedule, RRule
-
-USER = 'helsinki'
-PASSWD = 'helsinki'
-DB = 'helsinki'
-
-RRULES = {
-    0: RRule.objects.get(pk=1),
-    7: RRule.objects.get(pk=3),
-    14: RRule.objects.get(pk=4),
-    28: RRule.objects.get(pk=5)
-}
-
-
-class Command(NoArgsCommand):
-    help = 'Import schedules from the current program'
-
-    def handle_noargs(self, **options):
-        connection = MySQLdb.connect(user=USER, passwd=PASSWD, db=DB)
-        cursor = connection.cursor()
-
-        cursor.execute("""SELECT titel, beginn, ende, erster_termin, letzter_termin, rhytmus, termin
-FROM sendungen
-WHERE letzter_termin > current_date AND titel NOT LIKE 'Musikprogramm' AND titel NOT LIKE '%%(Wiederholung)'""")
-
-        counter = 0
-
-        for titel, beginn, ende, erster_termin, letzter_termin, rhytmus, termin in cursor.fetchall():
-            titel = strip_tags(titel)
-
-            hours, seconds = divmod(beginn.seconds, 3600)
-            minutes, seconds = divmod(seconds, 60)
-            tstart = time(hour=hours, minute=minutes, second=seconds)
-
-            hours, seconds = divmod(ende.seconds, 3600)
-            minutes, seconds = divmod(seconds, 60)
-            tend = time(hour=hours, minute=minutes, second=seconds)
-
-            try:
-                rrule = RRULES[rhytmus]
-                try:
-                    show = Show.objects.get(name=titel)
-                except ObjectDoesNotExist:
-                    self.stdout.write(self.style.NOTICE, f'show with name "{titel}" not found')
-                else:
-                    schedule = Schedule(rrule=rrule, byweekday=termin, show=show, dstart=erster_termin,
-                                        tstart=tstart, tend=tend, until=letzter_termin)
-                    try:
-                        schedule.save()
-                        counter += 1
-                    except:
-                        pass
-            except KeyError:
-                self.stdout.write(self.style.NOTICE, f'rhythmus "{rhytmus}" is not supported for sendung "{titel}"')
-
-        cursor.execute("""SELECT titel, beginn, ende, erster_termin, letzter_termin, rhytmus, termin
-FROM sendungen
-WHERE letzter_termin > current_date AND titel LIKE '%%(Wiederholung)'""")
-
-        for titel, beginn, ende, erster_termin, letzter_termin, rhytmus, termin in cursor.fetchall():
-            titel = strip_tags(titel[:-15])
-
-            hours, seconds = divmod(beginn.seconds, 3600)
-            minutes, seconds = divmod(seconds, 60)
-            tstart = time(hour=hours, minute=minutes, second=seconds)
-
-            hours, seconds = divmod(ende.seconds, 3600)
-            minutes, seconds = divmod(seconds, 60)
-            tend = time(hour=hours, minute=minutes, second=seconds)
-
-            try:
-                rrule = RRULES[rhytmus]
-                try:
-                    show = Show.objects.get(name=titel)
-                except ObjectDoesNotExist:
-                    self.stdout.write(self.style.WARNING, f'show with name "{titel}" not found')
-                else:
-                    schedule = Schedule(rrule=rrule, byweekday=termin, show=show, dstart=erster_termin,
-                                        tstart=tstart, tend=tend, until=letzter_termin, is_repetition=True)
-                    try:
-                        schedule.save()
-                        counter += 1
-                    except:
-                        pass
-            except KeyError:
-                self.stdout.write(self.style.WARNING, f'rhythmus "{rhytmus}" is not supported for sendung "{titel}"')
-
-        cursor.close()
-        connection.close()
-
-        self.stdout.write(self.style.SUCCESS, f'{counter} schedules imported')
diff --git a/program/management/commands/importshows.py b/program/management/commands/importshows.py
deleted file mode 100644
index cff3d434d8b29ab7692c1da57e2cb93292020e27..0000000000000000000000000000000000000000
--- a/program/management/commands/importshows.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
-from django.core.management.base import NoArgsCommand
-from django.template.defaultfilters import slugify
-from django.utils.html import strip_tags
-
-import MySQLdb
-
-from program.models import BroadcastFormat, Host, Show
-
-USER = 'helsinki'
-PASSWD = 'helsinki'
-DB = 'helsinki'
-
-TALK = BroadcastFormat.objects.get(pk=1)
-
-
-class Command(NoArgsCommand):
-    help = 'Import shows from the current program'
-
-    def handle_noargs(self, **options):
-        connection = MySQLdb.connect(user=USER, passwd=PASSWD, db=DB)
-        cursor = connection.cursor()
-
-        cursor.execute("""SELECT titel, beschreibung, web, macher
-FROM sendungen
-WHERE letzter_termin > current_date AND titel NOT LIKE 'Musikprogramm' AND titel NOT LIKE '%%(Wiederholung)'
-ORDER BY titel, beginn, ende""")
-
-        counter = 0
-
-        for titel, beschreibung, web, macher in cursor.fetchall():
-            titel = strip_tags(titel)
-            beschreibung = strip_tags(beschreibung)
-
-            slug = slugify(titel)
-
-            hosts = []
-
-            for macher in macher.split(','):
-                macher = macher.strip()
-                try:
-                    host = Host.objects.get(name=macher)
-                except MultipleObjectsReturned:
-                    self.stdout.write(self.style.NOTICE, f'multiple hosts with name "{macher}" found')
-                except ObjectDoesNotExist:
-                    self.stdout.write(self.style.NOTICE, f'host with name "{macher}" not found')
-                else:
-                    hosts.append(host)
-
-            try:
-                show = Show.objects.get(name=titel)
-                self.stdout.write(self.style.NOTICE, f'sendung "{titel}" already imported as show "{show}"')
-            except ObjectDoesNotExist:
-                show = Show(broadcastformat=TALK, name=titel, slug=slug, short_description='FIXME',
-                            description=beschreibung)
-                try:
-                    show.save()
-                    counter += 1
-                except:
-                    self.stdout.write(self.style.NOTICE, f'sendung "{titel}" could not be imported')
-                else:
-                    for h in hosts:
-                        show.hosts.add(h)
-                        show.save()
-
-        cursor.close()
-        connection.close()
-
-        self.stdout.write(self.style.SUCCESS, f'{counter} shows imported')
diff --git a/program/migrations/0001_squashed.py b/program/migrations/0001_squashed.py
new file mode 100644
index 0000000000000000000000000000000000000000..4cb32c530694e42fb9a26896c1c84ecd552c3bf4
--- /dev/null
+++ b/program/migrations/0001_squashed.py
@@ -0,0 +1,342 @@
+# Generated by Django 2.2.12 on 2020-11-21 01:34
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import tinymce.models
+import versatileimagefield.fields
+
+
+class Migration(migrations.Migration):
+
+    replaces = [('program', '0001_initial'), ('program', '0002_host_is_always_visible'), ('program', '0003_host_is_active'), ('program', '0004_show_is_active'), ('program', '0005_programslot_is_active'), ('program', '0006_note_remove_cba_entry_id'), ('program', '0007_show_remove_cba_series_id'), ('program', '0008_show_remove_automation_id'), ('program', '0009_host_remove_is_active'), ('program', '0010_show_remove_is_active'), ('program', '0011_programslot_remove_is_active'), ('program', '0012_auto_20180104_0005'), ('program', '0013_auto_20180124_1748'), ('program', '0014_auto_20180216_2000'), ('program', '0015_auto_20180218_1111'), ('program', '0016_auto_20180222_1253'), ('program', '0017_auto_20180314_1409'), ('program', '0018_auto_20190810_1146'), ('program', '0019_auto_20190810_1340'), ('program', '0020_auto_20190810_1341'), ('program', '0021_show_is_active'), ('program', '0022_show_is_public')]
+
+    initial = True
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Host',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=128, verbose_name='Name')),
+                ('email', models.EmailField(blank=True, max_length=254, verbose_name='E-Mail')),
+                ('website', models.URLField(blank=True, help_text='URL to your personal website.', verbose_name='Website')),
+                ('biography', tinymce.models.HTMLField(blank=True, help_text='Describe yourself and your fields of interest in a few sentences.', null=True, verbose_name='Biography')),
+                ('cba_url', models.URLField(blank=True, help_text='URL to your CBA profile.', verbose_name='CBA URL')),
+                ('dorftv_url', models.URLField(blank=True, help_text='URL to your dorfTV channel.', verbose_name='DorfTV URL')),
+                ('facebook_url', models.URLField(blank=True, help_text='URL to your Facebook profile.', verbose_name='Facebook URL')),
+                ('googleplus_url', models.URLField(blank=True, help_text='URL to your Google+ profile.', verbose_name='Google+ URL')),
+                ('height', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height')),
+                ('image', versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='host_images', verbose_name='Profile picture', width_field='width')),
+                ('linkedin_url', models.URLField(blank=True, help_text='URL to your LinkedIn profile.', verbose_name='LinkedIn URL')),
+                ('ppoi', versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI')),
+                ('twitter_url', models.URLField(blank=True, help_text='URL to your Twitter profile.', verbose_name='Twitter URL')),
+                ('width', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width')),
+                ('youtube_url', models.URLField(blank=True, help_text='URL to your Youtube channel.', verbose_name='Youtube URL')),
+                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+            ],
+            options={
+                'ordering': ('name',),
+                'verbose_name': 'Host',
+                'verbose_name_plural': 'Hosts',
+            },
+        ),
+        migrations.CreateModel(
+            name='MusicFocus',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('focus', models.CharField(max_length=32, verbose_name='Focus')),
+                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
+                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
+                ('button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image')),
+                ('button_hover', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)')),
+                ('big_button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image')),
+                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+            ],
+            options={
+                'ordering': ('focus',),
+                'verbose_name': 'Music focus',
+                'verbose_name_plural': 'Music focus',
+            },
+        ),
+        migrations.CreateModel(
+            name='RRule',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=32, unique=True, verbose_name='Name')),
+                ('freq', models.IntegerField(choices=[(1, 'Monthly'), (2, 'Weekly'), (3, 'Daily')], verbose_name='Frequency')),
+                ('interval', models.IntegerField(default=1, verbose_name='Interval')),
+                ('bysetpos', models.IntegerField(blank=True, choices=[(1, 'First'), (2, 'Second'), (3, 'Third'), (4, 'Fourth'), (5, 'Fifth'), (-1, 'Last')], null=True, verbose_name='Set position')),
+                ('count', models.IntegerField(blank=True, null=True, verbose_name='Count')),
+            ],
+            options={
+                'ordering': ('pk',),
+                'verbose_name': 'Recurrence rule',
+                'verbose_name_plural': 'Recurrence rules',
+            },
+        ),
+        migrations.CreateModel(
+            name='Show',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(help_text="The show's name. Avoid a subtitle.", max_length=255, verbose_name='Name')),
+                ('slug', models.CharField(help_text='A simple to read URL for your show', max_length=255, unique=True, verbose_name='Slug')),
+                ('image', versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload an image to your show. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='show_images', verbose_name='Image', width_field='width')),
+                ('short_description', models.TextField(help_text='Describe your show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Short description')),
+                ('description', tinymce.models.HTMLField(blank=True, help_text='Describe your show in detail.', null=True, verbose_name='Description')),
+                ('email', models.EmailField(blank=True, help_text='The main contact email address for your show.', max_length=254, null=True, verbose_name='E-Mail')),
+                ('website', models.URLField(blank=True, help_text='Is there a website to your show? Type in its URL.', null=True, verbose_name='Website')),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('last_updated', models.DateTimeField(auto_now=True)),
+                ('hosts', models.ManyToManyField(blank=True, related_name='shows', to='program.Host', verbose_name='Hosts')),
+                ('musicfocus', models.ManyToManyField(blank=True, related_name='shows', to='program.MusicFocus', verbose_name='Music focus')),
+                ('owners', models.ManyToManyField(blank=True, related_name='shows', to=settings.AUTH_USER_MODEL, verbose_name='Owners')),
+                ('predecessor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='successors', to='program.Show', verbose_name='Predecessor')),
+                ('cba_series_id', models.IntegerField(blank=True, help_text='Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to your CBA archive. Find out your ID under https://cba.fro.at/series', null=True, verbose_name='CBA Series ID')),
+                ('fallback_id', models.IntegerField(blank=True, null=True, verbose_name='Fallback ID')),
+                ('height', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height')),
+                ('logo', models.ImageField(blank=True, null=True, upload_to='show_images', verbose_name='Logo')),
+                ('ppoi', versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI')),
+                ('width', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width')),
+            ],
+            options={
+                'ordering': ('slug',),
+                'verbose_name': 'Show',
+                'verbose_name_plural': 'Shows',
+            },
+        ),
+        migrations.CreateModel(
+            name='TimeSlot',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('start', models.DateTimeField(verbose_name='Start time')),
+                ('end', models.DateTimeField(verbose_name='End time')),
+                ('show', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='timeslots', to='program.Show')),
+                ('is_repetition', models.BooleanField(default=False, verbose_name='REP')),
+                ('memo', models.TextField(blank=True, verbose_name='Memo')),
+                ('playlist_id', models.IntegerField(null=True, verbose_name='Playlist ID')),
+            ],
+            options={
+                'ordering': ('start', 'end'),
+                'verbose_name': 'Time slot',
+                'verbose_name_plural': 'Time slots',
+            },
+        ),
+        migrations.CreateModel(
+            name='Category',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('category', models.CharField(max_length=32, verbose_name='Category')),
+                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
+                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
+                ('color', models.TextField(blank=True, max_length=7, verbose_name='Color')),
+                ('description', models.TextField(blank=True, verbose_name='Description')),
+                ('button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image')),
+                ('button_hover', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)')),
+                ('big_button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image')),
+                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+            ],
+            options={
+                'verbose_name': 'Category',
+                'verbose_name_plural': 'Categories',
+                'ordering': ('category',),
+            },
+        ),
+        migrations.CreateModel(
+            name='Language',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=32, verbose_name='Language')),
+                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+            ],
+            options={
+                'verbose_name': 'Language',
+                'verbose_name_plural': 'Languages',
+                'ordering': ('language',),
+            },
+        ),
+        migrations.CreateModel(
+            name='Schedule',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('byweekday', models.IntegerField(choices=[(0, 'Monday'), (1, 'Tuesday'), (2, 'Wednesday'), (3, 'Thursday'), (4, 'Friday'), (5, 'Saturday'), (6, 'Sunday')], verbose_name='Weekday')),
+                ('dstart', models.DateField(verbose_name='First date')),
+                ('tstart', models.TimeField(verbose_name='Start time')),
+                ('tend', models.TimeField(verbose_name='End time')),
+                ('until', models.DateField(verbose_name='Last date')),
+                ('is_repetition', models.BooleanField(default=False, verbose_name='Is repetition')),
+                ('fallback_id', models.IntegerField(blank=True, null=True, verbose_name='Fallback ID')),
+                ('automation_id', models.IntegerField(blank=True, null=True, verbose_name='Automation ID')),
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('rrule', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='program.RRule', verbose_name='Recurrence rule')),
+                ('show', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='program.Show', verbose_name='Show')),
+                ('add_business_days_only', models.BooleanField(default=False, verbose_name='Only add business days?')),
+                ('add_days_no', models.IntegerField(blank=True, null=True, verbose_name='Add days')),
+            ],
+            options={
+                'verbose_name': 'Schedule',
+                'verbose_name_plural': 'Schedules',
+                'ordering': ('dstart', 'tstart'),
+            },
+        ),
+        migrations.CreateModel(
+            name='Topic',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('topic', models.CharField(max_length=32, verbose_name='Topic')),
+                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
+                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
+                ('button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image')),
+                ('button_hover', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)')),
+                ('big_button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image')),
+                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+            ],
+            options={
+                'verbose_name': 'Topic',
+                'verbose_name_plural': 'Topics',
+                'ordering': ('topic',),
+            },
+        ),
+        migrations.CreateModel(
+            name='Type',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('type', models.CharField(max_length=32, verbose_name='Type')),
+                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
+                ('color', models.CharField(default='#ffffff', max_length=7, verbose_name='Color')),
+                ('text_color', models.CharField(default='#000000', max_length=7, verbose_name='Text color')),
+                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+            ],
+            options={
+                'verbose_name': 'Type',
+                'verbose_name_plural': 'Types',
+                'ordering': ('type',),
+            },
+        ),
+        migrations.CreateModel(
+            name='Note',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('title', models.CharField(help_text="Give your note a good headline. What will your upcoming show be about? Try to arouse interest to listen to it!<br>Avoid technical data like the show's name, its airing times or its episode number. These data are added automatically.", max_length=128, verbose_name='Title')),
+                ('content', tinymce.models.HTMLField(help_text='Describe your upcoming show in detail.', verbose_name='Content')),
+                ('status', models.IntegerField(choices=[(0, 'Cancellation'), (1, 'Recommendation'), (2, 'Repetition')], default=1, verbose_name='Status')),
+                ('start', models.DateTimeField(editable=False)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('last_updated', models.DateTimeField(auto_now=True)),
+                ('show', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='program.Show')),
+                ('timeslot', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='program.TimeSlot', verbose_name='Time slot')),
+                ('audio_url', models.TextField(blank=True, editable=False, verbose_name='Direct URL to a linked audio file')),
+                ('cba_id', models.IntegerField(blank=True, help_text="Link the note to a certain CBA post by giving its ID. (E.g. if your post's CBA URL is https://cba.fro.at/1234, then your CBA ID is 1234)", null=True, verbose_name='CBA ID')),
+                ('height', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height')),
+                ('host', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hosts', to='program.Host')),
+                ('image', versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload an image to your note. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='note_images', verbose_name='Featured image', width_field='width')),
+                ('ppoi', versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI')),
+                ('slug', models.SlugField(default=1, help_text='A simple to read URL for your show.', max_length=32, unique=True, verbose_name='Slug')),
+                ('summary', models.TextField(blank=True, help_text='Describe your upcoming show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Summary')),
+                ('user', models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='users', to=settings.AUTH_USER_MODEL)),
+                ('width', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width')),
+            ],
+            options={
+                'ordering': ('timeslot',),
+                'verbose_name': 'Note',
+                'verbose_name_plural': 'Notes',
+            },
+        ),
+        migrations.AddField(
+            model_name='show',
+            name='category',
+            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Category', verbose_name='Category'),
+        ),
+        migrations.AddField(
+            model_name='show',
+            name='language',
+            field=models.ManyToManyField(blank=True, related_name='language', to='program.Language', verbose_name='Language'),
+        ),
+        migrations.AddField(
+            model_name='show',
+            name='topic',
+            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Topic', verbose_name='Topic'),
+        ),
+        migrations.AddField(
+            model_name='show',
+            name='type',
+            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.Type', verbose_name='Type'),
+            preserve_default=False,
+        ),
+        migrations.AddField(
+            model_name='timeslot',
+            name='schedule',
+            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='timeslots', to='program.Schedule', verbose_name='Schedule'),
+            preserve_default=False,
+        ),
+        migrations.AlterField(
+            model_name='timeslot',
+            name='is_repetition',
+            field=models.BooleanField(default=False, verbose_name='(REP)'),
+        ),
+        migrations.CreateModel(
+            name='FundingCategory',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('fundingcategory', models.CharField(max_length=32, verbose_name='Funding Category')),
+                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
+                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
+                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+            ],
+            options={
+                'verbose_name': 'Funding Category',
+                'verbose_name_plural': 'Funding Categories',
+                'ordering': ('fundingcategory',),
+            },
+        ),
+        migrations.AddField(
+            model_name='timeslot',
+            name='note_id',
+            field=models.IntegerField(editable=False, null=True, verbose_name='Note ID'),
+        ),
+        migrations.AlterField(
+            model_name='timeslot',
+            name='is_repetition',
+            field=models.BooleanField(default=False, verbose_name='Is repetition?'),
+        ),
+        migrations.AlterField(
+            model_name='show',
+            name='cba_series_id',
+            field=models.IntegerField(blank=True, help_text="Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to your CBA archive. Find out your show's ID under https://cba.fro.at/series", null=True, verbose_name='CBA Series ID'),
+        ),
+        migrations.AlterField(
+            model_name='show',
+            name='fallback_id',
+            field=models.IntegerField(blank=True, help_text='If a timeslot of your show is empty, this playlist will be aired as a backup.', null=True, verbose_name='Fallback ID'),
+        ),
+        migrations.AlterField(
+            model_name='show',
+            name='logo',
+            field=models.ImageField(blank=True, help_text='Upload a logo of your show.', null=True, upload_to='show_images', verbose_name='Logo'),
+        ),
+        migrations.AlterField(
+            model_name='show',
+            name='short_description',
+            field=models.TextField(help_text='Describe your show for your listeners in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Short description'),
+        ),
+        migrations.AddField(
+            model_name='show',
+            name='fundingcategory',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.FundingCategory', verbose_name='Funding Category'),
+        ),
+        migrations.AddField(
+            model_name='show',
+            name='is_active',
+            field=models.BooleanField(default=True, verbose_name='Is active?'),
+        ),
+        migrations.AddField(
+            model_name='show',
+            name='is_public',
+            field=models.BooleanField(default=False, help_text='Files and Playlists of Public Shows can only be changed by owners but may be used by everyone.', verbose_name='Is Public?'),
+        ),
+    ]
diff --git a/program/migrations/0002_auto_20210426_2345.py b/program/migrations/0002_auto_20210426_2345.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d67419dded6a1761da498a4a4869b48a8affb08
--- /dev/null
+++ b/program/migrations/0002_auto_20210426_2345.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2.20 on 2021-04-26 21:45
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('program', '0001_squashed'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='schedule',
+            old_name='fallback_id',
+            new_name='default_id'
+        ),
+        migrations.RenameField(
+            model_name='show',
+            old_name='fallback_id',
+            new_name='default_id'
+        ),
+    ]
diff --git a/program/migrations/0003_auto_20210713_0420.py b/program/migrations/0003_auto_20210713_0420.py
new file mode 100644
index 0000000000000000000000000000000000000000..88314acb966c742fcfffba664e8b59a8a37e7064
--- /dev/null
+++ b/program/migrations/0003_auto_20210713_0420.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2.12 on 2021-07-13 02:20
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('program', '0002_auto_20210426_2345'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='schedule',
+            old_name='default_id',
+            new_name='default_playlist_id'
+        ),
+        migrations.RenameField(
+            model_name='show',
+            old_name='default_id',
+            new_name='default_playlist_id'
+        ),
+    ]
diff --git a/program/models.py b/program/models.py
index ae330a3d9bb28b5b2ecc3321a44434eb8efc3678..daba737de59f533881333b622df353fbbdf859a1 100644
--- a/program/models.py
+++ b/program/models.py
@@ -1,24 +1,43 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import json
+from datetime import date, datetime, time, timedelta
+from urllib.request import urlopen
 
+from dateutil.relativedelta import relativedelta
+from dateutil.rrule import rrule
 from django.contrib.auth.models import User
 from django.core.exceptions import ObjectDoesNotExist, ValidationError, MultipleObjectsReturned
-from django.urls import reverse
 from django.db import models
 from django.db.models import Q
 from django.forms.models import model_to_dict
+from django.urls import reverse
+from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
-from versatileimagefield.fields import VersatileImageField, PPOIField
-
 from tinymce import models as tinymce_models
+from versatileimagefield.fields import VersatileImageField, PPOIField
 
-from datetime import date, datetime, time, timedelta
-from dateutil.relativedelta import relativedelta
-from dateutil.rrule import rrule
-
+from steering.settings import THUMBNAIL_SIZES, AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR, AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE
 from .utils import get_automation_id_choices
 
-from pv.settings import THUMBNAIL_SIZES, AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR, AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE
-
 
 class Type(models.Model):
     type = models.CharField(_("Type"), max_length=32)
@@ -252,7 +271,8 @@ class Host(models.Model):
     is_active = models.BooleanField(_("Is active?"), default=True)
     email = models.EmailField(_("E-Mail"), blank=True)
     website = models.URLField(_("Website"), blank=True, help_text=_("URL to your personal website."))
-    biography = tinymce_models.HTMLField(_("Biography"), blank=True, null=True, help_text=_("Describe yourself and your fields of interest in a few sentences."))
+    biography = tinymce_models.HTMLField(_("Biography"), blank=True, null=True,
+                                         help_text=_("Describe yourself and your fields of interest in a few sentences."))
     googleplus_url = models.URLField(_("Google+ URL"), blank=True, help_text=_("URL to your Google+ profile."))
     facebook_url = models.URLField(_("Facebook URL"), blank=True, help_text=_("URL to your Facebook profile."))
     twitter_url = models.URLField(_("Twitter URL"), blank=True, help_text=_("URL to your Twitter profile."))
@@ -263,7 +283,10 @@ class Host(models.Model):
     ppoi = PPOIField('Image PPOI')
     height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False)
     width = models.PositiveIntegerField('Image Width', blank=True, null=True, editable=False)
-    image = VersatileImageField(_("Profile picture"), blank=True, null=True, upload_to='host_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save."))
+    image = VersatileImageField(_("Profile picture"), blank=True, null=True, upload_to='host_images', width_field='width',
+                                height_field='height', ppoi_field='ppoi', help_text=_(
+            "Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in"
+            " the image to change it and press Save."))
 
     class Meta:
         ordering = ('name',)
@@ -277,36 +300,40 @@ class Host(models.Model):
         return reverse('host-detail', args=[str(self.id)])
 
     def active_shows(self):
-        return self.shows.filter(schedules__until__gt=datetime.today())
+        return self.shows.filter(schedules__until__gt=timezone.now())
 
-    def is_editable(self, host_id):
+    def save(self, *args, **kwargs):
+        super(Host, self).save(*args, **kwargs)
+
+        # Generate thumbnails
+        if self.image.name and THUMBNAIL_SIZES:
+            for size in THUMBNAIL_SIZES:
+                self.image.thumbnail = self.image.crop[size].name
+
+    # FIXME: this does not belong here
+    @staticmethod
+    def is_editable(host_view_set, host_id):
         """
         Whether the given host is assigned to a show the current user owns
         @return boolean
         """
-        if self.request.user.is_superuser:
+        if host_view_set.request.user.is_superuser:
             return True
 
-        host_ids = Host.objects.filter(shows__in=self.request.user.shows.all()).distinct().values_list('id', flat=True)
+        host_ids = Host.objects.filter(shows__in=host_view_set.request.user.shows.all()).distinct().values_list('id', flat=True)
         return int(host_id) in host_ids
 
-    def save(self, *args, **kwargs):
-        super(Host, self).save(*args, **kwargs)
-
-        # Generate thumbnails
-        if self.image.name and THUMBNAIL_SIZES:
-            for size in THUMBNAIL_SIZES:
-                thumbnail = self.image.crop[size].name
-
 
 class Show(models.Model):
-    predecessor = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE, related_name='successors', verbose_name=_("Predecessor"))
+    predecessor = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE, related_name='successors',
+                                    verbose_name=_("Predecessor"))
     hosts = models.ManyToManyField(Host, blank=True, related_name='shows', verbose_name=_("Hosts"))
     owners = models.ManyToManyField(User, blank=True, related_name='shows', verbose_name=_("Owners"))
     language = models.ManyToManyField(Language, blank=True, related_name='language', verbose_name=_("Language"))
     type = models.ForeignKey(Type, on_delete=models.CASCADE, related_name='shows', verbose_name=_("Type"))
     category = models.ManyToManyField(Category, blank=True, related_name='shows', verbose_name=_("Category"))
-    fundingcategory = models.ForeignKey(FundingCategory, null=True, on_delete=models.CASCADE, blank=True, related_name='shows', verbose_name=_("Funding Category"))
+    fundingcategory = models.ForeignKey(FundingCategory, null=True, on_delete=models.CASCADE, blank=True, related_name='shows',
+                                        verbose_name=_("Funding Category"))
     topic = models.ManyToManyField(Topic, blank=True, related_name='shows', verbose_name=_("Topic"))
     musicfocus = models.ManyToManyField(MusicFocus, blank=True, related_name='shows', verbose_name=_("Music focus"))
     name = models.CharField(_("Name"), max_length=255, help_text=_("The show's name. Avoid a subtitle."))
@@ -314,18 +341,30 @@ class Show(models.Model):
     ppoi = PPOIField('Image PPOI')
     height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False)
     width = models.PositiveIntegerField('Image Width', blank=True, null=True, editable=False)
-    image = VersatileImageField(_("Image"), blank=True, null=True, upload_to='show_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload an image to your show. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save."))
-    logo = models.ImageField(_("Logo"), blank=True, null=True, upload_to='show_images', help_text=_("Upload a logo of your show."))
-    short_description = models.TextField(_("Short description"), help_text=_("Describe your show for your listeners in some sentences. Avoid technical data like airing times and contact information. They will be added automatically."))
-    description = tinymce_models.HTMLField(_("Description"), blank=True, null=True, help_text=_("Describe your show in detail."))
+    image = VersatileImageField(_("Image"), blank=True, null=True, upload_to='show_images', width_field='width',
+                                height_field='height', ppoi_field='ppoi', help_text=_(
+            "Upload an image to your show. Images are automatically cropped around the 'Primary Point of Interest'. Click in"
+            " the image to change it and press Save."))
+    logo = models.ImageField(_("Logo"), blank=True, null=True, upload_to='show_images',
+                             help_text=_("Upload a logo of your show."))
+    short_description = models.TextField(_("Short description"), help_text=_(
+        "Describe your show for your listeners in some sentences. Avoid technical data like airing times and contact"
+        " information. They will be added automatically."))
+    description = tinymce_models.HTMLField(_("Description"), blank=True, null=True,
+                                           help_text=_("Describe your show in detail."))
     email = models.EmailField(_("E-Mail"), blank=True, null=True, help_text=_("The main contact email address for your show."))
-    website = models.URLField(_("Website"), blank=True, null=True, help_text=_("Is there a website to your show? Type in its URL."))
-    cba_series_id = models.IntegerField(_("CBA Series ID"), blank=True, null=True, help_text=_("Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to your CBA archive. Find out your show's ID under https://cba.fro.at/series"))
-    fallback_id = models.IntegerField(_("Fallback ID"), blank=True, null=True, help_text=_("If a timeslot of your show is empty, this playlist will be aired as a backup."))
+    website = models.URLField(_("Website"), blank=True, null=True,
+                              help_text=_("Is there a website to your show? Type in its URL."))
+    cba_series_id = models.IntegerField(_("CBA Series ID"), blank=True, null=True, help_text=_(
+        "Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to"
+        " your CBA archive. Find out your show's ID under https://cba.fro.at/series"))
+    default_playlist_id = models.IntegerField(_("Default Playlist ID"), blank=True, null=True, help_text=_(
+        "If a timeslot of your show is empty, this playlist will be aired as a backup."))
     created = models.DateTimeField(auto_now_add=True, editable=False)
     last_updated = models.DateTimeField(auto_now=True, editable=False)
     is_active = models.BooleanField(_("Is active?"), default=True)
-    is_public = models.BooleanField(_("Is Public?"), default=False, help_text=_("Files and Playlists of Public Shows can only be changed by owners but may be used by everyone."))
+    is_public = models.BooleanField(_("Is Public?"), default=False, help_text=_(
+        "Files and Playlists of Public Shows can only be changed by owners but may be used by everyone."))
 
     class Meta:
         ordering = ('slug',)
@@ -334,7 +373,7 @@ class Show(models.Model):
 
     def __str__(self):
         if self.id is None:
-            return '%s' % (self.name)
+            return '%s' % self.name
 
         return '%04d | %s' % (self.id, self.name)
 
@@ -345,20 +384,21 @@ class Show(models.Model):
     def active_schedules(self):
         return self.schedules.filter(until__gt=date.today())
 
-    def is_editable(self, show_id):
+    # FIXME: this does not belong here
+    @staticmethod
+    def is_editable(show_view_set, show_id):
         """
         Whether the current user is owner of the given show
         @return boolean
         """
-        if self.request.user.is_superuser:
+        if show_view_set.request.user.is_superuser:
             return True
 
-        show_ids = self.request.user.shows.all().values_list('id', flat=True)
+        show_ids = show_view_set.request.user.shows.all().values_list('id', flat=True)
         return int(show_id) in show_ids
 
 
 class RRule(models.Model):
-
     FREQ_CHOICES = (
         (1, _("Monthly")),
         (2, _("Weekly")),
@@ -376,8 +416,7 @@ class RRule(models.Model):
     name = models.CharField(_("Name"), max_length=32, unique=True)
     freq = models.IntegerField(_("Frequency"), choices=FREQ_CHOICES)
     interval = models.IntegerField(_("Interval"), default=1)
-    bysetpos = models.IntegerField(_("Set position"), blank=True,
-                                   choices=BYSETPOS_CHOICES, null=True)
+    bysetpos = models.IntegerField(_("Set position"), blank=True, choices=BYSETPOS_CHOICES, null=True)
     count = models.IntegerField(_("Count"), blank=True, null=True)
 
     class Meta:
@@ -410,9 +449,12 @@ class Schedule(models.Model):
     is_repetition = models.BooleanField(_("Is repetition"), default=False)
     add_days_no = models.IntegerField(_("Add days"), blank=True, null=True)
     add_business_days_only = models.BooleanField(_("Only add business days?"), default=False)
-    fallback_id = models.IntegerField(_("Fallback ID"), blank=True, null=True)
-    automation_id = models.IntegerField(_("Automation ID"), blank=True, null=True, choices=get_automation_id_choices())  # Deprecated
-    created = models.DateTimeField(auto_now_add=True, editable=False, null=True)  # -> both see https://stackoverflow.com/questions/1737017/django-auto-now-and-auto-now-add
+    default_playlist_id = models.IntegerField(_("Default Playlist ID"), blank=True, null=True)
+    automation_id = models.IntegerField(_("Automation ID"), blank=True, null=True,
+                                        choices=get_automation_id_choices())  # Deprecated
+    # -> both see https://stackoverflow.com/questions/1737017/django-auto-now-and-auto-now-add
+    created = models.DateTimeField(auto_now_add=True, editable=False,
+                                   null=True)
     last_updated = models.DateTimeField(auto_now=True, editable=False, null=True)
 
     class Meta:
@@ -433,6 +475,11 @@ class Schedule(models.Model):
         else:
             return '%s, %s, %s - %s' % (weekday, self.rrule, tstart, tend)
 
+    def save(self, *args, **kwargs):
+        super(Schedule, self).save(*args, **kwargs)
+
+    # FIXME: this does not belong here
+    @staticmethod
     def instantiate_upcoming(sdl, show_pk, pk=None):
         """Returns an upcoming schedule instance for conflict resolution"""
 
@@ -440,17 +487,17 @@ class Schedule(models.Model):
         rrule = RRule.objects.get(pk=int(sdl['rrule']))
         show = Show.objects.get(pk=int(show_pk))
 
-        is_repetition = True if 'is_repetition' in sdl and sdl['is_repetition'] == 'true' else False
-        fallback_id = int(sdl['fallback_id']) if sdl['fallback_id'] else None
+        is_repetition = True if 'is_repetition' in sdl and sdl['is_repetition'] is True else False
+        default_playlist_id = int(sdl['default_playlist_id']) if sdl['default_playlist_id'] else None
         automation_id = int(sdl['automation_id']) if sdl['automation_id'] else None
         add_days_no = int(sdl['add_days_no']) if sdl['add_days_no'] > 0 else None
-        add_business_days_only = True if sdl['add_business_days_only'] == 'true' else False
+        add_business_days_only = True if 'add_business_days_only' in sdl and sdl['add_business_days_only'] is True else False
 
         dstart = datetime.strptime(str(sdl['dstart']), '%Y-%m-%d').date()
 
         # Schedule mustn't start in the past when adding
-        if pk is None and dstart < datetime.today().date():
-            dstart = datetime.today().date()
+        if pk is None and dstart < timezone.now().date():
+            dstart = timezone.now().date()
 
         tstart = sdl['tstart'] + ':00' if len(str(sdl['tstart'])) == 5 else sdl['tstart']
         tend = sdl['tend'] + ':00' if len(str(sdl['tend'])) == 5 else sdl['tend']
@@ -465,7 +512,7 @@ class Schedule(models.Model):
             # Set it to the end of the year
             # Or add x days
             if AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR:
-                now = datetime.now()
+                now = timezone.now()
                 until = datetime.strptime(str(now.year) + '-12-31', '%Y-%m-%d').date()
             else:
                 until = dstart + timedelta(days=+AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE)
@@ -473,11 +520,13 @@ class Schedule(models.Model):
         schedule = Schedule(pk=pk, byweekday=sdl['byweekday'], rrule=rrule,
                             dstart=dstart, tstart=tstart, tend=tend,
                             until=until, is_repetition=is_repetition,
-                            fallback_id=fallback_id, show=show,
+                            default_playlist_id=default_playlist_id, show=show,
                             add_days_no=add_days_no, add_business_days_only=add_business_days_only)
 
         return schedule
 
+    # FIXME: this does not belong here
+    @staticmethod
     def generate_timeslots(schedule):
         """
         Returns a list of timeslot objects based on a schedule and its rrule
@@ -594,8 +643,8 @@ class Schedule(models.Model):
                 weekday = datetime.date(starts[k]).weekday()
                 if schedule.add_business_days_only and weekday > 3:
                     days_until_sunday = 6 - weekday
-                    starts[k] = starts[k] + relativedelta(days=+days_until_sunday+schedule.add_days_no)
-                    ends[k] = ends[k] + relativedelta(days=+days_until_sunday+schedule.add_days_no)
+                    starts[k] = starts[k] + relativedelta(days=+days_until_sunday + schedule.add_days_no)
+                    ends[k] = ends[k] + relativedelta(days=+days_until_sunday + schedule.add_days_no)
                 else:
                     starts[k] = starts[k] + relativedelta(days=+schedule.add_days_no)
                     ends[k] = ends[k] + relativedelta(days=+schedule.add_days_no)
@@ -607,6 +656,8 @@ class Schedule(models.Model):
 
         return timeslots
 
+    # FIXME: this does not belong here
+    @staticmethod
     def get_collisions(timeslots):
         """
         Tests a list of timeslot objects for colliding timeslots in the database
@@ -619,11 +670,11 @@ class Schedule(models.Model):
         for ts in timeslots:
 
             collision = TimeSlot.objects.filter(
-                           (Q(start__lt=ts.end) & Q(end__gte=ts.end)) |
-                           (Q(end__gt=ts.start) & Q(end__lte=ts.end)) |
-                           (Q(start__gte=ts.start) & Q(end__lte=ts.end)) |
-                           (Q(start__lte=ts.start) & Q(end__gte=ts.end))
-                        )
+                (Q(start__lt=ts.end) & Q(end__gte=ts.end)) |
+                (Q(end__gt=ts.start) & Q(end__lte=ts.end)) |
+                (Q(start__gte=ts.start) & Q(end__lte=ts.end)) |
+                (Q(start__lte=ts.start) & Q(end__gte=ts.end))
+            )
 
             if collision:
                 collisions.append(collision[0])  # TODO: Do we really always retrieve one?
@@ -632,6 +683,8 @@ class Schedule(models.Model):
 
         return collisions
 
+    # FIXME: this does not belong here
+    @staticmethod
     def generate_conflicts(timeslots):
         """
         Tests a list of timeslot objects for colliding timeslots in the database
@@ -656,31 +709,20 @@ class Schedule(models.Model):
 
             # Get collisions for each timeslot
             collision_list = list(TimeSlot.objects.filter(
-                           (Q(start__lt=ts.end) & Q(end__gte=ts.end)) |
-                           (Q(end__gt=ts.start) & Q(end__lte=ts.end)) |
-                           (Q(start__gte=ts.start) & Q(end__lte=ts.end)) |
-                           (Q(start__lte=ts.start) & Q(end__gte=ts.end))
-                        ).order_by('start'))
+                (Q(start__lt=ts.end) & Q(end__gte=ts.end)) |
+                (Q(end__gt=ts.start) & Q(end__lte=ts.end)) |
+                (Q(start__gte=ts.start) & Q(end__lte=ts.end)) |
+                (Q(start__lte=ts.start) & Q(end__gte=ts.end))
+            ).order_by('start'))
 
             # Add the projected timeslot
-            projected_entry = {}
-            projected_entry['hash'] = ts.hash
-            projected_entry['start'] = str(ts.start)
-            projected_entry['end'] = str(ts.end)
+            projected_entry = {'hash': ts.hash, 'start': str(ts.start), 'end': str(ts.end)}
 
             for c in collision_list:
-
                 # Add the collision
-                collision = {}
-                collision['id'] = c.id
-                collision['start'] = str(c.start)
-                collision['end'] = str(c.end)
-                collision['playlist_id'] = c.playlist_id
-                collision['show'] = c.show.id
-                collision['show_name'] = c.show.name
-                collision['is_repetition'] = c.is_repetition
-                collision['schedule'] = c.schedule_id
-                collision['memo'] = c.memo
+                collision = {'id': c.id, 'start': str(c.start), 'end': str(c.end), 'playlist_id': c.playlist_id,
+                             'show': c.show.id, 'show_name': c.show.name, 'is_repetition': c.is_repetition,
+                             'schedule': c.schedule_id, 'memo': c.memo}
 
                 # Get note
                 try:
@@ -712,7 +754,7 @@ class Schedule(models.Model):
                     #   |  |
                     #   +--+
                     #
-                    if ts.start < c.start and ts.end > c.start and ts.end <= c.end:
+                    if ts.end > c.start > ts.start <= c.end:
                         solution_choices.add('theirs-end')
                         solution_choices.add('ours-end')
 
@@ -726,7 +768,7 @@ class Schedule(models.Model):
                     #        |  |
                     #        +--+
                     #
-                    if ts.start >= c.start and ts.start < c.end and ts.end > c.end:
+                    if c.start <= ts.start < c.end < ts.end:
                         solution_choices.add('theirs-start')
                         solution_choices.add('ours-start')
 
@@ -772,6 +814,8 @@ class Schedule(models.Model):
 
         return conflicts
 
+    # FIXME: this does not belong here
+    @staticmethod
     def make_conflicts(sdl, schedule_pk, show_pk):
         """
         Retrieves POST vars
@@ -804,6 +848,8 @@ class Schedule(models.Model):
 
         return conflicts
 
+    # FIXME: this does not belong here
+    @staticmethod
     def resolve_conflicts(data, schedule_pk, show_pk):
         """
         Resolves conflicts
@@ -847,7 +893,7 @@ class Schedule(models.Model):
         for ts in conflicts['projected']:
 
             # Ignore past dates
-            if datetime.strptime(ts['start'], "%Y-%m-%d %H:%M:%S") <= datetime.today():
+            if datetime.strptime(ts['start'], "%Y-%m-%d %H:%M:%S") <= timezone.now():
                 continue
 
             # If no solution necessary
@@ -1020,10 +1066,8 @@ class Schedule(models.Model):
 
         # If 'dryrun' is true, just return the projected changes instead of executing them
         if 'dryrun' in sdl and sdl['dryrun']:
-            output = {}
-            output['create'] = [model_to_dict(ts) for ts in create]
-            output['update'] = [model_to_dict(ts) for ts in update]
-            output['delete'] = [model_to_dict(ts) for ts in delete]
+            output = {'create': [model_to_dict(ts) for ts in create], 'update': [model_to_dict(ts) for ts in update],
+                      'delete': [model_to_dict(ts) for ts in delete]}
             return output
 
         '''Database changes if no errors found'''
@@ -1066,9 +1110,6 @@ class Schedule(models.Model):
 
         return model_to_dict(schedule)
 
-    def save(self, *args, **kwargs):
-        super(Schedule, self).save(*args, **kwargs)
-
 
 class TimeSlotManager(models.Manager):
     @staticmethod
@@ -1080,16 +1121,16 @@ class TimeSlotManager(models.Manager):
     @staticmethod
     def get_or_create_current():
         try:
-            return TimeSlot.objects.get(start__lte=datetime.now(), end__gt=datetime.now())
+            return TimeSlot.objects.get(start__lte=timezone.now(), end__gt=timezone.now())
         except MultipleObjectsReturned:
-            return TimeSlot.objects.filter(start__lte=datetime.now(), end__gt=datetime.now())[0]
+            return TimeSlot.objects.filter(start__lte=timezone.now(), end__gt=timezone.now())[0]
         except ObjectDoesNotExist:
             once = RRule.objects.get(pk=1)
             today = date.today().weekday()
             default = Show.objects.get(pk=1)
 
-            previous_timeslot = TimeSlot.objects.filter(end__lte=datetime.now()).order_by('-start')[0]
-            next_timeslot = TimeSlot.objects.filter(start__gte=datetime.now())[0]
+            previous_timeslot = TimeSlot.objects.filter(end__lte=timezone.now()).order_by('-start')[0]
+            next_timeslot = TimeSlot.objects.filter(start__gte=timezone.now())[0]
 
             dstart, tstart = previous_timeslot.end.date(), previous_timeslot.end.time()
             until, tend = next_timeslot.start.date(), next_timeslot.start.time()
@@ -1141,7 +1182,9 @@ class TimeSlotManager(models.Manager):
 
 class TimeSlot(models.Model):
     schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE, related_name='timeslots', verbose_name=_("Schedule"))
-    start = models.DateTimeField(_("Start time"))  # Removed 'unique=True' because new Timeslots need to be created before deleting the old ones (otherwise linked notes get deleted first)
+    start = models.DateTimeField(_("Start time"))
+    # Removed 'unique=True' because new Timeslots need to be created before deleting the old ones (otherwise linked notes get
+    # deleted first)
     end = models.DateTimeField(_("End time"))
     show = models.ForeignKey(Show, editable=False, on_delete=models.CASCADE, related_name='timeslots')
     memo = models.TextField(_("Memo"), blank=True)
@@ -1159,7 +1202,7 @@ class TimeSlot(models.Model):
     def __str__(self):
         start = self.start.strftime('%a, %d.%m.%Y %H:%M')
         end = self.end.strftime('%H:%M')
-        is_repetition = ' ' + _('(REP)') if self.schedule.is_repetition == 1 else ''
+        is_repetition = ' ' + _('(REP)') if self.schedule.is_repetition is True else ''
 
         return '%s - %s  %s (%s)' % (start, end, is_repetition, self.show.name)
 
@@ -1168,7 +1211,7 @@ class TimeSlot(models.Model):
         super(TimeSlot, self).save(*args, **kwargs)
         return self
 
-    def generate(self, **kwargs):
+    def generate(self):
         """Returns the object instance without saving"""
 
         self.show = self.schedule.show
@@ -1190,18 +1233,28 @@ class Note(models.Model):
         (2, _("Repetition")),
     )
     timeslot = models.OneToOneField(TimeSlot, on_delete=models.CASCADE, verbose_name=_("Time slot"), unique=True)
-    title = models.CharField(_("Title"), max_length=128, help_text=_("Give your note a good headline. What will your upcoming show be about? Try to arouse interest to listen to it!<br>Avoid technical data like the show's name, its airing times or its episode number. These data are added automatically."))
+    title = models.CharField(_("Title"), max_length=128, help_text=_(
+        "Give your note a good headline. What will your upcoming show be about? Try to arouse interest to listen to it!<br>"
+        "Avoid technical data like the show's name, its airing times or its episode number. These data are added"
+        " automatically."))
     slug = models.SlugField(_("Slug"), max_length=32, unique=True, help_text=_("A simple to read URL for your show."))
-    summary = models.TextField(_("Summary"), blank=True, help_text=_("Describe your upcoming show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically."))
+    summary = models.TextField(_("Summary"), blank=True, help_text=_(
+        "Describe your upcoming show in some sentences. Avoid technical data like airing times and contact information. They"
+        " will be added automatically."))
     content = tinymce_models.HTMLField(_("Content"), help_text=_("Describe your upcoming show in detail."))
     ppoi = PPOIField('Image PPOI')
     height = models.PositiveIntegerField('Image Height', blank=True, null=True, editable=False)
     width = models.PositiveIntegerField('Image Width', blank=True, null=True, editable=False)
-    image = VersatileImageField(_("Featured image"), blank=True, null=True, upload_to='note_images', width_field='width', height_field='height', ppoi_field='ppoi', help_text=_("Upload an image to your note. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save."))
+    image = VersatileImageField(_("Featured image"), blank=True, null=True, upload_to='note_images', width_field='width',
+                                height_field='height', ppoi_field='ppoi', help_text=_(
+            "Upload an image to your note. Images are automatically cropped around the 'Primary Point of Interest'. Click in"
+            " the image to change it and press Save."))
     status = models.IntegerField(_("Status"), choices=STATUS_CHOICES, default=1)
     start = models.DateTimeField(editable=False)
     show = models.ForeignKey(Show, on_delete=models.CASCADE, related_name='notes', editable=True)
-    cba_id = models.IntegerField(_("CBA ID"), blank=True, null=True, help_text=_("Link the note to a certain CBA post by giving its ID. (E.g. if your post's CBA URL is https://cba.fro.at/1234, then your CBA ID is 1234)"))
+    cba_id = models.IntegerField(_("CBA ID"), blank=True, null=True, help_text=_(
+        "Link the note to a certain CBA post by giving its ID. (E.g. if your post's CBA URL is https://cba.fro.at/1234, then"
+        " your CBA ID is 1234)"))
     audio_url = models.TextField(_("Direct URL to a linked audio file"), blank=True, editable=False)
     created = models.DateTimeField(auto_now_add=True, editable=False)
     last_updated = models.DateTimeField(auto_now=True, editable=False)
@@ -1216,19 +1269,38 @@ class Note(models.Model):
     def __str__(self):
         return '%s - %s' % (self.title, self.timeslot)
 
-    def is_editable(self, note_id):
+    def save(self, *args, **kwargs):
+        self.start = self.timeslot.start
+        self.show = self.timeslot.schedule.show
+
+        timeslot = TimeSlot.objects.get(pk=self.timeslot.id)
+        timeslot.note_id = self.id
+        timeslot.save()
+
+        super(Note, self).save(*args, **kwargs)
+
+        # Generate thumbnails
+        if self.image.name and THUMBNAIL_SIZES:
+            for size in THUMBNAIL_SIZES:
+                self.image.thumbnail = self.image.crop[size].name
+
+    # FIXME: this does not belong here
+    @staticmethod
+    def is_editable(note_view_set, note_id):
         """
         Whether the given note is assigned to a show the current user owns
         @return boolean
         """
 
-        if self.request.user.is_superuser:
+        if note_view_set.request.user.is_superuser:
             return True
 
         note = Note.objects.get(pk=note_id)
 
-        return int(note.show_id) in self.request.user.shows.all().values_list('id', flat=True)
+        return int(note.show_id) in note_view_set.request.user.shows.all().values_list('id', flat=True)
 
+    # FIXME: this does not belong here
+    @staticmethod
     def get_audio_url(cba_id):
         """
         Retrieve the direct URL to the mp3 in CBA
@@ -1239,36 +1311,19 @@ class Note(models.Model):
         Therefore contact cba@fro.at
         """
 
-        from pv.settings import CBA_AJAX_URL, CBA_API_KEY
+        from steering.settings import CBA_AJAX_URL, CBA_API_KEY
 
         audio_url = ''
 
         if cba_id is not None and cba_id != '' and CBA_API_KEY != '':
-            from urllib.request import urlopen
-            import json
-
             url = CBA_AJAX_URL + '?action=cba_ajax_get_filename&post_id=' + str(cba_id) + '&api_key=' + CBA_API_KEY
 
             # For momentary testing without being whitelisted - TODO: delete the line
-            url = 'https://cba.fro.at/wp-content/plugins/cba/ajax/cba-get-filename.php?post_id=' + str(cba_id) + '&c=Ml3fASkfwR8'
+            url = 'https://cba.fro.at/wp-content/plugins/cba/ajax/cba-get-filename.php?post_id=' + str(
+                cba_id) + '&c=Ml3fASkfwR8'
 
             with urlopen(url) as conn:
                 audio_url_json = conn.read().decode('utf-8-sig')
                 audio_url = json.loads(audio_url_json)
 
         return audio_url
-
-    def save(self, *args, **kwargs):
-        self.start = self.timeslot.start
-        self.show = self.timeslot.schedule.show
-
-        timeslot = TimeSlot.objects.get(pk=self.timeslot.id)
-        timeslot.note_id = self.id
-        timeslot.save()
-
-        super(Note, self).save(*args, **kwargs)
-
-        # Generate thumbnails
-        if self.image.name and THUMBNAIL_SIZES:
-            for size in THUMBNAIL_SIZES:
-                thumbnail = self.image.crop[size].name
diff --git a/program/serializers.py b/program/serializers.py
index 6f6c5c3a88e1cb27016c0b4771e81553034e27e2..cff27afb31914cf916ec7012f04de912c7610cf5 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -1,15 +1,34 @@
-# -*- coding: utf-8 -*-
-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from django.contrib.auth.models import User
 from django.core.exceptions import ObjectDoesNotExist
-from django.contrib.auth.models import User, Group
-from rest_framework import serializers, status
-from rest_framework.response import Response
-from program.models import Show, Schedule, TimeSlot, Category, FundingCategory, Host, Language, Topic, MusicFocus, Note, Type, Language, RRule
+from django.utils import timezone
+from rest_framework import serializers
+
 from profile.models import Profile
 from profile.serializers import ProfileSerializer
-from datetime import datetime
+from program.models import Show, Schedule, TimeSlot, Category, FundingCategory, Host, Topic, MusicFocus, Note, Type, Language, \
+    RRule
+from steering.settings import THUMBNAIL_SIZES
 
-from pv.settings import THUMBNAIL_SIZES
 
 class UserSerializer(serializers.ModelSerializer):
     # Add profile fields to JSON
@@ -19,7 +38,6 @@ class UserSerializer(serializers.ModelSerializer):
         model = User
         fields = '__all__'
 
-
     def create(self, validated_data):
         """
         Create and return a new User instance, given the validated data.
@@ -28,16 +46,16 @@ class UserSerializer(serializers.ModelSerializer):
         profile_data = validated_data.pop('profile')
 
         user = super(UserSerializer, self).create(validated_data)
-        user.date_joined = datetime.today()
+        user.date_joined = timezone.now()
         user.set_password(validated_data['password'])
         user.save()
 
-        profile = Profile(user=user, cba_username=profile_data.get('cba_username').strip(), cba_user_token=profile_data.get('cba_user_token').strip())
+        profile = Profile(user=user, cba_username=profile_data.get('cba_username').strip(),
+                          cba_user_token=profile_data.get('cba_user_token').strip())
         profile.save()
 
         return user
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing User instance, given the validated data.
@@ -70,13 +88,11 @@ class UserSerializer(serializers.ModelSerializer):
         return instance
 
 
-
 class CategorySerializer(serializers.ModelSerializer):
     class Meta:
         model = Category
         fields = '__all__'
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing Category instance, given the validated data.
@@ -93,9 +109,10 @@ class CategorySerializer(serializers.ModelSerializer):
 
 
 class HostSerializer(serializers.ModelSerializer):
-    thumbnails = serializers.SerializerMethodField() # Read-only
+    thumbnails = serializers.SerializerMethodField()  # Read-only
 
-    def get_thumbnails(self, host):
+    @staticmethod
+    def get_thumbnails(host):
         """Returns thumbnails"""
         thumbnails = []
 
@@ -109,7 +126,6 @@ class HostSerializer(serializers.ModelSerializer):
         model = Host
         fields = '__all__'
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing Host instance, given the validated data.
@@ -139,7 +155,6 @@ class LanguageSerializer(serializers.ModelSerializer):
         model = Language
         fields = '__all__'
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing Language instance, given the validated data.
@@ -156,7 +171,6 @@ class TopicSerializer(serializers.ModelSerializer):
         model = Topic
         fields = '__all__'
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing Topic instance, given the validated data.
@@ -175,7 +189,6 @@ class MusicFocusSerializer(serializers.ModelSerializer):
         model = MusicFocus
         fields = '__all__'
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing MusicFocus instance, given the validated data.
@@ -194,7 +207,6 @@ class TypeSerializer(serializers.ModelSerializer):
         model = Type
         fields = '__all__'
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing Type instance, given the validated data.
@@ -214,7 +226,6 @@ class FundingCategorySerializer(serializers.ModelSerializer):
         model = FundingCategory
         fields = '__all__'
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing FundingCategory instance, given the validated data.
@@ -229,18 +240,19 @@ class FundingCategorySerializer(serializers.ModelSerializer):
 
 
 class ShowSerializer(serializers.HyperlinkedModelSerializer):
-    owners = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(),many=True)
-    category = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(),many=True)
-    hosts = serializers.PrimaryKeyRelatedField(queryset=Host.objects.all(),many=True)
-    language = serializers.PrimaryKeyRelatedField(queryset=Language.objects.all(),many=True)
-    topic = serializers.PrimaryKeyRelatedField(queryset=Topic.objects.all(),many=True)
-    musicfocus = serializers.PrimaryKeyRelatedField(queryset=MusicFocus.objects.all(),many=True)
+    owners = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), many=True)
+    category = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(), many=True)
+    hosts = serializers.PrimaryKeyRelatedField(queryset=Host.objects.all(), many=True)
+    language = serializers.PrimaryKeyRelatedField(queryset=Language.objects.all(), many=True)
+    topic = serializers.PrimaryKeyRelatedField(queryset=Topic.objects.all(), many=True)
+    musicfocus = serializers.PrimaryKeyRelatedField(queryset=MusicFocus.objects.all(), many=True)
     type = serializers.PrimaryKeyRelatedField(queryset=Type.objects.all())
     fundingcategory = serializers.PrimaryKeyRelatedField(queryset=FundingCategory.objects.all())
-    predecessor = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all(),required=False,allow_null=True)
-    thumbnails = serializers.SerializerMethodField() # Read-only
+    predecessor = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all(), required=False, allow_null=True)
+    thumbnails = serializers.SerializerMethodField()  # Read-only
 
-    def get_thumbnails(self, show):
+    @staticmethod
+    def get_thumbnails(show):
         """Returns thumbnails"""
         thumbnails = []
 
@@ -250,15 +262,13 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
 
         return thumbnails
 
-
     class Meta:
         model = Show
         fields = ('id', 'name', 'slug', 'image', 'ppoi', 'logo', 'short_description', 'description',
                   'email', 'website', 'created', 'last_updated', 'type', 'fundingcategory',
-                  'predecessor', 'cba_series_id', 'fallback_id', 'category', 'hosts',
+                  'predecessor', 'cba_series_id', 'default_playlist_id', 'category', 'hosts',
                   'owners', 'language', 'topic', 'musicfocus', 'thumbnails', 'is_active', 'is_public')
 
-
     def create(self, validated_data):
         """
         Create and return a new Show instance, given the validated data.
@@ -274,17 +284,16 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
         show = Show.objects.create(**validated_data)
 
         # Save many-to-many relationships
-        show.owners = owners
-        show.category = category
-        show.hosts = hosts
-        show.language = language
-        show.topic = topic
-        show.musicfocus = musicfocus
+        show.owners.set(owners)
+        show.category.set(category)
+        show.hosts.set(hosts)
+        show.language.set(language)
+        show.topic.set(topic)
+        show.musicfocus.set(musicfocus)
 
         show.save()
         return show
 
-
     def update(self, instance, validated_data):
         """
         Update and return an existing Show instance, given the validated data.
@@ -302,16 +311,16 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
         instance.email = validated_data.get('email', instance.email)
         instance.website = validated_data.get('website', instance.website)
         instance.cba_series_id = validated_data.get('cba_series_id', instance.cba_series_id)
-        instance.fallback_id = validated_data.get('fallback_id', instance.fallback_id)
+        instance.default_playlist_id = validated_data.get('default_playlist_id', instance.default_playlist_id)
 
         # Only superusers may update the following fields
         if user.is_superuser:
-            instance.owners = validated_data.get('owners', instance.owners)
-            instance.category = validated_data.get('category', instance.category)
-            instance.hosts = validated_data.get('hosts', instance.hosts)
-            instance.language = validated_data.get('language', instance.language)
-            instance.topic = validated_data.get('topic', instance.topic)
-            instance.musicfocus = validated_data.get('musicfocus', instance.musicfocus)
+            instance.owners.set(validated_data.get('owners', instance.owners))
+            instance.category.set(validated_data.get('category', instance.category))
+            instance.hosts.set(validated_data.get('hosts', instance.hosts))
+            instance.language.set(validated_data.get('language', instance.language))
+            instance.topic.set(validated_data.get('topic', instance.topic))
+            instance.musicfocus.set(validated_data.get('musicfocus', instance.musicfocus))
             instance.type = validated_data.get('type', instance.type)
             instance.fundingcategory = validated_data.get('fundingcategory', instance.fundingcategory)
             instance.predecessor = validated_data.get('predecessor', instance.predecessor)
@@ -343,7 +352,6 @@ class ScheduleSerializer(serializers.ModelSerializer):
         schedule.save()
         return schedule
 
-
     def update(self, instance, validated_data):
         """Update and return an existing Schedule instance, given the validated data."""
 
@@ -353,7 +361,7 @@ class ScheduleSerializer(serializers.ModelSerializer):
         instance.tend = validated_data.get('tend', instance.tend)
         instance.until = validated_data.get('until', instance.until)
         instance.is_repetition = validated_data.get('is_repetition', instance.is_repetition)
-        instance.fallback_id = validated_data.get('fallback_id', instance.fallback_id)
+        instance.default_playlist_id = validated_data.get('default_playlist_id', instance.default_playlist_id)
         instance.automation_id = validated_data.get('automation_id', instance.automation_id)
         instance.rrule = validated_data.get('rrule', instance.rrule)
         instance.show = validated_data.get('show', instance.show)
@@ -376,7 +384,6 @@ class TimeSlotSerializer(serializers.ModelSerializer):
         """Create and return a new TimeSlot instance, given the validated data."""
         return TimeSlot.objects.create(**validated_data)
 
-
     def update(self, instance, validated_data):
         """Update and return an existing Show instance, given the validated data."""
 
@@ -392,9 +399,10 @@ class NoteSerializer(serializers.ModelSerializer):
     show = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all())
     timeslot = serializers.PrimaryKeyRelatedField(queryset=TimeSlot.objects.all())
     host = serializers.PrimaryKeyRelatedField(queryset=Host.objects.all())
-    thumbnails = serializers.SerializerMethodField() # Read-only
+    thumbnails = serializers.SerializerMethodField()  # Read-only
 
-    def get_thumbnails(self, note):
+    @staticmethod
+    def get_thumbnails(note):
         """Returns thumbnails"""
         thumbnails = []
 
@@ -404,12 +412,10 @@ class NoteSerializer(serializers.ModelSerializer):
 
         return thumbnails
 
-
     class Meta:
         model = Note
         fields = '__all__'
 
-
     def create(self, validated_data):
         """Create and return a new Note instance, given the validated data."""
 
@@ -422,7 +428,7 @@ class NoteSerializer(serializers.ModelSerializer):
         note = Note.objects.create(**validated_data)
 
         # Assign note to timeslot
-        if note.timeslot_id != None:
+        if note.timeslot_id is not None:
             try:
                 timeslot = TimeSlot.objects.get(pk=note.timeslot_id)
                 timeslot.note_id = note.id
@@ -432,7 +438,6 @@ class NoteSerializer(serializers.ModelSerializer):
 
         return note
 
-
     def update(self, instance, validated_data):
         """Update and return an existing Note instance, given the validated data."""
 
@@ -458,7 +463,7 @@ class NoteSerializer(serializers.ModelSerializer):
             ts.save(update_fields=["note_id"])
 
         # Assign note to timeslot
-        if instance.timeslot.id != None:
+        if instance.timeslot.id is not None:
             try:
                 timeslot = TimeSlot.objects.get(pk=instance.timeslot.id)
                 timeslot.note_id = instance.id
@@ -466,4 +471,4 @@ class NoteSerializer(serializers.ModelSerializer):
             except ObjectDoesNotExist:
                 pass
 
-        return instance
\ No newline at end of file
+        return instance
diff --git a/program/templates/boxes/category.html b/program/templates/boxes/category.html
deleted file mode 100644
index 85520b1c51882a0443d78b3e3e6e0742afc0c24b..0000000000000000000000000000000000000000
--- a/program/templates/boxes/category.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% if category_list %}
-    <dl id="filterbox_category" class="portlet filterbox">
-        <dt class="portletHeader"><span>Sendungsinfo<span></dt>
-        <dd class="portletItem">
-            <ul>
-                {% for ca in category_list %}
-                    <li>
-                        <a title="Sendungen mit der Kategorie {{ ca.category }} anzeigen."
-                           class="abbrev ca-{{ ca.abbrev }}"
-                           href="?category={{ ca.slug }}">{{ ca.category }}</a>
-                    </li>
-                {% endfor %}
-            </ul>
-        </dd>
-    </dl>
-{% endif %}
\ No newline at end of file
diff --git a/program/templates/boxes/current.html b/program/templates/boxes/current.html
deleted file mode 100644
index add51f5e1a54733fd047275a1e5f0b6b5f9d1c18..0000000000000000000000000000000000000000
--- a/program/templates/boxes/current.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!doctype html>
-<html>
-<head>
-    <meta charset="utf-8"/>
-    <title>Current program box</title>
-</head>
-<body>
-{% if previous_timeslot or current_timeslot or next_timeslot or after_next_timeslot %}
-    <dl id="program-current-box" class="portlet program-box">
-        <dt class="portletHeader">Programm derzeit</dt>
-        <dd class="portletItem">
-            <table>
-                <tr class="previous">
-                    <td class="start">{{ previous_timeslot.start|date:"H:i" }}</td>
-                    <td class="type ty-{{ previous_timeslot.show.type.slug }}"
-                        title="{{ previous_timeslot.show.type.type }}">&nbsp;</td>
-                    <td class="show">
-                        <h3>
-                            <a href="{% url "timeslot-detail" previous_timeslot.id %}">{{ previous_timeslot.show.name }}</a>
-                        </h3>
-                    </td>
-                    <td class="show"></td>
-                </tr>
-                <tr class="current">
-                    <td class="start">{{ current_timeslot.start|date:"H:i" }}</td>
-                    <td class="type ty-{{ current_timeslot.show.type.slug }}"
-                        title="{{ current_timeslot.show.type.type }}">&#x25B6;</td>
-                    <td class="show">
-                        <h3>
-                            <a href="{% url "timeslot-detail" current_timeslot.id %}">{{ current_timeslot.show.name }}</a>
-                        </h3>
-                        {% if current_timeslot.note %}
-                            <p>{{ current_timeslot.note.title }}</p>
-                        {% else %}
-                            <p>{{ current_timeslot.show.short_description }}</p>
-                        {% endif %}
-                    </td>
-                </tr>
-                <tr class="next">
-                    <td class="start">{{ next_timeslot.start|date:"H:i" }}</td>
-                    <td class="type ty-{{ next_timeslot.show.type.slug }}"
-                        title="{{ next_timeslot.show.type.type }}">&nbsp;</td>
-                    <td class="show">
-                        <h3><a href="{% url "timeslot-detail" next_timeslot.id %}">{{ next_timeslot.show.name }}</a>
-                        </h3>
-                    </td>
-                    <td class="show"></td>
-                </tr>
-                <tr class="after_next">
-                    <td class="start">{{ after_next_timeslot.start|date:"H:i" }}</td>
-                    <td class="type ty-{{ after_next_timeslot.show.type.slug }}"
-                        title="{{ after_next_timeslot.show.type.type }}">&nbsp;</td>
-                    <td class="show">
-                        <h3>
-                            <a href="{% url "timeslot-detail" after_next_timeslot.id %}">{{ after_next_timeslot.show.name }}</a>
-                        </h3>
-                    </td>
-                    <td class="show"></td>
-                </tr>
-            </table>
-        </dd>
-    </dl>
-{% endif %}
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/boxes/musicfocus.html b/program/templates/boxes/musicfocus.html
deleted file mode 100644
index 021185b01ef905dd879cd91563c6938771b960db..0000000000000000000000000000000000000000
--- a/program/templates/boxes/musicfocus.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% if musicfocus_list %}
-    <dl id="filterbox_musicfocus" class="portlet filterbox">
-        <dt class="portletHeader"><span>Musiktendenz<span></dt>
-        <dd class="portletItem">
-            <ul>
-                {% for mf in musicfocus_list %}
-                    <li>
-                        <a title="Sendungen mit der Musiktendenz {{ mf.focus }} anzeigen."
-                           class="abbrev mf-{{ mf.abbrev }}" href="?musicfocus={{ mf.slug }}">{{ mf.focus }}</a>
-                    </li>
-                {% endfor %}
-            </ul>
-        </dd>
-    </dl>
-{% endif %}
diff --git a/program/templates/boxes/recommendation.html b/program/templates/boxes/recommendation.html
deleted file mode 100644
index 9ac8625b0ab68db1243f907bac360fb17f9a5f5a..0000000000000000000000000000000000000000
--- a/program/templates/boxes/recommendation.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!doctype html>
-<html>
-<head>
-    <meta charset="utf-8"/>
-    <title>Recomendations box</title>
-</head>
-<body>
-{% if recommendation_list %}
-    <dl id="recommendations" class="portlet program-box">
-        <dt class="portletHeader">Programmhinweise</dt>
-        <dd class="portletItem">
-            <table>
-                {% for recommendation in recommendation_list %}
-                    <tr>
-                        <td class="start">&nbsp;</td>
-                        <td class="type ty-{{ recommendation.show.type.slug }}"
-                            title="{{ recommendation.show.type.type }}">&nbsp;</td>
-                        <td class="show">
-                            {{ recommendation.start|date:"d.m. H:i" }} - {{ recommendation.end|date:"H:i" }}<br/>
-                            <h3>
-                                <a href="{% url "timeslot-detail" recommendation.id %}">{{ recommendation.show.name }}</a>
-                            </h3>
-                            <p class="note-title">
-                                {% if recommendation.note %}
-                                    {{ recommendation.note.title }}<br/>
-                                {% else %}
-                                    {{ recommendation.show.type.type }}<br/>
-                                {% endif %}
-                                <a href="{% url "timeslot-detail" recommendation.id %}">[weiter]</a>
-                            </p>
-                        </td>
-                    </tr>
-                {% endfor %}
-            </table>
-        </dd>
-    </dl>
-{% endif %}
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/boxes/showinformation.html b/program/templates/boxes/showinformation.html
deleted file mode 100644
index dbbe60dfc09f72304fa408d90d02702eb735f7cc..0000000000000000000000000000000000000000
--- a/program/templates/boxes/showinformation.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% if showinformation_list %}
-    <dl id="filterbox_showinformation" class="portlet filterbox">
-        <dt class="portletHeader"><span>Sendungsinfo<span></dt>
-        <dd class="portletItem">
-            <ul>
-                {% for si in showinformation_list %}
-                    <li>
-                        <a title="Sendungen mit der Information {{ si.information }} anzeigen."
-                           class="abbrev si-{{ si.abbrev }}"
-                           href="?showinformation={{ si.slug }}">{{ si.information }}</a>
-                    </li>
-                {% endfor %}
-            </ul>
-        </dd>
-    </dl>
-{% endif %}
diff --git a/program/templates/boxes/showtopic.html b/program/templates/boxes/showtopic.html
deleted file mode 100644
index 93e873a9367f5df84f99f713c2ea233134b8e487..0000000000000000000000000000000000000000
--- a/program/templates/boxes/showtopic.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% if showtopic_list %}
-    <dl id="filterbox_showtopic" class="portlet filterbox">
-        <dt class="portletHeader"><span>Thema / Schwerpunkt<span></dt>
-        <dd class="portletItem">
-            <ul>
-                {% for showtopic in showtopic_list %}
-                    <li>
-                        <a title="Sendungen mit dem Schwerpunkt {{ showtopic.topic }} anzeigen."
-                           class="abbrev st-{{ showtopic.abbrev }}"
-                           href="?showtopic={{ showtopic.slug }}">{{ showtopic.topic }}</a>
-                    </li>
-                {% endfor %}
-            </ul>
-        </dd>
-    </dl>
-{% endif %}
diff --git a/program/templates/boxes/topic.html b/program/templates/boxes/topic.html
deleted file mode 100644
index 7cbab0b6e42d0f05673e2caaf5f9e6146277ed33..0000000000000000000000000000000000000000
--- a/program/templates/boxes/topic.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% if topic_list %}
-    <dl id="filterbox_topic" class="portlet filterbox">
-        <dt class="portletHeader"><span>Thema / Schwerpunkt<span></dt>
-        <dd class="portletItem">
-            <ul>
-                {% for topic in topic_list %}
-                    <li>
-                        <a title="Sendungen mit dem Schwerpunkt {{ topic.topic }} anzeigen."
-                           class="abbrev to-{{ topic.abbrev }}"
-                           href="?topic={{ topic.slug }}">{{ topic.topic }}</a>
-                    </li>
-                {% endfor %}
-            </ul>
-        </dd>
-    </dl>
-{% endif %}
\ No newline at end of file
diff --git a/program/templates/boxes/type.html b/program/templates/boxes/type.html
deleted file mode 100644
index 6fb2deff601dcea79861b986b3225e03ec6011fb..0000000000000000000000000000000000000000
--- a/program/templates/boxes/type.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% if type_list %}
-    <dl id="type" class="portlet">
-        <dt class="portletHeader"><span>Legende</span></dt>
-        {% for ty in type_list %}
-            <dd class="portletItem type ty-{{ ty.slug }}">
-                <a title="Sendungen mit dem Sendungsformat {{ ty.type }} anzeigen."
-                   href="?type={{ ty.slug }}">{{ type.type }}</a>
-            </dd>
-        {% endfor %}
-    </dl>
-{% endif %}
\ No newline at end of file
diff --git a/program/templates/calendar.html b/program/templates/calendar.html
deleted file mode 100644
index 41d593365287344df187d8833997ab005fe87fea..0000000000000000000000000000000000000000
--- a/program/templates/calendar.html
+++ /dev/null
@@ -1,283 +0,0 @@
-<!doctype html>
-<html>
-<head>
-    <title>Kalender</title>
-    <link rel="stylesheet" href="/program/styles.css" type="text/css" />
-    <link rel="stylesheet" href="/static/admin/css/base.css" type="text/css" />
-    <!--<link rel="stylesheet" href="/static/admin/css/forms.css" type="text/css" />-->
-    <link rel="stylesheet" href="/site_media/js/calendar/lib/cupertino/jquery-ui.min.css" type="text/css" media="all" />
-    <link rel="stylesheet" href="/site_media/js/calendar/fullcalendar.min.css" type="text/css" media="all" />
-
-    <script type="text/javascript" src="/site_media/js/jquery/jquery.js"></script>
-    <script type="text/javascript" src="/site_media/js/calendar/lib/moment.min.js"></script>
-    <script type="text/javascript" src="/site_media/js/calendar/fullcalendar.min.js"></script>
-    <script type="text/javascript" src="/site_media/js/calendar/locale-all.js"></script>
-
-    <style type="text/css">
-    /* Calendar Screen */
-
-    /* Sidebar */
-    #sidebar {
-      width:calc( 20% - 40px );
-      position:fixed;
-      top:0px;
-      bottom:0;
-      right:0;
-      padding:10px 30px;
-      background-color:#eee;
-    }
-
-    #calendar {
-      width:calc( 80% - 40px );
-      float:left;
-    }
-
-    /* Notification popup */
-    #notification {
-      display:none;
-      z-index:9999999;
-      position:fixed;
-      width:300px;
-      left:50%;
-      margin-left:-150px;
-      top:33%;
-      padding: 40px 0px 40px 0px;
-      -moz-box-shadow:0px 0px 5px 1px #ccc;
-      -webkit-box-shadow:0px 0px 5px 1px #ccc;
-      box-shadow:0px 0px 5px 1px #ccc;
-      background-color:#FFFBCC;
-      text-align:center;
-      vertical-align:middle;
-      font-size:1.5em;
-      font-weight:bold;
-    }
-
-    /* Close button for each event */
-    .closeon {
-       display:none; /* Visibility is triggered by mouseover/mouseout */
-       position:absolute;
-       right:0;
-       top:0;
-       padding: 1px 4px;
-       border: 1px solid #000;
-       background: #fff;
-       opacity: .5;
-       color: black;
-       border-radius: 10px;
-       font-size:.8em;
-    }
-
-    .default {
-       background-color:#3a87ad;
-    }
-    .danger {
-       background-color:#D60935;
-       border-color:#222;
-    }
-
-    </style>
-
-</head>
-<body>
-<div id="notification"></div>
-
-<div id="container">
-  {% csrf_token %}
-  <div id="header">Kalender</div>
-  <div class="breadcrumb"></div>
-
-  <div id="content">
-
-    <h1></h1>
-
-    <div class="calendar-container">
-      <div id="calendar"></div>
-      <div id="sidebar">
-        <!--<div id="timeslot-id"></div>-->
-        <div>
-          <span id="show-name"></span>
-          <span id="show-id"></span>
-        </div>
-        <div id="timeslot-start"></div>
-        <div id="timeslot-end"></div>
-        <p></p>
-        <div id="playlist-id"></div>
-        <div id="is-repetition"></div>
-        <div id="fallback-id"></div>
-        <p></p>
-        <div id="show-hosts"></div>
-        <div id="show-categories"></div>
-        <div id="show-type"></div>
-        <div id="show-musicfocus"></div>
-        <div id="show-fundingcategory"></div>
-        <p></p>
-        <div id="memo"></div>
-        <div id="response-message"></div>
-      </div>
-    </div>
-
-  </div>
-
-</div>
-
-    <script>
-
-    /* Displays a message to the user after receiving an AJAX response */
-    function notify(msg) {
-    	var notify = jQuery("#notification");
-    	notify.html(msg);
-    	notify.show();
-    	notify.fadeOut(2000);
-    }
-
-    /**
-     * Makes sure the csrftoken get submitted properly
-     * See https://stackoverflow.com/questions/35112451/forbidden-csrf-token-missing-or-incorrect-django-error
-     */
-    function getCookie(name) {
-        var cookieValue = null;
-        if (document.cookie && document.cookie != '') {
-            var cookies = document.cookie.split(';');
-            for (var i = 0; i < cookies.length; i++) {
-                var cookie = jQuery.trim(cookies[i]);
-                // Does this cookie string begin with the name we want?
-                if (cookie.substring(0, name.length + 1) == (name + '=')) {
-                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
-                    break;
-                }
-            }
-        }
-        return cookieValue;
-    }
-    var csrftoken = getCookie('csrftoken');
-    function csrfSafeMethod(method) {
-        // These HTTP methods do not require CSRF protection
-        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
-    }
-
-    jQuery(document).ready( function() {
-
-       jQuery("#calendar").fullCalendar({
-          theme: true, // Enable theme
-          timezone: 'Europe/Berlin',
-          locale: 'de', // TODO: make an option for that
-          defaultView: 'agendaWeek',
-          // Event dragging & resizing
-          editable: false,
-          // Header
-          header: {
-            left: 'prev,next today',
-            center: 'title',
-            right: 'agendaWeek,agendaDay'
-          },
-          weekNumberCalculation: 'ISO', // Week begins with Monday
-          firstDay: 1, // Week begins with Monday
-          events: '/api/v1/program/week',
-          eventRender: function(event, element) {
-             element.find('.fc-content').append( '<span class="closeon">X</span>' );
-             element.find('.closeon').click(function() {
-                // Confirm
-                if( ! confirm( "Wollen Sie diese Episode wirklich löschen?" ) )
-                   return false;
-
-                jQuery.ajaxSetup({
-                  beforeSend: function(xhr, settings) {
-                    if( ! csrfSafeMethod(settings.type) && ! this.crossDomain) {
-                      xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken') );
-                    }
-                  }
-                });
-
-                jQuery.ajax({
-                  url: '/api/v1/shows/' + event.show_id + '/timeslots/' + event._id + '/',
-                  type: 'DELETE',
-                  success: function(result) {
-                    jQuery('#calendar').fullCalendar('removeEvents', event._id );
-                    notify( 'Timeslot deleted.' );
-                  },
-                  error: function(request, msg, error) {
-                    notify( 'Delete failed: ' + request.responseJSON.detail );
-                    console.log(error)
-                    console.log(request)
-                  }
-                });
-
-             });
-          },
-          // Triggered when the user mouses over an event.
-          eventMouseover: function( event, jsEvent, view ) {
-             jQuery(this).find('.closeon').show();
-          },
-          // Triggered when the user mouses out an event.
-          eventMouseout: function( event, jsEvent, view ) {
-             jQuery(this).find('.closeon').hide();
-          },
-          // Triggered when an event was clicked
-          // Load the timeslot into the sidebar form
-          eventClick: function(calEvent, jsEvent, view) {
-          	console.log(calEvent);
-
-            jQuery("#timeslot-id").html(calEvent.id);
-            jQuery("#timeslot-start").html('Start: ' + moment(calEvent.start).format("DD.MM. YYYY HH:SS"));
-            jQuery("#timeslot-end").html('End: ' + moment(calEvent.end).format("DD.MM. YYYY HH:SS"));
-            jQuery("#show-name").html(calEvent.show_name);
-            jQuery("#show-id").html('(ID ' + calEvent.show_id + ')');
-            jQuery("#show-hosts").html('Hosts: ' + calEvent.show_hosts);
-            jQuery("#show-type").html('Type: ' + calEvent.show_type);
-            jQuery("#show-categories").html('Categories: ' + calEvent.show_categories);
-            jQuery("#show-topics").html('Topics: ' + calEvent.show_topics);
-            jQuery("#show-musicfocus").html('Music focus: ' + calEvent.show_musicfocus);
-            jQuery("#show-fundingcategory").html('Funding category: ' + calEvent.show_fundingcategory);
-            jQuery("#is-repetition").html('Is repetition: ' + calEvent.is_repetition);
-            jQuery("#playlist-id").html('Playlist ID: ' + calEvent.playlist_id);
-            jQuery("#fallback-id").html('Fallback ID: ' + calEvent.fallback_id);
-            jQuery("#memo").html(calEvent.memo);
-
-          },
-          // How is this callback triggered?
-          select: function( start, end, jsEvent, view ) {
-             console.log("Selected: " + start + " - " + end );
-          },
-          // Triggered when event dragging stops - BUT BEFORE data was updated
-          /*   eventDragStop: function( event, jsEvent, ui, view ) {
-             updateTimeslot( event );
-          }, */
-          // Triggered when resizing stops and the event has changed in duration.
-          eventResize: function( event, jsEvent, ui, view ) {
-             updateTimeslot( event );
-          },
-          // Triggered when dragging stops and the event has moved to a different day/time.
-          eventDrop: function( event, delta, revertFunc, jsEvent, ui, view ) {
-          	 updateTimeslot( event );
-          }
-
-       });
-    });
-
-/*
-    function updateTimeslot( event ) {
-
-       var id = event.id;
-       // Use moment.utc() to avoid the offset being added to times
-       var date = moment.utc( event.start._d ).format('YYYY-MM-DD');
-       var start = moment.utc( event.start._d ).format('HH:mm') + ':00';
-       var stop = moment.utc( event.end._d ).format('HH:mm') + ':00';
-
-       console.log( event );
-       console.log( "program_id: " + event.id + " date: " + date + " start: " + start + " stop: " + stop );
-
-       jQuery.post( ajaxurl, { 'action': 'update_timeslot', 'id': id, 'date': date, 'start': start, 'stop' : stop } )
-       .done(function( data ) {
-          notify( 'Changes saved.' );
-          console.log(data.result);
-       })
-       .fail(function( data ) {
-          notify( data.result );
-       });
-
-    }
-*/
-    </script>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/collisions.html b/program/templates/collisions.html
deleted file mode 100644
index c2ad336e7b8e742c4a287cfdc0ec0f97a2bb9b26..0000000000000000000000000000000000000000
--- a/program/templates/collisions.html
+++ /dev/null
@@ -1,301 +0,0 @@
-<!doctype html>
-<html>
-<head>
-    <title>Teste nach Terminkollisionen</title>
-    <link rel="stylesheet" href="/program/styles.css" type="text/css" />
-    <link rel="stylesheet" href="/static/admin/css/base.css" type="text/css" />
-    <script type="text/javascript" src="/site_media/js/jquery/jquery.js"></script>
-    <script type="text/javascript" src="/site_media/js/jquery/ui/core.min.js"></script>
-    <script type="text/javascript" src="/site_media/js/jquery/ui/widget.min.js"></script>
-    <script type="text/javascript" src="/site_media/js/jquery/ui/mouse.min.js"></script>
-    <script type="text/javascript" src="/site_media/js/jquery/ui/draggable.min.js"></script>
-    <script type="text/javascript" src="/site_media/js/jquery/ui/droppable.min.js"></script>
-</head>
-<body>
-
-<div id="container">
-
-  <div id="header">Timeslots (Schritt {{ step|add:"-1" }} / {{ max_steps }})</div>
-  <div class="breadcrumb"></div>
-
-  <div id="content">
-
-  <h1>Termine &amp; Kollisionen</h1>
-
-    <div id="content-main">
-
-      <strong>{{ schedule.show }}</strong>
-      <p>{{ schedule }}</p>
-      <p>
-        {{ timeslots|length }} Timeslots generiert.
-        {% if self.num_collisions > 0 %}
-           Davon kollidieren {{ self.num_collisions }}.
-        {% endif %}
-      </p>
-
-      <form id="collisions_form" action="/admin/program/show/{{ schedule.show_id }}/change/" enctype="multipart/form-data" method="post">
-      {% csrf_token %}
-
-        <table class="table">
-        <thead>
-          <tr>
-            <th class="table-head">Gew&uuml;nschter Termin <span class="check-all projected">&#10003;</span> </th>
-            <th class="table-head"><span class="check-all collision">&#10003;</span> kollidiert mit</th>
-          </tr>
-        </thead>
-        <tbody>
-          {% for timeslot, collision in timeslots_to_collisions %}
-            {% if timeslot.start|date:"U" < now|date:"U" %}
-              <tr class="table-row past" id="row-{{ forloop.counter0 }}">
-                <td class="table-cell">
-                  <label>
-                    <span class="timeslot-date">{{ timeslot.start|date:"D, d.m. Y "}}</span>
-                    <span class="timeslot-time">{{ timeslot.start|date:"H:i"}} - {{ timeslot.end|date:"H:i" }} Uhr</span>
-                  </label>
-                </td>
-                <td class="table-cell">
-                  <label>
-                    <input type="radio" name="resolved_timeslots[{{ forloop.counter0 }}]" value="{{ collision.id }}" id="collision-{{ forloop.counter0 }}" checked="checked" style="display:none;" />
-                    <span>Timeslot liegt in der Vergangenheit</span>
-                  </label>
-                </td>
-              </tr>
-            {% else %}
-
-              {% if collision != None %}
-              <tr class="table-row" id="row-{{ forloop.counter0 }}">
-                <td class="table-cell projected keep" timeslot_index="{{ forloop.counter0 }}">
-                  <div class="droppable">
-                  <label for="timeslot-{{ forloop.counter0 }}" class="noselect">
-                    <input type="radio" name="resolved_timeslots[{{ forloop.counter0 }}]" value="{{ timeslot.start|date:"Y-m-d H:i:s"}} - {{ timeslot.end|date:"Y-m-d H:i:s" }}" checked="checked" id="timeslot-{{ forloop.counter0 }}" />
-                    <span>
-                      <span class="timeslot-date">{{ timeslot.start|date:"D, d.m. Y "}}</span>
-                      <span class="timeslot-time">{{ timeslot.start|date:"H:i"}} - {{ timeslot.end|date:"H:i" }} Uhr</span>
-                    </span>
-                  </label>
-                  </div>
-                </td>
-                <td class="table-cell collision remove" timeslot_id="{{ collision.id }}">
-                  <div class="droppable">
-                  <label for="collision-{{ forloop.counter0 }}" class="noselect">
-                    <input type="radio" name="resolved_timeslots[{{ forloop.counter0 }}]" value="{{ collision.id }}" id="collision-{{ forloop.counter0 }}" />
-                    <span>
-                      <span class="timeslot-date">{{ collision.start|date:"D, d.m. Y"}}</span>
-                      <span class="timeslot-time">{{ collision.start|date:"H:i"}} - {{ collision.end|date:"H:i" }} Uhr</span>
-                      <span class="timeslot-show">{{ collision.show }}</span>
-                    </span>
-                  </label>
-                  </div>
-                  {% for note in self.notes %}
-                    {% if collision.id == note.timeslot_id %}
-                    <div id="collision-note-{{ forloop.counter0 }}" class="collision-note draggable" note_id="{{ note.id }}">
-                      <strong>Note: {{ note.title }}</strong>
-                    </div>
-                    {% endif %}
-                  {% endfor %}
-
-                </td>
-              </tr>
-              {% else %}
-              <tr class="table-row projected keep">
-                <td class="table-cell projected" timeslot_index="{{ forloop.counter0 }}">
-                  <div class="droppable">
-                  <label for="timeslot-{{ forloop.counter0 }}" class="noselect">
-                      <span class="timeslot-date">{{ timeslot.start|date:"D, d.m. Y "}}</span>
-                      <span class="timeslot-time">{{ timeslot.start|date:"H:i"}} - {{ timeslot.end|date:"H:i" }} Uhr</span>
-                      <span>&#10003;</span>
-                  </label>
-                  <input type="radio" name="resolved_timeslots[{{ forloop.counter0 }}]" value="{{ timeslot.start|date:"Y-m-d H:i:s"}} - {{ timeslot.end|date:"Y-m-d H:i:s" }}" checked="checked" />
-                  </div>
-                </td>
-                <td class="table-cell projected">
-                  <label>nichts</label>
-                </td>
-              </tr>
-              {% endif %}
-
-            {% endif %}
-          {% endfor %}
-        </tbody>
-        </table>
-
-        {% for timeslot in timeslots %}
-          <input type="hidden" name="create_timeslots[{{ forloop.counter0 }}]" value="{{ timeslot.start|date:"Y-m-d H:i:s"}} - {{ timeslot.end|date:"Y-m-d H:i:s" }}" />
-        {% endfor %}
-
-        {% for collision in collisions %}
-          <input type="hidden" name="collisions[{{ forloop.counter0 }}]" value="{{ collision.id}}" />
-        {% endfor %}
-
-        <input type="hidden" name="ps_save_id" value="{{ schedule.id }}" />
-        <input type="hidden" name="ps_save_rrule_id" value="{{ schedule.rrule_id }}" />
-        <input type="hidden" name="ps_save_byweekday" value="{{ schedule.byweekday }}" />
-        <input type="hidden" name="ps_save_dstart" value="{{ schedule.dstart|date:"Y-m-d" }}" />
-        <input type="hidden" name="ps_save_tstart" value="{{ schedule.tstart }}" />
-        <input type="hidden" name="ps_save_tend" value="{{ schedule.tend }}" />
-        <input type="hidden" name="ps_save_until" value="{{ schedule.until|date:"Y-m-d" }}" />
-        <input type="hidden" name="ps_save_is_repetition" value="{{ schedule.is_repetition }}" />
-        <input type="hidden" name="ps_save_automation_id" value="{{ schedule.automation_id }}" />
-        <input type="hidden" name="ps_save_fallback_id" value="{{ schedule.fallback_id }}" />
-        <input type="hidden" name="ps_save_show_id" value="{{ schedule.show_id }}" />
-        <input type="hidden" name="ps_save_add_days_no" value="{{ schedule.add_days_no }}" />
-        <input type="hidden" name="ps_save_add_business_days_only" value="{{ schedule.add_business_days_only }}" />
-        <input type="hidden" name="num_inputs" value="{{ num_inputs }}" />
-        <input type="hidden" name="step" value="{{ step }}" />
-
-        <input type="hidden" name="num_ntind" value="0" id="ntind-num" />
-        <input type="hidden" name="num_ntids" value="0" id="ntids-num" />
-
-        <!-- Linking notes to timeslots that will be created -->
-        <div id="ntind"></div>
-
-        <!-- Linking notes to already existing timeslots -->
-        <div id="ntids"></div>
-
-        <div class="submit-row">
-          <input class="default" type="submit" name="_continue" value="Speichern" />
-          <p class="deletelink-box"><a href="/admin/program/show/{{ obj.id }}/change" class="deletelink">Abbrechen und &Auml;nderungen verwerfen</a></p>
-        </div>
-
-        <!-- TODO: Problemo: If form validation failed, submit will be prevented -> only include the fields necessary -->
-        <div style="display:none;">
-         {{ schedulesform.as_ul }}
-         {{ showform.as_ul }}
-        </div>
-
-      </form>
-
-    </div> <!-- /#content-main -->
-
-  </div> <!-- /#content -->
-
-</div> <!-- /#container -->
-
-<script type="text/javascript">
-
-jQuery(document).ready( function() {
-
-  /* Change classes if a timeslot or collision checked */
-  jQuery(document).on( 'click', 'input[name^="resolved_timeslots"]', function() {
-     var row_id = jQuery(this).closest('.table-row').attr('id');
-
-     if( jQuery(this).closest('.table-cell').hasClass('projected') ) {
-        jQuery('#' + row_id + ' .projected').removeClass('remove').addClass('keep');
-        jQuery('#' + row_id + ' .collision').removeClass('keep').addClass('remove');
-     } else {
-        jQuery('#' + row_id + ' .projected').removeClass('keep').addClass('remove');
-        jQuery('#' + row_id + ' .collision').removeClass('remove').addClass('keep');
-     }
-  });
-
-  /* Select a column (all projected timeslots or all collisions */
-  /* TODO: Not working */
-  jQuery(document).on( 'click', '.check-all', function() {
-
-     if( jQuery(this).hasClass('projected') ) {
-        jQuery('.projected input[name^="resolved_timeslots"]').attr('checked', 'checked');
-        jQuery('.collision input[name^="resolved_timeslots"]').removeAttr('checked');
-
-        console.log("check all projected");
-     }
-
-     if( jQuery(this).hasClass('collision') ) {
-        jQuery('.collision input[name^="resolved_timeslots"]').attr('checked', 'checked');
-        jQuery('.projected input[name^="resolved_timeslots"]').removeAttr('checked');
-        console.log("check all collisions");
-     }
-
-  });
-
-});
-
-  var ntind = []
-  var ntids = []
-
-  /* Redraws hidden inputs when a note was dropped to a timeslot */
-  function drawInputs(nts, name) {
-    jQuery('#' + name).html('');
-
-    for(index = 0; index < nts.length; ++index) {
-      jQuery('#' + name).append('<input type="hidden" name="' + name + '[' + index + '][id]" value="' + nts[index].id + '" />');
-      jQuery('#' + name).append('<input type="hidden" name="' + name + '[' + index + '][note_id]" value="' + nts[index].note_id + '" />');
-    }
-  }
-
-
-  /* The draggable note */
-  jQuery( function() {
-    jQuery( ".draggable" ).draggable({
-      revert: 'invalid',
-      snap: '.droppable',
-      snapMode: 'inner',
-      cursor: 'move',
-      drag: function() {
-      },
-      stop: function() {
-      }
-    });
-
-
-    /**
-     * When a note was dropped onto a timelost
-     * regenerate note/timeslot arrays for indices and ids and call drawInputs()
-     */
-    jQuery( ".droppable" ).droppable({
-      classes: {
-        "ui-droppable-active": "ui-state-active",
-        "ui-droppable-hover": "ui-state-hover"
-      },
-      drop: function( event, ui ) {
-        jQuery(this).parent("td").append( jQuery(ui.draggable).css({"top": 0, "left": 0 }) );
-
-        var note_id = jQuery(ui.draggable).attr("note_id");
-
-        if( jQuery(this).parent("td").hasClass("projected") ) {
-           // Dropped onto the left column
-
-           var ts_index = jQuery(this).parent("td").attr("timeslot_index");
-
-           // Remove note id from arrays if already existing
-           ntind = jQuery.grep(ntind, function(e){
-              return e.note_id != note_id;
-           });
-
-           ntids = jQuery.grep(ntind, function(e){
-              return e.note_id != note_id;
-           });
-
-           ntind.push({"id": ts_index, "note_id": note_id});
-
-        } else {
-           // Dropped onto the right column
-
-           var ts_id = jQuery(this).parent("td").attr("timeslot_id");
-
-           // Remove not id from arrays if already existing
-           ntids = jQuery.grep(ntind, function(e){
-              return e.note_id != note_id;
-           });
-
-           ntind = jQuery.grep(ntind, function(e){
-              return e.note_id != note_id;
-           });
-
-           ntids.push({"id": ts_id, "note_id": note_id});
-
-        }
-
-        jQuery("#ntind-num").val(ntind.length);
-        jQuery("#ntids-num").val(ntids.length);
-
-        drawInputs(ntind, "ntind");
-        drawInputs(ntids, "ntids");
-
-      }
-    });
-  } );
-
-</script>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/day_schedule.html b/program/templates/day_schedule.html
deleted file mode 100644
index e627292857f0ca80c5501d31edef00de2a8e3c37..0000000000000000000000000000000000000000
--- a/program/templates/day_schedule.html
+++ /dev/null
@@ -1,131 +0,0 @@
-<html>
-<head>
-    <title>Tagesansicht {{ day|date:"l, d.m.Y" }} &mdash; Radio Helsinki - Freies Radio Graz</title>
-    <script type="text/javascript" src="/program/static/js/jquery/jquery.min.js"></script>
-    <script type="text/javascript" src="/program/static/js/jquery-ui/jquery-ui.min.js"></script>
-    <script type="text/javascript" src="/program/static/js/jquery-ui/ui/jquery.ui.datepicker.min.js"></script>
-    <script type="text/javascript">
-        jQuery(document).ready(function () {
-            jQuery("#calendar").datepicker({
-                dateFormat: "yy.mm.dd",
-                monthNames: ["Jänner", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
-                monthNamesShort: ["Jän", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
-                dayNames: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
-                dayNamesMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
-                dayNamesShort: ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam"],
-                firstDay: 1,
-                nextText: "Weiter",
-                prevText: "Zurück",
-                defaultDate: location.href.split('/').slice(4, 7).join('.'),
-                onSelect: function (dateText, inst) {
-                    location = '/program/' + dateText.split('.').join('/');
-                }
-            });
-        });
-    </script>
-</head>
-<body>
-
-<dl id="box_calendar" class="portlet calendar">
-    <dt class="portletHeader"><span>Kalender<span></dt>
-    <dd class="portletItem">
-        <div id="calendar"></div>
-    </dd>
-</dl>
-
-{% load content_boxes %}
-<div id="filter-type">
-    {% type %}
-</div>
-
-{% comment %}
-<div id="filter-topic">
-  <dl id="filter-header" class="portlet">
-    <dt class="portletHeader"><span>Filter</span></dt>
-  </dl>
-{% musicfocus %}
-{% category %}
-{% topic %}
-</div>
-{% endcomment %}
-
-<div id="content-main" class="day-schedule">
-    <h2>Tagesansicht</h2>
-    <h1 id="date">{{ day|date:"l, d.m.Y" }}</h1>
-
-    <div id="timeslots">
-        {% for timeslot in timeslots %}
-            {% if forloop.first and timeslot.start != timeslot.get_previous_by_start.end %}
-                <div class="timeslot ty-{{ default_show.type.slug }}">
-                    <div class="show-start">{{ timeslot.get_previous_by_start.end|date:"H:i" }}</div>
-                    <div class="show-abbrevs">
-                        {% for ca in default_show.category.all %}
-                            <span title="{{ ca.category }}"
-                                  class="abbrev ca-{{ ca.abbrev }}"><span>{{ ca.abbrev }}</span></span>
-                        {% endfor %}
-                        {% for to in default_show.topic.all %}
-                            <span title="{{ to.topic }}" class="abbrev to-{{ to.abbrev }}"><span>{{ to.abbrev }}</span></span>
-                        {% endfor %}
-                        {% for mf in default_show.musicfocus.all %}
-                            <span title="{{ mf.focus }}" class="abbrev mf-{{ mf.abbrev }}"><span>{{ mf.abbrev }}</span></span>
-                        {% endfor %}
-                    </div>
-                    <div class="show-detail">
-                        <h3 class="show-title">{{ default_show.name }}</h3>
-                        <p class="show-description">{{ default_show.short_description }}</p>
-                    </div>
-                </div>
-            {% endif %}
-            <div class="timeslot bf-{{ timeslot.show.type.slug }}">
-                <div class="show-start">{{ timeslot.start|date:"H:i" }}</div>
-                <div class="show-abbrevs">
-                    {% for ca in timeslot.show.category.all %}
-                        <span title="{{ ca.category }}"
-                              class="abbrev ca-{{ ca.abbrev }}"><span>{{ ca.abbrev }}</span></span>
-                    {% endfor %}
-                    {% for to in timeslot.show.topic.all %}
-                        <span title="{{ to.topic }}"
-                              class="abbrev to-{{ to.abbrev }}"><span>{{ to.abbrev }}</span></span>
-                    {% endfor %}
-                    {% for mf in timeslot.show.musicfocus.all %}
-                        <span title="{{ mf.focus }}"
-                              class="abbrev mf-{{ mf.abbrev }}"><span>{{ mf.abbrev }}</span></span>
-                    {% endfor %}
-                </div>
-                <div class="show-detail">
-                    <h3 class="show-title"><a
-                            href="{% url "timeslot-detail" timeslot.id %}">{{ timeslot.show.name }}</a></h3>
-                    {% if timeslot.note %}
-                        <p class="note-title"><strong>Heute:</strong> {{ timeslot.note.title }}</p>
-                    {% else %}
-                        <p class="show-description">{{ timeslot.show.short_description }}</p>
-                    {% endif %}
-                </div>
-            </div>
-            {% if timeslot.end != timeslot.get_next_by_start.start %}
-                <div class="timeslot ty-{{ default_show.type.slug }}">
-                    <div class="show-start">{{ timeslot.end|date:"H:i" }}</div>
-                    <div class="show-abbrevs">
-                        {% for ca in default_show.category.all %}
-                            <span title="{{ ca.category }}"
-                                  class="abbrev ca-{{ ca.abbrev }}"><span>{{ ca.abbrev }}</span></span>
-                        {% endfor %}
-                        {% for to in default_show.topic.all %}
-                            <span title="{{ to.topic }}" class="abbrev to-{{ to.abbrev }}"><span>{{ to.abbrev }}</span></span>
-                        {% endfor %}
-                        {% for mf in default_show.musicfocus.all %}
-                            <span title="{{ mf.focus }}" class="abbrev mf-{{ mf.abbrev }}"><span>{{ mf.abbrev }}</span></span>
-                        {% endfor %}
-                    </div>
-                    <div class="show-detail">
-                        <h3 class="show-title">{{ default_show.name }}</h3>
-                        <p class="show-description">{{ default_show.short_description }}</p>
-                    </div>
-                </div>
-            {% endif %}
-        {% endfor %}
-    </div>
-</div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/host_detail.html b/program/templates/host_detail.html
deleted file mode 100644
index d8177481b825ee1428f19dcce552af3f1596f150..0000000000000000000000000000000000000000
--- a/program/templates/host_detail.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html>
-<head>
-    <title>Host: {{ host.name }} &mdash; Radio Helsinki - Freies Radio Graz</title>
-</head>
-<body>
-
-<div id="content-main" class="host-detail">
-    <div id="name">{{ host.name }}</div>
-
-    <div id="shows">
-        <div id="shows-title">Sendungen</div>
-        {% for show in host.active_shows %}
-            <div class="show {{ show.type.slug }}"><a href="{% url "show-detail" show.slug %}"> {{ show.name }}</a></div>
-        {% endfor %}
-    </div>
-
-    {% if host.email %}
-        <div id="email">E-Mail Adresse: <a href="{{ host.email }}">{{ host.email }}</a></div>
-    {% endif %}
-
-    {% if host.website %}
-        <div id="website">Website: <a href="{{ host.website }}">{{ host.website }}</a></div>
-    {% endif %}
-</div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/host_list.html b/program/templates/host_list.html
deleted file mode 100644
index ada9bf184ed38442673793da6196831a91a9112c..0000000000000000000000000000000000000000
--- a/program/templates/host_list.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<html>
-<head>
-    <title>Sendungsmacherinnen &mdash; Radio Helsinki - Freies Radio Graz</title>
-</head>
-<body>
-
-<div id="content-main">
-    <h1>Sendungsmachende A-Z</h1>
-    <div class="host-list">
-        {% for host in host_list %}
-            <div class="host">
-                <a href="{% url "host-detail" host.id %}">{{ host.name }}</a>
-            </div>
-        {% endfor %}
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/program/templates/recommendation_list.html b/program/templates/recommendation_list.html
deleted file mode 100644
index e0de76365698a2fc11ae5f9460e4a05959fbbffa..0000000000000000000000000000000000000000
--- a/program/templates/recommendation_list.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<html>
-<head>
-    <title>Tipps &mdash; Radio Helsinki - Freies Radio Graz</title>
-</head>
-<body>
-
-<div id="content-main" class="recommendations">
-    <h1>Programmhinweise</h1>
-    <div id="shows">
-        {% for recommendation in recommendation_list %}
-            <div class="show recommendation  ty-{{ recommendation.show.type.slug }}">
-                <div class="show-abbrevs">
-                    {% for ca in recommendation.show.category.all %}
-                        <span title="{{ ca.category }}"
-                              class="abbrev ca-{{ ca.abbrev }}"><span>{{ ca.abbrev }}</span></span>
-                    {% endfor %}
-                    {% for to in recommendation.show.topic.all %}
-                        <span title="{{ to.topic }}"
-                              class="abbrev to-{{ to.abbrev }}"><span>{{ to.abbrev }}</span></span>
-                    {% endfor %}
-                    {% for mf in recommendation.show.musicfocus.all %}
-                        <span title="{{ mf.focus }}"
-                              class="abbrev mf-{{ mf.abbrev }}"><span>{{ mf.abbrev }}</span></span>
-                    {% endfor %}
-                </div>
-                <div class="show-detail">
-                    <h4>
-                        <a href="{% url "show-detail" recommendation.show.slug %}">{{ recommendation.show.name }}</a><br/>
-                        vom {{ recommendation.start|date:"d.m. H:i" }}-{{ recommendation.end|date:"H:i" }}</h4>
-                    {% if recommendation.note %}
-                        <h3 class="show-title">
-                          <a href="{% url "timeslot-detail" recommendation.id %}">{{ recommendation.note.title }}</a>
-                        </h3>
-                        <div class="note-content">{{ recommendation.note.content|safe }}</div>
-                    {% else %}
-                        <h3 class="show-title"><a
-                                href="{% url "timeslot-detail" recommendation.id %}">{{ recommendation.show.type.type }}</a>
-                        </h3>
-                    {% endif %}
-                </div>
-            </div>
-        {% endfor %}
-    </div>
-</div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/show_detail.html b/program/templates/show_detail.html
deleted file mode 100644
index 43fd9a0b0be14b00f3e84ac92c52b29ac630210d..0000000000000000000000000000000000000000
--- a/program/templates/show_detail.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<html>
-<head>
-    <title>Sendung: {{ show.name }} &mdash; Radio Helsinki - Freies Radio Graz</title>
-</head>
-<body>
-
-<div id="calendar"></div>
-
-<div id="content-main" class="show-detail">
-
-    <div class="show-detail-header ty-{{ show.type.slug }}">
-        <div class="show-details">
-            <h1 id="name">{{ show.name }}</h1>
-            {% if show.id != 1 %}
-                <p id="schedules">
-                    {% for schedule in show.active_schedules %}
-                        <span class="schedule">{{ schedule }}</span><br/>
-                    {% endfor %}
-                </p>
-            {% endif %}
-        </div>
-
-        <div class="show-categorization">
-            <p id="type">{{ show.type.type }}</p>
-            {% for ca in show.category.all %}
-                <span title="{{ ca.category }}" class="abbrev ca-{{ ca.abbrev }}"><span>{{ ca.abbrev }}</span></span>
-            {% endfor %}
-            {% for to in show.topic.all %}
-                <span title="{{ to.topic }}" class="abbrev to-{{ to.abbrev }}"><span>{{ to.abbrev }}</span></span>
-            {% endfor %}
-            {% for mf in show.musicfocus.all %}
-                <span title="{{ mf.focus }}" class="abbrev mf-{{ mf.abbrev }}"><span>{{ mf.abbrev }}</span></span>
-            {% endfor %}
-        </div>
-
-    </div>
-
-    <div id="short-description" class="documentDescription">{{ show.short_description }}</div>
-
-    {% if show.description %}
-        <div id="description">{{ show.description|safe }}</div>
-    {% endif %}
-
-    {% if show.image %}
-        <div id="image" style="float: right;"><img src="/program/static/{{ show.image }}" width="200" alt="image"></div>
-    {% endif %}
-
-    <p>
-        {% for host in show.hosts.all %}
-            <a href="{% url "host-detail" host.id %}">{{ host }}</a><br/>
-        {% endfor %}
-        {% if show.email %}
-            <strong>Email:</strong> <a href="mailto:{{ show.email }}">{{ show.email }}</a><br/>
-        {% endif %}
-        {% if show.website %}
-            <strong>Website:</strong> <a href="{{ show.website }}">{{ show.website }}</a><br/>
-        {% endif %}
-    </p>
-
-    {% if show.notes.all %}
-        <br/>
-        <h2>Sendungstipps</h2>
-        <ul class="recommendations-list">
-            {% for note in show.notes.all reversed %}
-                <li>
-                    <a href="{% url "timeslot-detail" note.timeslot.id %}"
-                       title="{{ note.title }}">{{ note.start|date:"d. M Y" }}:</a>
-                    <div class="title">{{ note.title }}</div>
-                </li>
-            {% endfor %}
-            {% if show.predecessor and show.predecessor.notes.all %}
-                {% if show.name != show.predecessor.name %}
-                    <h3>Davor als <a href="{% url "show-detail" show.predecessor.slug %}">{{ show.predecessor.name }}</a></h3>
-                {%  endif %}
-                {% for note in show.predecessor.notes.all reversed %}
-                    <li>
-                        <a href="{%  url "timeslot-detail" note.timeslot.id %}"
-                           title="{{ note.title }}">{{ note.start|date:"d. M Y" }}:</a>
-                        <div class="title">{{ note.title }}</div>
-                    </li>
-                {% endfor %}
-            {% endif %}
-        </ul>
-    {% endif %}
-</div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/show_list.html b/program/templates/show_list.html
deleted file mode 100644
index d16c90ea6179b6f1cda8e089db7b156143c9b31b..0000000000000000000000000000000000000000
--- a/program/templates/show_list.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<html>
-<head>
-    <title>Sendungen &mdash; Radio Helsinki - Freies Radio Graz</title>
-</head>
-<body>
-
-{% load content_boxes %}
-<div id="filter-type">
-    {% type %}
-</div>
-<div id="filter-topic">
-    <dl id="filter-header" class="portlet">
-        <dt class="portletHeader"><span>Filter</span></dt>
-    </dl>
-    {% musicfocus %}
-    {% category %}
-    {% topic %}
-</div>
-
-<div id="content-main" class="show-list">
-    <h1>Sendungen A-Z</h1>
-
-    <div id="shows">
-        {% for show in show_list %}
-            <div class="show ty-{{ show.type.slug }}">
-                <div class="show-abbrevs">
-                    {% for ca in show.category.all %}
-                        <span title="{{ ca.category }}"
-                              class="abbrev ca-{{ ca.abbrev }}"><span>{{ ca.abbrev }}</span></span>
-                    {% endfor %}
-                    {% for to in show.topic.all %}
-                        <span title="{{ to.topic }}"
-                              class="abbrev to-{{ to.abbrev }}"><span>{{ to.abbrev }}</span></span>
-                    {% endfor %}
-                    {% for mf in show.musicfocus.all %}
-                        <span title="{{ mf.focus }}"
-                              class="abbrev mf-{{ mf.abbrev }}"><span>{{ mf.abbrev }}</span></span>
-                    {% endfor %}
-                </div>
-                <div class="show-detail">
-                    <h3 class="show-title"><a href="{% url "show-detail" show.slug %}">{{ show.name }}</a></h3>
-                    <ul class="show-schedules">
-                        {% for schedule in show.active_schedules %}
-                            <li class="show-schedule">{{ schedule }}</li>
-                        {% endfor %}
-                    </ul>
-                    <p class="show-description">{{ show.short_description }}</p>
-                </div>
-            </div>
-        {% endfor %}
-    </div>
-
-</div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/styles.css b/program/templates/styles.css
deleted file mode 100644
index e9b98eec7fb11fb840b0cc428461a2974abb9066..0000000000000000000000000000000000000000
--- a/program/templates/styles.css
+++ /dev/null
@@ -1,179 +0,0 @@
-{% for ty in types %}
-.ty-{{ ty.slug }} { background-color: {{ ty.color }}; color: {{ ty.text_color }}; }
-{% endfor %}
-
-{% for mf in musicfocus %}
-.mf-{{ mf.abbrev }} { background-image:url({{ mf.button_url }}); }
-.filterbox .mf-{{ mf.abbrev }}:hover { background-image:url({{ mf.button_hover_url }}); }
-{% endfor %}
-
-{% for ca in category %}
-.ca-{{ ca.abbrev }} { background-image:url({{ ca.button_url }}); }
-.filterbox .ca-{{ ca.abbrev }}:hover { background-image:url({{ ca.button_hover_url }}); }
-{% endfor %}
-
-{% for to in topic %}
-.to-{{ to.abbrev }} { background-image:url({{ to.button_url }}); }
-.filterbox .to-{{ to.abbrev }}:hover { background-image:url({{ to.button_hover_url }}); }
-{% endfor %}
-
-{% for mf in musicfocus %}
-.show-detail-header .mf-{{ mf.abbrev }} { background-image:url({{ mf.big_button_url }}); }
-{% endfor %}
-
-{% for ca in category %}
-.show-detail-header .ca-{{ ca.abbrev }} { background-image:url({{ ca.big_button_url }}); }
-{% endfor %}
-
-{% for to in topic %}
-.show-detail-header .to-{{ to.abbrev }} { background-image:url({{ to.big_button_url }}); }
-{% endfor %}
-
-
-.draggable {
-  border:1px dashed #bbb;
-  cursor:move;
-}
-
-.ui-draggable-dragging {
-  background:#fff;
-  border-color:#222;
-}
-
-.projected.droppable {
-   display:none;
-}
-
-.table { display:table; width:100%; border-collapse:collapse; }
-.table-row { display:table-row; }
-.table-heading { display:table-header-group; background-color:#ddd; font-weight:bold; }
-.table-body { display:table-row-group; }
-.table-foot { display:table-footer-group; font-weight:bold; background-color:#ddd; }
-.table-cell { display:table-cell; vertical-align:top; border:1px solid #777; padding:0; line-height:40px; width:50%; }
-.table-head { display:table-cell; vertical-align:top; border:1px solid #777; padding:0 20px; line-height:40px; background-color:#333; color:#fff; font-weight:bold; }
-
-.table td.table-cell {
-   padding:0;
-   line-height:40px;
-   vertical-align:top;
-}
-
-.timeslot-date {
-   display:inline-block;
-   width:130px;
-}
-
-.timeslot-time {
-   display:inline-block;
-   width:150px;
-}
-
-.past { background-color:#ddd; color:#000; }
-.keep { background-color:#B3E6BA; }
-.remove { background-color:#eee; }
-
-.collision-note {
-   padding-left:20px;
-}
-
-.table-cell label {
-  display:block;
-  cursor:pointer;
-  line-height:2em;
-  padding:10px 20px;
-}
-
-/* Radio buttons */
-.table-cell input[type="radio"] {
-  border:0;
-  clip:rect(0 0 0 0);
-  height:1px;
-  margin:-1px;
-  overflow:hidden;
-  padding:0;
-  position:absolute;
-  width:1px;
-}
-
-.table-cell.projected input[type="radio"] + span {
-  display: block;
-}
-
-/* Unchecked style */
-.table-cell.projected input[type="radio"] + span::before {
-  content:'';
-  float:right;
-  width:1.5em;
-  height:1.5em;
-  border-radius:1.5em;
-  border:1px solid #fff;
-  box-shadow:0 0 0 0.15em #000;
-  margin:.3em;
-  /*transition:0.5s ease all;*/
-
-}
-
-/* Checked style */
-.table-cell.projected input[type="radio"]:checked + span::before {
-  background:green;
-  box-shadow:0 0 0 0.25em #000;
-}
-
-.table-cell.projected input[type="radio"]:focus + span::after {
-}
-
-
-.table-cell.collision input[type="radio"] + span {
-  display: block;
-}
-
-/* Unchecked style */
-.table-cell.collision input[type="radio"] + span::before {
-  content:'';
-  float:left;
-  width:1.5em;
-  height:1.5em;
-  border-radius:1.5em;
-  border:1px solid #fff;
-  box-shadow:0 0 0 0.15em #000;
-  margin:.3em;
-  margin-right:25px;
-  /*transition:0.5s ease all;*/
-}
-
-/* Checked style */
-.table-cell.collision input[type="radio"]:checked + span::before {
-  background:green;
-  box-shadow:0 0 0 0.25em #000;
-}
-
-.table-cell.collision input[type="radio"]:focus + span::after {
-}
-
-.check-all {
-   font-size:15px;
-   text-align:center;
-   width:30px;
-}
-
-.check-all.projected {
-   float:right;
-}
-
-.check-all.collision {
-   float:left;
-}
-
-.validation-error {
-   border:2px solid #ba2121 !important;
-}
-
-.noselect {
-  -webkit-touch-callout: none; /* iOS Safari */
-    -webkit-user-select: none; /* Safari */
-     -khtml-user-select: none; /* Konqueror HTML */
-       -moz-user-select: none; /* Firefox */
-        -ms-user-select: none; /* Internet Explorer/Edge */
-            user-select: none; /* Non-prefixed version, currently
-                                  supported by Chrome and Opera */
-}
\ No newline at end of file
diff --git a/program/templates/timeslot_detail.html b/program/templates/timeslot_detail.html
deleted file mode 100644
index 5914548dba573c06154f420863d5125b1020781d..0000000000000000000000000000000000000000
--- a/program/templates/timeslot_detail.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<html>
-<head>
-    <title>Sendung: {{ timeslot.show.name }} &mdash; Radio Helsinki - Freies Radio Graz</title>
-</head>
-<body>
-
-<div id="content-main" class="timeslot-detail">
-
-    <div class="show-detail-header ty-{{ timeslot.show.type.slug }}">
-        <h1 id="name">
-            <a href="{% url "show-detail" timeslot.show.slug %}">{{ timeslot.show.name }}</a>
-        </h1>
-        {% if timeslot.note %}
-            <h2>{{ timeslot.note.title }}</h2>
-        {% endif %}
-        <strong>Sendung am {{ timeslot.start|date:"d.m.Y H:i" }} bis {{ timeslot.end|date:"H:i" }}</strong>
-
-        <div class="show-abbrevs">
-            {% for ca in timeslot.show.category.all %}
-                <span title="{{ ca.category }}" class="abbrev ca-{{ ca.abbrev }}"><span>{{ ca.abbrev }}</span></span>
-            {% endfor %}
-            {% for to in timeslot.show.topic.all %}
-                <span title="{{ to.topic }}" class="abbrev to-{{ to.abbrev }}"><span>{{ to.abbrev }}</span></span>
-            {% endfor %}
-            {% for mf in timeslot.show.musicfocus.all %}
-                <span title="{{ mf.focus }}" class="abbrev mf-{{ mf.abbrev }}"><span>{{ mf.abbrev }}</span></span>
-            {% endfor %}
-        </div>
-
-        <p id="type">{{ timeslot.show.type.type }}</p>
-    </div>
-
-    {% if timeslot.note %}
-        <p class="timeslot-note">{{ timeslot.note.content|safe }}</p>
-    {% endif %}
-
-    <div id="short-description" class="documentDescription">{{ timeslot.show.short_description }}</div>
-
-    {% if timeslot.show.description %}
-        <div id="description">{{ timeslot.show.description|safe }}</div>
-    {% endif %}
-
-    <p>
-        {% for host in timeslot.show.hosts.all %}
-            <a href="{% url "host-detail" host.id %}">{{ host }}</a><br/>
-        {% endfor %}
-        {% if timeslot.show.email %}
-            <strong>Email:</strong> <a href="mailto:{{ timeslot.show.email }}">{{ timeslot.show.email }}</a><br/>
-        {% endif %}
-        {% if timeslot.show.website %}
-            <strong>Website:</strong> <a href="{{ timeslot.show.website }}">{{ timeslot.show.website }}</a><br/>
-        {% endif %}
-    </p>
-</div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/program/templates/week_schedule.html b/program/templates/week_schedule.html
deleted file mode 100644
index ad6b012591fecb3336bae7106b918cb331aaf79a..0000000000000000000000000000000000000000
--- a/program/templates/week_schedule.html
+++ /dev/null
@@ -1,127 +0,0 @@
-<html>
-<head>
-    <title>Wochenansicht &mdash; Radio Helsinki - Freies Radio Graz</title>
-</head>
-
-<body>
-
-<div id="content-main" class="week-schedule">
-    <table class="week-navigation">
-        <tr>
-            <td><a href="/program/{{ last_w }}">&lt;--</a></td>
-            <td class="current">{{ cur_w }}</td>
-            <td><a href="/program/{{ next_w1 }}">{{ next_w1 }}</a></td>
-            <td><a href="/program/{{ next_w2 }}">{{ next_w2 }}</a></td>
-            <td><a href="/program/{{ next_w3 }}">{{ next_w3 }}</a></td>
-            <td><a href="/program/{{ next_w4 }}">{{ next_w4 }}</a></td>
-            <td><a href="/program/{{ next_w1 }}">--&gt;</a></td>
-        </tr>
-    </table>
-    <div class="weekday-starts weekday-starts-left">
-        <div style="height: 43px;">&nbsp;</div>
-        <div style="height: 60px;">06:00</div>
-        <div style="height: 60px;">07:00</div>
-        <div style="height: 60px;">08:00</div>
-        <div style="height: 60px;">09:00</div>
-        <div style="height: 60px;">10:00</div>
-        <div style="height: 60px;">11:00</div>
-        <div style="height: 60px;">12:00</div>
-        <div style="height: 60px;">13:00</div>
-        <div style="height: 60px;">14:00</div>
-        <div style="height: 60px;">15:00</div>
-        <div style="height: 60px;">16:00</div>
-        <div style="height: 60px;">17:00</div>
-        <div style="height: 60px;">18:00</div>
-        <div style="height: 60px;">19:00</div>
-        <div style="height: 60px;">20:00</div>
-        <div style="height: 60px;">21:00</div>
-        <div style="height: 60px;">22:00</div>
-        <div style="height: 60px;">23:00</div>
-        <div style="height: 60px;">00:00</div>
-        <div style="height: 60px;">01:00</div>
-        <div style="height: 60px;">02:00</div>
-        <div style="height: 60px;">03:00</div>
-        <div style="height: 60px;">04:00</div>
-        <div style="height: 60px;">05:00</div>
-    </div>
-    <div id="monday" class="weekday weekday-first">
-        <h2>{{ monday|date:"l d.m.Y" }}</h2>
-        {% for timeslot in monday_timeslots %}
-            {% include "week_schedule_timeslot.html" %}
-        {% endfor %}
-    </div>
-
-    <div id="tuesday" class="weekday">
-        <h2>{{ tuesday|date:"l d.m.Y" }}</h2>
-        {% for timeslot in tuesday_timeslots %}
-            {% include "week_schedule_timeslot.html" %}
-        {% endfor %}
-    </div>
-
-    <div id="wednesday" class="weekday">
-        <h2>{{ wednesday|date:"l d.m.Y" }}</h2>
-        {% for timeslot in wednesday_timeslots %}
-            {% include "week_schedule_timeslot.html" %}
-        {% endfor %}
-    </div>
-
-    <div id="thursday" class="weekday">
-        <h2>{{ thursday|date:"l d.m.Y" }}</h2>
-        {% for timeslot in thursday_timeslots %}
-            {% include "week_schedule_timeslot.html" %}
-        {% endfor %}
-    </div>
-
-    <div id="friday" class="weekday">
-        <h2>{{ friday|date:"l d.m.Y" }}</h2>
-        {% for timeslot in friday_timeslots %}
-            {% include "week_schedule_timeslot.html" %}
-        {% endfor %}
-    </div>
-
-    <div id="saturday" class="weekday">
-        <h2>{{ saturday|date:"l d.m.Y" }}</h2>
-        {% for timeslot in saturday_timeslots %}
-            {% include "week_schedule_timeslot.html" %}
-        {% endfor %}
-    </div>
-
-    <div id="sunday" class="weekday weekday-last">
-        <h2>{{ sunday|date:"l d.m.Y" }}</h2>
-        {% for timeslot in sunday_timeslots %}
-            {% include "week_schedule_timeslot.html" %}
-        {% endfor %}
-    </div>
-
-    <div class="weekday-starts weekday-starts-right">
-        <div style="height: 43px;">&nbsp;</div>
-        <div style="height: 60px;">06:00</div>
-        <div style="height: 60px;">07:00</div>
-        <div style="height: 60px;">08:00</div>
-        <div style="height: 60px;">09:00</div>
-        <div style="height: 60px;">10:00</div>
-        <div style="height: 60px;">11:00</div>
-        <div style="height: 60px;">12:00</div>
-        <div style="height: 60px;">13:00</div>
-        <div style="height: 60px;">14:00</div>
-        <div style="height: 60px;">15:00</div>
-        <div style="height: 60px;">16:00</div>
-        <div style="height: 60px;">17:00</div>
-        <div style="height: 60px;">18:00</div>
-        <div style="height: 60px;">19:00</div>
-        <div style="height: 60px;">20:00</div>
-        <div style="height: 60px;">21:00</div>
-        <div style="height: 60px;">22:00</div>
-        <div style="height: 60px;">23:00</div>
-        <div style="height: 60px;">00:00</div>
-        <div style="height: 60px;">01:00</div>
-        <div style="height: 60px;">02:00</div>
-        <div style="height: 60px;">03:00</div>
-        <div style="height: 60px;">04:00</div>
-        <div style="height: 60px;">05:00</div>
-    </div>
-
-</div>
-
-</body>
-</html>
diff --git a/program/templates/week_schedule_timeslot.html b/program/templates/week_schedule_timeslot.html
deleted file mode 100644
index 12abade9c886e2a9a1ec2aef77395e2a4ba60376..0000000000000000000000000000000000000000
--- a/program/templates/week_schedule_timeslot.html
+++ /dev/null
@@ -1,54 +0,0 @@
-{% load timeslots %}
-
-{% if forloop.first and timeslot.start != timeslot.get_previous_by_start.end %}
-    <div class="timeslot ty-{{ default_show.type.slug }}" {% duration_until timeslot.start %}>
-        <div>{{ default_show.name }}</div>
-    </div>
-{% endif %}
-
-{% if forloop.first and timeslot.start == timeslot.get_next_by_start.end and timeslot.start != "06:00" %}
-    <div class="timeslot ty-{{ timeslot.show.type.slug }}" {% duration timeslot.start timeslot.end %}>
-        <div><a href="{% url "timeslot-detail" timeslot.id %}">{{ timeslot.show.name }}</a></div>
-    </div>
-{% endif %}
-
-{% if forloop.first and timeslot.start != "06:00" and timeslot.show == default_show %}
-    <div class="timeslot ty-{{ timeslot.show.type.slug }}" {% duration_until timeslot.end %}>
-        <div><a href="{% url "timeslot-detail" timeslot.id %}">{{ timeslot.show.name }}</a></div>
-    </div>
-{% endif %}
-
-{% if forloop.first and timeslot.start != "06:00" and timeslot.show != default_show %}
-    <div class="timeslot ty-{{ timeslot.show.type.slug }}" {% duration timeslot.start timeslot.end %}>
-        <div><a href="{% url "timeslot-detail" timeslot.id %}">{{ timeslot.show.name }}</a></div>
-    </div>
-{% endif %}
-
-{% if not forloop.first and not forloop.last %}
-    <div class="timeslot ty-{{ timeslot.show.type.slug }}" {% duration timeslot.start timeslot.end %}>
-        <div><a href="{% url "timeslot-detail" timeslot.id %}">{{ timeslot.show.name }}</a></div>
-    </div>
-    {% if timeslot.end != timeslot.get_next_by_start.start %}
-        <div class="timeslot ty-{{ default_show.type.slug }}" {% duration timeslot.end timeslot.get_next_by_start.start %}>
-            <div>{{ default_show.name }}</div>
-        </div>
-    {% endif %}
-{% endif %}
-
-{% if forloop.last and timeslot.end != "06:00" and timeslot.show == default_show %}
-    <div class="timeslot ty-{{ timeslot.show.type.slug }}" {% duration_since timeslot.start %}>
-        <div><a href="{% url "timeslot-detail" timeslot.id %}">{{ timeslot.show.name }}</a></div>
-    </div>
-{% endif %}
-
-{% if forloop.last and timeslot.end != "06:00" and timeslot.show != default_show %}
-    <div class="timeslot ty-{{ timeslot.show.type.slug }}" {% duration timeslot.start timeslot.end %}>
-        <div><a href="{% url "timeslot-detail" timeslot.id %}">{{ timeslot.show.name }}</a></div>
-    </div>
-{% endif %}
-
-{% if forloop.last and timeslot.end != timeslot.get_next_by_start.start %}
-    <div class="timeslot ty-{{ default_show.type.slug }}" {% duration_since timeslot.end %}>
-        <div>{{ default_show.name }}</div>
-    </div>
-{% endif %}
\ No newline at end of file
diff --git a/program/templatetags/__init__.py b/program/templatetags/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/program/templatetags/content_boxes.py b/program/templatetags/content_boxes.py
deleted file mode 100644
index 6f4caa326ab457e6bf5de2c4fb5f3f9dce9d6793..0000000000000000000000000000000000000000
--- a/program/templatetags/content_boxes.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from django import template
-
-from program.models import Type, MusicFocus, Category, Topic
-
-register = template.Library()
-
-
-@register.inclusion_tag('boxes/type.html')
-def type():
-    return {'type_list': Type.objects.filter(is_active=True)}
-
-
-@register.inclusion_tag('boxes/musicfocus.html')
-def musicfocus():
-    return {'musicfocus_list': MusicFocus.objects.filter(is_active=True)}
-
-
-@register.inclusion_tag('boxes/category.html')
-def category():
-    return {'category_list': Category.objects.filter(is_active=True)}
-
-
-@register.inclusion_tag('boxes/topic.html')
-def topic():
-    return {'topic_list': Topic.objects.filter(is_active=True)}
\ No newline at end of file
diff --git a/program/templatetags/timeslots.py b/program/templatetags/timeslots.py
deleted file mode 100644
index efab3ccd8d703df902da56889630e052436f6def..0000000000000000000000000000000000000000
--- a/program/templatetags/timeslots.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from django import template
-
-from datetime import datetime, time, timedelta
-
-register = template.Library()
-
-
-@register.simple_tag
-def duration(start, end):
-    return 'style="height: %dpx"' % ((end-start).seconds/60)
-
-
-@register.simple_tag
-def duration_until(end):
-    start = datetime.combine(end.date(), time(6, 0))
-    return 'style="height: %dpx"' % ((end-start).seconds/60)
-
-
-@register.simple_tag
-def duration_since(start):
-    if start.time() < time(23, 59):
-        end = datetime.combine(start.date()+timedelta(days=1), time(6, 0))
-    else:
-        end = datetime.combine(start.date(), time(6, 0))
-    return 'style="height: %dpx"' % ((end-start).seconds/60)
\ No newline at end of file
diff --git a/program/urls.py b/program/urls.py
index 54c8b31c424091a8e90e6a5891d10e4d9b8638aa..ab21bb1adfc31fc07e830c88f7afea12d0f6216e 100644
--- a/program/urls.py
+++ b/program/urls.py
@@ -1,31 +1,32 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
 
 from django.conf import settings
 from django.conf.urls import url
-from django.views.decorators.cache import cache_page
 from django.views.static import serve
-from .import views
-
-import os
 
 PROGRAM_SITE_MEDIA = os.path.join(os.path.dirname(__file__), '../site_media')
 
-urlpatterns = [
-    url(r'^calendar/?$', views.CalendarView.as_view()),
-    url(r'^today/?$', views.DayScheduleView.as_view()),
-    url(r'^week/?$', views.WeekScheduleView.as_view()),
-    url(r'^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/?$', views.DayScheduleView.as_view()),
-    url(r'^(?P<year>\d{4})/(?P<week>\d{1,2})/?$', views.WeekScheduleView.as_view()),
-    url(r'^current_box/?$', cache_page(60)(views.CurrentShowBoxView.as_view())),
-    url(r'^hosts/?$', views.HostListView.as_view()),
-    url(r'^hosts/(?P<pk>\d+)/?$', views.HostDetailView.as_view(), name='host-detail'),
-    url(r'^tips/?$', views.RecommendationsListView.as_view()),
-    url(r'^tips_box/?$', views.RecommendationsBoxView.as_view()),
-    url(r'^shows/?$', views.ShowListView.as_view()),
-    url(r'^shows/(?P<slug>[\w-]+)/?$', views.ShowDetailView.as_view(), name='show-detail'),
-    url(r'^(?P<pk>\d+)/?$', views.TimeSlotDetailView.as_view(), name='timeslot-detail'),
-    url(r'^styles.css$', views.StylesView.as_view())
-]
-
 if settings.DEBUG:
-    urlpatterns.append(url(r'^static/(?P<path>.*)$', serve, {'document_root': PROGRAM_SITE_MEDIA}))
\ No newline at end of file
+    urlpatterns = [url(r'^static/(?P<path>.*)$', serve, {'document_root': PROGRAM_SITE_MEDIA})]
+else:
+    urlpatterns = []
diff --git a/program/utils.py b/program/utils.py
index e5df6a0a019fd16d8feffae6adc5ee8e55d11d4e..94298e28b787e2ea8f2d3b00881f8cbcf828d077 100644
--- a/program/utils.py
+++ b/program/utils.py
@@ -1,12 +1,30 @@
-# -*- coding: utf-8 -*-
-
-from django.conf import settings
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
+import bisect
 import json
 import urllib
-import bisect
-from os.path import join
 from datetime import datetime, date, timedelta
+from os.path import join
+
+from django.conf import settings
 
 
 def get_automation_id_choices():
@@ -16,7 +34,7 @@ def get_automation_id_choices():
     shows = []
     if base_url:
         try:
-            shows_json = urllib.urlopen(base_url).read()
+            shows_json = urllib.request.urlopen(base_url).read()
             shows_list = json.loads(shows_json)['shows']
             multi_shows_list = json.loads(shows_json)['multi-shows']
         except IOError:
@@ -57,4 +75,4 @@ def tofirstdayinisoweek(year, week):
     ret = datetime.strptime('%04d-%02d-1' % (year, week), '%Y-%W-%w')
     if date(year, 1, 4).isoweekday() > 4:
         ret -= timedelta(days=7)
-    return ret
\ No newline at end of file
+    return ret
diff --git a/program/views.py b/program/views.py
index 48a7c45c132a5f1472ea0db42a22fbc4eb5ba3ab..520e003b921424011f1876654a7eb65be44883d4 100644
--- a/program/views.py
+++ b/program/views.py
@@ -1,222 +1,43 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
 import json
 from datetime import date, datetime, time, timedelta
 
-from django.db.models import Q
-from django.utils.translation import ugettext_lazy as _
-from django.core.exceptions import ObjectDoesNotExist
 from django.contrib.auth.models import User
-from django.http import Http404, HttpResponse, JsonResponse
+from django.db.models import Q
+from django.http import HttpResponse
 from django.shortcuts import get_object_or_404
-from django.views.generic.base import TemplateView
-from django.views.generic.detail import DetailView
-from django.views.generic.list import ListView
-from django.forms.models import model_to_dict
-from rest_framework import permissions, serializers, status, viewsets
-from rest_framework.views import APIView
-from rest_framework.response import Response
+from django.utils import timezone
+from django.utils.translation import ugettext_lazy as _
+from rest_framework import permissions, status, viewsets
 from rest_framework.pagination import LimitOffsetPagination
+from rest_framework.response import Response
 
-from program.models import Type, MusicFocus, Language, Note, Show, Category, FundingCategory, Topic, TimeSlot, Host, Schedule, RRule
-from program.serializers import TypeSerializer, LanguageSerializer, MusicFocusSerializer, NoteSerializer, ShowSerializer, ScheduleSerializer, CategorySerializer, FundingCategorySerializer, TopicSerializer, TimeSlotSerializer, HostSerializer, UserSerializer
-from program.utils import tofirstdayinisoweek, get_cached_shows
-
-# Deprecated
-class CalendarView(TemplateView):
-    template_name = 'calendar.html'
-
-
-# Deprecated
-class HostListView(ListView):
-    context_object_name = 'host_list'
-    queryset = Host.objects.filter(Q(is_active=True) | Q(shows__schedules__until__gt=datetime.now())).distinct()
-    template_name = 'host_list.html'
-
-
-# Deprecated
-class HostDetailView(DetailView):
-    context_object_name = 'host'
-    queryset = Host.objects.all()
-    template_name = 'host_detail.html'
-
-
-# Deprecated
-class ShowListView(ListView):
-    context_object_name = 'show_list'
-    template_name = 'show_list.html'
-
-    def get_queryset(self):
-        queryset = Show.objects.filter(schedules__until__gt=date.today()).exclude(id=1).distinct()
-        if 'type' in self.request.GET:
-            type = get_object_or_404(Type, slug=self.request.GET['type'])
-            queryset = queryset.filter(type=type)
-        elif 'musicfocus' in self.request.GET:
-            musicfocus = get_object_or_404(MusicFocus, slug=self.request.GET['musicfocus'])
-            queryset = queryset.filter(musicfocus=musicfocus)
-        elif 'category' in self.request.GET:
-            category = get_object_or_404(Category, slug=self.request.GET['category'])
-            queryset = queryset.filter(category=category)
-        elif 'topic' in self.request.GET:
-            topic = get_object_or_404(Topic, slug=self.request.GET['topic'])
-            queryset = queryset.filter(topic=topic)
-        elif 'fundingcategory' in self.request.GET:
-            fundingcategory = get_object_or_404(FundingCategory, slug=self.request.GET['fundingcategory'])
-            queryset = queryset.filter(fundingcategory=fundingcategory)
-
-
-        return queryset
-
-
-# Deprecated
-class ShowDetailView(DetailView):
-    queryset = Show.objects.all().exclude(id=1)
-    template_name = 'show_detail.html'
-
-
-# Deprecated
-class TimeSlotDetailView(DetailView):
-    queryset = TimeSlot.objects.all()
-    template_name = 'timeslot_detail.html'
-
-
-# Deprecated
-class RecommendationsListView(ListView):
-    context_object_name = 'recommendation_list'
-    template_name = 'recommendation_list.html'
-
-    now = datetime.now()
-    end = now + timedelta(weeks=1)
-
-    queryset = TimeSlot.objects.filter(Q(note__isnull=False, note__status=1,
-                                         start__range=(now, end)) |
-                                       Q(show__type__slug='sondersendung',
-                                         start__range=(now, end))).order_by('start')[:20]
-
-
-# Deprecated
-class RecommendationsBoxView(RecommendationsListView):
-    template_name = 'boxes/recommendation.html'
-
-
-# Deprecated
-class DayScheduleView(TemplateView):
-    template_name = 'day_schedule.html'
+from program.models import Type, MusicFocus, Language, Note, Show, Category, FundingCategory, Topic, TimeSlot, Host, Schedule
+from program.serializers import TypeSerializer, LanguageSerializer, MusicFocusSerializer, NoteSerializer, ShowSerializer, \
+    ScheduleSerializer, CategorySerializer, FundingCategorySerializer, TopicSerializer, TimeSlotSerializer, HostSerializer, \
+    UserSerializer
+from program.utils import get_cached_shows
 
-    def get_context_data(self, **kwargs):
-        year = self.kwargs.get('year', None)
-        month = self.kwargs.get('month', None)
-        day = self.kwargs.get('day', None)
 
-        if year is None and month is None and day is None:
-            today = datetime.combine(date.today(), time(6, 0))
-        else:
-            today = datetime.strptime('%s__%s__%s__06__00' % (year, month, day), '%Y__%m__%d__%H__%M')
-
-        tomorrow = today + timedelta(days=1)
-
-        context = super(DayScheduleView, self).get_context_data(**kwargs)
-        context['day'] = today
-        context['recommendations'] = Note.objects.filter(status=1, timeslot__start__range=(today, tomorrow))
-        context['default_show'] = Show.objects.get(pk=1)
-
-        timeslots = TimeSlot.objects.get_day_timeslots(today)
-
-        if 'type' in self.request.GET:
-            type = get_object_or_404(Type, slug=self.request.GET['type'])
-            context['timeslots'] = timeslots.filter(show__type=type)
-        elif 'musicfocus' in self.request.GET:
-            musicfocus = get_object_or_404(MusicFocus, slug=self.request.GET['musicfocus'])
-            context['timeslots'] = timeslots.filter(show__musicfocus=musicfocus)
-        elif 'category' in self.request.GET:
-            category = get_object_or_404(Category, slug=self.request.GET['category'])
-            context['timeslots'] = timeslots.filter(show__category=category)
-        elif 'topic' in self.request.GET:
-            topic = get_object_or_404(Topic, slug=self.request.GET['topic'])
-            context['topic'] = timeslots.filter(show__topic=topic)
-        else:
-            context['timeslots'] = timeslots
-        return context
-
-
-# Deprecated
-class CurrentShowBoxView(TemplateView):
-    context_object_name = 'recommendation_list'
-    template_name = 'boxes/current.html'
-
-    def get_context_data(self, **kwargs):
-        current_timeslot = TimeSlot.objects.get_or_create_current()
-        previous_timeslot = current_timeslot.get_previous_by_start()
-        next_timeslot = current_timeslot.get_next_by_start()
-        after_next_timeslot = next_timeslot.get_next_by_start()
-
-        context = super(CurrentShowBoxView, self).get_context_data(**kwargs)
-        context['current_timeslot'] = current_timeslot
-        context['previous_timeslot'] = previous_timeslot
-        context['next_timeslot'] = next_timeslot
-        context['after_next_timeslot'] = after_next_timeslot
-        return context
-
-
-# Deprecated
-class WeekScheduleView(TemplateView):
-    template_name = 'week_schedule.html'
-
-    def get_context_data(self, **kwargs):
-        year = self.kwargs.get('year', None)
-        week = self.kwargs.get('week', None)
-
-        if year is None and week is None:
-            year, week = datetime.now().strftime('%G__%V').split('__')
-
-        monday = tofirstdayinisoweek(int(year), int(week))
-        tuesday = monday + timedelta(days=1)
-        wednesday = monday + timedelta(days=2)
-        thursday = monday + timedelta(days=3)
-        friday = monday + timedelta(days=4)
-        saturday = monday + timedelta(days=5)
-        sunday = monday + timedelta(days=6)
-
-        context = super(WeekScheduleView, self).get_context_data()
-        context['monday'] = monday
-        context['tuesday'] = tuesday
-        context['wednesday'] = wednesday
-        context['thursday'] = thursday
-        context['friday'] = friday
-        context['saturday'] = saturday
-        context['sunday'] = sunday
-        context['default_show'] = Show.objects.get(pk=1)
-        context['monday_timeslots'] = TimeSlot.objects.get_day_timeslots(monday)
-        context['tuesday_timeslots'] = TimeSlot.objects.get_day_timeslots(tuesday)
-        context['wednesday_timeslots'] = TimeSlot.objects.get_day_timeslots(wednesday)
-        context['thursday_timeslots'] = TimeSlot.objects.get_day_timeslots(thursday)
-        context['friday_timeslots'] = TimeSlot.objects.get_day_timeslots(friday)
-        context['saturday_timeslots'] = TimeSlot.objects.get_day_timeslots(saturday)
-        context['sunday_timeslots'] = TimeSlot.objects.get_day_timeslots(sunday)
-        context['last_w'] = datetime.strftime(monday - timedelta(days=7), '%G/%V')
-        context['cur_w'] = datetime.strftime(monday, '%G/%V')
-        context['next_w1'] = datetime.strftime(monday + timedelta(days=7), '%G/%V')
-        context['next_w2'] = datetime.strftime(monday + timedelta(days=14), '%G/%V')
-        context['next_w3'] = datetime.strftime(monday + timedelta(days=21), '%G/%V')
-        context['next_w4'] = datetime.strftime(monday + timedelta(days=28), '%G/%V')
-        return context
-
-
-# Deprecated
-class StylesView(TemplateView):
-    template_name = 'styles.css'
-    content_type = 'text/css'
-
-    def get_context_data(self, **kwargs):
-        context = super(StylesView, self).get_context_data(**kwargs)
-        context['types'] = Type.objects.filter(is_active=True)
-        context['musicfocus'] = MusicFocus.objects.all()
-        context['category'] = Category.objects.all()
-        context['topic'] = Topic.objects.all()
-        return context
-
-
-# Deprecated
 def json_day_schedule(request, year=None, month=None, day=None):
     if year is None and month is None and day is None:
         today = datetime.combine(date.today(), time(0, 0))
@@ -255,25 +76,23 @@ def json_playout(request):
          If end not given, it returns all timeslots of the next 7 days
     """
 
-    from pv.settings import STATION_FALLBACK_ID
-
-    if request.GET.get('start') == None:
+    if request.GET.get('start') is None:
         start = datetime.combine(date.today(), time(0, 0))
     else:
-        start = datetime.combine( datetime.strptime(request.GET.get('start'), '%Y-%m-%d').date(), time(0, 0))
+        start = datetime.combine(datetime.strptime(request.GET.get('start'), '%Y-%m-%d').date(), time(0, 0))
 
-    if request.GET.get('end') == None:
+    if request.GET.get('end') is None:
         # If no end was given, return the next week
         timeslots = TimeSlot.objects.get_7d_timeslots(start).select_related('schedule').select_related('show')
     else:
         # Otherwise return the given timerange
-        end = datetime.combine( datetime.strptime(request.GET.get('end'), '%Y-%m-%d').date(), time(23, 59))
+        end = datetime.combine(datetime.strptime(request.GET.get('end'), '%Y-%m-%d').date(), time(23, 59))
         timeslots = TimeSlot.objects.get_timerange_timeslots(start, end).select_related('schedule').select_related('show')
 
     schedule = []
     for ts in timeslots:
 
-        is_repetition = ' ' + _('REP') if ts.schedule.is_repetition is 1 else ''
+        is_repetition = ' ' + _('REP') if ts.schedule.is_repetition is True else ''
 
         hosts = ', '.join(ts.show.hosts.values_list('name', flat=True))
         categories = ', '.join(ts.show.category.values_list('category', flat=True))
@@ -281,11 +100,11 @@ def json_playout(request):
         musicfocus = ', '.join(ts.show.musicfocus.values_list('focus', flat=True))
         languages = ', '.join(ts.show.language.values_list('name', flat=True))
         fdcategory = None
-        if ts.show.fundingcategory_id is not None:
+        if ts.show.fundingcategory_id:
             fundingcategory = FundingCategory.objects.get(pk=ts.show.fundingcategory_id)
             fdcategory = fundingcategory.fundingcategory
 
-        type = Type.objects.get(pk=ts.show.type_id)
+        type_ = Type.objects.get(pk=ts.show.type_id)
 
         classname = 'default'
 
@@ -296,23 +115,22 @@ def json_playout(request):
             'id': ts.id,
             'start': ts.start.strftime('%Y-%m-%dT%H:%M:%S'),
             'end': ts.end.strftime('%Y-%m-%dT%H:%M:%S'),
-            'title': ts.show.name + is_repetition, # For JS Calendar
+            'title': ts.show.name + is_repetition,  # For JS Calendar
             'automation-id': -1,
             'schedule_id': ts.schedule.id,
             'is_repetition': ts.is_repetition,
             'playlist_id': ts.playlist_id,
-            'schedule_fallback_id': ts.schedule.fallback_id,
-            'show_fallback_id': ts.show.fallback_id,
+            'schedule_default_playlist_id': ts.schedule.default_playlist_id,
+            'show_default_playlist_id': ts.show.default_playlist_id,
             'show_id': ts.show.id,
             'show_name': ts.show.name + is_repetition,
             'show_hosts': hosts,
-            'show_type': type.type,
+            'show_type': type_.type,
             'show_categories': categories,
             'show_topics': topics,
             'show_musicfocus': musicfocus,
             'show_languages': languages,
             'show_fundingcategory': fdcategory,
-            'station_fallback_id': STATION_FALLBACK_ID, # TODO: Find a better way than getting it from the settings
             'memo': ts.memo,
             'className': classname,
         }
@@ -326,7 +144,6 @@ def json_playout(request):
                         content_type="application/json; charset=utf-8")
 
 
-# Deprecated
 def json_timeslots_specials(request):
     specials = {}
     shows = get_cached_shows()['shows']
@@ -335,8 +152,8 @@ def json_timeslots_specials(request):
         if show['type'] == 's':
             specials[show['id']] = show
 
-    for ts in TimeSlot.objects.filter(end__gt=datetime.now(),
-                                      schedule__automation_id__in=specials.iterkeys()).select_related('show'):
+    for ts in TimeSlot.objects.filter(end__gt=timezone.now(),
+                                      schedule__automation_id__in=specials.keys()).select_related('show'):
         automation_id = ts.schedule.automation_id
         start = ts.start.strftime('%Y-%m-%d_%H:%M:%S')
         end = ts.end.strftime('%Y-%m-%d_%H:%M:%S')
@@ -344,7 +161,7 @@ def json_timeslots_specials(request):
             if specials[automation_id]['pv_start'] < start:
                 continue
 
-        specials[automation_id]['pv_id'] = int(ts.show.id)
+        specials[automation_id]['pv_id'] = ts.show.id
         specials[automation_id]['pv_name'] = ts.show.name
         specials[automation_id]['pv_start'] = start
         specials[automation_id]['pv_end'] = end
@@ -353,19 +170,16 @@ def json_timeslots_specials(request):
                         content_type="application/json; charset=utf-8")
 
 
-
-
-####################################################################
-# REST API View Sets
-####################################################################
+def int_or_none(key, kwargs):
+    return int(kwargs[key]) if key in kwargs else None
 
 
 class APIUserViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/users   Returns oneself - Superusers see all users. Only superusers may create a user (GET, POST)
-    /api/v1/users/1 Used for retrieving or updating a single user. Non-superusers may only update certain fields. (GET, PUT) - DELETE is prohibited for everyone
+    /users returns oneself. Superusers see all users. Only superusers may create a user (GET, POST)
+    /users/{pk} retrieves or updates a single user. Non-superusers may only update certain fields (GET, PUT)
 
-    Superusers may access and update all users
+    Superusers may access and update all users.
     """
 
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
@@ -379,26 +193,24 @@ class APIUserViewSet(viewsets.ModelViewSet):
 
         return User.objects.filter(pk=self.request.user.id)
 
-
-    def list(self, request):
+    def list(self, request, *args, **kwargs):
         users = self.get_queryset()
         serializer = UserSerializer(users, many=True)
         return Response(serializer.data)
 
-
-    def retrieve(self, request, pk=None):
+    def retrieve(self, request, *args, **kwargs):
         """Returns a single user"""
+        pk = int_or_none('pk', self.kwargs)
 
         # Common users only see themselves
-        if not request.user.is_superuser and int(pk) != request.user.id:
+        if not request.user.is_superuser and pk != request.user.id:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
         user = get_object_or_404(User, pk=pk)
         serializer = UserSerializer(user)
         return Response(serializer.data)
 
-
-    def create(self, request, pk=None):
+    def create(self, request, *args, **kwargs):
         """
         Create a User
         Only superusers may create a user
@@ -415,48 +227,38 @@ class APIUserViewSet(viewsets.ModelViewSet):
 
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
 
+    def update(self, request, *args, **kwargs):
+        pk = int_or_none('pk', self.kwargs)
 
-    def update(self, request, pk=None):
-
+        serializer = UserSerializer(data=request.data)
         # Common users may only edit themselves
-        if not request.user.is_superuser and int(pk) != request.user.id:
+        if not request.user.is_superuser and pk != request.user.id:
             return Response(serializer.initial_data, status=status.HTTP_401_UNAUTHORIZED)
 
         user = get_object_or_404(User, pk=pk)
-        serializer = UserSerializer(user, data=request.data, context={ 'user': request.user })
+        serializer = UserSerializer(user, data=request.data, context={'user': request.user})
 
         if serializer.is_valid():
-            serializer.save();
+            serializer.save()
             return Response(serializer.data)
 
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
 
-
-    def destroy(self, request, pk=None):
+    def destroy(self, request, *args, **kwargs):
         """Deleting users is prohibited: Set 'is_active' to False instead"""
         return Response(status=status.HTTP_401_UNAUTHORIZED)
 
 
-
 class APIShowViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/shows/                                             Returns all shows (GET, POST)
-    /api/v1/shows/?active=true                                 Returns all active shows (= currently running) (GET)
-    /api/v1/shows/?active=false                                Returns all inactive shows (= past or upcoming) (GET)
-    /api/v1/shows/?public=true                                 Returns all public shows (GET)
-    /api/v1/shows/?public=false                                Returns all non-public shows (GET)
-    /api/v1/shows/?host=1                                      Returns shows assigned to a given host (GET)
-    /api/v1/shows/?owner=1                                     Returns shows of a given owner (GET)
-    /api/v1/shows/1                                            Used for retrieving a single show or update (if owned) (GET, PUT) - DELETE is not allowed via API. Set is_active to False instead.
-    /api/v1/shows/1/notes                                      Returns all notes to the show (GET) - POST not allowed at this level, use /shows/1/schedules/1/timeslots/1/note instead
-    /api/v1/shows/1/notes/1                                    Returns the note of the show by its ID (GET) - PUT/DELETE not allowed at this level, use /shows/1/schedules/1/timeslots/1/note/1/ instead
-    /api/v1/shows/1/schedules                                  Returns all schedules of the show (GET, POST)
-    /api/v1/shows/1/schedules/1                                Returns the schedule of the show by its ID (GET) - POST not allowed at this level, use /shows/1/schedules/ instead
-    /api/v1/shows/1/timeslots                                  Returns all timeslots of the show (GET) - Timeslots may only be added by creating/updating a schedule
-    /api/v1/shows/1/timeslots/1                                Returns the timeslot of the show (GET) - Timeslots may only be added by creating/updating a schedule
-    /api/v1/shows/1/timeslots?start=2017-01-01&end=2017-12-31  Returns all timeslots of the show within the given timerange (GET)
-    /api/v1/shows/1/timeslots/1/note                           Returns a note to the timeslot (one at max) (GET) - POST not allowed at this level, use /shows/1/schedules/1/timelots/1/note/ instead
-    /api/v1/shows/1/timeslots/1/note/1                         Returns the note of the show's timeslot by its ID (GET) - PUT/DELETE not allowed at this level, use /shows/1/schedules/1/timeslots/1/note/1/ instead
+    /shows/ returns all shows (GET, POST)
+    /shows/?active=true returns all active shows (= currently running) (GET)
+    /shows/?active=false returns all inactive shows (= past or upcoming) (GET)
+    /shows/?public=true returns all public shows (GET)
+    /shows/?public=false returns all non-public shows (GET)
+    /shows/?host={host} returns shows assigned to a given host (GET)
+    /shows/?owner={owner} returns shows of a given owner (GET)
+    /shows/{pk} retrieves or updates (if owned) a single show (GET, PUT).
 
     Only superusers may add and delete shows
     """
@@ -467,50 +269,49 @@ class APIShowViewSet(viewsets.ModelViewSet):
     pagination_class = LimitOffsetPagination
 
     def get_queryset(self):
-
         shows = Show.objects.all()
 
-        '''Filters'''
-
-        if self.request.GET.get('active') == 'true' or self.request.GET.get('active') == 'false':
-            '''Filter currently running shows'''
-
+        # Filters
+        if self.request.query_params.get('active') == 'true' or self.request.query_params.get('active') == 'false':
+            # Filter currently running shows
             # Get currently running schedules to filter by first
             # For single dates we test if there'll be one in the future (and ignore the until date)
             # TODO: Really consider dstart? (=currently active, not just upcoming ones)
             # Add limit for future?
-            show_ids = Schedule.objects.filter( Q(rrule_id__gt=1,dstart__lte=date.today(),until__gte=date.today()) |
-                                                 Q(rrule_id=1,dstart__gte=date.today())
+            show_ids = Schedule.objects.filter(Q(rrule_id__gt=1,
+                                                 dstart__lte=date.today(),
+                                                 until__gte=date.today()) |
+                                               Q(rrule_id=1,
+                                                 dstart__gte=date.today())
                                                ).distinct().values_list('show_id', flat=True)
 
             # Filter active shows based on timeslots as well as on the is_active flag
             # Even if there are future timeslots but is_active=True the show will be considered as inactive
-            shows = Show.objects.filter(id__in=show_ids,is_active=True)
+            shows = Show.objects.filter(id__in=show_ids, is_active=True)
 
-        if self.request.GET.get('active') == 'false':
-            '''Return all shows except those which are running'''
-            shows = Show.objects.exclude(id__in=show_ids,is_active=True)
+        if self.request.query_params.get('active') == 'false':
+            # Return all shows except those which are running
+            shows = Show.objects.exclude(id__in=show_ids, is_active=True)
 
-        if self.request.GET.get('public') == 'true':
-            '''Return all public shows'''
+        if self.request.query_params.get('public') == 'true':
+            # Return all public shows
             shows = shows.filter(is_public=True)
 
-        if self.request.GET.get('public') == 'false':
-            '''Return all public shows'''
+        if self.request.query_params.get('public') == 'false':
+            # Return all public shows
             shows = shows.filter(is_public=False)
 
-        if self.request.GET.get('owner') != None:
-            '''Filter shows by owner'''
-            shows = shows.filter(owners__in=[int(self.request.GET.get('owner'))])
+        if owner := self.request.query_params.get('owner'):
+            # Filter shows by owner
+            shows = shows.filter(owners__in=[int(owner)])
 
-        if self.request.GET.get('host') != None:
-            '''Filter shows by host'''
-            shows = shows.filter(hosts__in=[int(self.request.GET.get('host'))])
+        if host := self.request.query_params.get('host'):
+            # Filter shows by host
+            shows = shows.filter(hosts__in=[int(host)])
 
         return shows
 
-
-    def create(self, request, pk=None):
+    def create(self, request, *args, **kwargs):
         """
         Create a show
         Only superusers may create a show
@@ -527,62 +328,63 @@ class APIShowViewSet(viewsets.ModelViewSet):
 
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
 
-
-    def retrieve(self, request, pk=None):
+    def retrieve(self, request, *args, **kwargs):
         """Returns a single show"""
+
+        pk = int_or_none('pk', self.kwargs)
+
         show = get_object_or_404(Show, pk=pk)
         serializer = ShowSerializer(show)
 
         return Response(serializer.data)
 
-
-    def update(self, request, pk=None):
+    def update(self, request, *args, **kwargs):
         """
         Update a show
         Common users may only update shows they own
         """
 
+        pk = int_or_none('pk', self.kwargs)
+
         if not Show.is_editable(self, pk):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
         show = get_object_or_404(Show, pk=pk)
-        serializer = ShowSerializer(show, data=request.data, context={ 'user': request.user })
+        serializer = ShowSerializer(show, data=request.data, context={'user': request.user})
 
         if serializer.is_valid():
             # Common users mustn't edit the show's name
             if not request.user.is_superuser:
                 serializer.validated_data['name'] = show.name
-            serializer.save();
+            serializer.save()
             return Response(serializer.data)
 
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
 
-
-    def destroy(self, request, pk=None):
+    def destroy(self, request, *args, **kwargs):
         """
         Delete a show
         Only superusers may delete shows
         """
 
-        """
-        if not request.user.is_superuser:
-            return Response(status=status.HTTP_401_UNAUTHORIZED)
-
-        show = get_object_or_404(Show, pk=pk)
-        Show.objects.get(pk=pk).delete()
-
-        return Response(status=status.HTTP_204_NO_CONTENT)
-        """
+        # if not request.user.is_superuser:
+        #     return Response(status=status.HTTP_401_UNAUTHORIZED)
+        #
+        # show = get_object_or_404(Show, pk=pk)
+        # Show.objects.get(pk=pk).delete()
+        #
+        # return Response(status=status.HTTP_204_NO_CONTENT)
+        #
 
         return Response(status=status.HTTP_401_UNAUTHORIZED)
 
 
 class APIScheduleViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/schedules/          Returns schedules (GET) - POST not allowed at this level
-    /api/v1/schedules/1         Returns the given schedule (GET) - POST not allowed at this level
-    /api/v1/shows/1/schedules   Returns schedules of the show (GET, POST)
-    /api/v1/shows/1/schedules/1 Returns schedules by its ID (GET, PUT, DELETE)
+    /schedules/ returns all schedules (GET)
+    /schedules/{pk} returns the given schedule (GET)
+    /shows/{show_pk}/schedules returns schedules of the show (GET, POST)
+    /shows/{show_pk}/schedules/{pk} returns schedules by its ID (GET, PUT, DELETE)
 
     Only superusers may create and update schedules
     """
@@ -592,24 +394,25 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
 
     def get_queryset(self):
-        show_pk = self.kwargs['show_pk'] if 'show_pk' in self.kwargs else None
+        show_pk = int_or_none('show_pk', self.kwargs)
 
-        if show_pk != None:
+        if show_pk:
             return Schedule.objects.filter(show=show_pk)
 
         return Schedule.objects.all()
 
-
-    def list(self, request, show_pk=None, pk=None):
+    def list(self, request, *args, **kwargs):
         """List Schedules of a show"""
+
         schedules = self.get_queryset()
         serializer = ScheduleSerializer(schedules, many=True)
         return Response(serializer.data)
 
+    def retrieve(self, request, *args, **kwargs):
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
 
-    def retrieve(self, request, pk=None, show_pk=None):
-
-        if show_pk != None:
+        if show_pk:
             schedule = get_object_or_404(Schedule, pk=pk, show=show_pk)
         else:
             schedule = get_object_or_404(Schedule, pk=pk)
@@ -617,100 +420,98 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
         serializer = ScheduleSerializer(schedule)
         return Response(serializer.data)
 
-
-    def create(self, request, pk=None, show_pk=None):
+    def create(self, request, *args, **kwargs):
         """
         Create a schedule, generate timeslots, test for collisions and resolve them including notes
 
         Only superusers may add schedules
         TODO: Perhaps directly insert into database if no conflicts found
         """
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
 
         # Only allow creating when calling /shows/1/schedules/
-        if show_pk == None or not request.user.is_superuser:
+        if show_pk is None or not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
         # The schedule dict is mandatory
-        if not 'schedule' in request.data:
+        if 'schedule' not in request.data:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
         # First create submit -> return projected timeslots and collisions
-        if not 'solutions' in request.data:
+        if 'solutions' not in request.data:
             return Response(Schedule.make_conflicts(request.data['schedule'], pk, show_pk))
 
         # Otherwise try to resolve
         resolution = Schedule.resolve_conflicts(request.data, pk, show_pk)
 
         # If resolution went well
-        if not 'projected' in resolution:
+        if 'projected' not in resolution:
             return Response(resolution, status=status.HTTP_201_CREATED)
 
         # Otherwise return conflicts
         return Response(resolution)
 
-
-    def update(self, request, pk=None, show_pk=None):
+    def update(self, request, *args, **kwargs):
         """
         Update a schedule, generate timeslots, test for collisions and resolve them including notes
 
         Only superusers may update schedules
         """
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
 
         # Only allow updating when calling /shows/1/schedules/1
-        if show_pk == None or not request.user.is_superuser:
+        if show_pk is None or not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        schedule = get_object_or_404(Schedule, pk=pk, show=show_pk)
-
         # The schedule dict is mandatory
-        if not 'schedule' in request.data:
+        if 'schedule' not in request.data:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
         # First update submit -> return projected timeslots and collisions
-        if not 'solutions' in request.data:
-            # TODO: If nothing else than fallback_id, automation_id or is_repetition changed -> just save and don't do anything
+        if 'solutions' not in request.data:
+            # TODO: If nothing else than default_playlist_id, automation_id or is_repetition changed -> just save and don't do anything
             return Response(Schedule.make_conflicts(request.data['schedule'], pk, show_pk))
 
         # Otherwise try to resolve
         resolution = Schedule.resolve_conflicts(request.data, pk, show_pk)
 
         # If resolution went well
-        if not 'projected' in resolution:
+        if 'projected' not in resolution:
             return Response(resolution, status=status.HTTP_200_OK)
 
         # Otherwise return conflicts
         return Response(resolution)
 
-
-    def destroy(self, request, pk=None, show_pk=None):
+    def destroy(self, request, *args, **kwargs):
         """
         Delete a schedule
         Only superusers may delete schedules
         """
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = self.kwargs.get('show_pk')
 
         # Only allow deleting when calling /shows/1/schedules/1
-        if show_pk == None or not request.user.is_superuser:
+        if show_pk is None or not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        schedule = get_object_or_404(Schedule, pk=pk)
         Schedule.objects.get(pk=pk).delete()
 
         return Response(status=status.HTTP_204_NO_CONTENT)
 
 
-
-
 class APITimeSlotViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/timeslots                                                     Returns timeslots of the next 60 days (GET) - Timeslots may only be added by creating/updating a schedule
-    /api/v1/timeslots/1                                                   Returns the given timeslot (GET) - PUT/DELETE not allowed at this level
-    /api/v1/timeslots/?start=2017-01-01&end=2017-02-01                    Returns timeslots within the given timerange (GET)
-    /api/v1/shows/1/timeslots                                             Returns timeslots of the show (GET, POST)
-    /api/v1/shows/1/timeslots/1                                           Returns a timeslots by its ID (GET, PUT, DELETE)
-    /api/v1/shows/1/timeslots?start=2017-01-01&end=2017-02-01             Returns timeslots of the show within the given timerange
-    /api/v1/shows/1/schedules/1/timeslots                                 Returns all timeslots of the schedule (GET, POST)
-    /api/v1/shows/1/schedules/1/timeslots/1                               Returns a timeslot by its ID (GET, DELETE). If PUT, the next repetition is returned or nothing if the next timeslot isn't one
-    /api/v1/shows/1/schedules/1/timeslots?start=2017-01-01&end=2017-02-01 Returns all timeslots of the schedule within the given timerange
+    /timeslots returns timeslots of the next 60 days (GET). Timeslots may only be added by creating/updating a schedule
+    /timeslots/{pk} eturns the given timeslot (GET)
+    /timeslots/?start={start_date}&end={end_date} returns timeslots within the time range (GET)
+    /shows/{show_pk}/timeslots returns timeslots of the show (GET, POST)
+    /shows/{show_pk}/timeslots/{pk} returns a timeslots by its ID (GET, PUT, DELETE)
+    /shows/{show_pk}/timeslots/?start={start_date}&end={end_date} returns timeslots of the show within the time range
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots returns all timeslots of the schedule (GET, POST)
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{pk} returns a timeslot by its ID (GET, DELETE). If PUT, the next repetition is returned or nothing if the next timeslot isn't one
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots?start={start_date}&end={end_date} returns all timeslots of the schedule within the time range
     """
 
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
@@ -719,28 +520,27 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
     queryset = TimeSlot.objects.none()
 
     def get_queryset(self):
+        show_pk = int_or_none('show_pk', self.kwargs)
+        schedule_pk = int_or_none('schedule_pk', self.kwargs)
 
-        show_pk = self.kwargs['show_pk'] if 'show_pk' in self.kwargs else None
-        schedule_pk = self.kwargs['schedule_pk'] if 'schedule_pk' in self.kwargs else None
-
-        '''Filters'''
+        # Filters
 
         # Return next 60 days by default
         start = datetime.combine(date.today(), time(0, 0))
         end = start + timedelta(days=60)
 
-        if self.request.GET.get('start') and self.request.GET.get('end'):
-            start = datetime.combine( datetime.strptime(self.request.GET.get('start'), '%Y-%m-%d').date(), time(0, 0))
-            end = datetime.combine( datetime.strptime(self.request.GET.get('end'), '%Y-%m-%d').date(), time(23, 59))
+        if ('start' in self.request.query_params) and ('end' in self.request.query_params):
+            start = datetime.combine(datetime.strptime(self.request.query_params.get('start'), '%Y-%m-%d').date(), time(0, 0))
+            end = datetime.combine(datetime.strptime(self.request.query_params.get('end'), '%Y-%m-%d').date(), time(23, 59))
 
-        '''Endpoints'''
+        # Endpoints
 
         #
         #     /shows/1/schedules/1/timeslots/
         #
         #     Returns timeslots of the given show and schedule
         #
-        if show_pk != None and schedule_pk != None:
+        if show_pk and schedule_pk:
             return TimeSlot.objects.filter(show=show_pk, schedule=schedule_pk, start__gte=start, end__lte=end).order_by('start')
 
         #
@@ -748,7 +548,7 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
         #
         #     Returns timeslots of the show
         #
-        elif show_pk != None and schedule_pk == None:
+        elif show_pk and schedule_pk is None:
             return TimeSlot.objects.filter(show=show_pk, start__gte=start, end__lte=end).order_by('start')
 
         #
@@ -759,10 +559,11 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
         else:
             return TimeSlot.objects.filter(start__gte=start, end__lte=end).order_by('start')
 
+    def retrieve(self, request, *args, **kwargs):
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
 
-    def retrieve(self, request, pk=None, schedule_pk=None, show_pk=None):
-
-        if show_pk != None:
+        if show_pk:
             timeslot = get_object_or_404(TimeSlot, pk=pk, show=show_pk)
         else:
             timeslot = get_object_or_404(TimeSlot, pk=pk)
@@ -770,20 +571,21 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
         serializer = TimeSlotSerializer(timeslot)
         return Response(serializer.data)
 
-
-    def create(self, request):
+    def create(self, request, *args, **kwargs):
         """
         Timeslots may only be created by adding/updating schedules
         TODO: Adding single timeslot which fits to schedule?
         """
-        return Response(status=HTTP_401_UNAUTHORIZED)
-
+        return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-    def update(self, request, pk=None, schedule_pk=None, show_pk=None):
+    def update(self, request, *args, **kwargs):
         """Link a playlist_id to a timeslot"""
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
+        schedule_pk = int_or_none('schedule_pk', self.kwargs)
 
         # Update is only allowed when calling /shows/1/schedules/1/timeslots/1 and if user owns the show
-        if schedule_pk == None or show_pk == None or not Show.is_editable(self, show_pk):
+        if schedule_pk is None or show_pk is None or not Show.is_editable(self, show_pk):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
         timeslot = get_object_or_404(TimeSlot, pk=pk, schedule=schedule_pk, show=show_pk)
@@ -805,41 +607,40 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
 
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
 
-
-    def destroy(self, request, pk=None, schedule_pk=None, show_pk=None):
+    def destroy(self, request, *args, **kwargs):
         """
         Delete a timeslot
         Only superusers may delete timeslots
         """
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
 
         # Only allow when calling endpoint starting with /shows/1/...
-        if show_pk == None:
+        if show_pk is None:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
         if not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        timeslot = get_object_or_404(TimeSlot, pk=pk)
         TimeSlot.objects.get(pk=pk).delete()
 
         return Response(status=status.HTTP_204_NO_CONTENT)
 
 
-
 class APINoteViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/notes/                                  Returns all notes (GET) - POST not allowed at this level
-    /ap1/v1/notes/1                                 Returns a single note (if owned) (GET) - PUT/DELETE not allowed at this level
-    /api/v1/notes/?ids=1,2,3,4,5                    Returns given notes (if owned) (GET)
-    /api/v1/notes/?host=1                           Returns notes assigned to a given host (GET)
-    /api/v1/notes/?owner=1                          Returns notes editable by a given user (GET)
-    /api/v1/notes/?user=1                           Returns notes created by a given user (GET)
-    /api/v1/shows/1/notes                           Returns all notes of a show (GET) - POST not allowed at this level
-    /api/v1/shows/1/notes/1                         Returns a note by its ID (GET) - PUT/DELETE not allowed at this level
-    /api/v1/shows/1/timeslots/1/note/               Returns a note of the timeslot (GET) - POST not allowed at this level
-    /api/v1/shows/1/timeslots/1/note/1              Returns a note by its ID (GET) - PUT/DELETE not allowed at this level
-    /api/v1/shows/1/schedules/1/timeslots/1/note    Returns a note to the timeslot (GET, POST) - Only one note allowed per timeslot
-    /api/v1/shows/1/schedules/1/timeslots/1/note/1  Returns a note by its ID (GET, PUT, DELETE)
+    /notes/ returns all notes (GET)
+    /notes/{pk} returns a single note (if owned) (GET)
+    /notes/?ids={...} returns given notes (if owned) (GET)
+    /notes/?host={host} returns notes assigned to a given host (GET)
+    /notes/?owner={owner} returns notes editable by a given user (GET)
+    /notes/?user={user} returns notes created by a given user (GET)
+    /shows/{show_pk}/notes returns all notes of a show (GET)
+    /shows/{show_pk}/notes/{pk} returns a note by its ID (GET)
+    /shows/{show_pk}/timeslots/{timeslot_pk}/note/ returns a note of the timeslot (GET)
+    /shows/{show_pk}/timeslots/{timeslot_pk}/note/{pk} returns a note by its ID (GET)
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{timeslot_pk}/note returns a note to the timeslot (GET, POST).
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{timeslot_pk}/note/{pk} returns a note by its ID (GET, PUT, DELETE)
 
     Superusers may access and update all notes
     """
@@ -850,12 +651,10 @@ class APINoteViewSet(viewsets.ModelViewSet):
     pagination_class = LimitOffsetPagination
 
     def get_queryset(self):
+        timeslot_pk = int_or_none('timeslot_pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
 
-        pk = self.kwargs['pk'] if 'pk' in self.kwargs else None
-        timeslot_pk = self.kwargs['timeslot_pk'] if 'timeslot_pk' in self.kwargs else None
-        show_pk = self.kwargs['show_pk'] if 'show_pk' in self.kwargs else None
-
-        '''Endpoints'''
+        # Endpoints
 
         #
         #     /shows/1/schedules/1/timeslots/1/note
@@ -863,7 +662,7 @@ class APINoteViewSet(viewsets.ModelViewSet):
         #
         #     Return a note to the timeslot
         #
-        if show_pk != None and timeslot_pk != None:
+        if show_pk and timeslot_pk:
             notes = Note.objects.filter(show=show_pk, timeslot=timeslot_pk)
 
         #
@@ -871,7 +670,7 @@ class APINoteViewSet(viewsets.ModelViewSet):
         #
         #     Returns notes to the show
         #
-        elif show_pk != None and timeslot_pk == None:
+        elif show_pk and timeslot_pk is None:
             notes = Note.objects.filter(show=show_pk)
 
         #
@@ -882,45 +681,47 @@ class APINoteViewSet(viewsets.ModelViewSet):
         else:
             notes = Note.objects.all()
 
-        '''Filters'''
+        # Filters
 
-        if self.request.GET.get('ids') != None:
-            '''Filter notes by their IDs'''
-            note_ids = self.request.GET.get('ids').split(',')
+        if ids := self.request.query_params.get('ids'):
+            # Filter notes by their IDs
+            note_ids = list(map(int, ids.split(',')))
             notes = notes.filter(id__in=note_ids)
 
-        if self.request.GET.get('host') != None:
-            '''Filter notes by host'''
-            notes = notes.filter(host=int(self.request.GET.get('host')))
+        if host := self.request.query_params.get('host'):
+            # Filter notes by host
+            notes = notes.filter(host=int(host))
 
-        if self.request.GET.get('owner') != None:
-            '''Filter notes by show owner: all notes the user may edit'''
-            shows = Show.objects.filter(owners=int(self.request.GET.get('owner')))
+        if owner := self.request.query_params.get('owner'):
+            # Filter notes by show owner: all notes the user may edit
+            shows = Show.objects.filter(owners=int(owner))
             notes = notes.filter(show__in=shows)
 
-        if self.request.GET.get('user') != None:
-            '''Filter notes by their creator'''
-            notes = notes.filter(user=int(self.request.GET.get('user')))
+        if user := self.request.query_params.get('user'):
+            # Filter notes by their creator
+            notes = notes.filter(user=int(user))
 
         return notes
 
-
-    def create(self, request, pk=None, timeslot_pk=None, schedule_pk=None, show_pk=None):
+    def create(self, request, *args, **kwargs):
         """Create a note"""
+        show_pk = int_or_none('show_pk', self.kwargs)
+        schedule_pk = int_or_none('schedule_pk', self.kwargs)
+        timeslot_pk = int_or_none('timeslot_pk', self.kwargs)
 
         # Only create a note if show_id, timeslot_id and schedule_id is given
-        if show_pk == None or schedule_pk == None or timeslot_pk == None:
+        if show_pk is None or schedule_pk is None or timeslot_pk is None:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
         if not Show.is_editable(self, show_pk):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        serializer = NoteSerializer(data=request.data, context={ 'user_id': request.user.id })
+        serializer = NoteSerializer(data=request.data, context={'user_id': request.user.id})
 
         if serializer.is_valid():
 
             # Don't assign a host the user mustn't edit
-            if not Host.is_editable(self, request.data['host']) or request.data['host'] == None:
+            if not Host.is_editable(self, request.data['host']) or request.data['host'] is None:
                 serializer.validated_data['host'] = None
 
             serializer.save()
@@ -928,8 +729,7 @@ class APINoteViewSet(viewsets.ModelViewSet):
 
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
 
-
-    def retrieve(self, request, pk=None, timeslot_pk=None, schedule_pk=None, show_pk=None):
+    def retrieve(self, request, *args, **kwargs):
         """
         Returns a single note
 
@@ -939,13 +739,17 @@ class APINoteViewSet(viewsets.ModelViewSet):
         /shows/1/timeslots/1/note/1
         /shows/1/schedules/1/timeslots/1/note/1
         """
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
+        schedule_pk = int_or_none('schedule_pk', self.kwargs)
+        timeslot_pk = int_or_none('timeslot_pk', self.kwargs)
 
         #
         #      /shows/1/notes/1
         #
         #      Returns a note to a show
         #
-        if show_pk != None and timeslot_pk == None and schedule_pk == None:
+        if show_pk and timeslot_pk is None and schedule_pk is None:
             note = get_object_or_404(Note, pk=pk, show=show_pk)
 
         #
@@ -954,7 +758,7 @@ class APINoteViewSet(viewsets.ModelViewSet):
         #
         #     Return a note to a timeslot
         #
-        elif show_pk != None and timeslot_pk != None:
+        elif show_pk and timeslot_pk:
             note = get_object_or_404(Note, pk=pk, show=show_pk, timeslot=timeslot_pk)
 
         #
@@ -968,11 +772,14 @@ class APINoteViewSet(viewsets.ModelViewSet):
         serializer = NoteSerializer(note)
         return Response(serializer.data)
 
-
-    def update(self, request, pk=None, show_pk=None, schedule_pk=None, timeslot_pk=None):
+    def update(self, request, *args, **kwargs):
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
+        schedule_pk = int_or_none('schedule_pk', self.kwargs)
+        timeslot_pk = int_or_none('timeslot_pk', self.kwargs)
 
         # Allow PUT only when calling /shows/1/schedules/1/timeslots/1/note/1
-        if show_pk == None or schedule_pk == None or timeslot_pk == None:
+        if show_pk is None or schedule_pk is None or timeslot_pk is None:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
         note = get_object_or_404(Note, pk=pk, timeslot=timeslot_pk, show=show_pk)
@@ -986,18 +793,22 @@ class APINoteViewSet(viewsets.ModelViewSet):
         if serializer.is_valid():
 
             # Don't assign a host the user mustn't edit. Reassign the original value instead
-            if not Host.is_editable(self, request.data['host']) and request.data['host'] != None:
+            if not Host.is_editable(self, request.data['host']) and request.data['host']:
                 serializer.validated_data['host'] = Host.objects.filter(pk=note.host_id)[0]
 
-            serializer.save();
+            serializer.save()
             return Response(serializer.data)
 
         return Response(status=status.HTTP_400_BAD_REQUEST)
 
-
-    def destroy(self, request, pk=None, show_pk=None, schedule_pk=None, timeslot_pk=None):
+    def destroy(self, request, *args, **kwargs):
         # Allow DELETE only when calling /shows/1/schedules/1/timeslots/1/note/1
-        if show_pk == None or schedule_pk == None or timeslot_pk == None:
+        pk = int_or_none('pk', self.kwargs)
+        show_pk = int_or_none('show_pk', self.kwargs)
+        schedule_pk = int_or_none('schedule_pk', self.kwargs)
+        timeslot_pk = int_or_none('timeslot_pk', self.kwargs)
+
+        if show_pk is None or schedule_pk is None or timeslot_pk is None:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
         note = get_object_or_404(Note, pk=pk)
@@ -1011,23 +822,23 @@ class APINoteViewSet(viewsets.ModelViewSet):
 
 class APICategoryViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/categories/              Returns all categories (GET, POST)
-    /api/v1/categories/?active=true  Returns all active categories (GET)
-    /api/v1/categories/?active=false Returns all inactive categories (GET)
-    /api/v1/categories/1             Returns a category by its ID (GET, PUT, DELETE)
+    /categories/ returns all categories (GET, POST)
+    /categories/?active=true returns all active categories (GET)
+    /categories/?active=false returns all inactive categories (GET)
+    /categories/{pk} Returns a category by its ID (GET, PUT, DELETE)
     """
+
     queryset = Category.objects.all()
     serializer_class = CategorySerializer
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
 
-
     def get_queryset(self):
-        '''Filters'''
+        """Filters"""
 
-        if self.request.GET.get('active') == 'true':
+        if self.request.query_params.get('active') == 'true':
             return Category.objects.filter(is_active=True)
 
-        if self.request.GET.get('active') == 'false':
+        if self.request.query_params.get('active') == 'false':
             return Category.objects.filter(is_active=False)
 
         return Category.objects.all()
@@ -1035,10 +846,10 @@ class APICategoryViewSet(viewsets.ModelViewSet):
 
 class APITypeViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/types/              Returns all types (GET, POST)
-    /api/v1/types/?active=true  Returns all active types (GET)
-    /api/v1/types/?active=false Returns all active types (GET)
-    /api/v1/types/1             Returns a type by its ID (GET, PUT, DELETE)
+    /types/ returns all types (GET, POST)
+    /types/?active=true returns all active types (GET)
+    /types/?active=false returns all inactive types (GET)
+    /types/{pk} returns a type by its ID (GET, PUT, DELETE)
     """
 
     queryset = Type.objects.all()
@@ -1046,12 +857,12 @@ class APITypeViewSet(viewsets.ModelViewSet):
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
 
     def get_queryset(self):
-        '''Filters'''
+        """Filters"""
 
-        if self.request.GET.get('active') == 'true':
+        if self.request.query_params.get('active') == 'true':
             return Type.objects.filter(is_active=True)
 
-        if self.request.GET.get('active') == 'false':
+        if self.request.query_params.get('active') == 'false':
             return Type.objects.filter(is_active=False)
 
         return Type.objects.all()
@@ -1059,9 +870,9 @@ class APITypeViewSet(viewsets.ModelViewSet):
 
 class APITopicViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/topics/             Returns all topics (GET, POST)
-    /api/v1/topics/?active=true Returns all active topics (GET)
-    /api/v1/topics/1            Returns a topic by its ID (GET, PUT, DELETE)
+    /topics/: Returns all topics (GET, POST)
+    /topics/?active=true Returns all active topics (GET)
+    /topics/{pk}: Returns a topic by its ID (GET, PUT, DELETE)
     """
 
     queryset = Topic.objects.all()
@@ -1069,24 +880,23 @@ class APITopicViewSet(viewsets.ModelViewSet):
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
 
     def get_queryset(self):
-        '''Filters'''
+        """Filters"""
 
-        if self.request.GET.get('active') == 'true':
+        if self.request.query_params.get('active') == 'true':
             return Topic.objects.filter(is_active=True)
 
-        if self.request.GET.get('active') == 'false':
+        if self.request.query_params.get('active') == 'false':
             return Topic.objects.filter(is_active=False)
 
         return Topic.objects.all()
 
 
-
 class APIMusicFocusViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/musicfocus/              Returns all musicfocuses (GET, POST)
-    /api/v1/musicfocus/?active=true  Returns all active musicfocuses (GET)
-    /api/v1/musicfocus/?active=false Returns all inactive musicfocuses (GET)
-    /api/v1/musicfocus/1             Returns a musicfocus by its ID (GET, PUT, DELETE)
+    /musicfocus/ returns all music focuses (GET, POST)
+    /musicfocus/?active=true: returns all active music focuses (GET)
+    /musicfocus/?active=false: returns all inactive music focuses (GET)
+    /musicfocus/{pk}: returns a music focus by its ID (GET, PUT, DELETE)
     """
 
     queryset = MusicFocus.objects.all()
@@ -1094,24 +904,23 @@ class APIMusicFocusViewSet(viewsets.ModelViewSet):
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
 
     def get_queryset(self):
-        '''Filters'''
+        """Filters"""
 
-        if self.request.GET.get('active') == 'true':
+        if self.request.query_params.get('active') == 'true':
             return MusicFocus.objects.filter(is_active=True)
 
-        if self.request.GET.get('active') == 'false':
+        if self.request.query_params.get('active') == 'false':
             return MusicFocus.objects.filter(is_active=False)
 
         return MusicFocus.objects.all()
 
 
-
 class APIFundingCategoryViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/fundingcategories/              Returns all fundingcategories (GET, POST)
-    /api/v1/fundingcategories/?active=true  Returns all active fundingcategories (GET)
-    /api/v1/fundingcategories/?active=false Returns all active fundingcategories (GET)
-    /api/v1/fundingcategories/1             Returns a fundingcategory by its ID (GET, PUT, DELETE)
+    /fundingcategories/: returns all funding categories (GET, POST)
+    /fundingcategories/?active=true returns all active funding categories (GET)
+    /fundingcategories/?active=false returns all inactive funding categories (GET)
+    /fundingcategories/{pk} returns a funding category by its ID (GET, PUT, DELETE)
     """
 
     queryset = FundingCategory.objects.all()
@@ -1119,24 +928,23 @@ class APIFundingCategoryViewSet(viewsets.ModelViewSet):
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
 
     def get_queryset(self):
-        '''Filters'''
+        """Filters"""
 
-        if self.request.GET.get('active') == 'true':
+        if self.request.query_params.get('active') == 'true':
             return FundingCategory.objects.filter(is_active=True)
 
-        if self.request.GET.get('active') == 'false':
+        if self.request.query_params.get('active') == 'false':
             return FundingCategory.objects.filter(is_active=False)
 
         return FundingCategory.objects.all()
 
 
-
 class APILanguageViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/languages/              Returns all languages (GET, POST)
-    /api/v1/languages/?active=true  Returns all active languages (GET)
-    /api/v1/languages/?active=false Returns all active languages (GET)
-    /api/v1/languages/1             Returns a language by its ID (GET, PUT, DELETE)
+    /languages/ returns all languages (GET, POST)
+    /languages/?active=true returns all active languages (GET)
+    /languages/?active=false returns all inactive languages (GET)
+    /languages/{pk} returns a language by its ID (GET, PUT, DELETE)
     """
 
     queryset = Language.objects.all()
@@ -1144,24 +952,23 @@ class APILanguageViewSet(viewsets.ModelViewSet):
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
 
     def get_queryset(self):
-        '''Filters'''
+        """Filters"""
 
-        if self.request.GET.get('active') == 'true':
+        if self.request.query_params.get('active') == 'true':
             return Language.objects.filter(is_active=True)
 
-        if self.request.GET.get('active') == 'false':
+        if self.request.query_params.get('active') == 'false':
             return Language.objects.filter(is_active=False)
 
         return Language.objects.all()
 
 
-
 class APIHostViewSet(viewsets.ModelViewSet):
     """
-    /api/v1/hosts/              Returns all hosts (GET, POST)
-    /api/v1/hosts/?active=true  Returns all active hosts (GET)
-    /api/v1/hosts/?active=false Returns all active hosts (GET)
-    /api/v1/hosts/1             Returns a host by its ID (GET, PUT, DELETE)
+    /hosts/ returns all hosts (GET, POST)
+    /hosts/?active=true returns all active hosts (GET)
+    /hosts/?active=false returns all inactive hosts (GET)
+    /hosts/{pk} returns a host by its ID (GET, PUT, DELETE)
     """
 
     queryset = Host.objects.all()
@@ -1170,12 +977,12 @@ class APIHostViewSet(viewsets.ModelViewSet):
     pagination_class = LimitOffsetPagination
 
     def get_queryset(self):
-        '''Filters'''
+        """Filters"""
 
-        if self.request.GET.get('active') == 'true':
+        if self.request.query_params.get('active') == 'true':
             return Host.objects.filter(is_active=True)
 
-        if self.request.GET.get('active') == 'false':
+        if self.request.query_params.get('active') == 'false':
             return Host.objects.filter(is_active=False)
 
-        return Host.objects.all()
\ No newline at end of file
+        return Host.objects.all()
diff --git a/pv/__init__.py b/pv/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/pv/local_settings.py.sample b/pv/local_settings.py.sample
deleted file mode 100644
index a46813ea3171ee20c938686c8263ca27705f4158..0000000000000000000000000000000000000000
--- a/pv/local_settings.py.sample
+++ /dev/null
@@ -1,42 +0,0 @@
-
-import os
-
-CONFIG_DIR = '/etc/aura/'
-DB_CONFIG = 'steering.mysql.cnf'
-
-SECRET_KEY = '---some-secred-key---'
-
-DATABASES = {
-    'default': {
-        'ENGINE': 'django.db.backends.mysql',
-        'OPTIONS': {
-            'read_default_file': os.path.join(CONFIG_DIR, DB_CONFIG),
-        },
-    }
-}
-
-CORS_ALLOW_CREDENTIALS = True
-CORS_ORIGIN_WHITELIST = (
-    'http://localhost:8080'
-    # 'https://aura-test.o94.at',
-    # 'https://aura-test.o94.at:443',
-)
-CORS_ALLOW_HEADERS = list(default_headers) + [
-    'content-disposition',
-]
-
-# Uncomment this *after* you have initialized the DB with default tables and data:
-#USE_TZ = False
-
-
-# Comment out the following for temporary debugging, if you want to use the
-# native DRF web forms
-"""
-REST_FRAMEWORK = {
-    # Use Django's standard `django.contrib.auth` permissions,
-    # or allow read-only access for unauthenticated users.
-    'DEFAULT_PERMISSION_CLASSES': [
-        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
-    ],
-}
-"""
diff --git a/pv/oidc_provider_settings.py b/pv/oidc_provider_settings.py
deleted file mode 100644
index a3e2465b3ee6607f9153dc4574058938d15147b7..0000000000000000000000000000000000000000
--- a/pv/oidc_provider_settings.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from django.utils.translation import ugettext as _
-from oidc_provider.lib.claims import ScopeClaims
-
-
-class AuraScopeClaims(ScopeClaims):
-
-    info_username = (
-        _(u'username'),
-        _(u'Your username.'),
-    )
-
-    def scope_username(self):
-        dic = {
-            'username': self.user.username,
-            #'privileged': (self.user.is_staff or self.user.is_superuser)
-            'privileged': (self.user.is_superuser)
-        }
-
-        return dic
-
-    info_aura_shows = (
-        _(u'AURA Shows'),
-        _(u'AURA shows you have access to.'),
-    )
-
-    def scope_aura_shows(self):
-        from program.models import Show
-
-        # TODO: should add filter `is_active=True` ?
-        public_show_slugs = list(Show.objects.filter(is_public=True).values_list('slug', flat=True))
-        show_slugs = list(self.user.shows.all().values_list('slug', flat=True))
-        dic = {
-            'shows': show_slugs,
-            'public-shows': public_show_slugs
-        }
-
-        return dic
diff --git a/requirements.txt b/requirements.txt
index 895d7bbde875a25d6eca5072254a5dad1a77d617..6cf615e69087413e41e1cc4c0f145653299bf19c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,8 +3,14 @@ django-cors-headers==3.2.1
 django-oidc-provider==0.7.0
 django-tinymce==2.8.0
 django-versatileimagefield==1.11
+django-environ==0.4.5
 djangorestframework==3.11.0
 drf-nested-routers==0.91
 Pillow==4.3.0
 python-dateutil==2.8.1
-PyYAML==3.13
+
+# needed for the database (container)
+psycopg2_binary==2.8.6
+
+# needed for production server
+gunicorn==20.0.4
diff --git a/run.sh b/run.sh
index 4ad27d8f8a0621bd8ac58b91f0de76878c807e73..2d50f25e71ed9cdba2db0e96d08692992706628e 100755
--- a/run.sh
+++ b/run.sh
@@ -1,4 +1,100 @@
 #!/bin/bash
-BASE_D=$(realpath "${BASH_SOURCE%/*}/")
+# Default mode
+mode="dev"
+docker="false"
 
-exec sudo docker run --rm -it -u $UID:$GID -p 127.0.0.1:8000:8000 -v "$BASE_D":/srv aura/pv /srv/manage.py runserver 0.0.0.0:8000
+#
+# Run Script for AURA Steering
+#
+# Call with one of these parameters:
+#
+# - init
+# - dev
+# - prod
+# - test
+
+# - docker:build
+# - docker:push
+# - docker:serve
+# 
+
+if [[ $* =~ ^(init|dev|prod|test|build|push|serve)$ ]]; then 
+	mode=$1 
+fi
+
+if [[ "$1" == *"docker:"* ]]; then
+	docker="true"
+	mode=${1#*:}
+fi
+
+
+echo "[ Run mode=$mode ]"
+echo "[ Docker=$docker ]"
+
+
+
+# +++ DEFAULT COMMANDS +++ #
+
+if [[ $docker == "false" ]]; then
+
+	### Initializes the project (Development) ###
+
+	if [[ $mode == "init" ]]; then
+		echo "Creating Python VirtualEnvironment"
+		virtualenv -p python3.6 python
+        echo "Install dependencies"
+        pip3 install -r requirements.txt
+        echo "Next you need to create the configuration, run fixtues, migrations and create a superuser."
+	fi
+
+	### Runs Steering in development mode (Virtualenv) ###
+
+	if [[ $mode == "dev" ]]; then
+		echo "Activating Python Environment"
+		source python/bin/activate
+        python manage.py runserver
+	fi
+
+	### Runs Steering in production mode (WSGI) ###
+
+	if [[ $mode == "prod" ]]; then
+		echo "!!! Not yet implemented !!!"
+		#gunicorn -c config/gunicorn.conf.py src.app:app
+	fi
+
+	### Runs the test-cases ###
+
+	if [[ $mode == "test" ]]; then
+		echo "!!! Not yet implemented !!!"
+	fi
+
+fi
+
+
+# +++ DOCKER COMMANDS +++ #
+
+if [[ $docker == "true" ]]; then
+	BASE_D=$(realpath "${BASH_SOURCE%/*}/")
+
+	### Runs Steering from Docker ###
+
+	if [[ $mode == "serve" ]]; then
+		exec sudo docker run --rm -it \
+            -u $UID:$GID \
+            -p 127.0.0.1:8000:8000 \
+            -v "$BASE_D":/srv autoradio/steering /srv/manage.py \
+            runserver 0.0.0.0:8000
+	fi
+
+	### Create Docker Image from local project ###
+
+	if [[ $mode == "build" ]]; then
+		exec sudo docker build -t autoradio/steering .
+	fi
+
+	### Pushes the latest Docker Image to Docker Hub ###
+
+	if [[ $mode == "push" ]]; then
+		exec sudo docker push autoradio/steering
+	fi
+fi
diff --git a/nop/__init__.py b/steering/__init__.py
similarity index 100%
rename from nop/__init__.py
rename to steering/__init__.py
diff --git a/steering/oidc_provider_settings.py b/steering/oidc_provider_settings.py
new file mode 100644
index 0000000000000000000000000000000000000000..e82cbd7a3e722c9342b7f5b0b73555571ed0608a
--- /dev/null
+++ b/steering/oidc_provider_settings.py
@@ -0,0 +1,56 @@
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from django.utils.translation import ugettext as _
+from oidc_provider.lib.claims import ScopeClaims
+
+
+class AuraScopeClaims(ScopeClaims):
+    info_username = (
+        _(u'username'),
+        _(u'Your username.'),
+    )
+
+    def scope_username(self):
+        dic = {
+            'username': self.user.username,
+            # 'privileged': (self.user.is_staff or self.user.is_superuser)
+            'privileged': self.user.is_superuser
+        }
+
+        return dic
+
+    info_aura_shows = (
+        _(u'AURA Shows'),
+        _(u'AURA shows you have access to.'),
+    )
+
+    def scope_aura_shows(self):
+        from program.models import Show
+
+        # TODO: should add filter `is_active=True` ?
+        public_show_slugs = list(Show.objects.filter(is_public=True).values_list('slug', flat=True))
+        show_slugs = list(self.user.shows.all().values_list('slug', flat=True))
+        dic = {
+            'shows': show_slugs,
+            'public-shows': public_show_slugs
+        }
+
+        return dic
diff --git a/pv/settings.py b/steering/settings.py
similarity index 66%
rename from pv/settings.py
rename to steering/settings.py
index 80514a60eb68ab845283e11006f7e50309206cbe..6d3390c4b590825329e6fc1eb2658a9c748311eb 100644
--- a/pv/settings.py
+++ b/steering/settings.py
@@ -1,8 +1,8 @@
-# -*- coding: utf-8 -*-
-
 # Django settings for pv project.
 
 import os.path
+import environ
+from corsheaders.defaults import default_headers
 
 # Paths
 
@@ -18,67 +18,68 @@ MEDIA_URL = '/site_media/'
 STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
 STATIC_URL = '/static/'
 
-ROOT_URLCONF = 'pv.urls'
+ROOT_URLCONF = 'steering.urls'
+
+env = environ.Env()
+env.read_env(env_file=PROJECT_DIR+'/../.env')
 
-DEBUG = True
+DOCKER = env.bool('RUN_IN_DOCKER', default=True)
+DEBUG = env.bool('DEBUG', default=False)
 SITE_ID = 1
 ADMINS = ()
 MANAGERS = ADMINS
 
 # Must be set if DEBUG is False
-ALLOWED_HOSTS = ['127.0.0.1', 'localhost']
+ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['127.0.0.1', 'localhost'])
 
 # Whitelist IPs that access the API
-CORS_ORIGIN_WHITELIST = (
-   'localhost',
-   'localhost:8080'
-)
-
+CORS_ORIGIN_WHITELIST = env.list('CORS_ORIGIN_WHITELIST', default=(
+    'http://localhost:8080',
+    'http://127.0.0.1:8080'
+))
+CORS_ALLOW_CREDENTIALS = True
+CORS_ALLOW_HEADERS = list(default_headers) + [
+    'content-disposition',
+]
 
 # Define which database backend to use for our apps
 DATABASES = {
     # SQLITE
-    'default': {
-        'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': os.path.join(PROJECT_DIR, 'dev_data.sqlite'),
-    },
+    #'default': {
+    #    'ENGINE': 'django.db.backends.sqlite3',
+    #    'NAME': os.path.join(PROJECT_DIR, 'dev_data.sqlite'),
+    #},
 
-    """
+    # PostgreSQL
     'default': {
         'ENGINE': 'django.db.backends.postgresql',
-        'OPTIONS': {
-            'read_default_file': os.path.join(PROJECT_DIR, 'postgresql.cnf'),
-        },
+        'NAME': env.str('DBNAME', default='steering'),
+        'USER': env.str('DBUSER', default='steering'),
+        'PASSWORD': env.str('DBPASS'),
+        'HOST': env.str('DBHOST', default='steering-postgres'),
+        'PORT': env.str('DBPORT', '5432'),
     },
-    """
 
-    """
     # MySQL
-    'default': {
-        'ENGINE': 'django.db.backends.mysql',
-        'OPTIONS': {
-            'read_default_file': os.path.join(PROJECT_DIR, 'mysql.cnf'),
-        },
-    },
-    """
-
-    # Deprecated
-    'nop': {
-        'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': os.path.join(PROJECT_DIR, 'dev_nop.sqlite'),
-    },
-
+    #    'default': {
+    #        'ENGINE': 'django.db.backends.mysql',
+    #        'OPTIONS': {
+    #            'read_default_file': os.path.join(PROJECT_DIR, 'mysql.cnf'),
+    #        },
+    #   },
 }
+if not DOCKER:
+    DATABASES['default']['HOST'] = env.str('DBHOST', default='localhost')
 
 CACHE_BACKEND = 'locmem://'
 
 # LOCALIZATION
-TIME_ZONE = 'Europe/Vienna'
-LANGUAGE_CODE = 'de'
+TIME_ZONE = env.str('TIME_ZONE', default='Europe/Vienna')
+LANGUAGE_CODE = env.str('LANGUAGE_CODE', default='de')
 USE_I18N = True
 USE_L10N = True
 
-SECRET_KEY = ''
+SECRET_KEY = env.str('SECRET_KEY')
 
 TEMPLATES = [
     {
@@ -130,7 +131,6 @@ INSTALLED_APPS = (
     'django.contrib.admin',
     'django.contrib.staticfiles',
     'program',
-    'nop', # Deprecated
     'profile',
     'tinymce',
     'versatileimagefield',
@@ -145,13 +145,13 @@ INSTALLED_APPS = (
 # Will apply to all uploaded images
 THUMBNAIL_SIZES = ['640x480', '200x200', '150x150']
 
-#TINYMCE_JS_URL = '/static/js/tiny_mce/tiny_mce.js'
+# TINYMCE_JS_URL = '/static/js/tiny_mce/tiny_mce.js'
 TINYMCE_DEFAULT_CONFIG = {
-    #'plugins': 'contextmenu',
+    # 'plugins': 'contextmenu',
     'selector': 'textarea',
     'theme': 'advanced',
     'theme_advanced_toolbar_location': 'top',
-    'theme_advanced_buttons1' : 'bold,italic,underline,separator,bullist,numlist,separator,link,unlink,separator,undo,redo,separator,formatselect',
+    'theme_advanced_buttons1': 'bold,italic,underline,separator,bullist,numlist,separator,link,unlink,separator,undo,redo,separator,formatselect',
     'theme_advanced_blockformats': 'p,h1,h2,h3,blockquote',
     'theme_advanced_font_sizes': '14px,16px',
     'cleanup_on_startup': True,
@@ -159,7 +159,6 @@ TINYMCE_DEFAULT_CONFIG = {
     'height': 400,
 }
 
-
 # When generating schedules/timeslots:
 # If until date wasn't set manually, add x days to the start date
 AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE = 365
@@ -168,10 +167,6 @@ AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE = 365
 # Overrides the above setting if True
 AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR = True
 
-# The station's fallback playlist ID
-# If there's no program, this playlist will be aired as a backup
-STATION_FALLBACK_ID = None
-
 # URL to CBA - Cultural Broadcasting Archive
 CBA_URL = 'https://cba.fro.at'
 
@@ -185,23 +180,12 @@ CBA_AJAX_URL = CBA_URL + '/wp-admin/admin-ajax.php'
 # URL to CBA's REST API with trailing slash
 CBA_REST_API_URL = CBA_URL + '/wp-json/wp/v2/'
 
-
 # OIDC Provider Settings
-USE_TZ = True # django-oidc-provider needs timezones in database
-LOGIN_URL = '/admin/login/' # Login page OIDC redirects to
-OIDC_EXTRA_SCOPE_CLAIMS = 'pv.oidc_provider_settings.AuraScopeClaims'
-
-#WSGI_APPLICATION = 'pv.wsgi.application';
-
-
-# Deprecated
-DATABASE_ROUTERS = ['nop.dbrouter.NopRouter']
-MUSIKPROG_IDS = (
-    1,    # unmodieriertes musikprogramm
-)
-SPECIAL_PROGRAM_IDS = ()
-
+USE_TZ = True  # django-oidc-provider needs timezones in database
+LOGIN_URL = '/admin/login/'  # Login page OIDC redirects to
+OIDC_EXTRA_SCOPE_CLAIMS = 'steering.oidc_provider_settings.AuraScopeClaims'
 
+# WSGI_APPLICATION = 'steering.wsgi.application';
 
 try:
     from .local_settings import *
diff --git a/pv/site_media/buttons/default-11.png b/steering/site_media/buttons/default-11.png
similarity index 100%
rename from pv/site_media/buttons/default-11.png
rename to steering/site_media/buttons/default-11.png
diff --git a/pv/site_media/buttons/default-17.png b/steering/site_media/buttons/default-17.png
similarity index 100%
rename from pv/site_media/buttons/default-17.png
rename to steering/site_media/buttons/default-17.png
diff --git a/pv/site_media/js/calendar/CHANGELOG.txt b/steering/site_media/js/calendar/CHANGELOG.txt
similarity index 100%
rename from pv/site_media/js/calendar/CHANGELOG.txt
rename to steering/site_media/js/calendar/CHANGELOG.txt
diff --git a/pv/site_media/js/calendar/CONTRIBUTING.txt b/steering/site_media/js/calendar/CONTRIBUTING.txt
similarity index 100%
rename from pv/site_media/js/calendar/CONTRIBUTING.txt
rename to steering/site_media/js/calendar/CONTRIBUTING.txt
diff --git a/pv/site_media/js/calendar/LICENSE.txt b/steering/site_media/js/calendar/LICENSE.txt
similarity index 100%
rename from pv/site_media/js/calendar/LICENSE.txt
rename to steering/site_media/js/calendar/LICENSE.txt
diff --git a/pv/site_media/js/calendar/demos/agenda-views.html b/steering/site_media/js/calendar/demos/agenda-views.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/agenda-views.html
rename to steering/site_media/js/calendar/demos/agenda-views.html
diff --git a/pv/site_media/js/calendar/demos/background-events.html b/steering/site_media/js/calendar/demos/background-events.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/background-events.html
rename to steering/site_media/js/calendar/demos/background-events.html
diff --git a/pv/site_media/js/calendar/demos/basic-views.html b/steering/site_media/js/calendar/demos/basic-views.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/basic-views.html
rename to steering/site_media/js/calendar/demos/basic-views.html
diff --git a/pv/site_media/js/calendar/demos/default.html b/steering/site_media/js/calendar/demos/default.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/default.html
rename to steering/site_media/js/calendar/demos/default.html
diff --git a/pv/site_media/js/calendar/demos/external-dragging.html b/steering/site_media/js/calendar/demos/external-dragging.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/external-dragging.html
rename to steering/site_media/js/calendar/demos/external-dragging.html
diff --git a/pv/site_media/js/calendar/demos/gcal.html b/steering/site_media/js/calendar/demos/gcal.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/gcal.html
rename to steering/site_media/js/calendar/demos/gcal.html
diff --git a/pv/site_media/js/calendar/demos/json.html b/steering/site_media/js/calendar/demos/json.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/json.html
rename to steering/site_media/js/calendar/demos/json.html
diff --git a/pv/site_media/js/calendar/demos/json/events.json b/steering/site_media/js/calendar/demos/json/events.json
similarity index 100%
rename from pv/site_media/js/calendar/demos/json/events.json
rename to steering/site_media/js/calendar/demos/json/events.json
diff --git a/pv/site_media/js/calendar/demos/list-views.html b/steering/site_media/js/calendar/demos/list-views.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/list-views.html
rename to steering/site_media/js/calendar/demos/list-views.html
diff --git a/pv/site_media/js/calendar/demos/locales.html b/steering/site_media/js/calendar/demos/locales.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/locales.html
rename to steering/site_media/js/calendar/demos/locales.html
diff --git a/pv/site_media/js/calendar/demos/php/get-events.php b/steering/site_media/js/calendar/demos/php/get-events.php
similarity index 100%
rename from pv/site_media/js/calendar/demos/php/get-events.php
rename to steering/site_media/js/calendar/demos/php/get-events.php
diff --git a/pv/site_media/js/calendar/demos/php/get-timezones.php b/steering/site_media/js/calendar/demos/php/get-timezones.php
similarity index 100%
rename from pv/site_media/js/calendar/demos/php/get-timezones.php
rename to steering/site_media/js/calendar/demos/php/get-timezones.php
diff --git a/pv/site_media/js/calendar/demos/php/utils.php b/steering/site_media/js/calendar/demos/php/utils.php
similarity index 100%
rename from pv/site_media/js/calendar/demos/php/utils.php
rename to steering/site_media/js/calendar/demos/php/utils.php
diff --git a/pv/site_media/js/calendar/demos/selectable.html b/steering/site_media/js/calendar/demos/selectable.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/selectable.html
rename to steering/site_media/js/calendar/demos/selectable.html
diff --git a/pv/site_media/js/calendar/demos/theme.html b/steering/site_media/js/calendar/demos/theme.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/theme.html
rename to steering/site_media/js/calendar/demos/theme.html
diff --git a/pv/site_media/js/calendar/demos/timezones.html b/steering/site_media/js/calendar/demos/timezones.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/timezones.html
rename to steering/site_media/js/calendar/demos/timezones.html
diff --git a/pv/site_media/js/calendar/demos/week-numbers.html b/steering/site_media/js/calendar/demos/week-numbers.html
similarity index 100%
rename from pv/site_media/js/calendar/demos/week-numbers.html
rename to steering/site_media/js/calendar/demos/week-numbers.html
diff --git a/pv/site_media/js/calendar/fullcalendar.css b/steering/site_media/js/calendar/fullcalendar.css
similarity index 100%
rename from pv/site_media/js/calendar/fullcalendar.css
rename to steering/site_media/js/calendar/fullcalendar.css
diff --git a/pv/site_media/js/calendar/fullcalendar.js b/steering/site_media/js/calendar/fullcalendar.js
similarity index 100%
rename from pv/site_media/js/calendar/fullcalendar.js
rename to steering/site_media/js/calendar/fullcalendar.js
diff --git a/pv/site_media/js/calendar/fullcalendar.min.css b/steering/site_media/js/calendar/fullcalendar.min.css
similarity index 100%
rename from pv/site_media/js/calendar/fullcalendar.min.css
rename to steering/site_media/js/calendar/fullcalendar.min.css
diff --git a/pv/site_media/js/calendar/fullcalendar.min.js b/steering/site_media/js/calendar/fullcalendar.min.js
similarity index 100%
rename from pv/site_media/js/calendar/fullcalendar.min.js
rename to steering/site_media/js/calendar/fullcalendar.min.js
diff --git a/pv/site_media/js/calendar/fullcalendar.print.css b/steering/site_media/js/calendar/fullcalendar.print.css
similarity index 100%
rename from pv/site_media/js/calendar/fullcalendar.print.css
rename to steering/site_media/js/calendar/fullcalendar.print.css
diff --git a/pv/site_media/js/calendar/fullcalendar.print.min.css b/steering/site_media/js/calendar/fullcalendar.print.min.css
similarity index 100%
rename from pv/site_media/js/calendar/fullcalendar.print.min.css
rename to steering/site_media/js/calendar/fullcalendar.print.min.css
diff --git a/pv/site_media/js/calendar/gcal.js b/steering/site_media/js/calendar/gcal.js
similarity index 100%
rename from pv/site_media/js/calendar/gcal.js
rename to steering/site_media/js/calendar/gcal.js
diff --git a/pv/site_media/js/calendar/gcal.min.js b/steering/site_media/js/calendar/gcal.min.js
similarity index 100%
rename from pv/site_media/js/calendar/gcal.min.js
rename to steering/site_media/js/calendar/gcal.min.js
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_100_e4f1fb_1x400.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_100_e4f1fb_1x400.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_100_e4f1fb_1x400.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_100_e4f1fb_1x400.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_50_3baae3_1x400.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_50_3baae3_1x400.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_50_3baae3_1x400.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_50_3baae3_1x400.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_80_d7ebf9_1x400.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_80_d7ebf9_1x400.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_80_d7ebf9_1x400.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-bg_glass_80_d7ebf9_1x400.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-hard_70_000000_1x100.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-hard_70_000000_1x100.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-hard_70_000000_1x100.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-hard_70_000000_1x100.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-soft_100_deedf7_1x100.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-soft_100_deedf7_1x100.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-soft_100_deedf7_1x100.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-soft_100_deedf7_1x100.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-soft_25_ffef8f_1x100.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-icons_2694e8_256x240.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-icons_2694e8_256x240.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-icons_2694e8_256x240.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-icons_2694e8_256x240.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-icons_2e83ff_256x240.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-icons_2e83ff_256x240.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-icons_2e83ff_256x240.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-icons_2e83ff_256x240.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-icons_3d80b3_256x240.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-icons_3d80b3_256x240.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-icons_3d80b3_256x240.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-icons_3d80b3_256x240.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-icons_72a7cf_256x240.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-icons_72a7cf_256x240.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-icons_72a7cf_256x240.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-icons_72a7cf_256x240.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/images/ui-icons_ffffff_256x240.png b/steering/site_media/js/calendar/lib/cupertino/images/ui-icons_ffffff_256x240.png
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/images/ui-icons_ffffff_256x240.png
rename to steering/site_media/js/calendar/lib/cupertino/images/ui-icons_ffffff_256x240.png
diff --git a/pv/site_media/js/calendar/lib/cupertino/jquery-ui.min.css b/steering/site_media/js/calendar/lib/cupertino/jquery-ui.min.css
similarity index 100%
rename from pv/site_media/js/calendar/lib/cupertino/jquery-ui.min.css
rename to steering/site_media/js/calendar/lib/cupertino/jquery-ui.min.css
diff --git a/pv/site_media/js/calendar/lib/jquery-ui.min.js b/steering/site_media/js/calendar/lib/jquery-ui.min.js
similarity index 100%
rename from pv/site_media/js/calendar/lib/jquery-ui.min.js
rename to steering/site_media/js/calendar/lib/jquery-ui.min.js
diff --git a/pv/site_media/js/calendar/lib/jquery.min.js b/steering/site_media/js/calendar/lib/jquery.min.js
similarity index 100%
rename from pv/site_media/js/calendar/lib/jquery.min.js
rename to steering/site_media/js/calendar/lib/jquery.min.js
diff --git a/pv/site_media/js/calendar/lib/moment.min.js b/steering/site_media/js/calendar/lib/moment.min.js
similarity index 100%
rename from pv/site_media/js/calendar/lib/moment.min.js
rename to steering/site_media/js/calendar/lib/moment.min.js
diff --git a/pv/site_media/js/calendar/locale-all.js b/steering/site_media/js/calendar/locale-all.js
similarity index 100%
rename from pv/site_media/js/calendar/locale-all.js
rename to steering/site_media/js/calendar/locale-all.js
diff --git a/pv/site_media/js/calendar/locale/af.js b/steering/site_media/js/calendar/locale/af.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/af.js
rename to steering/site_media/js/calendar/locale/af.js
diff --git a/pv/site_media/js/calendar/locale/ar-dz.js b/steering/site_media/js/calendar/locale/ar-dz.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ar-dz.js
rename to steering/site_media/js/calendar/locale/ar-dz.js
diff --git a/pv/site_media/js/calendar/locale/ar-ly.js b/steering/site_media/js/calendar/locale/ar-ly.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ar-ly.js
rename to steering/site_media/js/calendar/locale/ar-ly.js
diff --git a/pv/site_media/js/calendar/locale/ar-ma.js b/steering/site_media/js/calendar/locale/ar-ma.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ar-ma.js
rename to steering/site_media/js/calendar/locale/ar-ma.js
diff --git a/pv/site_media/js/calendar/locale/ar-sa.js b/steering/site_media/js/calendar/locale/ar-sa.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ar-sa.js
rename to steering/site_media/js/calendar/locale/ar-sa.js
diff --git a/pv/site_media/js/calendar/locale/ar-tn.js b/steering/site_media/js/calendar/locale/ar-tn.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ar-tn.js
rename to steering/site_media/js/calendar/locale/ar-tn.js
diff --git a/pv/site_media/js/calendar/locale/ar.js b/steering/site_media/js/calendar/locale/ar.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ar.js
rename to steering/site_media/js/calendar/locale/ar.js
diff --git a/pv/site_media/js/calendar/locale/bg.js b/steering/site_media/js/calendar/locale/bg.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/bg.js
rename to steering/site_media/js/calendar/locale/bg.js
diff --git a/pv/site_media/js/calendar/locale/ca.js b/steering/site_media/js/calendar/locale/ca.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ca.js
rename to steering/site_media/js/calendar/locale/ca.js
diff --git a/pv/site_media/js/calendar/locale/cs.js b/steering/site_media/js/calendar/locale/cs.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/cs.js
rename to steering/site_media/js/calendar/locale/cs.js
diff --git a/pv/site_media/js/calendar/locale/da.js b/steering/site_media/js/calendar/locale/da.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/da.js
rename to steering/site_media/js/calendar/locale/da.js
diff --git a/pv/site_media/js/calendar/locale/de-at.js b/steering/site_media/js/calendar/locale/de-at.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/de-at.js
rename to steering/site_media/js/calendar/locale/de-at.js
diff --git a/pv/site_media/js/calendar/locale/de.js b/steering/site_media/js/calendar/locale/de.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/de.js
rename to steering/site_media/js/calendar/locale/de.js
diff --git a/pv/site_media/js/calendar/locale/el.js b/steering/site_media/js/calendar/locale/el.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/el.js
rename to steering/site_media/js/calendar/locale/el.js
diff --git a/pv/site_media/js/calendar/locale/en-au.js b/steering/site_media/js/calendar/locale/en-au.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/en-au.js
rename to steering/site_media/js/calendar/locale/en-au.js
diff --git a/pv/site_media/js/calendar/locale/en-ca.js b/steering/site_media/js/calendar/locale/en-ca.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/en-ca.js
rename to steering/site_media/js/calendar/locale/en-ca.js
diff --git a/pv/site_media/js/calendar/locale/en-gb.js b/steering/site_media/js/calendar/locale/en-gb.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/en-gb.js
rename to steering/site_media/js/calendar/locale/en-gb.js
diff --git a/pv/site_media/js/calendar/locale/en-ie.js b/steering/site_media/js/calendar/locale/en-ie.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/en-ie.js
rename to steering/site_media/js/calendar/locale/en-ie.js
diff --git a/pv/site_media/js/calendar/locale/en-nz.js b/steering/site_media/js/calendar/locale/en-nz.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/en-nz.js
rename to steering/site_media/js/calendar/locale/en-nz.js
diff --git a/pv/site_media/js/calendar/locale/es-do.js b/steering/site_media/js/calendar/locale/es-do.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/es-do.js
rename to steering/site_media/js/calendar/locale/es-do.js
diff --git a/pv/site_media/js/calendar/locale/es.js b/steering/site_media/js/calendar/locale/es.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/es.js
rename to steering/site_media/js/calendar/locale/es.js
diff --git a/pv/site_media/js/calendar/locale/eu.js b/steering/site_media/js/calendar/locale/eu.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/eu.js
rename to steering/site_media/js/calendar/locale/eu.js
diff --git a/pv/site_media/js/calendar/locale/fa.js b/steering/site_media/js/calendar/locale/fa.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/fa.js
rename to steering/site_media/js/calendar/locale/fa.js
diff --git a/pv/site_media/js/calendar/locale/fi.js b/steering/site_media/js/calendar/locale/fi.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/fi.js
rename to steering/site_media/js/calendar/locale/fi.js
diff --git a/pv/site_media/js/calendar/locale/fr-ca.js b/steering/site_media/js/calendar/locale/fr-ca.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/fr-ca.js
rename to steering/site_media/js/calendar/locale/fr-ca.js
diff --git a/pv/site_media/js/calendar/locale/fr-ch.js b/steering/site_media/js/calendar/locale/fr-ch.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/fr-ch.js
rename to steering/site_media/js/calendar/locale/fr-ch.js
diff --git a/pv/site_media/js/calendar/locale/fr.js b/steering/site_media/js/calendar/locale/fr.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/fr.js
rename to steering/site_media/js/calendar/locale/fr.js
diff --git a/pv/site_media/js/calendar/locale/gl.js b/steering/site_media/js/calendar/locale/gl.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/gl.js
rename to steering/site_media/js/calendar/locale/gl.js
diff --git a/pv/site_media/js/calendar/locale/he.js b/steering/site_media/js/calendar/locale/he.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/he.js
rename to steering/site_media/js/calendar/locale/he.js
diff --git a/pv/site_media/js/calendar/locale/hi.js b/steering/site_media/js/calendar/locale/hi.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/hi.js
rename to steering/site_media/js/calendar/locale/hi.js
diff --git a/pv/site_media/js/calendar/locale/hr.js b/steering/site_media/js/calendar/locale/hr.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/hr.js
rename to steering/site_media/js/calendar/locale/hr.js
diff --git a/pv/site_media/js/calendar/locale/hu.js b/steering/site_media/js/calendar/locale/hu.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/hu.js
rename to steering/site_media/js/calendar/locale/hu.js
diff --git a/pv/site_media/js/calendar/locale/id.js b/steering/site_media/js/calendar/locale/id.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/id.js
rename to steering/site_media/js/calendar/locale/id.js
diff --git a/pv/site_media/js/calendar/locale/is.js b/steering/site_media/js/calendar/locale/is.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/is.js
rename to steering/site_media/js/calendar/locale/is.js
diff --git a/pv/site_media/js/calendar/locale/it.js b/steering/site_media/js/calendar/locale/it.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/it.js
rename to steering/site_media/js/calendar/locale/it.js
diff --git a/pv/site_media/js/calendar/locale/ja.js b/steering/site_media/js/calendar/locale/ja.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ja.js
rename to steering/site_media/js/calendar/locale/ja.js
diff --git a/pv/site_media/js/calendar/locale/kk.js b/steering/site_media/js/calendar/locale/kk.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/kk.js
rename to steering/site_media/js/calendar/locale/kk.js
diff --git a/pv/site_media/js/calendar/locale/ko.js b/steering/site_media/js/calendar/locale/ko.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ko.js
rename to steering/site_media/js/calendar/locale/ko.js
diff --git a/pv/site_media/js/calendar/locale/lb.js b/steering/site_media/js/calendar/locale/lb.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/lb.js
rename to steering/site_media/js/calendar/locale/lb.js
diff --git a/pv/site_media/js/calendar/locale/lt.js b/steering/site_media/js/calendar/locale/lt.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/lt.js
rename to steering/site_media/js/calendar/locale/lt.js
diff --git a/pv/site_media/js/calendar/locale/lv.js b/steering/site_media/js/calendar/locale/lv.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/lv.js
rename to steering/site_media/js/calendar/locale/lv.js
diff --git a/pv/site_media/js/calendar/locale/mk.js b/steering/site_media/js/calendar/locale/mk.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/mk.js
rename to steering/site_media/js/calendar/locale/mk.js
diff --git a/pv/site_media/js/calendar/locale/ms-my.js b/steering/site_media/js/calendar/locale/ms-my.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ms-my.js
rename to steering/site_media/js/calendar/locale/ms-my.js
diff --git a/pv/site_media/js/calendar/locale/ms.js b/steering/site_media/js/calendar/locale/ms.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ms.js
rename to steering/site_media/js/calendar/locale/ms.js
diff --git a/pv/site_media/js/calendar/locale/nb.js b/steering/site_media/js/calendar/locale/nb.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/nb.js
rename to steering/site_media/js/calendar/locale/nb.js
diff --git a/pv/site_media/js/calendar/locale/nl-be.js b/steering/site_media/js/calendar/locale/nl-be.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/nl-be.js
rename to steering/site_media/js/calendar/locale/nl-be.js
diff --git a/pv/site_media/js/calendar/locale/nl.js b/steering/site_media/js/calendar/locale/nl.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/nl.js
rename to steering/site_media/js/calendar/locale/nl.js
diff --git a/pv/site_media/js/calendar/locale/nn.js b/steering/site_media/js/calendar/locale/nn.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/nn.js
rename to steering/site_media/js/calendar/locale/nn.js
diff --git a/pv/site_media/js/calendar/locale/pl.js b/steering/site_media/js/calendar/locale/pl.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/pl.js
rename to steering/site_media/js/calendar/locale/pl.js
diff --git a/pv/site_media/js/calendar/locale/pt-br.js b/steering/site_media/js/calendar/locale/pt-br.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/pt-br.js
rename to steering/site_media/js/calendar/locale/pt-br.js
diff --git a/pv/site_media/js/calendar/locale/pt.js b/steering/site_media/js/calendar/locale/pt.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/pt.js
rename to steering/site_media/js/calendar/locale/pt.js
diff --git a/pv/site_media/js/calendar/locale/ro.js b/steering/site_media/js/calendar/locale/ro.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ro.js
rename to steering/site_media/js/calendar/locale/ro.js
diff --git a/pv/site_media/js/calendar/locale/ru.js b/steering/site_media/js/calendar/locale/ru.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/ru.js
rename to steering/site_media/js/calendar/locale/ru.js
diff --git a/pv/site_media/js/calendar/locale/sk.js b/steering/site_media/js/calendar/locale/sk.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/sk.js
rename to steering/site_media/js/calendar/locale/sk.js
diff --git a/pv/site_media/js/calendar/locale/sl.js b/steering/site_media/js/calendar/locale/sl.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/sl.js
rename to steering/site_media/js/calendar/locale/sl.js
diff --git a/pv/site_media/js/calendar/locale/sr-cyrl.js b/steering/site_media/js/calendar/locale/sr-cyrl.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/sr-cyrl.js
rename to steering/site_media/js/calendar/locale/sr-cyrl.js
diff --git a/pv/site_media/js/calendar/locale/sr.js b/steering/site_media/js/calendar/locale/sr.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/sr.js
rename to steering/site_media/js/calendar/locale/sr.js
diff --git a/pv/site_media/js/calendar/locale/sv.js b/steering/site_media/js/calendar/locale/sv.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/sv.js
rename to steering/site_media/js/calendar/locale/sv.js
diff --git a/pv/site_media/js/calendar/locale/th.js b/steering/site_media/js/calendar/locale/th.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/th.js
rename to steering/site_media/js/calendar/locale/th.js
diff --git a/pv/site_media/js/calendar/locale/tr.js b/steering/site_media/js/calendar/locale/tr.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/tr.js
rename to steering/site_media/js/calendar/locale/tr.js
diff --git a/pv/site_media/js/calendar/locale/uk.js b/steering/site_media/js/calendar/locale/uk.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/uk.js
rename to steering/site_media/js/calendar/locale/uk.js
diff --git a/pv/site_media/js/calendar/locale/vi.js b/steering/site_media/js/calendar/locale/vi.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/vi.js
rename to steering/site_media/js/calendar/locale/vi.js
diff --git a/pv/site_media/js/calendar/locale/zh-cn.js b/steering/site_media/js/calendar/locale/zh-cn.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/zh-cn.js
rename to steering/site_media/js/calendar/locale/zh-cn.js
diff --git a/pv/site_media/js/calendar/locale/zh-tw.js b/steering/site_media/js/calendar/locale/zh-tw.js
similarity index 100%
rename from pv/site_media/js/calendar/locale/zh-tw.js
rename to steering/site_media/js/calendar/locale/zh-tw.js
diff --git a/pv/site_media/js/jquery/jquery.js b/steering/site_media/js/jquery/jquery.js
similarity index 100%
rename from pv/site_media/js/jquery/jquery.js
rename to steering/site_media/js/jquery/jquery.js
diff --git a/pv/site_media/js/jquery/ui/core.min.js b/steering/site_media/js/jquery/ui/core.min.js
similarity index 100%
rename from pv/site_media/js/jquery/ui/core.min.js
rename to steering/site_media/js/jquery/ui/core.min.js
diff --git a/pv/site_media/js/jquery/ui/draggable.min.js b/steering/site_media/js/jquery/ui/draggable.min.js
similarity index 100%
rename from pv/site_media/js/jquery/ui/draggable.min.js
rename to steering/site_media/js/jquery/ui/draggable.min.js
diff --git a/pv/site_media/js/jquery/ui/droppable.min.js b/steering/site_media/js/jquery/ui/droppable.min.js
similarity index 100%
rename from pv/site_media/js/jquery/ui/droppable.min.js
rename to steering/site_media/js/jquery/ui/droppable.min.js
diff --git a/pv/site_media/js/jquery/ui/mouse.min.js b/steering/site_media/js/jquery/ui/mouse.min.js
similarity index 100%
rename from pv/site_media/js/jquery/ui/mouse.min.js
rename to steering/site_media/js/jquery/ui/mouse.min.js
diff --git a/pv/site_media/js/jquery/ui/sortable.min.js b/steering/site_media/js/jquery/ui/sortable.min.js
similarity index 100%
rename from pv/site_media/js/jquery/ui/sortable.min.js
rename to steering/site_media/js/jquery/ui/sortable.min.js
diff --git a/pv/site_media/js/jquery/ui/widget.min.js b/steering/site_media/js/jquery/ui/widget.min.js
similarity index 100%
rename from pv/site_media/js/jquery/ui/widget.min.js
rename to steering/site_media/js/jquery/ui/widget.min.js
diff --git a/pv/site_media/js/note_change.js b/steering/site_media/js/note_change.js
similarity index 100%
rename from pv/site_media/js/note_change.js
rename to steering/site_media/js/note_change.js
diff --git a/pv/site_media/js/show_change.js b/steering/site_media/js/show_change.js
similarity index 100%
rename from pv/site_media/js/show_change.js
rename to steering/site_media/js/show_change.js
diff --git a/pv/urls.py b/steering/urls.py
similarity index 69%
rename from pv/urls.py
rename to steering/urls.py
index e0159f0812048341d20038b54c6993c4e1f31a96..a498c5ac925f83ab950bea6431f0c7c58c115389 100644
--- a/pv/urls.py
+++ b/steering/urls.py
@@ -1,4 +1,22 @@
-# -*- coding: utf-8 -*-
+#
+# steering, Programme/schedule management for AURA
+#
+# Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt
+# Copyright (C) 2017-2019, Ingo Leindecker
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
 
 from django.conf import settings
 from django.conf.urls import url, include
@@ -6,7 +24,9 @@ from django.contrib import admin
 from django.views.static import serve
 from rest_framework_nested import routers
 
-from program.views import APIUserViewSet, APIHostViewSet, APIShowViewSet, APIScheduleViewSet, APITimeSlotViewSet, APINoteViewSet, APICategoryViewSet, APITypeViewSet, APITopicViewSet, APIMusicFocusViewSet, APIFundingCategoryViewSet, APILanguageViewSet, json_day_schedule, json_playout, json_timeslots_specials
+from program.views import APIUserViewSet, APIHostViewSet, APIShowViewSet, APIScheduleViewSet, APITimeSlotViewSet, \
+    APINoteViewSet, APICategoryViewSet, APITypeViewSet, APITopicViewSet, APIMusicFocusViewSet, APIFundingCategoryViewSet, \
+    APILanguageViewSet, json_day_schedule, json_playout
 
 admin.autodiscover()
 
@@ -24,8 +44,7 @@ router.register(r'musicfocus', APIMusicFocusViewSet)
 router.register(r'fundingcategories', APIFundingCategoryViewSet)
 router.register(r'languages', APILanguageViewSet)
 
-
-'''Nested Routers'''
+# Nested Routers
 
 show_router = routers.NestedSimpleRouter(router, r'shows', lookup='show')
 
@@ -52,10 +71,9 @@ timeslot_router = routers.NestedSimpleRouter(schedule_router, r'timeslots', look
 # /shows/1/schedules/1/timeslots/1/note
 timeslot_router.register(r'note', APINoteViewSet, basename='timeslots-note')
 
-
 urlpatterns = [
     url(r'^openid/', include('oidc_provider.urls', namespace='oidc_provider')),
-    url(r'^api/v1/', include(router.urls) ),
+    url(r'^api/v1/', include(router.urls)),
     url(r'^api/v1/', include(show_router.urls)),
     url(r'^api/v1/', include(show_timeslot_router.urls)),
     url(r'^api/v1/', include(schedule_router.urls)),
@@ -65,10 +83,8 @@ urlpatterns = [
     url(r'^api/v1/program/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', json_day_schedule),
     url(r'^admin/', admin.site.urls),
     url(r'^program/', include('program.urls')),
-    url(r'^nop', include('nop.urls')), # Deprecated
     url(r'^api/', include('frapp.urls')),
-    #url(r'^tinymce/', include('tinymce.urls')),
-    url(r'^export/timeslots_specials.json$', json_timeslots_specials), # Deprecated
+    # url(r'^tinymce/', include('tinymce.urls')),
 ]
 
 if settings.DEBUG:
diff --git a/pv/wsgi.py b/steering/wsgi.py
similarity index 89%
rename from pv/wsgi.py
rename to steering/wsgi.py
index ccae5d481913485cbb4b07f4c2f1394bf129e1cf..7c83fe0c815e9c0dd96b815a90e35b328c2fe7fb 100644
--- a/pv/wsgi.py
+++ b/steering/wsgi.py
@@ -20,7 +20,7 @@ import sys
 
 sys.path.append('/srv/pv/pv')
 
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pv.settings")
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "steering.settings")
 
 # This application object is used by any WSGI server configured to use this
 # file. This includes Django's development server, if the WSGI_APPLICATION
@@ -30,4 +30,4 @@ application = get_wsgi_application()
 
 # Apply WSGI middleware here.
 # from helloworld.wsgi import HelloWorldApplication
-# application = HelloWorldApplication(application)
\ No newline at end of file
+# application = HelloWorldApplication(application)