Commit 81264c64 authored by John E. Vincent's avatar John E. Vincent

Updating README and working on documentation

parent d7eb709d
...@@ -11,4 +11,4 @@ tmp/* ...@@ -11,4 +11,4 @@ tmp/*
.bundle .bundle
warbler/* warbler/*
Gemfile.lock Gemfile.lock
Gemfile.lock doc
lib/noah.rb 269c31354e0a093534b6ab797495b550159d31e4
lib/noah/ark.rb da39a3ee5e6b4b0d3255bfef95601890afd80709
lib/noah/app.rb a6dd925f097aefef6d8dc39c2a26834ae31b2c11
lib/noah/hosts.rb b006e064b7ac812822f9372c50698541d2516f8d
lib/noah/models.rb 3131318013e90b57d973480127f8df323b9a2d73
lib/noah/version.rb fff0731d5b3ed195ea84b8568a1d436580d39687
lib/noah/helpers.rb d64ca090b4b6669b083c48eb7992b257438ea0d9
lib/noah/services.rb a0560ef81155dd845eb2e6a1969e5c5d31cf5a67
lib/noah/watchers.rb f6b78188e5479f49bf4241eb51dae6104ba082db
lib/noah/applications.rb 176e30deccd1444617b711ca4297b9edded36213
lib/noah/configurations.rb c0a086d67deb04e67e84a8210f1d19f1b8abd287
# Noah testing quickstart # Noah
(make sure redis is running) Noah is an application registry loosely based on [Apache ZooKeeper](http://zookeeper.apache.org)
## Install What does that mean? From the ZooKeeper Home Page:
You can either do `gem install noah`, `git clone git://github.com/lusis/Noah.git noah` and do the `bundle` dance or download `noah.war` from the downloads link.
## Setup > ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications.
There is no specific configuration file in use anymore. Everything is configured via command-line options to the noah binary or stored in config.ru.
* The instance of Redis is configured via the `REDIS_URL` env setting. This is honored by Ohm.
* Redis DSN strings are in the format of "redis://hostname:port/db"
* `RACK_ENV` is honored.
* `rake sample["redis://localhost:6379/2"]` populates the locally running redis instance - db 2
* `rake spec` runs the test suite (using 'redis://localhost:6379/3' for storing test data)
_rake sample_
Creating Host entry for 'localhost'
Create Service entry for redis
Create Service entry for noah
Creating Application entry for 'noah'
Creating Configuration entry for 'noah'
Creating sample entries - Host and Service
Creating sample entries - Application and Configuration
Setup successful!
## Run it
There are three (well four) ways to run Noah
### downloaded war file
You can either deploy the war file to an existing container (tomcat and Jetty6 tested) or run it in standalone mode using the embedded winstone server.
Please note that you'll need to set the environment variable `REDIS_URL` if you want to point to any Redis server OTHER than localhost:6379/0.
#### Using winstone
export REDIS_URL=redis://hostname:port/dbnumber
java -server [-d64] -jar noah.war [-httpPort=<portnumber>] [--prefix=<different context root>]
_Winstone doesn't do ANY error checking on options passed to it. Please check carefully that you're using `--var=value` after the war file name._
#### Deploying to a container
Just copy noah.war to your webapps folder. It will be served from `/noah` unless you rename it to ROOT.war or create a context file (under Jetty)
### config.ru
Edit config.ru to change the redis instance or rack environment.
### bin/noah
The binary script in bin was created using [Vegas](https://github.com/quirkey/vegas). It accepts the familiar rack options as well as an option for specifying the redis url.
bin/noah -p 9292 -s thin -d -F -e production -r redis://localhost:6379/2
[2011-02-07 16:48:15 -0500] Starting 'noah'...
[2011-02-07 16:48:15 -0500] trying port 9292...
Couldn't get a file descriptor referring to the console
[2011-02-07 16:48:15 -0500] Running with Rack handler: Rack::Handler::Thin
>> Thin web server (v1.2.7 codename No Hup)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:9292, CTRL+C to stop
If you leave off `-F`, all information will be logged to `$HOME/.vegas/noah`. Run `bin/noah -h` for more options.
Please note on JRuby that the port setting does not work for some f'cking reason. Bug claims to have been fixed. Until then, when on Jruby run like so:
noah -F -d -r redis://localhost:6379/0
## Example links
[Noah Start Page](http://localhost:9292/)
If you have Noah running, you can hit the above link for some links created by the setup samples.
## All configs
_curl http://localhost:9292/c/_
[
{"id":"1",
"name":"db",
"format":"string",
"body":"redis://127.0.0.1:6379/0",
"update_at":"2011-01-17 14:12:43 UTC",
"application":"noah"
}
]
## All services
_curl http://localhost:9292/s/_
[
{
"id":"1",
"name":"redis",
"status":"up",
"updated_at":"2011-01-17 14:12:43 UTC",
"host":"localhost"
},
{
"id":"2",
"name":"noah",
"status":"up",
"updated_at":"2011-01-17 14:12:43 UTC",
"host":"localhost"
}
]
## All hosts
_curl http://localhost:9292/h/_
[
{
"id":"1",
"name":"localhost",
"status":"up",
"updated_at":"2011-01-17 14:12:43 UTC",
"services":[
{
"id":"1",
"name":"redis",
"status":"up",
"updated_at":"2011-01-17 14:12:43 UTC",
"host":"localhost"
},
{
"id":"2",
"name":"noah",
"status":"up",
"updated_at":"2011-01-17 14:12:43 UTC",
"host":"localhost"
}
]
}
]
## All applications
_curl http://localhost:9292/a/_
[
{
"id":"1",
"name":"noah",
"updated_at":"2011-01-17 14:12:43 UTC"
}
]
Most other combinations of endpoints work as well:
* `http://localhost:9292/h/<hostname>/<servicename>` - `<servicename>` on `<hostname>`
* `http://localhost:9292/a/<appname>/<configname>` - Configuration for `<appname>`
* `http://localhost:9292/c/<appname>/<element>` - Specific configuration element for `<appname>`
{
"id":"1",
"name":"db",
"format":"string",
"body":"redis://127.0.0.1:6379/0",
"update_at":"2011-01-17 14:12:43 UTC",
"application":"noah"
}
# Adding new entries
There are two ways to add new objects: via irb and via the [API](https://github.com/lusis/Noah/wiki/Stabilize-API) on a running instance. The API is still in a state of flux.
## Adding a new application and configuration item
irb -rohm -rohm/contrib -r./lib/noah/models.rb
a1 = Application.create(:name => 'myapplication')
if a1.save
a1.configurations << Configuration.create(:name => 'jsonconfigobj', :format => 'json', :body => '{"configvar1":"foo","configvar2":"bar"}', :application => a1)
end
JSON.parse(Configuration[2].body)
{"configvar1"=>"foo", "configvar2"=>"bar"}
## database.yml inside Noah? Sure!
dbyaml = <<EOY
development:
adapter: mysql
database: rails_development
username: root
password: my super secret password
EOY
a2 = Application.create(:name => 'myrailsapp')
if a2.save
a2.configurations << Configuration.create(:name => 'database.yml', :format => 'yaml', :body => dbyaml, :application => a2)
end
puts YAML.dump(Configuration[3].body)
development:
adapter: mysql
database: rails_development
username: root
password: my super secret password
# Hosts and Services/Applications and Configurations
Host/Services and Applications/Configurations are almost the same thing with a few exceptions. Here are some basic facts:
* Hosts have many Services
* Applications have many Configurations
* Hosts and Services have a status - `up`,`down` or `pending`
The intention of the `status` field for Hosts and Services is that a service might, when starting up, set the appropriate status. Same goes for said service shutting down. This also applies to hosts (i.e. a curl PUT is sent to Noah during the boot process).
While an application might have different "configurations" based on environment (production, qa, dev), the Configuration object in Noah is intended to be more holistic i.e. these are the Configuration atoms (a yaml file, property X, property Y) that form the running configuration of an Application.
Here's a holistic example using a tomcat application:
* Host running tomcat comes up. It sets its status as "pending"
* Each service on the box starts up and sets its status to "pending" and finally "up" (think steps in the init script for the service)
* Tomcat (now in the role of `Application`) given a single property in a properties file called "bootstrap.url", grabs a list of `Configuration`atoms it needs to run. Let's say, by default, Tomcat starts up with all webapps disabled. Using the `Configuration` item `webapps`, it knows which ones to start up.
* Each webapp (an application under a different context root) now has the role of `Application` and the role of `Service`. As an application, the webapp would grab things that would normally be stored in a .properties file. Maybe even the log4j.xml file. In the role of `Service`, a given webapp might be an API endpoint and so it would have a hostname (a virtual host maybe?) and services associated with it. Each of those, has a `status`.
That might be confusing and it's a fairly overly-contrived example. A more comon use case would be the above where, instead of storing the database.yml on the server, the Rails application actually reads the file from Noah. Now that might not be too exciting but try this example:
* Rails application with memcached as part of the stack.
* Instead of a local configuration file, the list of memcached servers is a `Configuration` object belonging to the rails application's `Application` object.
* As new memcached servers are brought online, your CM tool (puppet or chef) updates Noah
* Your Rails application either via restarting (and thus rebootstrapping the list of memcached servers from Noah) or using the Watcher subsystem is instantly aware of those servers. You could fairly easily implement a custom Watcher that, when the list of memcached server changes, the Passenger restart file is written.
Make sense?
# Constraints
You can view all the constraints inside `models.rb` but here they are for now:
* A new host must have at least `name` and `status` set.
* A new service must have at least `name` and `status` set.
* Each Host `name` must be unique
* Each Service `name` per Host must be unique
* Each Application `name` must exist and be unique
* Each Configuration name per Application must be unique.
* Each Configuration must have `name`,`format` and `body`
Essentially Noah, is a port of those concepts into a stateless RESTful application.
## Quick Start
The quickstart guide has been moved to the wiki:
[Quick Start Guide](https://github.com/lusis/Noah/wiki/Quick-Start)
## Design Goals
Noah has a few basic design goals:
* The system **MUST** support RESTful interaction for operations where REST maps properly
* The system **MUST** support basic concepts of hosts, services, applications and configurations
* The system **MUST** support horizontal scaling.
Additionally:
* The system **SHOULD** be flexible in deployment options.
* The system **SHOULD** support watches similar to ZooKeeper
* The system **SHOULD** support pluggable callbacks for watches.
* The system **SHOULD** support being a client of itself.
## Opinionated Stack
Noah is somewhat opinionated in its stack. Noah attempts to minimize the external requirements wherever possible to allow for the widest possible installation options.
However, excellent work has been done to create performant and well-tested libraries that would be foolish to ignore. To this end, the current requirements are:
* [Redis 2.0](http://redis.io)
* [Sinatra](http://www.sinatrarb.com)
* [Ohm/Ohm-Contrib](http://ohm.keyvalue.org)
* [EventMachine](http://rubyeventmachine.com)
The above stack provides much of the functionality needed to port over ZooKeeper concepts.
### Redis
Redis is the backbone of the system. Through the native [datatypes](http://redis.io/commands) and [pubsub](http://redis.io/commands#pubsub) capabilities, much of the heavy lifting has already been done.
### Sinatra
Sinatra is the perfect library for creating API-only style applications. It allows you do focus on the meat of what an endpoint should do instead of the hassle of creating the endpoint.
### Ohm
Ohm is quite simply the most unobtrusive and flexible orm for Redis. It gets out of the way and allows you to very easily interact directly with Redis if the need arises
### EventMachine
EventMachine combined with Redis pubsub forms the basis of the Watcher and callback system.
## Motivation
It's something I've wanted to do for a while. Everytime I've needed something like Zookeeper, Zookeeper has always been too bulky and had too many moving parts. I've also always needed to interact with it from more than just Java or C. Sometimes it's been Ruby and sometimes it's been Python.
In the end, we reinvent the wheel ANYWAY. Maybe we do something like have our CM tool write our application config files with a list of memcached hosts. Maybe we write our own logic around (shudder) RMI to do some chatty broadcasting around the network for finding local nodes of type X. We always reinvent the wheel in some way.
## More information
Here are a list of some key [wiki](https://github.com/lusis/Noah/wiki) pages:
* [Concepts](https://github.com/lusis/Noah/wiki/Concepts)
How Noah views various object types in the system
* [API](https://github.com/lusis/Noah/wiki/Stablize-API)
The API is currently in draft state. It will be finalized before the 1.0 release.
* [Example Use Cases](https://github.com/lusis/Noah/wiki/Example-Use-Cases)
Some use cases for Noah and how it would fit into an existing application or infrastructure
* [Watchers and Callbacks](https://github.com/lusis/Noah/wiki/Watchers-and-Callbacks)
The general idea behind how Noah would implement watches
* [Watcher/Callback Examples](https://github.com/lusis/Noah/blob/master/examples/README.md)
Some example callbacks.
...@@ -90,7 +90,21 @@ EOJ ...@@ -90,7 +90,21 @@ EOJ
end end
puts "Sample data populated!" puts "Sample data populated!"
end end
begin
require 'yard'
require 'yard/sinatra'
desc "Generate documentation"
YARD::Rake::YardocTask.new do |t|
t.files = ['lib/**/*.rb'] # optional
t.options = ['--title', "Noah #{Noah::VERSION} Documentation"]
t.options += ['--plugin', "yard-sinatra"]
t.options += ['--protected', '--private'] # optional
end
rescue LoadError
"You need YARD installed to generate docs"
end
desc "Demo environment" desc "Demo environment"
task :start_demo do task :start_demo do
puts "Soon, young padawan" puts "Soon, young padawan"
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Noah C0 Coverage Information - RCov</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery.tablesorter.min.js"></script>
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<noscript><style type="text/css">.if_js { display:none; }</style></noscript>
<div class="filters if_js">
<fieldset>
<label>File Filter:</label>
<select id="file_filter" class="filter">
<option value="all_files">Show All</option>
<option value="lib">lib/</option><option value="noah">noah/</option>
</select>
</fieldset>
<fieldset>
<label>Code Coverage Threshold:</label>
<select id="coverage_filter" class="filter">
<option value="all_coverage">Show All</option>
<option value="10">&lt; 10% Coverage</option><option value="20">&lt; 20% Coverage</option><option value="30">&lt; 30% Coverage</option><option value="40">&lt; 40% Coverage</option><option value="50">&lt; 50% Coverage</option><option value="60">&lt; 60% Coverage</option><option value="70">&lt; 70% Coverage</option><option value="80">&lt; 80% Coverage</option><option value="90">&lt; 90% Coverage</option><option value="100">&lt; 100% Coverage</option>
<option value="110">= 100% Coverage</option>
</select>
</fieldset>
</div>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tfoot>
<tr>
<td class="left_align">TOTAL</td>
<td class='right_align'><tt>572</tt></td>
<td class='right_align'><tt>491</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>76.40%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:76px"></div>
<div class="uncovered" style="width:24px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class='coverage_total'>74.34%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:74px"></div>
<div class="uncovered" style="width:26px"></div>
</div></td>
</tr>
</tfoot>
<tbody>
<tr class="all_files all_coverage 60 70 80 90 100 lib noah even">
<td class="left_align"><a href="lib-noah-watchers_rb.html">lib/noah/watchers.rb</a></td>
<td class='right_align'><tt>18</tt></td>
<td class='right_align'><tt>15</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>61.11%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:61px"></div>
<div class="uncovered" style="width:39px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>53.33%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:53px"></div>
<div class="uncovered" style="width:47px"></div>
</div></td>
</tr>
<tr class="all_files all_coverage 60 70 80 90 100 lib noah odd">
<td class="left_align"><a href="lib-noah-helpers_rb.html">lib/noah/helpers.rb</a></td>
<td class='right_align'><tt>57</tt></td>
<td class='right_align'><tt>46</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>57.89%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:58px"></div>
<div class="uncovered" style="width:42px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>58.70%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:59px"></div>
<div class="uncovered" style="width:41px"></div>
</div></td>
</tr>
<tr class="all_files all_coverage 70 80 90 100 lib noah even">
<td class="left_align"><a href="lib-noah-applications_rb.html">lib/noah/applications.rb</a></td>
<td class='right_align'><tt>46</tt></td>
<td class='right_align'><tt>39</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>73.91%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:74px"></div>
<div class="uncovered" style="width:26px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>69.23%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:69px"></div>
<div class="uncovered" style="width:31px"></div>
</div></td>
</tr>
<tr class="all_files all_coverage 80 90 100 lib noah odd">
<td class="left_align"><a href="lib-noah-services_rb.html">lib/noah/services.rb</a></td>
<td class='right_align'><tt>57</tt></td>
<td class='right_align'><tt>48</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>73.68%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:74px"></div>
<div class="uncovered" style="width:26px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>70.83%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:71px"></div>
<div class="uncovered" style="width:29px"></div>
</div></td>
</tr>
<tr class="all_files all_coverage 80 90 100 lib noah even">
<td class="left_align"><a href="lib-noah-hosts_rb.html">lib/noah/hosts.rb</a></td>
<td class='right_align'><tt>54</tt></td>
<td class='right_align'><tt>46</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>75.93%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:76px"></div>
<div class="uncovered" style="width:24px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>71.74%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:72px"></div>
<div class="uncovered" style="width:28px"></div>
</div></td>
</tr>
<tr class="all_files all_coverage 80 90 100 lib noah odd">
<td class="left_align"><a href="lib-noah-app_rb.html">lib/noah/app.rb</a></td>
<td class='right_align'><tt>317</tt></td>
<td class='right_align'><tt>275</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>81.07%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:81px"></div>
<div class="uncovered" style="width:19px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>79.27%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:79px"></div>
<div class="uncovered" style="width:21px"></div>
</div></td>
</tr>
<tr class="all_files all_coverage 90 100 lib noah even">
<td class="left_align"><a href="lib-noah-models_rb.html">lib/noah/models.rb</a></td>
<td class='right_align'><tt>5</tt></td>
<td class='right_align'><tt>5</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>80.00%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:80px"></div>
<div class="uncovered" style="width:20px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>80.00%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:80px"></div>
<div class="uncovered" style="width:20px"></div>
</div></td>
</tr>
<tr class="all_files all_coverage 90 100 lib odd">
<td class="left_align"><a href="lib-noah_rb.html">lib/noah.rb</a></td>
<td class='right_align'><tt>18</tt></td>
<td class='right_align'><tt>17</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>83.33%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:83px"></div>
<div class="uncovered" style="width:17px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>82.35%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:82px"></div>
<div class="uncovered" style="width:18px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<p>Generated on 2011-02-08 01:54:20 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
<script type="text/javascript">
$(document).ready(function(){$("#report_table").tablesorter({widgets: ['zebra'], textExtraction: 'complex'});});
$('.filter').change(function(){
ff = $('#file_filter').val();
cf = $('#coverage_filter').val();
$('table#report_table tbody tr').each(function(i){
if ((this.className.split(" ").indexOf(ff) > -1) && (this.className.split(" ").indexOf(cf) > -1)) {
this.style.display = "";
} else {
this.style.display = "none";
};
restripe();
})
})
</script>
</body>
</html>
/*
* jQuery JavaScript Library v1.3.2
* http://jquery.com/
*
* Copyright (c) 2009 John Resig
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*
* Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
* Revision: 6246
*/
(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
/*
* Sizzle CSS Selector Engine - v0.9.3
* Copyright 2009, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
*/
(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.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|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML=' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<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>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();
\ No newline at end of file
/*
*
* TableSorter 2.0 - Client-side table sorting with ease!
* Version 2.0.3
* @requires jQuery v1.2.3
*
* Copyright (c) 2007 Christian Bach
* Examples and docs at: http://tablesorter.com
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
(function($){$.extend({tablesorter:new function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'.',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}var rows=table.tBodies[0].rows;if(table.tBodies[0].rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,cells[i]);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,node){var l=parsers.length;for(var i=1;i<l;i++){if(parsers[i].is($.trim(getElementText(table.config,node)),table,node)){return parsers[i];}}return parsers[0];}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=table.tBodies[0].rows[i],cols=[];cache.row.push($(c));for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j]));}cols.push(i);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){if(!node)return"";var t="";if(config.textExtraction=="simple"){if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){t=node.childNodes[0].innerHTML;}else{t=node.innerHTML;}}else{if(typeof(config.textExtraction)=="function"){t=config.textExtraction(node);}else{t=$(node).text();}}return t;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){rows.push(r[n[i][checkCell]]);if(!table.config.appender){var o=r[n[i][checkCell]];var l=o.length;for(var j=0;j<l;j++){tableBody[0].appendChild(o[j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false,tableHeadersRows=[];for(var i=0;i<table.tHead.rows.length;i++){tableHeadersRows[i]=0;};$tableHeaders=$("thead th",table);$tableHeaders.each(function(index){this.count=0;this.column=index;this.order=formatSortingOrder(table.config.sortInitialOrder);if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(!this.sortDisabled){$(this).addClass(table.config.cssHeader);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){i=(v.toLowerCase()=="desc")?1:0;}else{i=(v==(0||1))?v:0;}return i;}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(getCachedSortType(table.config.parsers,c)=="text")?((order==0)?"sortText":"sortTextDesc"):((order==0)?"sortNumeric":"sortNumericDesc");var e="e"+i;dynamicExp+="var "+e+" = "+s+"(a["+c+"],b["+c+"]); ";dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function sortText(a,b){return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){var DECIMAL='\\'+config.decimal;var exp='/(^[+]?0('+DECIMAL+'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)'+DECIMAL+'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*'+DECIMAL+'0+$)/';return RegExp(exp).test($.trim(s));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}$("tr:visible",table.tBodies[0]).filter(':even').removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]).end().filter(':odd').removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>lib/noah/app.rb</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<h2>lib/noah/app.rb</h2>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left_align"><a href="lib-noah-app_rb.html">lib/noah/app.rb</a></td>
<td class='right_align'><tt>317</tt></td>
<td class='right_align'><tt>275</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>81.07%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:81px"></div>
<div class="uncovered" style="width:19px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>79.27%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:79px"></div>
<div class="uncovered" style="width:21px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<h3>Key</h3>
<div class="key"><pre><span class='marked'>Code reported as executed by Ruby looks like this...</span><span class='marked1'>and this: this line is also marked as covered.</span><span class='inferred'>Lines considered as run by rcov, but not reported by Ruby, look like this,</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).</span><span class='uncovered'>Finally, here's a line marked as not executed.</span></pre></div>
<h3>Coverage Details</h3>
<table class="details">
<tbody>
<tr class="uncovered">
<td><pre><a name="line1">1</a> require 'sinatra/base'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line2">2</a> require 'sinatra/namespace'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line3">3</a> require 'ohm'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line4">4</a> require 'ohm/contrib'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line5">5</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line6">6</a> require File.join(File.dirname(__FILE__), 'helpers')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line7">7</a> require File.join(File.dirname(__FILE__), 'models')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line8">8</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line9">9</a> module Noah</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line10">10</a> class App &lt; Sinatra::Base</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line11">11</a> register ::Sinatra::Namespace</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line12">12</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line13">13</a> helpers Noah::SinatraHelpers</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line14">14</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line15">15</a> configure do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line16">16</a> set :app_file, __FILE__</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line17">17</a> set :root, File.expand_path(File.join(File.dirname(__FILE__), &quot;..&quot;,&quot;..&quot;))</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line18">18</a> set :server, %w[thin mongrel webrick]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line19">19</a> set :logging, true</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line20">20</a> set :raise_errors, false</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line21">21</a> set :show_exceptions, false</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line22">22</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line23">23</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line24">24</a> configure(:development) do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line25">25</a> begin</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line26">26</a> require 'sinatra/reloader'</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line27">27</a> register Sinatra::Reloader</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line28">28</a> also_reload File.join(File.dirname(__FILE__), 'models.rb')</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line29">29</a> also_reload File.join(File.dirname(__FILE__), 'helpers.rb')</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line30">30</a> rescue LoadError</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line31">31</a> puts &quot;sinatra-reloader gem missing. reloading disabled&quot;</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line32">32</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line33">33</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line34">34</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line35">35</a> before do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line36">36</a> content_type &quot;application/json&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line37">37</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line38">38</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line39">39</a> get '/' do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line40">40</a> content_type &quot;text/html&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line41">41</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line42">42</a> haml :index, :format =&gt; :html5</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line43">43</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line44">44</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line45">45</a> not_found do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line46">46</a> content_type &quot;application/json&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line47">47</a> erb :'404'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line48">48</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line49">49</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line50">50</a> error do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line51">51</a> content_type &quot;application/json&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line52">52</a> erb :'500'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line53">53</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line54">54</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line55">55</a> namespace &quot;/h&quot; do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line56">56</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line57">57</a> get '/:hostname/:servicename/?' do |hostname, servicename|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line58">58</a> h = host_service(hostname, servicename)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line59">59</a> if h.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line60">60</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line61">61</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line62">62</a> h.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line63">63</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line64">64</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line65">65</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line66">66</a> get '/:hostname/?' do |hostname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line67">67</a> h = host(:name =&gt; hostname)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line68">68</a> if h.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line69">69</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line70">70</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line71">71</a> h.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line72">72</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line73">73</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line74">74</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line75">75</a> get '/?' do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line76">76</a> hosts.map {|h| h.to_hash}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line77">77</a> if hosts.size == 0</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line78">78</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line79">79</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line80">80</a> hosts.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line81">81</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line82">82</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line83">83</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line84">84</a> put '/:hostname/?' do |hostname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line85">85</a> required_params = [&quot;name&quot;, &quot;status&quot;]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line86">86</a> data = JSON.parse(request.body.read)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line87">87</a> (data.keys.sort == required_params.sort &amp;&amp; data['name'] == hostname) ? (host = ::Host.find_or_create(:name =&gt; data['name'], :status =&gt; data['status'])) : (raise &quot;Missing Parameters&quot;)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line88">88</a> if host.valid?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line89">89</a> r = {&quot;result&quot; =&gt; &quot;success&quot;,&quot;id&quot; =&gt; &quot;#{host.id}&quot;,&quot;status&quot; =&gt; &quot;#{host.status}&quot;, &quot;name&quot; =&gt; &quot;#{host.name}&quot;, &quot;new_record&quot; =&gt; host.is_new?}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line90">90</a> r.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line91">91</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line92">92</a> raise &quot;#{host.errors}&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line93">93</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line94">94</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line95">95</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line96">96</a> delete '/:hostname/?' do |hostname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line97">97</a> host = ::Host.find(:name =&gt; hostname).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line98">98</a> if host</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line99">99</a> services = []</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line100">100</a> Service.find(:host_id =&gt; host.id).sort.each {|x| services &lt;&lt; x; x.delete} if host.services.size &gt; 0</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line101">101</a> host.delete</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line102">102</a> r = {&quot;result&quot; =&gt; &quot;success&quot;, &quot;id&quot; =&gt; &quot;#{host.id}&quot;, &quot;name&quot; =&gt; &quot;#{hostname}&quot;, &quot;service_count&quot; =&gt; &quot;#{services.size}&quot;}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line103">103</a> r.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line104">104</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line105">105</a> halt 404</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line106">106</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line107">107</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line108">108</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line109">109</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line110">110</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line111">111</a> namespace &quot;/s&quot; do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line112">112</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line113">113</a> get '/:servicename/:hostname/?' do |servicename, hostname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line114">114</a> hs = host_service(hostname, servicename)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line115">115</a> if hs.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line116">116</a> halt 404</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line117">117</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line118">118</a> hs.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line119">119</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line120">120</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line121">121</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line122">122</a> get '/:servicename/?' do |servicename|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line123">123</a> s = services(:name =&gt; servicename)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line124">124</a> s.map {|x| x.to_hash}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line125">125</a> if s.empty?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line126">126</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line127">127</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line128">128</a> s.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line129">129</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line130">130</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line131">131</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line132">132</a> get '/?' do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line133">133</a> if services.empty?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line134">134</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line135">135</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line136">136</a> services.map {|s| s.to_hash}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line137">137</a> services.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line138">138</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line139">139</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line140">140</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line141">141</a> put '/:servicename/?' do |servicename|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line142">142</a> required_params = [&quot;status&quot;, &quot;host&quot;, &quot;name&quot;]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line143">143</a> data = JSON.parse(request.body.read)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line144">144</a> if data.keys.sort == required_params.sort</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line145">145</a> h = ::Host.find(:name =&gt; data['host']).first || (raise &quot;Invalid Host&quot;)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line146">146</a> service = ::Service.find_or_create(:name =&gt; servicename, :status =&gt; data['status'], :host =&gt; h)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line147">147</a> if service.valid?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line148">148</a> action = service.is_new? ? &quot;create&quot; : &quot;update&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line149">149</a> service.save</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line150">150</a> r = {&quot;action&quot; =&gt; action, &quot;result&quot; =&gt; &quot;success&quot;, &quot;id&quot; =&gt; service.id, &quot;host&quot; =&gt; h.name, &quot;name&quot; =&gt; service.name}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line151">151</a> r.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line152">152</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line153">153</a> raise &quot;#{service.errors}&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line154">154</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line155">155</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line156">156</a> raise &quot;Missing Parameters&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line157">157</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line158">158</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line159">159</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line160">160</a> delete '/:servicename/:hostname/?' do |servicename, hostname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line161">161</a> host = ::Host.find(:name =&gt; hostname).first || (halt 404)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line162">162</a> service = ::Service.find(:name =&gt; servicename, :host_id =&gt; host.id).first || (halt 404)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line163">163</a> if host &amp;&amp; service</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line164">164</a> service.delete</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line165">165</a> r = {&quot;action&quot; =&gt; &quot;delete&quot;, &quot;result&quot; =&gt; &quot;success&quot;, &quot;id&quot; =&gt; service.id, &quot;host&quot; =&gt; host.name, &quot;service&quot; =&gt; servicename}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line166">166</a> r.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line167">167</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line168">168</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line169">169</a> end </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line170">170</a> end </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line171">171</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line172">172</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line173">173</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line174">174</a> namespace &quot;/a&quot; do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line175">175</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line176">176</a> get '/:appname/:config/?' do |appname, config|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line177">177</a> app = ::Application.find(:name =&gt; appname).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line178">178</a> if app.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line179">179</a> halt 404</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line180">180</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line181">181</a> c = ::Configuration.find(:name =&gt; config, :application_id =&gt; app.id).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line182">182</a> c.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line183">183</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line184">184</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line185">185</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line186">186</a> get '/:appname/?' do |appname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line187">187</a> app = ::Application.find(:name =&gt; appname).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line188">188</a> if app.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line189">189</a> halt 404</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line190">190</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line191">191</a> app.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line192">192</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line193">193</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line194">194</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line195">195</a> put '/:appname/?' do |appname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line196">196</a> required_params = [&quot;name&quot;]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line197">197</a> data = JSON.parse(request.body.read)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line198">198</a> if data.keys.sort == required_params.sort &amp;&amp; data['name'] == appname</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line199">199</a> app = ::Application.find_or_create(:name =&gt; appname)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line200">200</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line201">201</a> raise &quot;Missing Parameters&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line202">202</a> end </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line203">203</a> if app.valid?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line204">204</a> action = app.is_new? ? &quot;create&quot; : &quot;update&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line205">205</a> app.save</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line206">206</a> r = {&quot;result&quot; =&gt; &quot;success&quot;,&quot;id&quot; =&gt; app.id, &quot;action&quot; =&gt; action, &quot;name&quot; =&gt; app.name }</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line207">207</a> r.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line208">208</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line209">209</a> raise &quot;#{app.errors}&quot;</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line210">210</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line211">211</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line212">212</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line213">213</a> delete '/:appname/?' do |appname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line214">214</a> app = ::Application.find(:name =&gt; appname).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line215">215</a> if app.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line216">216</a> halt 404</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line217">217</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line218">218</a> configurations = []</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line219">219</a> ::Configuration.find(:application_id =&gt; app.id).sort.each {|x| configurations &lt;&lt; x; x.delete} if app.configurations.size &gt; 0</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line220">220</a> app.delete</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line221">221</a> r = {&quot;result&quot; =&gt; &quot;success&quot;, &quot;action&quot; =&gt; &quot;delete&quot;, &quot;id&quot; =&gt; &quot;#{app.id}&quot;, &quot;name&quot; =&gt; &quot;#{appname}&quot;, &quot;configurations&quot; =&gt; &quot;#{configurations.size}&quot;}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line222">222</a> r.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line223">223</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line224">224</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line225">225</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line226">226</a> get '/?' do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line227">227</a> apps = []</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line228">228</a> ::Application.all.sort.each {|a| apps &lt;&lt; a.to_hash}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line229">229</a> if apps.empty?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line230">230</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line231">231</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line232">232</a> apps.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line233">233</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line234">234</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line235">235</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line236">236</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line237">237</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line238">238</a> namespace '/c' do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line239">239</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line240">240</a> # Need to move this out to configuration.</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line241">241</a> # Maybe bootstrap them from itself?</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line242">242</a> content_type_mapping = {</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line243">243</a> :yaml =&gt; &quot;text/x-yaml&quot;,</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line244">244</a> :json =&gt; &quot;application/json&quot;,</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line245">245</a> :xml =&gt; &quot;text/xml&quot;,</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line246">246</a> :string =&gt; &quot;text/plain&quot;</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line247">247</a> }</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line248">248</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line249">249</a> get '/:appname/:element/?' do |appname, element|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line250">250</a> a = ::Application.find(:name =&gt; appname).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line251">251</a> if a.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line252">252</a> halt 404</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line253">253</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line254">254</a> c = ::Configuration.find(:name =&gt; element, :application_id =&gt; a.id).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line255">255</a> content_type content_type_mapping[c.format.to_sym] if content_type_mapping[c.format.to_sym]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line256">256</a> c.body</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line257">257</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line258">258</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line259">259</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line260">260</a> get '/:appname/?' do |appname|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line261">261</a> config = []</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line262">262</a> a = ::Application.find(:name =&gt; appname).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line263">263</a> if a.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line264">264</a> halt 404</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line265">265</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line266">266</a> ::Configuration.find(:application_id =&gt; a.id).sort.each {|c| config &lt;&lt; c.to_hash}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line267">267</a> config.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line268">268</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line269">269</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line270">270</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line271">271</a> get '/?' do</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line272">272</a> configs = []</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line273">273</a> ::Configuration.all.sort.each {|c| configs &lt;&lt; c.to_hash}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line274">274</a> if configs.empty?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line275">275</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line276">276</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line277">277</a> configs.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line278">278</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line279">279</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line280">280</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line281">281</a> put '/:appname/:element?' do |appname, element|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line282">282</a> app = ::Application.find_or_create(:name =&gt; appname)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line283">283</a> config = ::Configuration.find_or_create(:name =&gt; element, :application_id =&gt; app.id)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line284">284</a> required_params = [&quot;format&quot;, &quot;body&quot;]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line285">285</a> data = JSON.parse(request.body.read)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line286">286</a> data.keys.sort == required_params.sort ? (config.format = data[&quot;format&quot;]; config.body = data[&quot;body&quot;]) : (raise &quot;Missing Parameters&quot;)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line287">287</a> if config.valid?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line288">288</a> config.save</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line289">289</a> action = config.is_new? ? &quot;create&quot; : &quot;update&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line290">290</a> dependency_action = app.is_new? ? &quot;created&quot; : &quot;updated&quot;</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line291">291</a> r = {&quot;result&quot; =&gt; &quot;success&quot;,&quot;id&quot; =&gt; &quot;#{config.id}&quot;, &quot;action&quot; =&gt; action, &quot;dependencies&quot; =&gt; dependency_action, &quot;application&quot; =&gt; app.name, &quot;item&quot; =&gt; config.name}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line292">292</a> r.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line293">293</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line294">294</a> raise &quot;#{config.errors}&quot;</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line295">295</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line296">296</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line297">297</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line298">298</a> delete '/:appname/:element?' do |appname, element|</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line299">299</a> app = ::Application.find(:name =&gt; appname).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line300">300</a> if app</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line301">301</a> config = ::Configuration.find(:name=&gt; element, :application_id =&gt; app.id).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line302">302</a> if config</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line303">303</a> config.delete</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line304">304</a> r = {&quot;result&quot; =&gt; &quot;success&quot;, &quot;id&quot; =&gt; &quot;#{config.id}&quot;, &quot;action&quot; =&gt; &quot;delete&quot;, &quot;application&quot; =&gt; &quot;#{app.name}&quot;, &quot;item&quot; =&gt; &quot;#{element}&quot;}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line305">305</a> r.to_json</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line306">306</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line307">307</a> halt 404</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line308">308</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line309">309</a> else</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line310">310</a> halt 404</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line311">311</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line312">312</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line313">313</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line314">314</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line315">315</a> # run! if app_file == $0</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line316">316</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line317">317</a> end</pre></td>
</tr>
</tbody>
</table>
<p>Generated on 2011-02-08 01:54:21 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>lib/noah/applications.rb</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<h2>lib/noah/applications.rb</h2>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left_align"><a href="lib-noah-applications_rb.html">lib/noah/applications.rb</a></td>
<td class='right_align'><tt>46</tt></td>
<td class='right_align'><tt>39</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>73.91%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:74px"></div>
<div class="uncovered" style="width:26px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>69.23%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:69px"></div>
<div class="uncovered" style="width:31px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<h3>Key</h3>
<div class="key"><pre><span class='marked'>Code reported as executed by Ruby looks like this...</span><span class='marked1'>and this: this line is also marked as covered.</span><span class='inferred'>Lines considered as run by rcov, but not reported by Ruby, look like this,</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).</span><span class='uncovered'>Finally, here's a line marked as not executed.</span></pre></div>
<h3>Coverage Details</h3>
<table class="details">
<tbody>
<tr class="uncovered">
<td><pre><a name="line1">1</a> class Application &lt; Ohm::Model</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line2">2</a> include Ohm::Typecast</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line3">3</a> include Ohm::Timestamping</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line4">4</a> include Ohm::Callbacks</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line5">5</a> include Ohm::ExtraValidations</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line6">6</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line7">7</a> attribute :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line8">8</a> collection :configurations, Configuration</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line9">9</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line10">10</a> index :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line11">11</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line12">12</a> def validate</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line13">13</a> assert_present :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line14">14</a> assert_unique :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line15">15</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line16">16</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line17">17</a> def to_hash</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line18">18</a> arr = []</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line19">19</a> configurations.sort.each {|c| arr &lt;&lt; c.to_hash}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line20">20</a> super.merge(:name =&gt; name, :updated_at =&gt; updated_at, :configurations =&gt; arr)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line21">21</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line22">22</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line23">23</a> def is_new?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line24">24</a> self.created_at == self.updated_at</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line25">25</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line26">26</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line27">27</a> class &lt;&lt; self</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line28">28</a> def find_or_create(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line29">29</a> begin</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line30">30</a> find(opts).first.nil? ? (app = create(opts)) : (app = find(opts).first)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line31">31</a> if app.valid?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line32">32</a> app.save</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line33">33</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line34">34</a> app</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line35">35</a> rescue Exception =&gt; e</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line36">36</a> e.message</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line37">37</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line38">38</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line39">39</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line40">40</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line41">41</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line42">42</a> class Applications</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line43">43</a> def self.all(options = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line44">44</a> options.empty? ? Application.all.sort : Application.find(options).sort</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line45">45</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line46">46</a> end</pre></td>
</tr>
</tbody>
</table>
<p>Generated on 2011-02-08 01:54:20 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>lib/noah/helpers.rb</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<h2>lib/noah/helpers.rb</h2>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left_align"><a href="lib-noah-helpers_rb.html">lib/noah/helpers.rb</a></td>
<td class='right_align'><tt>57</tt></td>
<td class='right_align'><tt>46</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>57.89%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:58px"></div>
<div class="uncovered" style="width:42px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>58.70%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:59px"></div>
<div class="uncovered" style="width:41px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<h3>Key</h3>
<div class="key"><pre><span class='marked'>Code reported as executed by Ruby looks like this...</span><span class='marked1'>and this: this line is also marked as covered.</span><span class='inferred'>Lines considered as run by rcov, but not reported by Ruby, look like this,</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).</span><span class='uncovered'>Finally, here's a line marked as not executed.</span></pre></div>
<h3>Coverage Details</h3>
<table class="details">
<tbody>
<tr class="uncovered">
<td><pre><a name="line1">1</a> require File.join(File.dirname(__FILE__), 'models')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line2">2</a> module Noah</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line3">3</a> module SinatraHelpers</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line4">4</a> extend(Ohm)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line5">5</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line6">6</a> def host(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line7">7</a> Host.find(opts).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line8">8</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line9">9</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line10">10</a> def hosts(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line11">11</a> Hosts.all(opts)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line12">12</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line13">13</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line14">14</a> def service(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line15">15</a> Service.find(options)</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line16">16</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line17">17</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line18">18</a> def services(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line19">19</a> Services.all(opts)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line20">20</a> end </pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line21">21</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line22">22</a> def host_service(hostname, servicename)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line23">23</a> h = Host.find(:name =&gt; hostname).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line24">24</a> if h.nil?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line25">25</a> nil</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line26">26</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line27">27</a> Service.find(:host_id =&gt; h.id, :name =&gt; servicename).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line28">28</a> end </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line29">29</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line30">30</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line31">31</a> def host_services(hostname)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line32">32</a> h = Host.find(:name =&gt; hostname).first</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line33">33</a> if h.nil?</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line34">34</a> nil</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line35">35</a> else </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line36">36</a> Services.all(:host_id =&gt; id)</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line37">37</a> end </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line38">38</a> end </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line39">39</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line40">40</a> def application(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line41">41</a> Application.find(opts).first</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line42">42</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line43">43</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line44">44</a> def applications(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line45">45</a> Applications.all(opts)</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line46">46</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line47">47</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line48">48</a> def configuration(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line49">49</a> Configuration.find(opts).first</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line50">50</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line51">51</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line52">52</a> def configurations(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line53">53</a> Configurations.all(opts)</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line54">54</a> end</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line55">55</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line56">56</a> </pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line57">57</a> end</pre></td>
</tr>
</tbody>
</table>
<p>Generated on 2011-02-08 01:54:20 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>lib/noah/hosts.rb</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<h2>lib/noah/hosts.rb</h2>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left_align"><a href="lib-noah-hosts_rb.html">lib/noah/hosts.rb</a></td>
<td class='right_align'><tt>54</tt></td>
<td class='right_align'><tt>46</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>75.93%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:76px"></div>
<div class="uncovered" style="width:24px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>71.74%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:72px"></div>
<div class="uncovered" style="width:28px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<h3>Key</h3>
<div class="key"><pre><span class='marked'>Code reported as executed by Ruby looks like this...</span><span class='marked1'>and this: this line is also marked as covered.</span><span class='inferred'>Lines considered as run by rcov, but not reported by Ruby, look like this,</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).</span><span class='uncovered'>Finally, here's a line marked as not executed.</span></pre></div>
<h3>Coverage Details</h3>
<table class="details">
<tbody>
<tr class="uncovered">
<td><pre><a name="line1">1</a> class Host &lt; Ohm::Model</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line2">2</a> include Ohm::Typecast</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line3">3</a> include Ohm::Timestamping</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line4">4</a> include Ohm::Callbacks</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line5">5</a> include Ohm::ExtraValidations</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line6">6</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line7">7</a> attribute :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line8">8</a> attribute :status</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line9">9</a> collection :services, Service</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line10">10</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line11">11</a> index :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line12">12</a> index :status</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line13">13</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line14">14</a> def validate</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line15">15</a> assert_present :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line16">16</a> assert_present :status</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line17">17</a> assert_unique :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line18">18</a> assert_member :status, [&quot;up&quot;,&quot;down&quot;,&quot;pending&quot;]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line19">19</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line20">20</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line21">21</a> def to_hash</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line22">22</a> arr = []</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line23">23</a> services.sort.each {|s| arr &lt;&lt; s.to_hash}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line24">24</a> h = {:name =&gt; name, :status =&gt; status, :created_at =&gt; created_at, :updated_at =&gt; updated_at, :services =&gt; arr}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line25">25</a> super.merge(h)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line26">26</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line27">27</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line28">28</a> def is_new?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line29">29</a> self.created_at == self.updated_at</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line30">30</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line31">31</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line32">32</a> class &lt;&lt; self</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line33">33</a> def find_or_create(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line34">34</a> begin</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line35">35</a> # exclude requested status from lookup</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line36">36</a> h = find(opts.reject{|key,value| key == :status}).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line37">37</a> host = h.nil? ? create(opts) : h</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line38">38</a> host.status = opts[:status]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line39">39</a> if host.valid?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line40">40</a> host.save</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line41">41</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line42">42</a> host</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line43">43</a> rescue Exception =&gt; e</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line44">44</a> e.message</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line45">45</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line46">46</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line47">47</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line48">48</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line49">49</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line50">50</a> class Hosts</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line51">51</a> def self.all(options = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line52">52</a> options.empty? ? Host.all.sort : Host.find(options).sort</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line53">53</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line54">54</a> end</pre></td>
</tr>
</tbody>
</table>
<p>Generated on 2011-02-08 01:54:21 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>lib/noah/models.rb</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<h2>lib/noah/models.rb</h2>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left_align"><a href="lib-noah-models_rb.html">lib/noah/models.rb</a></td>
<td class='right_align'><tt>5</tt></td>
<td class='right_align'><tt>5</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>80.00%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:80px"></div>
<div class="uncovered" style="width:20px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>80.00%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:80px"></div>
<div class="uncovered" style="width:20px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<h3>Key</h3>
<div class="key"><pre><span class='marked'>Code reported as executed by Ruby looks like this...</span><span class='marked1'>and this: this line is also marked as covered.</span><span class='inferred'>Lines considered as run by rcov, but not reported by Ruby, look like this,</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).</span><span class='uncovered'>Finally, here's a line marked as not executed.</span></pre></div>
<h3>Coverage Details</h3>
<table class="details">
<tbody>
<tr class="uncovered">
<td><pre><a name="line1">1</a> require File.join(File.dirname(__FILE__),'hosts')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line2">2</a> require File.join(File.dirname(__FILE__),'services')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line3">3</a> require File.join(File.dirname(__FILE__),'applications')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line4">4</a> require File.join(File.dirname(__FILE__),'configurations')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line5">5</a> require File.join(File.dirname(__FILE__),'watchers')</pre></td>
</tr>
</tbody>
</table>
<p>Generated on 2011-02-08 01:54:21 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>lib/noah/services.rb</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<h2>lib/noah/services.rb</h2>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left_align"><a href="lib-noah-services_rb.html">lib/noah/services.rb</a></td>
<td class='right_align'><tt>57</tt></td>
<td class='right_align'><tt>48</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>73.68%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:74px"></div>
<div class="uncovered" style="width:26px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>70.83%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:71px"></div>
<div class="uncovered" style="width:29px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<h3>Key</h3>
<div class="key"><pre><span class='marked'>Code reported as executed by Ruby looks like this...</span><span class='marked1'>and this: this line is also marked as covered.</span><span class='inferred'>Lines considered as run by rcov, but not reported by Ruby, look like this,</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).</span><span class='uncovered'>Finally, here's a line marked as not executed.</span></pre></div>
<h3>Coverage Details</h3>
<table class="details">
<tbody>
<tr class="uncovered">
<td><pre><a name="line1">1</a> class Service &lt; Ohm::Model</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line2">2</a> include Ohm::Typecast</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line3">3</a> include Ohm::Timestamping</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line4">4</a> include Ohm::Callbacks</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line5">5</a> include Ohm::ExtraValidations</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line6">6</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line7">7</a> attribute :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line8">8</a> attribute :status</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line9">9</a> reference :host, Host</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line10">10</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line11">11</a> index :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line12">12</a> index :status</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line13">13</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line14">14</a> def validate</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line15">15</a> assert_present :name</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line16">16</a> assert_present :status</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line17">17</a> assert_present :host_id</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line18">18</a> assert_unique [:name, :host_id]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line19">19</a> assert_member :status, [&quot;up&quot;, &quot;down&quot;, &quot;pending&quot;]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line20">20</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line21">21</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line22">22</a> def to_hash</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line23">23</a> super.merge(:name =&gt; name, :status =&gt; status, :updated_at =&gt; updated_at, :host =&gt; Host[host_id].name)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line24">24</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line25">25</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line26">26</a> def is_new?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line27">27</a> self.created_at == self.updated_at</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line28">28</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line29">29</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line30">30</a> class &lt;&lt; self</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line31">31</a> def find_or_create(opts = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line32">32</a> begin</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line33">33</a> # convert passed host object to host_id if passed</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line34">34</a> if opts.has_key?(:host)</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line35">35</a> opts.merge!({:host_id =&gt; opts[:host].id})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line36">36</a> opts.reject!{|key, value| key == :host}</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line37">37</a> end </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line38">38</a> # exclude requested status from lookup</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line39">39</a> s = find(opts.reject{|key,value| key == :status}).first</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line40">40</a> service = s.nil? ? create(opts) : s</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line41">41</a> service.status = opts[:status]</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line42">42</a> if service.valid?</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line43">43</a> service.save</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line44">44</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line45">45</a> service</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line46">46</a> rescue Exception =&gt; e</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line47">47</a> e.message</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line48">48</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line49">49</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line50">50</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line51">51</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line52">52</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line53">53</a> class Services</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line54">54</a> def self.all(options = {})</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line55">55</a> options.empty? ? Service.all.sort : Service.find(options).sort</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line56">56</a> end</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line57">57</a> end</pre></td>
</tr>
</tbody>
</table>
<p>Generated on 2011-02-08 01:54:20 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>lib/noah/watchers.rb</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<h2>lib/noah/watchers.rb</h2>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left_align"><a href="lib-noah-watchers_rb.html">lib/noah/watchers.rb</a></td>
<td class='right_align'><tt>18</tt></td>
<td class='right_align'><tt>15</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>61.11%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:61px"></div>
<div class="uncovered" style="width:39px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>53.33%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:53px"></div>
<div class="uncovered" style="width:47px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<h3>Key</h3>
<div class="key"><pre><span class='marked'>Code reported as executed by Ruby looks like this...</span><span class='marked1'>and this: this line is also marked as covered.</span><span class='inferred'>Lines considered as run by rcov, but not reported by Ruby, look like this,</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).</span><span class='uncovered'>Finally, here's a line marked as not executed.</span></pre></div>
<h3>Coverage Details</h3>
<table class="details">
<tbody>
<tr class="uncovered">
<td><pre><a name="line1">1</a> class Watcher &lt; Ohm::Model #NYI</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line2">2</a> include Ohm::Typecast</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line3">3</a> include Ohm::Timestamping</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line4">4</a> include Ohm::Callbacks</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line5">5</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line6">6</a> attribute :client</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line7">7</a> attribute :endpoint</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line8">8</a> attribute :event</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line9">9</a> attribute :action </pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line10">10</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line11">11</a> index :client</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line12">12</a> index :event</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line13">13</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line14">14</a> def validate</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line15">15</a> assert_present :client, :endpoint, :event, :action</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line16">16</a> assert_unique [:client, :endpoint, :event, :action]</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line17">17</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line18">18</a> end</pre></td>
</tr>
</tbody>
</table>
<p>Generated on 2011-02-08 01:54:20 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>lib/noah.rb</title>
<link href="screen.css" media="all" rel="stylesheet" type="text/css" />
<link href="print.css" media="print" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript" src="rcov.js"></script>
</head>
<body>
<h1>Noah C0 Coverage Information - RCov</h1>
<h2>lib/noah.rb</h2>
<div class="report_table_wrapper">
<table class='report' id='report_table'>
<thead>
<tr>
<th class="left_align">Name</th>
<th class="right_align">Total Lines</th>
<th class="right_align">Lines of Code</th>
<th class="left_align">Total Coverage</th>
<th class="left_align">Code Coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left_align"><a href="lib-noah_rb.html">lib/noah.rb</a></td>
<td class='right_align'><tt>18</tt></td>
<td class='right_align'><tt>17</tt></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>83.33%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:83px"></div>
<div class="uncovered" style="width:17px"></div>
</div></td>
<td class="left_align"><div class="percent_graph_legend"><tt class=''>82.35%</tt></div>
<div class="percent_graph">
<div class="covered" style="width:82px"></div>
<div class="uncovered" style="width:18px"></div>
</div></td>
</tr>
</tbody>
</table>
</div>
<h3>Key</h3>
<div class="key"><pre><span class='marked'>Code reported as executed by Ruby looks like this...</span><span class='marked1'>and this: this line is also marked as covered.</span><span class='inferred'>Lines considered as run by rcov, but not reported by Ruby, look like this,</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).</span><span class='uncovered'>Finally, here's a line marked as not executed.</span></pre></div>
<h3>Coverage Details</h3>
<table class="details">
<tbody>
<tr class="uncovered">
<td><pre><a name="line1">1</a> require 'ohm'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line2">2</a> require 'ohm/contrib'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line3">3</a> begin</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line4">4</a> require 'yajl'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line5">5</a> rescue LoadError</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line6">6</a> require 'json'</pre></td>
</tr>
<tr class="inferred">
<td><pre><a name="line7">7</a> end</pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line8">8</a> require 'haml'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line9">9</a> require 'yaml'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line10">10</a> require 'sinatra/base'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line11">11</a> require 'sinatra/namespace'</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line12">12</a> </pre></td>
</tr>
<tr class="uncovered">
<td><pre><a name="line13">13</a> require File.join(File.dirname(__FILE__), 'noah','hosts')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line14">14</a> require File.join(File.dirname(__FILE__), 'noah','services')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line15">15</a> require File.join(File.dirname(__FILE__), 'noah','applications')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line16">16</a> require File.join(File.dirname(__FILE__), 'noah','configurations')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line17">17</a> require File.join(File.dirname(__FILE__), 'noah','watchers')</pre></td>
</tr>
<tr class="marked">
<td><pre><a name="line18">18</a> require File.join(File.dirname(__FILE__), 'noah','app')</pre></td>
</tr>
</tbody>
</table>
<p>Generated on 2011-02-08 01:54:21 -0500 with <a href="http://github.com/relevance/rcov">rcov 0.9.8</a></p>
</body>
</html>
/* Hide controls */
body {
color: #000000;
background-color: #ffffff;
}
/* Hide controls */
div.filters {
display: none;
}
\ No newline at end of file
function toggleCode( id ) {
if ( document.getElementById ) {
elem = document.getElementById( id );
} else if ( document.all ) {
elem = eval( "document.all." + id );
} else {
return false;
}
elemStyle = elem.style;
if ( elemStyle.display != "block" ) {
elemStyle.display = "block";
} else {
elemStyle.display = "none";
}
return true;
}
function restripe() {
i = 0;
$('table#report_table tbody tr').each(function(){
if (this.style.display != "none") {
i += 1;
classes = this.className.split(" ");
if ($.inArray("even",classes) != -1) {
classes.splice($.inArray("even",classes),1);
} else if ($.inArray("odd",classes) != -1) {
classes.splice($.inArray("odd",classes),1);
}
if (i % 2 === 0) {
this.className = classes.join(" ") + " odd";
} else {
this.className = classes.join(" ") + " even";
}
}
});
}
// Fix IE's lack of support for indexOf (!)
if (!Array.indexOf) { Array.prototype.indexOf = function(obj){ for(var i=0; i<this.length; i++){ if(this[i]==obj){return i;} } return -1; }}
\ No newline at end of file
/* @group General */
body {
font-family: Verdana, Helvetica, Arial, Sans-Serif;
font-size: 12px;
color: #4C4C4C;
background-color: #F4F2ED;
padding: 1em;
}
a:link {
color: #191919;
}
a:visited {
color: #191919;
}
pre, code {
color: #000000;
font-family: "Bitstream Vera Sans Mono","Monaco","Courier New",monospace;
font-size: 95%;
line-height: 1.3em;
margin-top: 0;
margin-bottom: 0;
padding: 0;
word-wrap: break-word;
}
h1, h2, h3, h4, h5, h6 {
margin: 0em 0em 1em 0em;
color: #666666;
}
h1 {
display: block;
font-size: 2em;
letter-spacing: -1px;
}
h2 {
margin-top: -1em;
}
fieldset {
display: inline;
border: 0px;
padding: 0px;
margin-right: 1em;
}
div.filters {
margin-bottom: 1em;
}
.hidden {
display: none;
}
/* @end */
/* @group Cross-References */
span.cross-ref-title {
font-size: 140%;
}
span.cross-ref a {
text-decoration: none;
}
span.cross-ref {
background-color:#f3f7fa;
border: 1px dashed #333;
margin: 1em;
padding: 0.5em;
overflow: hidden;
}
a.crossref-toggle {
text-decoration: none;
}
/* @end */
/* @group Report Table */
div.report_table_wrapper {
min-width: 900px;
}
table.report {
border-collapse: collapse;
border: 1px solid #666666;
width: 100%;
margin-bottom: 1em;
}
table.report tr {
line-height: 1.75em;
}
table.report th {
background: #666666;
color: #ffffff;
text-align: right;
text-transform: uppercase;
font-size: .8em;
font-weight: bold;
padding: 0em .5em;
border: 1px solid #666666;
}
table.report tfoot tr {
background: #dddddd;
font-weight: bold;
padding: .5em;
border: 1px solid #666666;
}
th.left_align, td.left_align {
text-align: left !important;
}
th.right_align, td.right_align {
text-align: right;
padding-right: 2em !important;
}
table.report th.header:hover {
cursor: pointer;
text-decoration: underline;
}
table.report th.headerSortUp:after{
content: "\25BC";
margin-left: 1em;
}
table.report th.headerSortDown:after {
content: "\25B2";
margin-left: 1em;
}
table.report tr.summary_row {
background: #cccccc;
border: 1px solid #cccccc;
}
table.report tr.summary_row td {
padding-left: .2em !important;
color: #333333;
font-weight: bold;
}
table.report td {
padding: .2em .5em .2em .5em;
}
table.report td a {
text-decoration: none;
}
table.report tbody tr:hover {
background: #cccccc !important;
}
table.report tr.summary_row td {
border-bottom: 1px solid #aaaaaa;
}
table.report tr {
background-color: #eeeeee;
}
table.report tr.odd {
background-color: #dddddd;
}
/* @end */
/* @group Percentage Graphs */
div.percent_graph_legend {
width: 5.5em;
float: left;
margin: .5em 1em .5em 0em;
height: 1em;
line-height: 1em;
}
div.percent_graph {
height: 1em;
border: #333333 1px solid;
empty-cells: show;
padding: 0px;
border-collapse: collapse;
width: 100px !important;
float: left;
margin: .5em 1em .5em 0em;
}
div.percent_graph div {
float: left;
height: 1em;
padding: 0px !important;
}
div.percent_graph div.covered {
background: #649632;
}
div.percent_graph div.uncovered {
background: #a92730;
}
div.percent_graph div.NA {
background: #eaeaea;
}
/* @end */
/* @group Details page */
table.details {
margin-top: 1em;
border-collapse: collapse;
width: 100%;
border: 1px solid #666666;
}
table.details tr {
line-height: 1.75em;
}
table.details td {
padding: .25em;
}
span.inferred, span.inferred1, span.marked, span.marked1, span.uncovered, span.uncovered1 {
display: block;
padding: .25em;
}
tr.inferred td, span.inferred {
background-color: #e0dedb;
}
tr.inferred1 td, span.inferred1 {
background-color: #e0dedb;
}
tr.marked td, span.marked, span.marked1 {
background-color: #bed2be;
}
tr.uncovered td, span.uncovered {
background-color: #ce8b8c;
}
tr.uncovered1 td, span.uncovered1 {
background-color: #ce8b8c;
}
div.key {
border: 1px solid #666666;
margin: 1em 0em;
}
/* @end */
em-hiredis @ 0ce6400c
Subproject commit 0ce6400c5a8340ee923b3cbae46317372ead9334
...@@ -35,6 +35,7 @@ module Noah ...@@ -35,6 +35,7 @@ module Noah
channel = EventMachine::Channel.new channel = EventMachine::Channel.new
r = EventMachine::Hiredis::Client.connect r = EventMachine::Hiredis::Client.connect
r.db(5)
r.psubscribe(@my_pattern) r.psubscribe(@my_pattern)
r.on(:pmessage) do |pattern, event, message| r.on(:pmessage) do |pattern, event, message|
channel.push "#{message}" channel.push "#{message}"
......
...@@ -4,8 +4,6 @@ require File.join(File.dirname(__FILE__), 'models') ...@@ -4,8 +4,6 @@ require File.join(File.dirname(__FILE__), 'models')
module Noah module Noah
class App < Sinatra::Base class App < Sinatra::Base
register ::Sinatra::Namespace
helpers Noah::SinatraHelpers helpers Noah::SinatraHelpers
configure do configure do
...@@ -30,10 +28,20 @@ module Noah ...@@ -30,10 +28,20 @@ module Noah
end end
end end
# Need to move this out to configuration.
# Maybe bootstrap them from itself?
content_type_mapping = {
:yaml => "text/x-yaml",
:json => "application/json",
:xml => "text/xml",
:string => "text/plain"
}
before do before do
content_type "application/json" content_type "application/json"
end end
# Displays an overview page of all registered objects
get '/' do get '/' do
content_type "text/html" content_type "text/html"
...@@ -50,273 +58,248 @@ module Noah ...@@ -50,273 +58,248 @@ module Noah
erb :'500' erb :'500'
end end
# Placeholder for admin functions # GET named {Service} for named {Host}
namespace "/ark" do get '/h/:hostname/:servicename/?' do |hostname, servicename|
end h = host_service(hostname, servicename)
if h.nil?
# Placeholder for watchers halt 404
namespace "/w" do else
h.to_json
end
end end
namespace "/h" do # GET named {Host}
# @param :hostname name of {Host}
get '/:hostname/:servicename/?' do |hostname, servicename| # @return [JSON] representation of {Host}
h = host_service(hostname, servicename) get '/h/:hostname/?' do |hostname|
if h.nil? h = host(:name => hostname)
halt 404 if h.nil?
else halt 404
h.to_json else
end h.to_json
end
get '/:hostname/?' do |hostname|
h = host(:name => hostname)
if h.nil?
halt 404
else
h.to_json
end
end end
end
get '/?' do # GET all {Hosts}
hosts.map {|h| h.to_hash} get '/h/?' do
if hosts.size == 0 hosts.map {|h| h.to_hash}
halt 404 if hosts.size == 0
else halt 404
hosts.to_json else
end hosts.to_json
end end
end
put '/:hostname/?' do |hostname| put '/h/:hostname/?' do |hostname|
required_params = ["name", "status"] required_params = ["name", "status"]
data = JSON.parse(request.body.read) data = JSON.parse(request.body.read)
(data.keys.sort == required_params.sort && data['name'] == hostname) ? (host = ::Host.find_or_create(:name => data['name'], :status => data['status'])) : (raise "Missing Parameters") (data.keys.sort == required_params.sort && data['name'] == hostname) ? (host = ::Host.find_or_create(:name => data['name'], :status => data['status'])) : (raise "Missing Parameters")
if host.valid? if host.valid?
r = {"result" => "success","id" => "#{host.id}","status" => "#{host.status}", "name" => "#{host.name}", "new_record" => host.is_new?} r = {"result" => "success","id" => "#{host.id}","status" => "#{host.status}", "name" => "#{host.name}", "new_record" => host.is_new?}
r.to_json r.to_json
else else
raise "#{host.errors}" raise "#{host.errors}"
end
end end
end
delete '/:hostname/?' do |hostname| delete '/h/:hostname/?' do |hostname|
host = ::Host.find(:name => hostname).first host = ::Host.find(:name => hostname).first
if host if host
services = [] services = []
Service.find(:host_id => host.id).sort.each {|x| services << x; x.delete} if host.services.size > 0 Service.find(:host_id => host.id).sort.each {|x| services << x; x.delete} if host.services.size > 0
host.delete host.delete
r = {"result" => "success", "id" => "#{host.id}", "name" => "#{hostname}", "service_count" => "#{services.size}"} r = {"result" => "success", "id" => "#{host.id}", "name" => "#{hostname}", "service_count" => "#{services.size}"}
r.to_json r.to_json
else else
halt 404 halt 404
end
end end
end end
namespace "/s" do # Service URIs
get '/:servicename/:hostname/?' do |servicename, hostname|
hs = host_service(hostname, servicename)
if hs.nil?
halt 404
else
hs.to_json
end
end
get '/:servicename/?' do |servicename| # get named {Service} for named {Host}
s = services(:name => servicename) get '/s/:servicename/:hostname/?' do |servicename, hostname|
s.map {|x| x.to_hash} hs = host_service(hostname, servicename)
if s.empty? if hs.nil?
halt 404 halt 404
else else
s.to_json hs.to_json
end end
end end
get '/?' do get '/s/:servicename/?' do |servicename|
if services.empty? s = services(:name => servicename)
halt 404 s.map {|x| x.to_hash}
else if s.empty?
services.map {|s| s.to_hash} halt 404
services.to_json else
end s.to_json
end end
end
put '/:servicename/?' do |servicename| get '/s/?' do
required_params = ["status", "host", "name"] if services.empty?
data = JSON.parse(request.body.read) halt 404
if data.keys.sort == required_params.sort else
h = ::Host.find(:name => data['host']).first || (raise "Invalid Host") services.map {|s| s.to_hash}
service = ::Service.find_or_create(:name => servicename, :status => data['status'], :host => h) services.to_json
if service.valid? end
action = service.is_new? ? "create" : "update" end
service.save
r = {"action" => action, "result" => "success", "id" => service.id, "host" => h.name, "name" => service.name}
r.to_json
else
raise "#{service.errors}"
end
else
raise "Missing Parameters"
end
end
delete '/:servicename/:hostname/?' do |servicename, hostname| put '/s/:servicename/?' do |servicename|
host = ::Host.find(:name => hostname).first || (halt 404) required_params = ["status", "host", "name"]
service = ::Service.find(:name => servicename, :host_id => host.id).first || (halt 404) data = JSON.parse(request.body.read)
if host && service if data.keys.sort == required_params.sort
service.delete h = ::Host.find(:name => data['host']).first || (raise "Invalid Host")
r = {"action" => "delete", "result" => "success", "id" => service.id, "host" => host.name, "service" => servicename} service = ::Service.find_or_create(:name => servicename, :status => data['status'], :host => h)
if service.valid?
action = service.is_new? ? "create" : "update"
service.save
r = {"action" => action, "result" => "success", "id" => service.id, "host" => h.name, "name" => service.name}
r.to_json r.to_json
else else
halt 404 raise "#{service.errors}"
end end
else
raise "Missing Parameters"
end end
end end
namespace "/a" do delete '/s/:servicename/:hostname/?' do |servicename, hostname|
host = ::Host.find(:name => hostname).first || (halt 404)
get '/:appname/:config/?' do |appname, config| service = ::Service.find(:name => servicename, :host_id => host.id).first || (halt 404)
app = ::Application.find(:name => appname).first if host && service
if app.nil? service.delete
halt 404 r = {"action" => "delete", "result" => "success", "id" => service.id, "host" => host.name, "service" => servicename}
else r.to_json
c = ::Configuration.find(:name => config, :application_id => app.id).first else
c.to_json halt 404
end end
end end
get '/a/:appname/:config/?' do |appname, config|
app = ::Application.find(:name => appname).first
if app.nil?
halt 404
else
c = ::Configuration.find(:name => config, :application_id => app.id).first
c.to_json
end
end
get '/:appname/?' do |appname| get '/a/:appname/?' do |appname|
app = ::Application.find(:name => appname).first app = ::Application.find(:name => appname).first
if app.nil? if app.nil?
halt 404 halt 404
else else
app.to_json app.to_json
end
end
put '/:appname/?' do |appname|
required_params = ["name"]
data = JSON.parse(request.body.read)
if data.keys.sort == required_params.sort && data['name'] == appname
app = ::Application.find_or_create(:name => appname)
else
raise "Missing Parameters"
end
if app.valid?
action = app.is_new? ? "create" : "update"
app.save
r = {"result" => "success","id" => app.id, "action" => action, "name" => app.name }
r.to_json
else
raise "#{app.errors}"
end
end end
end
delete '/:appname/?' do |appname| put '/a/:appname/?' do |appname|
app = ::Application.find(:name => appname).first required_params = ["name"]
if app.nil? data = JSON.parse(request.body.read)
halt 404 if data.keys.sort == required_params.sort && data['name'] == appname
else app = ::Application.find_or_create(:name => appname)
configurations = [] else
::Configuration.find(:application_id => app.id).sort.each {|x| configurations << x; x.delete} if app.configurations.size > 0 raise "Missing Parameters"
app.delete end
r = {"result" => "success", "action" => "delete", "id" => "#{app.id}", "name" => "#{appname}", "configurations" => "#{configurations.size}"} if app.valid?
r.to_json action = app.is_new? ? "create" : "update"
end app.save
r = {"result" => "success","id" => app.id, "action" => action, "name" => app.name }
r.to_json
else
raise "#{app.errors}"
end end
end
get '/?' do delete '/a/:appname/?' do |appname|
apps = [] app = ::Application.find(:name => appname).first
::Application.all.sort.each {|a| apps << a.to_hash} if app.nil?
if apps.empty? halt 404
halt 404 else
else configurations = []
apps.to_json ::Configuration.find(:application_id => app.id).sort.each {|x| configurations << x; x.delete} if app.configurations.size > 0
end app.delete
r = {"result" => "success", "action" => "delete", "id" => "#{app.id}", "name" => "#{appname}", "configurations" => "#{configurations.size}"}
r.to_json
end end
end end
namespace '/c' do get '/a/?' do
apps = []
::Application.all.sort.each {|a| apps << a.to_hash}
if apps.empty?
halt 404
else
apps.to_json
end
end
# Need to move this out to configuration. get '/c/:appname/:element/?' do |appname, element|
# Maybe bootstrap them from itself? a = ::Application.find(:name => appname).first
content_type_mapping = { if a.nil?
:yaml => "text/x-yaml", halt 404
:json => "application/json", else
:xml => "text/xml", c = ::Configuration.find(:name => element, :application_id => a.id).first
:string => "text/plain" content_type content_type_mapping[c.format.to_sym] if content_type_mapping[c.format.to_sym]
} c.body
end
end
get '/:appname/:element/?' do |appname, element| get '/c/:appname/?' do |appname|
a = ::Application.find(:name => appname).first config = []
if a.nil? a = ::Application.find(:name => appname).first
halt 404 if a.nil?
else halt 404
c = ::Configuration.find(:name => element, :application_id => a.id).first else
content_type content_type_mapping[c.format.to_sym] if content_type_mapping[c.format.to_sym] ::Configuration.find(:application_id => a.id).sort.each {|c| config << c.to_hash}
c.body config.to_json
end end
end end
get '/:appname/?' do |appname| get '/c/?' do
config = [] configs = []
a = ::Application.find(:name => appname).first ::Configuration.all.sort.each {|c| configs << c.to_hash}
if a.nil? if configs.empty?
halt 404 halt 404
else else
::Configuration.find(:application_id => a.id).sort.each {|c| config << c.to_hash} configs.to_json
config.to_json end
end end
end
get '/?' do put '/c/:appname/:element?' do |appname, element|
configs = [] app = ::Application.find_or_create(:name => appname)
::Configuration.all.sort.each {|c| configs << c.to_hash} config = ::Configuration.find_or_create(:name => element, :application_id => app.id)
if configs.empty? required_params = ["format", "body"]
halt 404 data = JSON.parse(request.body.read)
else data.keys.sort == required_params.sort ? (config.format = data["format"]; config.body = data["body"]) : (raise "Missing Parameters")
configs.to_json if config.valid?
end config.save
action = config.is_new? ? "create" : "update"
dependency_action = app.is_new? ? "created" : "updated"
r = {"result" => "success","id" => "#{config.id}", "action" => action, "dependencies" => dependency_action, "application" => app.name, "item" => config.name}
r.to_json
else
raise "#{config.errors}"
end end
end
put '/:appname/:element?' do |appname, element| delete '/c/:appname/:element?' do |appname, element|
app = ::Application.find_or_create(:name => appname) app = ::Application.find(:name => appname).first
config = ::Configuration.find_or_create(:name => element, :application_id => app.id) if app
required_params = ["format", "body"] config = ::Configuration.find(:name=> element, :application_id => app.id).first
data = JSON.parse(request.body.read) if config
data.keys.sort == required_params.sort ? (config.format = data["format"]; config.body = data["body"]) : (raise "Missing Parameters") config.delete
if config.valid? r = {"result" => "success", "id" => "#{config.id}", "action" => "delete", "application" => "#{app.name}", "item" => "#{element}"}
config.save
action = config.is_new? ? "create" : "update"
dependency_action = app.is_new? ? "created" : "updated"
r = {"result" => "success","id" => "#{config.id}", "action" => action, "dependencies" => dependency_action, "application" => app.name, "item" => config.name}
r.to_json r.to_json
else
raise "#{config.errors}"
end
end
delete '/:appname/:element?' do |appname, element|
app = ::Application.find(:name => appname).first
if app
config = ::Configuration.find(:name=> element, :application_id => app.id).first
if config
config.delete
r = {"result" => "success", "id" => "#{config.id}", "action" => "delete", "application" => "#{app.name}", "item" => "#{element}"}
r.to_json
else
halt 404
end
else else
halt 404 halt 404
end end
else
halt 404
end end
end end
end end
end end
class Host < Ohm::Model class Host < Ohm::Model
# Host model
# @return {Host} a {Host} object
include Ohm::Typecast include Ohm::Typecast
include Ohm::Timestamping include Ohm::Timestamping
include Ohm::Callbacks include Ohm::Callbacks
...@@ -25,6 +27,7 @@ class Host < Ohm::Model ...@@ -25,6 +27,7 @@ class Host < Ohm::Model
assert_member :status, ["up","down","pending"] assert_member :status, ["up","down","pending"]
end end
# @return [Hash] A hash representation of a {Host}
def to_hash def to_hash
arr = [] arr = []
services.sort.each {|s| arr << s.to_hash} services.sort.each {|s| arr << s.to_hash}
...@@ -32,6 +35,7 @@ class Host < Ohm::Model ...@@ -32,6 +35,7 @@ class Host < Ohm::Model
super.merge(h) super.merge(h)
end end
# Evaluate if {Host} record is new or not
def is_new? def is_new?
self.created_at == self.updated_at self.created_at == self.updated_at
end end
...@@ -54,6 +58,7 @@ class Host < Ohm::Model ...@@ -54,6 +58,7 @@ class Host < Ohm::Model
end end
protected protected
# Saves the original {Host#name} attribute before deleting an object
def stash_name def stash_name
@deleted_name = self.name @deleted_name = self.name
end end
...@@ -70,6 +75,8 @@ class Host < Ohm::Model ...@@ -70,6 +75,8 @@ class Host < Ohm::Model
end end
class Hosts class Hosts
# @param [Hash] optional filters for results
# @return [Array] Array of {Host} objects
def self.all(options = {}) def self.all(options = {})
options.empty? ? Host.all.sort : Host.find(options).sort options.empty? ? Host.all.sort : Host.find(options).sort
end end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment