diff options
Diffstat (limited to 'doc')
38 files changed, 12969 insertions, 0 deletions
diff --git a/doc/.htaccess b/doc/.htaccess new file mode 100644 index 0000000..efe66e1 --- /dev/null +++ b/doc/.htaccess @@ -0,0 +1,4 @@ +AuthType Basic +AuthName "Hidra: Acesso restrito, senha requerida." +AuthUserFile /var/sites/hidra/site/.htpasswd +#Require valid-user diff --git a/doc/.htpasswd b/doc/.htpasswd new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/doc/.htpasswd diff --git a/doc/hidra-detalhe.jpg b/doc/hidra-detalhe.jpg Binary files differnew file mode 100644 index 0000000..03a0461 --- /dev/null +++ b/doc/hidra-detalhe.jpg diff --git a/doc/hidra-logo.png b/doc/hidra-logo.png Binary files differnew file mode 100644 index 0000000..a131950 --- /dev/null +++ b/doc/hidra-logo.png diff --git a/doc/hidra-oil.png b/doc/hidra-oil.png Binary files differnew file mode 100644 index 0000000..8a378e5 --- /dev/null +++ b/doc/hidra-oil.png diff --git a/doc/hidra-trace.jpg.png b/doc/hidra-trace.jpg.png Binary files differnew file mode 100644 index 0000000..02c1f95 --- /dev/null +++ b/doc/hidra-trace.jpg.png diff --git a/doc/hidra.css b/doc/hidra.css new file mode 100644 index 0000000..50b6c1e --- /dev/null +++ b/doc/hidra.css @@ -0,0 +1,113 @@ +@import url(s6/projection.css); /* required to make the slide show run at all */
+
+body { font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; }
+
+a:link, a:visited { color: black; }
+
+.slide h1 { font-size: 30pt; }
+
+.slide h1 { text-align: center; }
+
+.slide h1.fullscreen { position: absolute;
+ top: 40%;
+ width: 100%; }
+
+/* lets you create slides with no heading (because heading is hidden but gets included in toc) */
+.slide h1.hidden { display: none; }
+
+
+.slide h2 { font-size: 28pt; }
+
+h3 { font-size: 25pt; }
+
+/* todo: add special formating for .cover slide
+ lets you use h1(cover). for title/cover slide (a la S5 slide0) but more generic (not bound to 1st slide)
+*/
+
+.cover h1 { /* tbd */ }
+.cover h2 { /* tbd */ }
+
+/* todo: add special formating for h1, h2 in footer */
+
+#footer h1 { /* tbd */ }
+#footer h2 { /* tbd */ }
+
+
+p, li, dt, dd, td, th { font-size: 18pt; }
+
+ul { list-style-type: square; }
+
+/**********************************/
+/* general text-alignment classes */
+
+.left { text-align: left; }
+.center { text-align: center; }
+.right { text-align: right; }
+
+/**********************************/
+/* general font-size classes */
+
+.small { font-size: 97%; }
+
+.x-small,
+.smaller { font-size: 88%; }
+
+.xx-small,
+.smallest,
+.tiny { font-size: 82%; }
+
+
+
+pre { font-size: 16pt; }
+
+.code {
+ background-color: azure;
+ padding: 5px;
+ }
+
+.footnote a:first-of-type { text-decoration: none; }
+
+
+p.small { font-size: 97%; }
+
+p.x-small,
+p.smaller,
+p.footnote { font-size: 88%; }
+
+p.xx-small,
+p.smallest,
+p.tiny { font-size: 82%; }
+
+
+.help p,
+.help td { font-size: 88%; }
+
+
+.step { color: silver; }
+/* or hide next steps e.g. .step { visibility: hidden; } */
+.stepcurrent { color: black; }
+
+
+ +body { + font-family: monospace; +} + +.centered img { + display: block; + margin-left: auto; + margin-right: auto; +} + +.centered { + text-align: center; +} + +p, li, dt, dd, td, th { + font-size: 16pt; +} + +.slide h1 { + font-size: 25pt; +} + diff --git a/doc/hidra.html b/doc/hidra.html new file mode 100644 index 0000000..e2b81e0 --- /dev/null +++ b/doc/hidra.html @@ -0,0 +1,954 @@ +<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
+ <title>O Processo Hidra</title>
+
+<meta name="generator" content="S9">
+<meta name="author" content="Silvio Rhatto" >
+
+<!-- S6 style sheet links -->
+<link rel="stylesheet" href="hidra.css" media="projection" id="styleProjection">
+<link rel="stylesheet" href="s6/screen.css" media="screen" id="styleScreen">
+<link rel="stylesheet" href="s6/print.css" media="print">
+
+<!-- S6 JS -->
+<script src="s6/jquery.js"></script>
+<script src="s6/jquery.slideshow.js"></script>
+<script>
+ $(document).ready( function() {
+ Slideshow.init();
+ } );
+
+
+</script>
+
+<!-- Better Browser Banner for Microsoft Internet Explorer (IE) -->
+<!--[if IE]>
+<script src="s6/jquery.microsoft.js"></script>
+<![endif]-->
+
+
+
+</head>
+<body>
+
+<div class="layout">
+ <div id="header"></div>
+ <div id="footer">
+ <h1></h1>
+ <h2></h2>
+ </div>
+</div>
+
+<div class="presentation">
+
+<div class='slide centered'> + +<!-- _S9SLIDE_ centered --> + +<p><img src="hidra-oil.png" alt="O Processo Hidra" /></p> + + +</div> +<div class='slide '> +<h1 id="o-processo-hidra">O Processo Hidra</h1><div class="centered"> + <p><img src="hidra-oil.png" alt="O Processo Hidra" /></p> + + <p>De relógios a nuvens, de nuvens a hidras.</p> +</div> + + +</div> +<div class='slide '> +<h1 id="parte-1-introduo">Parte 1: Introdução</h1></div> +<div class='slide '> +<h1 id="objetivo-da-apresentao">Objetivo da apresentação</h1><p>O objetivo desta fala é divulgar os estudos em andamento sobre o processo hidra dando espaço para possíveis andamentos:</p> + +<ol> + <li> + <p>Informar os grupos e pessoas que possuem conteúdo hospedado em infraestruturas tecno-sociais comuns sobre o trabalho desenvolvido.</p> + </li> + <li> + <p>Encorajar grupos técnicos existentes para adotarem procedimentos que favoreçam suas infraestruturas a terem comportamento hidra.</p> + </li> +</ol> + +<p>Esta apresentação ainda está em processo de concepção e revisão e por isso não está sendo divulgada.</p> + + +</div> +<div class='slide '> +<h1 id="o-que--uma-hidra">O que é uma Hidra?</h1></div> +<div class='slide '> +<h1 id="ser-mitolgico-de-mltiplas-cabeas-regenerativas-destrudo-por-hrcules">Ser mitológico de múltiplas cabeças regenerativas, destruído por Hércules</h1><div class="centered"> + <p><img src="images/Hydra_04.jpg" alt="Hidra mitológica" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="na-biologia-moderna-animal-aqutico-que-possui-capacidades-regenerativas">Na biologia moderna, animal aquático que possui capacidades regenerativas</h1><div class="centered"> + <p><img src="images/Hydra001.jpg" alt="Hida biológica" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="o-que--o-processo-hidra">O que é o Processo Hidra?</h1><p>O Processo Hidra é uma descrição de infraestruturas tecno-sociais que apresentam:</p> + +<ol> + <li> + <p>Replicabilidade e escalabilidade.</p> + </li> + <li> + <p>Capacidade de combinação rizomática.</p> + </li> + <li> + <p>Regeneração e reagrupamento após eventos catastróficos.</p> + </li> +</ol> + +<p>A Hidra moderna pode resistir a Hércules.</p> + + +</div> +<div class='slide '> +<h1 id="parte-2-grupos-tcnicos-sociais">Parte 2: Grupos Técnicos Sociais</h1><p>Mas antes façamos uma retrospectiva…</p> + + +</div> +<div class='slide '> +<h1 id="sistemas-informacionais-sociais">Sistemas informacionais sociais</h1><p>Modelo “clássico” de hospedagem: arquitetura “cliente-servidor”:</p> + +<div class="centered"> + <p><img src="http://code.google.com/edu/parallel/img/client-server.gif" alt="Arquitetura cliente-servidor" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="trabalho-tcnico-informacional-em-grupos-sociais">Trabalho técnico informacional em grupos sociais</h1><p>Características:</p> + +<ul> + <li> + <p>Considerado tecnicamente de alta dificuldade e dedicação.</p> + </li> + <li> + <p>Esforço para provisionamento, configuração e manutenção de sistemas.</p> + </li> + <li> + <p>Trabalho demorado: escala de meses para alcançar estabilidade.</p> + </li> + <li> + <p>Suscetível a muitas falhas: escala de horas para que um sistema seja inutilizado.</p> + </li> + <li> + <p>Pouco tempo disponível para o trabalho.</p> + </li> + <li> + <p>Dificuldade para a realização de backups e manutenção de procedimentos administrativos.</p> + </li> + <li> + <p>Baixa mobilização e força de trabalho “tarefeira”.</p> + </li> + <li> + <p>Custa um bom dinheiro…</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="interldio-a-destruio-das-redes">Interlúdio: a destruição das redes</h1><p><img src="http://www.ibiblio.org/pioneers/images/centralized.gif" alt="Redes centralizadas e descentralizadas" /> +<img src="http://www.ibiblio.org/pioneers/images/distributed.gif" alt="Rede distribuída" /></p> + +<p>A cada evento catastrófico, vários grupos são prejudicados com danos à comunicação de difícil cicatrização.</p> + + +</div> +<div class='slide '> +<h1 id="parte-3-contra-ataque-infraestrutural">Parte 3: Contra-ataque infraestrutural</h1><p>Como impedir que uma rede seja destruída mesmo que a remoção de nodos continue?</p> + + +</div> +<div class='slide '> +<h1 id="a-diviso-em-camadas">A divisão em camadas</h1><p>Observação crucial:</p> + +<pre><code>"Ghost in the shell": o disco e o hardware são intercambiáveis, + provisionamento pode ocorrer em múltiplas etapas. É possível + manter um estoque de discos pré-instalados e uma reserva financeira + para a aquisição de máquinas. Isso e backups permite a reconstrução + de sistemas. +</code></pre> + +<p>Conclusão imediata:</p> + +<pre><code>É necessário "descolar" a camada de serviços (web, streaming, email, +etc) da camada infraestrutural (máquinas, conexões, etc): filtragem +de problemas físicos e jurídicos. +</code></pre> + +<p>A camada de serviços pode então ser “congelada” na forma de backups, enquanto que a camada infraestrutural não possui “alma” intrínseca, podendo ser reconfigurada quando necessário. Desse modo, várias máquinas podem ser mantidas no ar para aumentar a tolerância a falhas.</p> + +<p>Mas como um sítio pode estar simultaneamente em várias máquinas?</p> + + +</div> +<div class='slide '> +<h1 id="dns-colando-domnios-em-mquinas">DNS: colando domínios em máquinas</h1><p><img src="images/An_example_of_theoretical_DNS_recursion.png" alt="DNS" /> +<img src="http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2s-round-robin.jpeg" alt="Round Robin DNS" /></p> + +<p>O colamento/descolamento entre camadas é possível mediante mudanças de DNS.</p> + + +</div> +<div class='slide '> +<h1 id="proxies-distribuindo-um-stio-entre-mquinas">Proxies: distribuindo um sítio entre máquinas</h1><div class="centered"> + <p><img src="http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png" alt="App proxy" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="aplicao-descentralizada-ou-distribuda">Aplicação descentralizada ou distribuída</h1><div class="centered"> + <p><img src="http://upload.wikimedia.org/wikipedia/en/thumb/5/5a/ICEgrid.png/800px-ICEgrid.png" alt="ICE" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="tipos-de-camadas">Tipos de camadas</h1><p>Informação de um sistema é dividida conforme sua aplicabilidade:</p> + +<ul> + <li> + <p>Hardware: manifestações cristalizadas de informação: computadores.</p> + </li> + <li> + <p>Programas (software): pacotes.</p> + </li> + <li> + <p>Configuração (módulos).</p> + </li> + <li> + <p>Chaves e senhas.</p> + </li> + <li> + <p>Dados (o conteúdo propriamente dito).</p> + </li> +</ul> + +<p>Tais camadas podem ser empacotadas em sistemas e tais sistemas podem ser agregados em outros sistemas (camadas de camadas de camadas): pode ser uma abstração complicada, mas o ganho conceitual em isolamento de instâncias é importante.</p> + + +</div> +<div class='slide '> +<h1 id="problemas">Problemas</h1><p>O discurso é bonito, porém…</p> + +<ol> + <li> + <p>Hardware é muito heterogêneo para padronizações serem efetivas.</p> + </li> + <li> + <p>Os programas são muito diversos para serem estudados, integrados e desenvolvidos.</p> + </li> + <li> + <p>Configurações são muito complexas e numerosas para serem facilmente separadas e replicadas de forma genérica.</p> + </li> + <li> + <p>São necessárias muitas senhas de boa complexidade, o que torna sua manutenção complicada.</p> + </li> + <li> + <p>Backups são difíceis de serem realizados e recuperados.</p> + </li> +</ol> + +<p>Ou seja: o discurso da divisão em camadas é interessante, porém na realidade sua implementação enfrenta diversos problemas. Serão eles impeditivos?</p> + + +</div> +<div class='slide '> +<h1 id="o-plano-r">O Plano R*</h1><p><img src="http://www.autistici.org/orangebook/slides/rete.png" alt="Rede" /> +<img src="http://www.autistici.org/orangebook/slides/rings.png" alt="Anéis" /></p> + + +</div> +<div class='slide '> +<h1 id="o-plano-r-email">O Plano R*: email</h1><div class="centered"> + <p><img src="http://www.autistici.org/orangebook/slides/flussomail.png" alt="Sistema de email escalável" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="como--possvel">Como é possível?</h1><p>O segredo está na articulação da força de trabalho com a divisão de camadas. A regra geral é:</p> + +<ol> + <li>Utilização de ferramentas sólidas e amplamente utilizadas por comunidades de software livre e aberto.</li> + <li>Trabalho de desenvolvimento focado na integração de soluções existentes, enviando alterações em código corrente acima sempre que possível.</li> + <li>Desenvolvendo código próprio, porém livre, apenas quando não existente ou insuficiente nas comunidades.</li> +</ol> + +<p>Cada um desdes tipos informacionais é distribuído em unidades que por sua vez são agregados em árvores:</p> + +<ul> + <li>Hardware em servidores (canalizadores de fluxos, nodos ou instâncias em nuvens).</li> + <li>Programas em pacotes e distribuições.</li> + <li>Configurações em módulos e repositórios.</li> + <li>Chaves (que são unidades de segredo) em repositórios.</li> + <li>Dados em árvore de backups.</li> +</ul> + + +</div> +<div class='slide '> +<h1 id="diviso-arteftica">Divisão artefática</h1><p>A divisão em camadas é artificial (artefática), porém com importantes consequências quando observada à luz da divisão do trabalho de comunidades de software livre e aberto:</p> + +<pre><code> /'\ | + | \./ +upstream downstream +</code></pre> + +<ul> + <li>Hardware: desenvolvimento caro e complexo; hardware livre e aberto engatinhando; dependência do mercado. Exemplo: disco rígido.</li> + <li>Programas e distribuições: grandes comunidades de desenvolvimento e uso. Exemplo: GNU/Linux, Debian.</li> + <li>Configuração: comunidades mais restritas de desenvolvimento e uso. Exemplo: manuais, howtos, módulos.</li> + <li>Chaves e senhas: restrita ao grupo responsável por manter uma dada infraestrutura. Exemplo: senha de superusuário/a.</li> + <li>Dados: desenvolvidos pelas pessoas e grupos hospedados. Exemplo: texto num wiki. </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="diviso-arteftica---2">Divisão artefática - 2</h1><p>É possível reconstruir um sistema dados esses elementos. A divisão do trabalho upstream/downstream é favorável à reconstrução, já que as tarefas se tornam mais complexas ao longo da subida da corrente onde usualmente os grandes grupos sociais se reúnem para solucioná-las.</p> + + +</div> +<div class='slide '> +<h1 id="economia-de-trabalho">Economia de trabalho</h1><p>Assim, é possível economizar muita força de trabalho.</p> + +<ol> + <li> + <p>Enviar um desenvolvimento corrente acima (upstream) libera o grupo técnico de uma manutenção posterior, pois o trabalho passa a ser de responsabilidade da comunidades mais ampla.</p> + </li> + <li> + <p>Quanto mais específica for a informação, mais abaixo da corrente (downstream) ela deve ser mantida.</p> + </li> + <li> + <p>Naquilo que não houver desenvolvimento corrente acima, atuar como fonte (ou seja, agir como upstream) e fornecer para a comunidade.</p> + </li> +</ol> + + +</div> +<div class='slide '> +<h1 id="tipos-de-salvaguarda">Tipos de salvaguarda</h1><p>Para todas as camadas divididas anteriormente é possível criar algum tipo de salvaguarda contra perdas:</p> + +<ul> + <li> + <p>Dinheiro: armazenamento e replicação de força de trabalho (potencial de trabalho armazenado).</p> + </li> + <li> + <p>Estoque: hardware hoje é commodity, podendo ser minimamente estocado ou mantido online em diversos locais.</p> + </li> + <li> + <p>Repositórios: programas, pacotes, distribuições e configurações.</p> + </li> + <li> + <p>Backups: manutenção de dados ou coisas sobressalentes.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-3-contexto-brasileiro">Parte 3: contexto brasileiro</h1></div> +<div class='slide '> +<h1 id="oramento-e-infraestrutura">Orçamento e infraestrutura</h1><p>Custos:</p> + +<ul> + <li>Plano R*: EUR 10.000 anuais.</li> + <li>No Brasil, é praticamente a despesa anual de um centro social alugado e muito mais do que a receita da maioria dos grupos.</li> +</ul> + +<p>Conexão:</p> + +<ul> + <li>Nos EUA e na Europa, a conexão é rápida e barata. Datacenters corporativos são acessíveis.</li> + <li>No Brasil, a conexão é lenta, cara e o preço dos datacenters é exorbitante.</li> +</ul> + +<p>Repressão:</p> + +<ul> + <li>Criminalização dos movimentos sociais (entulho jurídico).</li> + <li>Polícia violenta.</li> +</ul> + +<p>Estaremos impossibilitados/as de mantermos servidores no país?</p> + + +</div> +<div class='slide '> +<h1 id="por-outro-lado">Por outro lado</h1><ul> + <li> + <p>A legislação, a jurisprudência, cultura e valores brasileiros são muito mais favoráveis à preservação da privacidade que nos EUA ou na Europa (fator Dantas).</p> + </li> + <li> + <p>Honorários advocatícios não são tão altos quanto no exterior (?).</p> + </li> + <li> + <p>O câmbio é favorável a doações internacionais.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="o-caso-satangoss">O caso Satangoss</h1><p>“O que demorou quatro anos para juntarmos nos foi arrebatado num único dia.”</p> + +<ul> + <li> + <p>Agosto de 2008: polícia civil apreende o servidor do Saravá sem mandado judicial.</p> + </li> + <li> + <p>Mais de cem sítios fora do ar.</p> + </li> + <li> + <p>Não havia backup remoto e nem medidas de contingência estabelecidas.</p> + </li> + <li> + <p>Todos os ovos estavam na mesma cesta.</p> + </li> + <li> + <p>Grande desmobilização.</p> + </li> + <li> + <p>Análise do caso: http://www.sarava.org/node/44</p> + </li> +</ul> + +<p>Como reverter a crise num novo ciclo de mudança e amadurecimento?</p> + + +</div> +<div class='slide '> +<h1 id="parte-4-o-processo-hidra">Parte 4: O Processo Hidra</h1><div class="centered"> + <p><img src="http://f.i.uol.com.br/folha/ciencia/images/0825246.jpg" alt="Regeneração" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="regenerao">Regeneração</h1><p>Hidra: toda célula pode ter o germe da própria organização. Múltiplas cabeças, células tronco que podem adquirir especialização conforme a necessidade.</p> + +<div class="centered"> + <p><img src="http://image.wistatutor.com/content/growth-regeneration-ageing/regeneration-hydra.jpeg" alt="Regeneração da hidra" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="hidra-em-processo">Hidra em processo</h1><div class="centered"> + <p><img src="http://www.uni-kiel.de/zoologie/bosch/jpg/bosch_fig2.jpg" alt="Regeneração da Hidra" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="hidra-em-processo---2">Hidra em processo - 2</h1><div class="centered"> + <p><img src="http://www.uni-kiel.de/zoologie/bosch/jpg/bosch_fig3.jpg" alt="Regeneração da Hidra" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="topologias">Topologias</h1><pre><code>"[To] keep our sources safe, we have had to spread assets, encrypt everything, +and move telecommunications and people around the world to activate protective +laws in different national jurisdictions," Mr Assange said told the BBC earlier +this year. +</code></pre> + +<p>Fonte: <a href="http://www.bbc.co.uk/news/world-11047811">http://www.bbc.co.uk/news/world-11047811</a></p> + +<p>Possíveis montagens: anel, estrela, rizomática, etc. Frontends e backends.</p> + + +</div> +<div class='slide '> +<h1 id="parte-5-o-processo-hidra-saravento">Parte 5: O Processo Hidra Saravento</h1><ol> + <li> + <p>Apresenta Padrão Saravá (Sarava Pattern, <a href="http://padrao.sarava.org">http://padrao.sarava.org</a>).</p> + </li> + <li> + <p>Utiliza Resource Sharing Protocol (RSP, <a href="http://rsp.sarava.org">http://rsp.sarava.org</a>).</p> + </li> + <li> + <p>Considerando a adoção de padrões definidos de política de segurança e privacidade.</p> + </li> + <li> + <p>Organiza-se de acordo com protocolos (<a href="http://protocolos.sarava.org">http://protocolos.sarava.org</a>).</p> + </li> +</ol> + +<p>Na Hidra Saraventa, cada célula é chamada de “nodo”:</p> + +<ul> + <li> + <p>Nodos físicos com servidores virtuais com fins específicos.</p> + </li> + <li> + <p>Nodos virtuais em diversos locais (inclusive hospedados por terceiros).</p> + </li> +</ul> + +<p>Baseada no seguinte pricípio: quais problemas solucionaremos, quais não.</p> + + +</div> +<div class='slide '> +<h1 id="o-padro-sarav">O Padrão Saravá</h1><p>O Padrão Saravá é uma sistematização de configuração de servidores, gerenciadores de conteúdo e aplicações diversas usados pelo Grupo Saravá. O padrão foi desenvolvido para:</p> + +<ul> + <li> + <p>Ter controle dos pacotes utilizados, arquivos de configuração e serviços em uso.</p> + </li> + <li> + <p>Uniformidade de administração.</p> + </li> + <li> + <p>Sistema de gerenciamento de backups comum para que as máquinas de um projeto possam trocar dados.</p> + </li> + <li> + <p>Que um servidor seja configurado apenas uma vez e que suas configurações possam ser aproveitados para outras máquinas.</p> + </li> + <li> + <p>Que sites e serviços sejam armazenados de maneira regular para facilitar atualizações e migrações.</p> + </li> + <li> + <p>Manter projetos e serviços isolados uns dos outros através de servidores virtuais.</p> + </li> + <li> + <p>Tornar a instalação dos servidores facilmente replicável.</p> + </li> +</ul> + +<p>Dinâmica de desenvolvimento:</p> + +<pre><code>Documentação wiki -> Configurações pré-gravadas -> Software +</code></pre> + + +</div> +<div class='slide '> +<h1 id="puppet">Puppet</h1><p><img src="http://docs.reductivelabs.com/images/Puppet_Star.png" alt="Puppet: topologia" /> +<img src="http://www.puppetlabs.com/images/system_diagram.png" alt="Puppet: diagrama de sistema" /></p> + + +</div> +<div class='slide '> +<h1 id="puppet-compartilhando-configurao">Puppet: compartilhando configuração</h1><p>Código puppet:</p> + +<pre><code>file { '/etc/passwd': + owner => root, + group => root, + mode => 644, +} +</code></pre> + +<p>Módulos compartilhados:</p> + +<ul> + <li> + <p><a href="http://git.sarava.org">http://git.sarava.org</a></p> + </li> + <li> + <p><a href="https://labs.riseup.net/code/projects/sharedpuppetmodules">https://labs.riseup.net/code/projects/sharedpuppetmodules</a></p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="git-e-gitosis">Git e gitosis</h1><p><img src="http://hoth.entp.com/output/scm.png" alt="VCS" /> +<img src="http://hoth.entp.com/output/dscm.png" alt="VCS distribuído" /></p> + + +</div> +<div class='slide '> +<h1 id="o-protocolo-de-compartilhamento-de-recursos">O Protocolo de Compartilhamento de Recursos</h1><pre><code>"The Resource Sharing Protocol (RSP) is a set of metadata intended to help free +software groups + + * Share their available resources and also Find groups that can host + * services for them given their needs and requirements. + +The RSP splits each resource in a layer or set of service layers. You can think +of service layers something very general, ranging from servers, databases, +websites. If you need to, you can even consider stuff such as tables and +bicycles as layers that provide some kind of service to a hosted group. ;)" + +-- http://rsp.sarava.org +</code></pre> + + +</div> +<div class='slide '> +<h1 id="orquestrao">Orquestração</h1><p>Para complementar a Configuração de sistemas padronizada e centralizada, procedimentos como</p> + +<ol> + <li>Atualização de pacotes.</li> + <li>Atualização de código de gerenciadores de conteúdo.</li> + <li>Carga de bancos de dados. </li> +</ol> + +<p>podem ser codificados de forma a serem facilmente aplicados a múltiplas camadas de forma simultânea.</p> + +<p>Exemplos:</p> + +<ul> + <li><a href="https://git.sarava.org/?p=hydra.git;a=summary">https://git.sarava.org/?p=hydra.git;a=summary</a></li> + <li><a href="http://www.capify.org">http://www.capify.org</a></li> + <li><a href="http://marionette-collective.org">http://marionette-collective.org</a></li> + <li><a href="https://fedorahosted.org/func">https://fedorahosted.org/func</a></li> + <li><a href="http://fabfile.org">http://fabfile.org</a></li> + <li><a href="http://www.debian-administration.org/article/Automating_ssh_and_scp_across_multiple_hosts">http://www.debian-administration.org/article/Automating_ssh_and_scp_across_multiple_hosts</a></li> +</ul> + + +</div> +<div class='slide '> +<h1 id="ikiwiki">Ikiwiki</h1><p>O Ikiwiki (<a href="http://ikiwiki.info">http://ikiwiki.info</a>) é um software de wiki que usa um sistema de controle de versão e arquivos de texto, possibilitando:</p> + +<ol> + <li>A existência de múltiplas cópias integrais do wiki (online e offline).</li> + <li>Desenvolvimento distribuído de documentação.</li> +</ol> + +<p>O ikiwiki é muito útil para reunir documentação de sistemas, já que não necessita de nenhum sistema web funcional para abrigá-la.</p> + + +</div> +<div class='slide '> +<h1 id="virtualizao">Virtualização</h1><p>Virtualização através de Linux-VServer (existem outras implementações possíveis):</p> + +<ul> + <li><a href="http://www.linux-vserver.org">http://www.linux-vserver.org</a></li> + <li><a href="http://slack.sarava.org/vservers">http://slack.sarava.org/vservers</a></li> +</ul> + +<p>Principais vantagens:</p> + +<ul> + <li> + <p>Permite diversos grupos compartilharem uma mesma máquina presevando sua autonomia.</p> + </li> + <li> + <p>Grupos podem hospedar mutuamente instâncias virtuais. Exemplo: se existem 5 grupos com uma máquina cada um, se cada um deles hospedar um vserver para cada grupo, teremos 4 locais remotos de hospedagem por grupo, aumentando assim as possibilidades de salvaguarda e escalabilidade.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="keyringer-e-monkeysphere">Keyringer e monkeysphere</h1><p>O Keyringer (<a href="http://git.sarava.org/?p=keyringer.git;a=summary">http://git.sarava.org/?p=keyringer.git;a=summary</a>) é um repositório distribuído de senhas/chaves baseado em GPG e git.</p> + +<p>O monkeysphere (<a href="http://web.monkeysphere.info">http://web.monkeysphere.info</a>) é um programa que permite a verificação de hosts SSH e usuários/as através da Teia de Confiabilidade do OpenPGP. Com ele, o gerenciamento de fingerprints fica mais fácil e evita que páginas como esta centralizem informações que possam se desatualizar. </p> + + +</div> +<div class='slide '> +<h1 id="tecnologia-bootless">Tecnologia bootless</h1><p>Muitos esquemas de criptografia em disco se baseiam na proteção das partições de dadados e da área de troca, porém dependem da existência de ao menos uma partição de inicialização com as imagens do sistema e de um setor de inicialização.</p> + +<p>Com acesso físico à máquina, é possível infectar tais dados de inicialização e comprometer a criptografia de todo o sistema.</p> + +<p>Para mitigar a situação, o esquema Bootless é um repositório git que contém as imagens de inicialização e a configuração necessárias para o procedimento de partida.</p> + +<p>Assim, é possível manter a parte de inicialização fora da máquina, por exemplo em chaveiros USB.</p> + +<p>Projeto similar: <a href="http://lfde.org">http://lfde.org</a></p> + + +</div> +<div class='slide '> +<h1 id="monitoramento-nagios">Monitoramento: nagios</h1><div class="centered"> + <p><img src="http://nagios.sourceforge.net/images/screens/new/statusmap-circular.png" alt="Nagios" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="monitoramento-munin">Monitoramento: munin</h1><div class="centered"> + <p><img src="http://upload.wikimedia.org/wikipedia/commons/c/ce/Munin-memory-week.png" alt="Munin" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="backups">Backups</h1><p>Estratégia:</p> + +<ol> + <li>Backups locais criptografados com duplicity: + <ul> + <li>Incluindo apenas <code>/etc</code>, <code>/var</code>, <code>/home</code>.</li> + <li>Excluindo logs, cache e backups remotos.</li> + </ul> + </li> + <li>Backups remotos apenas do backup local em duplicity, via rdiff ou rsync.</li> + <li>Nodos designados para armazenamento de backups.</li> + <li>Incrementos locais e remotos para aumentar consistência dos dados.</li> + <li>Procedimento integrado de restore e ativação de nodo.</li> +</ol> + + +</div> +<div class='slide '> +<h1 id="hardware-e-custos">Hardware e custos</h1><ul> + <li>Servidor mini-ITX Atom dual core + 2GB RAM + 1TB: R$680.00.</li> + <li>Nobreaks APC: +/- R$500,00.</li> + <li>Banda larga ADSL/cabo: R$80,00 a R$200,00.</li> + <li>Energia: 180W (mini-ITX) máx.</li> + <li>Sistema pode ser instalado inclusive em memórias de estado sólido (microSD por exemplo).</li> +</ul> + +<div class="centered"> + <p><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Mini-itx-motherboard.jpg/800px-Mini-itx-motherboard.jpg" alt="Mini ITX" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="utilidades-adaptador-para-discos">Utilidades: adaptador para discos</h1><div class="centered"> + <p><img src="http://www.sataadapter.com/sata-to-usb-adapter-cable-for-windows-and-mac.jpg" alt="Adaptador SATA" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="utilidades-chave-de-entropia">Utilidades: chave de entropia</h1><p><img src="http://www.entropykey.co.uk/res/device.jpeg" alt="Entropy key" /> +<img src="http://www.entropykey.co.uk/res/entropy-trite-small-nq8.png" alt="Entropy graph" /></p> + + +</div> +<div class='slide '> +<h1 id="segurana">Segurança</h1><p>Acesso remoto:</p> + +<ul> + <li> + <p>Contas SSH administrativas em todos os nodos.</p> + </li> + <li> + <p>Contas SSH de backup para nodos de backup.</p> + </li> + <li> + <p>Contas SSH de tunelamento para nodos diversos.</p> + </li> +</ul> + +<p>Análise:</p> + +<ol> + <li> + <p>É importante isolar o máximo a capacidade de acesso para contas de nodos de backup ou que tunelem conexões.</p> + </li> + <li> + <p>Administradores/as precisam ter boas medidas de segurança:</p> + <ul> + <li>Pasta criptografada.</li> + <li>Senhas e chaves seguras.</li> + </ul> + </li> +</ol> + + +</div> +<div class='slide '> +<h1 id="protocolos-sociais">Protocolos sociais</h1><ul> + <li>Protocolo de Ação Coletiva: <a href="http://protocolos.sarava.org">http://protocolos.sarava.org</a>.</li> + <li>Outros protocolos e metodologias (contabilidade, acesso à informação, relação com grupos, etc).</li> + <li> + <p>Uso de um sistema de gestão de processos (trac ou similar).</p> + + <pre><code> .------------------->-----------------. + / .----------<--------------<-------. \ + | ' \ \ + | | .------>-----. \ \ + | | | \ \ \ + Proposta -----> Discussão ->--. \ \ \ + | ^ | \ \ \ \ + | | | \ \ \ \ + | `----<-----' | \ \ \ + | | | \ \ + `------>------ Decisão --<--' | \ \ + | | | \ \ + | | | | | + Atribuição de --<---' '---> Arquivamento --->---' ; + Responsabilidades ----->-------' ^ \ / + ^ | ___________/ `---<-----' + | \ .' + | `--> Realização -->--. + | | | \ + | | | / + `----<-----' `-----<---' +</code></pre> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="resumo-estratgia-de-gesto">Resumo: Estratégia de gestão</h1><ul> + <li> + <p>Facilitar instalação, manutenção e gestão de dados.</p> + </li> + <li> + <p>Manter backups em máquinas prontas para serem inicializadas.</p> + </li> + <li> + <p>Manter nodos master prontos para assumirem o posto de “cabeça ativa”.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-6-a-confederao-das-hidras-unidas">Parte 6: A Confederação das Hidras Unidas</h1><div class="centered"> + <p><img src="http://apod.nasa.gov/apod/image/0104/hydra_aat116.jpg" alt="Hidra Cluster" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="a-confederao-das-hidras-unidas">A Confederação das Hidras Unidas</h1><ul> + <li> + <p>Hidra é um processo, não uma tecnologia, implementação, sistema ou serviço.</p> + </li> + <li> + <p>Assim, é possível ter hidras menos sistematizadas e com diferentes formas de organização. O processo já ocorre em vários locais.</p> + </li> + <li> + <p>Havendo várias hidras, se elas se integram passa a existir a Confederação das Hidras Unidas.</p> + </li> + <li> + <p>Importante questão do licenciamento: AGPL 3.0 para garantir o máximo possível da disponibilização de código e documentação.</p> + </li> + <li> + <p>Não é estritamente necessária a criação de uma “confederação”, já que a cultura de hidras pode ser não-coordenada.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-7-nuvens-e-hidras">Parte 7: Nuvens e Hidras</h1><p>Hidras são nuvens (cloud computing)?</p> + +<ul> + <li> + <p>Cloud computing foca apenas nas instâncias e como estas são integradas por aplicações (IaaS, SaaS, PaaS) e no seu uso sob demanda.</p> + </li> + <li> + <p>Cloud computing é uma iniciativa do mercado e uma tendência à terceirização total das atividades.</p> + </li> + <li> + <p>A Hidra leva em consideração a organização social que suporta a infraestrutura computacional.</p> + </li> + <li> + <p>A Hidra é uma nuvem na qual certos nodos desempenham papéis determinados, porém contendo o germe de toda a organização.</p> + </li> + <li> + <p>Outra classe de nuvens: botnets.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="nuvens-diagramas">Nuvens: diagramas</h1><p><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cloud_Computing_Stack.svg/340px-Cloud_Computing_Stack.svg.png" alt="Camadas" /> +<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/79/CloudComputingSampleArchitecture.svg/550px-CloudComputingSampleArchitecture.svg.png" alt="Arquitetura" /></p> + + +</div> +<div class='slide '> +<h1 id="tipos-de-nuvens">Tipos de nuvens</h1><div class="centered"> + <p><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Cloud_computing_types.svg/800px-Cloud_computing_types.svg.png" alt="Tipos de nuvens" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="parte-8-futuro">Parte 8: Futuro</h1><ul> + <li>Hidra Saraventa: ainda em intenso desenvolvimento, porém já em estágio maduro. Falta (em agosto/2010): + <ul> + <li>Melhoria no procedimento de bootstrap.</li> + <li>Integração com DNS.</li> + <li>Sistema de proxy para balanceamento de carga.</li> + <li>Melhoria de procedimentos de sunsetting de sítios, plataformas e contas.</li> + <li>Longuíssimo prazo, caso realizável: possibilidade de um nodo ser convertido de uma classe para outra.</li> + <li>Procedimentos para suporte jurídico.</li> + <li>Nodos em conexões DSL e cabo: IP dinâmico, DNS reverso, etc.</li> + <li>VPN entre os nodos, Puppet Dashboard?, External node tool?</li> + <li>Migrar para Linux Containers (lxc).</li> + <li>Melhoria da documentação e representações gráficas do processo.</li> + <li>Storage de dados distribuído.</li> + </ul> + </li> + <li>Hidras via Rádio.</li> + <li>Hidras em outros tipos de organizações sociais.</li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-9-concluses">Parte 9: Conclusões</h1><ul> + <li> + <p>Resolver a replicação e escalabilidade primeiro na infraestrutura (máquinas, configurações e backups), depois nas camadas superiores (CMSs, por exemplo)</p> + </li> + <li> + <p>Não importa tanto se a rede é centralizada, descentralizada ou distribuída se antes de tudo ela for regenerativa. No entanto, em geral são as redes distribuídas e descentralizadas que possuem fatores de regeneração maiores do que no caso centralizado.</p> + </li> + <li> + <p>Número grande de máquinas é interessante: várias podem estar sem funcionar num dado momento, mas as que estiverem funcionando podem dar conta da demanda.</p> + </li> + <li> + <p>A hidra é indestrutível? Essa questão faz sentido? Positivismo, revoluções e cataclismas: o limite da hidra por ter uma relação e abertura e fechamento (autonomia dependente).</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-10-referncias">Parte 10: Referências</h1></div> +<div class='slide '> +<h1 id="referncias-imagens-usadas">Referências: imagens usadas</h1><ul> + <li><a href="http://en.wikipedia.org/wiki/File:Hydra_04.jpg">http://en.wikipedia.org/wiki/File:Hydra_04.jpg</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:Hydra001.jpg">http://en.wikipedia.org/wiki/File:Hydra001.jpg</a></li> + <li><a href="http://code.google.com/edu/parallel/dsd-tutorial.html">http://code.google.com/edu/parallel/dsd-tutorial.html</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:DNS_in_the_real_world.svg">http://en.wikipedia.org/wiki/File:DNS_in_the_real_world.svg</a></li> + <li><a href="http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2sfarm.html">http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2sfarm.html</a></li> + <li><a href="http://www.autistici.org/orangebook/slides/orangebook.en.html">http://www.autistici.org/orangebook/slides/orangebook.en.html</a>.</li> + <li><a href="http://www.autistici.org/orangebook/slides/orangebook.en.html">http://www.autistici.org/orangebook/slides/orangebook.en.html</a></li> + <li><a href="http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png">http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:ICEgrid.png">http://en.wikipedia.org/wiki/File:ICEgrid.png</a></li> + <li><a href="http://www.ibiblio.org/pioneers/baran.html">http://www.ibiblio.org/pioneers/baran.html</a></li> + <li><a href="http://www1.folha.uol.com.br/folha/ciencia/ult306u442499.shtml">http://www1.folha.uol.com.br/folha/ciencia/ult306u442499.shtml</a></li> + <li><a href="http://www.tutorvista.com/content/biology/biology-iv/growth-regeneration-ageing/regeneration.php">http://www.tutorvista.com/content/biology/biology-iv/growth-regeneration-ageing/regeneration.php</a></li> + <li><a href="http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html">http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html</a></li> + <li><a href="http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html">http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html</a></li> + <li><a href="http://www.puppetlabs.com/puppet/introduction">http://www.puppetlabs.com/puppet/introduction</a></li> + <li><a href="http://docs.reductivelabs.com/guides/introduction.html">http://docs.reductivelabs.com/guides/introduction.html</a></li> + <li><a href="http://www.nagios.org/about/screenshots">http://www.nagios.org/about/screenshots</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:Munin-memory-week.png">http://en.wikipedia.org/wiki/File:Munin-memory-week.png</a></li> + <li><a href="http://hoth.entp.com/output/git_for_designers.html">http://hoth.entp.com/output/git_for_designers.html</a></li> + <li><a href="http://en.wikipedia.org/wiki/Mini-itx">http://en.wikipedia.org/wiki/Mini-itx</a></li> + <li><a href="http://www.sataadapter.com">http://www.sataadapter.com</a></li> + <li><a href="http://www.entropykey.co.uk">http://www.entropykey.co.uk</a></li> + <li><a href="http://apod.nasa.gov/apod/ap010416.html">http://apod.nasa.gov/apod/ap010416.html</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:Cloud_Computing_Stack.svg">http://en.wikipedia.org/wiki/File:Cloud_Computing_Stack.svg</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:CloudComputingSampleArchitecture.svg">http://en.wikipedia.org/wiki/File:CloudComputingSampleArchitecture.svg</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:Cloud_computing_types.svg">http://en.wikipedia.org/wiki/File:Cloud_computing_types.svg</a></li> +</ul> +</div> +
+
+</div><!-- presentation -->
+</body>
+</html>
\ No newline at end of file diff --git a/doc/hidra.jpg b/doc/hidra.jpg Binary files differnew file mode 100755 index 0000000..372265a --- /dev/null +++ b/doc/hidra.jpg diff --git a/doc/hidra.markdown b/doc/hidra.markdown new file mode 100644 index 0000000..b620443 --- /dev/null +++ b/doc/hidra.markdown @@ -0,0 +1,764 @@ +Title: O Processo Hidra +Author: Silvio Rhatto +Generator: S9 + +%css + +body { + font-family: monospace; +} + +.centered img { + display: block; + margin-left: auto; + margin-right: auto; +} + +.centered { + text-align: center; +} + +p, li, dt, dd, td, th { + font-size: 16pt; +} + +.slide h1 { + font-size: 25pt; +} + +%end + +!SLIDE centered + +![O Processo Hidra](hidra-oil.png) + +O Processo Hidra +================ + +<div class="centered" markdown="1"> +![O Processo Hidra](hidra-oil.png) + +De relógios a nuvens, de nuvens a hidras. +</div> + +Parte 1: Introdução +=================== + +Objetivo da apresentação +======================== + +O objetivo desta fala é divulgar os estudos em andamento sobre o processo hidra dando espaço para possíveis andamentos: + + 1. Informar os grupos e pessoas que possuem conteúdo hospedado em infraestruturas tecno-sociais comuns sobre o trabalho desenvolvido. + + 2. Encorajar grupos técnicos existentes para adotarem procedimentos que favoreçam suas infraestruturas a terem comportamento hidra. + +Esta apresentação ainda está em processo de concepção e revisão e por isso não está sendo divulgada. + +O que é uma Hidra? +================== + +Ser mitológico de múltiplas cabeças regenerativas, destruído por Hércules +========================================================================= + +<div class="centered" markdown="1"> +![Hidra mitológica](images/Hydra_04.jpg) +</div> + +Na biologia moderna, animal aquático que possui capacidades regenerativas +========================================================================= + +<div class="centered" markdown="1"> +![Hida biológica](images/Hydra001.jpg) +</div> + +O que é o Processo Hidra? +========================= + +O Processo Hidra é uma descrição de infraestruturas tecno-sociais que apresentam: + + 1. Replicabilidade e escalabilidade. + + 2. Capacidade de combinação rizomática. + + 3. Regeneração e reagrupamento após eventos catastróficos. + +A Hidra moderna pode resistir a Hércules. + +Parte 2: Grupos Técnicos Sociais +================================ + +Mas antes façamos uma retrospectiva... + +Sistemas informacionais sociais +=============================== + +Modelo "clássico" de hospedagem: arquitetura "cliente-servidor": + +<div class="centered" markdown="1"> +![Arquitetura cliente-servidor](http://code.google.com/edu/parallel/img/client-server.gif) +</div> + +Trabalho técnico informacional em grupos sociais +================================================ + +Características: + + - Considerado tecnicamente de alta dificuldade e dedicação. + + - Esforço para provisionamento, configuração e manutenção de sistemas. + + - Trabalho demorado: escala de meses para alcançar estabilidade. + + - Suscetível a muitas falhas: escala de horas para que um sistema seja inutilizado. + + - Pouco tempo disponível para o trabalho. + + - Dificuldade para a realização de backups e manutenção de procedimentos administrativos. + + - Baixa mobilização e força de trabalho "tarefeira". + + - Custa um bom dinheiro... + +Interlúdio: a destruição das redes +================================== + +![Redes centralizadas e descentralizadas](http://www.ibiblio.org/pioneers/images/centralized.gif) +![Rede distribuída](http://www.ibiblio.org/pioneers/images/distributed.gif) + +A cada evento catastrófico, vários grupos são prejudicados com danos à comunicação de difícil cicatrização. + +Parte 3: Contra-ataque infraestrutural +====================================== + +Como impedir que uma rede seja destruída mesmo que a remoção de nodos continue? + +A divisão em camadas +==================== + +Observação crucial: + + "Ghost in the shell": o disco e o hardware são intercambiáveis, + provisionamento pode ocorrer em múltiplas etapas. É possível + manter um estoque de discos pré-instalados e uma reserva financeira + para a aquisição de máquinas. Isso e backups permite a reconstrução + de sistemas. + +Conclusão imediata: + + É necessário "descolar" a camada de serviços (web, streaming, email, + etc) da camada infraestrutural (máquinas, conexões, etc): filtragem + de problemas físicos e jurídicos. + +A camada de serviços pode então ser "congelada" na forma de backups, enquanto que a camada infraestrutural não possui "alma" intrínseca, podendo ser reconfigurada quando necessário. Desse modo, várias máquinas podem ser mantidas no ar para aumentar a tolerância a falhas. + +Mas como um sítio pode estar simultaneamente em várias máquinas? + +DNS: colando domínios em máquinas +================================= + +![DNS](images/An_example_of_theoretical_DNS_recursion.png) +![Round Robin DNS](http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2s-round-robin.jpeg) + +O colamento/descolamento entre camadas é possível mediante mudanças de DNS. + +Proxies: distribuindo um sítio entre máquinas +============================================= + +<div class="centered" markdown="1"> +![App proxy](http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png) +</div> + +Aplicação descentralizada ou distribuída +======================================== + +<div class="centered" markdown="1"> +![ICE](http://upload.wikimedia.org/wikipedia/en/thumb/5/5a/ICEgrid.png/800px-ICEgrid.png) +</div> + +Tipos de camadas +================ + +Informação de um sistema é dividida conforme sua aplicabilidade: + + - Hardware: manifestações cristalizadas de informação: computadores. + + - Programas (software): pacotes. + + - Configuração (módulos). + + - Chaves e senhas. + + - Dados (o conteúdo propriamente dito). + +Tais camadas podem ser empacotadas em sistemas e tais sistemas podem ser agregados em outros sistemas (camadas de camadas de camadas): pode ser uma abstração complicada, mas o ganho conceitual em isolamento de instâncias é importante. + +Problemas +========= + +O discurso é bonito, porém... + + 1. Hardware é muito heterogêneo para padronizações serem efetivas. + + 2. Os programas são muito diversos para serem estudados, integrados e desenvolvidos. + + 3. Configurações são muito complexas e numerosas para serem facilmente separadas e replicadas de forma genérica. + + 4. São necessárias muitas senhas de boa complexidade, o que torna sua manutenção complicada. + + 5. Backups são difíceis de serem realizados e recuperados. + +Ou seja: o discurso da divisão em camadas é interessante, porém na realidade sua implementação enfrenta diversos problemas. Serão eles impeditivos? + +O Plano R* +========== + +![Rede](http://www.autistici.org/orangebook/slides/rete.png) +![Anéis](http://www.autistici.org/orangebook/slides/rings.png) + +O Plano R*: email +================= + +<div class="centered" markdown="1"> +![Sistema de email escalável](http://www.autistici.org/orangebook/slides/flussomail.png) +</div> + +Como é possível? +================ + +O segredo está na articulação da força de trabalho com a divisão de camadas. A regra geral é: + + 1. Utilização de ferramentas sólidas e amplamente utilizadas por comunidades de software livre e aberto. + 2. Trabalho de desenvolvimento focado na integração de soluções existentes, enviando alterações em código corrente acima sempre que possível. + 3. Desenvolvendo código próprio, porém livre, apenas quando não existente ou insuficiente nas comunidades. + +Cada um desdes tipos informacionais é distribuído em unidades que por sua vez são agregados em árvores: + + - Hardware em servidores (canalizadores de fluxos, nodos ou instâncias em nuvens). + - Programas em pacotes e distribuições. + - Configurações em módulos e repositórios. + - Chaves (que são unidades de segredo) em repositórios. + - Dados em árvore de backups. + +Divisão artefática +================== + +A divisão em camadas é artificial (artefática), porém com importantes consequências quando observada à luz da divisão do trabalho de comunidades de software livre e aberto: + + /'\ | + | \./ + upstream downstream + + - Hardware: desenvolvimento caro e complexo; hardware livre e aberto engatinhando; dependência do mercado. Exemplo: disco rígido. + - Programas e distribuições: grandes comunidades de desenvolvimento e uso. Exemplo: GNU/Linux, Debian. + - Configuração: comunidades mais restritas de desenvolvimento e uso. Exemplo: manuais, howtos, módulos. + - Chaves e senhas: restrita ao grupo responsável por manter uma dada infraestrutura. Exemplo: senha de superusuário/a. + - Dados: desenvolvidos pelas pessoas e grupos hospedados. Exemplo: texto num wiki. + +Divisão artefática - 2 +====================== + +É possível reconstruir um sistema dados esses elementos. A divisão do trabalho upstream/downstream é favorável à reconstrução, já que as tarefas se tornam mais complexas ao longo da subida da corrente onde usualmente os grandes grupos sociais se reúnem para solucioná-las. + +Economia de trabalho +==================== + +Assim, é possível economizar muita força de trabalho. + + 1. Enviar um desenvolvimento corrente acima (upstream) libera o grupo técnico de uma manutenção posterior, pois o trabalho passa a ser de responsabilidade da comunidades mais ampla. + + 2. Quanto mais específica for a informação, mais abaixo da corrente (downstream) ela deve ser mantida. + + 3. Naquilo que não houver desenvolvimento corrente acima, atuar como fonte (ou seja, agir como upstream) e fornecer para a comunidade. + +Tipos de salvaguarda +==================== + +Para todas as camadas divididas anteriormente é possível criar algum tipo de salvaguarda contra perdas: + + - Dinheiro: armazenamento e replicação de força de trabalho (potencial de trabalho armazenado). + + - Estoque: hardware hoje é commodity, podendo ser minimamente estocado ou mantido online em diversos locais. + + - Repositórios: programas, pacotes, distribuições e configurações. + + - Backups: manutenção de dados ou coisas sobressalentes. + +Parte 3: contexto brasileiro +============================ + +Orçamento e infraestrutura +========================== + +Custos: + + - Plano R*: EUR 10.000 anuais. + - No Brasil, é praticamente a despesa anual de um centro social alugado e muito mais do que a receita da maioria dos grupos. + +Conexão: + + - Nos EUA e na Europa, a conexão é rápida e barata. Datacenters corporativos são acessíveis. + - No Brasil, a conexão é lenta, cara e o preço dos datacenters é exorbitante. + +Repressão: + + - Criminalização dos movimentos sociais (entulho jurídico). + - Polícia violenta. + +Estaremos impossibilitados/as de mantermos servidores no país? + +Por outro lado +============== + + - A legislação, a jurisprudência, cultura e valores brasileiros são muito mais favoráveis à preservação da privacidade que nos EUA ou na Europa (fator Dantas). + + - Honorários advocatícios não são tão altos quanto no exterior (?). + + - O câmbio é favorável a doações internacionais. + +O caso Satangoss +================ + +"O que demorou quatro anos para juntarmos nos foi arrebatado num único dia." + + - Agosto de 2008: polícia civil apreende o servidor do Saravá sem mandado judicial. + + - Mais de cem sítios fora do ar. + + - Não havia backup remoto e nem medidas de contingência estabelecidas. + + - Todos os ovos estavam na mesma cesta. + + - Grande desmobilização. + + - Análise do caso: http://www.sarava.org/node/44 + +Como reverter a crise num novo ciclo de mudança e amadurecimento? + +Parte 4: O Processo Hidra +========================= + +<div class="centered" markdown="1"> +![Regeneração](http://f.i.uol.com.br/folha/ciencia/images/0825246.jpg) +</div> + +Regeneração +=========== + +Hidra: toda célula pode ter o germe da própria organização. Múltiplas cabeças, células tronco que podem adquirir especialização conforme a necessidade. + +<div class="centered" markdown="1"> +![Regeneração da hidra](http://image.wistatutor.com/content/growth-regeneration-ageing/regeneration-hydra.jpeg) +</div> + +Hidra em processo +================= + +<div class="centered" markdown="1"> +![Regeneração da Hidra](http://www.uni-kiel.de/zoologie/bosch/jpg/bosch_fig2.jpg) +</div> + +Hidra em processo - 2 +===================== + +<div class="centered" markdown="1"> +![Regeneração da Hidra](http://www.uni-kiel.de/zoologie/bosch/jpg/bosch_fig3.jpg) +</div> + +%% Hidra em processo - 3 +%% ===================== +%% +%%![Regeneração da Hidra](http://odelberglab.genetics.utah.edu/images/HydraRgn-web.jpg) +%% +%%Fonte: http://odelberglab.genetics.utah.edu/regen_mech.htm + +%% Arredondamento de aglomerados celulares: +%% ======================================== +%% +%% http://hal.archives-ouvertes.fr/docs/00/02/92/51/PDF/rounding_revised.pdf + +Topologias +========== + + "[To] keep our sources safe, we have had to spread assets, encrypt everything, + and move telecommunications and people around the world to activate protective + laws in different national jurisdictions," Mr Assange said told the BBC earlier + this year. + +Fonte: [http://www.bbc.co.uk/news/world-11047811](http://www.bbc.co.uk/news/world-11047811) + +Possíveis montagens: anel, estrela, rizomática, etc. Frontends e backends. + +Parte 5: O Processo Hidra Saravento +=================================== + + 1. Apresenta Padrão Saravá (Sarava Pattern, [http://padrao.sarava.org](http://padrao.sarava.org)). + + 2. Utiliza Resource Sharing Protocol (RSP, [http://rsp.sarava.org](http://rsp.sarava.org)). + + 3. Considerando a adoção de padrões definidos de política de segurança e privacidade. + + 4. Organiza-se de acordo com protocolos ([http://protocolos.sarava.org](http://protocolos.sarava.org)). + +Na Hidra Saraventa, cada célula é chamada de "nodo": + + - Nodos físicos com servidores virtuais com fins específicos. + + - Nodos virtuais em diversos locais (inclusive hospedados por terceiros). + +Baseada no seguinte pricípio: quais problemas solucionaremos, quais não. + +O Padrão Saravá +=============== + +O Padrão Saravá é uma sistematização de configuração de servidores, gerenciadores de conteúdo e aplicações diversas usados pelo Grupo Saravá. O padrão foi desenvolvido para: + + - Ter controle dos pacotes utilizados, arquivos de configuração e serviços em uso. + + - Uniformidade de administração. + + - Sistema de gerenciamento de backups comum para que as máquinas de um projeto possam trocar dados. + + - Que um servidor seja configurado apenas uma vez e que suas configurações possam ser aproveitados para outras máquinas. + + - Que sites e serviços sejam armazenados de maneira regular para facilitar atualizações e migrações. + + - Manter projetos e serviços isolados uns dos outros através de servidores virtuais. + + - Tornar a instalação dos servidores facilmente replicável. + +Dinâmica de desenvolvimento: + + Documentação wiki -> Configurações pré-gravadas -> Software + +Puppet +====== + +![Puppet: topologia](http://docs.reductivelabs.com/images/Puppet_Star.png) +![Puppet: diagrama de sistema](http://www.puppetlabs.com/images/system_diagram.png) + +Puppet: compartilhando configuração +=================================== + +Código puppet: + + file { '/etc/passwd': + owner => root, + group => root, + mode => 644, + } + +Módulos compartilhados: + + - [http://git.sarava.org](http://git.sarava.org) + + - [https://labs.riseup.net/code/projects/sharedpuppetmodules](https://labs.riseup.net/code/projects/sharedpuppetmodules) + +Git e gitosis +============= + +![VCS](http://hoth.entp.com/output/scm.png) +![VCS distribuído](http://hoth.entp.com/output/dscm.png) + +O Protocolo de Compartilhamento de Recursos +=========================================== + + "The Resource Sharing Protocol (RSP) is a set of metadata intended to help free + software groups + + * Share their available resources and also Find groups that can host + * services for them given their needs and requirements. + + The RSP splits each resource in a layer or set of service layers. You can think + of service layers something very general, ranging from servers, databases, + websites. If you need to, you can even consider stuff such as tables and + bicycles as layers that provide some kind of service to a hosted group. ;)" + + -- http://rsp.sarava.org + +Orquestração +============ + +Para complementar a Configuração de sistemas padronizada e centralizada, procedimentos como + + 1. Atualização de pacotes. + 2. Atualização de código de gerenciadores de conteúdo. + 3. Carga de bancos de dados. + +podem ser codificados de forma a serem facilmente aplicados a múltiplas camadas de forma simultânea. + +Exemplos: + + - [https://git.sarava.org/?p=hydra.git;a=summary](https://git.sarava.org/?p=hydra.git;a=summary) + - [http://www.capify.org](http://www.capify.org) + - [http://marionette-collective.org](http://marionette-collective.org) + - [https://fedorahosted.org/func](https://fedorahosted.org/func) + - [http://fabfile.org](http://fabfile.org) + - [http://www.debian-administration.org/article/Automating_ssh_and_scp_across_multiple_hosts](http://www.debian-administration.org/article/Automating_ssh_and_scp_across_multiple_hosts) + +Ikiwiki +======= + +O Ikiwiki ([http://ikiwiki.info](http://ikiwiki.info)) é um software de wiki que usa um sistema de controle de versão e arquivos de texto, possibilitando: + + 1. A existência de múltiplas cópias integrais do wiki (online e offline). + 2. Desenvolvimento distribuído de documentação. + +O ikiwiki é muito útil para reunir documentação de sistemas, já que não necessita de nenhum sistema web funcional para abrigá-la. + +Virtualização +============= + +Virtualização através de Linux-VServer (existem outras implementações possíveis): + + - [http://www.linux-vserver.org](http://www.linux-vserver.org) + - [http://slack.sarava.org/vservers](http://slack.sarava.org/vservers) + +Principais vantagens: + + - Permite diversos grupos compartilharem uma mesma máquina presevando sua autonomia. + + - Grupos podem hospedar mutuamente instâncias virtuais. Exemplo: se existem 5 grupos com uma máquina cada um, se cada um deles hospedar um vserver para cada grupo, teremos 4 locais remotos de hospedagem por grupo, aumentando assim as possibilidades de salvaguarda e escalabilidade. + +Keyringer e monkeysphere +======================== + +O Keyringer ([http://git.sarava.org/?p=keyringer.git;a=summary](http://git.sarava.org/?p=keyringer.git;a=summary)) é um repositório distribuído de senhas/chaves baseado em GPG e git. + +O monkeysphere ([http://web.monkeysphere.info](http://web.monkeysphere.info)) é um programa que permite a verificação de hosts SSH e usuários/as através da Teia de Confiabilidade do OpenPGP. Com ele, o gerenciamento de fingerprints fica mais fácil e evita que páginas como esta centralizem informações que possam se desatualizar. + +Tecnologia bootless +=================== + +Muitos esquemas de criptografia em disco se baseiam na proteção das partições de dadados e da área de troca, porém dependem da existência de ao menos uma partição de inicialização com as imagens do sistema e de um setor de inicialização. + +Com acesso físico à máquina, é possível infectar tais dados de inicialização e comprometer a criptografia de todo o sistema. + +Para mitigar a situação, o esquema Bootless é um repositório git que contém as imagens de inicialização e a configuração necessárias para o procedimento de partida. + +Assim, é possível manter a parte de inicialização fora da máquina, por exemplo em chaveiros USB. + +Projeto similar: [http://lfde.org](http://lfde.org) + +Monitoramento: nagios +===================== + +<div class="centered" markdown="1"> +![Nagios](http://nagios.sourceforge.net/images/screens/new/statusmap-circular.png) +</div> + +Monitoramento: munin +==================== + +<div class="centered" markdown="1"> +![Munin](http://upload.wikimedia.org/wikipedia/commons/c/ce/Munin-memory-week.png) +</div> + +%%![Munin: icecast](http://static.k5-storitve.net/site_media/images/plugins/262-1215526146-icecast2.png) +%%Fonte: [http://exchange.munin-monitoring.org/plugins/icecast2/details](http://exchange.munin-monitoring.org/plugins/icecast2/details) + +Backups +======= + +Estratégia: + + 1. Backups locais criptografados com duplicity: + - Incluindo apenas `/etc`, `/var`, `/home`. + - Excluindo logs, cache e backups remotos. + 2. Backups remotos apenas do backup local em duplicity, via rdiff ou rsync. + 3. Nodos designados para armazenamento de backups. + 4. Incrementos locais e remotos para aumentar consistência dos dados. + 5. Procedimento integrado de restore e ativação de nodo. + +Hardware e custos +================= + + - Servidor mini-ITX Atom dual core + 2GB RAM + 1TB: R$680.00. + - Nobreaks APC: +/- R$500,00. + - Banda larga ADSL/cabo: R$80,00 a R$200,00. + - Energia: 180W (mini-ITX) máx. + - Sistema pode ser instalado inclusive em memórias de estado sólido (microSD por exemplo). + +<div class="centered" markdown="1"> +![Mini ITX](http://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Mini-itx-motherboard.jpg/800px-Mini-itx-motherboard.jpg) +</div> + +Utilidades: adaptador para discos +================================= + +<div class="centered" markdown="1"> +![Adaptador SATA](http://www.sataadapter.com/sata-to-usb-adapter-cable-for-windows-and-mac.jpg) +</div> + +Utilidades: chave de entropia +============================= + +![Entropy key](http://www.entropykey.co.uk/res/device.jpeg) +![Entropy graph](http://www.entropykey.co.uk/res/entropy-trite-small-nq8.png) + +Segurança +========= + +Acesso remoto: + + - Contas SSH administrativas em todos os nodos. + + - Contas SSH de backup para nodos de backup. + + - Contas SSH de tunelamento para nodos diversos. + +Análise: + + 1. É importante isolar o máximo a capacidade de acesso para contas de nodos de backup ou que tunelem conexões. + + 2. Administradores/as precisam ter boas medidas de segurança: + - Pasta criptografada. + - Senhas e chaves seguras. + +Protocolos sociais +================== + + - Protocolo de Ação Coletiva: [http://protocolos.sarava.org](http://protocolos.sarava.org). + - Outros protocolos e metodologias (contabilidade, acesso à informação, relação com grupos, etc). + - Uso de um sistema de gestão de processos (trac ou similar). + + .------------------->-----------------. + / .----------<--------------<-------. \ + | ' \ \ + | | .------>-----. \ \ + | | | \ \ \ + Proposta -----> Discussão ->--. \ \ \ + | ^ | \ \ \ \ + | | | \ \ \ \ + | `----<-----' | \ \ \ + | | | \ \ + `------>------ Decisão --<--' | \ \ + | | | \ \ + | | | | | + Atribuição de --<---' '---> Arquivamento --->---' ; + Responsabilidades ----->-------' ^ \ / + ^ | ___________/ `---<-----' + | \ .' + | `--> Realização -->--. + | | | \ + | | | / + `----<-----' `-----<---' + +Resumo: Estratégia de gestão +============================ + + - Facilitar instalação, manutenção e gestão de dados. + + - Manter backups em máquinas prontas para serem inicializadas. + + - Manter nodos master prontos para assumirem o posto de "cabeça ativa". + +Parte 6: A Confederação das Hidras Unidas +========================================= + +<div class="centered" markdown="1"> +![Hidra Cluster](http://apod.nasa.gov/apod/image/0104/hydra_aat116.jpg) +</div> + +A Confederação das Hidras Unidas +================================ + + - Hidra é um processo, não uma tecnologia, implementação, sistema ou serviço. + + - Assim, é possível ter hidras menos sistematizadas e com diferentes formas de organização. O processo já ocorre em vários locais. + + - Havendo várias hidras, se elas se integram passa a existir a Confederação das Hidras Unidas. + + - Importante questão do licenciamento: AGPL 3.0 para garantir o máximo possível da disponibilização de código e documentação. + + - Não é estritamente necessária a criação de uma "confederação", já que a cultura de hidras pode ser não-coordenada. + +Parte 7: Nuvens e Hidras +======================== + +Hidras são nuvens (cloud computing)? + + - Cloud computing foca apenas nas instâncias e como estas são integradas por aplicações (IaaS, SaaS, PaaS) e no seu uso sob demanda. + + - Cloud computing é uma iniciativa do mercado e uma tendência à terceirização total das atividades. + + - A Hidra leva em consideração a organização social que suporta a infraestrutura computacional. + + - A Hidra é uma nuvem na qual certos nodos desempenham papéis determinados, porém contendo o germe de toda a organização. + + - Outra classe de nuvens: botnets. + +Nuvens: diagramas +================= + +![Camadas](http://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cloud_Computing_Stack.svg/340px-Cloud_Computing_Stack.svg.png) +![Arquitetura](http://upload.wikimedia.org/wikipedia/commons/thumb/7/79/CloudComputingSampleArchitecture.svg/550px-CloudComputingSampleArchitecture.svg.png) + +Tipos de nuvens +=============== + +<div class="centered" markdown="1"> +![Tipos de nuvens](http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Cloud_computing_types.svg/800px-Cloud_computing_types.svg.png) +</div> + +Parte 8: Futuro +=============== + + - Hidra Saraventa: ainda em intenso desenvolvimento, porém já em estágio maduro. Falta (em agosto/2010): + - Melhoria no procedimento de bootstrap. + - Integração com DNS. + - Sistema de proxy para balanceamento de carga. + - Melhoria de procedimentos de sunsetting de sítios, plataformas e contas. + - Longuíssimo prazo, caso realizável: possibilidade de um nodo ser convertido de uma classe para outra. + - Procedimentos para suporte jurídico. + - Nodos em conexões DSL e cabo: IP dinâmico, DNS reverso, etc. + - VPN entre os nodos, Puppet Dashboard?, External node tool? + - Migrar para Linux Containers (lxc). + - Melhoria da documentação e representações gráficas do processo. + - Storage de dados distribuído. + - Hidras via Rádio. + - Hidras em outros tipos de organizações sociais. + +Parte 9: Conclusões +=================== + + - Resolver a replicação e escalabilidade primeiro na infraestrutura (máquinas, configurações e backups), depois nas camadas superiores (CMSs, por exemplo) + + - Não importa tanto se a rede é centralizada, descentralizada ou distribuída se antes de tudo ela for regenerativa. No entanto, em geral são as redes distribuídas e descentralizadas que possuem fatores de regeneração maiores do que no caso centralizado. + + - Número grande de máquinas é interessante: várias podem estar sem funcionar num dado momento, mas as que estiverem funcionando podem dar conta da demanda. + + - A hidra é indestrutível? Essa questão faz sentido? Positivismo, revoluções e cataclismas: o limite da hidra por ter uma relação e abertura e fechamento (autonomia dependente). + +Parte 10: Referências +===================== + +Referências: imagens usadas +=========================== + + - [http://en.wikipedia.org/wiki/File:Hydra\_04.jpg](http://en.wikipedia.org/wiki/File:Hydra_04.jpg) + - [http://en.wikipedia.org/wiki/File:Hydra001.jpg](http://en.wikipedia.org/wiki/File:Hydra001.jpg) + - [http://code.google.com/edu/parallel/dsd-tutorial.html](http://code.google.com/edu/parallel/dsd-tutorial.html) + - [http://en.wikipedia.org/wiki/File:DNS_in_the_real_world.svg](http://en.wikipedia.org/wiki/File:DNS_in_the_real_world.svg) + - [http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2sfarm.html](http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2sfarm.html) + - [http://www.autistici.org/orangebook/slides/orangebook.en.html](http://www.autistici.org/orangebook/slides/orangebook.en.html). + - [http://www.autistici.org/orangebook/slides/orangebook.en.html](http://www.autistici.org/orangebook/slides/orangebook.en.html) + - [http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png](http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png) + - [http://en.wikipedia.org/wiki/File:ICEgrid.png](http://en.wikipedia.org/wiki/File:ICEgrid.png) + - [http://www.ibiblio.org/pioneers/baran.html](http://www.ibiblio.org/pioneers/baran.html) + - [http://www1.folha.uol.com.br/folha/ciencia/ult306u442499.shtml](http://www1.folha.uol.com.br/folha/ciencia/ult306u442499.shtml) + - [http://www.tutorvista.com/content/biology/biology-iv/growth-regeneration-ageing/regeneration.php](http://www.tutorvista.com/content/biology/biology-iv/growth-regeneration-ageing/regeneration.php) + - [http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html](http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html) + - [http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html](http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html) + - [http://www.puppetlabs.com/puppet/introduction](http://www.puppetlabs.com/puppet/introduction) + - [http://docs.reductivelabs.com/guides/introduction.html](http://docs.reductivelabs.com/guides/introduction.html) + - [http://www.nagios.org/about/screenshots](http://www.nagios.org/about/screenshots) + - [http://en.wikipedia.org/wiki/File:Munin-memory-week.png](http://en.wikipedia.org/wiki/File:Munin-memory-week.png) + - [http://hoth.entp.com/output/git_for_designers.html](http://hoth.entp.com/output/git_for_designers.html) + - [http://en.wikipedia.org/wiki/Mini-itx](http://en.wikipedia.org/wiki/Mini-itx) + - [http://www.sataadapter.com](http://www.sataadapter.com) + - [http://www.entropykey.co.uk](http://www.entropykey.co.uk) + - [http://apod.nasa.gov/apod/ap010416.html](http://apod.nasa.gov/apod/ap010416.html) + - [http://en.wikipedia.org/wiki/File:Cloud_Computing_Stack.svg](http://en.wikipedia.org/wiki/File:Cloud_Computing_Stack.svg) + - [http://en.wikipedia.org/wiki/File:CloudComputingSampleArchitecture.svg](http://en.wikipedia.org/wiki/File:CloudComputingSampleArchitecture.svg) + - [http://en.wikipedia.org/wiki/File:Cloud_computing_types.svg](http://en.wikipedia.org/wiki/File:Cloud_computing_types.svg) diff --git a/doc/hidra.pdf.html b/doc/hidra.pdf.html new file mode 100644 index 0000000..7c5da53 --- /dev/null +++ b/doc/hidra.pdf.html @@ -0,0 +1,989 @@ +<!DOCTYPE html> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <title>O Processo Hidra</title> + + + +<style> +html, body { margin: 0; padding: 0; } + +body { font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; } + +a:link, a:visited { color: black; } + +h1 { font-size: 30pt; } +h2 { font-size: 28pt; } +h3 { font-size: 25pt; } +p, li, dt, dd, td, th { font-size: 18pt; } + +pre { font-size: 14pt; } +pre.small { font-size: 11pt; } + +pre.code { + background-color: azure; + padding: 5px; + } + +ul { list-style-type: square; } + +.center { text-align: center; } + +.slide { page-break-after: always; + min-height: 100mm; + padding: 40px; + + border: 1px dotted black; + +/* + background: -moz-linear-gradient( top, maroon, red); +*/ + } + + +body { + font-family: monospace; +} + +.centered img { + display: block; + margin-left: auto; + margin-right: auto; +} + +.centered { + text-align: center; +} + +p, li, dt, dd, td, th { + font-size: 16pt; +} + +.slide h1 { + font-size: 25pt; +} + + + +/* +for princexml (CSS3 paged media support) +@page { size: A4 landscape } +*/ +</style> + +</head> +<body> + +<div class="presentation"> + +<div class='slide centered'> + +<!-- _S9SLIDE_ centered --> + +<p><img src="hidra-oil.png" alt="O Processo Hidra" /></p> + + +</div> +<div class='slide '> +<h1 id="o-processo-hidra">O Processo Hidra</h1><div class="centered"> + <p><img src="hidra-oil.png" alt="O Processo Hidra" /></p> + + <p>De relógios a nuvens, de nuvens a hidras.</p> +</div> + + +</div> +<div class='slide '> +<h1 id="parte-1-introduo">Parte 1: Introdução</h1></div> +<div class='slide '> +<h1 id="objetivo-da-apresentao">Objetivo da apresentação</h1><p>O objetivo desta fala é divulgar os estudos em andamento sobre o processo hidra dando espaço para possíveis andamentos:</p> + +<ol> + <li> + <p>Informar os grupos e pessoas que possuem conteúdo hospedado em infraestruturas tecno-sociais comuns sobre o trabalho desenvolvido.</p> + </li> + <li> + <p>Encorajar grupos técnicos existentes para adotarem procedimentos que favoreçam suas infraestruturas a terem comportamento hidra.</p> + </li> +</ol> + +<p>Esta apresentação ainda está em processo de concepção e revisão e por isso não está sendo divulgada.</p> + + +</div> +<div class='slide '> +<h1 id="o-que--uma-hidra">O que é uma Hidra?</h1></div> +<div class='slide '> +<h1 id="ser-mitolgico-de-mltiplas-cabeas-regenerativas-destrudo-por-hrcules">Ser mitológico de múltiplas cabeças regenerativas, destruído por Hércules</h1><div class="centered"> + <p><img src="images/Hydra_04.jpg" alt="Hidra mitológica" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="na-biologia-moderna-animal-aqutico-que-possui-capacidades-regenerativas">Na biologia moderna, animal aquático que possui capacidades regenerativas</h1><div class="centered"> + <p><img src="images/Hydra001.jpg" alt="Hida biológica" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="o-que--o-processo-hidra">O que é o Processo Hidra?</h1><p>O Processo Hidra é uma descrição de infraestruturas tecno-sociais que apresentam:</p> + +<ol> + <li> + <p>Replicabilidade e escalabilidade.</p> + </li> + <li> + <p>Capacidade de combinação rizomática.</p> + </li> + <li> + <p>Regeneração e reagrupamento após eventos catastróficos.</p> + </li> +</ol> + +<p>A Hidra moderna pode resistir a Hércules.</p> + + +</div> +<div class='slide '> +<h1 id="parte-2-grupos-tcnicos-sociais">Parte 2: Grupos Técnicos Sociais</h1><p>Mas antes façamos uma retrospectiva…</p> + + +</div> +<div class='slide '> +<h1 id="sistemas-informacionais-sociais">Sistemas informacionais sociais</h1><p>Modelo “clássico” de hospedagem: arquitetura “cliente-servidor”:</p> + +<div class="centered"> + <p><img src="http://code.google.com/edu/parallel/img/client-server.gif" alt="Arquitetura cliente-servidor" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="trabalho-tcnico-informacional-em-grupos-sociais">Trabalho técnico informacional em grupos sociais</h1><p>Características:</p> + +<ul> + <li> + <p>Considerado tecnicamente de alta dificuldade e dedicação.</p> + </li> + <li> + <p>Esforço para provisionamento, configuração e manutenção de sistemas.</p> + </li> + <li> + <p>Trabalho demorado: escala de meses para alcançar estabilidade.</p> + </li> + <li> + <p>Suscetível a muitas falhas: escala de horas para que um sistema seja inutilizado.</p> + </li> + <li> + <p>Pouco tempo disponível para o trabalho.</p> + </li> + <li> + <p>Dificuldade para a realização de backups e manutenção de procedimentos administrativos.</p> + </li> + <li> + <p>Baixa mobilização e força de trabalho “tarefeira”.</p> + </li> + <li> + <p>Custa um bom dinheiro…</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="interldio-a-destruio-das-redes">Interlúdio: a destruição das redes</h1><p><img src="http://www.ibiblio.org/pioneers/images/centralized.gif" alt="Redes centralizadas e descentralizadas" /> +<img src="http://www.ibiblio.org/pioneers/images/distributed.gif" alt="Rede distribuída" /></p> + +<p>A cada evento catastrófico, vários grupos são prejudicados com danos à comunicação de difícil cicatrização.</p> + + +</div> +<div class='slide '> +<h1 id="parte-3-contra-ataque-infraestrutural">Parte 3: Contra-ataque infraestrutural</h1><p>Como impedir que uma rede seja destruída mesmo que a remoção de nodos continue?</p> + + +</div> +<div class='slide '> +<h1 id="a-diviso-em-camadas">A divisão em camadas</h1><p>Observação crucial:</p> + +<pre><code>"Ghost in the shell": o disco e o hardware são intercambiáveis, + provisionamento pode ocorrer em múltiplas etapas. É possível + manter um estoque de discos pré-instalados e uma reserva financeira + para a aquisição de máquinas. Isso e backups permite a reconstrução + de sistemas. +</code></pre> + +<p>Conclusão imediata:</p> + +<pre><code>É necessário "descolar" a camada de serviços (web, streaming, email, +etc) da camada infraestrutural (máquinas, conexões, etc): filtragem +de problemas físicos e jurídicos. +</code></pre> + +<p>A camada de serviços pode então ser “congelada” na forma de backups, enquanto que a camada infraestrutural não possui “alma” intrínseca, podendo ser reconfigurada quando necessário. Desse modo, várias máquinas podem ser mantidas no ar para aumentar a tolerância a falhas.</p> + +<p>Mas como um sítio pode estar simultaneamente em várias máquinas?</p> + + +</div> +<div class='slide '> +<h1 id="dns-colando-domnios-em-mquinas">DNS: colando domínios em máquinas</h1><p><img src="images/An_example_of_theoretical_DNS_recursion.png" alt="DNS" /> +<img src="http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2s-round-robin.jpeg" alt="Round Robin DNS" /></p> + +<p>O colamento/descolamento entre camadas é possível mediante mudanças de DNS.</p> + + +</div> +<div class='slide '> +<h1 id="proxies-distribuindo-um-stio-entre-mquinas">Proxies: distribuindo um sítio entre máquinas</h1><div class="centered"> + <p><img src="http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png" alt="App proxy" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="aplicao-descentralizada-ou-distribuda">Aplicação descentralizada ou distribuída</h1><div class="centered"> + <p><img src="http://upload.wikimedia.org/wikipedia/en/thumb/5/5a/ICEgrid.png/800px-ICEgrid.png" alt="ICE" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="tipos-de-camadas">Tipos de camadas</h1><p>Informação de um sistema é dividida conforme sua aplicabilidade:</p> + +<ul> + <li> + <p>Hardware: manifestações cristalizadas de informação: computadores.</p> + </li> + <li> + <p>Programas (software): pacotes.</p> + </li> + <li> + <p>Configuração (módulos).</p> + </li> + <li> + <p>Chaves e senhas.</p> + </li> + <li> + <p>Dados (o conteúdo propriamente dito).</p> + </li> +</ul> + +<p>Tais camadas podem ser empacotadas em sistemas e tais sistemas podem ser agregados em outros sistemas (camadas de camadas de camadas): pode ser uma abstração complicada, mas o ganho conceitual em isolamento de instâncias é importante.</p> + + +</div> +<div class='slide '> +<h1 id="problemas">Problemas</h1><p>O discurso é bonito, porém…</p> + +<ol> + <li> + <p>Hardware é muito heterogêneo para padronizações serem efetivas.</p> + </li> + <li> + <p>Os programas são muito diversos para serem estudados, integrados e desenvolvidos.</p> + </li> + <li> + <p>Configurações são muito complexas e numerosas para serem facilmente separadas e replicadas de forma genérica.</p> + </li> + <li> + <p>São necessárias muitas senhas de boa complexidade, o que torna sua manutenção complicada.</p> + </li> + <li> + <p>Backups são difíceis de serem realizados e recuperados.</p> + </li> +</ol> + +<p>Ou seja: o discurso da divisão em camadas é interessante, porém na realidade sua implementação enfrenta diversos problemas. Serão eles impeditivos?</p> + + +</div> +<div class='slide '> +<h1 id="o-plano-r">O Plano R*</h1><p><img src="http://www.autistici.org/orangebook/slides/rete.png" alt="Rede" /> +<img src="http://www.autistici.org/orangebook/slides/rings.png" alt="Anéis" /></p> + + +</div> +<div class='slide '> +<h1 id="o-plano-r-email">O Plano R*: email</h1><div class="centered"> + <p><img src="http://www.autistici.org/orangebook/slides/flussomail.png" alt="Sistema de email escalável" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="como--possvel">Como é possível?</h1><p>O segredo está na articulação da força de trabalho com a divisão de camadas. A regra geral é:</p> + +<ol> + <li>Utilização de ferramentas sólidas e amplamente utilizadas por comunidades de software livre e aberto.</li> + <li>Trabalho de desenvolvimento focado na integração de soluções existentes, enviando alterações em código corrente acima sempre que possível.</li> + <li>Desenvolvendo código próprio, porém livre, apenas quando não existente ou insuficiente nas comunidades.</li> +</ol> + +<p>Cada um desdes tipos informacionais é distribuído em unidades que por sua vez são agregados em árvores:</p> + +<ul> + <li>Hardware em servidores (canalizadores de fluxos, nodos ou instâncias em nuvens).</li> + <li>Programas em pacotes e distribuições.</li> + <li>Configurações em módulos e repositórios.</li> + <li>Chaves (que são unidades de segredo) em repositórios.</li> + <li>Dados em árvore de backups.</li> +</ul> + + +</div> +<div class='slide '> +<h1 id="diviso-arteftica">Divisão artefática</h1><p>A divisão em camadas é artificial (artefática), porém com importantes consequências quando observada à luz da divisão do trabalho de comunidades de software livre e aberto:</p> + +<pre><code> /'\ | + | \./ +upstream downstream +</code></pre> + +<ul> + <li>Hardware: desenvolvimento caro e complexo; hardware livre e aberto engatinhando; dependência do mercado. Exemplo: disco rígido.</li> + <li>Programas e distribuições: grandes comunidades de desenvolvimento e uso. Exemplo: GNU/Linux, Debian.</li> + <li>Configuração: comunidades mais restritas de desenvolvimento e uso. Exemplo: manuais, howtos, módulos.</li> + <li>Chaves e senhas: restrita ao grupo responsável por manter uma dada infraestrutura. Exemplo: senha de superusuário/a.</li> + <li>Dados: desenvolvidos pelas pessoas e grupos hospedados. Exemplo: texto num wiki. </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="diviso-arteftica---2">Divisão artefática - 2</h1><p>É possível reconstruir um sistema dados esses elementos. A divisão do trabalho upstream/downstream é favorável à reconstrução, já que as tarefas se tornam mais complexas ao longo da subida da corrente onde usualmente os grandes grupos sociais se reúnem para solucioná-las.</p> + + +</div> +<div class='slide '> +<h1 id="economia-de-trabalho">Economia de trabalho</h1><p>Assim, é possível economizar muita força de trabalho.</p> + +<ol> + <li> + <p>Enviar um desenvolvimento corrente acima (upstream) libera o grupo técnico de uma manutenção posterior, pois o trabalho passa a ser de responsabilidade da comunidades mais ampla.</p> + </li> + <li> + <p>Quanto mais específica for a informação, mais abaixo da corrente (downstream) ela deve ser mantida.</p> + </li> + <li> + <p>Naquilo que não houver desenvolvimento corrente acima, atuar como fonte (ou seja, agir como upstream) e fornecer para a comunidade.</p> + </li> +</ol> + + +</div> +<div class='slide '> +<h1 id="tipos-de-salvaguarda">Tipos de salvaguarda</h1><p>Para todas as camadas divididas anteriormente é possível criar algum tipo de salvaguarda contra perdas:</p> + +<ul> + <li> + <p>Dinheiro: armazenamento e replicação de força de trabalho (potencial de trabalho armazenado).</p> + </li> + <li> + <p>Estoque: hardware hoje é commodity, podendo ser minimamente estocado ou mantido online em diversos locais.</p> + </li> + <li> + <p>Repositórios: programas, pacotes, distribuições e configurações.</p> + </li> + <li> + <p>Backups: manutenção de dados ou coisas sobressalentes.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-3-contexto-brasileiro">Parte 3: contexto brasileiro</h1></div> +<div class='slide '> +<h1 id="oramento-e-infraestrutura">Orçamento e infraestrutura</h1><p>Custos:</p> + +<ul> + <li>Plano R*: EUR 10.000 anuais.</li> + <li>No Brasil, é praticamente a despesa anual de um centro social alugado e muito mais do que a receita da maioria dos grupos.</li> +</ul> + +<p>Conexão:</p> + +<ul> + <li>Nos EUA e na Europa, a conexão é rápida e barata. Datacenters corporativos são acessíveis.</li> + <li>No Brasil, a conexão é lenta, cara e o preço dos datacenters é exorbitante.</li> +</ul> + +<p>Repressão:</p> + +<ul> + <li>Criminalização dos movimentos sociais (entulho jurídico).</li> + <li>Polícia violenta.</li> +</ul> + +<p>Estaremos impossibilitados/as de mantermos servidores no país?</p> + + +</div> +<div class='slide '> +<h1 id="por-outro-lado">Por outro lado</h1><ul> + <li> + <p>A legislação, a jurisprudência, cultura e valores brasileiros são muito mais favoráveis à preservação da privacidade que nos EUA ou na Europa (fator Dantas).</p> + </li> + <li> + <p>Honorários advocatícios não são tão altos quanto no exterior (?).</p> + </li> + <li> + <p>O câmbio é favorável a doações internacionais.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="o-caso-satangoss">O caso Satangoss</h1><p>“O que demorou quatro anos para juntarmos nos foi arrebatado num único dia.”</p> + +<ul> + <li> + <p>Agosto de 2008: polícia civil apreende o servidor do Saravá sem mandado judicial.</p> + </li> + <li> + <p>Mais de cem sítios fora do ar.</p> + </li> + <li> + <p>Não havia backup remoto e nem medidas de contingência estabelecidas.</p> + </li> + <li> + <p>Todos os ovos estavam na mesma cesta.</p> + </li> + <li> + <p>Grande desmobilização.</p> + </li> + <li> + <p>Análise do caso: http://www.sarava.org/node/44</p> + </li> +</ul> + +<p>Como reverter a crise num novo ciclo de mudança e amadurecimento?</p> + + +</div> +<div class='slide '> +<h1 id="parte-4-o-processo-hidra">Parte 4: O Processo Hidra</h1><div class="centered"> + <p><img src="http://f.i.uol.com.br/folha/ciencia/images/0825246.jpg" alt="Regeneração" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="regenerao">Regeneração</h1><p>Hidra: toda célula pode ter o germe da própria organização. Múltiplas cabeças, células tronco que podem adquirir especialização conforme a necessidade.</p> + +<div class="centered"> + <p><img src="http://image.wistatutor.com/content/growth-regeneration-ageing/regeneration-hydra.jpeg" alt="Regeneração da hidra" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="hidra-em-processo">Hidra em processo</h1><div class="centered"> + <p><img src="http://www.uni-kiel.de/zoologie/bosch/jpg/bosch_fig2.jpg" alt="Regeneração da Hidra" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="hidra-em-processo---2">Hidra em processo - 2</h1><div class="centered"> + <p><img src="http://www.uni-kiel.de/zoologie/bosch/jpg/bosch_fig3.jpg" alt="Regeneração da Hidra" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="topologias">Topologias</h1><pre><code>"[To] keep our sources safe, we have had to spread assets, encrypt everything, +and move telecommunications and people around the world to activate protective +laws in different national jurisdictions," Mr Assange said told the BBC earlier +this year. +</code></pre> + +<p>Fonte: <a href="http://www.bbc.co.uk/news/world-11047811">http://www.bbc.co.uk/news/world-11047811</a></p> + +<p>Possíveis montagens: anel, estrela, rizomática, etc. Frontends e backends.</p> + + +</div> +<div class='slide '> +<h1 id="parte-5-o-processo-hidra-saravento">Parte 5: O Processo Hidra Saravento</h1><ol> + <li> + <p>Apresenta Padrão Saravá (Sarava Pattern, <a href="http://padrao.sarava.org">http://padrao.sarava.org</a>).</p> + </li> + <li> + <p>Utiliza Resource Sharing Protocol (RSP, <a href="http://rsp.sarava.org">http://rsp.sarava.org</a>).</p> + </li> + <li> + <p>Considerando a adoção de padrões definidos de política de segurança e privacidade.</p> + </li> + <li> + <p>Organiza-se de acordo com protocolos (<a href="http://protocolos.sarava.org">http://protocolos.sarava.org</a>).</p> + </li> +</ol> + +<p>Na Hidra Saraventa, cada célula é chamada de “nodo”:</p> + +<ul> + <li> + <p>Nodos físicos com servidores virtuais com fins específicos.</p> + </li> + <li> + <p>Nodos virtuais em diversos locais (inclusive hospedados por terceiros).</p> + </li> +</ul> + +<p>Baseada no seguinte pricípio: quais problemas solucionaremos, quais não.</p> + + +</div> +<div class='slide '> +<h1 id="o-padro-sarav">O Padrão Saravá</h1><p>O Padrão Saravá é uma sistematização de configuração de servidores, gerenciadores de conteúdo e aplicações diversas usados pelo Grupo Saravá. O padrão foi desenvolvido para:</p> + +<ul> + <li> + <p>Ter controle dos pacotes utilizados, arquivos de configuração e serviços em uso.</p> + </li> + <li> + <p>Uniformidade de administração.</p> + </li> + <li> + <p>Sistema de gerenciamento de backups comum para que as máquinas de um projeto possam trocar dados.</p> + </li> + <li> + <p>Que um servidor seja configurado apenas uma vez e que suas configurações possam ser aproveitados para outras máquinas.</p> + </li> + <li> + <p>Que sites e serviços sejam armazenados de maneira regular para facilitar atualizações e migrações.</p> + </li> + <li> + <p>Manter projetos e serviços isolados uns dos outros através de servidores virtuais.</p> + </li> + <li> + <p>Tornar a instalação dos servidores facilmente replicável.</p> + </li> +</ul> + +<p>Dinâmica de desenvolvimento:</p> + +<pre><code>Documentação wiki -> Configurações pré-gravadas -> Software +</code></pre> + + +</div> +<div class='slide '> +<h1 id="puppet">Puppet</h1><p><img src="http://docs.reductivelabs.com/images/Puppet_Star.png" alt="Puppet: topologia" /> +<img src="http://www.puppetlabs.com/images/system_diagram.png" alt="Puppet: diagrama de sistema" /></p> + + +</div> +<div class='slide '> +<h1 id="puppet-compartilhando-configurao">Puppet: compartilhando configuração</h1><p>Código puppet:</p> + +<pre><code>file { '/etc/passwd': + owner => root, + group => root, + mode => 644, +} +</code></pre> + +<p>Módulos compartilhados:</p> + +<ul> + <li> + <p><a href="http://git.sarava.org">http://git.sarava.org</a></p> + </li> + <li> + <p><a href="https://labs.riseup.net/code/projects/sharedpuppetmodules">https://labs.riseup.net/code/projects/sharedpuppetmodules</a></p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="git-e-gitosis">Git e gitosis</h1><p><img src="http://hoth.entp.com/output/scm.png" alt="VCS" /> +<img src="http://hoth.entp.com/output/dscm.png" alt="VCS distribuído" /></p> + + +</div> +<div class='slide '> +<h1 id="o-protocolo-de-compartilhamento-de-recursos">O Protocolo de Compartilhamento de Recursos</h1><pre><code>"The Resource Sharing Protocol (RSP) is a set of metadata intended to help free +software groups + + * Share their available resources and also Find groups that can host + * services for them given their needs and requirements. + +The RSP splits each resource in a layer or set of service layers. You can think +of service layers something very general, ranging from servers, databases, +websites. If you need to, you can even consider stuff such as tables and +bicycles as layers that provide some kind of service to a hosted group. ;)" + +-- http://rsp.sarava.org +</code></pre> + + +</div> +<div class='slide '> +<h1 id="orquestrao">Orquestração</h1><p>Para complementar a Configuração de sistemas padronizada e centralizada, procedimentos como</p> + +<ol> + <li>Atualização de pacotes.</li> + <li>Atualização de código de gerenciadores de conteúdo.</li> + <li>Carga de bancos de dados. </li> +</ol> + +<p>podem ser codificados de forma a serem facilmente aplicados a múltiplas camadas de forma simultânea.</p> + +<p>Exemplos:</p> + +<ul> + <li><a href="https://git.sarava.org/?p=hydra.git;a=summary">https://git.sarava.org/?p=hydra.git;a=summary</a></li> + <li><a href="http://www.capify.org">http://www.capify.org</a></li> + <li><a href="http://marionette-collective.org">http://marionette-collective.org</a></li> + <li><a href="https://fedorahosted.org/func">https://fedorahosted.org/func</a></li> + <li><a href="http://fabfile.org">http://fabfile.org</a></li> + <li><a href="http://www.debian-administration.org/article/Automating_ssh_and_scp_across_multiple_hosts">http://www.debian-administration.org/article/Automating_ssh_and_scp_across_multiple_hosts</a></li> +</ul> + + +</div> +<div class='slide '> +<h1 id="ikiwiki">Ikiwiki</h1><p>O Ikiwiki (<a href="http://ikiwiki.info">http://ikiwiki.info</a>) é um software de wiki que usa um sistema de controle de versão e arquivos de texto, possibilitando:</p> + +<ol> + <li>A existência de múltiplas cópias integrais do wiki (online e offline).</li> + <li>Desenvolvimento distribuído de documentação.</li> +</ol> + +<p>O ikiwiki é muito útil para reunir documentação de sistemas, já que não necessita de nenhum sistema web funcional para abrigá-la.</p> + + +</div> +<div class='slide '> +<h1 id="virtualizao">Virtualização</h1><p>Virtualização através de Linux-VServer (existem outras implementações possíveis):</p> + +<ul> + <li><a href="http://www.linux-vserver.org">http://www.linux-vserver.org</a></li> + <li><a href="http://slack.sarava.org/vservers">http://slack.sarava.org/vservers</a></li> +</ul> + +<p>Principais vantagens:</p> + +<ul> + <li> + <p>Permite diversos grupos compartilharem uma mesma máquina presevando sua autonomia.</p> + </li> + <li> + <p>Grupos podem hospedar mutuamente instâncias virtuais. Exemplo: se existem 5 grupos com uma máquina cada um, se cada um deles hospedar um vserver para cada grupo, teremos 4 locais remotos de hospedagem por grupo, aumentando assim as possibilidades de salvaguarda e escalabilidade.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="keyringer-e-monkeysphere">Keyringer e monkeysphere</h1><p>O Keyringer (<a href="http://git.sarava.org/?p=keyringer.git;a=summary">http://git.sarava.org/?p=keyringer.git;a=summary</a>) é um repositório distribuído de senhas/chaves baseado em GPG e git.</p> + +<p>O monkeysphere (<a href="http://web.monkeysphere.info">http://web.monkeysphere.info</a>) é um programa que permite a verificação de hosts SSH e usuários/as através da Teia de Confiabilidade do OpenPGP. Com ele, o gerenciamento de fingerprints fica mais fácil e evita que páginas como esta centralizem informações que possam se desatualizar. </p> + + +</div> +<div class='slide '> +<h1 id="tecnologia-bootless">Tecnologia bootless</h1><p>Muitos esquemas de criptografia em disco se baseiam na proteção das partições de dadados e da área de troca, porém dependem da existência de ao menos uma partição de inicialização com as imagens do sistema e de um setor de inicialização.</p> + +<p>Com acesso físico à máquina, é possível infectar tais dados de inicialização e comprometer a criptografia de todo o sistema.</p> + +<p>Para mitigar a situação, o esquema Bootless é um repositório git que contém as imagens de inicialização e a configuração necessárias para o procedimento de partida.</p> + +<p>Assim, é possível manter a parte de inicialização fora da máquina, por exemplo em chaveiros USB.</p> + +<p>Projeto similar: <a href="http://lfde.org">http://lfde.org</a></p> + + +</div> +<div class='slide '> +<h1 id="monitoramento-nagios">Monitoramento: nagios</h1><div class="centered"> + <p><img src="http://nagios.sourceforge.net/images/screens/new/statusmap-circular.png" alt="Nagios" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="monitoramento-munin">Monitoramento: munin</h1><div class="centered"> + <p><img src="http://upload.wikimedia.org/wikipedia/commons/c/ce/Munin-memory-week.png" alt="Munin" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="backups">Backups</h1><p>Estratégia:</p> + +<ol> + <li>Backups locais criptografados com duplicity: + <ul> + <li>Incluindo apenas <code>/etc</code>, <code>/var</code>, <code>/home</code>.</li> + <li>Excluindo logs, cache e backups remotos.</li> + </ul> + </li> + <li>Backups remotos apenas do backup local em duplicity, via rdiff ou rsync.</li> + <li>Nodos designados para armazenamento de backups.</li> + <li>Incrementos locais e remotos para aumentar consistência dos dados.</li> + <li>Procedimento integrado de restore e ativação de nodo.</li> +</ol> + + +</div> +<div class='slide '> +<h1 id="hardware-e-custos">Hardware e custos</h1><ul> + <li>Servidor mini-ITX Atom dual core + 2GB RAM + 1TB: R$680.00.</li> + <li>Nobreaks APC: +/- R$500,00.</li> + <li>Banda larga ADSL/cabo: R$80,00 a R$200,00.</li> + <li>Energia: 180W (mini-ITX) máx.</li> + <li>Sistema pode ser instalado inclusive em memórias de estado sólido (microSD por exemplo).</li> +</ul> + +<div class="centered"> + <p><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Mini-itx-motherboard.jpg/800px-Mini-itx-motherboard.jpg" alt="Mini ITX" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="utilidades-adaptador-para-discos">Utilidades: adaptador para discos</h1><div class="centered"> + <p><img src="http://www.sataadapter.com/sata-to-usb-adapter-cable-for-windows-and-mac.jpg" alt="Adaptador SATA" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="utilidades-chave-de-entropia">Utilidades: chave de entropia</h1><p><img src="http://www.entropykey.co.uk/res/device.jpeg" alt="Entropy key" /> +<img src="http://www.entropykey.co.uk/res/entropy-trite-small-nq8.png" alt="Entropy graph" /></p> + + +</div> +<div class='slide '> +<h1 id="segurana">Segurança</h1><p>Acesso remoto:</p> + +<ul> + <li> + <p>Contas SSH administrativas em todos os nodos.</p> + </li> + <li> + <p>Contas SSH de backup para nodos de backup.</p> + </li> + <li> + <p>Contas SSH de tunelamento para nodos diversos.</p> + </li> +</ul> + +<p>Análise:</p> + +<ol> + <li> + <p>É importante isolar o máximo a capacidade de acesso para contas de nodos de backup ou que tunelem conexões.</p> + </li> + <li> + <p>Administradores/as precisam ter boas medidas de segurança:</p> + <ul> + <li>Pasta criptografada.</li> + <li>Senhas e chaves seguras.</li> + </ul> + </li> +</ol> + + +</div> +<div class='slide '> +<h1 id="protocolos-sociais">Protocolos sociais</h1><ul> + <li>Protocolo de Ação Coletiva: <a href="http://protocolos.sarava.org">http://protocolos.sarava.org</a>.</li> + <li>Outros protocolos e metodologias (contabilidade, acesso à informação, relação com grupos, etc).</li> + <li> + <p>Uso de um sistema de gestão de processos (trac ou similar).</p> + + <pre><code> .------------------->-----------------. + / .----------<--------------<-------. \ + | ' \ \ + | | .------>-----. \ \ + | | | \ \ \ + Proposta -----> Discussão ->--. \ \ \ + | ^ | \ \ \ \ + | | | \ \ \ \ + | `----<-----' | \ \ \ + | | | \ \ + `------>------ Decisão --<--' | \ \ + | | | \ \ + | | | | | + Atribuição de --<---' '---> Arquivamento --->---' ; + Responsabilidades ----->-------' ^ \ / + ^ | ___________/ `---<-----' + | \ .' + | `--> Realização -->--. + | | | \ + | | | / + `----<-----' `-----<---' +</code></pre> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="resumo-estratgia-de-gesto">Resumo: Estratégia de gestão</h1><ul> + <li> + <p>Facilitar instalação, manutenção e gestão de dados.</p> + </li> + <li> + <p>Manter backups em máquinas prontas para serem inicializadas.</p> + </li> + <li> + <p>Manter nodos master prontos para assumirem o posto de “cabeça ativa”.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-6-a-confederao-das-hidras-unidas">Parte 6: A Confederação das Hidras Unidas</h1><div class="centered"> + <p><img src="http://apod.nasa.gov/apod/image/0104/hydra_aat116.jpg" alt="Hidra Cluster" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="a-confederao-das-hidras-unidas">A Confederação das Hidras Unidas</h1><ul> + <li> + <p>Hidra é um processo, não uma tecnologia, implementação, sistema ou serviço.</p> + </li> + <li> + <p>Assim, é possível ter hidras menos sistematizadas e com diferentes formas de organização. O processo já ocorre em vários locais.</p> + </li> + <li> + <p>Havendo várias hidras, se elas se integram passa a existir a Confederação das Hidras Unidas.</p> + </li> + <li> + <p>Importante questão do licenciamento: AGPL 3.0 para garantir o máximo possível da disponibilização de código e documentação.</p> + </li> + <li> + <p>Não é estritamente necessária a criação de uma “confederação”, já que a cultura de hidras pode ser não-coordenada.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-7-nuvens-e-hidras">Parte 7: Nuvens e Hidras</h1><p>Hidras são nuvens (cloud computing)?</p> + +<ul> + <li> + <p>Cloud computing foca apenas nas instâncias e como estas são integradas por aplicações (IaaS, SaaS, PaaS) e no seu uso sob demanda.</p> + </li> + <li> + <p>Cloud computing é uma iniciativa do mercado e uma tendência à terceirização total das atividades.</p> + </li> + <li> + <p>A Hidra leva em consideração a organização social que suporta a infraestrutura computacional.</p> + </li> + <li> + <p>A Hidra é uma nuvem na qual certos nodos desempenham papéis determinados, porém contendo o germe de toda a organização.</p> + </li> + <li> + <p>Outra classe de nuvens: botnets.</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="nuvens-diagramas">Nuvens: diagramas</h1><p><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cloud_Computing_Stack.svg/340px-Cloud_Computing_Stack.svg.png" alt="Camadas" /> +<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/79/CloudComputingSampleArchitecture.svg/550px-CloudComputingSampleArchitecture.svg.png" alt="Arquitetura" /></p> + + +</div> +<div class='slide '> +<h1 id="tipos-de-nuvens">Tipos de nuvens</h1><div class="centered"> + <p><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Cloud_computing_types.svg/800px-Cloud_computing_types.svg.png" alt="Tipos de nuvens" /></p> +</div> + + +</div> +<div class='slide '> +<h1 id="parte-8-futuro">Parte 8: Futuro</h1><ul> + <li>Hidra Saraventa: ainda em intenso desenvolvimento, porém já em estágio maduro. Falta (em agosto/2010): + <ul> + <li>Melhoria no procedimento de bootstrap.</li> + <li>Integração com DNS.</li> + <li>Sistema de proxy para balanceamento de carga.</li> + <li>Melhoria de procedimentos de sunsetting de sítios, plataformas e contas.</li> + <li>Longuíssimo prazo, caso realizável: possibilidade de um nodo ser convertido de uma classe para outra.</li> + <li>Procedimentos para suporte jurídico.</li> + <li>Nodos em conexões DSL e cabo: IP dinâmico, DNS reverso, etc.</li> + <li>VPN entre os nodos, Puppet Dashboard?, External node tool?</li> + <li>Migrar para Linux Containers (lxc).</li> + <li>Melhoria da documentação e representações gráficas do processo.</li> + <li>Storage de dados distribuído.</li> + </ul> + </li> + <li>Hidras via Rádio.</li> + <li>Hidras em outros tipos de organizações sociais.</li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-9-concluses">Parte 9: Conclusões</h1><ul> + <li> + <p>Resolver a replicação e escalabilidade primeiro na infraestrutura (máquinas, configurações e backups), depois nas camadas superiores (CMSs, por exemplo)</p> + </li> + <li> + <p>Não importa tanto se a rede é centralizada, descentralizada ou distribuída se antes de tudo ela for regenerativa. No entanto, em geral são as redes distribuídas e descentralizadas que possuem fatores de regeneração maiores do que no caso centralizado.</p> + </li> + <li> + <p>Número grande de máquinas é interessante: várias podem estar sem funcionar num dado momento, mas as que estiverem funcionando podem dar conta da demanda.</p> + </li> + <li> + <p>A hidra é indestrutível? Essa questão faz sentido? Positivismo, revoluções e cataclismas: o limite da hidra por ter uma relação e abertura e fechamento (autonomia dependente).</p> + </li> +</ul> + + +</div> +<div class='slide '> +<h1 id="parte-10-referncias">Parte 10: Referências</h1></div> +<div class='slide '> +<h1 id="referncias-imagens-usadas">Referências: imagens usadas</h1><ul> + <li><a href="http://en.wikipedia.org/wiki/File:Hydra_04.jpg">http://en.wikipedia.org/wiki/File:Hydra_04.jpg</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:Hydra001.jpg">http://en.wikipedia.org/wiki/File:Hydra001.jpg</a></li> + <li><a href="http://code.google.com/edu/parallel/dsd-tutorial.html">http://code.google.com/edu/parallel/dsd-tutorial.html</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:DNS_in_the_real_world.svg">http://en.wikipedia.org/wiki/File:DNS_in_the_real_world.svg</a></li> + <li><a href="http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2sfarm.html">http://www.linux.org/docs/ldp/howto/Jabber-Server-Farming-HOWTO/c2sfarm.html</a></li> + <li><a href="http://www.autistici.org/orangebook/slides/orangebook.en.html">http://www.autistici.org/orangebook/slides/orangebook.en.html</a>.</li> + <li><a href="http://www.autistici.org/orangebook/slides/orangebook.en.html">http://www.autistici.org/orangebook/slides/orangebook.en.html</a></li> + <li><a href="http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png">http://perl.apache.org/docs/tutorials/apps/scale_etoys/machine_layout.png</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:ICEgrid.png">http://en.wikipedia.org/wiki/File:ICEgrid.png</a></li> + <li><a href="http://www.ibiblio.org/pioneers/baran.html">http://www.ibiblio.org/pioneers/baran.html</a></li> + <li><a href="http://www1.folha.uol.com.br/folha/ciencia/ult306u442499.shtml">http://www1.folha.uol.com.br/folha/ciencia/ult306u442499.shtml</a></li> + <li><a href="http://www.tutorvista.com/content/biology/biology-iv/growth-regeneration-ageing/regeneration.php">http://www.tutorvista.com/content/biology/biology-iv/growth-regeneration-ageing/regeneration.php</a></li> + <li><a href="http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html">http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html</a></li> + <li><a href="http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html">http://www.uni-kiel.de/zoologie/bosch/developmentalbiology.html</a></li> + <li><a href="http://www.puppetlabs.com/puppet/introduction">http://www.puppetlabs.com/puppet/introduction</a></li> + <li><a href="http://docs.reductivelabs.com/guides/introduction.html">http://docs.reductivelabs.com/guides/introduction.html</a></li> + <li><a href="http://www.nagios.org/about/screenshots">http://www.nagios.org/about/screenshots</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:Munin-memory-week.png">http://en.wikipedia.org/wiki/File:Munin-memory-week.png</a></li> + <li><a href="http://hoth.entp.com/output/git_for_designers.html">http://hoth.entp.com/output/git_for_designers.html</a></li> + <li><a href="http://en.wikipedia.org/wiki/Mini-itx">http://en.wikipedia.org/wiki/Mini-itx</a></li> + <li><a href="http://www.sataadapter.com">http://www.sataadapter.com</a></li> + <li><a href="http://www.entropykey.co.uk">http://www.entropykey.co.uk</a></li> + <li><a href="http://apod.nasa.gov/apod/ap010416.html">http://apod.nasa.gov/apod/ap010416.html</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:Cloud_Computing_Stack.svg">http://en.wikipedia.org/wiki/File:Cloud_Computing_Stack.svg</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:CloudComputingSampleArchitecture.svg">http://en.wikipedia.org/wiki/File:CloudComputingSampleArchitecture.svg</a></li> + <li><a href="http://en.wikipedia.org/wiki/File:Cloud_computing_types.svg">http://en.wikipedia.org/wiki/File:Cloud_computing_types.svg</a></li> +</ul> +</div> + + + </div> <!-- presentation --> +</body> +</html> + diff --git a/doc/hidra.svg b/doc/hidra.svg new file mode 100644 index 0000000..0a9452c --- /dev/null +++ b/doc/hidra.svg @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="hidra.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <inkscape:perspective + id="perspective2464" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 526.18109 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.35" + inkscape:cx="350" + inkscape:cy="520" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Camada 1" + inkscape:groupmode="layer" + id="layer1"> + <image + y="471.79077" + x="184.28572" + id="image2466" + height="544" + width="520" + sodipodi:absref="/mnt/crypt/home/rhatto/upload/hidra-detalhe.jpg" + xlink:href="/mnt/crypt/home/rhatto/upload/hidra-detalhe.jpg" /> + <path + style="fill:#000000" + d="M 246.28571,473.21932 C 246.28571,472.66932 246.73571,472.21932 247.28571,472.21932 C 247.83571,472.21932 248.28571,472.66932 248.28571,473.21932 C 248.28571,473.76932 247.83571,474.21932 247.28571,474.21932 C 246.73571,474.21932 246.28571,473.76932 246.28571,473.21932 z M 121.78571,464.21932 C 122.12563,463.66932 123.16469,463.22621 124.09473,463.23463 C 125.552,463.24783 125.5784,463.38392 124.28571,464.21932 C 122.32734,465.48492 121.00353,465.48492 121.78571,464.21932 z M 339.28571,446.17267 C 330.11419,443.85535 300.15749,429.30046 300.79069,427.46932 C 301.02843,426.78182 300.82456,426.21932 300.33766,426.21932 C 299.85075,426.21932 299.29797,426.68254 299.10925,427.24871 C 298.56922,428.86879 269.21649,415.53437 267.61356,412.94078 C 267.21951,412.30318 267.47577,412.21875 268.28571,412.71932 C 269.17793,413.27074 269.35412,413.13903 268.83907,412.30565 C 268.42346,411.63318 267.4869,411.31187 266.75784,411.59164 C 265.25642,412.16779 260.30542,410.13242 260.29351,408.93414 C 260.28922,408.50229 261.22425,408.65124 262.37136,409.26516 C 263.51846,409.87907 264.70587,410.13249 265.01004,409.82832 C 265.31422,409.52415 264.37568,408.82382 262.9244,408.27205 C 261.47312,407.72027 260.28571,406.8362 260.28571,406.30743 C 260.28571,405.77866 258.82321,405.20503 257.03571,405.03268 C 254.72592,404.80997 253.82208,404.23593 253.91142,403.0484 C 253.98686,402.04567 253.50828,401.58042 252.71465,401.88496 C 251.14342,402.4879 243.93498,395.59582 244.75282,394.27254 C 245.06385,393.76928 244.79146,393.03189 244.14751,392.63391 C 243.41629,392.18199 243.24459,392.34377 243.69022,393.06481 C 244.08266,393.69979 244.01546,394.21932 243.54089,394.21932 C 242.31335,394.21932 236.14335,387.69501 236.77426,387.06411 C 237.0623,386.77606 236.28271,385.68065 235.04184,384.62986 L 232.78571,382.71932 L 234.6907,384.96932 C 237.09724,387.81171 235.65441,387.91433 232.6724,385.11287 C 231.43918,383.95432 230.64315,382.45141 230.90345,381.77308 C 231.16375,381.09475 230.56875,379.90515 229.58122,379.12953 C 227.94393,377.84359 227.90665,377.87353 229.15815,379.46932 C 229.913,380.43182 230.11013,381.21932 229.59621,381.21932 C 228.24841,381.21932 223.77273,374.94454 224.09065,373.50067 C 224.23823,372.83042 223.4874,371.73771 222.42213,371.07244 C 221.31246,370.37944 220.72823,369.22971 221.05416,368.38035 C 221.48289,367.2631 221.08874,367.03757 219.45438,367.46496 C 217.3214,368.02275 216.29206,366.7172 218.32939,366.03809 C 218.90459,365.84636 218.48275,364.73456 217.3896,363.56121 C 216.2987,362.39027 215.58358,361.25478 215.80045,361.03791 C 216.01732,360.82105 215.26813,360.06492 214.13559,359.35764 C 212.43987,358.29864 212.20791,358.30533 212.82137,359.3955 C 213.23109,360.1236 211.72345,358.79082 209.47105,356.43376 C 207.21865,354.0767 205.61119,351.53472 205.89891,350.78491 C 206.18664,350.0351 205.86491,349.07728 205.18394,348.65643 C 204.30819,348.11518 204.1421,348.4027 204.61645,349.63884 C 205.06205,350.80006 204.86742,351.24824 204.03639,350.97455 C 203.34852,350.74801 202.63508,349.53331 202.45099,348.27522 C 202.26689,347.01712 201.24491,345.7599 200.17991,345.4814 C 198.6242,345.07457 198.47755,344.69309 199.43391,343.54075 C 200.0886,342.7519 200.21058,342.18515 199.70498,342.28132 C 196.3602,342.91749 194.83231,340.74578 198.03571,339.90865 C 199.36355,339.56164 199.24753,339.42334 197.55476,339.33532 C 196.07821,339.25855 195.11778,338.39841 194.71451,336.79168 C 194.3794,335.45647 193.50037,334.13194 192.76112,333.84826 C 191.8845,333.51187 191.55954,332.18246 191.82677,330.0259 C 192.05213,328.20728 191.90723,327.24346 191.50478,327.88408 C 190.96174,328.74848 190.27411,328.68401 188.83825,327.63408 C 187.44932,326.61847 187.31004,326.20993 188.34458,326.18605 C 189.32632,326.16339 189.06848,325.55444 187.53571,324.27576 C 185.23372,322.35536 184.40439,320.5566 186.38548,321.78098 C 187.07738,322.2086 187.01914,321.58975 186.22844,320.1123 C 185.02036,317.85499 184.94166,317.84061 184.19895,319.74162 C 183.48326,321.57348 183.4211,321.54905 183.356,319.4103 C 183.31734,318.14034 182.86254,317.36282 182.34532,317.68248 C 181.04523,318.48598 177.123,314.08572 177.7298,312.50443 C 178.00103,311.79762 177.78706,311.21932 177.25433,311.21932 C 176.17142,311.21932 175.93741,313.53768 176.92103,314.5213 C 177.27045,314.87073 177.71612,316.63323 177.9114,318.43797 C 178.44124,323.33467 178.82642,325.09336 179.5212,325.78814 C 180.39328,326.66022 179.25869,329.32066 178.27418,328.7122 C 177.83311,328.4396 177.71769,329.15522 178.01771,330.30247 C 178.43238,331.8882 178.76604,332.06838 179.40913,331.05385 C 179.97322,330.16397 180.26019,330.11201 180.2704,330.89789 C 180.27882,331.54611 179.54964,332.81253 178.65,333.71218 C 177.42921,334.93296 177.30238,335.63599 178.15,336.48361 C 179.67704,338.01065 179.59709,339.51315 178.03571,338.63163 C 177.1538,338.13373 177.08857,338.25725 177.81419,339.05109 C 178.37985,339.66994 178.66868,342.00067 178.45604,344.23048 C 178.13548,347.59185 177.82763,348.08404 176.65467,347.11056 C 175.51456,346.16436 175.3622,346.25508 175.86981,347.57788 C 176.21624,348.48067 176.97129,349.21932 177.54769,349.21932 C 178.12409,349.21932 177.76367,350.13869 176.74676,351.26235 C 175.26109,352.904 175.21077,353.18531 176.49063,352.69418 C 177.36666,352.35802 178.38737,352.5748 178.75889,353.17592 C 179.13598,353.78606 178.84935,354.14749 178.11004,353.9941 C 177.11351,353.78733 176.82682,355.20446 176.95181,359.71932 C 177.25557,370.69159 177.20572,372.53973 176.57865,373.55434 C 176.23638,374.10815 175.59495,373.58432 175.15325,372.39029 C 174.23874,369.91814 172.28571,369.46115 172.28571,371.71932 C 172.28571,372.54432 172.69358,373.21932 173.19209,373.21932 C 173.6906,373.21932 173.86444,374.11426 173.5784,375.20807 C 173.29236,376.30189 172.58996,376.90736 172.01751,376.55356 C 171.44111,376.19733 171.27284,376.38948 171.64039,376.98419 C 172.00543,377.57483 171.73746,378.66757 171.0449,379.41251 C 169.60902,380.95699 168.96745,382.9368 169.08215,385.46932 C 169.12575,386.43182 168.71282,387.21932 168.16454,387.21932 C 167.61627,387.21932 167.44579,387.66932 167.78571,388.21932 C 168.12563,388.76932 168.02295,389.21932 167.55753,389.21932 C 167.09211,389.21932 166.64444,390.10713 166.5627,391.19223 C 166.48097,392.27734 165.50076,394.14549 164.38448,395.34368 C 163.26819,396.54187 162.63842,397.98099 162.98497,398.54173 C 163.33683,399.11105 163.93454,398.69766 164.33853,397.60557 C 164.73643,396.52994 165.8605,394.99051 166.83647,394.1846 C 168.67648,392.66521 168.64431,392.87748 166.33656,397.48368 C 165.37456,399.40382 164.42073,400.07956 163.21333,399.69635 C 161.48466,399.14769 157.28571,403.70063 157.28571,406.12369 C 157.28571,407.62315 159.00182,407.50983 159.62343,405.96932 C 160.01974,404.98716 160.14473,404.99287 160.20676,405.99597 C 160.29482,407.41996 154.43939,414.21932 153.12503,414.21932 C 151.516,414.21932 152.29943,412.44899 154.11904,411.97316 C 155.12738,411.70947 155.95238,410.78963 155.95238,409.92906 C 155.95238,408.76448 155.2397,409.03705 153.16522,410.99503 C 151.26863,412.78511 150.68391,413.9942 151.33526,414.77903 C 152.57886,416.27747 145.8092,423.66089 144.13846,422.62832 C 143.49949,422.23341 143.23286,422.32479 143.54595,422.83139 C 144.37365,424.17063 139.13543,430.04097 136.78571,430.40741 C 135.68571,430.57896 134.56071,431.19253 134.28571,431.77089 C 133.9486,432.47989 132.97127,432.40325 131.28571,431.53564 C 128.91534,430.31553 128.89813,430.24804 130.95392,430.23406 C 133.9123,430.21395 136.28571,429.21497 136.28571,427.98989 C 136.28571,427.43139 135.54155,427.59203 134.63202,428.34688 C 133.72248,429.10172 132.82248,429.60682 132.63202,429.46932 C 132.44155,429.33182 131.14098,429.21932 129.74187,429.21932 C 127.92666,429.21932 127.2822,429.6915 127.49187,430.86786 C 127.81607,432.68672 124.28046,433.46739 122.07021,432.06497 C 121.11522,431.45902 121.2195,431.24602 122.47669,431.23463 C 123.40673,431.22621 124.4101,430.82708 124.70639,430.34767 C 125.00268,429.86826 121.54174,429.47181 117.0154,429.46667 C 108.59096,429.4571 102.68066,428.00733 103.78455,426.22119 C 104.12511,425.67016 103.92719,425.21932 103.34473,425.21932 C 102.76227,425.21932 102.28571,425.7181 102.28571,426.32773 C 102.28571,427.04292 101.31012,427.18343 99.535714,426.72381 C 96.350984,425.89888 94.100384,425.40444 93.035714,425.29583 C 92.623214,425.25375 92.398214,424.71307 92.535714,424.09432 C 92.673214,423.47557 92.160574,422.74219 91.396514,422.46459 C 90.570464,422.16446 90.280314,422.40157 90.680764,423.04951 C 91.166204,423.83497 90.480244,423.83449 88.223584,423.04782 C 85.842074,422.21762 85.415134,421.72788 86.439344,421.00115 C 87.414524,420.30921 87.178214,420.17843 85.582194,420.5268 C 84.370254,420.79134 82.570254,420.37927 81.582194,419.61109 C 79.926874,418.32416 79.923224,418.2623 81.535714,418.82386 C 84.474454,419.84728 83.484634,418.37352 80.035714,416.59047 C 76.911044,414.97506 76.843554,414.98026 78.285714,416.72545 C 79.693834,418.42944 79.651854,418.45727 77.600394,417.17982 C 76.398474,416.43138 75.606594,415.50915 75.840654,415.13043 C 76.074724,414.7517 74.695614,413.24387 72.775974,411.77969 C 70.856334,410.3155 69.285714,408.46544 69.285714,407.66843 C 69.285714,406.87142 68.835714,406.21932 68.285714,406.21932 C 67.735714,406.21932 67.285714,406.69033 67.285714,407.266 C 67.285714,407.84168 66.209054,407.50418 64.893124,406.516 C 62.997354,405.0924 62.605274,404.06882 63.004934,401.58662 C 63.482674,398.61947 63.363114,398.48187 60.742664,398.9828 C 58.304054,399.44897 58.042514,399.25732 58.536974,397.3665 C 58.845514,396.18664 58.702434,394.97686 58.219004,394.67809 C 57.735584,394.37932 56.860494,392.35388 56.274344,390.1771 C 55.688204,388.00032 54.775974,386.21932 54.247174,386.21932 C 53.718374,386.21932 53.285714,384.86932 53.285714,383.21932 C 53.285714,381.55265 52.752384,380.21932 52.085714,380.21932 C 51.239584,380.21932 51.198654,379.90638 51.946904,379.15813 C 52.554974,378.55006 52.727604,376.73537 52.351204,374.90813 C 51.989914,373.15429 52.060404,369.02727 52.507844,365.73698 C 52.955294,362.4467 53.093514,359.16083 52.815004,358.43505 C 52.536494,357.70927 52.716854,357.36774 53.215794,357.67611 C 53.714744,357.98447 54.420344,356.88285 54.783794,355.22805 C 55.470214,352.10281 56.751764,351.30908 57.623434,353.46932 C 57.900844,354.15682 58.163344,353.71838 58.206764,352.495 C 58.368194,347.94677 68.152124,345.85512 74.100284,349.09722 C 75.960584,350.1112 76.181884,350.6395 75.227834,351.78906 C 74.265214,352.94895 74.421824,353.21932 76.056284,353.21932 C 79.559114,353.21932 79.996494,358.34886 76.604644,359.65043 C 75.743624,359.98084 75.329784,360.89178 75.655324,361.74012 C 76.111454,362.92878 75.661534,363.11969 73.509074,362.6508 C 71.469454,362.2065 71.155044,362.31528 72.256754,363.08406 C 73.065824,363.64864 73.515824,364.24754 73.256754,364.41495 C 72.997684,364.58235 71.885714,365.22931 70.785714,365.85264 C 69.169814,366.7683 68.827424,367.89333 69.002904,371.71064 C 69.122364,374.30922 69.629794,376.94923 70.130524,377.57733 C 70.631244,378.20542 71.382664,379.84432 71.800324,381.21932 C 74.102064,388.79696 93.130284,408.66948 96.242494,406.74603 C 96.816264,406.39142 97.285714,406.57784 97.285714,407.1603 C 97.285714,407.74276 98.159154,408.21932 99.226694,408.21932 C 100.29423,408.21932 101.45033,408.67666 101.79579,409.23563 C 102.14126,409.7946 102.81172,410.01226 103.28571,409.71932 C 103.7597,409.42638 104.41307,409.61638 104.73764,410.14154 C 105.06221,410.66671 106.29746,410.90964 107.48264,410.68139 C 108.66782,410.45315 110.12086,410.64959 110.71161,411.11792 C 111.92363,412.07877 115.25021,411.97733 116.94851,410.92772 C 117.56871,410.54442 118.33417,410.90322 118.64954,411.72506 C 118.96491,412.5469 119.71362,413.21932 120.31334,413.21932 C 120.91952,413.21932 121.07025,412.66422 120.65277,411.96932 C 120.21509,411.2408 120.68773,411.3451 121.78571,412.21932 C 122.82186,413.04432 123.36083,413.20397 122.98341,412.5741 C 122.60599,411.94424 122.94142,411.18168 123.7288,410.87953 C 124.5574,410.56157 125.34854,411.04395 125.60706,412.02475 C 126.01021,413.5543 126.065,413.547 126.16971,411.94976 C 126.25837,410.59732 126.91194,410.29376 128.94238,410.66195 C 130.40355,410.92691 132.0707,410.85221 132.64715,410.49594 C 133.22361,410.13967 135.0159,409.70359 136.63003,409.52689 C 139.30535,409.23401 144.28144,404.93263 144.28449,402.9103 C 144.28516,402.46534 144.70331,402.35938 145.21371,402.67482 C 145.72412,402.99027 146.41625,402.3834 146.75178,401.32622 C 147.08732,400.26905 148.04824,399.14069 148.88716,398.81876 C 149.72608,398.49684 150.13043,397.77709 149.78571,397.21932 C 149.44099,396.66155 149.81274,395.95431 150.61182,395.64767 C 151.47222,395.31751 151.8583,394.3009 151.55857,393.15474 C 151.09853,391.39553 152.08624,390.71414 154.53571,391.1009 C 154.94821,391.16603 155.19999,390.88182 155.09521,390.46932 C 154.61296,388.57068 156.61168,383.13222 158.11386,382.25569 C 159.03338,381.71913 159.26303,381.26645 158.62419,381.24973 C 157.1466,381.21104 157.57275,377.95697 159.12308,377.4402 C 159.76253,377.22705 160.28571,376.41515 160.28571,375.63599 C 160.28571,374.85682 160.76227,374.21932 161.34473,374.21932 C 161.92719,374.21932 162.10982,373.74374 161.75058,373.16248 C 160.67663,371.4248 162.18032,367.03905 163.56503,367.87038 C 164.49802,368.43052 164.49315,368.24171 163.54439,367.06927 C 162.86166,366.22559 162.58108,365.25728 162.92088,364.91748 C 164.93233,362.90603 165.46479,329.9984 163.51739,328.051 C 161.64904,326.18265 162.04273,324.21932 164.28571,324.21932 C 165.38571,324.21932 166.28571,323.78344 166.28571,323.2507 C 166.28571,322.71797 165.65623,322.52364 164.88686,322.81888 C 164.11749,323.11411 163.19094,322.87499 162.82784,322.28749 C 162.46475,321.7 162.67079,321.21932 163.28571,321.21932 C 163.90063,321.21932 164.09634,320.72193 163.72062,320.114 C 162.52943,318.18662 162.07604,312.21932 163.1208,312.21932 C 163.66983,312.21932 164.33601,312.78182 164.6012,313.46932 C 164.86639,314.15682 164.97886,313.4876 164.85114,311.98216 C 164.72342,310.47672 163.95292,308.45172 163.13891,307.48216 C 162.3249,306.5126 161.71475,305.04432 161.78302,304.21932 C 161.85128,303.39432 161.53392,301.65546 161.07777,300.35518 C 160.42111,298.48331 160.55404,298.10831 161.71614,298.55425 C 162.76465,298.9566 163.01126,298.63219 162.57955,297.41839 C 162.24718,296.4839 161.63795,295.26932 161.2257,294.71932 C 160.43534,293.66485 159.81344,290.26637 158.7553,281.21932 C 158.40149,278.19432 157.60779,274.14432 156.99151,272.21932 C 156.37523,270.29432 155.85181,268.41932 155.82836,268.05265 C 155.7191,266.34475 154.28498,266.11326 154.27955,267.80265 C 154.27443,269.39463 154.05358,269.29581 152.97586,267.21932 C 152.26223,265.84432 151.36389,263.81932 150.97957,262.71932 C 150.33123,260.86366 150.37915,260.84561 151.6435,262.46932 C 152.39298,263.43182 153.38409,264.21932 153.84595,264.21932 C 154.30782,264.21932 154.14571,263.67932 153.48571,263.01932 C 152.82571,262.35932 152.28571,261.03588 152.28571,260.07834 C 152.28571,259.1208 151.75924,258.01198 151.11577,257.61429 C 150.32912,257.12811 150.15503,257.43639 150.58439,258.55528 C 151.49412,260.926 150.56832,260.6159 149.22113,258.09864 C 148.32994,256.43345 148.35591,256.14467 149.34204,256.75413 C 150.29923,257.34571 150.43829,256.73223 149.92675,254.17452 C 149.55761,252.32884 148.69987,250.46576 148.02065,250.03434 C 147.34143,249.60292 147.23571,249.23616 147.78571,249.21932 C 148.33571,249.20248 148.11071,248.75248 147.28571,248.21932 C 146.28571,247.57307 146.20238,247.24484 147.03571,247.23463 C 148.6608,247.21473 148.64227,244.72991 147.00444,243.04075 C 146.29974,242.31396 145.73724,240.08922 145.75444,238.09687 C 145.77181,236.08458 145.34122,234.64268 144.78571,234.85296 C 144.22046,235.06693 143.65838,232.98343 143.49283,230.06053 C 143.33174,227.2165 142.9219,224.43968 142.58207,223.88982 C 142.24224,223.33996 142.06975,219.97826 142.19877,216.41938 C 142.39731,210.94293 142.19645,210.03959 140.89156,210.54033 C 139.00281,211.26511 138.19445,210.07078 137.75625,205.90803 C 137.57163,204.15424 137.64823,203.50682 137.92647,204.46932 C 138.20471,205.43182 138.74771,206.21932 139.13314,206.21932 C 139.51858,206.21932 139.39727,203.32234 138.86357,199.78159 C 138.32988,196.24084 137.56392,193.54737 137.16146,193.79611 C 135.82748,194.62056 135.09828,190.15008 136.32554,188.67133 C 136.98832,187.87273 137.138,187.21243 136.65815,187.20401 C 136.17831,187.19559 136.46071,186.75248 137.28571,186.21932 C 138.38439,185.5093 138.43388,185.24585 137.47068,185.23463 C 136.49281,185.22325 136.2681,183.82807 136.59424,179.79288 C 136.84769,176.65703 136.57965,173.91326 135.95927,173.29288 C 135.19452,172.52813 135.4297,172.21932 136.77684,172.21932 C 138.4767,172.21932 138.50609,172.0929 137.06742,170.96932 C 135.06338,169.4042 134.09802,160.93332 136.00719,161.66593 C 136.71037,161.93577 137.28571,161.76882 137.28571,161.29492 C 137.28571,160.82103 136.55439,160.15267 135.66056,159.80967 C 134.37598,159.31673 134.1689,158.35128 134.67238,155.20268 C 135.06249,152.76307 134.91721,151.21932 134.29753,151.21932 C 133.74103,151.21932 133.28571,150.74276 133.28571,150.1603 C 133.28571,149.57784 133.73571,149.3794 134.28571,149.71932 C 134.83571,150.05924 135.28571,149.60924 135.28571,148.71932 C 135.28571,147.8294 134.83571,147.3794 134.28571,147.71932 C 132.9396,148.55126 132.96368,137.94135 134.31097,136.59406 C 135.19236,135.71267 135.7852,132.03796 136.18639,124.96932 C 136.24101,124.00682 136.78817,123.21932 137.40229,123.21932 C 138.05408,123.21932 138.31993,124.25997 138.04096,125.71932 C 137.42792,128.92623 138.06475,128.93069 139.28241,125.728 C 140.34845,122.92411 139.60075,119.90658 138.07379,120.85029 C 137.48306,121.21538 137.28491,120.6997 137.59126,119.59455 C 137.87716,118.56317 138.3981,116.01931 138.74892,113.94153 C 139.10286,111.84524 139.82454,110.4343 140.37031,110.77161 C 140.9441,111.12623 141.1856,110.40872 140.94999,109.0494 C 140.47115,106.28691 144.56488,94.831823 145.64496,95.911903 C 146.05551,96.322453 146.09449,95.884573 145.73157,94.938843 C 145.25443,93.695423 145.58589,93.215083 146.92872,93.204013 C 148.22229,93.193343 148.40849,92.949143 147.54242,92.399133 C 146.26309,91.586703 147.34983,89.600483 151.53571,85.100593 C 152.49821,84.065893 152.98227,83.219323 152.6114,83.219323 C 152.24052,83.219323 153.02802,82.021763 154.3614,80.558073 C 155.69477,79.094383 156.11071,78.280763 155.28571,78.750033 C 154.0019,79.480273 153.97969,79.363993 155.13162,77.943253 C 155.87187,77.030263 156.9371,76.381373 157.49878,76.501293 C 158.06047,76.621213 158.65118,75.940823 158.81146,74.989313 C 159.23601,72.468943 162.10528,69.936103 163.79941,70.586203 C 164.63446,70.906643 165.15963,70.626593 165.02371,69.933333 C 164.89281,69.265633 165.28793,68.811733 165.90175,68.924673 C 166.51557,69.037613 166.96557,68.189593 166.90175,67.040193 C 166.83793,65.890793 167.67534,64.448393 168.76267,63.834853 C 169.85,63.221313 171.34587,62.044323 172.08683,61.219323 C 172.82779,60.394323 173.16831,60.250733 172.84356,60.900223 C 172.5188,61.549723 172.82293,62.409363 173.5194,62.810553 C 174.21587,63.211733 174.46404,63.183663 174.07089,62.748163 C 172.95165,61.508373 175.27785,58.002333 176.82561,58.596263 C 177.5882,58.888893 179.06234,58.047453 180.10149,56.726393 C 181.42571,55.042923 182.30615,54.639763 183.04495,55.378563 C 183.78374,56.117353 184.05218,56.026853 183.94238,55.075993 C 183.85621,54.329823 184.10384,53.719323 184.49266,53.719323 C 184.88149,53.719323 185.85719,52.820033 186.6609,51.720893 C 187.46461,50.621763 188.4508,50.051073 188.85243,50.452703 C 189.25406,50.854343 190.41871,50.218983 191.44053,49.040813 C 192.46236,47.862633 193.58736,47.187633 193.94053,47.540813 C 194.29371,47.893983 195.30335,47.402783 196.18419,46.449243 C 198.53552,43.903833 201.80235,41.498353 200.92573,42.957873 C 200.42384,43.793493 200.67642,44.006623 201.70215,43.613013 C 202.53833,43.292143 203.1242,42.509793 203.00409,41.874463 C 202.88398,41.239143 203.46071,40.719323 204.28571,40.719323 C 205.11071,40.719323 206.14557,40.156823 206.5854,39.469323 C 207.02523,38.781823 207.92523,38.226213 208.5854,38.234633 C 209.33953,38.244253 209.22813,38.651043 208.28571,39.328973 C 207.08308,40.194073 207.1822,40.264673 208.78571,39.685063 C 209.88571,39.287453 211.91071,38.736243 213.28571,38.460153 C 214.66071,38.184073 216.49723,37.340963 217.36686,36.586573 C 218.23649,35.832183 219.25816,35.525103 219.63723,35.904183 C 220.5951,36.862043 224.28571,37.049483 224.28571,36.140263 C 224.28571,35.730603 225.41071,35.518933 226.78571,35.669863 C 228.16071,35.820803 229.2926,35.443673 229.30102,34.831813 C 229.31123,34.090343 229.56136,34.062563 230.05102,34.748503 C 230.4551,35.314553 231.68571,35.627203 232.78571,35.443283 C 237.97804,34.575133 246.63024,34.312223 244.80238,35.078133 C 243.13487,35.776853 243.45335,36.040973 246.80238,36.736733 C 248.99321,37.191873 251.12321,37.655403 251.53571,37.766793 C 251.94821,37.878183 252.98727,38.025573 253.84473,38.094323 C 254.70219,38.163073 255.12563,38.669323 254.78571,39.219323 C 254.44579,39.769323 254.69672,40.219323 255.34332,40.219323 C 256.06382,40.219323 256.2995,39.348233 255.95208,37.969323 C 255.41894,35.853313 255.46759,35.829503 256.76891,37.569463 C 257.58055,38.654673 258.65747,39.107593 259.37368,38.664953 C 260.15395,38.182723 260.33716,38.327063 259.8812,39.064813 C 259.41126,39.825203 260.06142,40.219323 261.78571,40.219323 C 263.22563,40.219323 264.14485,40.638233 263.82842,41.150223 C 263.51198,41.662223 263.71043,42.363783 264.2694,42.709243 C 265.2198,43.296623 265.69613,42.025323 265.38965,39.719323 C 265.31655,39.169323 265.93826,39.592833 266.77123,40.660453 C 267.60419,41.728073 268.28571,43.013723 268.28571,43.517443 C 268.28571,44.021163 268.9463,44.179813 269.75368,43.869983 C 270.56107,43.560163 271.46286,43.696943 271.75766,44.173933 C 272.05245,44.650923 273.07936,44.923583 274.03968,44.779833 C 275,44.636083 276.379,45.358693 277.10413,46.385633 C 277.82926,47.412563 278.81067,48.012913 279.28503,47.719743 C 279.7594,47.426573 280.39864,47.593023 280.70557,48.089653 C 281.0125,48.586273 282.84359,49.289003 284.77466,49.651273 C 286.70574,50.013543 288.2926,50.852053 288.30102,51.514633 C 288.31192,52.372013 288.52814,52.398303 289.05102,51.605813 C 290.01493,50.144893 292.78571,51.308513 292.78571,53.174243 C 292.78571,53.974443 293.7021,54.874443 294.82212,55.174243 C 297.18591,55.806953 309.73388,64.080133 313.03571,67.182883 C 314.27321,68.345773 315.28571,69.092223 315.28571,68.841653 C 315.28571,68.591073 316.86071,69.915593 318.78571,71.785023 C 322.23577,75.135493 323.38534,77.016963 321.1312,75.623833 C 320.45237,75.204293 320.24677,75.347303 320.6322,75.970933 C 320.99272,76.554283 322.21384,76.789373 323.34579,76.493363 C 324.8579,76.097933 325.55178,76.520763 325.96142,78.087243 C 326.26807,79.259883 327.06034,80.219323 327.72201,80.219323 C 329.06236,80.219323 332.50346,83.889153 334.28571,87.219323 C 334.92472,88.413333 336.42364,90.512843 337.61663,91.884903 C 338.80962,93.256973 339.83534,94.681013 339.896,95.049443 C 340.67831,99.800803 341.77824,102.22161 343.16071,102.23463 C 344.57518,102.24796 344.59138,102.37553 343.28571,103.21932 C 341.98004,104.06311 341.99624,104.19068 343.41071,104.20401 C 345.04625,104.21942 346.21263,107.74013 346.356,113.09432 C 346.41825,115.41939 346.51634,115.4908 347.21446,113.71932 C 347.90323,111.97156 348.09357,112.12921 348.72363,114.96932 C 349.12017,116.75682 349.94887,118.21932 350.56517,118.21932 C 351.32754,118.21932 351.28883,118.6162 350.44407,119.46096 C 349.45521,120.44982 349.01043,120.39892 348.25938,119.21096 C 347.74071,118.39056 347.30944,118.07265 347.30102,118.5045 C 347.2926,118.93635 348.04363,120.44642 348.96997,121.8602 C 350.42883,124.08669 350.49868,125.17233 349.49194,129.972 C 348.34449,135.44252 346.04081,139.21932 343.85148,139.21932 C 343.23314,139.21932 342.11985,140.06201 341.3775,141.09197 C 340.57274,142.20851 339.27231,142.76707 338.15674,142.47534 C 336.82516,142.12713 336.2813,142.52424 336.2704,143.85269 C 336.26104,144.99374 335.9695,145.28674 335.5204,144.60645 C 335.11632,143.99437 333.66071,143.61937 332.28571,143.77312 C 330.91071,143.92686 329.42165,144.09015 328.97669,144.13599 C 328.53173,144.18182 328.39796,144.59193 328.67943,145.04735 C 328.96089,145.50276 326.51516,145.50941 323.24447,145.06211 C 316.11345,144.08688 301.36349,138.58558 300.60915,136.6198 C 300.31357,135.84954 299.62609,135.21932 299.08141,135.21932 C 298.53674,135.21932 295.23721,132.29432 291.74912,128.71932 C 288.26104,125.14432 286.05483,122.21932 286.84643,122.21932 C 287.63803,122.21932 288.28571,121.83172 288.28571,121.35799 C 288.28571,120.88426 287.16071,120.71172 285.78571,120.97457 C 283.99827,121.31626 283.28571,121.01547 283.28571,119.91923 C 283.28571,119.07595 283.62321,118.19724 284.03571,117.96655 C 284.44821,117.73586 284.19376,117.69553 283.47027,117.87694 C 281.86738,118.27885 273.28571,110.42541 273.28571,108.55664 C 273.28571,107.82111 272.83571,107.21932 272.28571,107.21932 C 270.98281,107.21932 267.87814,103.95097 267.45696,102.13599 C 267.27614,101.35682 266.48864,100.00889 265.70696,99.140583 C 264.92527,98.272273 264.28571,97.282963 264.28571,96.942103 C 264.28571,96.601253 263.16071,95.108473 261.78571,93.624823 C 260.41071,92.141173 259.28571,90.317983 259.28571,89.573303 C 259.28571,88.828613 258.93804,88.219323 258.51311,88.219323 C 256.98924,88.219323 254.18639,81.641713 254.90846,79.760053 C 255.31657,78.696523 255.22918,78.135393 254.70565,78.457843 C 253.1902,79.391253 253.22182,72.965773 254.74412,70.642453 C 255.74437,69.115873 255.8444,68.178013 255.08768,67.421293 C 254.50054,66.834153 254.33368,65.536703 254.71688,64.538093 C 255.33602,62.924633 255.59935,63.028523 257.08128,65.470873 C 259.44625,69.368543 260.34305,68.882213 258.40924,64.750733 C 257.32277,62.429533 255.70758,60.914293 253.5265,60.170143 C 251.73394,59.558543 250.52578,58.639893 250.84171,58.128713 C 251.15764,57.617523 250.14929,57.267303 248.60092,57.350443 C 244.09696,57.592283 242.13045,57.279553 242.66961,56.407173 C 242.94568,55.960493 239.70973,55.625153 235.47863,55.661973 C 231.24752,55.698793 226.77321,55.400403 225.53571,54.998873 C 224.03166,54.510863 223.28063,54.675033 223.2704,55.494073 C 223.2606,56.278023 222.90594,56.179063 222.28571,55.219323 C 221.63946,54.219323 221.31123,54.135993 221.30102,54.969323 C 221.2926,55.656823 220.35915,56.219323 219.22669,56.219323 C 217.90845,56.219323 217.39547,55.769603 217.80085,54.969323 C 218.1491,54.281823 217.78283,54.514643 216.98692,55.486693 C 216.05886,56.620163 214.8974,57.007543 213.74872,56.566753 C 212.37924,56.041233 212.15912,56.213693 212.81362,57.299383 C 213.5443,58.511423 213.4219,58.518383 211.97767,57.346873 C 210.87513,56.452553 210.28571,56.365453 210.28571,57.096873 C 210.28571,57.714223 209.73825,58.219323 209.06914,58.219323 C 206.75367,58.219323 199.32808,61.478873 199.82221,62.278373 C 200.09508,62.719893 199.81068,63.394873 199.19022,63.778343 C 198.56976,64.161803 197.72485,63.929863 197.31264,63.262903 C 196.79689,62.428403 196.39847,62.680113 196.03499,64.070073 C 195.64824,65.549023 194.94162,65.942103 193.39625,65.537983 C 192.23545,65.234423 191.28571,65.451843 191.28571,66.021133 C 191.28571,66.590423 189.70791,68.031343 187.77948,69.223173 C 185.85105,70.415003 184.52442,71.796553 184.83142,72.293283 C 185.13841,72.790003 184.70828,72.934973 183.87557,72.615433 C 182.98141,72.272313 181.3779,73.095823 179.95896,74.626883 C 178.63753,76.052723 177.14386,77.219323 176.63968,77.219323 C 174.7116,77.219323 165.56059,87.021923 163.52343,91.269513 C 161.65137,95.172853 159.24787,100.74681 158.80185,102.21932 C 158.71855,102.49432 157.47768,106.54432 156.04435,111.21932 C 153.68523,118.91391 153.0983,121.23645 151.87365,127.72322 C 151.66558,128.82536 151.00807,131.53668 150.41252,133.74838 C 149.09234,138.65116 149.1617,146.1923 150.5049,143.79214 C 150.99388,142.91838 151.11492,141.75199 150.77387,141.20016 C 149.76105,139.56139 157.93359,131.87022 159.89001,132.62097 C 161.22374,133.13277 161.33482,132.98342 160.43068,131.894 C 159.54895,130.83158 159.78094,130.09475 161.46114,128.62111 C 162.91428,127.34661 163.38342,127.21408 162.88345,128.21932 C 162.32934,129.33339 162.48144,129.30327 163.47458,128.10227 C 165.13465,126.09476 172.02847,122.91853 179.29402,120.81369 C 183.6827,119.54228 202.58345,118.39178 205.28571,119.23155 C 210.12719,120.73613 217.28848,121.66405 217.30102,120.78843 C 217.30944,120.20042 217.70913,120.33947 218.18922,121.09744 C 218.69771,121.90024 219.59074,122.14884 220.32842,121.69293 C 221.15289,121.18338 221.34576,121.31313 220.8812,122.06481 C 220.44406,122.77212 220.8684,123.23246 221.97669,123.25325 C 222.97165,123.27191 225.58571,124.15664 227.78571,125.21932 C 229.98571,126.282 232.40593,127.16673 233.16398,127.18539 C 233.92203,127.20405 237.07203,128.66671 240.16398,130.43575 C 243.25593,132.20478 245.89821,133.55478 246.03571,133.43575 C 246.99513,132.60517 248.39856,133.48285 247.95584,134.63656 C 247.42523,136.01931 250.0549,137.78347 251.0955,136.74286 C 251.38345,136.45491 251.01904,136.21932 250.28571,136.21932 C 249.55238,136.21932 249.22871,135.94299 249.56644,135.60525 C 250.5884,134.5833 257.02122,139.09992 257.57842,141.23062 C 257.86445,142.32441 258.7031,143.21243 259.44209,143.20401 C 260.4713,143.19228 260.43471,142.94046 259.28571,142.12788 C 257.95238,141.18493 257.95238,141.11255 259.28571,141.47652 C 260.11071,141.70173 260.78571,142.44726 260.78571,143.13326 C 260.78571,144.63825 264.12149,147.21932 266.06655,147.21932 C 266.83576,147.21932 268.35904,148.23182 269.45161,149.46932 C 270.54417,150.70682 271.10927,151.08729 270.70739,150.31481 C 270.22674,149.39094 270.37178,149.15448 271.1312,149.62383 C 271.76618,150.01627 272.28571,151.01235 272.28571,151.83735 C 272.28571,152.66235 272.62886,153.12528 273.04826,152.86607 C 273.46766,152.60687 274.93016,153.01436 276.29826,153.77162 C 277.66636,154.52888 278.3622,155.1644 277.84458,155.18388 C 277.32696,155.20337 277.77696,155.85804 278.84458,156.63871 C 279.9122,157.41937 280.80616,158.65687 280.83116,159.38871 C 280.85616,160.12054 281.42855,160.60352 282.10313,160.462 C 282.77771,160.32047 283.75862,161.33297 284.28293,162.712 C 284.86318,164.23817 286.02107,165.21932 287.24191,165.21932 C 288.54585,165.21932 289.46654,166.09161 289.87333,167.71241 C 290.21748,169.08361 290.93134,169.93833 291.45969,169.61179 C 291.98804,169.28526 292.65938,169.93223 292.95155,171.04951 C 293.26709,172.25614 294.04137,172.86658 294.85855,172.553 C 296.33498,171.98644 299.28571,174.38245 299.28571,176.14789 C 299.28571,176.73718 299.74249,177.21932 300.30077,177.21932 C 301.57102,177.21932 310.28571,185.61411 310.28571,186.83773 C 310.28571,187.333 311.18571,188.30029 312.28571,188.98725 C 313.38571,189.67421 314.28571,190.662 314.28571,191.18234 C 314.28571,191.70268 315.3616,193.20431 316.67659,194.51929 C 318.39753,196.24023 318.95406,197.72404 318.66273,199.81474 C 318.32476,202.24023 318.41364,202.38943 319.20157,200.71932 C 320.05404,198.91242 320.15193,198.98484 320.21542,201.46932 C 320.30126,204.82759 320.01565,205.79597 319.03571,205.46932 C 317.19115,204.85447 318.52101,206.37835 320.53571,207.18816 C 321.85784,207.71959 322.16713,208.12978 321.28571,208.18283 C 320.46071,208.23249 318.71842,210.00455 317.41396,212.12076 C 315.6109,215.04583 314.56152,215.8427 313.03749,215.44416 C 311.78688,215.11712 310.68106,215.54838 310.09778,216.59065 C 309.58354,217.50955 308.73699,217.99823 308.21658,217.67659 C 307.01607,216.93464 304.16171,219.72373 304.51785,221.29075 C 304.66517,221.93896 304.2229,222.67567 303.53503,222.92788 C 302.75129,223.21524 302.50136,222.82093 302.86559,221.87176 C 303.364,220.57292 302.93658,220.51367 299.86627,221.45598 C 297.89696,222.06038 296.28571,222.87635 296.28571,223.26926 C 296.28571,223.66217 294.59821,223.38142 292.53571,222.64537 C 290.47321,221.90933 287.53833,221.28735 286.01375,221.26321 C 284.48918,221.23907 280.27555,219.87436 276.65014,218.23052 C 273.02473,216.58668 269.59008,215.53121 269.01759,215.88503 C 268.4146,216.2577 268.27577,216.04442 268.68759,215.37808 C 269.11154,214.69212 268.37928,213.76344 266.87346,213.07735 C 265.48469,212.44458 264.62884,211.47314 264.97158,210.91858 C 265.3196,210.35546 265.09797,210.21731 264.46959,210.60568 C 263.03822,211.49031 257.71438,208.7788 256.94475,206.77316 C 256.62392,205.93709 255.7149,205.50113 254.92471,205.80435 C 254.13453,206.10758 253.14796,205.80546 252.73235,205.13299 C 252.20973,204.28736 252.40983,204.1575 253.3812,204.71188 C 254.15368,205.15275 253.79203,204.54727 252.57752,203.36639 C 251.36302,202.1855 249.87396,201.21932 249.26851,201.21932 C 248.66305,201.21932 248.49305,200.69285 248.89074,200.04938 C 249.38014,199.25751 249.06383,199.09048 247.9119,199.53252 C 246.79532,199.961 245.99079,199.58954 245.57261,198.45246 C 245.22205,197.49923 244.22683,195.61448 243.361,194.26412 C 241.45053,191.28448 239.32135,185.36152 239.30077,182.96932 C 239.29249,182.00682 238.72321,181.21243 238.03571,181.20401 C 237.26158,181.19452 237.1664,180.909 237.78571,180.45401 C 239.22819,179.39424 239.48204,177.21932 238.16327,177.21932 C 237.41803,177.21932 237.36467,176.79924 238.00446,175.96932 C 238.53447,175.28182 238.6634,173.59432 238.29098,172.21932 C 237.91857,170.84432 237.91292,168.81932 238.27843,167.71932 C 238.64394,166.61932 239.06056,163.47664 239.20425,160.7356 C 239.34795,157.99455 239.87506,154.98663 240.37561,154.05134 C 241.64165,151.68573 241.68457,151.74911 237.77846,150.21648 C 235.18379,149.19841 234.41379,148.39115 234.81914,147.11399 C 235.1205,146.16449 234.82229,145.05094 234.15645,144.63943 C 233.32848,144.12772 233.14378,144.40708 233.5721,145.52325 C 234.29371,147.40373 232.75791,148.79238 231.75366,147.16746 C 231.38502,146.57099 230.49792,146.30765 229.78233,146.58225 C 227.85992,147.31994 227.12837,146.11383 228.49757,144.46405 C 229.47198,143.28995 229.33219,143.0639 227.73889,143.2372 C 226.66464,143.35403 225.56071,143.36125 225.28571,143.25323 C 224.80439,143.06417 220.67791,142.43769 217.03571,142.00071 C 216.07321,141.88523 215.28571,141.15969 215.28571,140.3884 C 215.28571,139.47862 214.58358,139.16967 213.28671,139.50881 C 212.18725,139.79632 211.02438,139.6055 210.70255,139.08476 C 210.38071,138.56402 209.29314,138.39957 208.28571,138.71932 C 207.27828,139.03907 206.20218,138.89319 205.89438,138.39515 C 205.58658,137.89711 203.7797,137.66099 201.87911,137.87044 C 199.97851,138.07988 198.14092,137.79406 197.79558,137.23528 C 197.45023,136.6765 196.71768,136.21932 196.16768,136.21932 C 195.61768,136.21932 195.41665,136.62217 195.72095,137.11454 C 196.02525,137.6069 195.5517,138.28701 194.66863,138.62588 C 193.52145,139.06609 193.22862,138.81049 193.64298,137.73066 C 194.38897,135.78664 192.58236,135.77981 190.64285,137.71932 C 188.61586,139.74631 186.91862,139.61833 187.73157,137.4998 C 188.09449,136.55407 188.07154,136.10016 187.68057,136.49112 C 187.28961,136.88209 186.40123,136.73015 185.70639,136.15349 C 184.74622,135.35662 184.56331,135.56484 184.94416,137.02121 C 185.34111,138.53916 184.77198,139.07207 182.20576,139.58531 C 180.42404,139.94165 178.73814,140.00508 178.45932,139.72626 C 178.1805,139.44745 178.72893,139.21932 179.67806,139.21932 C 180.62719,139.21932 181.14882,138.80684 180.83724,138.3027 C 180.5144,137.78033 178.56556,138.0559 176.30618,138.94342 C 174.12566,139.79995 172.56137,140.85633 172.82997,141.29093 C 173.09857,141.72554 172.86099,142.36378 172.30202,142.70924 C 171.74305,143.0547 171.28571,142.60924 171.28571,141.71932 C 171.28571,140.8294 170.85536,140.36725 170.32938,140.69233 C 169.8034,141.0174 169.62655,141.94396 169.93637,142.75135 C 170.35997,143.85522 169.66706,144.23675 167.1427,144.28961 C 164.83916,144.33783 164.33371,144.57689 165.53199,145.05138 C 167.12708,145.68301 167.09637,145.85647 165.17734,147.05492 C 163.43804,148.14114 163.20809,148.13911 163.84139,147.04314 C 164.29009,146.26665 164.22999,146.06386 163.69604,146.55265 C 163.19536,147.01099 162.78424,147.68599 162.78245,148.05265 C 162.78065,148.41932 161.54315,150.3368 160.03245,152.31371 C 158.52174,154.29063 157.28571,156.42813 157.28571,157.06371 C 157.28571,157.6993 156.86155,158.21932 156.34313,158.21932 C 155.82471,158.21932 155.65053,159.23182 155.95606,160.46932 C 156.2616,161.70682 156.5646,164.3692 156.62941,166.38571 C 156.69422,168.40223 157.07978,169.84659 157.48622,169.5954 C 157.89265,169.34421 158.85413,170.61933 159.62285,172.42901 C 160.39157,174.23868 162.19363,176.96753 163.62743,178.49313 C 165.06123,180.01872 166.23251,181.49132 166.23027,181.76557 C 166.22412,182.51937 169.37359,186.92205 173.24256,191.56814 C 175.14382,193.85129 177.39382,196.61932 178.24256,197.71932 C 179.7714,199.70077 179.76485,199.70166 177.53571,197.81433 C 175.51162,196.10061 175.28571,196.07866 175.28571,197.59572 C 175.28571,198.52322 175.95813,199.54012 176.77997,199.85549 C 177.60181,200.17086 178.02609,200.83038 177.72282,201.32108 C 177.41954,201.81179 178.32213,201.77577 179.72856,201.24105 C 182.30011,200.26335 183.08675,201.0034 181.35303,202.76932 C 179.95649,204.19179 182.83901,207.60471 184.80105,206.85181 C 185.68733,206.51171 186.13239,205.78027 185.79008,205.22638 C 184.30127,202.81744 187.06639,204.52362 189.79524,207.69771 C 191.44,209.61082 193.68571,211.19271 194.78571,211.21302 C 196.38803,211.2426 196.49782,211.43208 195.33786,212.16592 C 194.2158,212.8758 194.55332,213.24547 196.83786,213.8088 C 201.41111,214.9365 204.47534,217.28074 203.77669,219.11724 C 203.28827,220.40112 203.41733,220.47105 204.42646,219.46932 C 206.22182,217.68715 207.28571,217.92282 207.28571,220.10269 C 207.28571,221.20376 208.20215,222.22571 209.49204,222.56303 C 212.34224,223.30837 213.08493,222.60776 210.36107,221.74324 C 209.21962,221.38096 208.28571,220.65922 208.28571,220.13939 C 208.28571,219.61955 210.07677,220.32488 212.26584,221.70678 C 214.45491,223.08867 216.70491,224.21932 217.26584,224.21932 C 217.82677,224.21932 218.28571,224.82209 218.28571,225.5588 C 218.28571,226.97373 222.33829,229.21932 224.89178,229.21932 C 225.76086,229.21932 226.10687,228.73896 225.70553,228.08959 C 225.27791,227.39768 225.5457,227.15547 226.39651,227.46459 C 227.16057,227.74219 227.64782,228.55174 227.47929,229.26359 C 227.2288,230.32158 227.457,230.32205 228.72929,229.26615 C 230.18033,228.06189 230.74193,228.5176 230.36324,230.592 C 230.27561,231.07198 230.86825,231.20976 231.68021,230.89818 C 232.49217,230.5866 233.33739,230.86889 233.55848,231.5255 C 233.85746,232.41342 234.38649,232.36765 235.62309,231.34688 C 237.05402,230.16569 237.28571,230.20053 237.28571,231.59688 C 237.28571,233.45004 238.83291,233.76098 239.85169,232.11256 C 240.33174,231.33582 240.77758,231.39716 241.34684,232.31823 C 241.79296,233.04007 243.64921,233.78893 245.47184,233.98237 C 247.29447,234.1758 249.31516,235.02406 249.96227,235.86739 C 250.71258,236.84521 251.89002,237.1623 253.21227,236.74263 C 254.51327,236.32971 255.28571,236.52564 255.28571,237.26856 C 255.28571,237.96025 256.11733,238.23511 257.28571,237.92957 C 258.38571,237.64191 259.28571,237.80031 259.28571,238.28155 C 259.28571,238.7628 259.96071,238.89753 260.78571,238.58095 C 261.66224,238.24459 262.29207,238.56937 262.30102,239.36233 C 262.31284,240.40941 262.53772,240.37675 263.28571,239.21932 C 263.85583,238.33712 264.26139,238.2054 264.2704,238.89951 C 264.28123,239.73472 265.16266,239.8282 267.28571,239.21932 C 269.08559,238.70312 270.28571,238.73105 270.28571,239.28913 C 270.28571,239.80073 271.29821,240.22546 272.53571,240.23297 C 276.26761,240.25562 279.30348,241.38155 278.61897,242.48911 C 278.19449,243.17593 279.06807,243.31285 281.17993,242.89048 C 283.09125,242.50821 284.15024,242.62951 283.80325,243.19094 C 283.46749,243.73421 284.59026,243.9592 286.45769,243.72287 C 288.23766,243.4976 290.36352,243.85464 291.18182,244.5163 C 292.00011,245.17796 292.39297,245.25598 292.05484,244.68968 C 291.68757,244.07457 292.51614,243.72227 294.11288,243.81462 C 295.58294,243.89964 296.67861,244.45928 296.54771,245.05827 C 296.4168,245.65726 296.9793,245.89039 297.79771,245.57634 C 298.61611,245.26229 299.28571,245.50349 299.28571,246.11233 C 299.28571,246.72118 299.76227,247.21932 300.34473,247.21932 C 300.92719,247.21932 301.09583,246.72111 300.7195,246.11219 C 300.24918,245.3512 300.77786,245.23701 302.41048,245.74697 C 303.71686,246.15502 305.09574,246.97284 305.47466,247.56434 C 305.93355,248.28067 306.79467,248.0687 308.0534,246.92956 C 309.09279,245.98893 310.6687,245.21932 311.55543,245.21932 C 312.44217,245.21932 313.42792,244.79824 313.74599,244.28359 C 314.09931,243.7119 313.1751,243.67745 311.37037,244.19504 C 309.01158,244.87153 308.52556,244.75785 308.95806,243.63077 C 309.25596,242.85447 310.12654,242.21932 310.8927,242.21932 C 311.65885,242.21932 312.17321,241.67177 312.03571,241.00255 C 311.89821,240.33332 313.27928,239.02495 315.10476,238.09505 C 316.93023,237.16515 319.21567,235.6877 320.1835,234.81182 C 321.15133,233.93595 322.47026,233.21932 323.11445,233.21932 C 323.75864,233.21932 324.28571,232.76932 324.28571,232.21932 C 324.28571,231.66932 324.93519,231.21932 325.72901,231.21932 C 326.52282,231.21932 327.88148,230.20682 328.74826,228.96932 C 329.61504,227.73182 330.54056,226.83182 330.80497,226.96932 C 332.17492,227.68173 333.29445,227.02568 333.36466,225.46932 C 333.41622,224.32633 333.62562,224.1741 333.96837,225.03045 C 334.37188,226.03862 334.95556,225.92309 336.49441,224.53045 C 337.59511,223.53433 338.67344,222.83182 338.8907,222.96932 C 339.96991,223.65235 341.25685,223.0804 341.03571,222.01603 C 340.89821,221.35421 341.46071,220.74776 342.28571,220.66834 C 346.00771,220.31006 346.36771,220.16101 345.78571,219.21932 C 345.44579,218.66932 345.89579,218.21932 346.78571,218.21932 C 347.67563,218.21932 348.12563,218.66932 347.78571,219.21932 C 347.44579,219.76932 347.89579,220.21932 348.78571,220.21932 C 349.67563,220.21932 350.13958,219.7919 349.81672,219.26949 C 349.49385,218.74709 350.23329,217.78256 351.4599,217.1261 C 353.189,216.20071 353.77972,216.20135 354.08891,217.12892 C 354.3669,217.96289 354.83579,217.8555 355.63671,216.77443 C 357.08389,214.82107 368.93211,214.14642 368.53214,216.04016 C 368.34035,216.94825 368.7985,216.9336 370.4128,215.98002 C 372.11717,214.97323 372.63819,214.97108 372.9997,215.96932 C 373.24867,216.65682 373.89143,217.21932 374.42806,217.21932 C 374.96469,217.21932 375.16039,216.82557 374.86296,216.34432 C 374.56554,215.86307 375.43898,215.46932 376.80395,215.46932 C 378.16892,215.46932 379.28571,215.82094 379.28571,216.2507 C 379.28571,216.68046 380.25608,216.77832 381.44208,216.46818 C 382.80506,216.11175 383.36017,216.28982 382.95083,216.95215 C 382.56955,217.56908 383.69295,218.26074 385.68249,218.63398 C 390.14054,219.47031 397.66083,225.29651 399.25734,229.15083 C 399.9564,230.8385 401.10457,232.21932 401.80884,232.21932 C 402.62981,232.21932 403.33918,234.37195 403.78553,238.21777 C 404.16844,241.51691 404.84919,243.98911 405.29831,243.71154 C 405.74743,243.43396 406.30247,243.76959 406.53173,244.45737 C 407.08216,246.10868 405.18189,252.21932 404.11793,252.21932 C 403.66021,252.21932 403.28571,253.76776 403.28571,255.6603 C 403.28571,257.55284 402.83571,259.3794 402.28571,259.71932 C 401.73571,260.05924 401.28571,259.7858 401.28571,259.11167 C 401.28571,258.43754 401.02425,258.14745 400.70469,258.46701 C 400.38513,258.78657 400.6294,259.99299 401.24751,261.14795 C 401.86563,262.3029 402.01459,263.18816 401.57853,263.11517 C 399.15143,262.70895 398.12403,263.3556 398.72176,264.91325 C 399.27577,266.357 399.05911,266.32422 397.25477,264.69132 C 396.09041,263.63759 395.28354,263.21282 395.46173,263.74738 C 395.63992,264.28195 395.46758,264.71932 395.07876,264.71932 C 394.68993,264.71932 393.7457,265.57557 392.98046,266.6221 C 392.21522,267.66862 391.10195,268.22378 390.50651,267.85578 C 389.91108,267.48779 389.12994,267.66234 388.77065,268.24369 C 388.41136,268.82503 387.30775,269.0437 386.31818,268.72963 C 385.32861,268.41555 382.42314,268.62826 379.86158,269.20232 C 376.60735,269.93161 374.60962,269.92785 373.23068,269.18987 C 371.73165,268.38761 371.3207,268.44115 371.52144,269.41253 C 371.70917,270.32101 370.13417,270.72881 366.08309,270.82063 C 361.60565,270.92211 360.28779,270.60284 359.94909,269.3346 C 359.5821,267.9604 359.5004,267.98051 359.40171,269.46932 C 359.26396,271.54751 353.75696,271.97416 352.94799,269.96932 C 352.54448,268.96932 352.42782,268.96932 352.36466,269.96932 C 352.32124,270.65682 351.82714,271.21932 351.26666,271.21932 C 350.69076,271.21932 350.48237,270.02343 350.78744,268.46932 C 351.30451,265.83534 351.27777,265.81425 350.15368,267.96932 C 349.5082,269.20682 348.26135,270.25095 347.3829,270.28961 C 346.19095,270.34206 346.29315,270.57795 347.78571,271.21932 C 349.69407,272.03937 349.68261,272.08197 347.53571,272.14903 C 346.17114,272.19166 345.28571,271.62903 345.28571,270.71932 C 345.28571,269.89432 344.61071,269.21932 343.78571,269.21932 C 342.96071,269.21932 342.28571,269.59432 342.28571,270.05265 C 342.28571,270.51099 341.63571,270.88599 340.84127,270.88599 C 340.04682,270.88599 339.48432,270.40341 339.59127,269.81359 C 339.70035,269.21198 338.61575,268.87268 337.12067,269.04069 C 335.22934,269.25324 334.31949,268.81458 333.98667,267.52975 C 333.54406,265.82103 333.5112,265.82365 333.40171,267.57631 C 333.32801,268.75617 332.76231,269.23245 331.85032,268.88249 C 331.06085,268.57954 330.16085,268.86889 329.85032,269.5255 C 329.42075,270.43379 329.14619,270.42035 328.70238,269.46932 C 328.38154,268.78182 327.48154,268.21932 326.70238,268.21932 C 325.92321,268.21932 325.23351,267.20682 325.16971,265.96932 C 325.09637,264.54688 324.89687,264.30393 324.6273,265.30879 C 324.3268,266.42894 322.86536,266.94878 319.67776,267.06934 C 317.06321,267.16824 315.40015,266.84317 315.73648,266.29897 C 316.0565,265.78117 315.86099,265.07486 315.30202,264.7294 C 314.74305,264.38394 314.28571,264.57784 314.28571,265.1603 C 314.28571,265.74276 313.38571,266.21932 312.28571,266.21932 C 311.18571,266.21932 310.28571,265.80073 310.28571,265.28913 C 310.28571,264.76351 309.08963,264.67744 307.53571,265.09123 C 304.12105,266.00052 303.29408,265.93208 300.78571,264.5326 C 299.68571,263.91888 296.13401,263.13421 292.89304,262.78887 C 289.65206,262.44354 286.50206,261.84785 285.89304,261.46512 C 285.28401,261.08238 283.99821,260.89879 283.03571,261.05714 C 282.07321,261.21548 281.28316,260.97925 281.28005,260.53218 C 281.27694,260.08511 279.4152,259.64802 277.14286,259.56087 C 274.87051,259.47372 271.05914,258.85584 268.67313,258.1878 C 266.28713,257.51976 263.42325,257.2116 262.30895,257.50299 C 261.19465,257.79439 260.53513,257.62477 260.84335,257.12606 C 261.15157,256.62735 260.70219,256.21932 259.84473,256.21932 C 258.98727,256.21932 258.28571,255.68331 258.28571,255.02819 C 258.28571,254.37307 257.57734,254.71057 256.71155,255.77819 C 255.84577,256.84581 255.46288,257.09119 255.86071,256.32348 C 256.43266,255.21971 255.97738,255.06913 253.68486,255.60385 C 251.78128,256.04786 251.26033,255.96378 252.16784,255.35902 C 253.25638,254.63361 253.07055,254.28581 251.29299,253.72163 C 249.82058,253.25431 248.73712,253.47702 248.17618,254.36231 C 247.45216,255.50496 247.31392,255.50497 247.30102,254.36233 C 247.29207,253.56937 246.66224,253.24459 245.78571,253.58095 C 244.872,253.93157 244.28571,253.58253 244.28571,252.68794 C 244.28571,251.8802 243.80915,251.21932 243.22669,251.21932 C 242.64423,251.21932 242.41985,251.62735 242.72807,252.12606 C 243.03629,252.62477 242.34981,252.78734 241.20256,252.48732 C 239.72626,252.10126 239.48223,251.7159 240.36756,251.16873 C 241.1563,250.68127 239.66405,249.81522 236.32869,248.82472 C 233.4193,247.96073 230.5749,247.54059 230.0078,247.89108 C 229.413,248.25869 229.27862,248.03982 229.69022,247.37383 C 230.10657,246.70016 229.78849,246.21932 228.92651,246.21932 C 228.11404,246.21932 226.66366,245.91785 225.70345,245.54938 C 224.52111,245.09567 224.18871,245.25336 224.6736,246.03793 C 225.14082,246.79389 224.85236,246.99026 223.84339,246.60308 C 222.99298,246.27675 222.52354,245.64352 222.80018,245.19591 C 223.07682,244.74829 221.96778,244.08877 220.33565,243.73029 C 218.70352,243.37181 215.1018,241.9852 212.33183,240.64892 C 209.56186,239.31264 206.84331,238.21932 206.29061,238.21932 C 205.73792,238.21932 205.28571,237.86508 205.28571,237.43212 C 205.28571,236.99917 204.3137,236.57171 203.12569,236.48222 C 201.93767,236.39273 200.59457,235.73447 200.141,235.01941 C 199.68743,234.30436 199.30944,234.07265 199.30102,234.5045 C 199.2926,234.93635 198.27321,234.72825 197.03571,234.04205 C 195.79821,233.35585 194.33571,232.92752 193.78571,233.0902 C 193.23571,233.25288 193.09673,233.07496 193.47687,232.69482 C 193.85701,232.31468 190.70701,229.40943 186.47687,226.2387 C 182.24673,223.06797 175.23802,217.02668 170.90196,212.81361 C 166.5659,208.60054 162.75393,205.41776 162.43092,205.74077 C 162.10791,206.06378 162.5056,206.74671 163.31467,207.25838 C 164.12374,207.77005 164.39311,208.19559 163.91327,208.20401 C 163.43342,208.21243 163.5647,208.85056 164.205,209.62207 C 165.03861,210.6265 165.05566,211.12934 164.26506,211.39287 C 163.49006,211.6512 163.45967,212.54667 164.16311,214.39686 C 164.71431,215.84663 165.46761,219.88727 165.8371,223.37606 C 166.20659,226.86485 167.06821,230.17105 167.75179,230.72316 C 169.40135,232.05546 170.9156,236.72664 169.39284,235.78553 C 167.67939,234.72656 168.08617,235.81258 169.97767,237.34688 C 171.4219,238.51838 171.5443,238.51142 170.81362,237.29938 C 170.16339,236.22077 170.37729,236.04048 171.70345,236.54938 C 172.66366,236.91785 173.66404,237.21932 173.92651,237.21932 C 174.18899,237.21932 174.14485,237.63823 173.82842,238.15022 C 173.51198,238.66222 173.71043,239.36378 174.2694,239.70924 C 174.82837,240.0547 175.28571,240.78735 175.28571,241.33735 C 175.28571,241.88735 174.76618,242.01627 174.1312,241.62383 C 173.4159,241.18175 173.24814,241.34951 173.69022,242.06481 C 174.08266,242.69979 175.25063,243.21932 176.28571,243.21932 C 177.32079,243.21932 178.49305,243.74579 178.89074,244.38926 C 179.37563,245.17383 179.0705,245.35071 177.96439,244.92626 C 176.54841,244.3829 176.48847,244.57113 177.54089,246.25632 C 178.86049,248.36934 180.88794,249.04739 179.67283,246.96932 C 179.27083,246.28182 179.91768,246.57513 181.11028,247.62111 C 182.50413,248.8436 182.95369,249.91517 182.36889,250.62111 C 181.21072,252.01918 184.4836,256.21932 186.73119,256.21932 C 189.14158,256.21932 193.36757,259.27786 192.62262,260.48321 C 192.23385,261.11225 192.46312,261.22771 193.19851,260.77321 C 193.97541,260.29306 194.61929,260.77891 194.96671,262.10746 C 195.26722,263.25661 195.91511,263.94836 196.40646,263.64469 C 196.89782,263.34102 197.56881,263.79349 197.89756,264.65019 C 198.2263,265.5069 198.78585,266.02825 199.14099,265.80876 C 199.49613,265.58927 201.13648,266.5065 202.7862,267.84705 C 204.90903,269.57202 205.20116,270.10119 203.78571,269.65753 C 202.26843,269.18196 202.12586,269.27245 203.19503,270.03247 C 203.97015,270.58346 205.23449,270.79247 206.00468,270.49692 C 206.86071,270.16843 207.62037,270.78307 207.95906,272.07819 C 208.26377,273.24344 208.86478,273.97947 209.29462,273.71382 C 210.11519,273.20667 211.73525,276.12636 211.41969,277.54365 C 211.31875,277.99703 211.70465,278.07844 212.27725,277.72455 C 212.84984,277.37067 213.03572,276.62385 212.69031,276.06496 C 212.3449,275.50607 213.80006,276.17024 215.924,277.54089 C 218.04794,278.91154 219.67321,280.5249 219.53571,281.12615 C 219.39821,281.72739 220.18571,282.21932 221.28571,282.21932 C 222.38571,282.21932 223.28571,282.69588 223.28571,283.27834 C 223.28571,283.8608 222.76618,284.01627 222.1312,283.62383 C 221.43907,283.19607 221.24724,283.34806 221.65223,284.00334 C 222.02377,284.60452 223.2183,284.92488 224.30674,284.71527 C 225.39517,284.50566 226.28571,284.75832 226.28571,285.27674 C 226.28571,285.79516 226.62321,286.14982 227.03571,286.06488 C 228.35556,285.79309 235.08923,289.12988 235.4589,290.23889 C 235.65494,290.827 236.78999,291.3816 237.98124,291.47134 C 239.17249,291.56107 239.95591,291.94392 239.72218,292.32212 C 239.48844,292.70032 239.99298,293.27675 240.84339,293.60308 C 241.80878,293.97354 242.13601,293.78612 241.71452,293.10414 C 241.34324,292.50339 242.20008,292.77233 243.61861,293.70179 C 245.03714,294.63125 246.73708,295.05839 247.39624,294.65101 C 248.15448,294.18239 248.33262,294.33439 247.8812,295.06481 C 247.22888,296.12029 248.49443,296.68793 250.64097,296.30265 C 251.11136,296.21823 252.05277,296.61103 252.73298,297.17556 C 253.41319,297.74008 254.26582,297.90587 254.62772,297.54398 C 254.98961,297.18208 255.28571,297.44849 255.28571,298.13599 C 255.28571,298.82349 255.84419,299.19983 256.52678,298.9723 C 257.20937,298.74477 258.42678,299.21753 259.23214,300.02289 C 260.22651,301.01727 260.81772,301.12328 261.0744,300.35325 C 261.28229,299.72959 261.89143,299.21932 262.42806,299.21932 C 262.96469,299.21932 263.12563,299.66932 262.78571,300.21932 C 262.44579,300.76932 263.09423,301.21932 264.22669,301.21932 C 265.35915,301.21932 266.28571,301.69168 266.28571,302.26901 C 266.28571,302.9447 266.86513,302.99444 267.91193,302.40862 C 269.60123,301.46324 275.28571,303.59662 275.28571,305.17598 C 275.28571,305.62158 276.41071,306.20122 277.78571,306.46407 C 279.16071,306.72692 280.28571,306.52224 280.28571,306.00922 C 280.28571,305.4962 280.99285,305.78361 281.85714,306.64789 C 282.72142,307.51218 284.18392,308.18769 285.10714,308.14903 C 286.46088,308.09235 286.39868,307.91244 284.78571,307.21932 C 283.03503,306.46703 283.00777,306.35113 284.56709,306.28961 C 285.54686,306.25095 286.60651,306.89174 286.92188,307.71358 C 287.23725,308.53542 287.93271,308.93749 288.46734,308.60707 C 289.00197,308.27664 291.37778,308.74657 293.74692,309.65136 C 296.11605,310.55614 298.44397,311.22578 298.92007,311.13944 C 299.39617,311.05311 300.12321,311.09202 300.53571,311.2259 C 300.94821,311.35978 302.07321,311.56443 303.03571,311.68069 C 303.99821,311.79694 305.59262,312.24628 306.57884,312.67923 C 307.56506,313.11217 308.63461,313.20375 308.95562,312.88274 C 309.27663,312.56173 310.88175,312.99331 312.52256,313.8418 C 314.16336,314.69029 315.20475,314.89734 314.83676,314.30192 C 314.46596,313.70195 314.8627,313.21932 315.72669,313.21932 C 316.58415,313.21932 317.28571,313.83272 317.28571,314.58243 C 317.28571,316.8061 328.05029,319.74666 331.46803,318.4566 C 333.23,317.79154 334.28571,317.75729 334.28571,318.3652 C 334.28571,318.89989 334.73215,319.06144 335.27779,318.72421 C 336.40941,318.02483 339.38435,319.44604 339.62531,320.80115 C 339.71353,321.29727 340.77417,321.65713 341.98229,321.60084 C 343.1904,321.54456 344.42275,322.13406 344.72083,322.91085 C 345.02009,323.6907 344.8201,324.04959 344.27426,323.71224 C 342.65567,322.7119 343.15245,323.86633 344.97767,325.34688 C 346.12733,326.27943 346.42893,326.31868 345.91865,325.46932 C 345.50561,324.78182 345.53173,324.22621 345.97669,324.23463 C 350.63248,324.32276 361.20185,346.90318 358.0586,350.04643 C 357.41842,350.68661 357.4507,351.66697 358.15168,352.87294 C 359.10511,354.51324 359.22829,354.41239 359.2553,351.96932 C 359.27203,350.45682 359.73571,349.21932 360.28571,349.21932 C 361.81661,349.21932 361.4742,352.88797 359.78571,354.57646 C 358.96071,355.40146 358.28571,356.86826 358.28571,357.83601 C 358.28571,361.69743 349.83142,370.4317 347.93216,368.53243 C 347.58335,368.18363 346.42357,368.68957 345.35485,369.65675 C 344.26204,370.64573 342.87895,371.08596 342.19421,370.66277 C 341.46076,370.20947 341.23463,370.32766 341.62546,370.96003 C 342.45565,372.30331 339.50797,373.58938 336.33168,373.2697 C 334.18784,373.05393 334.04532,373.22474 335.20413,374.62102 C 335.93369,375.50008 336.0806,376.21932 335.5306,376.21932 C 334.9806,376.21932 333.9704,375.54432 333.28571,374.71932 C 332.60102,373.89432 331.66004,373.21932 331.19465,373.21932 C 330.72926,373.21932 330.6075,373.89432 330.92408,374.71932 C 331.62351,376.54198 330.18338,376.68126 328.33901,374.96932 C 327.25876,373.96664 327.1361,373.97339 327.71908,375.0034 C 328.25971,375.95857 327.73285,376.15818 325.66216,375.78269 C 323.89817,375.46282 322.22041,375.87343 321.08208,376.9036 C 319.4766,378.35654 319.28571,378.36283 319.28571,376.96279 C 319.28571,375.38944 317.74123,375.17781 315.67808,376.46847 C 315.06889,376.84956 313.17064,376.75991 311.45976,376.26924 C 307.98425,375.27247 303.16201,372.21932 305.0632,372.21932 C 305.73558,372.21932 306.28571,371.55844 306.28571,370.7507 C 306.28571,369.79177 305.70821,369.5037 304.62167,369.92064 C 303.52247,370.34245 303.19691,370.17202 303.66256,369.41858 C 304.101,368.70917 303.31239,368.01804 301.57661,367.59045 C 300.04161,367.21232 297.67811,366.18663 296.32439,365.31113 C 294.84523,364.35452 294.17046,364.21812 294.6334,364.96932 C 295.66132,366.63728 294.24258,366.50141 291.86775,364.70446 C 290.64349,363.7781 289.54392,363.59006 288.8276,364.18455 C 287.33978,365.41934 279.49342,361.44829 277.53493,358.46932 C 276.72135,357.23182 275.50219,356.21932 274.82569,356.21932 C 273.56394,356.21932 270.28571,353.09362 270.28571,351.89058 C 270.28571,350.39834 272.08877,351.41941 276.1638,355.21932 C 278.52309,357.41932 281.12282,359.21932 281.94099,359.21932 C 283.16927,359.21932 283.19823,359.00113 282.10714,357.96756 C 280.11108,356.07674 271.92426,350.73798 270.78571,350.58467 C 270.23571,350.51061 269.27199,350.39811 268.64412,350.33467 C 268.01624,350.27123 267.20884,349.04918 266.84989,347.619 C 266.49094,346.18883 265.29732,343.80146 264.1974,342.31375 C 261.96431,339.29332 258.88847,328.6969 259.66069,326.68452 C 259.93499,325.9697 259.43759,325.10784 258.55535,324.7693 C 257.39391,324.32361 257.25321,323.85182 258.04547,323.05956 C 258.7394,322.36563 258.82392,321.13492 258.27653,319.69517 C 257.80181,318.44656 257.60967,317.2287 257.84955,316.98881 C 258.08944,316.74892 257.6305,316.55265 256.8297,316.55265 C 256.02889,316.55265 255.60545,316.92765 255.88872,317.38599 C 256.6746,318.65757 254.84475,318.37836 253.48571,317.01932 C 252.82571,316.35932 252.26976,316.24682 252.25027,316.76932 C 252.23079,317.29182 251.5247,316.59432 250.6812,315.21932 C 249.83771,313.84432 249.37698,313.47411 249.65736,314.39664 C 250.09944,315.85116 249.77671,315.93784 247.22762,315.04923 C 245.61088,314.48562 244.53911,313.61833 244.84591,313.12191 C 245.15272,312.62548 244.47719,312.16307 243.34473,312.09432 C 240.41811,311.91665 240.15142,311.83052 236.50301,309.88482 C 234.69753,308.92195 233.47716,307.71856 233.79109,307.21062 C 234.36461,306.28264 220.88381,299.21932 218.53919,299.21932 C 216.94091,299.21932 216.89966,297.51467 218.48515,296.98617 C 219.25719,296.72883 219.10778,296.36502 218.06586,295.9652 C 216.7594,295.46386 216.51829,295.90628 216.816,298.25866 C 217.1513,300.90804 217.01107,301.06475 215.27518,299.98067 C 214.09137,299.24137 213.76914,298.53858 214.42744,298.13172 C 215.07309,297.73269 214.59107,296.84618 213.19789,295.87036 C 211.93756,294.98759 210.66726,294.50444 210.375,294.79669 C 210.08275,295.08895 210.5056,295.74671 211.31467,296.25838 C 214.99646,298.58681 210.2241,296.87847 205.53571,294.18971 C 199.9805,291.00383 198.23192,289.1059 203.23605,291.69364 C 206.91052,293.59378 207.36825,293.59799 206.64954,291.72506 C 206.33417,290.90322 205.67329,290.47978 205.18093,290.78408 C 203.6058,291.75756 201.90836,290.08001 203.42895,289.05262 C 204.51858,288.31641 204.48266,288.19336 203.24652,288.42762 C 201.75738,288.70983 195.93233,284.63192 189.81791,279.02673 C 187.69321,277.07898 186.63225,276.64888 186.08322,277.51271 C 185.49844,278.43279 185.3127,278.4365 185.30102,277.52834 C 185.2926,276.8733 185.73571,276.05924 186.28571,275.71932 C 186.83571,275.3794 187.25018,274.56534 187.20676,273.9103 C 187.1538,273.11126 186.95512,273.1508 186.60305,274.03045 C 186.1908,275.06048 185.69302,274.99292 184.28128,273.71531 C 183.09603,272.64268 182.26016,272.45165 181.82597,273.15418 C 181.46391,273.74001 181.59609,274.21932 182.1197,274.21932 C 182.64332,274.21932 183.37363,275.00606 183.74262,275.96763 C 184.16417,277.06617 183.27387,276.6241 181.34714,274.77818 C 179.66064,273.1624 178.67487,271.58816 179.15656,271.27986 C 179.63824,270.97156 178.24757,268.91932 176.06619,266.71932 C 173.88481,264.51932 172.56725,263.65633 173.13828,264.80156 C 173.70931,265.9468 174.87113,267.46029 175.7201,268.16487 C 176.56908,268.86946 177.06533,269.76689 176.82289,270.15916 C 176.17637,271.20526 180.941,280.2307 181.72558,279.44611 C 182.09179,279.07991 182.13159,279.45736 181.81403,280.28491 C 181.49648,281.11246 182.05791,282.67374 183.06167,283.75443 C 185.33324,286.2001 186.54463,289.21932 185.25433,289.21932 C 184.72159,289.21932 184.28571,289.69588 184.28571,290.27834 C 184.28571,290.8608 184.73215,291.06144 185.27779,290.72421 C 186.35162,290.06055 189.52176,291.48025 189.37531,292.55921 C 189.13293,294.34487 189.43789,295.08876 191.28571,297.21932 C 192.38571,298.48763 193.28571,300.30834 193.28571,301.26534 C 193.28571,302.22234 193.96071,303.26436 194.78571,303.58095 C 195.61071,303.89753 196.28571,304.84567 196.28571,305.68794 C 196.28571,306.5302 196.73571,307.21932 197.28571,307.21932 C 197.83571,307.21932 198.28571,307.69588 198.28571,308.27834 C 198.28571,308.8608 197.76618,309.01627 197.1312,308.62383 C 195.2941,307.48844 197.37729,310.51298 199.4745,312.02602 C 200.47067,312.74471 201.28571,313.78421 201.28571,314.33602 C 201.28571,314.88782 202.86071,317.40202 204.78571,319.92311 C 208.29009,324.51266 209.29833,326.96319 207.1312,325.62383 C 206.41016,325.1782 206.24838,325.3499 206.7003,326.08112 C 207.09828,326.72507 207.87878,326.97082 208.43473,326.62722 C 208.99068,326.28363 210.1889,327.06379 211.09744,328.36091 C 212.00598,329.65804 212.53252,330.78109 212.26752,330.85659 C 212.00252,330.93209 212.91071,331.98225 214.28571,333.19029 C 216.41758,335.0633 216.49121,335.3004 214.78571,334.80047 C 213.29347,334.36306 213.48519,334.74476 215.54086,336.30393 C 217.05619,337.45327 218.04214,338.80442 217.73184,339.30648 C 217.42155,339.80854 217.67079,340.21932 218.28571,340.21932 C 218.90063,340.21932 219.12881,340.66417 218.79279,341.20787 C 218.43336,341.78944 218.86825,341.93301 219.84917,341.55659 C 221.21534,341.03235 221.38451,341.33268 220.78571,343.21932 C 220.20189,345.05878 220.3695,345.40114 221.61912,344.92162 C 222.6265,344.53505 223.40249,345.01191 223.799,346.26119 C 224.13762,347.32809 226.65567,350.46572 229.39467,353.23369 C 232.41225,356.28319 234.09693,358.74967 233.66986,359.49284 C 233.28222,360.16741 233.31127,360.40776 233.73441,360.02697 C 234.68217,359.17404 240.11671,364.87188 241.36713,368.02949 C 241.87029,369.30009 242.73281,370.06103 243.28384,369.72048 C 243.83487,369.37992 244.28571,369.566 244.28571,370.13399 C 244.28571,371.16056 252.87445,380.21932 253.84776,380.21932 C 254.12794,380.21932 255.48134,381.23182 256.85531,382.46932 C 258.22929,383.70682 260.23821,385.50682 261.31958,386.46932 C 262.40095,387.43182 263.73057,388.21932 264.27428,388.21932 C 265.80069,388.21932 269.24543,391.47547 268.68255,392.38624 C 268.40715,392.83184 268.84368,392.94244 269.6526,392.63203 C 270.52305,392.298 272.44822,393.42512 274.36927,395.39348 C 276.15451,397.22269 277.23869,398.04432 276.77855,397.21932 C 276.24633,396.2651 276.73217,396.41245 278.11382,397.62431 C 279.30836,398.67205 280.28571,399.17945 280.28571,398.75186 C 280.28571,398.32428 280.95576,398.53052 281.7747,399.21018 C 282.59364,399.88985 282.98101,400.90332 282.6355,401.46236 C 282.2865,402.02706 282.62471,402.26229 283.39651,401.99164 C 284.16057,401.72371 285.96151,402.32703 287.39859,403.33236 C 288.83567,404.33769 290.29817,404.87353 290.64859,404.52311 C 290.99901,404.17269 291.28571,404.43754 291.28571,405.11167 C 291.28571,405.7858 291.73571,406.05924 292.28571,405.71932 C 292.83571,405.3794 293.28571,405.57784 293.28571,406.1603 C 293.28571,406.74276 293.62321,407.14982 294.03571,407.06488 C 294.44821,406.97993 296.45876,407.65493 298.50359,408.56488 C 300.54843,409.47482 302.69203,410.21932 303.26716,410.21932 C 303.84229,410.21932 305.09424,410.61438 306.04928,411.09724 C 307.00432,411.58009 309.47321,412.69781 311.53571,413.58106 C 313.59821,414.46431 315.28571,415.60211 315.28571,416.10952 C 315.28571,416.61693 316.18811,416.7961 317.29104,416.50768 C 319.35331,415.96838 322.61233,417.88182 321.81869,419.16596 C 321.57394,419.56197 322.0091,419.88599 322.78571,419.88599 C 323.56232,419.88599 323.96916,419.51614 323.68978,419.06411 C 323.41041,418.61207 323.87762,418.50923 324.72803,418.83556 C 325.57844,419.16189 326.02844,419.82658 325.72803,420.31265 C 325.42762,420.79872 325.88021,420.92842 326.73377,420.60088 C 327.63575,420.25476 328.28571,420.53876 328.28571,421.279 C 328.28571,421.97951 328.55381,422.28455 328.88149,421.95687 C 329.20918,421.62919 331.03487,422.23593 332.9386,423.30519 C 334.84232,424.37445 337.16172,425.36807 338.09281,425.51324 C 339.02391,425.65841 340.34821,426.12822 341.03571,426.55727 C 341.72321,426.98631 342.2926,426.9733 342.30102,426.52834 C 342.30944,426.08338 342.68292,426.29706 343.13097,427.00319 C 343.96538,428.31822 347.28571,427.66428 347.28571,426.18491 C 347.28571,425.73367 346.16071,424.47956 344.78571,423.39798 C 343.41071,422.3164 342.28571,420.98834 342.28571,420.44672 C 342.28571,419.40701 337.25154,416.98986 335.698,417.28364 C 335.19624,417.37853 333.94311,417.40287 332.91327,417.33774 C 331.3651,417.23983 331.25642,416.95954 332.28571,415.71932 C 333.15707,414.66939 333.19381,414.18181 332.40815,414.09432 C 331.28079,413.96877 329.93053,413.66961 328.53571,413.23636 C 328.12321,413.10822 326.55937,412.99095 325.0605,412.97575 C 323.56163,412.96055 322.58023,412.5518 322.8796,412.06741 C 323.17897,411.58302 323.7518,411.38934 324.15255,411.63703 C 324.55331,411.88471 325.53472,411.66579 326.33346,411.15054 C 327.39378,410.46655 327.11101,410.32936 325.28571,410.64221 C 323.91071,410.87788 322.44821,411.10414 322.03571,411.14501 C 321.62321,411.18588 321.28571,411.89432 321.28571,412.71932 C 321.28571,413.54432 320.80539,414.21932 320.21832,414.21932 C 319.63126,414.21932 319.41642,413.38285 319.7409,412.3605 C 320.51792,409.91232 318.45703,408.32144 314.21924,408.09813 C 311.91439,407.97667 310.04771,407.06286 308.54068,405.31826 C 307.30591,403.88884 306.29341,403.26812 306.29068,403.93887 C 306.28756,404.70502 304.89633,405.10619 302.54855,405.01792 C 300.49311,404.94065 299.36811,404.69185 300.04855,404.46504 C 301.96557,403.82603 301.50739,402.21932 299.40815,402.21932 C 298.3755,402.21932 296.913,401.46628 296.15815,400.54591 C 294.93,399.04843 295.03741,398.93741 297.17976,399.48996 C 298.94287,399.94469 299.27945,399.81306 298.45689,398.9905 C 297.63432,398.16793 296.67395,398.17702 294.81284,399.02501 C 292.64541,400.01255 292.27571,399.93041 292.21542,398.44788 C 292.15632,396.99433 292.0084,397.03752 291.28571,398.71932 C 290.81302,399.81932 290.39465,400.15682 290.356,399.46932 C 290.24683,397.52782 288.28765,397.99752 288.2704,399.96932 C 288.25777,401.41245 288.09505,401.46638 287.34245,400.27688 C 286.71685,399.28812 286.95756,398.43318 288.10776,397.55868 C 289.66348,396.37586 289.65393,396.28061 287.97669,396.25112 C 285.41953,396.20617 286.93735,394.23428 289.59473,394.14903 C 291.70709,394.08127 291.71395,394.04791 289.78571,393.21932 C 288.07549,392.48442 288.03927,392.34971 289.53571,392.28961 C 290.49821,392.25095 291.28571,391.76932 291.28571,391.21932 C 291.28571,390.66932 291.76227,390.21932 292.34473,390.21932 C 292.92719,390.21932 293.14485,390.63823 292.82842,391.15022 C 292.51198,391.66222 292.76074,392.39487 293.3812,392.77834 C 294.99308,393.77454 296.39753,391.05898 295.08706,389.47997 C 294.24162,388.46127 294.40047,388.32613 295.80831,388.86637 C 297.18039,389.39288 297.41918,389.21834 296.80305,388.13926 C 296.16865,387.02818 296.26934,386.97533 297.26598,387.89629 C 298.11955,388.68506 299.32237,388.77568 300.91268,388.17104 C 302.24283,387.66532 303.28571,387.65257 303.28571,388.14203 C 303.28571,388.62229 305.08591,388.94865 307.28615,388.86728 C 309.48639,388.7859 311.28639,389.05682 311.28615,389.46932 C 311.28591,389.88182 312.32071,390.21932 313.58571,390.21932 C 314.85071,390.21932 316.33962,390.67323 316.8944,391.22801 C 317.44918,391.78279 319.78685,392.34529 322.08922,392.47801 C 324.39159,392.61073 326.27768,393.05682 326.28053,393.46932 C 326.28338,393.88182 326.84821,394.10682 327.53571,393.96932 C 328.22321,393.83182 328.67321,394.28182 328.53571,394.96932 C 328.39821,395.65682 328.73571,396.21932 329.28571,396.21932 C 329.83571,396.21932 330.28571,395.76932 330.28571,395.21932 C 330.28571,393.70678 332.9451,394.02157 334.66071,395.73718 C 335.49553,396.572 336.76517,397.1345 337.48214,396.98718 C 338.2773,396.82379 338.67194,397.49934 338.49401,398.71932 C 338.28922,400.12348 338.46199,400.33683 339.07396,399.43545 C 340.22801,397.73562 342.77127,398.79616 344.09125,401.52766 C 344.67375,402.73307 345.18081,403.15682 345.21803,402.46932 C 345.26336,401.63216 345.89387,401.7973 347.12708,402.96932 C 348.13984,403.93182 348.78139,405.06797 348.55275,405.4941 C 348.32412,405.92022 348.55014,406.14522 349.05502,405.9941 C 349.91555,405.73652 355.09654,409.23832 357.82502,411.9217 C 358.49745,412.58301 359.32619,412.84551 359.66666,412.50503 C 360.00714,412.16456 360.28571,412.63599 360.28571,413.55265 C 360.28571,414.46932 360.62321,415.22101 361.03571,415.22307 C 361.806,415.22692 365.76475,423.92631 365.81214,425.71932 C 365.82668,426.26932 366.11134,427.16932 366.44473,427.71932 C 367.39525,429.28743 365.51738,433.21932 363.81793,433.21932 C 362.97521,433.21932 362.28571,433.69588 362.28571,434.27834 C 362.28571,434.8608 362.67621,435.09601 363.15348,434.80104 C 363.63075,434.50607 363.31199,435.82952 362.44513,437.74203 C 361.57827,439.65454 360.51277,441.21932 360.07736,441.21932 C 359.64195,441.21932 359.28571,441.89432 359.28571,442.71932 C 359.28571,443.54432 358.58415,444.21932 357.72669,444.21932 C 356.80055,444.21932 356.45808,444.68921 356.88306,445.37684 C 357.37317,446.16985 356.91971,446.35687 355.44308,445.97072 C 354.25762,445.66072 353.08607,445.73333 352.83963,446.13207 C 352.19122,447.18122 343.38178,447.2076 339.28571,446.17267 z M 337.73797,442.46932 C 338.25855,441.10191 338.13913,440.98237 337.19176,441.92252 C 336.33138,442.77634 335.37047,442.83291 333.88251,442.11735 C 331.8401,441.13514 331.83606,441.14933 333.72684,442.66415 C 336.21294,444.65593 336.91856,444.62166 337.73797,442.46932 z M 321.2704,435.46932 C 321.25731,433.97377 321.11414,433.93742 320.28571,435.21932 C 319.58132,436.30929 319.31215,436.36149 319.30102,435.4103 C 319.2926,434.69034 318.78767,434.40909 318.17895,434.7853 C 317.40742,435.26213 317.48314,435.72971 318.42895,436.32901 C 320.49185,437.63612 321.28725,437.39547 321.2704,435.46932 z M 312.20238,429.93635 C 311.97321,429.78072 310.88571,428.99322 309.78571,428.18635 C 307.9357,426.82934 307.88864,426.85056 309.15815,428.46932 C 309.913,429.43182 311.0005,430.21932 311.57482,430.21932 C 312.14914,430.21932 312.43154,430.09198 312.20238,429.93635 z M 139.78571,425.21932 C 140.12563,424.66932 139.95374,424.21932 139.40374,424.21932 C 138.85374,424.21932 138.12563,424.66932 137.78571,425.21932 C 137.44579,425.76932 137.61768,426.21932 138.16768,426.21932 C 138.71768,426.21932 139.44579,425.76932 139.78571,425.21932 z M 278.28571,414.21932 C 277.46071,413.68616 276.33571,413.24995 275.78571,413.24995 C 275.23571,413.24995 275.46071,413.68616 276.28571,414.21932 C 277.11071,414.75248 278.23571,415.18869 278.78571,415.18869 C 279.33571,415.18869 279.11071,414.75248 278.28571,414.21932 z M 313.28571,405.83595 C 313.28571,405.6251 312.38509,405.21707 311.28433,404.92921 C 310.18357,404.64136 309.53513,404.81387 309.84335,405.31258 C 310.3816,406.18349 313.28571,406.62502 313.28571,405.83595 z M 307.78571,401.21932 C 306.68571,400.74663 305.11071,400.33515 304.28571,400.30492 C 302.95238,400.25605 302.95238,400.35765 304.28571,401.21932 C 305.11071,401.75248 306.68571,402.16396 307.78571,402.13372 C 309.78571,402.07875 309.78571,402.07875 307.78571,401.21932 z M 250.7168,397.38165 C 249.84914,395.64237 248.98931,394.21932 248.80609,394.21932 C 248.19113,394.21932 249.56357,398.70527 250.57264,399.99349 C 252.28492,402.17944 252.36714,400.68983 250.7168,397.38165 z M 324.14874,399.88272 C 323.94907,399.75658 323.07321,399.11286 322.20238,398.45223 C 320.95638,397.50699 320.61904,397.52461 320.61904,398.53495 C 320.61904,399.24108 321.49491,399.8848 322.56541,399.96544 C 323.63591,400.04607 324.34841,400.00885 324.14874,399.88272 z M 295.28571,396.26729 C 295.28571,395.80859 294.54706,395.14985 293.64427,394.80342 C 292.34701,394.30561 292.24034,394.45973 293.13559,395.53844 C 293.75861,396.28913 293.93476,397.27158 293.52703,397.72165 C 293.11931,398.17173 293.34821,398.21627 294.03571,397.82063 C 294.72321,397.42499 295.28571,396.72599 295.28571,396.26729 z M 258.96882,394.03182 C 258.6496,393.23409 258.41264,393.47104 258.36466,394.63599 C 258.32124,395.69015 258.55758,396.28078 258.88988,395.94849 C 259.22217,395.6162 259.25769,394.7537 258.96882,394.03182 z M 307.41683,394.87731 C 306.80426,394.13921 306.62294,393.21542 307.01391,392.82446 C 307.40487,392.43349 306.87714,392.43887 305.84118,392.83641 C 304.39393,393.39177 304.14542,393.23028 304.76837,392.13926 C 305.40113,391.03104 305.30063,390.97658 304.31056,391.89118 C 303.61285,392.5357 302.42183,392.82505 301.66385,392.53419 C 300.90588,392.24332 300.28571,392.47765 300.28571,393.05491 C 300.28571,393.63218 301.1456,393.93888 302.19658,393.73649 C 303.24756,393.53409 304.93506,393.99561 305.94658,394.7621 C 308.29339,396.54041 308.83212,396.58263 307.41683,394.87731 z M 58.785414,389.52927 C 57.890564,387.9838 57.463104,387.61932 57.835514,388.71932 C 58.207924,389.81932 58.765434,391.60771 59.074434,392.69353 C 59.383424,393.77934 59.810884,394.14382 60.024324,393.50348 C 60.237774,392.86314 59.680264,391.07475 58.785414,389.52927 z M 315.28571,392.77834 C 315.28571,392.5358 314.83571,392.05924 314.28571,391.71932 C 313.73571,391.3794 313.28571,391.57784 313.28571,392.1603 C 313.28571,392.74276 313.73571,393.21932 314.28571,393.21932 C 314.83571,393.21932 315.28571,393.02088 315.28571,392.77834 z M 301.72807,390.31258 C 302.03629,389.81387 301.38785,389.64136 300.28709,389.92921 C 297.9521,390.53982 297.65694,391.21932 299.72669,391.21932 C 300.51923,391.21932 301.41985,390.81129 301.72807,390.31258 z M 315.23646,374.37401 C 314.43855,374.11048 313.33571,373.35031 312.78571,372.68475 C 311.52398,371.15792 307.28571,370.10081 307.28571,371.31294 C 307.28571,371.81145 308.0857,372.21932 309.06347,372.21932 C 310.04124,372.21932 311.62823,373.13847 312.59011,374.26187 C 313.57396,375.41092 314.8526,375.987 315.5131,375.57878 C 316.3607,375.05494 316.28376,374.71991 315.23646,374.37401 z M 329.1972,372.64117 C 330.07866,371.7597 319.71438,372.29537 318.28571,373.20511 C 317.28535,373.84212 318.78256,373.97753 322.78053,373.61164 C 326.07768,373.3099 328.96518,372.87318 329.1972,372.64117 z M 289.3803,362.46932 C 290.11701,361.50682 290.37458,361.00435 289.95268,361.35272 C 289.53077,361.70109 287.59746,361.62794 285.65642,361.19016 C 281.89773,360.34244 281.86202,360.75016 285.518,362.77023 C 286.76524,363.45938 287.84311,364.06735 287.91327,364.12127 C 287.98342,364.1752 288.64359,363.43182 289.3803,362.46932 z M 332.98203,359.38225 C 334.37564,360.53884 335.78571,359.84766 335.78571,358.00796 C 335.78571,357.43338 336.7646,356.31331 337.96102,355.51891 C 339.99587,354.16782 340.09942,354.2157 339.56471,356.26043 C 339.04923,358.23161 339.20389,358.33348 341.1394,357.29762 C 342.31987,356.66585 343.28571,355.48979 343.28571,354.68414 C 343.28571,353.87849 343.73571,353.21932 344.28571,353.21932 C 344.83571,353.21932 345.28571,352.31932 345.28571,351.21932 C 345.28571,350.11932 344.78757,349.21932 344.17872,349.21932 C 343.56988,349.21932 343.31677,348.58077 343.61626,347.80031 C 344.13533,346.44764 341.2994,342.21932 339.8731,342.21932 C 339.50019,342.21932 339.46837,343.90682 339.80239,345.96932 C 340.37299,349.49263 340.31528,349.60198 338.84771,347.77819 C 337.98861,346.71057 337.27873,345.36057 337.2702,344.77819 C 337.24975,343.38318 327.80369,334.21932 326.38616,334.21932 C 325.78091,334.21932 325.28571,335.70969 325.28571,337.53126 C 325.28571,341.54705 321.00612,345.21932 316.3262,345.21932 C 313.8443,345.21932 313.2829,344.80595 313.2704,342.96932 C 313.25786,341.12698 313.07117,340.99109 312.24002,342.21932 C 311.49736,343.31679 311.40193,342.91425 311.88444,340.71932 C 312.24716,339.06932 312.93583,337.29182 313.41482,336.76932 C 314.72789,335.33697 314.45962,333.99411 313.03571,334.87163 C 312.34821,335.29531 312.55467,334.466 313.49451,333.02871 C 315.17867,330.45313 315.16425,330.40494 312.49451,329.68638 C 311.00467,329.28538 306.48902,328.875 302.45974,328.7744 C 298.43046,328.67381 294.83046,328.13709 294.45974,327.58169 C 294.08902,327.02629 292.54821,326.64806 291.03571,326.74117 C 289.52321,326.83428 288.28571,326.5781 288.28571,326.17188 C 288.28571,325.76566 287.58734,325.16531 286.73377,324.83776 C 285.84385,324.49627 285.44245,324.66391 285.79279,325.23077 C 286.13458,325.7838 285.27633,326.21932 283.84473,326.21932 C 282.10431,326.21932 281.26046,325.65952 281.20676,324.46932 C 281.1596,323.42388 280.92475,323.22258 280.62343,323.96932 C 280.34602,324.65682 279.6584,325.21932 279.09539,325.21932 C 278.53238,325.21932 278.3196,324.57339 278.62254,323.78393 C 279.3528,321.88091 277.14687,321.2153 275.5157,322.84647 C 274.80737,323.5548 273.56585,323.88032 272.75677,323.56984 C 270.98126,322.88851 270.94638,323.27 272.45192,326.90422 C 273.09333,328.45253 273.69469,329.94432 273.78828,330.21932 C 274.74278,333.02403 275.95494,334.93587 277.46986,336.02602 C 278.46858,336.74471 279.28571,338.00877 279.28571,338.83504 C 279.28571,339.72742 279.7607,340.04379 280.45565,339.61429 C 281.24941,339.12372 281.41386,339.44299 280.9671,340.60721 C 280.59899,341.5665 280.71825,342.07003 281.23755,341.74908 C 282.18803,341.16166 286.28571,344.94329 286.28571,346.40788 C 286.28571,346.85417 287.03778,347.21932 287.95697,347.21932 C 288.87616,347.21932 290.33866,347.83599 291.20697,348.5897 C 292.86428,350.02828 301.24377,354.79895 302.54021,355.04201 C 305.96229,355.68362 308.20605,356.5392 307.87429,357.07599 C 307.4418,357.77577 308.41343,357.89555 318.53199,358.38979 C 322.24245,358.57103 325.27995,359.02541 325.28199,359.39951 C 325.28404,359.77362 326.71318,359.67032 328.45787,359.16995 C 330.596,358.55674 332.07073,358.62594 332.98203,359.38225 z M 309.03571,330.55704 C 309.72321,330.27963 310.84821,330.27963 311.53571,330.55704 C 312.22321,330.83445 311.66071,331.06143 310.28571,331.06143 C 308.91071,331.06143 308.34821,330.83445 309.03571,330.55704 z M 71.285714,349.77834 C 71.285714,348.72286 69.366604,348.27943 68.795794,349.20301 C 68.450334,349.76198 68.869234,350.21932 69.726694,350.21932 C 70.584154,350.21932 71.285714,350.02088 71.285714,349.77834 z M 167.28571,342.71932 C 167.28571,341.89432 166.84983,341.21932 166.31709,341.21932 C 165.78436,341.21932 165.6075,341.89432 165.92408,342.71932 C 166.24067,343.54432 166.67654,344.21932 166.8927,344.21932 C 167.10885,344.21932 167.28571,343.54432 167.28571,342.71932 z M 200.73765,337.12639 C 199.85797,335.42528 198.91046,334.26123 198.63207,334.53963 C 198.13111,335.04059 201.13487,340.21932 201.9264,340.21932 C 202.15227,340.21932 201.61733,338.8275 200.73765,337.12639 z M 334.28571,336.87431 C 334.28571,336.68455 333.32023,335.67205 332.1402,334.62431 C 330.00619,332.72953 330.00102,332.73138 331.17538,334.96932 C 332.15016,336.82691 334.28571,338.13488 334.28571,336.87431 z M 210.95238,334.76331 C 210.95238,333.9625 210.57004,333.5436 210.10273,333.83241 C 209.63543,334.12122 209.51198,334.77642 209.82842,335.28842 C 210.63704,336.5968 210.95238,336.44948 210.95238,334.76331 z M 316.28571,333.21932 C 316.28571,332.66932 315.80915,332.21932 315.22669,332.21932 C 314.64423,332.21932 314.44579,332.66932 314.78571,333.21932 C 315.12563,333.76932 315.60219,334.21932 315.84473,334.21932 C 316.08727,334.21932 316.28571,333.76932 316.28571,333.21932 z M 322.28571,333.745 C 322.28571,333.48412 320.93571,332.57257 319.28571,331.71932 C 315.52483,329.77449 315.29727,330.61921 319.03571,332.64735 C 322.17826,334.35221 322.28571,334.3885 322.28571,333.745 z M 191.64734,323.71932 C 191.33075,322.89432 190.89488,322.21932 190.67872,322.21932 C 190.46257,322.21932 190.28571,322.89432 190.28571,323.71932 C 190.28571,324.54432 190.72159,325.21932 191.25433,325.21932 C 191.78706,325.21932 191.96392,324.54432 191.64734,323.71932 z M 303.28571,324.83595 C 303.28571,324.6251 302.38509,324.21707 301.28433,323.92921 C 300.18357,323.64136 299.53513,323.81387 299.84335,324.31258 C 300.3816,325.18349 303.28571,325.62502 303.28571,324.83595 z M 323.28571,324.82631 C 323.28571,324.61015 322.58734,324.16531 321.73377,323.83776 C 320.84385,323.49627 320.44245,323.66391 320.79279,324.23077 C 321.38005,325.18098 323.28571,325.63622 323.28571,324.82631 z M 292.28571,321.61233 C 292.28571,321.39618 291.61071,321.21932 290.78571,321.21932 C 289.96071,321.21932 289.28571,321.6552 289.28571,322.18794 C 289.28571,322.72067 289.96071,322.89753 290.78571,322.58095 C 291.61071,322.26436 292.28571,321.82849 292.28571,321.61233 z M 312.28571,319.83595 C 312.28571,319.6251 311.38571,319.21723 310.28571,318.92957 C 309.18571,318.64191 308.28571,318.81443 308.28571,319.31294 C 308.28571,319.81145 309.18571,320.21932 310.28571,320.21932 C 311.38571,320.21932 312.28571,320.0468 312.28571,319.83595 z M 302.01488,317.61515 C 301.68259,317.28286 300.82009,317.24734 300.09821,317.53621 C 299.30048,317.85543 299.53743,318.09239 300.70238,318.14037 C 301.75654,318.18379 302.34717,317.94744 302.01488,317.61515 z M 316.28571,317.82631 C 316.28571,317.61015 315.61071,317.17428 314.78571,316.85769 C 313.96071,316.54111 313.28571,316.71797 313.28571,317.2507 C 313.28571,317.78344 313.96071,318.21932 314.78571,318.21932 C 315.61071,318.21932 316.28571,318.04246 316.28571,317.82631 z M 185.09258,313.69286 C 184.78469,313.38497 184.22553,313.93997 183.85,314.92619 C 183.30732,316.35139 183.42218,316.46625 184.4098,315.48599 C 185.09322,314.80765 185.40047,314.00075 185.09258,313.69286 z M 179.63079,309.67619 C 179.3051,308.82747 178.82416,308.34753 178.56204,308.60966 C 178.29991,308.87179 178.38206,309.5662 178.74459,310.15279 C 179.73064,311.74825 180.30697,311.4383 179.63079,309.67619 z M 283.28571,310.77834 C 283.28571,309.72286 281.3666,309.27943 280.79579,310.20301 C 280.45033,310.76198 280.86923,311.21932 281.72669,311.21932 C 282.58415,311.21932 283.28571,311.02088 283.28571,310.77834 z M 239.78571,309.21932 C 239.44579,308.66932 238.40673,308.22621 237.47669,308.23463 C 236.01942,308.24783 235.99302,308.38392 237.28571,309.21932 C 239.24408,310.48492 240.56789,310.48492 239.78571,309.21932 z M 163.94799,302.96932 C 163.67058,302.28182 163.4436,302.84432 163.4436,304.21932 C 163.4436,305.59432 163.67058,306.15682 163.94799,305.46932 C 164.2254,304.78182 164.2254,303.65682 163.94799,302.96932 z M 212.28571,291.77834 C 212.28571,291.5358 211.83571,291.05924 211.28571,290.71932 C 210.73571,290.3794 210.28571,290.57784 210.28571,291.1603 C 210.28571,291.74276 210.73571,292.21932 211.28571,292.21932 C 211.83571,292.21932 212.28571,292.02088 212.28571,291.77834 z M 220.10224,290.75464 C 219.92815,290.60921 218.66071,289.92098 217.28571,289.22524 L 214.78571,287.96025 L 216.78571,289.96191 C 217.88571,291.06282 219.15315,291.75105 219.60224,291.49131 C 220.05133,291.23156 220.27633,290.90006 220.10224,290.75464 z M 208.78571,290.21932 C 209.12563,289.66932 208.92719,289.21932 208.34473,289.21932 C 207.76227,289.21932 207.28571,289.66932 207.28571,290.21932 C 207.28571,290.76932 207.48415,291.21932 207.72669,291.21932 C 207.96923,291.21932 208.44579,290.76932 208.78571,290.21932 z M 202.28571,283.83595 C 202.28571,283.6251 201.38571,283.21723 200.28571,282.92957 C 199.18571,282.64191 198.28571,282.81443 198.28571,283.31294 C 198.28571,283.81145 199.18571,284.21932 200.28571,284.21932 C 201.38571,284.21932 202.28571,284.0468 202.28571,283.83595 z M 207.62366,283.46932 C 207.87445,283.05682 207.00101,281.91081 205.68268,280.92264 C 204.36435,279.93446 203.28571,279.54881 203.28571,280.06565 C 203.28571,280.58248 203.98923,281.27531 204.84909,281.60527 C 205.70895,281.93523 206.13239,282.65837 205.79008,283.21226 C 205.44776,283.76614 205.61768,284.21932 206.16768,284.21932 C 206.71768,284.21932 207.37287,283.88182 207.62366,283.46932 z M 202.28571,278.32631 C 202.28571,277.83515 201.54706,277.14985 200.64427,276.80342 C 199.27179,276.27675 199.20993,276.42308 200.26671,277.69643 C 201.70684,279.43167 202.28571,279.61227 202.28571,278.32631 z M 194.01488,277.61515 C 193.68258,277.28286 192.82009,277.24734 192.09821,277.53621 C 191.30048,277.85543 191.53743,278.09239 192.70238,278.14037 C 193.75654,278.18379 194.34717,277.94744 194.01488,277.61515 z M 196.63079,273.67619 C 196.3051,272.82747 195.82416,272.34753 195.56204,272.60966 C 195.29991,272.87179 195.38206,273.5662 195.74459,274.15279 C 196.73064,275.74825 197.30697,275.4383 196.63079,273.67619 z M 180.9034,267.8202 C 180.62051,265.89279 178.27991,263.21258 176.91327,263.25112 C 176.29311,263.26862 176.4886,263.83112 177.34768,264.50112 C 178.20677,265.17113 179.20514,266.50682 179.5663,267.46932 C 180.35228,269.56402 181.19166,269.7843 180.9034,267.8202 z M 189.28571,267.77834 C 189.28571,267.5358 188.83571,267.05924 188.28571,266.71932 C 187.73571,266.3794 187.28571,266.57784 187.28571,267.1603 C 187.28571,267.74276 187.73571,268.21932 188.28571,268.21932 C 188.83571,268.21932 189.28571,268.02088 189.28571,267.77834 z M 174.28571,261.32631 C 174.28571,260.83515 173.54706,260.14985 172.64427,259.80342 C 171.27179,259.27675 171.20993,259.42308 172.26671,260.69643 C 173.70684,262.43167 174.28571,262.61227 174.28571,261.32631 z M 281.53571,257.55704 C 280.84821,257.27963 279.72321,257.27963 279.03571,257.55704 C 278.34821,257.83445 278.91071,258.06143 280.28571,258.06143 C 281.66071,258.06143 282.22321,257.83445 281.53571,257.55704 z M 276.28571,256.82631 C 276.28571,256.61015 275.58734,256.16531 274.73377,255.83776 C 273.84385,255.49627 273.44245,255.66391 273.79279,256.23077 C 274.38005,257.18098 276.28571,257.63622 276.28571,256.82631 z M 351.99972,252.48132 C 352.73211,252.33773 352.99726,252.93282 352.66809,253.98132 C 352.20732,255.44897 352.36846,255.41738 353.70407,253.77819 C 355.1166,252.04461 355.74654,252.30071 355.40413,254.46932 C 355.339,254.88182 355.73571,255.21932 356.28571,255.21932 C 356.83571,255.21932 357.32124,254.65682 357.36466,253.96932 C 357.42507,253.01277 357.56528,253.02257 357.9619,254.01106 C 358.36036,255.00412 358.80512,255.03314 359.88544,254.13655 C 360.69501,253.46467 362.58235,253.22865 364.3379,253.57976 C 366.04334,253.92085 367.14098,253.79416 366.83066,253.29205 C 366.24696,252.34761 368.08544,252.37879 369.78571,253.34216 C 370.33571,253.65379 372.02321,253.82313 373.53571,253.71847 C 375.04821,253.61381 376.28571,254.00881 376.28571,254.59626 C 376.28571,255.1837 376.95734,254.70545 377.77821,253.53349 C 378.72916,252.17582 379.96477,251.58414 381.1835,251.90284 C 382.23553,252.17795 384.70106,251.64153 386.66246,250.71078 C 390.16269,249.04982 390.20441,248.96026 388.91841,245.86892 C 388.19778,244.13664 387.79488,242.04432 388.02307,241.21932 C 388.34321,240.06192 388.22913,240.01563 387.52357,241.01665 C 386.32723,242.71399 384.40925,240.54365 384.82635,237.96456 C 384.98243,236.99944 384.6923,236.46803 384.18161,236.78366 C 383.67092,237.09928 383.49277,237.74533 383.78571,238.21932 C 384.07865,238.69331 383.8307,239.38249 383.23471,239.75084 C 382.62696,240.12645 381.90986,239.49807 381.60177,238.31994 C 381.29964,237.1646 380.65493,236.21932 380.16908,236.21932 C 379.68323,236.21932 379.39821,236.55682 379.53571,236.96932 C 379.92344,238.13252 378.11356,238.24336 374.28571,237.29083 C 365.12484,235.01122 365.28571,235.00702 365.28571,237.52595 C 365.28571,241.62253 358.70243,246.08393 354.84291,244.60289 C 352.57334,243.73198 351.33824,240.25784 352.34635,237.58046 C 353.02131,235.78788 352.84057,235.52297 351.22995,235.94415 C 350.17299,236.22055 349.55152,236.84039 349.8489,237.32156 C 350.14627,237.80273 349.68548,237.92622 348.82491,237.59599 C 347.96434,237.26576 346.5967,237.54626 345.78571,238.21932 C 344.97472,238.89238 343.66335,239.19448 342.87156,238.89064 C 342.07977,238.5868 340.86931,239.01612 340.18166,239.8447 C 338.38183,242.01336 334.07381,243.93149 332.03922,243.47009 C 330.72836,243.17282 330.45896,243.50722 330.95916,244.81072 C 331.41285,245.99302 331.25212,246.31659 330.45565,245.82435 C 329.81218,245.42666 329.28571,245.6044 329.28571,246.21932 C 329.28571,246.83424 328.83571,247.05924 328.28571,246.71932 C 327.73571,246.3794 327.28571,246.56372 327.28571,247.12892 C 327.28571,247.69412 326.61071,247.89753 325.78571,247.58095 C 323.84806,246.8374 323.87595,247.6667 325.85516,249.64591 C 327.03984,250.83059 327.89789,250.96206 329.35516,250.18215 C 330.62754,249.5012 331.28571,249.49117 331.28571,250.15275 C 331.28571,250.70484 331.96071,250.89753 332.78571,250.58095 C 333.70147,250.22954 334.28571,250.58016 334.28571,251.48116 C 334.28571,252.5403 335.15495,252.85577 337.36443,252.59851 C 339.05773,252.40136 340.85258,251.98701 341.35298,251.67775 C 341.85338,251.36848 341.96483,251.89194 341.60065,252.84099 C 341.09079,254.16965 341.32343,254.4116 342.6121,253.89293 C 343.53259,253.52244 345.07321,252.95187 346.03571,252.62499 C 347.50914,252.12458 347.54865,252.20118 346.28571,253.10967 C 344.97806,254.05033 344.99943,254.19066 346.45238,254.20401 C 347.36904,254.21243 348.34602,253.65682 348.62343,252.96932 C 348.90109,252.28121 349.1949,252.61835 349.27705,253.71932 C 349.39252,255.26683 349.58006,255.37996 350.106,254.21932 C 350.47984,253.39432 351.33202,252.61222 351.99972,252.48132 z M 249.01488,249.61515 C 248.68258,249.28286 247.82009,249.24734 247.09821,249.53621 C 246.30048,249.85543 246.53743,250.09239 247.70238,250.14037 C 248.75654,250.18379 249.34717,249.94744 249.01488,249.61515 z M 152.63079,247.67619 C 152.3051,246.82747 151.82416,246.34753 151.56204,246.60966 C 151.29991,246.87179 151.38206,247.5662 151.74459,248.15279 C 152.73064,249.74825 153.30697,249.4383 152.63079,247.67619 z M 170.63079,247.67619 C 170.3051,246.82747 169.82416,246.34753 169.56204,246.60966 C 169.29991,246.87179 169.38206,247.5662 169.74459,248.15279 C 170.73064,249.74825 171.30697,249.4383 170.63079,247.67619 z M 242.78571,247.21932 C 240.03662,246.038 238.45774,246.038 240.28571,247.21932 C 241.11071,247.75248 242.46071,248.16396 243.28571,248.13372 C 244.27477,248.09747 244.10445,247.786 242.78571,247.21932 z M 228.01488,242.61515 C 227.68258,242.28286 226.82009,242.24734 226.09821,242.53621 C 225.30048,242.85543 225.53743,243.09239 226.70238,243.14037 C 227.75654,243.18379 228.34717,242.94744 228.01488,242.61515 z M 317.78571,242.21932 C 318.12563,241.66932 317.95374,241.21932 317.40374,241.21932 C 316.85374,241.21932 316.12563,241.66932 315.78571,242.21932 C 315.44579,242.76932 315.61768,243.21932 316.16768,243.21932 C 316.71768,243.21932 317.44579,242.76932 317.78571,242.21932 z M 274.53571,241.55704 C 273.84821,241.27963 272.72321,241.27963 272.03571,241.55704 C 271.34821,241.83445 271.91071,242.06143 273.28571,242.06143 C 274.66071,242.06143 275.22321,241.83445 274.53571,241.55704 z M 270.01488,240.61515 C 269.68259,240.28286 268.82009,240.24734 268.09821,240.53621 C 267.30048,240.85543 267.53743,241.09239 268.70238,241.14037 C 269.75654,241.18379 270.34717,240.94744 270.01488,240.61515 z M 251.28571,239.77834 C 251.28571,239.5358 250.83571,239.05924 250.28571,238.71932 C 249.73571,238.3794 249.28571,238.57784 249.28571,239.1603 C 249.28571,239.74276 249.73571,240.21932 250.28571,240.21932 C 250.83571,240.21932 251.28571,240.02088 251.28571,239.77834 z M 371.28571,233.82631 C 371.28571,233.61015 370.58734,233.16531 369.73377,232.83776 C 368.84385,232.49627 368.44245,232.66391 368.79279,233.23077 C 369.38005,234.18098 371.28571,234.63622 371.28571,233.82631 z M 215.73787,224.808 C 214.67631,224.03177 213.38267,223.65939 212.86311,223.9805 C 212.34356,224.3016 212.78859,224.90507 213.85209,225.32154 C 216.9837,226.54789 217.80969,226.32295 215.73787,224.808 z M 348.77863,223.23077 C 349.12897,222.66391 348.72757,222.49627 347.83765,222.83776 C 346.10523,223.50255 345.78826,224.21932 347.22669,224.21932 C 347.74423,224.21932 348.44261,223.77447 348.77863,223.23077 z M 200.743,221.15022 C 200.42657,220.63823 199.63173,220.25485 198.97669,220.29827 C 198.12425,220.35477 198.1428,220.52118 199.04194,220.88368 C 199.73287,221.16223 200.00084,221.87123 199.63743,222.45924 C 199.24361,223.09645 199.44967,223.23602 200.14751,222.80473 C 200.79146,222.40675 201.05944,221.66222 200.743,221.15022 z M 281.78571,217.21932 C 281.44579,216.66932 280.18173,216.26418 278.97669,216.319 C 276.9371,216.41179 276.95845,216.474 279.28571,217.21932 C 280.66071,217.65967 281.92477,218.06482 282.09473,218.11964 C 282.26469,218.17446 282.12563,217.76932 281.78571,217.21932 z M 200.78571,216.21932 C 200.44579,215.66932 199.18173,215.22621 197.97669,215.23463 C 196.19546,215.24708 196.06623,215.43123 197.28571,216.21932 C 199.25583,217.49251 201.57258,217.49251 200.78571,216.21932 z M 190.6827,214.05265 C 190.39944,213.59432 189.74423,213.21932 189.22669,213.21932 C 188.70915,213.21932 188.28571,213.59432 188.28571,214.05265 C 188.28571,214.51099 188.94092,214.88599 189.74172,214.88599 C 190.54253,214.88599 190.96597,214.51099 190.6827,214.05265 z M 161.96882,212.03182 C 161.6496,211.23409 161.41264,211.47104 161.36466,212.63599 C 161.32124,213.69015 161.55758,214.28078 161.88988,213.94849 C 162.22217,213.61619 162.25769,212.7537 161.96882,212.03182 z M 161.28571,204.21932 C 161.28571,203.66932 160.80915,203.21932 160.22669,203.21932 C 159.64423,203.21932 159.44579,203.66932 159.78571,204.21932 C 160.12563,204.76932 160.60219,205.21932 160.84473,205.21932 C 161.08727,205.21932 161.28571,204.76932 161.28571,204.21932 z M 298.79579,204.20301 C 299.14125,203.64404 299.90119,203.48167 300.48454,203.8422 C 301.10065,204.22298 301.33363,203.91548 301.04044,203.10852 C 300.76284,202.34446 300.02946,201.83182 299.41071,201.96932 C 298.79196,202.10682 298.38131,201.88182 298.49816,201.46932 C 298.61501,201.05682 298.13363,199.67777 297.42842,198.40475 C 296.39809,196.54482 295.86529,196.32334 294.71597,197.2772 C 293.92933,197.93005 293.28571,198.22091 293.28571,197.92355 C 293.28571,197.62619 293.01826,196.55859 292.69138,195.55111 C 292.19709,194.02765 292.27867,193.97181 293.17606,195.21932 C 293.76953,196.04432 294.26198,196.21419 294.2704,195.5968 C 294.29299,193.94091 282.49946,183.23907 280.49973,183.10084 C 279.55702,183.03567 278.15863,183.07023 277.39219,183.17763 C 276.62575,183.28504 275.66245,182.82889 275.25151,182.16399 C 274.73715,181.33172 274.30001,181.59891 273.84848,183.02154 C 273.48775,184.1581 272.42606,185.07796 271.48916,185.06569 C 270.55226,185.05341 268.59638,185.30802 267.14275,185.63149 C 265.31006,186.03931 264.32332,185.75971 263.92414,184.71947 C 263.60753,183.89439 263.78436,183.21932 264.31709,183.21932 C 264.84983,183.21932 265.28571,182.81145 265.28571,182.31294 C 265.28571,181.81443 264.31534,181.66032 263.12934,181.97046 C 261.56958,182.37835 261.187,182.18805 261.74656,181.28267 C 262.17203,180.59424 263.60314,180.23801 264.92679,180.49104 C 266.25045,180.74407 267.57426,180.56145 267.86859,180.08521 C 268.42328,179.18772 267.05487,178.85991 264.03571,179.16702 C 262.99664,179.27272 262.28571,178.66667 262.28571,177.67519 C 262.28571,176.65745 262.83058,176.21443 263.68095,176.54075 C 264.78489,176.96437 264.96617,176.20377 264.54923,172.89774 C 263.97677,168.35856 259.49319,163.2985 258.05131,165.56434 C 257.6155,166.2492 257.3101,165.77947 257.30102,164.4103 C 257.29117,162.92517 256.87477,162.35526 256.13401,162.81308 C 255.50057,163.20456 254.37557,162.69511 253.63401,161.68097 C 252.27729,159.82554 251.77184,160.67491 252.2281,164.04351 C 252.32675,164.77181 251.90821,165.96925 251.29803,166.70448 C 250.53226,167.62717 250.51341,168.24201 251.23715,168.68931 C 251.81386,169.04573 252.28571,170.67525 252.28571,172.31046 C 252.28571,177.03894 254.59553,181.30604 260.39095,187.28387 C 267.83994,194.9673 280.10772,202.24126 288.04436,203.68044 C 289.41207,203.92846 290.77589,204.37616 291.07507,204.67535 C 292.03128,205.63155 298.14403,205.25759 298.79579,204.20301 z M 288.94363,192.77025 C 288.57197,191.80173 288.86812,191.50558 289.83664,191.87724 C 290.63363,192.18307 291.28571,192.83515 291.28571,193.32631 C 291.28571,194.76393 289.55059,194.35198 288.94363,192.77025 z M 283.865,188.09548 C 281.28289,185.58412 282.22209,184.90843 285.18668,187.14462 C 286.49078,188.12831 287.15906,189.16499 286.67174,189.44835 C 286.18442,189.73172 284.92139,189.12293 283.865,188.09548 z M 258.82842,168.28842 C 258.51198,167.77642 258.63543,167.12122 259.10273,166.83241 C 259.57004,166.5436 259.95238,166.9625 259.95238,167.76331 C 259.95238,169.44948 259.63704,169.5968 258.82842,168.28842 z M 174.28571,202.82631 C 174.28571,202.61015 173.58734,202.16531 172.73377,201.83776 C 171.84385,201.49627 171.44245,201.66391 171.79279,202.23077 C 172.38005,203.18098 174.28571,203.63622 174.28571,202.82631 z M 170.01488,196.61515 C 169.68258,196.28286 168.82009,196.24734 168.09821,196.53621 C 167.30048,196.85543 167.53743,197.09239 168.70238,197.14037 C 169.75654,197.18379 170.34717,196.94745 170.01488,196.61515 z M 171.743,194.28842 C 172.05944,193.77642 171.86099,193.07486 171.30202,192.7294 C 170.74305,192.38394 170.28571,192.80284 170.28571,193.6603 C 170.28571,195.41683 170.88577,195.67546 171.743,194.28842 z M 245.73765,192.12639 C 244.85797,190.42528 243.87074,189.30096 243.5438,189.6279 C 242.79083,190.38086 245.33195,195.21932 246.48037,195.21932 C 246.95156,195.21932 246.61733,193.8275 245.73765,192.12639 z M 168.25675,190.18026 C 166.96928,189.36604 166.97289,189.24612 168.28571,189.21932 C 169.58479,189.1928 169.59119,189.06564 168.33346,188.26999 C 166.00984,186.80006 164.9931,188.23851 166.8811,190.32473 C 167.83023,191.3735 168.85901,191.97935 169.16729,191.67108 C 169.47556,191.3628 169.06582,190.69193 168.25675,190.18026 z M 161.81867,187.43902 L 158.95769,184.71932 L 161.3717,187.83754 C 162.69941,189.55256 163.98685,190.77642 164.23268,190.55723 C 164.47851,190.33805 163.39221,188.93485 161.81867,187.43902 z M 162.96912,182.77858 C 161.97,182.02116 161.1825,181.13547 161.21912,180.81039 C 161.43115,178.92834 161.17573,178.21932 160.28571,178.21932 C 159.73571,178.21932 159.28571,178.66932 159.28571,179.21932 C 159.28571,180.39932 162.95149,184.23349 164.03571,184.18752 C 164.44821,184.17002 163.96824,183.536 162.96912,182.77858 z M 156.63079,179.67619 C 156.3051,178.82747 155.82416,178.34753 155.56204,178.60966 C 155.29991,178.87179 155.38206,179.5662 155.74459,180.15279 C 156.73064,181.74825 157.30697,181.4383 156.63079,179.67619 z M 158.55368,175.21932 C 157.61183,174.11932 156.7004,173.21932 156.52829,173.21932 C 156.35617,173.21932 156.69701,174.11932 157.28571,175.21932 C 157.87441,176.31932 158.78584,177.21932 159.31111,177.21932 C 159.83637,177.21932 159.49553,176.31932 158.55368,175.21932 z M 267.28571,174.21932 C 267.28571,173.66932 266.83571,173.21932 266.28571,173.21932 C 265.73571,173.21932 265.28571,173.66932 265.28571,174.21932 C 265.28571,174.76932 265.73571,175.21932 266.28571,175.21932 C 266.83571,175.21932 267.28571,174.76932 267.28571,174.21932 z M 250.96882,171.03182 C 250.6496,170.23409 250.41264,170.47104 250.36466,171.63599 C 250.32124,172.69015 250.55758,173.28078 250.88988,172.94849 C 251.22217,172.61619 251.25769,171.7537 250.96882,171.03182 z M 241.28571,148.82631 C 241.28571,148.61015 240.58734,148.16531 239.73377,147.83776 C 238.84385,147.49627 238.44245,147.66391 238.79279,148.23077 C 239.38005,149.18098 241.28571,149.63622 241.28571,148.82631 z M 136.09258,143.69286 C 135.78469,143.38497 135.22553,143.93997 134.85,144.92619 C 134.30732,146.35139 134.42218,146.46625 135.4098,145.48599 C 136.09322,144.80765 136.40047,144.00075 136.09258,143.69286 z M 315.78571,141.21932 C 314.68571,140.74663 313.11071,140.33515 312.28571,140.30492 C 310.95238,140.25605 310.95238,140.35765 312.28571,141.21932 C 313.11071,141.75248 314.68571,142.16396 315.78571,142.13372 C 317.78571,142.07875 317.78571,142.07875 315.78571,141.21932 z M 305.28571,137.21932 C 304.46071,136.68616 303.33571,136.24995 302.78571,136.24995 C 302.23571,136.24995 302.46071,136.68616 303.28571,137.21932 C 304.11071,137.75248 305.23571,138.18869 305.78571,138.18869 C 306.33571,138.18869 306.11071,137.75248 305.28571,137.21932 z M 165.28571,130.21932 C 165.28571,129.66932 165.08727,129.21932 164.84473,129.21932 C 164.60219,129.21932 164.12563,129.66932 163.78571,130.21932 C 163.44579,130.76932 163.64423,131.21932 164.22669,131.21932 C 164.80915,131.21932 165.28571,130.76932 165.28571,130.21932 z M 296.78571,129.21932 C 297.12563,128.66932 296.67563,128.21932 295.78571,128.21932 C 294.89579,128.21932 294.44579,128.66932 294.78571,129.21932 C 295.12563,129.76932 295.57563,130.21932 295.78571,130.21932 C 295.99579,130.21932 296.44579,129.76932 296.78571,129.21932 z M 330.9358,126.33334 C 332.51565,126.17671 332.15812,118.23237 330.57089,118.22498 C 329.05859,118.21793 327.40203,115.14864 328.00417,113.46932 C 328.25068,112.78182 327.96488,112.21932 327.36904,112.21932 C 326.77321,112.21932 326.28571,111.54432 326.28571,110.71932 C 326.28571,109.89432 325.89811,109.21932 325.42438,109.21932 C 324.95065,109.21932 324.70949,107.98182 324.88847,106.46932 C 325.06744,104.95682 324.97204,104.50682 324.67647,105.46932 C 324.3809,106.43182 323.79429,107.21932 323.3729,107.21932 C 322.48202,107.21932 320.28571,102.70752 320.28571,100.87741 C 320.28571,100.19112 318.03571,97.194983 315.28571,94.219323 C 312.53571,91.243663 310.28571,89.181443 310.28571,89.636623 C 310.28571,90.091793 309.68181,89.963013 308.9437,89.350443 C 308.2056,88.737873 307.3056,88.532773 306.9437,88.894663 C 306.58181,89.256563 306.28571,88.829213 306.28571,87.945003 C 306.28571,87.060803 305.75924,86.011983 305.11577,85.614293 C 304.29114,85.104643 304.17749,85.456163 304.7307,86.805283 C 306.19767,90.382743 306.21417,95.219323 304.75941,95.219323 C 304.01125,95.219323 302.8111,96.025963 302.09241,97.011863 C 300.54301,99.137343 296.28571,99.688903 296.28571,97.764163 C 296.28571,97.032193 295.61071,96.174283 294.78571,95.857693 C 293.96071,95.541113 293.28571,94.557213 293.28571,93.671253 C 293.28571,92.440593 293.93475,92.196753 296.03571,92.638093 C 297.54821,92.955813 299.46071,92.752903 300.28571,92.187173 C 301.43516,91.398953 301.20146,91.292943 299.28571,91.733543 C 297.79001,92.077533 295.98227,91.700793 294.78571,90.795723 C 293.68431,89.962623 293.34733,89.268643 294.03571,89.251123 C 294.72321,89.233633 295.28571,88.544323 295.28571,87.719323 C 295.28571,86.885993 296.1746,86.219323 297.28571,86.219323 C 298.38571,86.219323 299.28571,85.716843 299.28571,85.102693 C 299.28571,84.478573 300.16741,84.216633 301.28471,84.508813 C 302.38417,84.796323 303.5787,84.554283 303.93922,83.970933 C 304.31149,83.368583 304.12244,83.202193 303.50168,83.585843 C 302.9005,83.957393 301.94466,83.464423 301.37758,82.490353 C 300.8105,81.516283 300.33284,81.111923 300.31612,81.591763 C 300.29939,82.071613 299.61071,81.904013 298.78571,81.219323 C 297.96071,80.534633 297.28571,80.264903 297.28571,80.619933 C 297.28571,80.974953 296.23729,80.578473 294.95588,79.738873 C 293.67448,78.899263 292.32448,78.438883 291.95588,78.715813 C 291.58729,78.992743 291.48928,78.940753 291.73809,78.600273 C 292.53493,77.509853 289.2871,75.004813 287.81094,75.571273 C 286.82001,75.951523 286.57563,75.627373 287.00658,74.504353 C 287.40099,73.476533 287.22616,73.138093 286.52475,73.571593 C 285.91928,73.945783 285.13672,73.787263 284.78571,73.219323 C 284.4347,72.651383 283.77576,72.416453 283.3214,72.697263 C 282.86703,72.978083 282.2263,72.506903 281.89756,71.650193 C 281.56881,70.793493 280.81637,70.391353 280.22546,70.756553 C 279.62968,71.124773 278.9077,70.489823 278.60471,69.331183 C 278.3042,68.182033 277.66041,67.487743 277.17407,67.788323 C 276.10318,68.450163 270.28571,65.155433 270.28571,63.887083 C 270.28571,63.391523 269.38509,63.221573 268.28433,63.509433 C 267.18357,63.797283 266.53513,63.624773 266.84335,63.126063 C 267.15157,62.627353 266.92719,62.219323 266.34473,62.219323 C 264.90479,62.219323 265.00923,63.437703 266.87872,68.449083 C 270.22978,77.432003 273.81325,83.183233 281.1747,91.393193 C 283.16075,93.608173 284.79398,96.162673 284.80408,97.069873 C 284.81574,98.115943 285.62061,98.692233 287.00436,98.645263 C 288.20441,98.604533 288.97951,98.905753 288.7268,99.314643 C 288.47409,99.723533 288.83396,100.65686 289.52652,101.3887 C 290.21907,102.12054 290.94333,103.6174 291.13598,104.71505 C 291.48565,106.70738 291.48225,106.7074 289.13598,104.7222 C 286.8583,102.79505 286.86253,102.82607 289.27269,105.72647 C 294.17792,111.62947 297.79904,115.0201 298.6418,114.49925 C 299.11339,114.20779 298.88869,113.58246 298.14247,113.10963 C 297.39625,112.6368 297.23571,112.24995 297.78571,112.24995 C 299.09269,112.24995 300.43917,113.27067 302.28571,115.66128 C 303.61904,117.38746 303.61904,117.50502 302.28571,116.71932 C 300.96303,115.9399 300.95871,116.04838 302.24916,117.63701 C 303.12469,118.71486 303.8612,118.99284 304.08249,118.32897 C 304.66411,116.58411 306.09074,117.02968 306.76947,119.16817 C 307.10967,120.24003 308.3775,121.40521 309.58686,121.75744 C 313.71334,122.9593 317.28571,124.70631 317.28571,125.52245 C 317.28571,125.97065 317.66177,126.10494 318.12139,125.82087 C 318.58102,125.53681 320.26852,125.67809 321.87139,126.13483 C 323.47427,126.59157 325.91071,126.84873 327.28571,126.70631 C 328.66071,126.56389 330.30325,126.39605 330.9358,126.33334 z M 292.35235,107.79961 C 291.40575,106.65903 291.51848,106.43045 292.92569,106.63699 C 293.88907,106.77838 294.85169,107.41725 295.06483,108.05669 C 295.6071,109.68349 293.77144,109.50951 292.35235,107.79961 z M 179.42242,124.43156 C 178.70098,124.19108 177.63526,124.46977 177.05416,125.05087 C 176.31209,125.79294 176.70252,125.92308 178.36587,125.48811 C 179.71807,125.1345 180.17137,124.68121 179.42242,124.43156 z M 209.78571,123.21932 C 209.44579,122.66932 208.63173,122.22621 207.97669,122.23463 C 207.26108,122.24383 207.38442,122.63686 208.28571,123.21932 C 210.20683,124.46085 210.55301,124.46085 209.78571,123.21932 z M 141.28571,118.6603 C 141.28571,117.80284 140.83571,117.3794 140.28571,117.71932 C 139.73571,118.05924 139.28571,118.7608 139.28571,119.27834 C 139.28571,119.79588 139.73571,120.21932 140.28571,120.21932 C 140.83571,120.21932 141.28571,119.51776 141.28571,118.6603 z M 331.28571,116.21932 C 331.28571,115.66932 331.08727,115.21932 330.84473,115.21932 C 330.60219,115.21932 330.12563,115.66932 329.78571,116.21932 C 329.44579,116.76932 329.64423,117.21932 330.22669,117.21932 C 330.80915,117.21932 331.28571,116.76932 331.28571,116.21932 z M 152.96882,112.03182 C 152.6496,111.23409 152.41264,111.47104 152.36466,112.63599 C 152.32124,113.69015 152.55758,114.28078 152.88988,113.94849 C 153.22217,113.61619 153.25769,112.7537 152.96882,112.03182 z M 278.28571,110.21932 C 278.28571,109.66932 278.08727,109.21932 277.84473,109.21932 C 277.60219,109.21932 277.12563,109.66932 276.78571,110.21932 C 276.44579,110.76932 276.64423,111.21932 277.22669,111.21932 C 277.80915,111.21932 278.28571,110.76932 278.28571,110.21932 z M 339.28571,104.21932 C 339.28571,103.66932 338.80915,103.21932 338.22669,103.21932 C 337.64423,103.21932 337.44579,103.66932 337.78571,104.21932 C 338.12563,104.76932 338.60219,105.21932 338.84473,105.21932 C 339.08727,105.21932 339.28571,104.76932 339.28571,104.21932 z M 283.8812,96.064813 C 284.32328,95.349513 284.15552,95.181753 283.44022,95.623833 C 282.80524,96.016273 282.28571,95.785803 282.28571,95.111673 C 282.28571,94.437543 282.01565,94.156053 281.68557,94.486123 C 281.11354,95.058163 281.98342,97.219323 282.78571,97.219323 C 282.99579,97.219323 283.48876,96.699793 283.8812,96.064813 z M 281.28571,92.719323 C 281.28571,92.562013 280.68571,92.203063 279.95238,91.921653 C 279.21904,91.640243 278.61904,91.999193 278.61904,92.719323 C 278.61904,93.439453 279.21904,93.798403 279.95238,93.516993 C 280.68571,93.235583 281.28571,92.876633 281.28571,92.719323 z M 267.64734,91.719323 C 267.33075,90.894323 266.61478,90.219323 266.05628,90.219323 C 265.47097,90.219323 265.56816,90.854733 266.28571,91.719323 C 266.9704,92.544323 267.68638,93.219323 267.87677,93.219323 C 268.06716,93.219323 267.96392,92.544323 267.64734,91.719323 z M 302.94063,87.762453 C 302.61495,86.913733 301.88054,86.219323 301.30862,86.219323 C 300.65046,86.219323 300.71682,86.936773 301.48938,88.173843 C 302.86916,90.383213 303.84064,90.107823 302.94063,87.762453 z M 299.28571,88.826313 C 299.28571,88.610153 298.58734,88.165313 297.73377,87.837763 C 296.84385,87.496273 296.44245,87.663913 296.79279,88.230773 C 297.38005,89.180983 299.28571,89.636223 299.28571,88.826313 z M 276.01488,87.615153 C 275.68259,87.282863 274.82009,87.247343 274.09821,87.536213 C 273.30048,87.855433 273.53743,88.092393 274.70238,88.140373 C 275.75654,88.183793 276.34717,87.947453 276.01488,87.615153 z M 256.85937,82.445513 C 255.13162,80.795293 255.1048,80.822113 256.24992,83.054973 C 256.90872,84.339573 257.72201,85.116363 258.05721,84.781163 C 258.39241,84.445963 257.85338,83.394923 256.85937,82.445513 z M 327.96882,83.031823 C 327.6496,82.234093 327.41264,82.471043 327.36466,83.635993 C 327.32124,84.690153 327.55759,85.280783 327.88988,84.948493 C 328.22217,84.616193 328.25769,83.753693 327.96882,83.031823 z M 270.78571,83.219323 C 271.12563,82.669323 270.92719,82.219323 270.34473,82.219323 C 269.76227,82.219323 269.28571,82.669323 269.28571,83.219323 C 269.28571,83.769323 269.48415,84.219323 269.72669,84.219323 C 269.96923,84.219323 270.44579,83.769323 270.78571,83.219323 z M 268.28571,76.778343 C 268.28571,76.535803 267.83571,76.059243 267.28571,75.719323 C 266.73571,75.379403 266.28571,75.577843 266.28571,76.160303 C 266.28571,76.742763 266.73571,77.219323 267.28571,77.219323 C 267.83571,77.219323 268.28571,77.020883 268.28571,76.778343 z M 265.69846,70.078153 C 265.26533,69.377333 264.80293,67.790793 264.67091,66.552523 C 264.31915,63.253213 262.71914,60.709003 261.86508,62.090903 C 261.48151,62.711533 261.75673,63.226213 262.47669,63.234633 C 263.42788,63.245763 263.37568,63.514933 262.28571,64.219323 C 261.21812,64.909253 261.15868,65.193113 262.07955,65.204013 C 262.79116,65.212433 263.25924,65.781823 263.11974,66.469323 C 262.8111,67.990383 265.23978,72.598593 265.96687,71.871503 C 266.25238,71.585983 266.1316,70.778983 265.69846,70.078153 z M 284.96882,69.031823 C 284.6496,68.234093 284.41264,68.471043 284.36466,69.635993 C 284.32124,70.690153 284.55759,71.280783 284.88988,70.948493 C 285.22217,70.616193 285.25769,69.753693 284.96882,69.031823 z M 191.67064,438.78006 C 191.36688,437.98846 191.54441,436.57947 192.06514,435.64897 C 192.8103,434.31744 192.98785,434.62347 192.89882,437.08595 C 192.77368,440.54745 192.49589,440.93062 191.67064,438.78006 z M 118.09821,431.53621 C 118.82008,431.24734 119.68258,431.28286 120.01488,431.61515 C 120.34717,431.94744 119.75654,432.18379 118.70238,432.14037 C 117.53743,432.09239 117.30048,431.85543 118.09821,431.53621 z M 193.28571,429.94089 C 193.28571,429.39029 192.49821,428.35619 191.53571,427.64287 C 189.8816,426.417 189.88598,426.36002 191.61568,426.603 C 192.62216,426.74439 193.74716,427.33884 194.11568,427.92401 C 194.4842,428.50918 195.68571,429.17487 196.78571,429.40331 C 198.43598,429.74604 198.30483,429.91688 196.03571,430.38032 C 194.49302,430.6954 193.28571,430.50248 193.28571,429.94089 z M 200.28571,428.21932 C 201.11071,427.68616 202.23571,427.24995 202.78571,427.24995 C 203.33571,427.24995 203.11071,427.68616 202.28571,428.21932 C 201.46071,428.75248 200.33571,429.18869 199.78571,429.18869 C 199.23571,429.18869 199.46071,428.75248 200.28571,428.21932 z M 188.95238,422.55265 C 188.58571,422.18599 188.2926,421.39849 188.30102,420.80265 C 188.30944,420.20682 188.70319,420.32986 189.17602,421.07608 C 189.77532,422.02189 190.2429,422.09761 190.71973,421.32608 C 191.70894,419.72551 193.28571,419.96715 193.28571,421.71932 C 193.28571,423.21922 190.21035,423.81063 188.95238,422.55265 z M 257.78571,407.21932 C 257.44579,406.66932 257.61768,406.21932 258.16768,406.21932 C 258.71768,406.21932 259.44579,406.66932 259.78571,407.21932 C 260.12563,407.76932 259.95374,408.21932 259.40374,408.21932 C 258.85374,408.21932 258.12563,407.76932 257.78571,407.21932 z M 294.54567,402.67132 C 293.86364,401.93087 293.70399,401.07884 294.19088,400.77793 C 294.67777,400.47701 295.35889,400.96763 295.70446,401.86819 C 296.53164,404.02378 296.07983,404.33692 294.54567,402.67132 z M 298.64233,371.0499 C 295.05643,370.10019 293.21934,367.26329 296.34259,367.49856 C 297.4113,367.57906 298.28571,368.02572 298.28571,368.49114 C 298.28571,368.95656 298.6447,369.11549 299.08346,368.84432 C 300.20237,368.15279 302.6077,369.78879 302.15759,370.93521 C 301.93554,371.50079 300.51927,371.547 298.64233,371.0499 z M 290.2842,367.67293 C 288.83571,366.87129 288.41609,366.28173 289.28571,366.27007 C 291.07189,366.24611 293.928,367.91036 293.25524,368.58312 C 292.99534,368.84302 291.65837,368.43343 290.2842,367.67293 z M 264.28571,351.21932 C 263.38442,350.63686 263.26108,350.24383 263.97669,350.23463 C 264.63173,350.22621 265.44579,350.66932 265.78571,351.21932 C 266.55301,352.46085 266.20683,352.46085 264.28571,351.21932 z M 262.49628,347.68128 C 261.7871,346.8772 261.66048,346.21932 262.2149,346.21932 C 262.76932,346.21932 262.94037,345.43182 262.595,344.46932 C 262.24963,343.50682 262.28354,343.00161 262.67035,343.34663 C 263.34686,343.95003 264.60703,349.25914 264.05527,349.18128 C 263.90701,349.16036 263.20547,348.48536 262.49628,347.68128 z M 359.78571,345.21932 C 359.78571,343.56932 360.12321,342.21932 360.53571,342.21932 C 360.94821,342.21932 361.28571,343.56932 361.28571,345.21932 C 361.28571,346.86932 360.94821,348.21932 360.53571,348.21932 C 360.12321,348.21932 359.78571,346.86932 359.78571,345.21932 z M 162.28571,309.6603 C 162.28571,308.80284 162.74305,308.38394 163.30202,308.7294 C 163.86099,309.07486 164.05944,309.77642 163.743,310.28842 C 162.88577,311.67546 162.28571,311.41683 162.28571,309.6603 z M 227.03571,305.64735 C 225.52321,304.8268 224.28571,303.97623 224.28571,303.75719 C 224.28571,303.05273 230.61503,305.14864 231.66826,306.20187 C 233.2201,307.75371 230.26669,307.40018 227.03571,305.64735 z M 219.72684,301.75112 C 218.65922,300.94362 218.23571,300.28293 218.78571,300.28293 C 219.33571,300.28293 220.65922,300.94362 221.72684,301.75112 C 222.79446,302.55863 223.21797,303.21932 222.66797,303.21932 C 222.11797,303.21932 220.79446,302.55863 219.72684,301.75112 z M 343.49628,294.61846 C 342.7871,293.84893 342.64804,293.21932 343.18727,293.21932 C 344.22571,293.21932 345.72899,295.12153 345.13585,295.68499 C 344.94327,295.86793 344.20547,295.38799 343.49628,294.61846 z M 194.53527,286.33484 C 190.19732,282.36957 188.88708,280.2825 192.03571,282.35333 C 193.74251,283.47588 199.8276,290.21932 199.13376,290.21932 C 198.94184,290.21932 196.87252,288.47131 194.53527,286.33484 z M 187.36466,279.63599 C 187.41264,278.47104 187.6496,278.23409 187.96882,279.03182 C 188.25769,279.7537 188.22217,280.6162 187.88988,280.94849 C 187.55758,281.28078 187.32124,280.69015 187.36466,279.63599 z M 336.09821,270.53621 C 336.82009,270.24734 337.68259,270.28286 338.01488,270.61515 C 338.34717,270.94744 337.75654,271.18379 336.70238,271.14037 C 335.53743,271.09239 335.30048,270.85543 336.09821,270.53621 z M 184.14649,253.25259 C 181.99841,251.46306 181.9584,251.28286 183.70238,251.25259 C 184.75654,251.23429 185.32604,251.51233 184.96792,251.87044 C 184.6098,252.22856 185.0973,253.11425 186.05125,253.83864 C 187.0052,254.56303 187.49806,255.17002 187.14649,255.18752 C 186.79493,255.20501 185.44493,254.33429 184.14649,253.25259 z M 221.78571,227.21932 C 220.1553,226.51871 220.0982,226.3469 221.47669,226.28961 C 222.40673,226.25095 223.44579,226.66932 223.78571,227.21932 C 224.49637,228.3692 224.46162,228.3692 221.78571,227.21932 z M 285.78571,225.21932 C 285.44579,224.66932 285.64423,224.21932 286.22669,224.21932 C 286.80915,224.21932 287.28571,224.66932 287.28571,225.21932 C 287.28571,225.76932 287.08727,226.21932 286.84473,226.21932 C 286.60219,226.21932 286.12563,225.76932 285.78571,225.21932 z M 131.28571,218.21932 C 131.28571,217.66932 131.76227,217.21932 132.34473,217.21932 C 132.92719,217.21932 133.12563,217.66932 132.78571,218.21932 C 132.44579,218.76932 131.96923,219.21932 131.72669,219.21932 C 131.48415,219.21932 131.28571,218.76932 131.28571,218.21932 z M 139.99622,217.22032 C 139.70871,216.12086 139.78576,215.02831 140.16745,214.79241 C 140.54914,214.55651 140.95185,215.45606 141.06237,216.79141 C 141.30566,219.7311 140.71495,219.96874 139.99622,217.22032 z M 263.79279,214.23077 C 263.44245,213.66391 263.84385,213.49627 264.73377,213.83776 C 266.46619,214.50255 266.78316,215.21932 265.34473,215.21932 C 264.82719,215.21932 264.12881,214.77447 263.79279,214.23077 z M 139.78571,212.21932 C 140.12563,211.66932 140.60219,211.21932 140.84473,211.21932 C 141.08727,211.21932 141.28571,211.66932 141.28571,212.21932 C 141.28571,212.76932 140.80915,213.21932 140.22669,213.21932 C 139.64423,213.21932 139.44579,212.76932 139.78571,212.21932 z M 182.30577,204.74349 C 181.51702,203.7931 181.44115,203.21932 182.10425,203.21932 C 183.3128,203.21932 184.72184,205.11652 184.02835,205.81002 C 183.77665,206.06172 183.00149,205.58178 182.30577,204.74349 z M 136.48066,197.71932 C 136.50104,196.06932 136.72516,195.51538 136.9787,196.48835 C 137.23224,197.46132 137.21557,198.81132 136.94165,199.48835 C 136.66772,200.16538 136.46028,199.36932 136.48066,197.71932 z M 233.09821,125.53621 C 233.82009,125.24734 234.68258,125.28286 235.01488,125.61515 C 235.34717,125.94745 234.75654,126.18379 233.70238,126.14037 C 232.53743,126.09239 232.30048,125.85543 233.09821,125.53621 z M 252.28571,70.219323 C 252.28571,69.669323 252.76227,69.219323 253.34473,69.219323 C 253.92719,69.219323 254.12563,69.669323 253.78571,70.219323 C 253.44579,70.769323 252.96923,71.219323 252.72669,71.219323 C 252.48415,71.219323 252.28571,70.769323 252.28571,70.219323 z M 12.364661,20.635993 C 12.412645,19.471043 12.649602,19.234093 12.968828,20.031823 C 13.257699,20.753703 13.222172,21.616203 12.889881,21.948493 C 12.557589,22.280783 12.32124,21.690153 12.364661,20.635993 z" + id="path3242" + inkscape:export-filename="/home/rhatto/upload/hidra-trace.jpg.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> +</svg> diff --git a/doc/images/An_example_of_theoretical_DNS_recursion.png b/doc/images/An_example_of_theoretical_DNS_recursion.png Binary files differnew file mode 100644 index 0000000..39c87e8 --- /dev/null +++ b/doc/images/An_example_of_theoretical_DNS_recursion.png diff --git a/doc/images/An_example_of_theoretical_DNS_recursion.svg b/doc/images/An_example_of_theoretical_DNS_recursion.svg new file mode 100644 index 0000000..a994bcb --- /dev/null +++ b/doc/images/An_example_of_theoretical_DNS_recursion.svg @@ -0,0 +1,424 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="450.00000pt" + height="160.00000pt" + id="svg1373" + sodipodi:version="0.32" + inkscape:version="0.42.2" + sodipodi:docbase="C:\Documents and Settings\test\Desktop" + sodipodi:docname="An example of theoretical DNS recursion.svg"> + <defs + id="defs1375"> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + sodipodi:nodetypes="ccccc" + id="path6037" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.8)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.70710678" + inkscape:cx="302.81250" + inkscape:cy="114.85429" + inkscape:document-units="px" + inkscape:current-layer="layer1" + inkscape:window-width="1024" + inkscape:window-height="721" + inkscape:window-x="-4" + inkscape:window-y="-4" /> + <metadata + id="metadata1378"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title>An example of theoretical DNS recursion</dc:title> + <dc:date>2005-10-24</dc:date> + <dc:creator> + <cc:Agent> + <dc:title>Lion Kimbro</dc:title> + </cc:Agent> + </dc:creator> + <dc:rights> + <cc:Agent> + <dc:title>Public Domain</dc:title> + </cc:Agent> + </dc:rights> + <dc:subject> + <rdf:Bag> + <rdf:li>DNS recursive resolver recurser root nameserver IP address</rdf:li> + </rdf:Bag> + </dc:subject> + <dc:description>A DNS resolver recursively queries a root nameserver, org. nameserver, and wikipedia.org. nameserver in it's quest to resolve the IP address associated with the domain name www.wikipedia.org. Created and placed into the public domain by myself, Lion Kimbro.</dc:description> + <dc:contributor> + <cc:Agent> + <dc:title>Lion Kimbro</dc:title> + </cc:Agent> + </dc:contributor> + <cc:license + rdf:resource="http://web.resource.org/cc/PublicDomain" /> + </cc:Work> + <cc:License + rdf:about="http://web.resource.org/cc/PublicDomain"> + <cc:permits + rdf:resource="http://web.resource.org/cc/Reproduction" /> + <cc:permits + rdf:resource="http://web.resource.org/cc/Distribution" /> + <cc:permits + rdf:resource="http://web.resource.org/cc/DerivativeWorks" /> + </cc:License> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <g + id="g2169" + transform="translate(-218.0000,-418.0000)"> + <text + id="text2778" + y="533.36218" + x="293" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="533.36218" + x="293.00000" + id="tspan2780" + sodipodi:role="line"> </tspan></text> + <rect + y="515.36218" + x="240.00000" + height="36.000000" + width="106.00000" + id="rect2782" + style="opacity:1.0000000;color:#000000;fill:#7f7fff;fill-opacity:0.13815786;fill-rule:nonzero;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" /> + <text + id="text1310" + y="537.71277" + x="250.70117" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="537.71277" + x="250.70117" + id="tspan1312" + sodipodi:role="line">DNS Recurser</tspan></text> + </g> + <g + id="g3690" + transform="translate(-120.0000,-396.0000)"> + <rect + style="opacity:1.0000000;color:#000000;fill:#ffff7f;fill-opacity:0.27631578;fill-rule:nonzero;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" + id="rect2183" + width="106.00000" + height="36.000000" + x="443.99414" + y="425.87830" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-weight:normal;text-align:center;line-height:125.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="496.43457" + y="440.50037" + id="text2185" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan2187" + x="496.43457" + y="440.50037">root</tspan><tspan + sodipodi:role="line" + x="496.43457" + y="455.50037" + id="tspan3684">nameserver</tspan></text> + </g> + <g + id="g3678" + transform="translate(-123.0059,-401.9883)"> + <rect + style="opacity:1.0000000;color:#000000;fill:#ffff7f;fill-opacity:0.27631578;fill-rule:nonzero;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" + id="rect2191" + width="106.00000" + height="36.000000" + x="447.00000" + y="483.86658" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-weight:normal;text-align:center;line-height:125.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="499.77734" + y="498.67908" + id="text2193" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan2195" + x="499.77734" + y="498.67908">org.</tspan><tspan + sodipodi:role="line" + x="499.77734" + y="513.67908" + id="tspan3672">nameserver</tspan></text> + </g> + <g + id="g3696" + transform="translate(-123.0059,-349.9883)"> + <rect + style="opacity:1.0000000;color:#000000;fill:#ffff7f;fill-opacity:0.27631578;fill-rule:nonzero;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" + id="rect3698" + width="106.00000" + height="36.000000" + x="447.00000" + y="483.86658" /> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-weight:normal;text-align:center;line-height:125.00000%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="499.77734" + y="498.67908" + id="text3700" + sodipodi:linespacing="125.00000%"><tspan + sodipodi:role="line" + id="tspan3702" + x="499.77734" + y="498.67908">wikipedia.org.</tspan><tspan + sodipodi:role="line" + x="499.77734" + y="513.67908" + id="tspan3704">nameserver</tspan></text> + </g> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="440" + y="66.179077" + id="text3706"><tspan + sodipodi:role="line" + id="tspan3708" + x="440.00000" + y="66.179077">198.41.0.4</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="440.68555" + y="118.19666" + id="text3710"><tspan + sodipodi:role="line" + id="tspan3712" + x="440.68555" + y="118.19666">204.74.112.1</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="440.68555" + y="170.19666" + id="text3714"><tspan + sodipodi:role="line" + id="tspan3716" + x="440.68555" + y="170.19666">207.142.131.234</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="416" + y="199.36218" + id="text3718"><tspan + sodipodi:role="line" + id="tspan3720" + x="416.00000" + y="199.36218"> </tspan></text> + <g + id="g5183" + transform="translate(-95.95840,-398.8284)"> + <path + id="rect3726" + d="M 243.03125,425.37500 C 189.29325,425.37500 146.03125,432.06500 146.03125,440.37500 C 146.03125,448.62038 188.65601,455.24082 241.81250,455.34375 C 237.21908,464.31404 228.80258,477.13945 212.12500,485.96875 C 226.52255,479.79837 244.48172,465.49000 254.93750,455.37500 L 254.96875,455.37500 C 308.70675,455.37500 351.96873,448.68500 351.96875,440.37500 C 351.96875,432.06500 308.70675,425.37500 254.96875,425.37500 L 243.03125,425.37500 z " + style="opacity:1.0000000;color:#000000;fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" /> + <text + id="text3722" + y="445.36218" + x="158" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="445.36218" + x="158.00000" + id="tspan3724" + sodipodi:role="line">"Where's www.wikipedia.org?"</tspan></text> + </g> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);stroke-opacity:1.0000000" + d="M 143.04372,129.56763 C 143.04372,129.56763 236.38182,145.12398 263.25188,147.95241 C 290.12193,150.78083 316.99199,138.05291 316.99199,138.05291 C 316.99199,138.05291 314.16356,140.88134 280.22244,140.88134 C 246.28131,140.88134 138.80108,111.18285 138.80108,111.18285 C 138.80108,111.18285 198.19805,116.83971 246.28131,116.83971 C 294.36457,116.83971 319.82042,92.798080 319.82042,92.798080 C 319.82042,92.798080 314.16356,95.626500 278.80822,99.869150 C 243.45289,104.11179 138.80108,101.28336 138.80108,101.28336 C 138.80108,101.28336 203.85491,91.383860 253.35238,81.484370 C 302.84986,71.584870 316.99199,53.200100 316.99199,53.200100 C 316.99199,53.200100 179.81328,74.413300 135.97265,92.798080" + id="path5188" + sodipodi:nodetypes="cscscscscscc" /> + <g + id="g6071" + transform="matrix(0.786178,0.000000,0.000000,0.786178,24.57500,-396.1817)"> + <path + transform="translate(39.59798,-31.11270)" + sodipodi:type="arc" + style="opacity:1.0000000;color:#000000;fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" + id="path6067" + sodipodi:cx="239.70920" + sodipodi:cy="618.90570" + sodipodi:rx="12.727922" + sodipodi:ry="12.727922" + d="M 252.43712 618.90570 A 12.727922 12.727922 0 1 1 226.98128,618.90570 A 12.727922 12.727922 0 1 1 252.43712 618.90570 z" /> + <text + id="text6053" + y="592.16998" + x="275.31696" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="592.16998" + x="275.31696" + id="tspan6055" + sodipodi:role="line">1</tspan></text> + </g> + <g + id="g6076" + transform="matrix(0.786178,0.000000,0.000000,0.786178,-12.51530,-364.4642)"> + <path + transform="translate(77.78175,-28.28427)" + sodipodi:type="arc" + style="opacity:1.0000000;color:#000000;fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" + id="path6069" + sodipodi:cx="239.70920" + sodipodi:cy="618.90570" + sodipodi:rx="12.727922" + sodipodi:ry="12.727922" + d="M 252.43712 618.90570 A 12.727922 12.727922 0 1 1 226.98128,618.90570 A 12.727922 12.727922 0 1 1 252.43712 618.90570 z" /> + <text + id="text6057" + y="595.07458" + x="313.59445" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="595.07458" + x="313.59445" + id="tspan6059" + sodipodi:role="line">2</tspan></text> + </g> + <g + id="g6081" + transform="matrix(0.786178,0.000000,0.000000,0.786178,-63.34762,-338.9106)"> + <path + transform="translate(124.4508,-21.21320)" + d="M 252.43712 618.90570 A 12.727922 12.727922 0 1 1 226.98128,618.90570 A 12.727922 12.727922 0 1 1 252.43712 618.90570 z" + sodipodi:ry="12.727922" + sodipodi:rx="12.727922" + sodipodi:cy="618.90570" + sodipodi:cx="239.70920" + id="path6065" + style="opacity:1.0000000;color:#000000;fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" + sodipodi:type="arc" /> + <text + id="text6061" + y="602.05481" + x="360.30746" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="602.05481" + x="360.30746" + id="tspan6063" + sodipodi:role="line">3</tspan></text> + </g> + <g + id="g7564" + transform="translate(17.17870,-557.2203)"> + <rect + ry="15.000001" + rx="97.000000" + y="620.18884" + x="242.33130" + height="15.818481" + width="112.13553" + id="rect6098" + style="opacity:1.0000000;color:#000000;fill:#ffffff;fill-opacity:1.0000000;fill-rule:nonzero;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" /> + <text + id="text6086" + y="631.63367" + x="259.50821" + style="font-size:8.3499565px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0.00000000;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1.0000000;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="631.63367" + x="259.50821" + id="tspan6088" + sodipodi:role="line">"Try 204.74.112.1"</tspan></text> + </g> + <g + id="g7580" + transform="translate(-73.33095,-513.3797)"> + <rect + ry="15.000001" + rx="97.000000" + y="623.72443" + x="313.74908" + height="15.818481" + width="112.13553" + id="rect7571" + style="opacity:1.0000000;color:#000000;fill:#ffffff;fill-opacity:1.0000000;fill-rule:nonzero;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" /> + <text + id="text6090" + y="634.4621" + x="323.1478" + style="font-size:8.3499565px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0.00000000;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1.0000000;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="634.46210" + x="323.14780" + id="tspan6092" + sodipodi:role="line">"Try 207.142.131.234"</tspan></text> + </g> + <g + transform="translate(-95.25130,-478.0244)" + id="g7587"> + <rect + ry="15.000001" + rx="97.000000" + y="623.72443" + x="313.74908" + height="15.818481" + width="112.13553" + id="rect7589" + style="opacity:1.0000000;color:#000000;fill:#ffffff;fill-opacity:1.0000000;fill-rule:nonzero;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" /> + <text + id="text7591" + y="634.4621" + x="323.1478" + style="font-size:8.3499565px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0.00000000;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:1.0000000;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" + xml:space="preserve"><tspan + y="634.46210" + x="323.14780" + id="tspan7593" + sodipodi:role="line">"It's at xxx.xx.xx.xxx"</tspan></text> + </g> + <text + xml:space="preserve" + style="font-size:12.000000px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" + x="377.80316" + y="74.4133" + id="text7595"><tspan + sodipodi:role="line" + id="tspan7597" + x="377.80316" + y="74.413300"> </tspan></text> + </g> +</svg> diff --git a/doc/images/Hydra001.jpg b/doc/images/Hydra001.jpg Binary files differnew file mode 100644 index 0000000..d38656d --- /dev/null +++ b/doc/images/Hydra001.jpg diff --git a/doc/images/Hydra_04.jpg b/doc/images/Hydra_04.jpg Binary files differnew file mode 100644 index 0000000..14584cb --- /dev/null +++ b/doc/images/Hydra_04.jpg diff --git a/doc/images/client-server.gif b/doc/images/client-server.gif Binary files differnew file mode 100644 index 0000000..00042b5 --- /dev/null +++ b/doc/images/client-server.gif diff --git a/doc/images/flussomail.png b/doc/images/flussomail.png Binary files differnew file mode 100644 index 0000000..4d62dc1 --- /dev/null +++ b/doc/images/flussomail.png diff --git a/doc/images/rete.png b/doc/images/rete.png Binary files differnew file mode 100644 index 0000000..9cb5fec --- /dev/null +++ b/doc/images/rete.png diff --git a/doc/images/rings.png b/doc/images/rings.png Binary files differnew file mode 100644 index 0000000..c1c1851 --- /dev/null +++ b/doc/images/rings.png diff --git a/doc/index.html b/doc/index.html new file mode 120000 index 0000000..473c42c --- /dev/null +++ b/doc/index.html @@ -0,0 +1 @@ +hidra.html
\ No newline at end of file diff --git a/doc/s6/jquery.js b/doc/s6/jquery.js new file mode 100644 index 0000000..5c99a8d --- /dev/null +++ b/doc/s6/jquery.js @@ -0,0 +1,8176 @@ +/*! + * jQuery JavaScript Library v1.5 + * 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: Mon Jan 31 08:31:29 2011 -0500 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The deferred used on DOM ready + readyList, + + // Promise methods + promiseMethods = "then done fail isResolved isRejected promise".split( " " ), + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.5", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; + } + + // Make sure that the DOM is not already loaded + if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval() ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type(array); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj , i /* internal */ ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ]; + } + return obj; + } + } ); + // Make sure only one callback list will be used + deferred.then( failDeferred.cancel, deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( object ) { + var args = arguments, + length = args.length, + deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ? + object : + jQuery.Deferred(), + promise = deferred.promise(), + resolveArray; + + if ( length > 1 ) { + resolveArray = new Array( length ); + jQuery.each( args, function( index, element ) { + jQuery.when( element ).then( function( value ) { + resolveArray[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; + if( ! --length ) { + deferred.resolveWith( promise, resolveArray ); + } + }, deferred.reject ); + } ); + } else if ( deferred !== object ) { + deferred.resolve( object ); + } + return promise; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySubclass( selector, context ) { + return new jQuerySubclass.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySubclass, this ); + jQuerySubclass.superclass = this; + jQuerySubclass.fn = jQuerySubclass.prototype = this(); + jQuerySubclass.fn.constructor = jQuerySubclass; + jQuerySubclass.subclass = this.subclass; + jQuerySubclass.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { + context = jQuerySubclass(context); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); + }; + jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; + var rootjQuerySubclass = jQuerySubclass(document); + return jQuerySubclass; + }, + + browser: {} +}); + +// Create readyList deferred +readyList = jQuery._Deferred(); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return (window.jQuery = window.$ = jQuery); + +})(); + + +(function() { + + jQuery.support = {}; + + var div = document.createElement("div"); + + div.style.display = "none"; + div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0], + select = document.createElement("select"), + opt = select.appendChild( document.createElement("option") ); + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: div.getElementsByTagName("input")[0].value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Will be defined later + deleteExpando: true, + optDisabled: false, + checkClone: false, + _scriptEval: null, + noCloneEvent: true, + boxModel: null, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableHiddenOffsets: true + }; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as diabled) + select.disabled = true; + jQuery.support.optDisabled = !opt.disabled; + + jQuery.support.scriptEval = function() { + if ( jQuery.support._scriptEval === null ) { + var root = document.documentElement, + script = document.createElement("script"), + id = "script" + jQuery.now(); + + script.type = "text/javascript"; + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + jQuery.support._scriptEval = true; + delete window[ id ]; + } else { + jQuery.support._scriptEval = false; + } + + root.removeChild( script ); + // release memory in IE + root = script = id = null; + } + + return jQuery.support._scriptEval; + }; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + + if ( div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>"; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"), + body = document.getElementsByTagName("body")[0]; + + // Frameset documents with no body should not run this code + if ( !body ) { + return; + } + + div.style.width = div.style.paddingLeft = "1px"; + body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "<div style='width:4px;'></div>"; + jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; + } + + div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>"; + var tds = div.getElementsByTagName("td"); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; + + tds[0].style.display = ""; + tds[1].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; + div.innerHTML = ""; + + body.removeChild( div ).style.display = "none"; + div = tds = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( !el.attachEvent ) { + return true; + } + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + div = all = a = null; +})(); + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !jQuery.isEmptyObject(elem); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !jQuery.isEmptyObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = name.substr( 5 ); + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + data = elem.getAttribute( "data-" + key ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + + + + +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspaces = /\s+/, + rreturn = /\r/g, + rspecialurl = /^(?:href|src|style)$/, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rradiocheck = /^(?:radio|checkbox)$/i; + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", + setClass = elem.className; + + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspaces ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( !arguments.length ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray(val) ) { + val = jQuery.map(val, function (value) { + return value == null ? "" : value + ""; + }); + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + // 'in' checks fail in Blackberry 4.7 #6931 + if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + if ( value === null ) { + if ( elem.nodeType === 1 ) { + elem.removeAttribute( name ); + } + + } else { + elem[ name ] = value; + } + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + // Ensure that missing attributes return undefined + // Blackberry 4.7 returns "" from getAttribute #6938 + if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { + return undefined; + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + // Handle everything which isn't a DOM element node + if ( set ) { + elem[ name ] = value; + } + return elem[ name ]; + } +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspace = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }, + eventKey = "events"; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData[ eventKey ], + eventHandle = elemData.handle; + + if ( typeof events === "function" ) { + // On plain objects events is a fn that holds the the data + // which prevents this data from being JSON serialized + // the function does not need to be called, it just contains the data + eventHandle = events.handle; + events = events.events; + + } else if ( !events ) { + if ( !elem.nodeType ) { + // On plain objects, create a fn that acts as the holder + // of the values to avoid JSON serialization of event data + elemData[ eventKey ] = elemData = function(){}; + } + + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData[ eventKey ]; + + if ( !elemData || !events ) { + return; + } + + if ( typeof events === "function" ) { + elemData = events; + events = events.events; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( typeof elemData === "function" ) { + jQuery.removeData( elem, eventKey, true ); + + } else if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + // XXX This code smells terrible. event.js should not be directly + // inspecting the data cache + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[type] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = elem.nodeType ? + jQuery._data( elem, "handle" ) : + (jQuery._data( elem, eventKey ) || {}).handle; + + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + event.preventDefault(); + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (inlineError) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var old, + target = event.target, + targetType = type.replace( rnamespaces, "" ), + isClick = jQuery.nodeName( target, "a" ) && targetType === "click", + special = jQuery.event.special[ targetType ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ targetType ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + targetType ]; + + if ( old ) { + target[ "on" + targetType ] = null; + } + + jQuery.event.triggered = true; + target[ targetType ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (triggerError) {} + + if ( old ) { + target[ "on" + targetType ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace_re, events, + namespace_sort = [], + args = jQuery.makeArray( arguments ); + + event = args[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace_sort = namespaces.slice(0).sort(); + namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.namespace = event.namespace || namespace_sort.join("."); + + events = jQuery._data(this, eventKey); + + if ( typeof events === "function" ) { + events = events.events; + } + + handlers = (events || {})[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.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( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, + body = document.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + e.liveFired = undefined; + return trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + e.liveFired = undefined; + return trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + return jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + args[0].type = type; + return jQuery.event.handle.apply( elem, args ); +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) || data === false ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, eventKey ); + + if ( typeof events === "function" ) { + events = events.events; + } + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); +} + +jQuery.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( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.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( elem ) { + return elem.getAttribute( "href" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !/\W/.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace(/\\/g, ""); + }, + + TAG: function( match, curLoop ) { + return match[1].toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace(/\\/g, ""); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + return "text" === elem.type; + }, + radio: function( elem ) { + return "radio" === elem.type; + }, + + checkbox: function( elem ) { + return "checkbox" === elem.type; + }, + + file: function( elem ) { + return "file" === elem.type; + }, + password: function( elem ) { + return "password" === elem.type; + }, + + submit: function( elem ) { + return "submit" === elem.type; + }, + + image: function( elem ) { + return "image" === elem.type; + }, + + reset: function( elem ) { + return "reset" === elem.type; + }, + + button: function( elem ) { + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // If the nodes are siblings (or identical) we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = "<a name='" + id + "'/>"; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = "<a href='#'></a>"; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "<p class='TEST'></p>"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + context.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + if ( matches ) { + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + return matches.call( node, expr ); + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "<div class='test e'></div><div class='test'></div>"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), + length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + var pos = POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique(ret) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /<tbody/i, + rhtml = /<|&#?\w+;/, + rnocache = /<(?:script|object|embed|option|style)/i, + // checked="checked" or checked (html5) + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + wrapMap = { + 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, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize <link> and <script> tags normally +if ( !jQuery.support.htmlSerialize ) { + wrapMap._default = [ 1, "div<div>", "</div>" ]; +} + +jQuery.fn.extend({ + text: function( text ) { + if ( jQuery.isFunction(text) ) { + return this.each(function(i) { + var self = jQuery( this ); + + self.text( text.call(this, i, self.text()) ); + }); + } + + if ( typeof text !== "object" && text !== undefined ) { + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + } + + return jQuery.text( this ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append(this); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + return this.each(function() { + jQuery( this ).wrapAll( html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this ); + }); + } else if ( arguments.length ) { + var set = jQuery(arguments[0]); + set.push.apply( set, this.toArray() ); + return this.pushStack( set, "before", arguments ); + } + }, + + after: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } else if ( arguments.length ) { + var set = this.pushStack( this, "after", arguments ); + set.push.apply( set, jQuery(arguments[0]).toArray() ); + return set; + } + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? true : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + if ( value === undefined ) { + return this[0] && this[0].nodeType === 1 ? + this[0].innerHTML.replace(rinlinejQuery, "") : + null; + + // See if we can take a shortcut and just use innerHTML + } else if ( typeof value === "string" && !rnocache.test( value ) && + (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && + !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { + + value = value.replace(rxhtmlTag, "<$1></$2>"); + + try { + for ( var i = 0, l = this.length; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + if ( this[i].nodeType === 1 ) { + jQuery.cleanData( this[i].getElementsByTagName("*") ); + this[i].innerHTML = value; + } + } + + // If using innerHTML throws an exception, use the fallback method + } catch(e) { + this.empty().append( value ); + } + + } else if ( jQuery.isFunction( value ) ) { + this.each(function(i){ + var self = jQuery( this ); + + self.html( value.call(this, i, self.html()) ); + }); + + } else { + this.empty().append( value ); + } + + return this; + }, + + replaceWith: function( value ) { + if ( this[0] && this[0].parentNode ) { + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this), old = self.html(); + self.replaceWith( value.call( this, i, old ) ); + }); + } + + if ( typeof value !== "string" ) { + value = jQuery( value ).detach(); + } + + return this.each(function() { + var next = this.nextSibling, + parent = this.parentNode; + + jQuery( this ).remove(); + + if ( next ) { + jQuery(next).before( value ); + } else { + jQuery(parent).append( value ); + } + }); + } else { + return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ); + } + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + var results, first, fragment, parent, + value = args[0], + scripts = []; + + // We can't cloneNode fragments that contain checked, in WebKit + if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { + return this.each(function() { + jQuery(this).domManip( args, table, callback, true ); + }); + } + + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call(this, i, table ? self.html() : undefined); + self.domManip( args, table, callback ); + }); + } + + if ( this[0] ) { + parent = value && value.parentNode; + + // If we're in a fragment, just use that instead of building a new one + if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { + results = { fragment: parent }; + + } else { + results = jQuery.buildFragment( args, this, scripts ); + } + + fragment = results.fragment; + + if ( fragment.childNodes.length === 1 ) { + first = fragment = fragment.firstChild; + } else { + first = fragment.firstChild; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + + for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) { + callback.call( + table ? + root(this[i], first) : + this[i], + // Make sure that we do not leak memory by inadvertently discarding + // the original fragment (which might have attached data) instead of + // using it; in addition, use the original fragment object for the last + // item instead of first because it can end up being emptied incorrectly + // in certain situations (Bug #8070). + // Fragments from the fragment cache must always be cloned and never used + // in place. + results.cacheable || (l > 1 && i < lastIndex) ? + jQuery.clone( fragment, true, true ) : + fragment + ); + } + } + + if ( scripts.length ) { + jQuery.each( scripts, evalScript ); + } + } + + return this; + } +}); + +function root( elem, cur ) { + return jQuery.nodeName(elem, "table") ? + (elem.getElementsByTagName("tbody")[0] || + elem.appendChild(elem.ownerDocument.createElement("tbody"))) : + elem; +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var internalKey = jQuery.expando, + oldData = jQuery.data( src ), + curData = jQuery.data( dest, oldData ); + + // Switch to use the internal data object, if it exists, for the next + // stage of data copying + if ( (oldData = oldData[ internalKey ]) ) { + var events = oldData.events; + curData = curData[ internalKey ] = jQuery.extend({}, oldData); + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( var type in events ) { + for ( var i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ], events[ type ][ i ].data ); + } + } + } + } +} + +function cloneFixAttributes(src, dest) { + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + var nodeName = dest.nodeName.toLowerCase(); + + // clearAttributes removes the attributes, which we don't want, + // but also removes the attachEvent events, which we *do* want + dest.clearAttributes(); + + // mergeAttributes, in contrast, only merges back on the + // original attributes, not the events + dest.mergeAttributes(src); + + // IE6-8 fail to clone children inside object elements that use + // the proprietary classid attribute value (rather than the type + // attribute) to identify the type of content to display + if ( nodeName === "object" ) { + dest.outerHTML = src.outerHTML; + + } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + if ( src.checked ) { + dest.defaultChecked = dest.checked = src.checked; + } + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } + + // Event data gets referenced instead of copied if the expando + // gets copied too + dest.removeAttribute( jQuery.expando ); +} + +jQuery.buildFragment = function( args, nodes, scripts ) { + var fragment, cacheable, cacheresults, + doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); + + // Only cache "small" (1/2 KB) HTML strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && + args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { + + cacheable = true; + cacheresults = jQuery.fragments[ args[0] ]; + if ( cacheresults ) { + if ( cacheresults !== 1 ) { + fragment = cacheresults; + } + } + } + + if ( !fragment ) { + fragment = doc.createDocumentFragment(); + jQuery.clean( args, doc, fragment, scripts ); + } + + if ( cacheable ) { + jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1; + } + + return { fragment: fragment, cacheable: cacheable }; +}; + +jQuery.fragments = {}; + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +}); + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var clone = elem.cloneNode(true), + srcElements, + destElements, + i; + + if ( !jQuery.support.noCloneEvent && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + // IE copies events bound via attachEvent when using cloneNode. + // Calling detachEvent on the clone will also remove the events + // from the original. In order to get around this, we use some + // proprietary methods to clear the events. Thanks to MooTools + // guys for this hotness. + + // Using Sizzle here is crazy slow, so we use getElementsByTagName + // instead + srcElements = elem.getElementsByTagName("*"); + destElements = clone.getElementsByTagName("*"); + + // Weird iteration because IE will replace the length property + // with an element if you are cloning the body and one of the + // elements on the page has a name or id of "length" + for ( i = 0; srcElements[i]; ++i ) { + cloneFixAttributes( srcElements[i], destElements[i] ); + } + + cloneFixAttributes( elem, clone ); + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + + cloneCopyEvent( elem, clone ); + + if ( deepDataAndEvents && "getElementsByTagName" in elem ) { + + srcElements = elem.getElementsByTagName("*"); + destElements = clone.getElementsByTagName("*"); + + if ( srcElements.length ) { + for ( i = 0; srcElements[i]; ++i ) { + cloneCopyEvent( srcElements[i], destElements[i] ); + } + } + } + } + // Return the cloned set + return clone; + }, + clean: function( elems, context, fragment, scripts ) { + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) { + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + } + + var ret = []; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( typeof elem === "number" ) { + elem += ""; + } + + if ( !elem ) { + continue; + } + + // Convert html string into DOM nodes + if ( typeof elem === "string" && !rhtml.test( elem ) ) { + elem = context.createTextNode( elem ); + + } else if ( typeof elem === "string" ) { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(rxhtmlTag, "<$1></$2>"); + + // Trim whitespace, otherwise indexOf won't work as expected + var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), + wrap = wrapMap[ tag ] || wrapMap._default, + depth = wrap[0], + div = context.createElement("div"); + + // Go to html and back, then peel off extra wrappers + div.innerHTML = wrap[1] + elem + wrap[2]; + + // Move to the right depth + while ( depth-- ) { + div = div.lastChild; + } + + // Remove IE's autoinserted <tbody> from table fragments + if ( !jQuery.support.tbody ) { + + // String was a <table>, *may* have spurious <tbody> + var hasBody = rtbody.test(elem), + tbody = tag === "table" && !hasBody ? + div.firstChild && div.firstChild.childNodes : + + // String was a bare <thead> or <tfoot> + wrap[1] === "<table>" && !hasBody ? + div.childNodes : + []; + + for ( var j = tbody.length - 1; j >= 0 ; --j ) { + if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { + tbody[ j ].parentNode.removeChild( tbody[ j ] ); + } + } + + } + + // IE completely kills leading whitespace when innerHTML is used + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); + } + + elem = div.childNodes; + } + + if ( elem.nodeType ) { + ret.push( elem ); + } else { + ret = jQuery.merge( ret, elem ); + } + } + + if ( fragment ) { + for ( i = 0; ret[i]; i++ ) { + if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { + scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); + + } else { + if ( ret[i].nodeType === 1 ) { + ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) ); + } + fragment.appendChild( ret[i] ); + } + } + } + + return ret; + }, + + cleanData: function( elems ) { + var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special, + deleteExpando = jQuery.support.deleteExpando; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + continue; + } + + id = elem[ jQuery.expando ]; + + if ( id ) { + data = cache[ id ] && cache[ id ][ internalKey ]; + + if ( data && data.events ) { + for ( var type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + + // Null the DOM reference to avoid IE6/7/8 leak (#7054) + if ( data.handle ) { + data.handle.elem = null; + } + } + + if ( deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + delete cache[ id ]; + } + } + } +}); + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + + + + +var ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity=([^)]*)/, + rdashAlpha = /-([a-z])/ig, + rupper = /([A-Z])/g, + rnumpx = /^-?\d+(?:px)?$/i, + rnum = /^-?\d/, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssWidth = [ "Left", "Right" ], + cssHeight = [ "Top", "Bottom" ], + curCSS, + + getComputedStyle, + currentStyle, + + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn.css = function( name, value ) { + // Setting 'undefined' is a no-op + if ( arguments.length === 2 && value === undefined ) { + return this; + } + + return jQuery.access( this, name, value, true, function( elem, name, value ) { + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }); +}; + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity", "opacity" ); + return ret === "" ? "1" : ret; + + } else { + return elem.style.opacity; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "zIndex": true, + "fontWeight": true, + "opacity": true, + "zoom": true, + "lineHeight": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, origName = jQuery.camelCase( name ), + style = elem.style, hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // Check if we're setting a value + if ( value !== undefined ) { + // Make sure that NaN and null values aren't set. See: #7116 + if ( typeof value === "number" && isNaN( value ) || value == null ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra ) { + // Make sure that we're working with the right name + var ret, origName = jQuery.camelCase( name ), + hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name, origName ); + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + }, + + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + } +}); + +// DEPRECATED, Use jQuery.css() instead +jQuery.curCSS = jQuery.css; + +jQuery.each(["height", "width"], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + var val; + + if ( computed ) { + if ( elem.offsetWidth !== 0 ) { + val = getWH( elem, name, extra ); + + } else { + jQuery.swap( elem, cssShow, function() { + val = getWH( elem, name, extra ); + }); + } + + if ( val <= 0 ) { + val = curCSS( elem, name, name ); + + if ( val === "0px" && currentStyle ) { + val = currentStyle( elem, name, name ); + } + + if ( val != null ) { + // Should return "auto" instead of 0, use 0 for + // temporary backwards-compat + return val === "" || val === "auto" ? "0px" : val; + } + } + + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + + // Should return "auto" instead of 0, use 0 for + // temporary backwards-compat + return val === "" || val === "auto" ? "0px" : val; + } + + return typeof val === "string" ? val : val + "px"; + } + }, + + set: function( elem, value ) { + if ( rnumpx.test( value ) ) { + // ignore negative width and height values #1599 + value = parseFloat(value); + + if ( value >= 0 ) { + return value + "px"; + } + + } else { + return value; + } + } + }; +}); + +if ( !jQuery.support.opacity ) { + jQuery.cssHooks.opacity = { + get: function( elem, computed ) { + // IE uses filters for opacity + return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ? + (parseFloat(RegExp.$1) / 100) + "" : + computed ? "1" : ""; + }, + + set: function( elem, value ) { + var style = elem.style; + + // IE has trouble with opacity if it does not have layout + // Force it by setting the zoom level + style.zoom = 1; + + // Set the alpha filter to set the opacity + var opacity = jQuery.isNaN(value) ? + "" : + "alpha(opacity=" + value * 100 + ")", + filter = style.filter || ""; + + style.filter = ralpha.test(filter) ? + filter.replace(ralpha, opacity) : + style.filter + ' ' + opacity; + } + }; +} + +if ( document.defaultView && document.defaultView.getComputedStyle ) { + getComputedStyle = function( elem, newName, name ) { + var ret, defaultView, computedStyle; + + name = name.replace( rupper, "-$1" ).toLowerCase(); + + if ( !(defaultView = elem.ownerDocument.defaultView) ) { + return undefined; + } + + if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) { + ret = computedStyle.getPropertyValue( name ); + if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { + ret = jQuery.style( elem, name ); + } + } + + return ret; + }; +} + +if ( document.documentElement.currentStyle ) { + currentStyle = function( elem, name ) { + var left, + ret = elem.currentStyle && elem.currentStyle[ name ], + rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ], + style = elem.style; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !rnumpx.test( ret ) && rnum.test( ret ) ) { + // Remember the original values + left = style.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + elem.runtimeStyle.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : (ret || 0); + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + elem.runtimeStyle.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +curCSS = getComputedStyle || currentStyle; + +function getWH( elem, name, extra ) { + var which = name === "width" ? cssWidth : cssHeight, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight; + + if ( extra === "border" ) { + return val; + } + + jQuery.each( which, function() { + if ( !extra ) { + val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0; + } + + if ( extra === "margin" ) { + val += parseFloat(jQuery.css( elem, "margin" + this )) || 0; + + } else { + val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0; + } + }); + + return val; +} + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.hidden = function( elem ) { + var width = elem.offsetWidth, + height = elem.offsetHeight; + + return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none"); + }; + + jQuery.expr.filters.visible = function( elem ) { + return !jQuery.expr.filters.hidden( elem ); + }; +} + + + + +var r20 = /%20/g, + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rhash = /#.*$/, + rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL + rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + rquery = /\?/, + rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, + rselectTextarea = /^(?:select|textarea)/i, + rspacesAjax = /\s+/, + rts = /([?&])_=[^&]*/, + rurl = /^(\w+:)\/\/([^\/?#:]+)(?::(\d+))?/, + + // Keep a copy of the old load method + _load = jQuery.fn.load, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + if ( jQuery.isFunction( func ) ) { + var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), + i = 0, + length = dataTypes.length, + dataType, + list, + placeBefore; + + // For each dataType in the dataTypeExpression + for(; i < length; i++ ) { + dataType = dataTypes[ i ]; + // We control if we're asked to add before + // any existing element + placeBefore = /^\+/.test( dataType ); + if ( placeBefore ) { + dataType = dataType.substr( 1 ) || "*"; + } + list = structure[ dataType ] = structure[ dataType ] || []; + // then we add to the structure accordingly + list[ placeBefore ? "unshift" : "push" ]( func ); + } + } + }; +} + +//Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jXHR, + dataType /* internal */, inspected /* internal */ ) { + + dataType = dataType || options.dataTypes[ 0 ]; + inspected = inspected || {}; + + inspected[ dataType ] = true; + + var list = structure[ dataType ], + i = 0, + length = list ? list.length : 0, + executeOnly = ( structure === prefilters ), + selection; + + for(; i < length && ( executeOnly || !selection ); i++ ) { + selection = list[ i ]( options, originalOptions, jXHR ); + // If we got redirected to another dataType + // we try there if not done already + if ( typeof selection === "string" ) { + if ( inspected[ selection ] ) { + selection = undefined; + } else { + options.dataTypes.unshift( selection ); + selection = inspectPrefiltersOrTransports( + structure, options, originalOptions, jXHR, selection, inspected ); + } + } + } + // If we're only executing or nothing was selected + // we try the catchall dataType if not done already + if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { + selection = inspectPrefiltersOrTransports( + structure, options, originalOptions, jXHR, "*", inspected ); + } + // unnecessary when only executing (prefilters) + // but it'll be ignored by the caller in that case + return selection; +} + +jQuery.fn.extend({ + load: function( url, params, callback ) { + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + + // Don't do a request if no elements are being requested + } else if ( !this.length ) { + return this; + } + + var off = url.indexOf( " " ); + if ( off >= 0 ) { + var selector = url.slice( off, url.length ); + url = url.slice( 0, off ); + } + + // Default to a GET request + var type = "GET"; + + // If the second parameter was provided + if ( params ) { + // If it's a function + if ( jQuery.isFunction( params ) ) { + // We assume that it's the callback + callback = params; + params = null; + + // Otherwise, build a param string + } else if ( typeof params === "object" ) { + params = jQuery.param( params, jQuery.ajaxSettings.traditional ); + type = "POST"; + } + } + + var self = this; + + // Request the remote document + jQuery.ajax({ + url: url, + type: type, + dataType: "html", + data: params, + // Complete callback (responseText is used internally) + complete: function( jXHR, status, responseText ) { + // Store the response as specified by the jXHR object + responseText = jXHR.responseText; + // If successful, inject the HTML into all the matched elements + if ( jXHR.isResolved() ) { + // #4825: Get the actual response in case + // a dataFilter is present in ajaxSettings + jXHR.done(function( r ) { + responseText = r; + }); + // See if a selector was specified + self.html( selector ? + // Create a dummy div to hold the results + jQuery("<div>") + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(responseText.replace(rscript, "")) + + // Locate the specified elements + .find(selector) : + + // If not, just inject the full result + responseText ); + } + + if ( callback ) { + self.each( callback, [ responseText, status, jXHR ] ); + } + } + }); + + return this; + }, + + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + + serializeArray: function() { + return this.map(function(){ + return this.elements ? jQuery.makeArray( this.elements ) : this; + }) + .filter(function(){ + return this.name && !this.disabled && + ( this.checked || rselectTextarea.test( this.nodeName ) || + rinput.test( this.type ) ); + }) + .map(function( i, elem ){ + var val = jQuery( this ).val(); + + return val == null ? + null : + jQuery.isArray( val ) ? + jQuery.map( val, function( val, i ){ + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }) : + { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }).get(); + } +}); + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ + jQuery.fn[ o ] = function( f ){ + return this.bind( o, f ); + }; +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = null; + } + + return jQuery.ajax({ + type: method, + url: url, + data: data, + success: callback, + dataType: type + }); + }; +} ); + +jQuery.extend({ + + getScript: function( url, callback ) { + return jQuery.get( url, null, callback, "script" ); + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + ajaxSetup: function( settings ) { + jQuery.extend( true, jQuery.ajaxSettings, settings ); + if ( settings.context ) { + jQuery.ajaxSettings.context = settings.context; + } + }, + + ajaxSettings: { + url: location.href, + global: true, + type: "GET", + contentType: "application/x-www-form-urlencoded", + processData: true, + async: true, + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + traditional: false, + headers: {}, + crossDomain: null, + */ + + 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" + }, + + // List of data converters + // 1) key format is "source_type destination_type" (a single space in-between) + // 2) the catchall symbol "*" can be used for source_type + converters: { + + // Convert anything to text + "* text": window.String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": jQuery.parseJSON, + + // Parse text as xml + "text xml": jQuery.parseXML + } + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If options is not an object, + // we simulate pre-1.5 signature + if ( typeof options !== "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var // Create the final options object + s = jQuery.extend( true, {}, jQuery.ajaxSettings, options ), + // Callbacks contexts + // We force the original context if it exists + // or take it from jQuery.ajaxSettings otherwise + // (plain objects used as context get extended) + callbackContext = + ( s.context = ( "context" in options ? options : jQuery.ajaxSettings ).context ) || s, + globalEventContext = callbackContext === s ? jQuery.event : jQuery( callbackContext ), + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery._Deferred(), + // Status-dependent callbacks + statusCode = s.statusCode || {}, + // Headers (they are sent all at once) + requestHeaders = {}, + // Response headers + responseHeadersString, + responseHeaders, + // transport + transport, + // timeout handle + timeoutTimer, + // Cross-domain detection vars + loc = document.location, + protocol = loc.protocol || "http:", + parts, + // The jXHR state + state = 0, + // Loop variable + i, + // Fake xhr + jXHR = { + + readyState: 0, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( state === 0 ) { + requestHeaders[ name.toLowerCase() ] = value; + } + return this; + }, + + // Raw string + getAllResponseHeaders: function() { + return state === 2 ? responseHeadersString : null; + }, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( state === 2 ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match || null; + }, + + // Cancel the request + abort: function( statusText ) { + statusText = statusText || "abort"; + if ( transport ) { + transport.abort( statusText ); + } + done( 0, statusText ); + return this; + } + }; + + // Callback for when everything is done + // It is defined here because jslint complains if it is declared + // at the end of the function (which would be more logical and readable) + function done( status, statusText, responses, headers) { + + // Called once + if ( state === 2 ) { + return; + } + + // State is "done" now + state = 2; + + // Clear timeout if it exists + if ( timeoutTimer ) { + clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jXHR.readyState = status ? 4 : 0; + + var isSuccess, + success, + error, + response = responses ? ajaxHandleResponses( s, jXHR, responses ) : undefined, + lastModified, + etag; + + // If successful, handle type chaining + if ( status >= 200 && status < 300 || status === 304 ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + + if ( ( lastModified = jXHR.getResponseHeader( "Last-Modified" ) ) ) { + jQuery.lastModified[ s.url ] = lastModified; + } + if ( ( etag = jXHR.getResponseHeader( "Etag" ) ) ) { + jQuery.etag[ s.url ] = etag; + } + } + + // If not modified + if ( status === 304 ) { + + statusText = "notmodified"; + isSuccess = true; + + // If we have data + } else { + + try { + success = ajaxConvert( s, response ); + statusText = "success"; + isSuccess = true; + } catch(e) { + // We have a parsererror + statusText = "parsererror"; + error = e; + } + } + } else { + // We extract error from statusText + // then normalize statusText and status for non-aborts + error = statusText; + if( status ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jXHR.status = status; + jXHR.statusText = statusText; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( s.global ) { + globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), + [ jXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.resolveWith( callbackContext, [ jXHR, statusText ] ); + + if ( s.global ) { + globalEventContext.trigger( "ajaxComplete", [ jXHR, s] ); + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + // Attach deferreds + deferred.promise( jXHR ); + jXHR.success = jXHR.done; + jXHR.error = jXHR.fail; + jXHR.complete = completeDeferred.done; + + // Status-dependent callbacks + jXHR.statusCode = function( map ) { + if ( map ) { + var tmp; + if ( state < 2 ) { + for( tmp in map ) { + statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; + } + } else { + tmp = map[ jXHR.status ]; + jXHR.then( tmp, tmp ); + } + } + return this; + }; + + // Remove hash character (#7531: and string promotion) + // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) + // We also use the url parameter if available + s.url = ( "" + ( url || s.url ) ).replace( rhash, "" ).replace( rprotocol, protocol + "//" ); + + // Extract dataTypes list + s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); + + // Determine if a cross-domain request is in order + if ( !s.crossDomain ) { + parts = rurl.exec( s.url.toLowerCase() ); + s.crossDomain = !!( parts && + ( parts[ 1 ] != protocol || parts[ 2 ] != loc.hostname || + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != + ( loc.port || ( protocol === "http:" ? 80 : 443 ) ) ) + ); + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jXHR ); + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Watch for a new set of requests + if ( s.global && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // If data is available, append data to url + if ( s.data ) { + s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; + } + + // Add anti-cache in url if needed + if ( s.cache === false ) { + + var ts = jQuery.now(), + // try replacing _= if it is there + ret = s.url.replace( rts, "$1_=" + ts ); + + // if nothing was replaced, add timestamp to the end + s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + requestHeaders[ "content-type" ] = s.contentType; + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ s.url ] ) { + requestHeaders[ "if-modified-since" ] = jQuery.lastModified[ s.url ]; + } + if ( jQuery.etag[ s.url ] ) { + requestHeaders[ "if-none-match" ] = jQuery.etag[ s.url ]; + } + } + + // Set the Accepts header for the server, depending on the dataType + requestHeaders.accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? + s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) : + s.accepts[ "*" ]; + + // Check for headers option + for ( i in s.headers ) { + requestHeaders[ i.toLowerCase() ] = s.headers[ i ]; + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jXHR, s ) === false || state === 2 ) ) { + // Abort if not done already + done( 0, "abort" ); + // Return false + jXHR = false; + + } else { + + // Install callbacks on deferreds + for ( i in { success: 1, error: 1, complete: 1 } ) { + jXHR[ i ]( s[ i ] ); + } + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + // Set state as sending + state = jXHR.readyState = 1; + // Send global event + if ( s.global ) { + globalEventContext.trigger( "ajaxSend", [ jXHR, s ] ); + } + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = setTimeout( function(){ + jXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + transport.send( requestHeaders, done ); + } catch (e) { + // Propagate exception as error if not done + if ( status < 2 ) { + done( -1, e ); + // Simply rethrow otherwise + } else { + jQuery.error( e ); + } + } + } + } + return jXHR; + }, + + // Serialize an array of form elements or a set of + // key/values into a query string + param: function( a, traditional ) { + var s = [], + add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction( value ) ? value() : value; + s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray( a ) || a.jquery ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( var prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ).replace( r20, "+" ); + } +}); + +function buildParams( prefix, obj, traditional, add ) { + if ( jQuery.isArray( obj ) && obj.length ) { + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + // If array item is non-scalar (array or object), encode its + // numeric index to resolve deserialization ambiguity issues. + // Note that rack (as of 1.0.0) can't currently deserialize + // nested arrays properly, and attempting to do so may cause + // a server error. Possible fixes are to modify rack's + // deserialization algorithm or to provide an option or flag + // to force array serialization to be shallow. + buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add ); + } + }); + + } else if ( !traditional && obj != null && typeof obj === "object" ) { + // If we see an array here, it is empty and should be treated as an empty + // object + if ( jQuery.isArray( obj ) || jQuery.isEmptyObject( obj ) ) { + add( prefix, "" ); + + // Serialize object item. + } else { + jQuery.each( obj, function( k, v ) { + buildParams( prefix + "[" + k + "]", v, traditional, add ); + }); + } + + } else { + // Serialize scalar item. + add( prefix, obj ); + } +} + +// This is still on the jQuery object... for now +// Want to move this to jQuery.ajax some day +jQuery.extend({ + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {} + +}); + +/* Handles responses to an ajax request: + * - sets all responseXXX fields accordingly + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jXHR, responses ) { + + var contents = s.contents, + dataTypes = s.dataTypes, + responseFields = s.responseFields, + ct, + type, + finalDataType, + firstDataType; + + // Fill responseXXX fields + for( type in responseFields ) { + if ( type in responses ) { + jXHR[ responseFields[type] ] = responses[ type ]; + } + } + + // Remove auto dataType and get content-type in the process + while( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = jXHR.getResponseHeader( "content-type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +// Chain conversions given the request and the original response +function ajaxConvert( s, response ) { + + // Apply the dataFilter if provided + if ( s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + var dataTypes = s.dataTypes, + converters = s.converters, + i, + length = dataTypes.length, + tmp, + // Current and previous dataTypes + current = dataTypes[ 0 ], + prev, + // Conversion expression + conversion, + // Conversion function + conv, + // Conversion functions (transitive conversion) + conv1, + conv2; + + // For each dataType in the chain + for( i = 1; i < length; i++ ) { + + // Get the dataTypes + prev = current; + current = dataTypes[ i ]; + + // If current is auto dataType, update it to prev + if( current === "*" ) { + current = prev; + // If no auto and dataTypes are actually different + } else if ( prev !== "*" && prev !== current ) { + + // Get the converter + conversion = prev + " " + current; + conv = converters[ conversion ] || converters[ "* " + current ]; + + // If there is no direct converter, search transitively + if ( !conv ) { + conv2 = undefined; + for( conv1 in converters ) { + tmp = conv1.split( " " ); + if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) { + conv2 = converters[ tmp[1] + " " + current ]; + if ( conv2 ) { + conv1 = converters[ conv1 ]; + if ( conv1 === true ) { + conv = conv2; + } else if ( conv2 === true ) { + conv = conv1; + } + break; + } + } + } + } + // If we found no converter, dispatch an error + if ( !( conv || conv2 ) ) { + jQuery.error( "No conversion from " + conversion.replace(" "," to ") ); + } + // If found converter is not an equivalence + if ( conv !== true ) { + // Convert with 1 or 2 converters accordingly + response = conv ? conv( response ) : conv2( conv1(response) ); + } + } + } + return response; +} + + + + +var jsc = jQuery.now(), + jsre = /(\=)\?(&|$)|()\?\?()/i; + +// Default jsonp settings +jQuery.ajaxSetup({ + jsonp: "callback", + jsonpCallback: function() { + return jQuery.expando + "_" + ( jsc++ ); + } +}); + +// Detect, normalize options and install callbacks for jsonp requests +jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, dataIsString /* internal */ ) { + + dataIsString = ( typeof s.data === "string" ); + + if ( s.dataTypes[ 0 ] === "jsonp" || + originalSettings.jsonpCallback || + originalSettings.jsonp != null || + s.jsonp !== false && ( jsre.test( s.url ) || + dataIsString && jsre.test( s.data ) ) ) { + + var responseContainer, + jsonpCallback = s.jsonpCallback = + jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback, + previous = window[ jsonpCallback ], + url = s.url, + data = s.data, + replace = "$1" + jsonpCallback + "$2"; + + if ( s.jsonp !== false ) { + url = url.replace( jsre, replace ); + if ( s.url === url ) { + if ( dataIsString ) { + data = data.replace( jsre, replace ); + } + if ( s.data === data ) { + // Add callback manually + url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback; + } + } + } + + s.url = url; + s.data = data; + + window[ jsonpCallback ] = function( response ) { + responseContainer = [ response ]; + }; + + s.complete = [ function() { + + // Set callback back to previous value + window[ jsonpCallback ] = previous; + + // Call if it was a function and we have a response + if ( previous) { + if ( responseContainer && jQuery.isFunction( previous ) ) { + window[ jsonpCallback ] ( responseContainer[ 0 ] ); + } + } else { + // else, more memory leak avoidance + try{ + delete window[ jsonpCallback ]; + } catch( e ) {} + } + + }, s.complete ]; + + // Use data converter to retrieve json after script execution + s.converters["script json"] = function() { + if ( ! responseContainer ) { + jQuery.error( jsonpCallback + " was not called" ); + } + return responseContainer[ 0 ]; + }; + + // force json dataType + s.dataTypes[ 0 ] = "json"; + + // Delegate to script + return "script"; + } +} ); + + + + +// Install script dataType +jQuery.ajaxSetup({ + accepts: { + script: "text/javascript, application/javascript" + }, + contents: { + script: /javascript/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +}); + +// Handle cache's special case and global +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + s.global = false; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function(s) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + + var script, + head = document.getElementsByTagName( "head" )[ 0 ] || document.documentElement; + + return { + + send: function( _, callback ) { + + script = document.createElement( "script" ); + + script.async = "async"; + + if ( s.scriptCharset ) { + script.charset = s.scriptCharset; + } + + script.src = s.url; + + // Attach handlers for all browsers + script.onload = script.onreadystatechange = function( _, isAbort ) { + + if ( !script.readyState || /loaded|complete/.test( script.readyState ) ) { + + // Handle memory leak in IE + script.onload = script.onreadystatechange = null; + + // Remove the script + if ( head && script.parentNode ) { + head.removeChild( script ); + } + + // Dereference the script + script = undefined; + + // Callback if not abort + if ( !isAbort ) { + callback( 200, "success" ); + } + } + }; + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709 and #4378). + head.insertBefore( script, head.firstChild ); + }, + + abort: function() { + if ( script ) { + script.onload( 0, 1 ); + } + } + }; + } +} ); + + + + +var // Next active xhr id + xhrId = jQuery.now(), + + // active xhrs + xhrs = {}, + + // #5280: see below + xhrUnloadAbortInstalled, + + // XHR used to determine supports properties + testXHR; + +// Create the request object +// (This is still attached to ajaxSettings for backward compatibility) +jQuery.ajaxSettings.xhr = window.ActiveXObject ? + /* Microsoft failed to properly + * implement the XMLHttpRequest in IE7 (can't request local files), + * so we use the ActiveXObject when it is available + * Additionally XMLHttpRequest can be disabled in IE7/IE8 so + * we need a fallback. + */ + function() { + if ( window.location.protocol !== "file:" ) { + try { + return new window.XMLHttpRequest(); + } catch( xhrError ) {} + } + + try { + return new window.ActiveXObject("Microsoft.XMLHTTP"); + } catch( activeError ) {} + } : + // For all other browsers, use the standard XMLHttpRequest object + function() { + return new window.XMLHttpRequest(); + }; + +// Test if we can create an xhr object +try { + testXHR = jQuery.ajaxSettings.xhr(); +} catch( xhrCreationException ) {} + +//Does this browser support XHR requests? +jQuery.support.ajax = !!testXHR; + +// Does this browser support crossDomain XHR requests +jQuery.support.cors = testXHR && ( "withCredentials" in testXHR ); + +// No need for the temporary xhr anymore +testXHR = undefined; + +// Create transport if the browser can provide an xhr +if ( jQuery.support.ajax ) { + + jQuery.ajaxTransport(function( s ) { + // Cross domain only allowed if supported through XMLHttpRequest + if ( !s.crossDomain || jQuery.support.cors ) { + + var callback; + + return { + send: function( headers, complete ) { + + // #5280: we need to abort on unload or IE will keep connections alive + if ( !xhrUnloadAbortInstalled ) { + + xhrUnloadAbortInstalled = 1; + + jQuery(window).bind( "unload", function() { + + // Abort all pending requests + jQuery.each( xhrs, function( _, xhr ) { + if ( xhr.onreadystatechange ) { + xhr.onreadystatechange( 1 ); + } + } ); + + } ); + } + + // Get a new xhr + var xhr = s.xhr(), + handle; + + // Open the socket + // Passing null username, generates a login popup on Opera (#2865) + if ( s.username ) { + xhr.open( s.type, s.url, s.async, s.username, s.password ); + } else { + xhr.open( s.type, s.url, s.async ); + } + + // Requested-With header + // Not set for crossDomain requests with no content + // (see why at http://trac.dojotoolkit.org/ticket/9486) + // Won't change header if already provided + if ( !( s.crossDomain && !s.hasContent ) && !headers["x-requested-with"] ) { + headers[ "x-requested-with" ] = "XMLHttpRequest"; + } + + // Need an extra try/catch for cross domain requests in Firefox 3 + try { + jQuery.each( headers, function( key, value ) { + xhr.setRequestHeader( key, value ); + } ); + } catch( _ ) {} + + // Do send the request + // This may raise an exception which is actually + // handled in jQuery.ajax (so no try/catch here) + xhr.send( ( s.hasContent && s.data ) || null ); + + // Listener + callback = function( _, isAbort ) { + + // Was never called and is aborted or complete + if ( callback && ( isAbort || xhr.readyState === 4 ) ) { + + // Only called once + callback = 0; + + // Do not keep as active anymore + if ( handle ) { + xhr.onreadystatechange = jQuery.noop; + delete xhrs[ handle ]; + } + + // If it's an abort + if ( isAbort ) { + // Abort it manually if needed + if ( xhr.readyState !== 4 ) { + xhr.abort(); + } + } else { + // Get info + var status = xhr.status, + statusText, + responseHeaders = xhr.getAllResponseHeaders(), + responses = {}, + xml = xhr.responseXML; + + // Construct response list + if ( xml && xml.documentElement /* #4958 */ ) { + responses.xml = xml; + } + responses.text = xhr.responseText; + + // Firefox throws an exception when accessing + // statusText for faulty cross-domain requests + try { + statusText = xhr.statusText; + } catch( e ) { + // We normalize with Webkit giving an empty statusText + statusText = ""; + } + + // Filter status for non standard behaviours + status = + // Opera returns 0 when it should be 304 + // Webkit returns 0 for failing cross-domain no matter the real status + status === 0 ? + ( + // Webkit, Firefox: filter out faulty cross-domain requests + !s.crossDomain || statusText ? + ( + // Opera: filter out real aborts #6060 + responseHeaders ? + 304 : + 0 + ) : + // We assume 302 but could be anything cross-domain related + 302 + ) : + ( + // IE sometimes returns 1223 when it should be 204 (see #1450) + status == 1223 ? + 204 : + status + ); + + // Call complete + complete( status, statusText, responses, responseHeaders ); + } + } + }; + + // if we're in sync mode or it's in cache + // and has been retrieved directly (IE6 & IE7) + // we need to manually fire the callback + if ( !s.async || xhr.readyState === 4 ) { + callback(); + } else { + // Add to list of active xhrs + handle = xhrId++; + xhrs[ handle ] = xhr; + xhr.onreadystatechange = callback; + } + }, + + abort: function() { + if ( callback ) { + callback(0,1); + } + } + }; + } + }); +} + + + + +var elemdisplay = {}, + rfxtypes = /^(?:toggle|show|hide)$/, + rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i, + timerId, + fxAttrs = [ + // height animations + [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], + // width animations + [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], + // opacity animations + [ "opacity" ] + ]; + +jQuery.fn.extend({ + show: function( speed, easing, callback ) { + var elem, display; + + if ( speed || speed === 0 ) { + return this.animate( genFx("show", 3), speed, easing, callback); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + elem = this[i]; + display = elem.style.display; + + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !jQuery._data(elem, "olddisplay") && display === "none" ) { + display = elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( display === "" && jQuery.css( elem, "display" ) === "none" ) { + jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName)); + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + elem = this[i]; + display = elem.style.display; + + if ( display === "" || display === "none" ) { + elem.style.display = jQuery._data(elem, "olddisplay") || ""; + } + } + + return this; + } + }, + + hide: function( speed, easing, callback ) { + if ( speed || speed === 0 ) { + return this.animate( genFx("hide", 3), speed, easing, callback); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + var display = jQuery.css( this[i], "display" ); + + if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) { + jQuery._data( this[i], "olddisplay", display ); + } + } + + // Set the display of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + this[i].style.display = "none"; + } + + return this; + } + }, + + // Save the old toggle function + _toggle: jQuery.fn.toggle, + + toggle: function( fn, fn2, callback ) { + var bool = typeof fn === "boolean"; + + if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { + this._toggle.apply( this, arguments ); + + } else if ( fn == null || bool ) { + this.each(function() { + var state = bool ? fn : jQuery(this).is(":hidden"); + jQuery(this)[ state ? "show" : "hide" ](); + }); + + } else { + this.animate(genFx("toggle", 3), fn, fn2, callback); + } + + return this; + }, + + fadeTo: function( speed, to, easing, callback ) { + return this.filter(":hidden").css("opacity", 0).show().end() + .animate({opacity: to}, speed, easing, callback); + }, + + animate: function( prop, speed, easing, callback ) { + var optall = jQuery.speed(speed, easing, callback); + + if ( jQuery.isEmptyObject( prop ) ) { + return this.each( optall.complete ); + } + + return this[ optall.queue === false ? "each" : "queue" ](function() { + // XXX 'this' does not always have a nodeName when running the + // test suite + + var opt = jQuery.extend({}, optall), p, + isElement = this.nodeType === 1, + hidden = isElement && jQuery(this).is(":hidden"), + self = this; + + for ( p in prop ) { + var name = jQuery.camelCase( p ); + + if ( p !== name ) { + prop[ name ] = prop[ p ]; + delete prop[ p ]; + p = name; + } + + if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) { + return opt.complete.call(this); + } + + if ( isElement && ( p === "height" || p === "width" ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE does not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height + // animated + if ( jQuery.css( this, "display" ) === "inline" && + jQuery.css( this, "float" ) === "none" ) { + if ( !jQuery.support.inlineBlockNeedsLayout ) { + this.style.display = "inline-block"; + + } else { + var display = defaultDisplay(this.nodeName); + + // inline-level elements accept inline-block; + // block-level elements need to be inline with layout + if ( display === "inline" ) { + this.style.display = "inline-block"; + + } else { + this.style.display = "inline"; + this.style.zoom = 1; + } + } + } + } + + if ( jQuery.isArray( prop[p] ) ) { + // Create (if needed) and add to specialEasing + (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1]; + prop[p] = prop[p][0]; + } + } + + if ( opt.overflow != null ) { + this.style.overflow = "hidden"; + } + + opt.curAnim = jQuery.extend({}, prop); + + jQuery.each( prop, function( name, val ) { + var e = new jQuery.fx( self, opt, name ); + + if ( rfxtypes.test(val) ) { + e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop ); + + } else { + var parts = rfxnum.exec(val), + start = e.cur() || 0; + + if ( parts ) { + var end = parseFloat( parts[2] ), + unit = parts[3] || "px"; + + // We need to compute starting value + if ( unit !== "px" ) { + jQuery.style( self, name, (end || 1) + unit); + start = ((end || 1) / e.cur()) * start; + jQuery.style( self, name, start + unit); + } + + // If a +=/-= token was provided, we're doing a relative animation + if ( parts[1] ) { + end = ((parts[1] === "-=" ? -1 : 1) * end) + start; + } + + e.custom( start, end, unit ); + + } else { + e.custom( start, val, "" ); + } + } + }); + + // For JS strict compliance + return true; + }); + }, + + stop: function( clearQueue, gotoEnd ) { + var timers = jQuery.timers; + + if ( clearQueue ) { + this.queue([]); + } + + this.each(function() { + // go in reverse order so anything added to the queue during the loop is ignored + for ( var i = timers.length - 1; i >= 0; i-- ) { + if ( timers[i].elem === this ) { + if (gotoEnd) { + // force the next step to be the last + timers[i](true); + } + + timers.splice(i, 1); + } + } + }); + + // start the next in the queue if the last step wasn't forced + if ( !gotoEnd ) { + this.dequeue(); + } + + return this; + } + +}); + +function genFx( type, num ) { + var obj = {}; + + jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() { + obj[ this ] = type; + }); + + return obj; +} + +// Generate shortcuts for custom animations +jQuery.each({ + slideDown: genFx("show", 1), + slideUp: genFx("hide", 1), + slideToggle: genFx("toggle", 1), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +}); + +jQuery.extend({ + speed: function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction(easing) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default; + + // Queueing + opt.old = opt.complete; + opt.complete = function() { + if ( opt.queue !== false ) { + jQuery(this).dequeue(); + } + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + }; + + return opt; + }, + + easing: { + linear: function( p, n, firstNum, diff ) { + return firstNum + diff * p; + }, + swing: function( p, n, firstNum, diff ) { + return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; + } + }, + + timers: [], + + fx: function( elem, options, prop ) { + this.options = options; + this.elem = elem; + this.prop = prop; + + if ( !options.orig ) { + options.orig = {}; + } + } + +}); + +jQuery.fx.prototype = { + // Simple function for setting a style value + update: function() { + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); + }, + + // Get the current size + cur: function() { + if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) { + return this.elem[ this.prop ]; + } + + var r = parseFloat( jQuery.css( this.elem, this.prop ) ); + return r || 0; + }, + + // Start an animation from one number to another + custom: function( from, to, unit ) { + var self = this, + fx = jQuery.fx; + + this.startTime = jQuery.now(); + this.start = from; + this.end = to; + this.unit = unit || this.unit || "px"; + this.now = this.start; + this.pos = this.state = 0; + + function t( gotoEnd ) { + return self.step(gotoEnd); + } + + t.elem = this.elem; + + if ( t() && jQuery.timers.push(t) && !timerId ) { + timerId = setInterval(fx.tick, fx.interval); + } + }, + + // Simple 'show' function + show: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); + this.options.show = true; + + // Begin the animation + // Make sure that we start at a small width/height to avoid any + // flash of content + this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur()); + + // Start by showing the element + jQuery( this.elem ).show(); + }, + + // Simple 'hide' function + hide: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); + this.options.hide = true; + + // Begin the animation + this.custom(this.cur(), 0); + }, + + // Each step of an animation + step: function( gotoEnd ) { + var t = jQuery.now(), done = true; + + if ( gotoEnd || t >= this.options.duration + this.startTime ) { + this.now = this.end; + this.pos = this.state = 1; + this.update(); + + this.options.curAnim[ this.prop ] = true; + + for ( var i in this.options.curAnim ) { + if ( this.options.curAnim[i] !== true ) { + done = false; + } + } + + if ( done ) { + // Reset the overflow + if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) { + var elem = this.elem, + options = this.options; + + jQuery.each( [ "", "X", "Y" ], function (index, value) { + elem.style[ "overflow" + value ] = options.overflow[index]; + } ); + } + + // Hide the element if the "hide" operation was done + if ( this.options.hide ) { + jQuery(this.elem).hide(); + } + + // Reset the properties, if the item has been hidden or shown + if ( this.options.hide || this.options.show ) { + for ( var p in this.options.curAnim ) { + jQuery.style( this.elem, p, this.options.orig[p] ); + } + } + + // Execute the complete function + this.options.complete.call( this.elem ); + } + + return false; + + } else { + var n = t - this.startTime; + this.state = n / this.options.duration; + + // Perform the easing function, defaults to swing + var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop]; + var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear"); + this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration); + this.now = this.start + ((this.end - this.start) * this.pos); + + // Perform the next step of the animation + this.update(); + } + + return true; + } +}; + +jQuery.extend( jQuery.fx, { + tick: function() { + var timers = jQuery.timers; + + for ( var i = 0; i < timers.length; i++ ) { + if ( !timers[i]() ) { + timers.splice(i--, 1); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + }, + + interval: 13, + + stop: function() { + clearInterval( timerId ); + timerId = null; + }, + + speeds: { + slow: 600, + fast: 200, + // Default speed + _default: 400 + }, + + step: { + opacity: function( fx ) { + jQuery.style( fx.elem, "opacity", fx.now ); + }, + + _default: function( fx ) { + if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) { + fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit; + } else { + fx.elem[ fx.prop ] = fx.now; + } + } + } +}); + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.animated = function( elem ) { + return jQuery.grep(jQuery.timers, function( fn ) { + return elem === fn.elem; + }).length; + }; +} + +function defaultDisplay( nodeName ) { + if ( !elemdisplay[ nodeName ] ) { + var elem = jQuery("<" + nodeName + ">").appendTo("body"), + display = elem.css("display"); + + elem.remove(); + + if ( display === "none" || display === "" ) { + display = "block"; + } + + elemdisplay[ nodeName ] = display; + } + + return elemdisplay[ nodeName ]; +} + + + + +var rtable = /^t(?:able|d|h)$/i, + rroot = /^(?:body|html)$/i; + +if ( "getBoundingClientRect" in document.documentElement ) { + jQuery.fn.offset = function( options ) { + var elem = this[0], box; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + try { + box = elem.getBoundingClientRect(); + } catch(e) {} + + var doc = elem.ownerDocument, + docElem = doc.documentElement; + + // Make sure we're not dealing with a disconnected DOM node + if ( !box || !jQuery.contains( docElem, elem ) ) { + return box ? { top: box.top, left: box.left } : { top: 0, left: 0 }; + } + + var body = doc.body, + win = getWindow(doc), + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ), + scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft), + top = box.top + scrollTop - clientTop, + left = box.left + scrollLeft - clientLeft; + + return { top: top, left: left }; + }; + +} else { + jQuery.fn.offset = function( options ) { + var elem = this[0]; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + jQuery.offset.initialize(); + + var computedStyle, + offsetParent = elem.offsetParent, + prevOffsetParent = elem, + doc = elem.ownerDocument, + docElem = doc.documentElement, + body = doc.body, + defaultView = doc.defaultView, + prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle, + top = elem.offsetTop, + left = elem.offsetLeft; + + while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { + if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { + break; + } + + computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle; + top -= elem.scrollTop; + left -= elem.scrollLeft; + + if ( elem === offsetParent ) { + top += elem.offsetTop; + left += elem.offsetLeft; + + if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevOffsetParent = offsetParent; + offsetParent = elem.offsetParent; + } + + if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevComputedStyle = computedStyle; + } + + if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) { + top += body.offsetTop; + left += body.offsetLeft; + } + + if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { + top += Math.max( docElem.scrollTop, body.scrollTop ); + left += Math.max( docElem.scrollLeft, body.scrollLeft ); + } + + return { top: top, left: left }; + }; +} + +jQuery.offset = { + initialize: function() { + var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0, + html = "<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>"; + + jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } ); + + container.innerHTML = html; + body.insertBefore( container, body.firstChild ); + innerDiv = container.firstChild; + checkDiv = innerDiv.firstChild; + td = innerDiv.nextSibling.firstChild.firstChild; + + this.doesNotAddBorder = (checkDiv.offsetTop !== 5); + this.doesAddBorderForTableAndCells = (td.offsetTop === 5); + + checkDiv.style.position = "fixed"; + checkDiv.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15); + checkDiv.style.position = checkDiv.style.top = ""; + + innerDiv.style.overflow = "hidden"; + innerDiv.style.position = "relative"; + + this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5); + + this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); + + body.removeChild( container ); + body = container = innerDiv = checkDiv = table = td = null; + jQuery.offset.initialize = jQuery.noop; + }, + + bodyOffset: function( body ) { + var top = body.offsetTop, + left = body.offsetLeft; + + jQuery.offset.initialize(); + + if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) { + top += parseFloat( jQuery.css(body, "marginTop") ) || 0; + left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; + } + + return { top: top, left: left }; + }, + + setOffset: function( elem, options, i ) { + var position = jQuery.css( elem, "position" ); + + // set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + var curElem = jQuery( elem ), + curOffset = curElem.offset(), + curCSSTop = jQuery.css( elem, "top" ), + curCSSLeft = jQuery.css( elem, "left" ), + calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1), + props = {}, curPosition = {}, curTop, curLeft; + + // need to be able to calculate position if either top or left is auto and position is absolute + if ( calculatePosition ) { + curPosition = curElem.position(); + } + + curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0; + curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0; + + if ( jQuery.isFunction( options ) ) { + options = options.call( elem, i, curOffset ); + } + + if (options.top != null) { + props.top = (options.top - curOffset.top) + curTop; + } + if (options.left != null) { + props.left = (options.left - curOffset.left) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + } +}; + + +jQuery.fn.extend({ + position: function() { + if ( !this[0] ) { + return null; + } + + var elem = this[0], + + // Get *real* offsetParent + offsetParent = this.offsetParent(), + + // Get correct offsets + offset = this.offset(), + parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + + // Subtract element margins + // note: when an element has margin: auto the offsetLeft and marginLeft + // are the same in Safari causing offset.left to incorrectly be 0 + offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; + offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; + + // Add offsetParent borders + parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; + parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; + + // Subtract the two offsets + return { + top: offset.top - parentOffset.top, + left: offset.left - parentOffset.left + }; + }, + + offsetParent: function() { + return this.map(function() { + var offsetParent = this.offsetParent || document.body; + while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent; + }); + } +}); + + +// Create scrollLeft and scrollTop methods +jQuery.each( ["Left", "Top"], function( i, name ) { + var method = "scroll" + name; + + jQuery.fn[ method ] = function(val) { + var elem = this[0], win; + + if ( !elem ) { + return null; + } + + if ( val !== undefined ) { + // Set the scroll offset + return this.each(function() { + win = getWindow( this ); + + if ( win ) { + win.scrollTo( + !i ? val : jQuery(win).scrollLeft(), + i ? val : jQuery(win).scrollTop() + ); + + } else { + this[ method ] = val; + } + }); + } else { + win = getWindow( elem ); + + // Return the scroll offset + return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + }; +}); + +function getWindow( elem ) { + return jQuery.isWindow( elem ) ? + elem : + elem.nodeType === 9 ? + elem.defaultView || elem.parentWindow : + false; +} + + + + +// Create innerHeight, innerWidth, outerHeight and outerWidth methods +jQuery.each([ "Height", "Width" ], function( i, name ) { + + var type = name.toLowerCase(); + + // innerHeight and innerWidth + jQuery.fn["inner" + name] = function() { + return this[0] ? + parseFloat( jQuery.css( this[0], type, "padding" ) ) : + null; + }; + + // outerHeight and outerWidth + jQuery.fn["outer" + name] = function( margin ) { + return this[0] ? + parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) : + null; + }; + + jQuery.fn[ type ] = function( size ) { + // Get window width or height + var elem = this[0]; + if ( !elem ) { + return size == null ? null : this; + } + + if ( jQuery.isFunction( size ) ) { + return this.each(function( i ) { + var self = jQuery( this ); + self[ type ]( size.call( this, i, self[ type ]() ) ); + }); + } + + if ( jQuery.isWindow( elem ) ) { + // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode + // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat + var docElemProp = elem.document.documentElement[ "client" + name ]; + return elem.document.compatMode === "CSS1Compat" && docElemProp || + elem.document.body[ "client" + name ] || docElemProp; + + // Get document width or height + } else if ( elem.nodeType === 9 ) { + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + return Math.max( + elem.documentElement["client" + name], + elem.body["scroll" + name], elem.documentElement["scroll" + name], + elem.body["offset" + name], elem.documentElement["offset" + name] + ); + + // Get or set width or height on the element + } else if ( size === undefined ) { + var orig = jQuery.css( elem, type ), + ret = parseFloat( orig ); + + return jQuery.isNaN( ret ) ? orig : ret; + + // Set the width or height on the element (default to pixels if value is unitless) + } else { + return this.css( type, typeof size === "string" ? size : size + "px" ); + } + }; + +}); + + +})(window); diff --git a/doc/s6/jquery.microsoft.js b/doc/s6/jquery.microsoft.js new file mode 100644 index 0000000..f85af8a --- /dev/null +++ b/doc/s6/jquery.microsoft.js @@ -0,0 +1,31 @@ + + +$(document).ready( function() { + + // 1) remove all content + $( 'body > *' ).remove(); + + // 2) show banner + $( "<div>" ).html( + "<p>" + + "Microsoft's Internet Explorer browser has no built-in vector graphics machinery " + + "required for 'loss-free' gradient background themes." + + "</p>" + + "<p>" + + "Please <span style='background: yellow'>upgrade to a better browser</span> " + + "such as <a href='http://getfirefox.com'>Firefox</a>, <a href='http://www.opera.com/download'>Opera</a>, " + + "<a href='http://google.com/chrome'>Chrome</a>, <a href='http://apple.com/safari/download'>Safari</a> or others " + + "with built-in vector graphics machinery and much more. " + + "(Learn more or post questions or comments " + + "at the <a href='http://slideshow.rubyforge.org'>Slide Show (S9)</a> project site. Thanks!)" + + "</p>" + ) + .css( { + border: 'red solid thick', + padding: '1em', + fontFamily: 'sans-serif', + fontWeight: 'bold' } ) + .prependTo( 'body' ); + } +); + diff --git a/doc/s6/jquery.slideshow.js b/doc/s6/jquery.slideshow.js new file mode 100644 index 0000000..6d6c560 --- /dev/null +++ b/doc/s6/jquery.slideshow.js @@ -0,0 +1,534 @@ +
+var Slideshow = {};
+
+
+/************************************
+ * lets you define your own "global" transition function
+ * passes in a reference to from and to slide wrapped in jQuery wrapper
+ */
+
+Slideshow.transition = function( $from, $to ) {
+ // $from.hide();
+ // $to.show();
+
+ $from.hide('fast');
+ $to.show('fast');
+}
+
+/***********************
+ * sample custom transition using scrollUp effect
+ * inspired by Karl Swedberg's Scroll Up Headline Reader jQuery Tutorial[1]
+ * [1] http://docs.jquery.com/Tutorials:Scroll_Up_Headline_Reader
+ */
+
+function transitionSlideUpSlideDown( $from, $to ) {
+ $from.slideUp( 500, function() { $to.slideDown( 1000 ); } );
+}
+
+function transitionFadeOutFadeIn( $from, $to ) {
+ $from.fadeOut( 500 );
+ $to.fadeIn( 500 );
+}
+
+function transitionScrollUp( $from, $to ) {
+ var cheight = $from.outerHeight();
+
+ // hide scrollbar during animation
+ $( 'body' ).css( 'overflow-y', 'hidden' );
+
+ $to.css( 'top', cheight+'px' );
+ $to.show();
+
+ $from.animate( {top: -cheight}, 'slow' );
+ $to.animate( {top: 0}, 'slow', function() {
+ $from.hide().css( 'top', '0px');
+
+ // restore possible scrollbar
+ $( 'body' ).css( 'overflow-y', 'auto' );
+ });
+}
+
+Slideshow.init = function( options ) {
+
+ var settings = $.extend({
+ mode : 'slideshow', // slideshow | outline | autoplay
+ projectionStyleId : '#styleProjection',
+ screenStyleId : '#styleScreen',
+ titleSelector : 'h1',
+ slideSelector : '.slide', // dummy (not yet working)
+ stepSelector : '.step', // dummy (not yet working)
+ debug : false,
+ change : null // todo: change to use a custom event and trigger
+ }, options || {});
+
+ settings.isProjection = true; // are we in projection (slideshow) mode (in contrast to screen (outline) mode)?
+ settings.snum = 1; // current slide # (non-zero based index e.g. starting with 1)
+ settings.smax = 1; // max number of slides
+ settings.incpos = 0; // current step in slide
+ settings.steps = null;
+ settings.autoplayInterval = null;
+
+ function debug( msg )
+ {
+ if( settings.debug && window.console && window.console.log )
+ window.console.log( '[debug] ' + msg );
+ }
+
+ function showHide( action )
+ {
+ var $navLinks = $( '#navLinks' )
+
+ switch( action ) {
+ case 's': $navLinks.css( 'visibility', 'visible' ); break;
+ case 'h': $navLinks.css( 'visibility', 'hidden' ); break;
+ case 'c': /* toggle control panel */
+ if( $navLinks.css( 'visibility' ) != 'visible' )
+ $navLinks.css( 'visibility', 'visible' );
+ else
+ $navLinks.css( 'visibility', 'hidden' );
+ break;
+ }
+ }
+
+ function updateCurrentSlideCounter()
+ {
+ $( '#currentSlide' ).html( settings.snum + '/' + settings.smax );
+ }
+
+ function updateJumpList()
+ {
+ $('#jumplist').get(0).selectedIndex = (settings.snum-1);
+ }
+
+ function updatePermaLink()
+ {
+ // todo: unify hash marks??; use #1 for div ids instead of #slide1?
+ window.location.hash = '#'+settings.snum;
+ }
+
+ function goTo( target )
+ {
+ if( target > settings.smax || target == settings.snum ) return;
+ go( target - settings.snum );
+ }
+
+ function go( dir )
+ {
+ debug( 'go: ' + dir );
+
+ if( dir == 0 ) return; /* same slide; nothing to do */
+
+ var cid = '#slide' + settings.snum; /* current slide (selector) id */
+ var csteps = settings.steps[settings.snum-1]; /* current slide steps array */
+
+ /* remove all step and stepcurrent classes from current slide */
+ if( csteps.length > 0) {
+ $( csteps ).each( function() {
+ $(this).removeClass( 'step' ).removeClass( 'stepcurrent' );
+ } );
+ }
+
+ /* set snum to next slide */
+ settings.snum += dir;
+ if( settings.snum > settings.smax ) settings.snum = settings.smax;
+ if( settings.snum < 1 ) settings.snum = 1;
+
+ var nid = '#slide' + settings.snum; /* next slide (selector) id */
+ var nsteps = settings.steps[settings.snum-1]; /* next slide steps array */
+
+ if( dir < 0 ) /* go backwards? */
+ {
+ settings.incpos = nsteps.length;
+ /* mark last step as current step */
+ if( nsteps.length > 0 )
+ $( nsteps[settings.incpos-1] ).addClass( 'stepcurrent' );
+ }
+ else /* go forwards? */
+ {
+ settings.incpos = 0;
+ if( nsteps.length > 0 ) {
+ $( nsteps ).each( function() {
+ $(this).addClass( 'step' ).removeClass( 'stepcurrent' );
+ } );
+ }
+ }
+
+ if( !(cid == nid) ) {
+ debug( "transition from " + cid + " to " + nid );
+ Slideshow.transition( $( cid ), $( nid ) );
+ }
+
+ updateJumpList();
+ updateCurrentSlideCounter();
+ updatePermaLink();
+
+ if (settings.change) { settings.change(); }
+}
+
+ function subgo( dir )
+ {
+ debug( 'subgo: ' + dir + ', incpos before: ' + settings.incpos + ', after: ' + (settings.incpos+dir) );
+
+ var csteps = settings.steps[settings.snum-1]; /* current slide steps array */
+
+ if( dir > 0)
+ { /* go forward? */
+ if( settings.incpos > 0 )
+ $( csteps[settings.incpos-1] ).removeClass( 'stepcurrent' );
+ $( csteps[settings.incpos] ).removeClass( 'step').addClass( 'stepcurrent' );
+ settings.incpos++;
+ }
+ else
+ { /* go backwards? */
+ settings.incpos--;
+ $( csteps[settings.incpos] ).removeClass( 'stepcurrent' ).addClass( 'step' );
+ if( settings.incpos > 0 )
+ $( csteps[settings.incpos-1] ).addClass( 'stepcurrent' );
+ }
+}
+
+
+function notOperaFix()
+{
+ $( settings.projectionStyleId ).attr( 'media','screen' );
+
+ var styleScreen = $( settings.screenStyleId ).get(0);
+ styleScreen.disabled = true;
+}
+
+
+function toggle()
+{
+ // toggle between projection (slide show) mode
+ // and screen (outline) mode
+
+ // get stylesheets
+ var styleProjection = $( settings.projectionStyleId ).get(0);
+ var styleScreen = $( settings.screenStyleId ).get(0);
+
+ if( !styleProjection.disabled )
+ {
+ styleProjection.disabled = true;
+ styleScreen.disabled = false;
+ settings.isProjection = false;
+ $('.slide').each( function() { $(this).show(); } );
+ }
+ else
+ {
+ styleProjection.disabled = false;
+ styleScreen.disabled = true;
+ settings.isProjection = true;
+ $('.slide').each( function(i) {
+ if( i == (settings.snum-1) )
+ $(this).show();
+ else
+ $(this).hide();
+ });
+ }
+}
+
+ function populateJumpList() {
+
+ var list = $('#jumplist').get(0);
+
+ $( '.slide' ).each( function(i) {
+ var text = $(this).find( settings.titleSelector ).text();
+ list.options[list.length] = new Option( (i+1)+' : '+ text, (i+1) );
+ });
+ }
+
+ function createControls()
+ {
+ // todo: make layout into an id (not class?)
+ // do we need or allow more than one element?
+
+
+ // if no div.layout exists, create one
+ if( $( '.layout' ).length == 0 )
+ $( "<div class='layout'></div>").appendTo( 'body' );
+
+ $( '.layout' )
+ .append( "<div id='controls'>" )
+ .append( "<div id='currentSlide'>" );
+
+ var $controls = $( '#controls' )
+
+ $controls.html( '<div id="navLinks">'
+ + '<a accesskey="t" id="toggle" href="#">Ø<\/a>'
+ + '<a accesskey="z" id="prev" href="#">«<\/a>'
+ + '<a accesskey="x" id="next" href="#">»<\/a>'
+ + '<div id="navList"><select id="jumplist" /><\/div>'
+ + '<\/div>' );
+
+ $controls.hover( function() { showHide('s') }, function() { showHide('h') });
+ $('#toggle').click( function() { toggle(); } );
+ $('#prev').click( function() { go(-1); } );
+ $('#next').click( function() { go(1); } );
+
+ $('#jumplist').change( function() { goTo( parseInt( $( '#jumplist' ).val() )); } );
+
+ populateJumpList();
+ updateCurrentSlideCounter();
+ updatePermaLink();
+ }
+
+ function toggleSlideNumber()
+ {
+ // toggle slide number/counter
+ $( '#currentSlide' ).toggle();
+ }
+
+ function toggleFooter()
+ {
+ $( '#footer').toggle();
+ }
+
+
+ function keys(key)
+ {
+ if (!key) {
+ key = event;
+ key.which = key.keyCode;
+ }
+ if (key.which == 84) {
+ toggle(); // toggle between project and screen css media mode
+ return;
+ }
+ if( settings.isProjection ) {
+ switch (key.which) {
+ case 32: // spacebar
+ case 34: // page down
+ case 39: // rightkey
+ case 40: // downkey
+
+ var csteps = settings.steps[settings.snum-1]; /* current slide steps array */
+
+ if ( !csteps || settings.incpos >= csteps.length ) {
+ go(1);
+ } else {
+ subgo(1);
+ }
+ break;
+ case 33: // page up
+ case 37: // leftkey
+ case 38: // upkey
+
+ if( !settings.steps[settings.snum-1] || settings.incpos <= 0 ) {
+ go(-1);
+ } else {
+ subgo(-1);
+ }
+ break;
+ case 36: // home
+ goTo(1);
+ break;
+ case 35: // end
+ goTo(settings.smax);
+ break;
+ case 67: // c
+ showHide('c'); // toggle controls (navlinks,navlist)
+ break;
+ case 65: //a
+ case 80: //p
+ case 83: //s
+ toggleAutoplay();
+ break;
+ case 70: //f
+ toggleFooter();
+ break;
+ case 78: // n
+ toggleSlideNumber();
+ break;
+ case 68: // d
+ toggleDebug();
+ break;
+ }
+ }
+}
+
+function autoplay()
+{
+ // suspend autoplay in outline view (just slideshow view)
+ if( !settings.isProjection )
+ return;
+
+ // next slide/step, please
+ var csteps = settings.steps[settings.snum-1]; // current slide steps array
+ if( !csteps || settings.incpos >= csteps.length ) {
+ if( settings.snum >= settings.smax )
+ goTo( 1 ); // reached end of show? start with 1st slide again (for endless cycle)
+ else
+ go(1);
+ }
+ else {
+ subgo(1);
+ }
+}
+
+function toggleDebug()
+{
+ settings.debug = !settings.debug;
+ doDebug();
+}
+
+function doDebug()
+{
+ // fix/todo: save background into oldbackground
+ // so we can restore later
+
+ if( settings.debug == true )
+ {
+ $( '#header' ).css( 'background', '#FCC' );
+ $( '#footer' ).css( 'background', '#CCF' );
+ $( '#controls' ).css( 'background', '#BBD' );
+ $( '#currentSlide' ).css( 'background', '#FFC' );
+ }
+ else
+ {
+ $( '#header' ).css( 'background', 'transparent' );
+ $( '#footer' ).css( 'background', 'transparent' );
+ $( '#controls' ).css( 'background', 'transparent' );
+ $( '#currentSlide' ).css( 'background', 'transparent' );
+ }
+}
+
+
+function toggleAutoplay()
+{
+ if( settings.autoplayInterval )
+ {
+ clearInterval( settings.autoplayInterval );
+ settings.autoplayInterval = null;
+ }
+ else
+ {
+ settings.autoplayInterval = setInterval ( autoplay, 2000 );
+ }
+}
+
+
+
+function collectStepsWorker(obj) {
+
+ var steps = new Array();
+ if( !obj )
+ return steps;
+
+ $(obj).children().each( function() {
+ if( $(this).hasClass( 'step' ) ) {
+
+ debug( 'step found for ' + this.tagName );
+ $(this).removeClass( 'step' );
+
+ /* don't add enclosing list; instead add step class to all list items/children */
+ if( $(this).is( 'ol,ul' ) ) {
+ debug( ' ol or ul found; adding auto steps' );
+ $(this).children().addClass( 'step' );
+ }
+ else
+ {
+ steps.push( this )
+ }
+ }
+
+ steps = steps.concat( collectStepsWorker(this) );
+ });
+
+ return steps;
+}
+
+function collectSteps() {
+
+ var steps = new Array();
+
+ $slides.each( function(i) {
+ debug ( 'collectSteps for ' + this.id + ':' );
+ steps[i] = collectStepsWorker( this );
+ });
+
+ $( steps ).each( function(i) {
+ debug( 'slide ' + (i+1) + ': found ' + this.length + ' steps' );
+ });
+
+ return steps;
+}
+
+
+function addClicker() {
+ // if you click on heading of slide -> go to next slide (or next step)
+
+ $( settings.titleSelector, $slides ).click( function( ev ) {
+ if(ev.which != 1) return; // only process left clicks (e.g 1; middle and rightclick use 2 and 3)
+
+ if( !settings.isProjection ) // suspend clicker in outline view (just slideshow view)
+ return;
+
+ var csteps = settings.steps[settings.snum-1]; // current slide steps array
+ if ( !csteps || settings.incpos >= csteps.length )
+ go(1);
+ else
+ subgo(1);
+ } );
+
+
+ $( settings.titleSelector, $slides ).bind('contextmenu', function() {
+ if( !settings.isProjection ) // suspend clicker in outline view (just slideshow view)
+ return;
+
+ var csteps = settings.steps[settings.snum-1]; // current slide steps array
+ if ( !csteps || settings.incpos >= csteps.length )
+ go(-1);
+ else
+ subgo(-1);
+
+ return false;
+ } );
+}
+
+function addSlideIds() {
+ $slides.each( function(i) {
+ this.id = 'slide'+(i+1);
+ });
+ }
+
+ // init code here
+
+ // store possible slidenumber from hash */
+ // todo: use regex to extract number
+ // might be #slide1 or just #1
+
+ var gotoSlideNum = parseInt( window.location.hash.substring(1) );
+ debug( "gotoSlideNum=" + gotoSlideNum );
+
+ var $slides = $( '.slide' );
+ settings.smax = $slides.length;
+
+ addSlideIds();
+ settings.steps = collectSteps();
+
+ createControls();
+
+ addClicker();
+
+ /* opera is the only browser currently supporting css projection mode */
+ /* if( !$.browser.opera ) */
+ notOperaFix();
+
+ if( !isNaN( gotoSlideNum ))
+ {
+ debug( "restoring slide on (re)load #: " + gotoSlideNum );
+ goTo( gotoSlideNum );
+ }
+
+ if( settings.mode == 'outline' )
+ toggle();
+ else if( settings.mode == 'autoplay' )
+ toggleAutoplay();
+
+
+ if( settings.debug == true )
+ doDebug();
+
+ document.onkeyup = keys;
+
+} // end Slideshow
diff --git a/doc/s6/print.css b/doc/s6/print.css new file mode 100644 index 0000000..91acb88 --- /dev/null +++ b/doc/s6/print.css @@ -0,0 +1 @@ +/*********************************
* CSS @media print rules (not projection or screen)
*/
/*************
* Make sure all slides are visible (to make them all appear in prin)
*/
.slide { page-break-inside: avoid;
display: block !important;
}
h1 { page-break-after: avoid; }
ul { page-break-inside: avoid; }
body { font-size: 12pt; }
/********************
* Extra styling for first slide (title slide)
*/
#slide1 h1 { font-size: 200%; border: none; margin: 0.5em 0 0.25em; }
#slide1 h3 { margin: 0; padding: 0;}
#slide1 h4 { margin: 0 0 0.5em; padding: 0;}
#slide1 { margin-bottom: 3em; }
h1 { border-top: 2pt solid gray;
border-bottom: 1px dotted silver;
}
/******
* Turn on print-specific stuff/classes
*/
.extra { background: transparent !important; }
div.extra, pre.extra, .example { font-size: 10pt; color: #333; }
ul.extra a { font-weight: bold; }
/*****
* Turn off online (screen/projection)-specific stuff/classes
*/
p.example { display: none; }
/*****************
* The following rule keeps the layout stuff out of print.
* Remove at your own risk!
*/
.layout,
.layout * {display: none !important;}
.projection { display: none; }
\ No newline at end of file diff --git a/doc/s6/projection.css b/doc/s6/projection.css new file mode 100644 index 0000000..5624b65 --- /dev/null +++ b/doc/s6/projection.css @@ -0,0 +1,109 @@ +/********************************* + * CSS @media projection rules (not print or screen) + * + * 1) projection -> slideshow mode (display one slide at-a-time; hide all others) + * 2) screen -> outline mode (display all slides-at-once on screen) + * 3) print -> print (and print preview) + * + * toogle between slideshow/outline mode using t-key + */ + +html, +body, +.presentation { margin: 0; padding: 0; } + + +.slide { display: none; + position: absolute; + top: 0; left: 0; + margin: 0; + padding: 2% 4% 0% 4%; /* css note: order is => top right bottom left */ + width: 92%; height: 95%; /* css note: to get to 100% add padding/border/margin */ + overflow-x: hidden; overflow-y: auto; + z-index: 2; + } + +#slide1 { display: block; } + +.notes { display: none; } /* handout notes/note (use note? handout? notes? */ + + +/********* format layout block + * + * .layout + * > #header + * > #footer + * > #controls (holding navigation controls) + * > #navLinks + * > #toggle + * > #navList + * > #jumplist + * > #currentSlide (e.g. 1/7) + * + */ + +.layout { display: block; } + +#header { position: fixed; + top: 0; left: 0; + width: 100%; height: 0.5em; + z-index: 1; + } + +#footer { position: fixed; + top: auto; bottom: 0; + padding: 1em 0; /* css note: order is => 1st top,bottom; 2nd right,left */ + width: 100%; height: 1em; + z-index: 5; + + /* todo: move font-size and font-style to blank.css */ + font-size: 100%; font-weight: bold; + } + +/* todo: move font-size and font-style to blank.css */ + + #footer h1 { display: block; margin: 0; padding: 0 1em; font-size: 0.5em; } + #footer h2 { display: block; margin: 0; padding: 0 1em; font-size: 0.5em; font-style: italic; } + + +/************************* + * format for navigation controls + */ + + +#controls { position: fixed; + left: 60%; bottom: 0; + width: 40%; + z-index: 100; + text-align: right; + font: bold 1.2em Verdana, Helvetica, sans-serif; + } + + #controls :focus { outline: 1px dotted white;} + + #controls #navLinks { text-align: right; margin: 0; visibility: hidden; } + + #controls #navLinks a { padding: 0; margin: 0 0.5em; cursor: pointer; border: none; } + + #controls #navLinks :link, + #controls #navLinks :visited {text-decoration: none; } + + #controls #navList #jumplist { background: white; color: black; } + +/************************* + * format for + * currentSlide block ( e.g. 2/20 ) + */ + +#currentSlide { position: fixed; + left: 45%; bottom: 1em; + width: 10%; + z-index: 10; + text-align: center; + font-size: 0.8em; + } + +#currentSlide :link, +#currentSlide :visited { text-decoration: none; } + + diff --git a/doc/s6/screen.css b/doc/s6/screen.css new file mode 100644 index 0000000..aa3fc21 --- /dev/null +++ b/doc/s6/screen.css @@ -0,0 +1,50 @@ +/********************************* + * CSS @media screen (not projection or print) + * + * 1) projection -> slideshow mode (display one slide at-a-time; hide all others) + * 2) screen -> outline mode (display all slides-at-once on screen) + * 3) print -> print (and print preview) + * + * toogle between slideshow/outline mode using t-key + */ + + +/**** + * hide layout stuff (header, footer, navLinks, navList etc.) + */ + +.layout * { display: none; } + +.projection { display: none; } + +/************* + * make toggle button visible and reposition to upper right corner * + * note: toogle button is nested inside #controls > #navLinks > #toogle + */ + +#controls, +#navLinks, +#toggle { display: block; + visibility: visible; + margin: 0; padding: 0; + } + +#toggle { position: fixed; + top: 0; right: 0; + padding: 0.5em; + border-left: 1px solid; + border-bottom: 1px solid; + background: white; + } + + +/************* + * making the outline look pretty-ish + */ + +#slide1, #slide1 h1, #slide1 h2, #slide1 h3, #slide1 h4 {border: none; margin: 0;} +#slide1 h1 {padding-top: 1.5em;} + +.slide { margin: 1.5em 0 0; border-top: 1px solid #888; } +.slide h1 { border-bottom: 1px solid #AAA; } + diff --git a/doc/ui/default/blank.gif b/doc/ui/default/blank.gif Binary files differnew file mode 100644 index 0000000..75b945d --- /dev/null +++ b/doc/ui/default/blank.gif diff --git a/doc/ui/default/bodybg.gif b/doc/ui/default/bodybg.gif Binary files differnew file mode 100644 index 0000000..5f448a1 --- /dev/null +++ b/doc/ui/default/bodybg.gif diff --git a/doc/ui/default/framing.css b/doc/ui/default/framing.css new file mode 100644 index 0000000..14d8509 --- /dev/null +++ b/doc/ui/default/framing.css @@ -0,0 +1,23 @@ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; + margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ diff --git a/doc/ui/default/iepngfix.htc b/doc/ui/default/iepngfix.htc new file mode 100644 index 0000000..bba2db7 --- /dev/null +++ b/doc/ui/default/iepngfix.htc @@ -0,0 +1,42 @@ +<public:component>
+<public:attach event="onpropertychange" onevent="doFix()" />
+
+<script>
+
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com
+// Free usage permitted as long as this notice remains intact.
+
+// This must be a path to a blank image. That's all the configuration you need here.
+var blankImg = 'ui/default/blank.gif';
+
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
+
+function filt(s, m) {
+ if (filters[f]) {
+ filters[f].enabled = s ? true : false;
+ if (s) with (filters[f]) { src = s; sizingMethod = m }
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
+}
+
+function doFix() {
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||
+ (event && !/(background|src)/.test(event.propertyName))) return;
+
+ if (tagName == 'IMG') {
+ if ((/\.png$/i).test(src)) {
+ filt(src, 'image'); // was 'scale'
+ src = blankImg;
+ } else if (src.indexOf(blankImg) < 0) filt();
+ } else if (style.backgroundImage) {
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {
+ var s = RegExp.$1;
+ style.backgroundImage = '';
+ filt(s, 'crop');
+ } else filt();
+ }
+}
+
+doFix();
+
+</script>
+</public:component>
\ No newline at end of file diff --git a/doc/ui/default/opera.css b/doc/ui/default/opera.css new file mode 100644 index 0000000..9e9d2a3 --- /dev/null +++ b/doc/ui/default/opera.css @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/doc/ui/default/outline.css b/doc/ui/default/outline.css new file mode 100644 index 0000000..62db519 --- /dev/null +++ b/doc/ui/default/outline.css @@ -0,0 +1,15 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} diff --git a/doc/ui/default/pretty.css b/doc/ui/default/pretty.css new file mode 100644 index 0000000..3d3acef --- /dev/null +++ b/doc/ui/default/pretty.css @@ -0,0 +1,86 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;} +:link, :visited {text-decoration: none; color: #00C;} +#controls :active {color: #88A !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {display: block;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #005; color: #AAB; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #DDE; background: #005;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 50%; bottom: 0; + width: 50%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0 0 1em 0; + top: auto;} +div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; + margin: 0; padding: 0;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #005; border: none; color: #779; + cursor: pointer;} +#controls #navList {height: 1em;} +#controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #449;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */
\ No newline at end of file diff --git a/doc/ui/default/print.css b/doc/ui/default/print.css new file mode 100644 index 0000000..e7a71d1 --- /dev/null +++ b/doc/ui/default/print.css @@ -0,0 +1 @@ +/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */
.slide, ul {page-break-inside: avoid; visibility: visible !important;}
h1 {page-break-after: avoid;}
body {font-size: 12pt; background: white;}
* {color: black;}
#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}
#slide0 h3 {margin: 0; padding: 0;}
#slide0 h4 {margin: 0 0 0.5em; padding: 0;}
#slide0 {margin-bottom: 3em;}
h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}
.extra {background: transparent !important;}
div.extra, pre.extra, .example {font-size: 10pt; color: #333;}
ul.extra a {font-weight: bold;}
p.example {display: none;}
#header {display: none;}
#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}
#footer h2, #controls {display: none;}
/* The following rule keeps the layout stuff out of print. Remove at your own risk! */
.layout, .layout * {display: none !important;}
\ No newline at end of file diff --git a/doc/ui/default/s5-core.css b/doc/ui/default/s5-core.css new file mode 100644 index 0000000..86444e0 --- /dev/null +++ b/doc/ui/default/s5-core.css @@ -0,0 +1,9 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} diff --git a/doc/ui/default/slides.css b/doc/ui/default/slides.css new file mode 100644 index 0000000..0786d7d --- /dev/null +++ b/doc/ui/default/slides.css @@ -0,0 +1,3 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */
\ No newline at end of file diff --git a/doc/ui/default/slides.js b/doc/ui/default/slides.js new file mode 100644 index 0000000..38fe853 --- /dev/null +++ b/doc/ui/default/slides.js @@ -0,0 +1,553 @@ +// S5 v1.1 slides.js -- released into the Public Domain +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + if (isOp) continue; + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>'; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + jl.selectedIndex = snum; + currentSlide(); + number = 0; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 22; // both yield 32 (after rounding) at 1024x768 + var hScale = 32; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!isIE) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!isIE) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('body','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function startup() { + defaultCheck(); + if (!isOp) + createControls(); + slideLabel(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) { + notOperaFix(); + incrementals = createIncrementals(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; + } +} + +window.onload = startup; +window.onresize = function(){setTimeout('fontScale()', 50);}
\ No newline at end of file |