User:Dan Nessett/Technical/Notes on Refactoring CZ: Difference between revisions

From Citizendium
Jump to navigation Jump to search
imported>Dan Nessett
No edit summary
 
(5 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{AccountNotLive}}
==Things to do for MW standard extension upgrade==
On Special:Version the line:
:<pre>MediaWiki 1.13.2 (modified) (r99)</pre>
has a link next to r99. This points to svn.wikimedia. It should point to svn.citizendium. This needs to be fixed.
==Where to get svn_load_dirs.pl and configure it==
==Where to get svn_load_dirs.pl and configure it==


Line 10: Line 19:


<pre>< my $svn = '/usr/bin/svn';</pre>
<pre>< my $svn = '/usr/bin/svn';</pre>
==Steps for upgrade==
===Pre-upgrade===
* merge LocalSettings on the live wiki with that on the test wiki and keep the results around for use during the upgrade process. ('''Done''')
* install php-xml on both locke and reid ('''Done''')
===Upgrade process===
* Switch en.citizendium.org so it points only to reid.
* On locke:
:* Change /etc/httpd/conf.d/en.citizendium.org to comment out /wiki Alias and add testing Alias
:* Change LocalSettings so $wgScript equals testing path
:* move mediawiki to mediawikibackup.
:* create a new mediawiki directory.
:* checkout CZ_Refactor_1_13_2_0 into the new mediawiki directory (this is the revision currently running on the test wiki).
:* soft link images and fix up the logo pointers.
:* test locke.citizendium.org using the test data in section below.
:* If the tests pass:
::* Change /etc/httpd/conf.d/en.citizendium.org to restore /wiki Alias
::* Change LocalSettings so $wgScript equals /wiki
::* switch en.citizendium.org to point to locke.
:* Wait 24 hours to see if any problems arise.
* During 24 hour wait period, perform same upgrade steps on reid that were applied to locke.
* If no problems arise during 24 test period, switch en.citizendium.org back into round-robin dns.
This process is flexible in the following ways:
* If problems arise, it is easy to switch back to the old code by simply renaming the new mediawiki directory to something else and mediawikibackup to mediawiki.
* If the new code somehow corrupts the db ('''extremely unlikely'''), we have the back up, which we can use to restore the wiki to its pre-upgrade state.


==MW standard extensions to check==
==MW standard extensions to check==
Line 170: Line 210:


<pre>SELECT column_name FROM information_schema.columns WHERE table_name ='table';</pre>
<pre>SELECT column_name FROM information_schema.columns WHERE table_name ='table';</pre>
==Selenium Framework for testing MW software==
===Installing the necessary software===
* Need to install PHPUnit. Use pear (comes installed with latest version of PHP)
<pre>sudo pear upgrade pear
sudo pear channel-discover pear.phpunit.de
sudo pear install phpunit/PHPUnit</pre>
Pear files are in (Ubuntu): /usr/share/php/PEAR
PHPUnit files are in (Ubuntu): /usr/share/php/PHPUnit
* Need to install Selenium
:* Selenium Remote Control (RC) is found at: http://seleniumhq.org/download/
:* Need java jvm installed (at least version 1.5)
:* Selenium RC only requires running selenium-server:
:* <pre>java -jar /path/to/selenium-server.jar</pre>
<br>
:* Selenium-IDE is also found at: http://seleniumhq.org/download/
:* It is a plugin for Firefox (only works on Firefox).
* Need to install Testing/Selenium:
<pre>sudo pear install Testing_Selenium</pre>
* You may need to specify a specific version. To find out the most recent verion:
<pre>pear remote-info Testing_Selenium</pre>
===Setting up RunSeleniumTests.php (for Ubuntu)===
* Edit RunSeleniumTests.php and uncomment the line:
<pre>set_include_path( get_include_path() . PATH_SEPARATOR . '/usr/share/php/PEAR' );</pre>
* Create the file: LocalSeleniumSettings.php and insert:
<pre>// Hostname of selenium server
$wgSeleniumTestsSeleniumHost = 'http://localhost';
// URL of the wiki to be tested.
$wgSeleniumTestsWikiUrl = 'http://localhost';
// Wiki login. Used by Selenium to log onto the wiki
$wgSeleniumTestsWikiUser      = '';
$wgSeleniumTestsWikiPassword  = '';
// Common browsers on Windows platform
// Use the *chrome handler in order to be able to test file uploads
$wgSeleniumTestsBrowsers['firefox']  = '*firefox c:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe';
$wgSeleniumTestsBrowsers['ff-chrome']  = '*chrome c:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe';
$wgSeleniumTestsBrowsers['iexplorer'] = '*iexploreproxy';
// Actually, use this browser
$wgSeleniumTestsUseBrowser = 'ff-chrome';</pre>
Edit this text and insert the name ($wgSeleniumTestsWikiUser) and password ($wgSeleniumTestsWikiPassword) of the wiki user under which the tests will run.
===Some useful URLs===
* Netbeans, Selenium and PHPUnit: <pre>http://netbeans.org/kb/docs/php/phpunit.html</pre>
===Selenium meeting notes 5/14/2010===
* The Selenium framework testing code in the latest trunk of MW (r66751 ) is designed to work with 1.13 and has been tested on 1.13 and 1.15.
* In order to allow tests to dynamically configure the wiki, create an extension that is called by a hook at the end of LocalSettings. This extension then sets any necessary global variables and returns.
* Each test needs to establish the db in a state suitable for testing. How this will be accomplished is yet undefined.
* Discussion of the Selenium Framework for MW will be conducted on Wikitech-l
* There exists RC scripts for the Selenium-Grid machines. These will be checked into the main trunk.
* Some relevant links from Ryan Lane:
:* http://grid.tesla.usability.wikimedia.org/console
:* http://grid.tesla.usability.wikimedia.org:4444
:* http://www.mediawiki.org/wiki/Selenium
:* http://www.mediawiki.org/wiki/SeleniumFramework


