├── lib
├── turbulence
│ ├── version.rb
│ ├── checks_environment.rb
│ ├── scm
│ │ ├── git.rb
│ │ └── perforce.rb
│ ├── file_name_mangler.rb
│ ├── configuration.rb
│ ├── calculators
│ │ ├── complexity.rb
│ │ └── churn.rb
│ ├── generators
│ │ ├── treemap.rb
│ │ └── scatterplot.rb
│ ├── cli_parser.rb
│ └── command_line_interface.rb
└── turbulence.rb
├── .travis.yml
├── Gemfile
├── .gitignore
├── win_rakefile_location_fix.rb
├── Rakefile
├── spec
└── turbulence
│ ├── configuration_spec.rb
│ ├── turbulence_spec.rb
│ ├── calculators
│ ├── complexity_spec.rb
│ └── churn_spec.rb
│ ├── generators
│ ├── treemap_spec.rb
│ └── scatter_plot_spec.rb
│ ├── scm
│ ├── git_spec.rb
│ └── perforce_spec.rb
│ ├── cli_parser_spec.rb
│ └── command_line_interface_spec.rb
├── bin
└── bule
├── Gemfile.lock
├── template
├── treemap.html
├── highchart_template.js.erb
├── turbulence.html
├── highcharts.js
└── jquery.min.js
├── LICENSE.txt
├── turbulence.gemspec
└── README.md
/lib/turbulence/version.rb:
--------------------------------------------------------------------------------
1 | class Turbulence
2 | VERSION = "1.2.4"
3 | end
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | rvm:
2 | - "1.9.3"
3 | - "1.9.2"
4 | - "1.8.7"
5 | - jruby-18mode
6 | - jruby-19mode
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 |
3 | # Specify your gem's dependencies in turbulence.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .DS_Store
3 | pkg/*
4 | *.gem
5 | *.swp
6 | .bundle
7 | .rvmrc
8 | turbulence/*
9 | tmp/*
10 |
--------------------------------------------------------------------------------
/win_rakefile_location_fix.rb:
--------------------------------------------------------------------------------
1 | class Rake::Application
2 | def rakefile_location(*)
3 | bt = caller
4 | bt.map { |t| t[/([^:]+):/,1] }
5 | bt.find {|str| str =~ /^#{@rakefile}$/ } || ""
6 | end
7 | end
8 |
9 |
--------------------------------------------------------------------------------
/lib/turbulence/checks_environment.rb:
--------------------------------------------------------------------------------
1 | class Turbulence
2 | class ChecksEnvironment
3 | class << self
4 | def scm_repo?(directory)
5 | churn_calculator = Turbulence::Calculators::Churn.new
6 | churn_calculator.scm.is_repo?(directory)
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'bundler'
2 | require File.join(File.dirname(__FILE__), 'win_rakefile_location_fix')
3 |
4 | Bundler::GemHelper.install_tasks
5 |
6 | require 'rake'
7 | require 'rspec/core/rake_task'
8 |
9 | RSpec::Core::RakeTask.new(:spec) do |t|
10 | t.skip_bundler = true
11 | end
12 |
13 | task :default => [:spec]
14 |
--------------------------------------------------------------------------------
/spec/turbulence/configuration_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rspec'
2 | require 'turbulence'
3 |
4 | describe Turbulence::Configuration do
5 | describe "defaults" do
6 | its(:output) { should eq(STDOUT) }
7 | its(:directory) { should eq(Dir.pwd) }
8 | its(:graph_type) { should eq('turbulence') }
9 | its(:scm_name) { should eq('Git') }
10 | its(:scm) { should eq(Turbulence::Scm::Git) }
11 | end
12 | end
13 |
14 |
--------------------------------------------------------------------------------
/bin/bule:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'turbulence'
3 | require 'turbulence/checks_environment'
4 |
5 | cli = Turbulence::CommandLineInterface.new(ARGV)
6 |
7 | unless Turbulence::ChecksEnvironment.scm_repo?(Dir.pwd)
8 | STDERR.puts "Turbulence could not calculate metrics, as we could not find a repository in the current directory."
9 | STDERR.puts "Please run bule from inside a repository."
10 | exit
11 | end
12 |
13 | cli.generate_bundle
14 | cli.open_bundle
15 |
--------------------------------------------------------------------------------
/lib/turbulence/scm/git.rb:
--------------------------------------------------------------------------------
1 | class Turbulence
2 | module Scm
3 | class Git
4 | class << self
5 | def log_command(commit_range = "")
6 | `git log --all -M -C --numstat --format="%n" #{commit_range}`
7 | end
8 |
9 | def is_repo?(directory)
10 | FileUtils.cd(directory) {
11 | return !(`git status 2>&1` =~ /Not a git repository/)
12 | }
13 | end
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/turbulence/file_name_mangler.rb:
--------------------------------------------------------------------------------
1 | require 'json'
2 |
3 | class Turbulence
4 | class FileNameMangler
5 | def initialize
6 | @current_id = 0
7 | @segment_map = { "" => "", "app" => "app", "controllers" => "controllers", "helpers" => "helpers", "lib" => "lib" }
8 | end
9 |
10 | def transform(segment)
11 | @segment_map[segment] ||= (@current_id += 1)
12 | end
13 |
14 | def mangle_name(filename)
15 | filename.split('/').map {|seg|transform(seg)}.join('/') + ".rb"
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/lib/turbulence/configuration.rb:
--------------------------------------------------------------------------------
1 | require 'ostruct'
2 |
3 | class Turbulence
4 | class Configuration
5 | attr_accessor *[
6 | :directory,
7 | :scm,
8 | :scm_name,
9 | :commit_range,
10 | :compute_mean,
11 | :exclusion_pattern,
12 | :graph_type,
13 | :output,
14 | ]
15 |
16 | def initialize
17 | @directory = Dir.pwd
18 | @graph_type = 'turbulence'
19 | @scm_name = 'Git'
20 | @output = STDOUT
21 | end
22 |
23 | # TODO: drop attr accessor and ivar once it stops getting set via Churn
24 | def scm
25 | @scm || Turbulence::Scm.const_get(scm_name)
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/turbulence/turbulence_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rspec'
2 | require 'turbulence'
3 |
4 | describe Turbulence do
5 | subject(:turb) { Turbulence.new(config) }
6 |
7 | let(:config) {
8 | Turbulence::Configuration.new.tap do |config|
9 | config.directory = '.'
10 | config.exclusion_pattern = nil
11 | config.output = nil
12 | end
13 | }
14 |
15 | it "finds files of interest" do
16 | turb.files_of_interest.should include "lib/turbulence.rb"
17 | end
18 |
19 | it "filters out exluded files" do
20 | config.exclusion_pattern = 'turbulence'
21 | turb.files_of_interest.should_not include "lib/turbulence.rb"
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/turbulence/calculators/complexity_spec.rb:
--------------------------------------------------------------------------------
1 | require 'turbulence/calculators/complexity'
2 |
3 | describe Turbulence::Calculators::Complexity do
4 | let(:calculator) { Turbulence::Calculators::Complexity.new(config) }
5 | let(:config) { Turbulence::Configuration.new }
6 |
7 | describe "::for_these_files" do
8 | it "yields up the filename and score for each file" do
9 | files = ["lib/corey.rb", "lib/chad.rb"]
10 | calculator.stub(:score_for_file) { |filename|
11 | filename.size
12 | }
13 | yielded_files = []
14 | calculator.for_these_files(files) do |filename, score|
15 | yielded_files << [filename, score]
16 | end
17 | yielded_files.should =~ [["lib/corey.rb", 12],
18 | ["lib/chad.rb",11]]
19 | end
20 | end
21 | end
22 |
23 |
--------------------------------------------------------------------------------
/spec/turbulence/generators/treemap_spec.rb:
--------------------------------------------------------------------------------
1 | require 'turbulence'
2 |
3 | describe Turbulence::Generators::TreeMap do
4 | context "with both Metrics" do
5 | it "generates JavaScript" do
6 | generator = Turbulence::Generators::TreeMap.new(
7 | "foo.rb" => { :churn => 1,
8 | :complexity => 2 }
9 | )
10 |
11 | generator.build_js.should =~ /var treemap_data/
12 | generator.build_js.should =~ /\'foo.rb\'/
13 | end
14 | end
15 |
16 | context "with a missing Metric" do
17 | it "generates JavaScript" do
18 | generator = Turbulence::Generators::TreeMap.new(
19 | "foo.rb" => { :churn => 1 }
20 | )
21 |
22 | generator.build_js.should == "var treemap_data = [['File', 'Parent', 'Churn (size)', 'Complexity (color)'],\n['Root', null, 0, 0],\n];"
23 | end
24 | end
25 | end
26 |
27 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: .
3 | specs:
4 | turbulence (1.2.4)
5 | flog (~> 4.1)
6 | json (>= 1.4.6)
7 | launchy (>= 2.0.0)
8 |
9 | GEM
10 | remote: http://rubygems.org/
11 | specs:
12 | addressable (2.3.6)
13 | diff-lcs (1.2.5)
14 | flog (4.2.1)
15 | ruby_parser (~> 3.1, > 3.1.0)
16 | sexp_processor (~> 4.4)
17 | json (1.8.1)
18 | launchy (2.4.2)
19 | addressable (~> 2.3)
20 | rake (10.1.0)
21 | rspec (2.14.1)
22 | rspec-core (~> 2.14.0)
23 | rspec-expectations (~> 2.14.0)
24 | rspec-mocks (~> 2.14.0)
25 | rspec-core (2.14.7)
26 | rspec-expectations (2.14.4)
27 | diff-lcs (>= 1.1.3, < 2.0)
28 | rspec-mocks (2.14.4)
29 | ruby_parser (3.6.1)
30 | sexp_processor (~> 4.1)
31 | sexp_processor (4.4.3)
32 |
33 | PLATFORMS
34 | ruby
35 |
36 | DEPENDENCIES
37 | rake
38 | rspec (~> 2.14.0)
39 | turbulence!
40 |
--------------------------------------------------------------------------------
/spec/turbulence/scm/git_spec.rb:
--------------------------------------------------------------------------------
1 | require 'turbulence/scm/git'
2 | require 'tmpdir'
3 | require 'fileutils'
4 |
5 | describe Turbulence::Scm::Git do
6 | describe "::is_repo?" do
7 | before do
8 | @tmp = Dir.mktmpdir(nil,'..')
9 | end
10 | after do
11 | FileUtils.rmdir(@tmp)
12 | end
13 | it "returns true for the working directory" do
14 | Turbulence::Scm::Git.is_repo?(".").should == true
15 | end
16 | it "return false for a newly created tmp directory" do
17 | Turbulence::Scm::Git.is_repo?(@tmp).should == false
18 | end
19 | end
20 |
21 | describe "::log_command" do
22 | it "takes an optional argument specify to the range" do
23 | expect{Turbulence::Scm::Git.log_command("d551e63f79a90430e560ea871f4e1e39e6e739bd HEAD")}.to_not raise_error
24 | end
25 | it "lists insertions/deletions per file and change" do
26 | Turbulence::Scm::Git.log_command.should match(/\d+\t\d+\t[A-z.]*/)
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/template/treemap.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2023 Kerri Miller, Chad Fowler
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/lib/turbulence/calculators/complexity.rb:
--------------------------------------------------------------------------------
1 | require 'stringio'
2 | require 'flog'
3 |
4 | class Ruby19Parser < RubyParser
5 | def process(ruby, file)
6 | ruby.gsub!(/(\w+):\s+/, '"\1" =>')
7 | super(ruby, file)
8 | end
9 | end unless defined?(:Ruby19Parser)
10 |
11 | class Flog19 < Flog
12 | def initialize option = {}
13 | super(option)
14 | @parser = Ruby19Parser.new
15 | end
16 | end
17 |
18 | class Turbulence
19 | module Calculators
20 | class Complexity
21 | attr_reader :config, :type
22 |
23 | def initialize(config = nil)
24 | @config = config || Turbulence.config
25 | @type = :complexity
26 | end
27 |
28 | def flogger
29 | @flogger ||= Flog19.new(:continue => true)
30 | end
31 |
32 | def for_these_files(files)
33 | files.each do |filename|
34 | yield filename, score_for_file(filename)
35 | end
36 | end
37 |
38 | def score_for_file(filename)
39 | flogger.reset
40 | flogger.flog filename
41 | flogger.total_score
42 | end
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/spec/turbulence/cli_parser_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rspec'
2 | require 'turbulence'
3 |
4 | describe Turbulence::CommandLineInterface::ConfigParser do
5 | let(:config) { Turbulence::Configuration.new }
6 |
7 | def parse(argv)
8 | described_class.parse_argv_into_config(argv, config)
9 | end
10 |
11 | it "sets directory" do
12 | parse %w( path/to/compute )
13 | config.directory.should == 'path/to/compute'
14 | end
15 |
16 | it "sets SCM name to 'Perforce'" do
17 | parse %w( --scm p4 )
18 | config.scm_name.should == 'Perforce'
19 | end
20 |
21 | it "sets commit range" do
22 | parse %w( --churn-range f3e1d7a6..830b9d3d9f )
23 | config.commit_range.should eq('f3e1d7a6..830b9d3d9f')
24 | end
25 |
26 | it "sets compute mean" do
27 | parse %w( --churn-mean )
28 | config.compute_mean.should be_true
29 | end
30 |
31 | it "sets the exclusion pattern" do
32 | parse %w( --exclude turbulence )
33 | config.exclusion_pattern.should == 'turbulence'
34 | end
35 |
36 | it "sets the graph type" do
37 | parse %w( --treemap )
38 | config.graph_type.should == 'treemap'
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/turbulence.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 | $:.push File.expand_path("../lib", __FILE__)
3 | require "turbulence/version"
4 |
5 | Gem::Specification.new do |s|
6 | s.name = "turbulence"
7 | s.version = Turbulence::VERSION
8 | s.platform = Gem::Platform::RUBY
9 | s.authors = ["Chad Fowler", "Michael Feathers", "Corey Haines"]
10 | s.email = ["chad@chadfowler.com", "mfeathers@obtiva.com", "coreyhaines@gmail.com"]
11 | s.homepage = "http://chadfowler.com"
12 | s.add_dependency "flog", "~>4.1"
13 | s.add_dependency "json", ">= 1.4.6"
14 | s.add_dependency "launchy", ">= 2.0.0"
15 | s.add_development_dependency 'rspec', '~> 2.14.0'
16 | s.add_development_dependency 'rake'
17 |
18 | s.summary = %q{Automates churn + flog scoring on a git repo for a Ruby project}
19 | s.description = %q{Automates churn + flog scoring on a git repo for a Ruby project. Based on the article https://www.stickyminds.com/article/getting-empirical-about-refactoring}
20 |
21 | s.files = `git ls-files`.split("\n")
22 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24 | s.require_paths = ["lib"]
25 | s.required_ruby_version = '>= 1.8.7'
26 | end
27 |
--------------------------------------------------------------------------------
/spec/turbulence/command_line_interface_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rspec'
2 | require 'turbulence'
3 |
4 | describe Turbulence::CommandLineInterface do
5 | let(:cli) { Turbulence::CommandLineInterface.new(%w(.), :output => nil) }
6 |
7 | describe "::TEMPLATE_FILES" do
8 | Turbulence::CommandLineInterface::TEMPLATE_FILES.each do |template_file|
9 | File.dirname(template_file).should == Turbulence::CommandLineInterface::TURBULENCE_TEMPLATE_PATH
10 | end
11 | end
12 |
13 | describe "#generate_bundle" do
14 | before do
15 | FileUtils.remove_dir("turbulence", true)
16 | end
17 | it "bundles the files" do
18 | cli.generate_bundle
19 | Dir.glob('turbulence/*').sort.should eq(["turbulence/cc.js",
20 | "turbulence/highcharts.js",
21 | "turbulence/jquery.min.js",
22 | "turbulence/treemap.html",
23 | "turbulence/turbulence.html"])
24 | end
25 |
26 | it "passes along exclusion pattern" do
27 | cli = Turbulence::CommandLineInterface.new(%w(--exclude turbulence), :output => nil)
28 | cli.generate_bundle
29 | lines = File.new('turbulence/cc.js').readlines
30 | lines.any? { |l| l =~ /turbulence\.rb/ }.should be_false
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/turbulence/generators/treemap.rb:
--------------------------------------------------------------------------------
1 | class Turbulence
2 | module Generators
3 | class TreeMap
4 | attr_reader :metrics_hash, :x_metric, :y_metric
5 |
6 | def initialize(metrics_hash,
7 | x_metric = :churn,
8 | y_metric = :complexity)
9 | @x_metric = x_metric
10 | @y_metric = y_metric
11 | @metrics_hash = metrics_hash
12 | end
13 |
14 | def generate_results(metrics, cli)
15 | File.open("treemap_data.js", "w") do |f|
16 | cli.copy_templates_into(Dir.pwd)
17 | f.write Turbulence::Generators::TreeMap.from(metrics).build_js
18 | end
19 | end
20 |
21 | def build_js
22 | clean_metrics_from_missing_data
23 |
24 | output = "var treemap_data = [['File', 'Parent', 'Churn (size)', 'Complexity (color)'],\n"
25 | output << "['Root', null, 0, 0],\n"
26 |
27 | @metrics_hash.each do |file|
28 | output << "['#{file[0]}', 'Root', #{file[1][@x_metric]}, #{file[1][@y_metric]}],\n"
29 | end
30 |
31 | output << "];"
32 |
33 | output
34 | end
35 |
36 | private
37 | def clean_metrics_from_missing_data
38 | @metrics_hash.reject! do |filename, metrics|
39 | metrics[@x_metric].nil? || metrics[@y_metric].nil?
40 | end
41 | end
42 |
43 | def self.from(metrics_hash)
44 | new(metrics_hash)
45 | end
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/template/highchart_template.js.erb:
--------------------------------------------------------------------------------
1 | var chart;
2 | $(document).ready(function() {
3 | chart = new Highcharts.Chart({
4 | chart: {
5 | renderTo: 'container',
6 | defaultSeriesType: 'scatter',
7 | zoomType: 'xy'
8 | },
9 | title: {
10 | text: 'Height Versus Weight of 507 Individuals by Gender'
11 | },
12 | subtitle: {
13 | text: 'Source: Heinz 2003'
14 | },
15 | xAxis: {
16 | title: {
17 | enabled: true,
18 | text: 'Height (cm)'
19 | },
20 | startOnTick: true,
21 | endOnTick: true,
22 | showLastLabel: true
23 | },
24 | yAxis: {
25 | title: {
26 | text: 'Weight (kg)'
27 | }
28 | },
29 |
30 | plotOptions: {
31 | scatter: {
32 | marker: {
33 | radius: 5,
34 | states: {
35 | hover: {
36 | enabled: true,
37 | lineColor: 'rgb(100,100,100)'
38 | }
39 | }
40 | },
41 | states: {
42 | hover: {
43 | marker: {
44 | enabled: false
45 | }
46 | }
47 | }
48 | }
49 | },
50 | series: [{
51 | name: 'Files',
52 | color: 'rgba(223, 83, 83, .5)',
53 | data: <%= data_in_json_format %>
54 |
55 | }]
56 | });
57 |
58 |
59 | });
60 |
61 |
--------------------------------------------------------------------------------
/lib/turbulence/cli_parser.rb:
--------------------------------------------------------------------------------
1 | class Turbulence
2 | class CommandLineInterface
3 | # I Update a Turbulence::Configuration instance to match the user's
4 | # expectations (as expressed in ARGV)
5 | module ConfigParser
6 | def self.parse_argv_into_config(argv, config)
7 | option_parser = OptionParser.new do |opts|
8 | opts.banner = "Usage: bule [options] [dir]"
9 |
10 | opts.on('--scm p4|git', String, 'scm to use (default: git)') do |s|
11 | case s
12 | when "git", "", nil
13 | when "p4"
14 | config.scm_name = 'Perforce'
15 | end
16 | end
17 |
18 | opts.on('--churn-range since..until', String, 'commit range to compute file churn') do |s|
19 | config.commit_range = s
20 | end
21 |
22 | opts.on('--churn-mean', 'calculate mean churn instead of cummulative') do
23 | config.compute_mean = true
24 | end
25 |
26 | opts.on('--exclude pattern', String, 'exclude files matching pattern') do |pattern|
27 | config.exclusion_pattern = pattern
28 | end
29 |
30 | opts.on('--treemap', String, 'output treemap graph instead of scatterplot') do |s|
31 | config.graph_type = "treemap"
32 | end
33 |
34 |
35 | opts.on_tail("-h", "--help", "Show this message") do
36 | puts opts
37 | exit
38 | end
39 | end
40 | option_parser.parse!(argv)
41 |
42 | config.directory = argv.first unless argv.empty?
43 | end
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/lib/turbulence/command_line_interface.rb:
--------------------------------------------------------------------------------
1 | require 'fileutils'
2 | require 'launchy'
3 | require 'optparse'
4 | require 'forwardable'
5 |
6 | require 'turbulence/configuration'
7 | require 'turbulence/cli_parser'
8 | require 'turbulence/scm/git'
9 | require 'turbulence/scm/perforce'
10 |
11 | class Turbulence
12 | class CommandLineInterface
13 | TURBULENCE_TEMPLATE_PATH = File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "template")
14 | TEMPLATE_FILES = [
15 | 'turbulence.html',
16 | 'highcharts.js',
17 | 'jquery.min.js',
18 | 'treemap.html',
19 | ].map do |filename|
20 | File.join(TURBULENCE_TEMPLATE_PATH, filename)
21 | end
22 |
23 | def initialize(argv, additional_options = {})
24 | ConfigParser.parse_argv_into_config argv, config
25 | config.output = additional_options.fetch(:output, STDOUT)
26 | end
27 |
28 | extend Forwardable
29 | def_delegators :Turbulence, :config
30 | def_delegators :config, *[
31 | :directory,
32 | :graph_type,
33 | :exclusion_pattern,
34 | ]
35 |
36 | def copy_templates_into(directory)
37 | FileUtils.cp TEMPLATE_FILES, directory
38 | end
39 |
40 | def generate_bundle
41 | FileUtils.mkdir_p("turbulence")
42 |
43 | Dir.chdir("turbulence") do
44 | turb = Turbulence.new(config)
45 |
46 | generator = case graph_type
47 | when "treemap"
48 | Turbulence::Generators::TreeMap.new({})
49 | else
50 | Turbulence::Generators::ScatterPlot.new({})
51 | end
52 |
53 | generator.generate_results(turb.metrics, self)
54 | end
55 | end
56 |
57 | def open_bundle
58 | Launchy.open("file:///#{directory}/turbulence/#{graph_type}.html")
59 | end
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/lib/turbulence/calculators/churn.rb:
--------------------------------------------------------------------------------
1 | require 'forwardable'
2 |
3 | class Turbulence
4 | module Calculators
5 | class Churn
6 | RUBY_FILE_EXTENSION = ".rb"
7 |
8 | attr_reader :config, :type
9 |
10 | def initialize(config = nil)
11 | @config = config || Turbulence.config
12 | @type = :churn
13 | end
14 |
15 | extend Forwardable
16 | def_delegators :config, *[
17 | :scm, :scm=,
18 | :commit_range, :commit_range=,
19 | :compute_mean, :compute_mean=,
20 | ]
21 |
22 | def for_these_files(files)
23 | changes_by_ruby_file.each do |filename, count|
24 | yield filename, count if files.include?(filename)
25 | end
26 | end
27 |
28 | def changes_by_ruby_file
29 | ruby_files_changed_in_scm.group_by(&:first).map do |filename, stats|
30 | churn_for_file(filename,stats)
31 | end
32 | end
33 |
34 | def churn_for_file(filename,stats)
35 | churn = stats[0..-2].map(&:last).inject(0){|running_total, changes| running_total + changes}
36 | churn = calculate_mean_of_churn(churn, stats.size - 1) if compute_mean
37 | [filename, churn]
38 | end
39 |
40 | def calculate_mean_of_churn(churn, sample_size)
41 | return churn if sample_size < 1
42 | churn /= sample_size
43 | end
44 |
45 | def ruby_files_changed_in_scm
46 | counted_line_changes_by_file_by_commit.select do |filename, _|
47 | filename.end_with?(RUBY_FILE_EXTENSION) && File.exist?(filename)
48 | end
49 | end
50 |
51 | def counted_line_changes_by_file_by_commit
52 | scm_log_file_lines.map do |line|
53 | adds, deletes, filename = line.split(/\t/)
54 | [filename, adds.to_i + deletes.to_i]
55 | end
56 | end
57 |
58 | def scm_log_file_lines
59 | scm_log_command.each_line.reject{|line| line == "\n"}.map(&:chomp)
60 | end
61 |
62 | def scm_log_command
63 | scm.log_command(commit_range)
64 | end
65 | end
66 | end
67 | end
68 |
--------------------------------------------------------------------------------
/template/turbulence.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/lib/turbulence/generators/scatterplot.rb:
--------------------------------------------------------------------------------
1 | class Turbulence
2 | module Generators
3 | class ScatterPlot
4 | attr_reader :metrics_hash, :x_metric, :y_metric
5 |
6 | def initialize(metrics_hash,
7 | x_metric = :churn,
8 | y_metric = :complexity)
9 | @x_metric = x_metric
10 | @y_metric = y_metric
11 | @metrics_hash = metrics_hash
12 | end
13 |
14 | def self.from(metrics_hash)
15 | new(metrics_hash)
16 | end
17 |
18 | def mangle
19 | mangler = FileNameMangler.new
20 | mangled = {}
21 | metrics_hash.each_pair { |filename, metrics| mangled[mangler.mangle_name(filename)] = metrics}
22 | @metrics_hash = mangled
23 | end
24 |
25 | def to_js
26 | clean_metrics_from_missing_data
27 | directory_series = {}
28 |
29 | grouped_by_directory.each_pair do |directory, metrics_hash|
30 | directory_series[directory] = file_metrics_for_directory(metrics_hash)
31 | end
32 |
33 | "var directorySeries = #{directory_series.to_json};"
34 | end
35 |
36 | def clean_metrics_from_missing_data
37 | metrics_hash.reject! do |filename, metrics|
38 | metrics[x_metric].nil? || metrics[y_metric].nil?
39 | end
40 | end
41 |
42 | def grouped_by_directory
43 | metrics_hash.group_by do |filename, _|
44 | directories = File.dirname(filename).split("/")
45 | directories[0..1].join("/")
46 | end
47 | end
48 |
49 | def file_metrics_for_directory(metrics_hash)
50 | metrics_hash.map do |filename, metrics|
51 | { :filename => filename,
52 | :x => metrics[x_metric],
53 | :y => metrics[y_metric]}
54 | end
55 | end
56 |
57 | def generate_results(metrics, ci)
58 | File.open("cc.js", "w") do |f|
59 | ci.copy_templates_into(Dir.pwd)
60 | f.write Turbulence::Generators::ScatterPlot.from(metrics).to_js
61 | end
62 | end
63 | end
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Hopefully-meaningful Metrics
2 | ============================
3 |
4 | Based on Michael Feathers' [recent work](http://www.stickyminds.com/sitewide.asp?Function=edetail&ObjectType=COL&ObjectId=16679&tth=DYN&tt=siteemail&iDyn=2) in project churn and complexity.
5 |
6 | Here is how to read the graph (extracted from the above article):
7 |
8 | * The upper right quadrant is particularly important.
9 | These files have a high degree of complexity, and they change quite frequently.
10 | There are a number of reasons why this can happen.
11 | The one to look out for, though, is something I call runaway conditionals.
12 | Sometimes a class becomes so complex that refactoring seems too difficult.
13 | Developers hack if-then-elses into if-then-elses, and the rat’s nest grows. These classes are particularly ripe for a refactoring investment.
14 |
15 | * The lower left quadrant. is the healthy closure region.
16 | Abstractions here have low complexity and don't change much.
17 |
18 | * The upper left is what I call the cowboy region. This is complex code that sprang from someone's head and didn't seem to grow incrementally.
19 |
20 | * The bottom right is very interesting. I call it the fertile ground.
21 | It can consist of files that are somewhat configurational, but often there are also files that act as incubators for new abstractions.
22 | People add code, it grows, and then they factor outward, extracting new classes. The files churn frequently, but their complexity remains low.
23 |
24 |
25 | Installation
26 | ------------
27 |
28 | $ gem install turbulence
29 |
30 | Usage
31 | -----
32 | In your project directory, run:
33 |
34 | $ bule
35 |
36 | and it will generate (and open) turbulence/turbulence.html
37 |
38 | Supported SCM systems
39 | ---------------------
40 | Currently, bule defaults to using git. If you are using Perforce, call it like so:
41 |
42 | $ bule --scm p4
43 |
44 | You need to have an environment variable P4CLIENT set to the name of your client workspace.
45 |
46 | WARNING
47 | -------
48 | When you run bule, it creates a JavaScript file which contains your file paths and names. If those are sensitive, be careful where you put these generated files and who you share them with.
49 |
--------------------------------------------------------------------------------
/lib/turbulence.rb:
--------------------------------------------------------------------------------
1 | require 'turbulence/configuration'
2 | require 'turbulence/file_name_mangler'
3 | require 'turbulence/command_line_interface'
4 | require 'turbulence/calculators/churn'
5 | require 'turbulence/calculators/complexity'
6 | require 'turbulence/generators/treemap'
7 | require 'turbulence/generators/scatterplot'
8 |
9 | class Turbulence
10 | CODE_DIRECTORIES = [
11 | "app/models",
12 | "app/controllers",
13 | "app/helpers",
14 | "app/jobs",
15 | "app/mailers",
16 | "app/validators",
17 | "lib",
18 | ]
19 | CALCULATORS = [
20 | Turbulence::Calculators::Complexity,
21 | Turbulence::Calculators::Churn,
22 | ]
23 |
24 | # Make a config instance available to anyone who wants one
25 | def self.config
26 | @config ||= Configuration.new
27 | end
28 |
29 | attr_reader :config
30 | attr_reader :metrics
31 |
32 | extend Forwardable
33 | def_delegators :config, *[
34 | :directory,
35 | :exclusion_pattern,
36 | :output,
37 | ]
38 |
39 | def initialize(config = nil)
40 | @config = config || Turbulence.config
41 | @metrics = {}
42 |
43 | Dir.chdir(directory) do
44 | calculators.each(&method(:calculate_metrics_with))
45 | end
46 | end
47 |
48 | def files_of_interest
49 | file_list = CODE_DIRECTORIES.map{|base_dir| "#{base_dir}/**/*\.rb"}
50 | @ruby_files ||= exclude_files(Dir[*file_list])
51 | end
52 |
53 | def calculate_metrics_with(calculator)
54 | report "calculating metric: #{calculator}\n"
55 |
56 | calculator.for_these_files(files_of_interest) do |filename, score|
57 | report "."
58 | set_file_metric(filename, calculator.type, score)
59 | end
60 |
61 | report "\n"
62 | end
63 |
64 | def report(this)
65 | output.print this unless output.nil?
66 | end
67 |
68 | def set_file_metric(filename, metric, value)
69 | metrics_for(filename)[metric] = value
70 | end
71 |
72 | def metrics_for(filename)
73 | @metrics[filename] ||= {}
74 | end
75 |
76 | private
77 | def exclude_files(files)
78 | if not exclusion_pattern.nil?
79 | files = files.reject { |f| f =~ Regexp.new(exclusion_pattern) }
80 | end
81 | files
82 | end
83 |
84 | def calculators
85 | CALCULATORS.map { |calc_class| calc_class.new(config) }
86 | end
87 | end
88 |
--------------------------------------------------------------------------------
/lib/turbulence/scm/perforce.rb:
--------------------------------------------------------------------------------
1 | require 'fileutils'
2 | require 'pathname'
3 |
4 | class Turbulence
5 | module Scm
6 | class Perforce
7 | class << self
8 | def log_command(commit_range = "")
9 | full_log = ""
10 | changes.each do |cn|
11 | files_per_change(cn).each do |file|
12 | full_log << transform_for_output(file)
13 | end
14 | end
15 | return full_log
16 | end
17 |
18 | def is_repo?(directory)
19 | p4client = ENV['P4CLIENT']
20 | return !((p4client.nil? or p4client.empty?) and not self.has_p4?)
21 | end
22 |
23 | def has_p4?
24 | ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory|
25 | File.executable?(File.join(directory, 'p4'))
26 | end
27 | end
28 |
29 | def changes(commit_range = "")
30 | p4_list_changes.each_line.map do |change|
31 | change.match(/Change (\d+)/)[1]
32 | end
33 | end
34 |
35 | def depot_to_local(depot_file)
36 | abs_path = extract_clientfile_from_fstat_of(depot_file)
37 | Pathname.new(abs_path).relative_path_from(Pathname.new(FileUtils.pwd)).to_s
38 | end
39 |
40 | def extract_clientfile_from_fstat_of(depot_file)
41 | p4_fstat(depot_file).each_line.select {
42 | |line| line =~ /clientFile/
43 | }[0].split(" ")[2].tr("\\","/")
44 | end
45 |
46 | def files_per_change(change)
47 | describe_output = p4_describe_change(change).split("\n")
48 | map = []
49 | describe_output.each_index do |index|
50 | if describe_output[index].start_with?("====")
51 | fn = filename_from_describe(describe_output, index)
52 | churn = sum_of_changes(describe_output[index .. index + 4].join("\n"))
53 | map << [churn,fn]
54 | end
55 | end
56 | return map
57 | end
58 |
59 | def filename_from_describe(output,index)
60 | depot_to_local(output[index].match(/==== (\/\/.*)#\d+/)[1])
61 | end
62 |
63 | def transform_for_output(arr)
64 | "#{arr[0]}\t0\t#{arr[1]}\n"
65 | end
66 |
67 | def sum_of_changes(p4_describe_output)
68 | churn = 0
69 | p4_describe_output.each_line do |line|
70 | next unless line =~ /(add|deleted|changed) .* (\d+) lines/
71 | churn += line.match(/(\d+) lines/)[1].to_i
72 | end
73 | return churn
74 | end
75 |
76 | def p4_list_changes(commit_range = "")
77 | `p4 changes -s submitted ...#{commit_range}`
78 | end
79 |
80 | def p4_fstat(depot_file)
81 | `p4 fstat #{depot_file}`
82 | end
83 |
84 | def p4_describe_change(change)
85 | `p4 describe -ds #{change}`
86 | end
87 | end
88 | end
89 | end
90 | end
91 |
--------------------------------------------------------------------------------
/spec/turbulence/generators/scatter_plot_spec.rb:
--------------------------------------------------------------------------------
1 | require 'turbulence'
2 |
3 | describe Turbulence::Generators::ScatterPlot do
4 | context "with both Metrics" do
5 | it "generates JavaScript" do
6 | generator = Turbulence::Generators::ScatterPlot.new(
7 | "foo.rb" => { :churn => 1,
8 | :complexity => 2 }
9 | )
10 |
11 | generator.to_js.should =~ /var directorySeries/
12 | generator.to_js.should =~ /\"filename\"\:\"foo.rb\"/
13 | generator.to_js.should =~ /\"x\":1/
14 | generator.to_js.should =~ /\"y\":2/
15 | end
16 | end
17 |
18 | context "with a missing Metric" do
19 | it "generates JavaScript" do
20 | generator = Turbulence::Generators::ScatterPlot.new(
21 | "foo.rb" => { :churn => 1 }
22 | )
23 |
24 | generator.to_js.should == 'var directorySeries = {};'
25 | end
26 | end
27 |
28 | describe "#clean_metrics_from_missing_data" do
29 | let(:spg) {Turbulence::Generators::ScatterPlot.new({})}
30 |
31 | it "removes entries with missing churn" do
32 | spg.stub(:metrics_hash).and_return("foo.rb" => {
33 | :complexity => 88.3})
34 | spg.clean_metrics_from_missing_data.should == {}
35 | end
36 |
37 | it "removes entries with missing complexity" do
38 | spg.stub(:metrics_hash).and_return("foo.rb" => {
39 | :churn => 1})
40 | spg.clean_metrics_from_missing_data.should == {}
41 | end
42 |
43 | it "keeps entries with churn and complexity present" do
44 | spg.stub(:metrics_hash).and_return("foo.rb" => {
45 | :churn => 1,
46 | :complexity => 88.3,
47 | })
48 |
49 | spg.clean_metrics_from_missing_data.should_not == {}
50 | end
51 | end
52 |
53 | describe "#grouped_by_directory" do
54 | let(:spg) {Turbulence::Generators::ScatterPlot.new("lib/foo/foo.rb" => {
55 | :churn => 1},
56 | "lib/bar.rb" => {
57 | :churn => 2} )}
58 |
59 | it "uses \".\" to denote flat hierarchy" do
60 | spg.stub(:metrics_hash).and_return("foo.rb" => {
61 | :churn => 1
62 | })
63 | spg.grouped_by_directory.should == {"." => [["foo.rb", {:churn => 1}]]}
64 | end
65 |
66 | it "takes full path into account" do
67 | spg.grouped_by_directory.should == {"lib/foo" => [["lib/foo/foo.rb", {:churn => 1}]],
68 | "lib" => [["lib/bar.rb", {:churn => 2}]]}
69 | end
70 | end
71 |
72 | describe "#file_metrics_for_directory" do
73 | let(:spg) {Turbulence::Generators::ScatterPlot.new({})}
74 | it "assigns :filename, :x, :y" do
75 | spg.file_metrics_for_directory("lib/foo/foo.rb" => {
76 | :churn => 1,
77 | :complexity => 88.2,
78 | }).should == [{:filename => "lib/foo/foo.rb", :x => 1, :y => 88.2}]
79 | end
80 | end
81 |
82 | describe Turbulence::FileNameMangler do
83 | subject { Turbulence::FileNameMangler.new }
84 | it "anonymizes a string" do
85 | subject.mangle_name("chad").should_not == "chad"
86 | end
87 |
88 | it "maintains standard directory names" do
89 | subject.mangle_name("/app/controllers/chad.rb").should =~ %r{/app/controllers/1.rb}
90 | end
91 |
92 | it "honors leading path separators" do
93 | subject.mangle_name("/a/b/c.rb").should == "/1/2/3.rb"
94 | end
95 | end
96 | end
97 |
98 |
--------------------------------------------------------------------------------
/spec/turbulence/calculators/churn_spec.rb:
--------------------------------------------------------------------------------
1 | require 'turbulence/calculators/churn'
2 |
3 | describe Turbulence::Calculators::Churn do
4 | let(:calculator) { Turbulence::Calculators::Churn.new(config) }
5 | let(:config) { Turbulence::Configuration.new }
6 |
7 | before do
8 | calculator.stub(:scm_log_command) { "" }
9 | end
10 |
11 | describe "::for_these_files" do
12 | it "yields up the filename and score for each file" do
13 | files = ["lib/corey.rb", "lib/chad.rb"]
14 | calculator.stub(:changes_by_ruby_file) {
15 | [
16 | ["lib/corey.rb", 5],
17 | ["lib/chad.rb", 10]
18 | ]
19 | }
20 | yielded_files = []
21 | calculator.for_these_files(files) do |filename, score|
22 | yielded_files << [filename, score]
23 | end
24 | yielded_files.should =~ [["lib/corey.rb", 5],
25 | ["lib/chad.rb",10]]
26 | end
27 |
28 | it "filters the results by the passed-in files" do
29 | files = ["lib/corey.rb"]
30 | calculator.stub(:changes_by_ruby_file) {
31 | [
32 | ["lib/corey.rb", 5],
33 | ["lib/chad.rb", 10]
34 | ]
35 | }
36 | yielded_files = []
37 | calculator.for_these_files(files) do |filename, score|
38 | yielded_files << [filename, score]
39 | end
40 | yielded_files.should =~ [["lib/corey.rb", 5]]
41 | end
42 | end
43 |
44 | describe "::scm_log_file_lines" do
45 | it "returns just the file lines" do
46 | calculator.stub(:scm_log_command) do
47 | "\n\n\n\n10\t6\tlib/turbulence.rb\n\n\n\n17\t2\tlib/eddies.rb\n"
48 | end
49 |
50 | calculator.scm_log_file_lines.should =~ [
51 | "10\t6\tlib/turbulence.rb",
52 | "17\t2\tlib/eddies.rb"
53 | ]
54 | end
55 | end
56 |
57 | describe "::counted_line_changes_by_file_by_commit" do
58 | before do
59 | calculator.stub(:scm_log_file_lines) {
60 | [
61 | "10\t6\tlib/turbulence.rb",
62 | "17\t2\tlib/eddies.rb"
63 | ]
64 | }
65 | end
66 |
67 | it "sums up the line changes" do
68 | calculator.counted_line_changes_by_file_by_commit.should =~ [["lib/turbulence.rb", 16], ["lib/eddies.rb", 19]]
69 | end
70 | end
71 |
72 | describe "::changes_by_ruby_file" do
73 | before do
74 | calculator.stub(:ruby_files_changed_in_scm) {
75 | [
76 | ['lib/eddies.rb', 4],
77 | ['lib/turbulence.rb', 5],
78 | ['lib/turbulence.rb', 16],
79 | ['lib/eddies.rb', 2],
80 | ['lib/turbulence.rb', 7],
81 | ['lib/eddies.rb', 19],
82 | ['lib/eddies.rb', 28]
83 | ]
84 | }
85 | end
86 |
87 | it "groups and sums churns, excluding the last" do
88 | calculator.compute_mean = false
89 | calculator.changes_by_ruby_file.should =~ [ ['lib/eddies.rb', 25], ['lib/turbulence.rb', 21]]
90 | end
91 |
92 | it "interprets a single entry as zero churn" do
93 | calculator.stub(:ruby_files_changed_in_scm) {
94 | [
95 | ['lib/eddies.rb', 4],
96 | ]
97 | }
98 | calculator.compute_mean = false
99 | calculator.changes_by_ruby_file.should =~ [ ['lib/eddies.rb', 0] ]
100 | end
101 |
102 | it "groups and takes the mean of churns, excluding the last" do
103 | calculator.compute_mean = true
104 | calculator.changes_by_ruby_file.should =~ [ ['lib/eddies.rb', 8], ['lib/turbulence.rb', 10]]
105 | calculator.compute_mean = false
106 | end
107 | end
108 |
109 | describe "::calculate_mean_of_churn" do
110 | it "handles zero sample size" do
111 | calculator.calculate_mean_of_churn(8,0).should == 8
112 | end
113 |
114 | it "returns original churn for sample size = 1" do
115 | calculator.calculate_mean_of_churn(8,1).should == 8
116 | end
117 |
118 | it "returns churn divided by sample size" do
119 | calculator.calculate_mean_of_churn(25,3).should == 8
120 | end
121 |
122 | end
123 |
124 | context "Full stack tests" do
125 | context "when one ruby file is given" do
126 | context "with two log entries for file" do
127 | before do
128 | calculator.stub(:scm_log_command) do
129 | "\n\n\n\n10\t6\tlib/turbulence.rb\n" +
130 | "\n\n\n\n11\t7\tlib/turbulence.rb\n"
131 | end
132 | end
133 | it "gives the line change count for the file" do
134 | yielded_files = []
135 | calculator.for_these_files(["lib/turbulence.rb"]) do |filename, score|
136 | yielded_files << [filename, score]
137 | end
138 | yielded_files.should =~ [["lib/turbulence.rb", 16]]
139 | end
140 | context "with only one log entry for file" do
141 | before do
142 | calculator.stub(:scm_log_command) do
143 | "\n\n\n\n10\t6\tlib/turbulence.rb\n"
144 | end
145 | end
146 | it "shows zero churn for the file" do
147 | yielded_files = []
148 | calculator.for_these_files(["lib/turbulence.rb"]) do |filename, score|
149 | yielded_files << [filename, score]
150 | end
151 | yielded_files.should =~ [["lib/turbulence.rb", 0]]
152 | end
153 | end
154 | end
155 | end
156 | end
157 | end
158 |
--------------------------------------------------------------------------------
/spec/turbulence/scm/perforce_spec.rb:
--------------------------------------------------------------------------------
1 | require 'turbulence/scm/perforce'
2 | require 'rspec/mocks'
3 |
4 | describe Turbulence::Scm::Perforce do
5 | let (:p4_scm) { Turbulence::Scm::Perforce }
6 |
7 | before do
8 | p4_scm.stub(:p4_list_changes) do
9 | "Change 62660 on 2005/11/28 by x@client 'CHANGED: adapted to DESCODE '
10 | Change 45616 on 2005/07/12 by x@client 'ADDED: trigger that builds and '
11 | Change 45615 on 2005/07/12 by x@client 'ADDED: for testing purposes '
12 | Change 45614 on 2005/07/12 by x@client 'COSMETIC: updated header '
13 | Change 11250 on 2004/09/17 by x@client 'CHANGED: trigger now also allow'
14 | Change 9250 on 2004/08/20 by x@client 'BUGFIX: bug#1583 (People can so'
15 | Change 5560 on 2004/04/26 by x@client 'ADDED: The \"BRANCHED\" tag.'"
16 | end
17 |
18 | p4_scm.stub(:p4_describe_change).with("5560") do
19 | "Change 5560 by x@client on 2004/04/26 17:25:03
20 |
21 | ADDED: The \"BRANCHED\" tag.
22 |
23 | Affected files ...
24 |
25 | ... //admin/scripts/triggers/enforce-submit-comment.py#2 edit
26 | ... //admin/scripts/triggers/check-consistency.py#3 edit
27 |
28 | Differences ...
29 |
30 | ==== //admin/scripts/triggers/enforce-submit-comment.py#2 (ktext) ====
31 |
32 | add 1 chunks 1 lines
33 | deleted 0 chunks 0 lines
34 | changed 1 chunks 3 / 3 lines
35 |
36 | ==== //admin/scripts/triggers/check-consistency.py#3 (ktext) ====
37 |
38 | add 0 chunks 0 lines
39 | deleted 0 chunks 0 lines
40 | changed 1 chunks 3 / 1 lines"
41 | end
42 | end
43 |
44 | describe "::is_repo?" do
45 | before :each do
46 | ENV.stub(:[]).with("P4CLIENT").and_return(nil)
47 | ENV.stub(:[]).with("PATH").and_return("")
48 | end
49 |
50 | it "returns true if P4CLIENT is set " do
51 | ENV.stub(:[]).with("P4CLIENT").and_return("c-foo.bar")
52 |
53 | Turbulence::Scm::Perforce.is_repo?(".").should be_true
54 | end
55 |
56 | it "returns false if P4CLIENT is empty" do
57 | Turbulence::Scm::Perforce.is_repo?(".").should be_false
58 | end
59 |
60 | it "returns false if p4 is not available" do
61 | Turbulence::Scm::Perforce.is_repo?(".").should be_false
62 | end
63 | end
64 |
65 | describe "::log_command" do
66 | before do
67 | p4_scm.stub(:depot_to_local).with("//admin/scripts/triggers/enforce-submit-comment.py")\
68 | .and_return("triggers/enforce-submit-comments.py")
69 | p4_scm.stub(:depot_to_local).with("//admin/scripts/triggers/check-consistency.py")\
70 | .and_return("triggers/check-consistency.py")
71 | p4_scm.stub(:p4_list_changes) do
72 | "Change 5560 on 2004/04/26 by x@client 'ADDED: The \"BRANCHED\" tag.'"
73 | end
74 | end
75 |
76 | it "takes an optional argument to specify the range" do
77 | expect{Turbulence::Scm::Perforce.log_command("@1,2")}.to_not raise_error
78 | end
79 |
80 | it "lists insertions/deletions per file and change" do
81 | Turbulence::Scm::Perforce.log_command().should match(/\d+\t\d+\t[A-z.]*/)
82 | end
83 | end
84 |
85 | describe "::changes" do
86 | it "lists changenumbers from parsing 'p4 changes' output" do
87 | p4_scm.changes.should =~ %w[62660 45616 45615 45614 11250 9250 5560]
88 | end
89 | end
90 |
91 | describe "::files_per_change" do
92 | before do
93 | p4_scm.stub(:depot_to_local).with("//admin/scripts/triggers/enforce-submit-comment.py")\
94 | .and_return("triggers/enforce-submit-comments.py")
95 | p4_scm.stub(:depot_to_local).with("//admin/scripts/triggers/check-consistency.py")\
96 | .and_return("triggers/check-consistency.py")
97 | end
98 |
99 | it "lists files with churn" do
100 | p4_scm.files_per_change("5560").should =~ [[4,"triggers/enforce-submit-comments.py"],
101 | [1,"triggers/check-consistency.py"]]
102 | end
103 | end
104 |
105 | describe "::transform_for_output" do
106 | it "adds a 0 for deletions" do
107 | p4_scm.transform_for_output([1,"triggers/check-consistency.py"]).should == "1\t0\ttriggers/check-consistency.py\n"
108 | end
109 | end
110 |
111 | describe "::depot_to_local" do
112 | describe "on windows" do
113 | before do
114 | p4_scm.stub(:extract_clientfile_from_fstat_of).and_return("D:/Perforce/admin/scripts/triggers/enforce-no-head-change.py")
115 | FileUtils.stub(:pwd).and_return("D:/Perforce")
116 | end
117 |
118 | it "converts depot-style paths to local paths using forward slashes" do
119 | p4_scm.depot_to_local("//admin/scripts/triggers/enforce-no-head-change.py").should \
120 | == "admin/scripts/triggers/enforce-no-head-change.py"
121 | end
122 | end
123 |
124 | describe "on unix" do
125 | before do
126 | p4_scm.stub(:extract_clientfile_from_fstat_of).and_return("/home/jhwist/admin/scripts/triggers/enforce-no-head-change.py")
127 | FileUtils.stub(:pwd).and_return("/home/jhwist")
128 | end
129 |
130 | it "converts depot-style paths to local paths using forward slashes" do
131 | p4_scm.depot_to_local("//admin/scripts/triggers/enforce-no-head-change.py").should \
132 | == "admin/scripts/triggers/enforce-no-head-change.py"
133 | end
134 | end
135 | end
136 |
137 | describe "::extract_clientfile_from_fstat_of" do
138 | before do
139 | p4_scm.stub(:p4_fstat) do
140 | "... depotFile //admin/scripts/triggers/enforce-no-head-change.py
141 | ... clientFile /home/jhwist/admin/scripts/triggers/enforce-no-head-change.py
142 | ... isMapped
143 | ... headAction edit
144 | ... headType ktext
145 | ... headTime 1214555059
146 | ... headRev 5
147 | ... headChange 211211
148 | ... headModTime 1214555028
149 | ... haveRev 5"
150 | end
151 | end
152 |
153 | it "uses clientFile field" do
154 | p4_scm.extract_clientfile_from_fstat_of("//admin/scripts/triggers/enforce-no-head-change.py").should ==
155 | "/home/jhwist/admin/scripts/triggers/enforce-no-head-change.py"
156 | end
157 | end
158 |
159 | describe "::sum_of_changes" do
160 | it "sums up changes" do
161 | output = "add 1 chunks 1 lines\ndeleted 0 chunks 0 lines\nchanged 1 chunks 3 / 3 lines"
162 | p4_scm.sum_of_changes(output).should == 4
163 | end
164 |
165 | it "ignores junk" do
166 | output = "add nothing, change nothing"
167 | p4_scm.sum_of_changes(output).should == 0
168 | end
169 | end
170 | end
171 |
--------------------------------------------------------------------------------
/template/highcharts.js:
--------------------------------------------------------------------------------
1 | /*
2 | Highcharts JS v2.1.3 (2011-02-07)
3 |
4 | (c) 2009-2010 Torstein H?nsi
5 |
6 | License: www.highcharts.com/license
7 | */
8 | (function(){function oa(a,b){a||(a={});for(var c in b)a[c]=b[c];return a}function pa(a,b){return parseInt(a,b||10)}function Jb(a){return typeof a=="string"}function Db(a){return typeof a=="object"}function ac(a){return typeof a=="number"}function mc(a,b){for(var c=a.length;c--;)if(a[c]==b){a.splice(c,1);break}}function I(a){return a!==Ra&&a!==null}function ya(a,b,c){var d,e;if(Jb(b))if(I(c))a.setAttribute(b,c);else{if(a&&a.getAttribute)e=a.getAttribute(b)}else if(I(b)&&Db(b))for(d in b)a.setAttribute(d,
9 | b[d]);return e}function nc(a){if(!a||a.constructor!=Array)a=[a];return a}function y(){var a=arguments,b,c,d=a.length;for(b=0;b3?g%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+cb(a-c).toFixed(f).slice(2):"")}function Hc(){}function Hd(a,b){function c(m,h){function x(k,
12 | p){this.pos=k;this.minor=p;this.isNew=true;p||this.addLabel()}function w(k){if(k){this.options=k;this.id=k.id}return this}function O(){var k=[],p=[],r;Ta=u=null;$=[];t(Ba,function(o){r=false;t(["xAxis","yAxis"],function(la){if(o.isCartesian&&(la=="xAxis"&&ma||la=="yAxis"&&!ma)&&(o.options[la]==h.index||o.options[la]===Ra&&h.index===0)){o[la]=s;$.push(o);r=true}});if(!o.visible&&v.ignoreHiddenSeries)r=false;if(r){var T,Z,G,B,ha;if(!ma){T=o.options.stacking;Ic=T=="percent";if(T){B=o.type+y(o.options.stack,
13 | "");ha="-"+B;o.stackKey=B;Z=k[B]||[];k[B]=Z;G=p[ha]||[];p[ha]=G}if(Ic){Ta=0;u=99}}if(o.isCartesian){t(o.data,function(la){var C=la.x,na=la.y,S=na<0,aa=S?G:Z;S=S?ha:B;if(Ta===null)Ta=u=la[H];if(ma)if(C>u)u=C;else{if(Cu)u=na;else if(la=0){Ta=0;Id=true}else if(u<0){u=0;Jd=true}}}})}function ia(k,
14 | p){var r;Eb=p?1:Ua.pow(10,Lb(Ua.log(k)/Ua.LN10));r=k/Eb;if(!p){p=[1,2,2.5,5,10];if(h.allowDecimals===false)if(Eb==1)p=[1,2,5,10];else if(Eb<=0.1)p=[1/Eb]}for(var o=0;o0||!Jd))P+=k*Kd}Wa=K==P?1:Mb&&!T&&Z==r.options.tickPixelInterval?r.tickInterval:y(T,Va?1:(P-K)*Z/A);if(!N&&!I(h.tickInterval))Wa=ia(Wa);s.tickInterval=Wa;Jc=h.minorTickInterval==="auto"&&Wa?Wa/5:h.minorTickInterval;if(N){ra=[];T=Sa.global.useUTC;
16 | var G=1E3/ob,B=6E4/ob,ha=36E5/ob;Z=864E5/ob;k=6048E5/ob;o=2592E6/ob;var la=31556952E3/ob,C=[["second",G,[1,2,5,10,15,30]],["minute",B,[1,2,5,10,15,30]],["hour",ha,[1,2,3,4,6,8,12]],["day",Z,[1,2]],["week",k,[1,2]],["month",o,[1,2,3,4,6]],["year",la,null]],na=C[6],S=na[1],aa=na[2];for(r=0;r=G)aa.setSeconds(S>=B?0:C*Lb(aa.getSeconds()/
17 | C));if(S>=B)aa[Cd](S>=ha?0:C*Lb(aa[$c]()/C));if(S>=ha)aa[Dd](S>=Z?0:C*Lb(aa[ad]()/C));if(S>=Z)aa[cd](S>=o?1:C*Lb(aa[oc]()/C));if(S>=o){aa[Ed](S>=la?0:C*Lb(aa[Dc]()/C));p=aa[Ec]()}if(S>=la){p-=p%C;aa[Fd](p)}S==k&&aa[cd](aa[oc]()-aa[bd]()+h.startOfWeek);r=1;p=aa[Ec]();G=aa.getTime()/ob;B=aa[Dc]();for(ha=aa[oc]();Gp&&ra.shift();if(h.endOnTick)P=r;else PFb[H])Fb[H]=ra.length}}function Ea(){var k,p;gb=K;cc=P;O();ga();ja=D;D=A/(P-K||1);if(!ma)for(k in fa)for(p in fa[k])fa[k][p].cum=fa[k][p].total;if(!s.isDirty)s.isDirty=K!=gb||P!=cc}function ua(k){k=
19 | (new w(k)).render();Nb.push(k);return k}function bb(){var k=h.title,p=h.alternateGridColor,r=h.lineWidth,o,T,Z=m.hasRendered,G=Z&&I(gb)&&!isNaN(gb);o=$.length&&I(K)&&I(P);A=M?Aa:ta;D=A/(P-K||1);wa=M?X:pb;if(o||Mb){if(Jc&&!Va)for(o=K+(ra[0]-K)%Jc;o<=P;o+=Jc){Wb[o]||(Wb[o]=new x(o,true));G&&Wb[o].isNew&&Wb[o].render(null,true);Wb[o].isActive=true;Wb[o].render()}t(ra,function(B,ha){if(!Mb||B>=K&&B<=P){G&&qb[B].isNew&&qb[B].render(ha,true);qb[B].isActive=true;qb[B].render(ha)}});p&&t(ra,function(B,ha){if(ha%
20 | 2===0&&B=1E3?Gd(k,0):k},Nc=M&&h.labels.staggerLines,Xb=h.reversed,Yb=Va&&h.tickmarkPlacement=="between"?0.5:0;x.prototype={addLabel:function(){var k=this.pos,p=h.labels,r=!(k==
23 | K&&!y(h.showFirstLabel,1)||k==P&&!y(h.showLastLabel,0)),o=Va&&M&&Va.length&&!p.step&&!p.staggerLines&&!p.rotation&&Aa/Va.length||!M&&Aa/2,T=this.label;k=$d.call({isFirst:k==ra[0],isLast:k==ra[ra.length-1],dateTimeLabelFormat:Kc,value:Va&&Va[k]?Va[k]:k});o=o&&{width:o-2*(p.padding||10)+$a};o=oa(o,p.style);if(T===Ra)this.label=I(k)&&r&&p.enabled?ca.text(k,0,0).attr({align:p.align,rotation:p.rotation}).css(o).add(rb):null;else T&&T.attr({text:k}).css(o)},getLabelSize:function(){var k=this.label;return k?
24 | (this.labelBBox=k.getBBox())[M?"height":"width"]:0},render:function(k,p){var r=!this.minor,o=this.label,T=this.pos,Z=h.labels,G=this.gridLine,B=r?h.gridLineWidth:h.minorGridLineWidth,ha=r?h.gridLineColor:h.minorGridLineColor,la=r?h.gridLineDashStyle:h.minorGridLineDashStyle,C=this.mark,na=r?h.tickLength:h.minorTickLength,S=r?h.tickWidth:h.minorTickWidth||0,aa=r?h.tickColor:h.minorTickColor,pc=r?h.tickPosition:h.minorTickPosition;r=Z.step;var hb=p&&Oc||Pa,Ob;Ob=M?va(T+Yb,null,null,p)+wa:X+Q+(Oa?(p&&
25 | hd||Xa)-zb-X:0);hb=M?hb-pb+Q-(Oa?ta:0):hb-va(T+Yb,null,null,p)-wa;if(B){T=Ka(T+Yb,B,p);if(G===Ra){G={stroke:ha,"stroke-width":B};if(la)G.dashstyle=la;this.gridLine=G=B?ca.path(T).attr(G).add(Gb):null}G&&T&&G.animate({d:T})}if(S){if(pc=="inside")na=-na;if(Oa)na=-na;B=ca.crispLine([Za,Ob,hb,Ca,Ob+(M?0:-na),hb+(M?na:0)],S);if(C)C.animate({d:B});else this.mark=ca.path(B).attr({stroke:aa,"stroke-width":S}).add(rb)}if(o){Ob=Ob+Z.x-(Yb&&M?Yb*D*(Xb?-1:1):0);hb=hb+Z.y-(Yb&&!M?Yb*D*(Xb?1:-1):0);I(Z.y)||(hb+=
26 | parseInt(o.styles.lineHeight)*0.9-o.getBBox().height/2);if(Nc)hb+=k%Nc*16;if(r)o[k%r?"hide":"show"]();o[this.isNew?"attr":"animate"]({x:Ob,y:hb})}this.isNew=false},destroy:function(){for(var k in this)this[k]&&this[k].destroy&&this[k].destroy()}};w.prototype={render:function(){var k=this,p=k.options,r=p.label,o=k.label,T=p.width,Z=p.to,G,B=p.from,ha=p.dashStyle,la=k.svgElem,C=[],na,S,aa=p.color;S=p.zIndex;var pc=p.events;if(T){C=Ka(p.value,T);p={stroke:aa,"stroke-width":T};if(ha)p.dashstyle=ha}else if(I(B)&&
27 | I(Z)){B=Da(B,K);Z=nb(Z,P);G=Ka(Z);if((C=Ka(B))&&G)C.push(G[4],G[5],G[1],G[2]);else C=null;p={fill:aa}}else return;if(I(S))p.zIndex=S;if(la)if(C)la.animate({d:C},null,la.onGetPath);else{la.hide();la.onGetPath=function(){la.show()}}else if(C&&C.length){k.svgElem=la=ca.path(C).attr(p).add();if(pc){ha=function(hb){la.on(hb,function(Ob){pc[hb].apply(k,[Ob])})};for(na in pc)ha(na)}}if(r&&I(r.text)&&C&&C.length&&Aa>0&&ta>0){r=xa({align:M&&G&&"center",x:M?!G&&4:10,verticalAlign:!M&&G&&"middle",y:M?G?16:10:
28 | G?6:-4,rotation:M&&!G&&90},r);if(!o)k.label=o=ca.text(r.text,0,0).attr({align:r.textAlign||r.align,rotation:r.rotation,zIndex:S}).css(r.style).add();G=[C[1],C[4],C[6]||C[1]];C=[C[2],C[5],C[7]||C[2]];na=nb.apply(Ua,G);S=nb.apply(Ua,C);o.align(r,false,{x:na,y:S,width:Da.apply(Ua,G)-na,height:Da.apply(Ua,C)-S});o.show()}else o&&o.hide();return k},destroy:function(){for(var k in this){this[k]&&this[k].destroy&&this[k].destroy();delete this[k]}mc(Nb,this)}};va=function(k,p,r,o){var T=1,Z=0,G=o?ja:D;o=
29 | o?gb:K;G||(G=D);if(r){T*=-1;Z=A}if(Xb){T*=-1;Z-=T*A}if(p){if(Xb)k=A-k;k=k/G+o}else k=T*(k-o)*G+Z;return k};Ka=function(k,p,r){var o,T,Z;k=va(k,null,null,r);var G=r&&Oc||Pa,B=r&&hd||Xa,ha;r=T=U(k+wa);o=Z=U(G-k-wa);if(isNaN(k))ha=true;else if(M){o=da;Z=G-pb;if(rX+Aa)ha=true}else{r=X;T=B-zb;if(oda+ta)ha=true}return ha?null:ca.crispLine([Za,r,o,Ca,T,Z],p||0)};if(Ga&&ma&&Xb===Ra)Xb=true;oa(s,{addPlotBand:ua,addPlotLine:ua,adjustTickAmount:function(){if(Fb&&!N&&!Va&&!Mb){var k=ec,p=ra.length;
30 | ec=Fb[H];if(pk)k=K;else if(P',
34 | A?Mc("%A, %b %e, %Y",D):D,"
"]:[];t(H,function(va){wa.push(va.point.tooltipFormatter(ja))});return wa.join("")}function x(H,A){E=ma?H:(2*E+H)/3;fa=ma?A:(fa+A)/2;s.translate(E,fa);id=cb(H-E)>1||cb(A-fa)>1?function(){x(H,A)}:null}function w(){if(!ma){var H=q.hoverPoints;s.hide();t(ga,function(A){A&&A.hide()});H&&t(H,function(A){A.setState()});q.hoverPoints=null;ma=true}}var O,ia=m.borderWidth,L=m.crosshairs,ga=[],Ea=m.style,ua=m.shared,bb=pa(Ea.padding),Ja=ia+bb,ma=true,Oa,M,E=0,fa=0;Ea.padding=
35 | 0;var s=ca.g("tooltip").attr({zIndex:8}).add(),N=ca.rect(Ja,Ja,0,0,m.borderRadius,ia).attr({fill:m.backgroundColor,"stroke-width":ia}).add(s).shadow(m.shadow),Q=ca.text("",bb+Ja,pa(Ea.fontSize)+bb+Ja).attr({zIndex:1}).css(Ea).add(s);s.hide();return{shared:ua,refresh:function(H){var A,D,ja,wa=0,va={},Ka=[];ja=H.tooltipPos;A=m.formatter||h;va=q.hoverPoints;var rb=function(Fa){return{series:Fa.series,point:Fa,x:Fa.category,y:Fa.y,percentage:Fa.percentage,total:Fa.total||Fa.stackTotal}};if(ua){va&&t(va,
36 | function(Fa){Fa.setState()});q.hoverPoints=H;t(H,function(Fa){Fa.setState(xb);wa+=Fa.plotY;Ka.push(rb(Fa))});D=H[0].plotX;wa=U(wa)/H.length;va={x:H[0].category};va.points=Ka;H=H[0]}else va=rb(H);va=A.call(va);O=H.series;D=ua?D:H.plotX;wa=ua?wa:H.plotY;A=U(ja?ja[0]:Ga?Aa-wa:D);D=U(ja?ja[1]:Ga?ta-D:wa);ja=ua||!H.series.isCartesian||hc(A,D);if(va===false||!ja)w();else{if(ma){s.show();ma=false}Q.attr({text:va});ja=Q.getBBox();Oa=ja.width+2*bb;M=ja.height+2*bb;N.attr({width:Oa,height:M,stroke:m.borderColor||
37 | H.color||O.color||"#606060"});A=A-Oa+X-25;D=D-M+da+10;if(A<7){A=7;D-=30}if(D<5)D=5;else if(D+M>Pa)D=Pa-M-5;x(U(A-Ja),U(D-Ja))}if(L){L=nc(L);D=L.length;for(var Gb;D--;)if(L[D]&&(Gb=H.series[D?"yAxis":"xAxis"])){A=Gb.getPlotLinePath(H[D?"y":"x"],1);if(ga[D])ga[D].attr({d:A,visibility:Ab});else{ja={"stroke-width":L[D].width||1,stroke:L[D].color||"#C0C0C0",zIndex:2};if(L[D].dashStyle)ja.dashstyle=L[D].dashStyle;ga[D]=ca.path(A).attr(ja).add()}}}},hide:w}}function f(m,h){function x(E){var fa;E=E||sb.event;
38 | if(!E.target)E.target=E.srcElement;fa=E.touches?E.touches.item(0):E;if(E.type!="mousemove"||sb.opera){for(var s=sa,N={left:s.offsetLeft,top:s.offsetTop};s=s.offsetParent;){N.left+=s.offsetLeft;N.top+=s.offsetTop;if(s!=za.body&&s!=za.documentElement){N.left-=s.scrollLeft;N.top-=s.scrollTop}}qc=N}if(Ac){E.chartX=E.x;E.chartY=E.y}else if(fa.layerX===Ra){E.chartX=fa.pageX-qc.left;E.chartY=fa.pageY-qc.top}else{E.chartX=E.layerX;E.chartY=E.layerY}return E}function w(E){var fa={xAxis:[],yAxis:[]};t(ab,function(s){var N=
39 | s.translate,Q=s.isXAxis;fa[Q?"xAxis":"yAxis"].push({axis:s,value:N((Ga?!Q:Q)?E.chartX-X:ta-E.chartY+da,true)})});return fa}function O(){var E=m.hoverSeries,fa=m.hoverPoint;fa&&fa.onMouseOut();E&&E.onMouseOut();rc&&rc.hide();jd=null}function ia(){if(ua){var E={xAxis:[],yAxis:[]},fa=ua.getBBox(),s=fa.x-X,N=fa.y-da;if(Ea){t(ab,function(Q){var H=Q.translate,A=Q.isXAxis,D=Ga?!A:A,ja=H(D?s:ta-N-fa.height,true);H=H(D?s+fa.width:ta-N,true);E[A?"xAxis":"yAxis"].push({axis:Q,min:nb(ja,H),max:Da(ja,H)})});La(m,
40 | "selection",E,kd)}ua=ua.destroy()}m.mouseIsDown=ld=Ea=false;Bb(za,Hb?"touchend":"mouseup",ia)}var L,ga,Ea,ua,bb=v.zoomType,Ja=/x/.test(bb),ma=/y/.test(bb),Oa=Ja&&!Ga||ma&&Ga,M=ma&&!Ga||Ja&&Ga;Pc=function(){if(Qc){Qc.translate(X,da);Ga&&Qc.attr({width:m.plotWidth,height:m.plotHeight}).invert()}else m.trackerGroup=Qc=ca.g("tracker").attr({zIndex:9}).add()};Pc();if(h.enabled)m.tooltip=rc=e(h);(function(){var E=true;sa.onmousedown=function(s){s=x(s);m.mouseIsDown=ld=true;L=s.chartX;ga=s.chartY;Qa(za,
41 | Hb?"touchend":"mouseup",ia)};var fa=function(s){if(!(s&&s.touches&&s.touches.length>1)){s=x(s);if(!Hb)s.returnValue=false;var N=s.chartX,Q=s.chartY,H=!hc(N-X,Q-da);if(Hb&&s.type=="touchstart")if(ya(s.target,"isTracker"))m.runTrackerClick||s.preventDefault();else!ae&&!H&&s.preventDefault();if(H){E||O();if(NX+Aa)N=X+Aa;if(Qda+ta)Q=da+ta}if(ld&&s.type!="touchstart"){if(Ea=Math.sqrt(Math.pow(L-N,2)+Math.pow(ga-Q,2))>10){if(ic&&(Ja||ma)&&hc(L-X,ga-da))ua||(ua=ca.rect(X,
42 | da,Oa?1:Aa,M?1:ta,0).attr({fill:"rgba(69,114,167,0.25)",zIndex:7}).add());if(ua&&Oa){N=N-L;ua.attr({width:cb(N),x:(N>0?0:N)+L})}if(ua&&M){Q=Q-ga;ua.attr({height:cb(Q),y:(Q>0?0:Q)+ga})}}}else if(!H){var A;Q=m.hoverPoint;N=m.hoverSeries;var D,ja,wa=Xa,va=Ga?s.chartY:s.chartX-X;if(rc&&h.shared){A=[];D=Ba.length;for(ja=0;jawa&&A.splice(D,
43 | 1);if(A.length&&A[0].plotX!=jd){rc.refresh(A);jd=A[0].plotX}}if(N&&N.tracker)(s=N.tooltipPoints[va])&&s!=Q&&s.onMouseOver()}return(E=H)||!ic}};sa.onmousemove=fa;Qa(sa,"mouseleave",O);sa.ontouchstart=function(s){if(Ja||ma)sa.onmousedown(s);fa(s)};sa.ontouchmove=fa;sa.ontouchend=function(){Ea&&O()};sa.onclick=function(s){var N=m.hoverPoint;s=x(s);s.cancelBubble=true;if(!Ea)if(N&&ya(s.target,"isTracker")){var Q=N.plotX,H=N.plotY;oa(N,{pageX:qc.left+X+(Ga?Aa-H:Q),pageY:qc.top+da+(Ga?ta-Q:H)});La(N.series,
44 | "click",oa(s,{point:N}));N.firePointEvent("click",s)}else{oa(s,w(s));hc(s.chartX-X,s.chartY-da)&&La(m,"click",s)}Ea=false}})();Nd=setInterval(function(){id&&id()},32);oa(this,{zoomX:Ja,zoomY:ma,resetTracker:O})}function g(m){var h=m.type||v.type||v.defaultSeriesType,x=tb[h],w=q.hasRendered;if(w)if(Ga&&h=="column")x=tb.bar;else if(!Ga&&h=="bar")x=tb.column;h=new x;h.init(q,m);if(!w&&h.inverted)Ga=true;if(h.isCartesian)ic=h.isCartesian;Ba.push(h);return h}function i(){v.alignTicks!==false&&t(ab,function(m){m.adjustTickAmount()});
45 | Fb=null}function l(m){var h=q.isDirtyLegend,x,w=q.isDirtyBox,O=Ba.length,ia=O,L=q.clipRect;for(bc(m,q);ia--;){m=Ba[ia];if(m.isDirty&&m.options.stacking){x=true;break}}if(x)for(ia=O;ia--;){m=Ba[ia];if(m.options.stacking)m.isDirty=true}t(Ba,function(ga){if(ga.isDirty){ga.cleanData();ga.getSegments();if(ga.options.legendType=="point")h=true}});if(h&&md.renderLegend){md.renderLegend();q.isDirtyLegend=false}if(ic){if(!Rc){Fb=null;t(ab,function(ga){ga.setScale()})}i();sc();t(ab,function(ga){if(ga.isDirty||
46 | w){ga.redraw();w=true}})}if(w){nd();Pc();if(L){Sc(L);L.animate({width:q.plotSizeX,height:q.plotSizeY})}}t(Ba,function(ga){if(ga.isDirty&&ga.visible&&(!ga.isCartesian||ga.xAxis))ga.redraw()});gc&&gc.resetTracker&&gc.resetTracker();La(q,"redraw")}function j(){var m=a.xAxis||{},h=a.yAxis||{},x;m=nc(m);t(m,function(w,O){w.index=O;w.isX=true});h=nc(h);t(h,function(w,O){w.index=O});ab=m.concat(h);q.xAxis=[];q.yAxis=[];ab=jc(ab,function(w){x=new c(q,w);q[x.isXAxis?"xAxis":"yAxis"].push(x);return x});i()}
47 | function n(m,h){kc=xa(a.title,m);tc=xa(a.subtitle,h);t([["title",m,kc],["subtitle",h,tc]],function(x){var w=x[0],O=q[w],ia=x[1];x=x[2];if(O&&ia){O.destroy();O=null}if(x&&x.text&&!O)q[w]=ca.text(x.text,0,0).attr({align:x.align,"class":"highcharts-"+w,zIndex:1}).css(x.style).add().align(x,false,uc)})}function z(){ib=v.renderTo;Od=Zb+od++;if(Jb(ib))ib=za.getElementById(ib);ib.innerHTML="";if(!ib.offsetWidth){Qb=ib.cloneNode(0);Ia(Qb,{position:lc,top:"-9999px",display:""});za.body.appendChild(Qb)}Tc=
48 | (Qb||ib).offsetWidth;vc=(Qb||ib).offsetHeight;q.chartWidth=Xa=v.width||Tc||600;q.chartHeight=Pa=v.height||(vc>19?vc:400);q.container=sa=fb(Kb,{className:"highcharts-container"+(v.className?" "+v.className:""),id:Od},oa({position:Pd,overflow:ub,width:Xa+$a,height:Pa+$a,textAlign:"left"},v.style),Qb||ib);q.renderer=ca=v.forExport?new Uc(sa,Xa,Pa,true):new Qd(sa,Xa,Pa);var m,h;if(Rd&&sa.getBoundingClientRect){m=function(){Ia(sa,{left:0,top:0});h=sa.getBoundingClientRect();Ia(sa,{left:-h.left%1+$a,top:-h.top%
49 | 1+$a})};m();Qa(sb,"resize",m);Qa(q,"destroy",function(){Bb(sb,"resize",m)})}}function F(){function m(){var x=v.width||ib.offsetWidth,w=v.height||ib.offsetHeight;if(x&&w){if(x!=Tc||w!=vc){clearTimeout(h);h=setTimeout(function(){pd(x,w,false)},100)}Tc=x;vc=w}}var h;Qa(window,"resize",m);Qa(q,"destroy",function(){Bb(window,"resize",m)})}function W(){var m=a.labels,h=a.credits,x;n();md=q.legend=new be(q);sc();t(ab,function(w){w.setTickPositions(true)});i();sc();nd();ic&&t(ab,function(w){w.render()});
50 | if(!q.seriesGroup)q.seriesGroup=ca.g("series-group").attr({zIndex:3}).add();t(Ba,function(w){w.translate();w.setTooltipPoints();w.render()});m.items&&t(m.items,function(){var w=oa(m.style,this.style),O=pa(w.left)+X,ia=pa(w.top)+da+12;delete w.left;delete w.top;ca.text(this.html,O,ia).attr({zIndex:2}).css(w).add()});if(!q.toolbar)q.toolbar=d(q);if(h.enabled&&!q.credits){x=h.href;ca.text(h.text,0,0).on("click",function(){if(x)location.href=x}).attr({align:h.position.align,zIndex:8}).css(h.style).add().align(h.position)}Pc();
51 | q.hasRendered=true;if(Qb){ib.appendChild(sa);Fc(Qb)}}function ba(){var m=Ba.length,h=sa&&sa.parentNode;La(q,"destroy");Bb(sb,"unload",ba);Bb(q);for(t(ab,function(x){Bb(x)});m--;)Ba[m].destroy();if(I(sa)){sa.innerHTML="";Bb(sa);h&&h.removeChild(sa)}sa=null;ca.alignedObjects=null;clearInterval(Nd);for(m in q)delete q[m]}function ka(){if(!wc&&!sb.parent&&za.readyState!="complete")za.attachEvent("onreadystatechange",function(){za.detachEvent("onreadystatechange",ka);ka()});else{z();qd();rd();t(a.series||
52 | [],function(m){g(m)});q.inverted=Ga=y(Ga,a.chart.inverted);j();q.render=W;q.tracker=gc=new f(q,a.tooltip);W();La(q,"load");b&&b.apply(q,[q]);t(q.callbacks,function(m){m.apply(q,[q])})}}Lc=xa(Lc,Sa.xAxis);fd=xa(fd,Sa.yAxis);Sa.xAxis=Sa.yAxis=null;a=xa(Sa,a);var v=a.chart,J=v.margin;J=Db(J)?J:[J,J,J,J];var ea=y(v.marginTop,J[0]),Y=y(v.marginRight,J[1]),V=y(v.marginBottom,J[2]),R=y(v.marginLeft,J[3]),Ha=v.spacingTop,Ya=v.spacingRight,sd=v.spacingBottom,Vc=v.spacingLeft,uc,kc,tc,da,zb,pb,X,Pb,ib,Qb,sa,
53 | Od,Tc,vc,Xa,Pa,hd,Oc,td,ud,vd,wd,q=this,ae=(J=v.events)&&!!J.click,xd,hc,rc,ld,$b,Sd,yd,ta,Aa,gc,Qc,Pc,md,Rb,Sb,qc,ic=v.showAxes,Rc=0,ab=[],Fb,Ba=[],Ga,ca,id,Nd,jd,nd,sc,qd,rd,pd,kd,Td,be=function(m){function h(u,$){var qa=u.legendItem,Na=u.legendLine,P=u.legendSymbol,K=M.color,gb=$?L.itemStyle.color:K;K=$?u.color:K;qa&&qa.css({fill:gb});Na&&Na.attr({stroke:K});P&&P.attr({stroke:K,fill:K})}function x(u,$,qa){var Na=u.legendItem,P=u.legendLine,K=u.legendSymbol;u=u.checkbox;Na&&Na.attr({x:$,y:qa});
54 | P&&P.translate($,qa-4);K&&K.attr({x:$+K.xOff,y:qa+K.yOff});if(u){u.x=$;u.y=qa}}function w(){t(bb,function(u){var $=u.checkbox;$&&Ia($,{left:Ka.attr("translateX")+u.legendItemWidth+$.x-40+$a,top:Ka.attr("translateY")+$.y-11+$a})})}function O(u){var $,qa,Na,P,K,gb=u.legendItem;P=u.series||u;if(!gb){K=/^(bar|pie|area|column)$/.test(P.type);u.legendItem=gb=ca.text(L.labelFormatter.call(u),0,0).css(u.visible?ma:M).on("mouseover",function(){u.setState(xb);gb.css(Oa)}).on("mouseout",function(){gb.css(u.visible?
55 | ma:M);u.setState()}).on("click",function(){var Vb=function(){u.setVisible()};u.firePointEvent?u.firePointEvent("legendItemClick",null,Vb):La(u,"legendItemClick",null,Vb)}).attr({zIndex:2}).add(Ka);if(!K&&u.options&&u.options.lineWidth){var cc=u.options;P={"stroke-width":cc.lineWidth,zIndex:2};if(cc.dashStyle)P.dashstyle=cc.dashStyle;u.legendLine=ca.path([Za,-Ea-ua,0,Ca,-ua,0]).attr(P).add(Ka)}if(K)$=ca.rect(qa=-Ea-ua,Na=-11,Ea,12,2).attr({"stroke-width":0,zIndex:3}).add(Ka);else if(u.options&&u.options.marker&&
56 | u.options.marker.enabled)$=ca.symbol(u.symbol,qa=-Ea/2-ua,Na=-4,u.options.marker.radius).attr(u.pointAttr[db]).attr({zIndex:3}).add(Ka);if($){$.xOff=qa;$.yOff=Na}u.legendSymbol=$;h(u,u.visible);if(u.options&&u.options.showCheckbox){u.checkbox=fb("input",{type:"checkbox",checked:u.selected,defaultChecked:u.selected},L.itemCheckboxStyle,sa);Qa(u.checkbox,"click",function(Vb){La(u,"checkboxClick",{checked:Vb.target.checked},function(){u.select()})})}}$=gb.getBBox();qa=u.legendItemWidth=L.itemWidth||
57 | Ea+ua+$.width+fa;D=$.height;if(ga&&Q-N+qa>(Gb||Xa-2*E-N)){Q=N;H+=D}A=H;x(u,Q,H);if(ga)Q+=qa;else H+=D;rb=Gb||Da(ga?Q-N:qa,rb);bb.push(u)}function ia(){Q=N;H=s;A=rb=0;bb=[];Ka||(Ka=ca.g("legend").attr({zIndex:7}).add());Ta&&Fa.reverse();t(Fa,function(Na){if(Na.options.showInLegend)t(Na.options.legendType=="point"?Na.data:[Na],O)});Ta&&Fa.reverse();Rb=Gb||rb;Sb=A-s+D;if(wa||va){Rb+=2*E;Sb+=2*E;if(ja)Rb>0&&Sb>0&&ja.animate({width:Rb,height:Sb});else ja=ca.rect(0,0,Rb,Sb,L.borderRadius,wa||0).attr({stroke:L.borderColor,
58 | "stroke-width":wa||0,fill:va||mb}).add(Ka).shadow(L.shadow);ja[bb.length?"show":"hide"]()}for(var u=["left","right","top","bottom"],$,qa=4;qa--;){$=u[qa];if(Ja[$]&&Ja[$]!="auto"){L[qa<2?"align":"verticalAlign"]=$;L[qa<2?"x":"y"]=pa(Ja[$])*(qa%2?-1:1)}}Ka.align(oa(L,{width:Rb,height:Sb}),true,uc);Rc||w()}var L=m.options.legend;if(L.enabled){var ga=L.layout=="horizontal",Ea=L.symbolWidth,ua=L.symbolPadding,bb,Ja=L.style,ma=L.itemStyle,Oa=L.itemHoverStyle,M=L.itemHiddenStyle,E=pa(Ja.padding),fa=20,s=
59 | 18,N=4+E+Ea+ua,Q,H,A,D=0,ja,wa=L.borderWidth,va=L.backgroundColor,Ka,rb,Gb=L.width,Fa=m.series,Ta=L.reversed;ia();Qa(m,"endResize",w);return{colorizeItem:h,destroyItem:function(u){var $=u.checkbox;t(["legendItem","legendLine","legendSymbol"],function(qa){u[qa]&&u[qa].destroy()});$&&Fc(u.checkbox)},renderLegend:ia}}};hc=function(m,h){return m>=0&&m<=Aa&&h>=0&&h<=ta};Td=function(){La(q,"selection",{resetSelection:true},kd);q.toolbar.remove("zoom")};kd=function(m){var h=Sa.lang,x=q.pointCount<100;q.toolbar.add("zoom",
60 | h.resetZoom,h.resetZoomTitle,Td);!m||m.resetSelection?t(ab,function(w){w.setExtremes(null,null,false,x)}):t(m.xAxis.concat(m.yAxis),function(w){var O=w.axis;if(q.tracker[O.isXAxis?"zoomX":"zoomY"])O.setExtremes(w.min,w.max,false,x)});l()};sc=function(){var m=a.legend,h=y(m.margin,10),x=m.x,w=m.y,O=m.align,ia=m.verticalAlign,L;qd();if((q.title||q.subtitle)&&!I(ea))if(L=Da(q.title&&!kc.floating&&!kc.verticalAlign&&kc.y||0,q.subtitle&&!tc.floating&&!tc.verticalAlign&&tc.y||0))da=Da(da,L+y(kc.margin,
61 | 15)+Ha);if(m.enabled&&!m.floating)if(O=="right")I(Y)||(zb=Da(zb,Rb-x+h+Ya));else if(O=="left")I(R)||(X=Da(X,Rb+x+h+Vc));else if(ia=="top")I(ea)||(da=Da(da,Sb+w+h+Ha));else if(ia=="bottom")I(V)||(pb=Da(pb,Sb-w+h+sd));ic&&t(ab,function(ga){ga.getOffset()});I(R)||(X+=Pb[3]);I(ea)||(da+=Pb[0]);I(V)||(pb+=Pb[2]);I(Y)||(zb+=Pb[1]);rd()};pd=function(m,h,x){var w=q.title,O=q.subtitle;Rc+=1;bc(x,q);Oc=Pa;hd=Xa;Xa=U(m);Pa=U(h);Ia(sa,{width:Xa+$a,height:Pa+$a});ca.setSize(Xa,Pa,x);Aa=Xa-X-zb;ta=Pa-da-pb;Fb=
62 | null;t(ab,function(ia){ia.isDirty=true;ia.setScale()});t(Ba,function(ia){ia.isDirty=true});q.isDirtyLegend=true;q.isDirtyBox=true;sc();w&&w.align(null,null,uc);O&&O.align(null,null,uc);l(x);Oc=null;La(q,"resize");setTimeout(function(){La(q,"endResize",null,function(){Rc-=1})},Bc&&Bc.duration||500)};rd=function(){q.plotLeft=X=U(X);q.plotTop=da=U(da);q.plotWidth=Aa=U(Xa-X-zb);q.plotHeight=ta=U(Pa-da-pb);q.plotSizeX=Ga?ta:Aa;q.plotSizeY=Ga?Aa:ta;uc={x:Vc,y:Ha,width:Xa-Vc-Ya,height:Pa-Ha-sd}};qd=function(){da=
63 | y(ea,Ha);zb=y(Y,Ya);pb=y(V,sd);X=y(R,Vc);Pb=[0,0,0,0]};nd=function(){var m=v.borderWidth||0,h=v.backgroundColor,x=v.plotBackgroundColor,w=v.plotBackgroundImage,O,ia={x:X,y:da,width:Aa,height:ta};O=m+(v.shadow?8:0);if(m||h)if(td)td.animate({width:Xa-O,height:Pa-O});else td=ca.rect(O/2,O/2,Xa-O,Pa-O,v.borderRadius,m).attr({stroke:v.borderColor,"stroke-width":m,fill:h||mb}).add().shadow(v.shadow);if(x)if(ud)ud.animate(ia);else ud=ca.rect(X,da,Aa,ta,0).attr({fill:x}).add().shadow(v.plotShadow);if(w)if(vd)vd.animate(ia);
64 | else vd=ca.image(w,X,da,Aa,ta).add();if(v.plotBorderWidth)if(wd)wd.animate(ia);else wd=ca.rect(X,da,Aa,ta,0,v.plotBorderWidth).attr({stroke:v.plotBorderColor,"stroke-width":v.plotBorderWidth,zIndex:4}).add();q.isDirtyBox=false};Wc=Ib=0;Qa(sb,"unload",ba);v.reflow!==false&&Qa(q,"load",F);if(J)for(xd in J)Qa(q,xd,J[xd]);q.options=a;q.series=Ba;q.addSeries=function(m,h,x){var w;if(m){bc(x,q);h=y(h,true);La(q,"addSeries",{options:m},function(){w=g(m);w.isDirty=true;q.isDirtyLegend=true;h&&q.redraw()})}return w};
65 | q.animation=y(v.animation,true);q.destroy=ba;q.get=function(m){var h,x,w;for(h=0;h-1,f=e?7:3,g;b=b.split(" ");c=[].concat(c);var i,l,j=function(n){for(g=n.length;g--;)n[g]==Za&&n.splice(g+1,0,n[g+1],n[g+2],n[g+1],n[g+2])};if(e){j(b);j(c)}if(a.isArea){i=b.splice(b.length-6,6);l=c.splice(c.length-6,6)}if(d){c=[].concat(c).splice(0,
72 | f).concat(c);a.shift=false}if(b.length)for(a=c.length;b.length255)b[e]=255}}return this},setOpacity:function(d){b[3]=d;return this}}};Mc=function(a,b,c){function d(F){return F.toString().replace(/^([0-9])$/,"0$1")}if(!I(b)||isNaN(b))return"Invalid date";a=y(a,"%Y-%m-%d %H:%M:%S");b=new Date(b*ob);var e=b[ad](),f=b[bd](),g=b[oc](),i=b[Dc](),l=b[Ec](),j=Sa.lang,n=j.weekdays;
83 | j=j.months;b={a:n[f].substr(0,3),A:n[f],d:d(g),e:g,b:j[i].substr(0,3),B:j[i],m:d(i+1),y:l.toString().substr(2,2),Y:l,H:d(e),I:d(e%12||12),l:e%12||12,M:d(b[$c]()),p:e<12?"AM":"PM",P:e<12?"am":"pm",S:d(b.getSeconds())};for(var z in b)a=a.replace("%"+z,b[z]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a};Hc.prototype={init:function(a,b){this.element=za.createElementNS("http://www.w3.org/2000/svg",b);this.renderer=a},animate:function(a,b,c){if(b=y(b,Bc,true)){b=xa(b);if(c)b.complete=c;Xc(this,a,
84 | b)}else{this.attr(a);c&&c()}},attr:function(a,b){var c,d,e,f,g=this.element,i=g.nodeName,l=this.renderer,j,n=this.shadows,z,F=this;if(Jb(a)&&I(b)){c=a;a={};a[c]=b}if(Jb(a)){c=a;if(i=="circle")c={x:"cx",y:"cy"}[c]||c;else if(c=="strokeWidth")c="stroke-width";F=ya(g,c)||this[c]||0;if(c!="d"&&c!="visibility")F=parseFloat(F)}else for(c in a){j=false;d=a[c];if(c=="d"){if(d&&d.join)d=d.join(" ");if(/(NaN| {2}|^$)/.test(d))d="M 0 0";this.d=d}else if(c=="x"&&i=="text"){for(e=0;eg||!I(g)&&I(b))){d.insertBefore(f,a);return this}}d.appendChild(f);this.added=true;return this},destroy:function(){var a=this.element||{},b=this.shadows,c=a.parentNode,d;a.onclick=a.onmouseout=a.onmouseover=a.onmousemove=null;Sc(this);c&&c.removeChild(a);
93 | b&&t(b,function(e){(c=e.parentNode)&&c.removeChild(e)});mc(this.renderer.alignedObjects,this);for(d in this)delete this[d];return null},empty:function(){for(var a=this.element,b=a.childNodes,c=b.length;c--;)a.removeChild(b[c])},shadow:function(a){var b=[],c,d=this.element,e=this.parentInverted?"(-1,-1)":"(1,1)";if(a){for(a=1;a<=3;a++){c=d.cloneNode(0);ya(c,{isShadow:"true",stroke:"rgb(0, 0, 0)","stroke-opacity":0.05*a,"stroke-width":7-2*a,transform:"translate"+e,fill:mb});d.parentNode.insertBefore(c,
94 | d);b.push(c)}this.shadows=b}return this}};var Uc=function(){this.init.apply(this,arguments)};Uc.prototype={init:function(a,b,c,d){var e=location,f;this.Element=Hc;f=this.createElement("svg").attr({xmlns:"http://www.w3.org/2000/svg",version:"1.1"});a.appendChild(f.element);this.box=f.element;this.boxWrapper=f;this.alignedObjects=[];this.url=Ac?"":e.href.replace(/#.*?$/,"");this.defs=this.createElement("defs").add();this.forExport=d;this.setSize(b,c,false)},createElement:function(a){var b=new this.Element;
95 | b.init(this,a);return b},buildText:function(a){for(var b=a.element,c=y(a.textStr,"").toString().replace(/<(b|strong)>/g,'').replace(/<(i|em)>/g,'').replace(//g,"").split(/
]?>/g),d=b.childNodes,e=/style="([^"]+)"/,f=/href="([^"]+)"/,g=ya(b,"x"),i=a.styles,l=Rd&&i&&i.HcDirection=="rtl"&&!this.forExport,j,n=i&&pa(i.width),z=i&&i.lineHeight,F,W=d.length;W--;)b.removeChild(d[W]);n&&!a.added&&
96 | this.box.appendChild(b);t(c,function(ba,ka){var v,J=0,ea;ba=ba.replace(//g,"|||");v=ba.split("|||");t(v,function(Y){if(Y!==""||v.length==1){var V={},R=za.createElementNS("http://www.w3.org/2000/svg","tspan");e.test(Y)&&ya(R,"style",Y.match(e)[1].replace(/(;| |^)color([ :])/,"$1fill$2"));if(f.test(Y)){ya(R,"onclick",'location.href="'+Y.match(f)[1]+'"');Ia(R,{cursor:"pointer"})}Y=Y.replace(/<(.|\n)*?>/g,"")||" ";if(l){j=[];for(W=Y.length;W--;)j.push(Y.charAt(W));
97 | Y=j.join("")}R.appendChild(za.createTextNode(Y));if(J)V.dx=3;else V.x=g;if(!J){if(ka){ea=pa(window.getComputedStyle(F,null).getPropertyValue("line-height"));if(isNaN(ea))ea=z||F.offsetHeight||18;ya(R,"dy",ea)}F=R}ya(R,V);b.appendChild(R);J++;if(n){Y=Y.replace(/-/g,"- ").split(" ");for(var Ha,Ya=[];Y.length||Ya.length;){Ha=b.getBBox().width;V=Ha>n;if(!V||Y.length==1){Y=Ya;Ya=[];if(Y.length){R=za.createElementNS("http://www.w3.org/2000/svg","tspan");ya(R,{x:g,dy:z||16});b.appendChild(R);if(Ha>n)n=Ha}}else{R.removeChild(R.firstChild);
98 | Ya.unshift(Y.pop())}R.appendChild(za.createTextNode(Y.join(" ").replace(/- /g,"-")))}}}})})},crispLine:function(a,b){if(a[1]==a[4])a[1]=a[4]=U(a[1])+b%2/2;if(a[2]==a[5])a[2]=a[5]=U(a[2])+b%2/2;return a},path:function(a){return this.createElement("path").attr({d:a,fill:mb})},circle:function(a,b,c){a=Db(a)?a:{x:a,y:b,r:c};return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(Db(a)){b=a.y;c=a.r;d=a.innerR;e=a.start;f=a.end;a=a.x}return this.symbol("arc",a||0,b||0,c||0,{innerR:d||
99 | 0,start:e||0,end:f||0})},rect:function(a,b,c,d,e,f){if(arguments.length>1){var g=(f||0)%2/2;a=U(a||0)+g;b=U(b||0)+g;c=U((c||0)-2*g);d=U((d||0)-2*g)}g=Db(a)?a:{x:a,y:b,width:Da(c,0),height:Da(d,0)};return this.createElement("rect").attr(oa(g,{rx:e||g.r,ry:e||g.r,fill:mb}))},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[y(c,true)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){return this.createElement("g").attr(I(a)&&
100 | {"class":Zb+a})},image:function(a,b,c,d,e){var f={preserveAspectRatio:mb};arguments.length>1&&oa(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a);return f},symbol:function(a,b,c,d,e){var f,g=this.symbols[a];g=g&&g(b,c,d,e);var i=/^url\((.*?)\)$/;if(g){f=this.path(g);oa(f,{symbolName:a,x:b,y:c,r:d});e&&oa(f,e)}else if(i.test(a)){a=a.match(i)[1];f=this.image(a).attr({x:b,y:c});fb("img",{onload:function(){var l=de[this.src]||
101 | [this.width,this.height];f.attr({width:l[0],height:l[1]}).translate(-U(l[0]/2),-U(l[1]/2))},src:a})}else f=this.circle(b,c,d);return f},symbols:{square:function(a,b,c){c=0.707*c;return[Za,a-c,b-c,Ca,a+c,b-c,a+c,b+c,a-c,b+c,"Z"]},triangle:function(a,b,c){return[Za,a,b-1.33*c,Ca,a+c,b+0.67*c,a-c,b+0.67*c,"Z"]},"triangle-down":function(a,b,c){return[Za,a,b+1.33*c,Ca,a-c,b-0.67*c,a+c,b-0.67*c,"Z"]},diamond:function(a,b,c){return[Za,a,b-c,Ca,a+c,b,a,b+c,a-c,b,"Z"]},arc:function(a,b,c,d){var e=d.start,
102 | f=d.end-1.0E-6,g=d.innerR,i=jb(e),l=yb(e),j=jb(f);f=yb(f);d=d.end-e');if(b){c=b==Kb||b=="span"||b=="img"?c.join(""):a.prepVML(c);this.element=fb(c)}this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box;d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);yc&&d.gVis==ub&&
105 | Ia(c,{visibility:ub});d.appendChild(c);this.added=true;this.alignOnAdd&&this.updateTransform();return this},attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,i=f.nodeName,l=this.renderer,j=this.symbolName,n,z,F=this.shadows,W=this;if(Jb(a)&&I(b)){c=a;a={};a[c]=b}if(Jb(a)){c=a;W=c=="strokeWidth"||c=="stroke-width"?this.strokeweight:this[c]}else for(c in a){d=a[c];n=false;if(j&&/^(x|y|r|start|end|width|height|innerR)/.test(c)){if(!z){this.symbolAttr(a);z=true}n=true}else if(c=="d"){d=d||[];
106 | this.d=d.join(" ");e=d.length;for(n=[];e--;)n[e]=ac(d[e])?U(d[e]*10)-5:d[e]=="Z"?"x":d[e];d=n.join(" ")||"x";f.path=d;if(F)for(e=F.length;e--;)F[e].path=d;n=true}else if(c=="zIndex"||c=="visibility"){if(yc&&c=="visibility"&&i=="DIV"){f.gVis=d;n=f.childNodes;for(e=n.length;e--;)Ia(n[e],{visibility:d});if(d==Ab)d=null}if(d)g[c]=d;n=true}else if(/^(width|height)$/.test(c)){if(this.updateClipping){this[c]=d;this.updateClipping()}else g[c]=d;n=true}else if(/^(x|y)$/.test(c)){this[c]=d;if(f.tagName=="SPAN")this.updateTransform();
107 | else g[{x:"left",y:"top"}[c]]=d}else if(c=="class")f.className=d;else if(c=="stroke"){d=l.color(d,f,c);c="strokecolor"}else if(c=="stroke-width"||c=="strokeWidth"){f.stroked=d?true:false;c="strokeweight";this[c]=d;if(ac(d))d+=$a}else if(c=="dashstyle"){(f.getElementsByTagName("stroke")[0]||fb(l.prepVML([""]),null,null,f))[c]=d||"solid";this.dashstyle=d;n=true}else if(c=="fill")if(i=="SPAN")g.color=d;else{f.filled=d!=mb?true:false;d=l.color(d,f,c);c="fillcolor"}else if(c=="translateX"||c==
108 | "translateY"||c=="rotation"||c=="align"){if(c=="align")c="textAlign";this[c]=d;this.updateTransform();n=true}else if(c=="text"){f.innerHTML=d;n=true}if(F&&c=="visibility")for(e=F.length;e--;)F[e].style[c]=d;if(!n)if(yc)f[c]=d;else ya(f,c,d)}return W},clip:function(a){var b=this,c=a.members;c.push(b);b.destroyClip=function(){mc(c,b)};return b.css(a.getCSS(b.inverted))},css:function(a){var b=this.element;if(b=a&&b.tagName=="SPAN"&&a.width){delete a.width;this.textWidth=b;this.updateTransform()}this.styles=
109 | oa(this.styles,a);Ia(this.element,a);return this},destroy:function(){this.destroyClip&&this.destroyClip();Hc.prototype.destroy.apply(this)},empty:function(){for(var a=this.element.childNodes,b=a.length,c;b--;){c=a[b];c.parentNode.removeChild(c)}},getBBox:function(){var a=this.element;if(a.nodeName=="text")a.style.position=lc;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}},on:function(a,b){this.element["on"+a]=function(){var c=sb.event;c.target=c.srcElement;b(c)};return this},
110 | updateTransform:function(){if(this.added){var a=this,b=a.element,c=a.translateX||0,d=a.translateY||0,e=a.x||0,f=a.y||0,g=a.textAlign||"left",i={left:0,center:0.5,right:1}[g],l=g&&g!="left";if(c||d)a.css({marginLeft:c,marginTop:d});a.inverted&&t(b.childNodes,function(J){a.renderer.invertChild(J,b)});if(b.tagName=="SPAN"){var j,n;c=a.rotation;var z;j=0;d=1;var F=0,W;z=pa(a.textWidth);var ba=a.xCorr||0,ka=a.yCorr||0,v=[c,g,b.innerHTML,a.textWidth].join(",");if(v!=a.cTT){if(I(c)){j=c*Ud;d=jb(j);F=yb(j);
111 | Ia(b,{filter:c?["progid:DXImageTransform.Microsoft.Matrix(M11=",d,", M12=",-F,", M21=",F,", M22=",d,", sizingMethod='auto expand')"].join(""):mb})}j=b.offsetWidth;n=b.offsetHeight;if(j>z){Ia(b,{width:z+$a,display:"block",whiteSpace:"normal"});j=z}z=U(pa(b.style.fontSize||12)*1.2);ba=d<0&&-j;ka=F<0&&-n;W=d*F<0;ba+=F*z*(W?1-i:i);ka-=d*z*(c?W?i:1-i:1);if(l){ba-=j*i*(d<0?-1:1);if(c)ka-=n*i*(F<0?-1:1);Ia(b,{textAlign:g})}a.xCorr=ba;a.yCorr=ka}Ia(b,{left:e+ba,top:f+ka});a.cTT=v}}else this.alignOnAdd=true},
112 | shadow:function(a){var b=[],c=this.element,d=this.renderer,e,f=c.style,g,i=c.path;if(""+c.path==="")i="x";if(a){for(a=1;a<=3;a++){g=[''];e=fb(d.prepVML(g),null,{left:pa(f.left)+1,top:pa(f.top)+1});g=[''];fb(d.prepVML(g),null,null,e);c.parentNode.insertBefore(e,c);b.push(e)}this.shadows=b}return this}});Ma=function(){this.init.apply(this,
113 | arguments)};Ma.prototype=xa(Uc.prototype,{isIE8:xc.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d;this.Element=ge;this.alignedObjects=[];d=this.createElement(Kb);a.appendChild(d.element);this.box=d.element;this.boxWrapper=d;this.setSize(b,c,false);if(!za.namespaces.hcv){za.namespaces.add("hcv","urn:schemas-microsoft-com:vml");za.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}},clipRect:function(a,b,c,d){var e=
114 | this.createElement();return oa(e,{members:[],left:a,top:b,width:c,height:d,getCSS:function(f){var g=this.top,i=this.left,l=i+this.width,j=g+this.height;g={clip:"rect("+U(f?i:g)+"px,"+U(f?j:l)+"px,"+U(f?l:j)+"px,"+U(f?g:i)+"px)"};!f&&yc&&oa(g,{width:l+$a,height:j+$a});return g},updateClipping:function(){t(e.members,function(f){f.css(e.getCSS(f.inverted))})}})},color:function(a,b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f,g,i=a.linearGradient,l,j,n,z;t(a.stops,function(F,W){if(e.test(F[1])){d=
115 | Ub(F[1]);f=d.get("rgb");g=d.get("a")}else{f=F[1];g=1}if(W){n=f;z=g}else{l=f;j=g}});a=90-Ua.atan((i[3]-i[1])/(i[2]-i[0]))*180/Tb;c=["<",c,' colors="0% ',l,",100% ",n,'" angle="',a,'" opacity="',z,'" o:opacity2="',j,'" type="gradient" focus="100%" />'];fb(this.prepVML(c),null,null,b)}else if(e.test(a)&&b.tagName!="IMG"){d=Ub(a);c=["<",c,' opacity="',d.get("a"),'"/>'];fb(this.prepVML(c),null,null,b);return d.get("rgb")}else return a},prepVML:function(a){var b=this.isIE8;a=a.join("");if(b){a=a.replace("/>",
116 | ' xmlns="urn:schemas-microsoft-com:vml" />');a=a.indexOf('style="')==-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')}else a=a.replace("<","1&&f.css({left:b,top:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){if(arguments.length>1){var g=(f||0)%2/2;a=U(a||0)+g;b=U(b||0)+g;c=U((c||0)-2*g);d=U((d||0)-2*g)}if(Db(a)){b=a.y;c=a.width;d=a.height;e=a.r;a=a.x}return this.symbol("rect",
118 | a||0,b||0,e||0,{width:c||0,height:d||0})},invertChild:function(a,b){var c=b.style;Ia(a,{flip:"x",left:pa(c.width)-10,top:pa(c.height)-10,rotation:-90})},symbols:{arc:function(a,b,c,d){var e=d.start,f=d.end,g=jb(e),i=yb(e),l=jb(f),j=yb(f);d=d.innerR;var n=0.07/c,z=d&&0.1/d||0;if(f-e===0)return["x"];else if(2*Tb-f+e=c.length)Ib=0}a.chart.pointCount++;return this},applyOptions:function(a){var b=this.series;this.config=a;if(ac(a)||a===null)this.y=a;else if(Db(a)&&!ac(a.length)){oa(this,a);this.options=a}else if(Jb(a[0])){this.name=a[0];this.y=a[1]}else if(ac(a[0])){this.x=a[0];this.y=a[1]}if(this.x===Ra)this.x=b.autoIncrement()},destroy:function(){var a=this,b=a.series,c;b.chart.pointCount--;a==b.chart.hoverPoint&&a.onMouseOut();
121 | b.chart.hoverPoints=null;Bb(a);t(["graphic","tracker","group","dataLabel","connector"],function(d){a[d]&&a[d].destroy()});a.legendItem&&a.series.chart.legend.destroyItem(a);for(c in a)a[c]=null},select:function(a,b){var c=this,d=c.series.chart;c.selected=a=y(a,!c.selected);c.firePointEvent(a?"select":"unselect");c.setState(a&&"select");b||t(d.getSelectedPoints(),function(e){if(e.selected&&e!=c){e.selected=false;e.setState(db);e.firePointEvent("unselect")}})},onMouseOver:function(){var a=this.series.chart,
122 | b=a.tooltip,c=a.hoverPoint;c&&c!=this&&c.onMouseOut();this.firePointEvent("mouseOver");b&&!b.shared&&b.refresh(this);this.setState(xb);a.hoverPoint=this},onMouseOut:function(){this.firePointEvent("mouseOut");this.setState();this.series.chart.hoverPoint=null},tooltipFormatter:function(a){var b=this.series;return['',this.name||b.name,": ",!a?"x = "+(this.name||this.x)+", ":"","",!a?"y = ":"",this.y,"
"].join("")},getDataLabelText:function(){return this.series.options.dataLabels.formatter.call({x:this.x,
123 | y:this.y,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal})},update:function(a,b,c){var d=this,e=d.series,f=d.dataLabel,g=e.chart;b=y(b,true);d.firePointEvent("update",{options:a},function(){d.applyOptions(a);f&&f.attr({text:d.getDataLabelText()});if(Db(a)){e.getAttribs();d.graphic.attr(d.pointAttr[e.state])}e.isDirty=true;b&&g.redraw(c)})},remove:function(a,b){var c=this,d=c.series,e=d.chart,f=d.data;bc(b,e);a=y(a,true);c.firePointEvent("remove",null,function(){mc(f,
124 | c);c.destroy();d.isDirty=true;a&&e.redraw()})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;if(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])this.importEvents();if(a=="click"&&e.allowPointSelect)c=function(f){d.select(null,f.ctrlKey||f.metaKey||f.shiftKey)};La(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=xa(this.series.options.point,this.options).events,b;this.events=a;for(b in a)Qa(this,b,a[b]);this.hasImportedEvents=true}},setState:function(a){var b=
125 | this.series,c=b.options.states,d=vb[b.type].marker&&b.options.marker,e=d&&!d.enabled,f=(d=d&&d.states[a])&&d.enabled===false,g=b.stateMarkerGraphic,i=b.chart,l=this.pointAttr;a||(a=db);if(!(a==this.state||this.selected&&a!="select"||c[a]&&c[a].enabled===false||a&&(f||e&&!d.enabled))){if(this.graphic)this.graphic.attr(l[a]);else{if(a){if(!g)b.stateMarkerGraphic=g=i.renderer.circle(0,0,l[a].r).attr(l[a]).add(b.group);g.translate(this.plotX,this.plotY)}if(g)g[a?"show":"hide"]()}this.state=a}}};var lb=
126 | function(){};lb.prototype={isCartesian:true,type:"line",pointClass:zc,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},init:function(a,b){var c,d;d=a.series.length;this.chart=a;b=this.setOptions(b);oa(this,{index:d,options:b,name:b.name||"Series "+(d+1),state:db,pointAttr:{},visible:b.visible!==false,selected:b.selected===true});d=b.events;for(c in d)Qa(this,c,d[c]);if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=
127 | true;this.getColor();this.getSymbol();this.setData(b.data,false)},autoIncrement:function(){var a=this.options,b=this.xIncrement;b=y(b,a.pointStart,0);this.pointInterval=y(this.pointInterval,a.pointInterval,1);this.xIncrement=b+this.pointInterval;return b},cleanData:function(){var a=this.chart,b=this.data,c,d,e=a.smallestInterval,f,g;b.sort(function(i,l){return i.x-l.x});for(g=b.length-1;g>=0;g--)b[g-1]&&b[g-1].x==b[g].x&&b.splice(g-1,1);for(g=b.length-1;g>=0;g--)if(b[g-1]){f=b[g].x-b[g-1].x;if(d===
128 | Ra||fa+1&&b.push(c.slice(a+1,e));a=e}else e==c.length-1&&b.push(c.slice(a+1,e+1))});this.segments=b},setOptions:function(a){var b=this.chart.options.plotOptions;return xa(b[this.type],b.series,a)},getColor:function(){var a=this.chart.options.colors;this.color=this.options.color||a[Ib++]||"#0000ff";if(Ib>=a.length)Ib=0},getSymbol:function(){var a=
129 | this.chart.options.symbols;this.symbol=this.options.marker.symbol||a[Wc++];if(Wc>=a.length)Wc=0},addPoint:function(a,b,c,d){var e=this.data,f=this.graph,g=this.area,i=this.chart;a=(new this.pointClass).init(this,a);bc(d,i);if(f&&c)f.shift=c;if(g){g.shift=c;g.isArea=true}b=y(b,true);e.push(a);c&&e[0].remove(false);this.isDirty=true;b&&i.redraw()},setData:function(a,b){var c=this,d=c.data,e=c.initialColor,f=c.chart,g=d&&d.length||0;c.xIncrement=null;if(I(e))Ib=e;for(a=jc(nc(a||[]),function(i){return(new c.pointClass).init(c,
130 | i)});g--;)d[g].destroy();c.data=a;c.cleanData();c.getSegments();c.isDirty=true;f.isDirtyBox=true;y(b,true)&&f.redraw(false)},remove:function(a,b){var c=this,d=c.chart;a=y(a,true);if(!c.isRemoving){c.isRemoving=true;La(c,"remove",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=true;a&&d.redraw(b)})}c.isRemoving=false},translate:function(){for(var a=this.chart,b=this.options.stacking,c=this.xAxis.categories,d=this.yAxis,e=this.data,f=e.length;f--;){var g=e[f],i=g.x,l=g.y,j=g.low,n=d.stacks[(l<
131 | 0?"-":"")+this.stackKey];g.plotX=this.xAxis.translate(i);if(b&&this.visible&&n[i]){j=n[i];i=j.total;j.cum=j=j.cum-l;l=j+l;if(b=="percent"){j=i?j*100/i:0;l=i?l*100/i:0}g.percentage=i?g.y*100/i:0;g.stackTotal=i}if(I(j))g.yBottom=d.translate(j,0,1);if(l!==null)g.plotY=d.translate(l,0,1);g.clientX=a.inverted?a.plotHeight-g.plotX:g.plotX;g.category=c&&c[g.x]!==Ra?c[g.x]:g.x}},setTooltipPoints:function(a){var b=this.chart,c=b.inverted,d=[],e=U((c?b.plotTop:b.plotLeft)+b.plotSizeX),f,g,i=[];if(a)this.tooltipPoints=
132 | null;t(this.segments,function(l){d=d.concat(l)});if(this.xAxis&&this.xAxis.reversed)d=d.reverse();t(d,function(l,j){f=d[j-1]?d[j-1].high+1:0;for(g=l.high=d[j+1]?Lb((l.plotX+(d[j+1]?d[j+1].plotX:e))/2):e;f<=g;)i[c?e-f++:f++]=l});this.tooltipPoints=i},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(!(!Hb&&a.mouseIsDown)){b&&b!=this&&b.onMouseOut();this.options.events.mouseOver&&La(this,"mouseOver");this.tracker&&this.tracker.toFront();this.setState(xb);a.hoverSeries=this}},onMouseOut:function(){var a=
133 | this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;d&&d.onMouseOut();this&&a.events.mouseOut&&La(this,"mouseOut");c&&!a.stickyTracking&&c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this.chart,c=this.clipRect,d=this.options.animation;if(d&&!Db(d))d={};if(a){if(!c.isAnimating){c.attr("width",0);c.isAnimating=true}}else{c.animate({width:b.plotSizeX},d);this.animate=null}},drawPoints:function(){var a,b=this.data,c=this.chart,d,e,f,g,i,l;if(this.options.marker.enabled)for(f=
134 | b.length;f--;){g=b[f];d=g.plotX;e=g.plotY;l=g.graphic;if(e!==Ra&&!isNaN(e)){a=g.pointAttr[g.selected?"select":db];i=a.r;if(l)l.animate({x:d,y:e,r:i});else g.graphic=c.renderer.symbol(y(g.marker&&g.marker.symbol,this.symbol),d,e,i).attr(a).add(this.group)}}},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,i={};a=a||{};b=b||{};c=c||{};d=d||{};for(f in e){g=e[f];i[f]=y(a[g],b[f],c[f],d[f])}return i},getAttribs:function(){var a=this,b=vb[a.type].marker?a.options.marker:a.options,c=
135 | b.states,d=c[xb],e,f=a.color,g={stroke:f,fill:f},i=a.data,l=[],j,n=a.pointAttrToOptions;if(a.options.marker){d.radius=d.radius||b.radius+2;d.lineWidth=d.lineWidth||b.lineWidth+1}else d.color=d.color||Ub(d.color||f).brighten(d.brightness).get();l[db]=a.convertAttribs(b,g);t([xb,"select"],function(F){l[F]=a.convertAttribs(c[F],l[db])});a.pointAttr=l;for(f=i.length;f--;){g=i[f];if((b=g.options&&g.options.marker||g.options)&&b.enabled===false)b.radius=0;e=false;if(g.options)for(var z in n)if(I(b[n[z]]))e=
136 | true;if(e){j=[];c=b.states||{};e=c[xb]=c[xb]||{};if(!a.options.marker)e.color=Ub(e.color||g.options.color).brighten(e.brightness||d.brightness).get();j[db]=a.convertAttribs(b,l[db]);j[xb]=a.convertAttribs(c[xb],l[xb],j[db]);j.select=a.convertAttribs(c.select,l.select,j[db])}else j=l;g.pointAttr=j}},destroy:function(){var a=this,b=a.chart,c=/\/5[0-9\.]+ Safari\//.test(xc),d,e;Bb(a);a.legendItem&&a.chart.legend.destroyItem(a);t(a.data,function(f){f.destroy()});t(["area","graph","dataLabelsGroup","group",
137 | "tracker"],function(f){if(a[f]){d=c&&f=="group"?"hide":"destroy";a[f][d]()}});if(b.hoverSeries==a)b.hoverSeries=null;mc(b.series,a);for(e in a)delete a[e]},drawDataLabels:function(){if(this.options.dataLabels.enabled){var a,b,c=this.data,d=this.options.dataLabels,e,f=this.dataLabelsGroup,g=this.chart,i=g.inverted,l=this.type,j;if(!f)f=this.dataLabelsGroup=g.renderer.g(Zb+"data-labels").attr({visibility:this.visible?Ab:ub,zIndex:5}).translate(g.plotLeft,g.plotTop).add();j=d.color;if(j=="auto")j=null;
138 | d.style.color=y(j,this.color);t(c,function(n){var z=n.barX;z=z&&z+n.barW/2||n.plotX||-999;var F=y(n.plotY,-999),W=n.dataLabel,ba=d.align;e=n.getDataLabelText();a=(i?g.plotWidth-F:z)+d.x;b=(i?g.plotHeight-z:F)+d.y;if(l=="column")a+={left:-1,right:1}[ba]*n.barW/2||0;if(W)W.animate({x:a,y:b});else if(I(e))W=n.dataLabel=g.renderer.text(e,a,b).attr({align:ba,rotation:d.rotation,zIndex:1}).css(d.style).add(f);i&&!d.y&&W.attr({y:b+parseInt(W.styles.lineHeight)*0.9-W.getBBox().height/2})})}},drawGraph:function(){var a=
139 | this,b=a.options,c=a.graph,d=[],e,f=a.area,g=a.group,i=b.lineColor||a.color,l=b.lineWidth,j=b.dashStyle,n,z=a.chart.renderer,F=a.yAxis.getThreshold(b.threshold||0),W=/^area/.test(a.type),ba=[],ka=[];t(a.segments,function(v){n=[];t(v,function(V,R){if(a.getPointSpline)n.push.apply(n,a.getPointSpline(v,V,R));else{n.push(R?Ca:Za);R&&b.step&&n.push(V.plotX,v[R-1].plotY);n.push(V.plotX,V.plotY)}});if(v.length>1)d=d.concat(n);else ba.push(v[0]);if(W){var J=[],ea,Y=n.length;for(ea=0;ea=0;ea--)J.push(v[ea].plotX,v[ea].yBottom);else J.push(Ca,v[v.length-1].plotX,F,Ca,v[0].plotX,F);ka=ka.concat(J)}});a.graphPath=d;a.singlePoints=ba;if(W){e=y(b.fillColor,Ub(a.color).setOpacity(b.fillOpacity||0.75).get());if(f)f.animate({d:ka});else a.area=a.chart.renderer.path(ka).attr({fill:e}).add(g)}if(c)c.animate({d:d});else if(l){c={stroke:i,"stroke-width":l};if(j)c.dashstyle=j;a.graph=z.path(d).attr(c).add(g).shadow(b.shadow)}},
141 | render:function(){var a=this,b=a.chart,c,d,e=a.options,f=e.animation,g=f&&a.animate;f=g?f&&f.duration||500:0;var i=a.clipRect;d=b.renderer;if(!i){i=a.clipRect=!b.hasRendered&&b.clipRect?b.clipRect:d.clipRect(0,0,b.plotSizeX,b.plotSizeY);if(!b.clipRect)b.clipRect=i}if(!a.group){c=a.group=d.g("series");if(b.inverted){d=function(){c.attr({width:b.plotWidth,height:b.plotHeight}).invert()};d();Qa(b,"resize",d)}c.clip(a.clipRect).attr({visibility:a.visible?Ab:ub,zIndex:e.zIndex}).translate(b.plotLeft,b.plotTop).add(b.seriesGroup)}a.drawDataLabels();
142 | g&&a.animate(true);a.getAttribs();a.drawGraph&&a.drawGraph();a.drawPoints();a.options.enableMouseTracking!==false&&a.drawTracker();g&&a.animate();setTimeout(function(){i.isAnimating=false;if((c=a.group)&&i!=b.clipRect&&i.renderer){c.clip(a.clipRect=b.clipRect);i.destroy()}},f);a.isDirty=false},redraw:function(){var a=this.chart,b=this.group;if(b){a.inverted&&b.attr({width:a.plotWidth,height:a.plotHeight});b.animate({translateX:a.plotLeft,translateY:a.plotTop})}this.translate();this.setTooltipPoints(true);
143 | this.render()},setState:function(a){var b=this.options,c=this.graph,d=b.states;b=b.lineWidth;a=a||db;if(this.state!=a){this.state=a;if(!(d[a]&&d[a].enabled===false)){if(a)b=d[a].lineWidth||b+1;if(c&&!c.dashstyle)c.attr({"stroke-width":b},a?0:500)}}},setVisible:function(a,b){var c=this.chart,d=this.legendItem,e=this.group,f=this.tracker,g=this.dataLabelsGroup,i,l=this.data,j=c.options.chart.ignoreHiddenSeries;i=this.visible;i=(this.visible=a=a===Ra?!i:a)?"show":"hide";e&&e[i]();if(f)f[i]();else for(e=
144 | l.length;e--;){f=l[e];f.tracker&&f.tracker[i]()}g&&g[i]();d&&c.legend.colorizeItem(this,a);this.isDirty=true;this.options.stacking&&t(c.series,function(n){if(n.options.stacking&&n.visible)n.isDirty=true});if(j)c.isDirtyBox=true;b!==false&&c.redraw();La(this,i)},show:function(){this.setVisible(true)},hide:function(){this.setVisible(false)},select:function(a){this.selected=a=a===Ra?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;La(this,a?"select":"unselect")},drawTracker:function(){var a=
145 | this,b=a.options,c=[].concat(a.graphPath),d=c.length,e=a.chart,f=e.options.tooltip.snap,g=a.tracker,i=b.cursor;i=i&&{cursor:i};var l=a.singlePoints,j;if(d)for(j=d+1;j--;){c[j]==Za&&c.splice(j+1,0,c[j+1]-f,c[j+2],Ca);if(j&&c[j]==Za||j==d)c.splice(j,0,Ca,c[j-2]+f,c[j-1])}for(j=0;j
147 | a&&l>e){l=Da(a,e);n=2*e-l}else if(lg&&n>e){n=Da(g,e);l=2*e-n}else if(nv?Y-v:ka-(ea<=ka?v:0)}Ya=R-3}oa(J,{barX:V,barY:R,barW:W,barH:Ha});J.shapeType="rect";J.shapeArgs={x:V,y:R,width:W,height:Ha,r:l.borderRadius};J.trackerArgs=I(Ya)&&
150 | xa(J.shapeArgs,{height:Da(6,Ha+3),y:Ya})})},getSymbol:function(){},drawGraph:function(){},drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d,e;t(a.data,function(f){var g=f.plotY;if(g!==Ra&&!isNaN(g)){d=f.graphic;e=f.shapeArgs;if(d){Sc(d);d.animate(e)}else f.graphic=c[f.shapeType](e).attr(f.pointAttr[f.selected?"select":db]).add(a.group).shadow(b.shadow)}})},drawTracker:function(){var a=this,b=a.chart,c=b.renderer,d,e,f=+new Date,g=a.options.cursor,i=g&&{cursor:g},l;t(a.data,function(j){e=
151 | j.tracker;d=j.trackerArgs||j.shapeArgs;if(j.y!==null)if(e)e.attr(d);else j.tracker=c[j.shapeType](d).attr({isTracker:f,fill:Vd,visibility:a.visible?Ab:ub,zIndex:1}).on(Hb?"touchstart":"mouseover",function(n){l=n.relatedTarget||n.fromElement;b.hoverSeries!=a&&ya(l,"isTracker")!=f&&a.onMouseOver();j.onMouseOver()}).on("mouseout",function(n){if(!a.options.stickyTracking){l=n.relatedTarget||n.toElement;ya(l,"isTracker")!=f&&a.onMouseOut()}}).css(i).add(b.trackerGroup)})},animate:function(a){var b=this,
152 | c=b.data;if(!a){t(c,function(d){var e=d.graphic;if(e){e.attr({height:0,y:b.yAxis.translate(0,0,1)});e.animate({height:d.barH,y:d.barY},b.options.animation)}});b.animate=null}},remove:function(){var a=this,b=a.chart;b.hasRendered&&t(b.series,function(c){if(c.type==a.type)c.isDirty=true});lb.prototype.remove.apply(a,arguments)}});tb.column=Zc;Ma=wb(Zc,{type:"bar",init:function(a){a.inverted=this.inverted=true;Zc.prototype.init.apply(this,arguments)}});tb.bar=Ma;Ma=wb(lb,{type:"scatter",translate:function(){var a=
153 | this;lb.prototype.translate.apply(a);t(a.data,function(b){b.shapeType="circle";b.shapeArgs={x:b.plotX,y:b.plotY,r:a.chart.options.tooltip.snap}})},drawTracker:function(){var a=this,b=a.options.cursor,c=b&&{cursor:b},d;t(a.data,function(e){(d=e.graphic)&&d.attr({isTracker:true}).on("mouseover",function(){a.onMouseOver();e.onMouseOver()}).on("mouseout",function(){a.options.stickyTracking||a.onMouseOut()}).css(c)})},cleanData:function(){}});tb.scatter=Ma;Ma=wb(zc,{init:function(){zc.prototype.init.apply(this,
154 | arguments);var a=this,b;oa(a,{visible:a.visible!==false,name:y(a.name,"Slice")});b=function(){a.slice()};Qa(a,"select",b);Qa(a,"unselect",b);return a},setVisible:function(a){var b=this.series.chart,c=this.tracker,d=this.dataLabel,e=this.connector,f;f=(this.visible=a=a===Ra?!this.visible:a)?"show":"hide";this.group[f]();c&&c[f]();d&&d[f]();e&&e[f]();this.legendItem&&b.legend.colorizeItem(this,a)},slice:function(a,b,c){var d=this.series.chart,e=this.slicedTranslation;bc(c,d);y(b,true);a=this.sliced=
155 | I(a)?a:!this.sliced;this.group.animate({translateX:a?e[0]:d.plotLeft,translateY:a?e[1]:d.plotTop})}});Ma=wb(lb,{type:"pie",isCartesian:false,pointClass:Ma,pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},getColor:function(){this.initialColor=Ib},animate:function(){var a=this;t(a.data,function(b){var c=b.graphic;b=b.shapeArgs;var d=-Tb/2;if(c){c.attr({r:0,start:d,end:d});c.animate({r:b.r,start:b.start,end:b.end},a.options.animation)}});a.animate=null},translate:function(){var a=
156 | 0,b=-0.25,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f=c.center,g=this.chart,i=g.plotWidth,l=g.plotHeight,j,n,z,F=this.data,W=2*Tb,ba,ka=nb(i,l),v,J,ea,Y=c.dataLabels.distance;f.push(c.size,c.innerSize||0);f=jc(f,function(V,R){return(v=/%$/.test(V))?[i,l,ka,ka][R]*pa(V)/100:V});this.getX=function(V,R){z=Ua.asin((V-f[1])/(f[2]/2+Y));return f[0]+(R?-1:1)*jb(z)*(f[2]/2+Y)};this.center=f;t(F,function(V){a+=V.y});t(F,function(V){ba=a?V.y/a:0;j=U(b*W*1E3)/1E3;b+=ba;n=U(b*W*1E3)/1E3;V.shapeType="arc";
157 | V.shapeArgs={x:f[0],y:f[1],r:f[2]/2,innerR:f[3]/2,start:j,end:n};z=(n+j)/2;V.slicedTranslation=jc([jb(z)*d+g.plotLeft,yb(z)*d+g.plotTop],U);J=jb(z)*f[2]/2;ea=yb(z)*f[2]/2;V.tooltipPos=[f[0]+J*0.7,f[1]+ea*0.7];V.labelPos=[f[0]+J+jb(z)*Y,f[1]+ea+yb(z)*Y,f[0]+J+jb(z)*e,f[1]+ea+yb(z)*e,f[0]+J,f[1]+ea,Y<0?"center":z0,j,n,z=this.center[1],F=[[],[],[],[]],W,ba,ka,v,J,ea,Y,V=4,R;lb.prototype.drawDataLabels.apply(this);t(a,function(Ha){var Ya=Ha.labelPos[7];F[Ya<0?0:YaYa.y};V--;){a=0;b=[].concat(F[V]);b.sort(Y);for(R=b.length;R--;)b[R].rank=R;for(v=0;v<2;v++){n=(ea=V%3)?9999:-9999;J=ea?-1:1;for(R=0;Rn-j){ba=n+J*j;W=this.getX(ba,V>1);if(!ea&&ba+j>z||ea&&ba-j").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";bZ[a]=c}return bZ[a]}function cc(a,b){var c={};d.each(cb.concat.apply([],cb.slice(0,b)),function(){c[this]=a});return c}function bY(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bX(){try{return new a.XMLHttpRequest}catch(b){}}function bW(){d(a).unload(function(){for(var a in bU)bU[a](0,1)})}function bQ(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function N(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function F(a,b){return(a&&a!=="*"?a+".":"")+b.replace(r,"`").replace(s,"&")}function E(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,q=[],r=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function C(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function w(){return!0}function v(){return!1}function g(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function f(a,c,f){if(f===b&&a.nodeType===1){f=a.getAttribute("data-"+c);if(typeof f==="string"){try{f=f==="true"?!0:f==="false"?!1:f==="null"?null:d.isNaN(f)?e.test(f)?d.parseJSON(f):f:parseFloat(f)}catch(g){}d.data(a,c,f)}else f=b}return f}var c=a.document,d=function(){function I(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(I,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x=!1,y,z="then done fail isResolved isRejected promise".split(" "),A,B=Object.prototype.toString,C=Object.prototype.hasOwnProperty,D=Array.prototype.push,E=Array.prototype.slice,F=String.prototype.trim,G=Array.prototype.indexOf,H={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.1",length:0,size:function(){return this.length},toArray:function(){return E.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?D.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(E.apply(this,arguments),"slice",E.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:D,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=!0;if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",A,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",A),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&I()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):H[B.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!C.call(a,"constructor")&&!C.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||C.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1){var f=E.call(arguments,0),g=b,h=function(a){return function(b){f[a]=arguments.length>1?E.call(arguments,0):b,--g||c.resolveWith(e,f)}};while(b--)a=f[b],a&&d.isFunction(a.promise)?a.promise().then(h(b),c.reject):--g;g||c.resolveWith(e,f)}else c!==a&&c.resolve(a);return e},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),y=d._Deferred(),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){H["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),G&&(d.inArray=function(a,b){return G.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?A=function(){c.removeEventListener("DOMContentLoaded",A,!1),d.ready()}:c.attachEvent&&(A=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",A),d.ready())});return d}();(function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML=" a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e),b=e=f=null}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function"),b=null;return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}})();var e=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!g(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,h=b.nodeType,i=h?d.cache:b,j=h?b[d.expando]:d.expando;if(!i[j])return;if(c){var k=e?i[j][f]:i[j];if(k){delete k[c];if(!g(k))return}}if(e){delete i[j][f];if(!g(i[j]))return}var l=i[j][f];d.support.deleteExpando||i!=a?delete i[j]:i[j]=null,l?(i[j]={},h||(i[j].toJSON=d.noop),i[j][f]=l):h&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var g=this[0].attributes,h;for(var i=0,j=g.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var k=i?f:0,l=i?f+1:h.length;k=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=k.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&l.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var o=a.getAttributeNode("tabIndex");return o&&o.specified?o.value:m.test(a.nodeName)||n.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var p=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return p===null?b:p}h&&(a[c]=e);return a[c]}});var p=/\.(.*)$/,q=/^(?:textarea|input|select)$/i,r=/\./g,s=/ /g,t=/[^\w\s.|`]/g,u=function(a){return a.replace(t,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=v;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(){return typeof d!=="undefined"&&!d.event.triggered?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=v);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),u).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(p,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=!0,l[m]())}catch(q){}k&&(l["on"+m]=k),d.event.triggered=!1}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},B=function B(a){var c=a.target,e,f;if(q.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=A(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:B,beforedeactivate:B,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&B.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&B.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",A(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in z)d.event.add(this,c+".specialChange",z[c]);return q.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return q.test(this.nodeName)}},z=d.event.special.change.filters,z.focus=z.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function c(a){a=d.event.fix(a),a.type=b;return d.event.handle.call(this,a)}d.event.special[b]={setup:function(){this.addEventListener(a,c,!0)},teardown:function(){this.removeEventListener(a,c,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){return"text"===a.getAttribute("type")},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector,d=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(e){d=!0}b&&(k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(d||!l.match.PSEUDO.test(c)&&!/!=/.test(c))return b.call(a,c)}catch(e){}return k(c,null,null,[a]).length>0})}(),function(){var a=c.createElement("div");a.innerHTML="";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=L.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(N(c[0])||N(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=K.call(arguments);G.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!M[a]?d.unique(f):f,(this.length>1||I.test(e))&&H.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var P=/ jQuery\d+="(?:\d+|null)"/g,Q=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,S=/<([\w:]+)/,T=/",""],legend:[1,""],thead:[1,""],tr:[2,""],td:[3,""],col:[2,""],area:[1,""],_default:[0,"",""]};X.optgroup=X.option,X.tbody=X.tfoot=X.colgroup=X.caption=X.thead,X.th=X.td,d.support.htmlSerialize||(X._default=[1,"div","
"]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(P,""):null;if(typeof a!=="string"||V.test(a)||!d.support.leadingWhitespace&&Q.test(a)||X[(S.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(R,"<$1>$2>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){$(a,e),f=_(a),g=_(e);for(h=0;f[h];++h)$(f[h],g[h])}if(b){Z(a,e);if(c){f=_(a),g=_(e);for(h=0;f[h];++h)Z(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||U.test(i)){if(typeof i==="string"){i=i.replace(R,"<$1>$2>");var j=(S.exec(i)||["",""])[1].toLowerCase(),k=X[j]||X._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=T.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&Q.test(i)&&m.insertBefore(b.createTextNode(Q.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bb=/alpha\([^)]*\)/i,bc=/opacity=([^)]*)/,bd=/-([a-z])/ig,be=/([A-Z])/g,bf=/^-?\d+(?:px)?$/i,bg=/^-?\d/,bh={position:"absolute",visibility:"hidden",display:"block"},bi=["Left","Right"],bj=["Top","Bottom"],bk,bl,bm,bn=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bk(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bk)return bk(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bd,bn)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bo(a,b,e):d.swap(a,bh,function(){f=bo(a,b,e)});if(f<=0){f=bk(a,b,b),f==="0px"&&bm&&(f=bm(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bf.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return bc.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bb.test(f)?f.replace(bb,e):c.filter+" "+e}}),c.defaultView&&c.defaultView.getComputedStyle&&(bl=function(a,c,e){var f,g,h;e=e.replace(be,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bm=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bf.test(d)&&bg.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bk=bl||bm,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var bp=/%20/g,bq=/\[\]$/,br=/\r?\n/g,bs=/#.*$/,bt=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bu=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bv=/(?:^file|^widget|\-extension):$/,bw=/^(?:GET|HEAD)$/,bx=/^\/\//,by=/\?/,bz=/