===An idea to improve test suite performance===
===An idea to improve test suite performance===

Latest revision as of 03:39, 22 November 2023


The account of this former contributor was not re-activated after the server upgrade of March 2022.


Things to do for MW standard extension upgrade

On Special:Version the line:

MediaWiki	1.13.2 (modified) (r99)

has a link next to r99. This points to svn.wikimedia. It should point to svn.citizendium. This needs to be fixed.

Where to get svn_load_dirs.pl and configure it

You can get svn_load_dirs.ph.in here: svn_load_dirs directory

Edit the file and (around line 26) change the following line:

< my $svn = '@SVN_BINDIR@/svn';

by replacing @SVN_BINDIR@/svn by the directory in which svn resides. For Ubuntu the line would like like:

< my $svn = '/usr/bin/svn';

Steps for upgrade

Pre-upgrade

  • merge LocalSettings on the live wiki with that on the test wiki and keep the results around for use during the upgrade process. (Done)
  • install php-xml on both locke and reid (Done)

Upgrade process

  • Switch en.citizendium.org so it points only to reid.
  • On locke:
  • Change /etc/httpd/conf.d/en.citizendium.org to comment out /wiki Alias and add testing Alias
  • Change LocalSettings so $wgScript equals testing path
  • move mediawiki to mediawikibackup.
  • create a new mediawiki directory.
  • checkout CZ_Refactor_1_13_2_0 into the new mediawiki directory (this is the revision currently running on the test wiki).
  • soft link images and fix up the logo pointers.
  • test locke.citizendium.org using the test data in section below.
  • If the tests pass:
  • Change /etc/httpd/conf.d/en.citizendium.org to restore /wiki Alias
  • Change LocalSettings so $wgScript equals /wiki
  • switch en.citizendium.org to point to locke.
  • Wait 24 hours to see if any problems arise.
  • During 24 hour wait period, perform same upgrade steps on reid that were applied to locke.
  • If no problems arise during 24 test period, switch en.citizendium.org back into round-robin dns.

This process is flexible in the following ways:

  • If problems arise, it is easy to switch back to the old code by simply renaming the new mediawiki directory to something else and mediawikibackup to mediawiki.
  • If the new code somehow corrupts the db (extremely unlikely), we have the back up, which we can use to restore the wiki to its pre-upgrade state.

MW standard extensions to check

Extension Name Notes Status
CategoryTree The default limit on entries displayed is 200.

This is controlled by $wgCategoryTreeMaxChildren

Works
CharInsert Works
CheckUser Requires db schema changes

First execute php CheckUser/install.php
After executing install.php, do full db backup
Make sure error_reporting = E_ALL & ~E_NOTICE
and display_errors = Off in php.ini

Make sure schema is set to mediawiki
in LocalSettings.

Works
Cite Works
ConfirmAccount Works
ConfirmEdit Need to move setting of $wgGroupPermissions['sysop']['skipcaptcha'] = false;

into LocalSettings.php, since the defaults of the MW standard
are not the same as the CZ modified version. Also need to set

$ceAllowConfirmedEmail = true;
$wgCaptchaTriggers['addurl'] = false;
$wgCaptchaTriggers['createaccount'] = true;
$wgCaptchaTriggers['badlogin'] = false;

While the FancyCaptcha module is loaded, it is not used, since
by default $wgCaptchaClass = 'SimpleCaptcha';
and LocalSettings doesn't override this default.

Works
EmbedVideo Works
ExpandTemplates The default size of the input box is 11 chars. Have to add

the following to Mediawiki:common.css:

body.page-Special_ExpandTemplates textarea {
  width: 100%;
  padding-top: 0.1em;
  padding-right: 0.1em;
  padding-bottom: 0.1em;
  padding-left: 0.1em;
}

Tested on:
Mac OS X (FF,Safari,Opera)
Linux (FF, Opera, IE6 [over Wine], Chrome)
Windows Vista (IE, FF, Opera, Chrome)

Works
ImageMap Must have php-xml module installed. ImageMap uses class DOMDocument

and that is supplied by the php-xml module. Don't forget to restart
the httpd after installing php-xml.

Works

Fixed problem with
this extension by

installing php-xml using
yum. This module is
required in order to

use the class
DOMDocument.

inputbox Works
Newuserlog This extension is obsolete and

replaced by core functionality starting in 1.14.
So, if we upgrade to a more recent MW version,
we shouldn't bring this extension along.

Works
ParserFunctions Works
Renameuser Works
Timeline Works
TreeAndMenu This extension replaces Treeview4 which

is obsolete. TreeAndMenu is backwards
compatible with Treeview4, so the replacement,
should not cause problems.
(There are only 3 pages which reference
this extension and I have tested all of them.

Works
wikihiero Works

Refactoring issues

  • It appears many pages (including the Request Account page) has constables@citizendium.org hardwired in. There is no magic word available to access the $wgPasswordSender global variable or any other email address. This is something that the Citizendium extension should add (i.e., a magic word for the site's configured complaint email address).
  • It also appears that many Mediawiki namespace pages have http://en.citizendium.org hardwired. These should be changed to: {{SERVER}}{{SCRIPTPATH}}
  • For some reason Special:Popularpages doesn't work in the MW version, nor does it appear in the SpecialPages list.
Solved. Had $wgDisableCounters=true in LocalSettings. Changed it to false.
  • Conversely, Special:ExpandTemplates doesn't work in the CZ version, nor does it appear in the SpecialPages list.
Actually, it does work. However, it doesn't show up in the Special:SpecialPages list
Actually, it does show up in the Special:SpecialPages list. However, it is under "Other special pages", rather than "Wiki data and tools".

Test harness notes

Useful SQL commands

To display a list of all tables in a schema use:

MySQL

SHOW TABLES;

Postgresql

SELECT table_name FROM information_schema.tables WHERE table_schema = 'mediawiki';

To display a list of all databases use:

MySQL

SHOW DATABASES;

Postgresql

SELECT datname FROM pg_database;

To display a list of all columns in a table use:

MySQL

SHOW COLUMNS

Postgresql

SELECT column_name FROM information_schema.columns WHERE table_name ='table';

An idea to improve test suite performance

Dropping tables and repopulating them or dropping the database and recreating it is a pretty expensive operation. Doing so could significantly slow down the time it takes to run a test suite. Here is another option. I am not a db expert, so this idea may make no sense at all, but for the record:

  • Before the test suite runs, setup starts a transaction with an SQL BEGIN statement.
  • Setup notes the value of $wgDBtype and copies that value to $wgDBActualtype. It then changes $wgDBtype to point to a new class that implements the logic described here.
  • When the methods of the new class (which extends class Database) are called, most simply forward the call to methods in the class specified by $wgDBActualtype.
  • However, when doQuery() is called, the new class methods check to see if the operation is either a BEGIN or a COMMIT. If so, it is not executed (so all of the test suite traffic belongs to a single transaction).
  • All reads to the database are then dirty reads, so they return non-committed data.
  • When the test suite completes, a tear down facility CANCELs the transaction.

Here are some pros and cons of this scheme:

Pros

  • Each time a test runs the database (or a set of tables) need not be dropped and repopulated. This should significantly speedup the execution of a test suite.
  • With this facility tests could be run against a real database, which would relieve the test designer from creating a test database configuration for each test/test suite.
  • This approach allows fuzz testing of random data, since a test suite could run against a real database, not just a database architected specifically for the purpose of testing.

Cons

  • Introducing the intervening Database class changes the software under test. This would lessen the confidence that the test suite verifies that software.
  • It isn't clear this strategy will actually work. Since all tests run under the same transaction, the transaction sequence could get quite long and it may be the case that some DB software will croak.
  • There may be other changes to the db state that occur outside the auspices of the BEGIN/COMMIT transaction scope. This requires investigation.
  • It isn't clear that all supported database allow dirty reads inside of transaction blocks. This is another issue that requires investigation.

After some thought, I think the best way to approach this problem is create a small CZ db that has only the minimum data necessary for defining a test. A test designer would then copy this db and modify the resulting wiki with data necessary for the test to run. The modified db could then be dumped using pg_dump and put in a standard or configurable location. When the test is run, the test (or a context manager) drops the existing wiki db, recreates it and uses psql to load the test db into the wiki db. The test is then run.

If it is useful to run tests in parallel, this approach requires some modification. In particular, each test needs to run off a unique db. So, you can't use the standard wiki db name. Each test would have to define a db name. It would then call psql to drop any existing version of this db, recreate it and use psql to load the test db into this newly created db. The test would than have to change $wgDBname to equal the test db name. Since LocalSettings defines $wgDBname, the extension approach specified in the Selenium Framework notes of 5/15/2010 where a test extension is called at the end of LocalSettings must be used to override $wgDBname (and perhaps $wgDBuser and $wgDBpassword ).

Testing data for MW standard extensions

Data for CategoryTree Special Page

Biology_tag
Engineering tag
Health Sciences tag
Sports tag

References to EmbedVideo

References to CharInsert

References to <ref>

References to ImageMap

References to InputBox

References to ParserFunctions

#exp

#if

#ifeq

#iferror

No References.

#ifexpr

#ifexist

#rel2abs

No References.

#switch

#time

#timel

No References.

#titleparts

No References.

References to Timeline

References to TreeAndMenu

{{#tree}}

{{#menu}}

{{#menu:

  • Root1
    • Sub-item
    • Another sub-item
  • Root2
    • Sub-item
    • Another sub-item

}}

References to Wikihiero

<hiero> D:d-=i-=n -Sms-w-A1 -i-q:r:Y1 -w-DA-A-Y1 -! -ib*Z1:=V31A -HAt:a-A1 -m-a:V31A -pH:D54-=n:=n:=Z2 -! -Xn:n-nw-w-pr -Ssp:p-a -x:r-p*W:xt -! -H-A25-A24 -mn:n-i-t-P11-xt -HAt:t*t-W -r:a:t -! -Hr:Z1 -tA:Z1*N23 -r:a -H-V31A:n-nw:W-A2 -nTr -dwA-! -A30-A2 -z:A1*Z1 -nb -Hr:Z1 -H-p:t-D32:a -sn-n:nw-w-A1-=y:=f -! -iz-w:t-A1-Z2-=t:=n:=Z2 -ii-i-t:D54 -aD:d-t:Y1 -D35:n -! -n:h-w-wr:=n -mSa-A1:Z2-=n:=Z2 -pH:D54-=n:=n:=Z2 -! -pH-w-y -wA-wA-t:xAst -z:n-X5:D54-=n:=n:=Z2 -! -z:n-mwt-t:xAst -m-a:V31A -r:f -n:Z2 -ii-i-D54-=n:=Z2 -! -m -Htp:t-p:Y1 -tA:N23*Z1-=n:=Z2 -pH:D54-=n:=Z2 -sw-W -! -sDm-m -r:V31A -n:=A1 -HAt:a-A1 -nw:V31A-A1 -Sw-W:wr -! -HA-A-w-Y1:Z2 -i-a:mw -a:t*W -i-im-m-a -! -mw -Hr:Z1 -D50-Z2:=V31A -i-x:Y1 -w-S-b-A2-=V31A -! -w-Sd:d:t-A2-=V31A -md-d-w-A2:=V31A -n -! -sw-t:n-G7 -ib*Z1:=V31A -m-a:=V31A -w-S-! -b-A2-=V31A -D35:n -n -i-t-i-t-A2 -i-w -r:Z1 :n -z:A1*Z1 -! -n:N42-m-a:=f -sw-w -i-w -md-d-w-! -A2-=f -a:=f -TA-A-m-S28 -n:=f -Hr:Z1 -! -ir:r-=V31A -m -x:r-t:Y1:Z2 -ib*Z1:=V31A -s-wr-! -r:d-G37 -p:W -D:d -n:=V31A -s-D:d-=A1 -r:f -! -n:=V31A -mi-i-t*t:Y1 -i-r:y -xpr:r -m-a-=A1 -! -D:z-=A1 -..-Sm-m-D54:=V31A-=w-=A1 -r -b-i-! -id:Hw-xAst -n -sAq:sAq-G7 -h-A-! -D54:=V31A-=w-=A1 -r -M14-wr:r-S -m -d:p*t-P1 -! -n:t -mH:a -V1-mD:mD -m -Aw-W-=s -mH:a -mD:mD-mD:mD -m -s-x-! -w-iab-=s -s-qd-d-A30-A1 -V1-V20:V20 -i-m-=s -! -m -stp:Y1 -n -km-m-t:niwt -mA:ir-A-=s-=n:=Z2 -! -p*t:pt -mA:ir-A-=s-=n:=Z2 -tA:N23*Z1 -m-a:V31A-A-a -! -ib:Z1-=s-=n:=Z2 -r -mA:ir-A-w-F27:Z2 -z:r-! -E27-A2-=s-=n:=3 -D:a-TAw -D35 -ii-i-t:D54 -n:S-! -n:y-E20-A24 -D35 -xpr:r-t:=f -D:a-TAw -pr:r-D54 -! -i-w-=n:=3 -m -M14-wr:r-S -tp:Z1 -a:Z1 -! -sAH-Y1-=n:=3 -tA:N23*Z1 -f-A-t-A9-a -TAw-w -! -ir:=f -wHm-m-i-i-t-A2 -n:U19-nw-W-i-i-t-mw -! -i-m-=f -n:t -mH:a -Z1:Z1-Z1:Z1-Z1:Z1-Z1:Z1 -i-n -xt:t*Z1 -H-H-! -A25-A24 -n-=A1 -s -aHa-a:=n -d:p*t-P1 -! -m-t:Z6 -n:t-tyw-Z2 -i-m-=s -D35 -z:p-zp -! -wa:a-A1-Z1 -i-m -aHa-a:=n-=A1 -r:a-=V31A-=w-=A1 -! -r -iw:N23*Z1 -i-n -wA-A-w-mw -n -M14-! -wr:r-S -ir:=n-=A1 -h:r-w-ra -Z1-Z1-Z1 -wa:a-Z1-wr-=k\:=W-=A1 -! -ib:Z1-=A1 -m -sn-n:nw-w-A1-Z1-Z1-=A1 -z:Dr:r-A55-=V31A-! -=w-=A1 -m -Xn:n-nw*W:pr -n -V31A-A-p-! -Aa19-pr -n -xt:t*Z1 -q:n-i-D32:a-=n-=A1 -Sw-W-! -i-i-t:ra -aHa-a:=n -d-wn:n-D54-=n-=A1 -r:d-! -D56-D56-=A1 -r -r:x-Y1 -a:t-=A1 -m -r:Z1-=A1 -! -gm-m-=n-=A1 -d-A-b-M43-N33:Z2 -i-A-! -r:r-t:D5-N33:Z2 -i-m -i-A-q:t-Hn-Z3A -nb:t -Sps-s-t:Y1 -! -V31A-A-w-N33:Z2 -i-m -H-n:a -n:q-w-t-N33:Z2 -! -Ssp-p:t-N33:Z2 -mi-i-ir:t-=s -r-m-W-K5:Z2 -! -i-m -H-n:a -A-p:d-w-zA:Z2 -D35:n -n:t*t -! -D35:n -s-t -m -Xn:n-nw-w-pr:=f -aHa-a:=n -! -s-s-Aa18-A-A2-=n -w-A1 -r:a-=n-=A1 -r -tA:N23*Z1 -! -n -wr:r -Hr:Z1 -a:Z1-w-y-=A1 -! -Sd:d-t:a-=A1 -DA-A-Z9:xt -s-xpr-r:=n-=A1 -x:t-Q7 -ir:=n-=A1 -! -zb:wr -n :Z9*t-Q7 -n -nTr-Z1:Z2 -aHa-a:=n -F21-m-=n:=A1 -! -x:r-P8-E23-w-A2 -q:r-i-E21-A24 -i-b-! -E8-=V31A-=w-=A1 -wA-A-w-mw -p:W -! -n -M14-wr-r:N36 -xt:t*Z1:Z2 -Hr-Z1 -gm-m-gm-m-Z9 -! -tA:N23*Z1 -Hr-Z1 -mn:n-mn:n-D54 -V31A:f-S28-=n:=A1 -! -Hr-Z1-=A1 -gm-m-=n-=A1 -H-f-A-w-I15 -! -p-w -i-w-=f :m-ii-i-t:D54 -n:ns-sw-W -! -V22:a -V20*V20:V20 -x-b-z:w-t:Sny-=f -wr:r-=s -! -r :mH-a :Z1*Z1 -H-a:F51-Z2:=f -z:x:r-w-T11-A24 -! -m -nbw:N33:Z2 -i-K1:n-D13:y-=f:=y -m -x-s-b-d:N33:Z2 -! -mA:Aa11:a-H2:Y1 -a:r:q-V12:Y1 -sw-w -r -xnt-n:t -! -$r-i-w -wp:p-Z9:=n:=f -$b-r*Z1:=f -r:=A1 -i-W:=A1 -! -Hr-Z1 -X:t*Z1-=A1 -m-b-bA-A-H-D53:Y1-=f -! -D:d-=f :n-=A1 -n-m:a -ini-n :t*w -zp :Z1*Z1 -n:D-z:wr-A1 -! -n-m:a -ini-n :t*w -i-r -w-d:f-gb-D54-! -=V31A :m-D:d -n:=A1 -ini-n :t*w -r -iw:N23*Z1 -p:n -! -r:a-=A1 -r:x-Y1:=V31A -t-w -i-w-=V31A :m -z:z-Q7 -! -xpr-r-t -m -n:t*y :D35 -mA:ir-A-t :f -i-W -md:d-! -w-A2-=V31A -n:=A1 -D35:n -w-A1 -Hr-Z1 -F21-m-=A1 -! -s-t -i-w-=A1 -m -b-bA-A-H-D53-Y1:=V31A -! -x:m-D35:=n -w-A1 -aHa-a:=n -r:a-=f -w-A1 -m-r*Z1:=f -! -iTi:t-A24-=f -w-A1 -r -st-t*pr:=f -! -n:t -s-nDm-m-Xrd -wA-A-H-wAH-! -A24-=f -w-A1 -D35:n -d-mi-i-t:a-=A1 -w-DA-! -A-Y1:=V31A-=w-=A1 -D35:n -iTi:t*t-A24 -i-m-=A1 -! -$r-i-w -wp:p-Z9:=n:=f -$b-r*Z1:=f -r-=A1 -i-w-=A1 -! -Hr-Z1 -X:t*Z1-=A1 -m -b-bA-A-H-D53:Y1-=f -! -aHa-a:n -D:d-=n:=f -n:=A1 -n-m:a -ini-n :t*W -zp -Z1*Z1 -! -n:D:z-wr-A1 -n-m:a -ini-n :t*w -r -iw:N23*Z1 -p:n -! -n -M14-wr:r-N36 -n:t*y -Aa13:Z1-=f:=y -m -n:U19-nw-W-! -i-i-mw -aHa-a:=n -w-S-b-Z9-A2-=n:=A1 -! -n:=f -s-t -a:Z1-w-y-i-i-=A1 -x-xA-A-m-D41 -! -m -b-bA-A-H-D53:Y1-=f -D:d-=A1 -n:=f -! -nw:V31A-A1 -p-w -h-A-D54-=V31A-=w-=A1 -! -r -b-i-N41:F18-N25 -m -wp:p-w-t:D54 -! -sAq:sAq-G7 -m-d:p*t-P1 -n:t -! -mH:a -V1-mD:mD -m -Aw-W-=s -mH:a -mD:mD-mD:mD -m -s-x:w-! -iab:Y1-=s -s-qd-d-A30-A1 -V1-V20:V20 -i-m-=s -! -m -s-t:p-w-U21:Y1 -n :km-m-t:niwt -! -mA:ir-A-=s-=n:=Z2 -p:t-pt -mA:ir-A-=s-=n:=Z2 -tA:N23*Z1 -! -m-a:V31A-A-A24 -ib-Z1-=s-=n:=Z2 -r -mA:ir-A-! -w-F27-Z2 -$r-z:r-E27-A2-=s-=n:=Z2 -$b-D:a:TAw -! -D35 -ii-i-t:D54-=f-n:S-n:y-E21 -D35 -xpr-r*t:=f -! -wa:W:a-A1-Z1 -i-m -nb -m-a:V31A-A-A24 -ib*Z1:=f -! -n:xt:x*t-A24 -a:Z1-=f :r -sn-n:nw-w-A1*Z1*Z1:=f -D35:n -! -w-x-xA-wr:A1 -m -Hr:r -ib-=s-=n:=Z2 -D:a-TAw -! -pr-r:D54 -i-w-=n:=Z2 -m -M14-wr-r:N36 -! -tp-Z1 -a-Z1 -D61-D54-=n:=3 -tA:N23*Z1 -f-A-t-A9-a -! -TAw-w -ir:=f -wHm-m-i-i-t-A2 -n:U19-nw-w-i-i-t-mw -! -i-m-=f -n:t -mH:a -Z1:Z1-Z1:Z1-Z1:Z1-Z1:Z1 -i-n -xt:t*Z1 -H-H-A19-a -! -n:=A1 -s -aHa-a:=n -d:p*t-P1 -m-t:Z6:=t -! -n:t-tyw-Z2 -i-m-=s -D35 :z-p:zp -wa:W:a-A1-Z1 -i-m -! -Hr-Z1 -x-x-x-=A1 -m-a:V31A -w-=A1 -r -gs*Z1:=V31A -! -$r-aHa-a:n -ini-n:=V31A-=w-=A1 -$b-r -iw:N23*Z1 -p:n -i-n -! -wA-A-w-mw-Z1 :n -M14-wr:r-N36 -! -D:d-=i-=n-=f :n-=A1 -m -G54-A2 -m -zp -Z1*Z1 -! -n:D-z:wr-A1 -m -A-t-w-A24 -Hr*Z1:=V31A -! -p-H-F22-=n:=V31A -w-A1 -m-a:V31A -nTr*Z1 -r:a-=n:=f -! -anx-n:x-=V31A -ini-n:=f -t-w -r -iw:N23*Z1 -p:n -n :D28*Z1 -! -D35:n -n:t:t -D35:n -s-t -m -Xn:n-nw-w-pr:=f -! -i-w-=f -mH:Y1 -Xr:r -nfr-f:r-t-Y1:Z2 -nb:t -! -m-a:V31A -t-w -r -ir:t -N11:N14-d:ra*Z1 -Hr-Z1 -! -N11:N14-d:ra*Z1 -r :km-m-t:Y1-=V31A -N11:N14-d:ra *Z1*Z1*Z1*Z1 -! -m -Xn:n-nw-w-pr :n -iw:N23*Z1 -p:n -i-w -! -d:p*t-P1 -r -ii-i-t:D54 -m -Xn:n-nw-w-pr -! -s-qd-d-w-A30-A1:Z2 -i-m-=s -r:x-Y1 :n-=V31A -! -++TXTEGsqdw im=s rx=w n=k +s -Sm-m-D54:=V31A -H-n:a-=s-=n:=Z2 -r -Xn:n-nw-w-pr -! -m-t:Z6-=V31A -m -niwt:t*Z1-=V31A -! -$r-r:S-D20-A2-w-y -$b-s-D:d-A2 -d:p*t-ns-A2-=n:=f -z:n-X5:D54 -x:t-Y1:Z2 -U23-m:r-wr -! -s-D:d-A2-=A1 -r:f -n:=V31A -mi-i-t:t-Y1 -i-r:y -xpr-r-w-m-iw-N23*Z1 -p:n -! -wn:n-=A1 -i-m-=f -H-n:a -sn-n:nw-w-A1*B1:Z2-=A1 -X:r-d-w-A17-A1*B1:Z2 -! -m -q-A-b-F46-=s-=n:=Z2 -km-m-Y1:n-=n:=Z2 -H-f-A-W-I15 -V20*V20*V20*V20:.*V20*V20*V20*.-Z1*Z1*Z1*Z1:.*Z1*Z1*Z1 *.-m -! -ms-s-w-A1*B1:Z2-=A1 -H-n:a -sn-n:nw-w-A1*B1:Z2-=A1 -D35:n -s-x-M12-A2-=A1 -n:=V31A -! -zA-t:B1 -V31A:t*t-wr:B1 -ini-n:t-=n:=A1 -m -z:M8-A-F5-Y1 -$r-aHa-a:n -s-b-A-N14-ra -$b-! -h-A-W-D54 -pr:r-D54:=n -n:A -m -x:t-Q7 -m-a:=f -xpr-r:=n -r-=s -D35:n -w-A1 -H-n:a -! -A-m-Q7-=n:=y -D35:n -w-A1 -m -Hr:r -ib-=s-=n:=Z2 -aHa-a:=n-=A1 -m-t:Z6-=V31A-=W-=A1 -n-=s-=n:=Z2 -gm-m-=n:=A1 -! -s-t -m -XA-A-i-i-t-Aa2:Z2 -wa:W-a:t*Z1 -i-r -q:n-A24-=n:=V31A -T12-A24 -ib-Z1-=V31A -! -mH:Y1-=V31A -q:n-i-D32-=V31A -m-A17-A1*B1:Z2-=V31A -s-n-D20-A2-=V31A -! -N41:t-B1-V31A -mA:ir-A-=V31A -pr-Z1-=V31A -nfr-f:r -s-t -r -x:t-Y1:Z2 -nb:t -! -p-H-pH-D54:=V31A -Xn:n-nw-w-pr -wn:n-=V31A -i-m-=f -! -m -q-A-b-F46:D54 -n -sn-n:nw-w-A1*B1:Z2-=V31A -wn:n-=V31A -r:f -! -d-mA-A-U32-Y1-=V31A-=W-=A1 -Hr-Z1 -X:t*Z1-=A1 -d-mi-i-D41:=n-=A1 -! -z:zA-A-t-w-N23:Z2 -m -b-bA-A-H-D53:Y1-=f -$r-D:d-=A1 -r:f -n:=V31A -$b-! -s-D:d-A2-=A1 -G30-Y1:Z2-=V31A :n -sAq-sAq-G7 -a:=A1 -z:S-A-Y1:=f -! -m -aA:a-A-Y1:=V31A -a:=A1 -ini-n:=t -n:=V31A -i-b-E8-i-Hnqt -H-V31A:n-nw:W-N33:Z2 -! -D54-w-d:n-b-N33:Z2 -X:z-A-i-i-t-N33:Z2 -sn-n:t-r-tr-N33:Z2 -n -Aa13*Z1:Z2 -pr:Z2 -! -s-Htp:t-p-w-Y1 -nTr-Z1 -nb -i-m-=f -s-D:d-=A1 -r:f -xpr-r:t-Y1:Z2 -! -Hr-Z1-=A1 -m -mA:ir-A-t:Z2:=n-=A1 -m -G30-Y1:=f -nTr-dwA-A-A30-=t-=w -n:=V31A -! -m -niwt:t*Z1 -x*t:f -Hr-Z1 -q:n-b-t-O38-A1:Z2 -tA:N23*Z1 -r -M36:r-=f -$r-z:f-t:T30-A24-=A1 -$b-! -n:=V31A -D52-E1-Z1:Z2 -m -zb-wr :n -Z9-t-Q7 -w-S:n-H1:a-n:=A1 -n:=V31A -! -A-p-d-w-zA:Z2 -a:=A1 -ini-n:=t -n:=V31A -H-a-w-P1:Z2 -A-t:p-w-A2-A24 -! -Xr:r -Sps-s-s-Y1:Z2 -nb :n -km-m-t-niwt:t*Z1 -mi-i -ir:r-t -n -nTr-Z1 -mr:r-r-A2 -! -r:T-A1*B1:Z2 -m -tA:N23*Z1 -wA-A-N31 -D35 -r:x-Y1 -sw-W -r-T-A1-B1-Z2 -! -$r-aHa-a:=n -s-b-t:F18-A2-=n:=f -i-m-=A1 -m -M22-M22 -D:d-=n:=A1 -$b-m-n:f-wr -m -ib-Z1-f -! -D:d-=f :n-=A1 -D35 -wr-r -n:=V31A -a:n-G4-W23:Z2 -xpr-r:t-nb-nTr-sn-n:t:r-M6-N33:Z2-! -nw:V31A-A1 -i-s -HqA-q-A-G7 -p-wn:n-t:N25 -a:n-G4-W23:Z2 -n:=A1 -i-m -sw-W -! -H-V31A:n-nw-W-N33:Z2 -p:f -D:d-=n:=V31A -ini-n:t:=f -b-w -p-W -wr-r :n -iw:N23*Z1 -p:n -! -xpr-r -i-s -E9-w-d:D54 -V31A -t-w -r -st-t:pr -t:n -D35 :z-p:zp -! -mA:ir-A-=V31A -iw:N23*Z1 -p:n -xpr-r -m -n:U19-nw:W-i-i-mw -$r-aHa-a:=n -d:p*t-P1 -t:f -$b-! -ii-i-t:D54 -mi-i -z:r*t-E27-A2-=n:=f -xnt-n:t -aHa-a:=n-=A1 -Sm-m-D54-=V31A-=W-=A1 -! -r:a-n :w-=A1 -Hr-Z1 -xt:t*Z1 -q-A-A28 -S32-A2-n :=A1 -n:t-G4-A1:Z2 -m-Xn-n:nw-W-pr-=s -! -aHa-a:=n -Sm-m-D54-=V31A-=w-=A1 -r -s-mi-i-t-A2 -s-t -gm-m-=n:=A1 -sw-W -r:x-Y1 -s-t -! -aHa-a:=n -D:d-=n:=f -n:=A1 -s-n:b-=t -zp :Z1*Z1 -n:D-z:wr-A1 -r-pr-Z1 -=V31A -mA:ir-A-=V31A -! -X:r-d-Xrd-A1*B1:Z2-=V31A -i-Aa13-m:a -r:n-=A1 -nfr-f:r -m -niwt:t*Z1-=V31A -m-a:V31A-Xr:r*t-Y1:Z2-=A1 -! -p-W -i-m-=V31A -! -aHa-a:=n -r:a-=n :w-A1 -Hr-Z1 -X:t*Z1-=A1 -a:Z1-w-y-=A1 -xA-A-m-A24 -m -b-bA-A-H-D53-Y1:=f -! -aHa-a:=n -r:a-=n:=f -n:=A1 -zb-b-t-Y1:Z2 -m -a:n-G4-W23:Z2 -H-V31A-n:nw*W-N33:Z2 -D54-w-d:n-b-N33:Z2 -! -X:z-Aa17-A-i-i-t-N33:Z2-U33 -Sps-s-N33:Z2 -SA-A-a:z-O47 -F31-s-d-m-t-N33:Z2 -s-d-w-M41:3 -! -nw-Z1 -m:a-m:a-F27 -U7:r-r-i-i-t-iw:Z2 -aA:a-A-t-Y1 -n:t -nTr-sn-n:t:r-M6-N33:Z2 -n:D-H-i-i-t-F18:Z2 -! -n:t -Ab-b-w-T19 -T:z-m-W-E14:Z2 -g-w-f-E33-Z3A -V31A-i-i-w-E32-Z3A -A50-s-s-Y1:Z2 -nb -nfr-f:r -! -$r-aHa-a:=n -A-t-p-A9-a:=n-=A1 -s-t -$b-r -d-p-t-P1 -t:n -xpr-r:n-r:a-=t-=w-=A1 -Hr-Z1 -X:t*Z1-=A1 -! -r -nTr-dwA-A-A30 -n:=f -aHa-a:=n -D:d-=n:=f -n:=A1 -m-a:V31A -t:W -r -spr:r-D54 -r-Xn-n:nw-W-pr -! -n :Abd-d:ra -Z1-Z1 -mH:Y1-=V31A -q:n-i-D32-=V31A -m -X:r-d-w-Xrd-A1*B1:Z2-=V31A -r-n:p-i-i-rnp-=V31A -! -m -Xn-n:nw-W-pr -q:r-s-t-Q6:a-=V31A -aHa-a:=n -h-A-D54-=V31A-=w-=A1 -r -mr:r-i-i-t-N23-Z1 -! -m -h-A-w-Y1:Z2 -d:p*t-P1 -t:n -aHa-a:=n-=A1 -Hr-Z1 -i-A-S-A2 -n -mSa-A1:Z2 -! -n:t*y -m -d:p*t-P1 -t:n -r:a-=n:=A1 -H-V31A:n-nw:W-A2 -Hr-Z1 -mr:r-i-i-t-N23-Z1 -n :nb-G7 -n -iw:N23*Z1 -p:n -! -n:t-G4-A1:Z2 -i-m-=s -r -mi-i-t:t-Y1 -i-r:y -$r-n:a-t-P1 -p:W -ir:=n-=n:=Z2 -$b-m -x-d-P1 -! -r -Xn-n:nw-w-pr :n -sAq-sAq-G7 -spr:r-D54-=n:=n-=Z2 :r-Xn-n:nw-W-pr -! -Hr-Z1 -Abd:dwA-d:ra -Z1-Z1 -mi-i -D:d-t:=n:=f -nb:t -aHa-a:=n -aq-q-D54-=V31A-=w-=A1 -Hr-Z1 -sAq-sAq-G7 -! -m:a-zb-D54-=n:=A1 -n:=f -ini-nw:Z2 -p:n -ini-n:=n-=A1 -m -Xn-n:nw-W-pr -n -iw:N23*Z1 -p:n -! -aHa-a:n -nTr-dwA-A-A30-=n:=f -n:=A1 -x*t:f -Hr-Z1 -q:n-b-t-O38-A1:Z2 -tA:N23*Z1 -r -Dr:r-=f -! -aHa-a:=n -r:a-=V31A-=w-A1 -r -Sms-W-A1 -! -s-Aa18-A-H-sAH-Y1:=V31A-=w-=A1 -m -! -tp-A1*B1:Z2-=f -mA:ir-A -w-A1 -r -! -Aa18-#b-Z1 -#e-s-Aa18-A-H-sAH:Y1-=A1 -tA:N23*Z1 -r -Aa18-Z1 -! -mA:ir-A-=A1 -d:p-t:F20-A2-=n:=A1 -sDm-m -r:=V31A -! -#b-n -r:Z1-#e-=A1 -m-a:V31A -nfr-f:r -sDm-m -n -r:T-A1*B1:Z2 -! -aHa-a:=n -D:d-=n:=f -n:=A1 -m -ir -i-q:r-Y1-A1 -! -x:n-T34-m-s-A21-A1 -i-n -m -r:a:t -mw -! -#b-n -A-#e-p:d-zA -HD-D:ra -tA:N23*Z1 -n:z:f-t-! -T31:a-=f -dwA-A-ra -! -D54-w-=f :p*W -HAt:t*Z1-=f -! -r-pH-=f:=y -mi-i -gm-m-i-i-t -m-zS-Y1 -! -#b-m -zS-Y1 -#e-zS-A1 -i-q:r:Y1 -n -Dba-Dba-Dba-=f -! -i-#b-mn:n-#e-i-i -zA -i-mn:n-aA:a-A-Y1-A1 -anx-DA-s -! -D36-Aa16-Z4-X1 -! </hiero>