#!/usr/bin/env perl
#------------------------------------------------------------------------------
#
# pgBadger - Advanced PostgreSQL log analyzer
#
# This program is open source, licensed under the PostgreSQL Licence.
# For license terms, see the LICENSE file.
#------------------------------------------------------------------------------
#
# Settings in postgresql.conf
#
# You should enable SQL query logging with log_min_duration_statement >= 0
# With stderr output
#  Log line prefix should be: log_line_prefix = '%t [%p]: '
#  Log line prefix should be: log_line_prefix = '%t [%p]: user=%u,db=%d '
#  Log line prefix should be: log_line_prefix = '%t [%p]: db=%d,user=%u '
# If you need report per client Ip adresses you can add client=%h or remote=%h
# pgbadger will also recognized the following form:
#     log_line_prefix = '%t [%p]: db=%d,user=%u,client=%h '
# or
#     log_line_prefix = '%t [%p]: user=%u,db=%d,remote=%h '
# With syslog output
#  Log line prefix should be: log_line_prefix = 'db=%d,user=%u '
#
# Additional information that could be collected and reported
#  log_checkpoints = on
#  log_connections = on
#  log_disconnections = on
#  log_lock_waits = on
#  log_temp_files = 0
#  log_autovacuum_min_duration = 0
#------------------------------------------------------------------------------
use vars qw($VERSION);

use strict qw(vars subs);

use Getopt::Long qw(:config no_ignore_case bundling);
use IO::File;
use Benchmark;
use File::Basename;
use Storable qw(store_fd fd_retrieve);
use Time::Local qw(timegm_nocheck timelocal_nocheck timegm timelocal);
use POSIX qw(locale_h sys_wait_h _exit strftime);
setlocale(LC_NUMERIC, '');
setlocale(LC_ALL,     'C');
use File::Spec qw/ tmpdir /;
use File::Temp qw/ tempfile /;
use IO::Handle;
use IO::Pipe;
use FileHandle;
use Socket;
use constant EBCDIC => "\t" ne "\011";
use Encode qw(encode decode);

$VERSION = '13.0';

$SIG{'CHLD'} = 'DEFAULT';

my $TMP_DIR      = File::Spec->tmpdir() || '/tmp';
my %RUNNING_PIDS = ();
my @tempfiles    = ();
my $parent_pid   = $$;
my $interrupt    = 0;
my $tmp_last_parsed = '';
my $tmp_dblist = '';
my @SQL_ACTION   = ('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'COPY FROM', 'COPY TO', 'CTE', 'DDL', 'TCL', 'CURSOR');
my @LATENCY_PERCENTILE = sort {$a <=> $b} (99,95,90);
my $graphid      = 1;
my $NODATA       = '<div class="jqplot-graph"><blockquote><b>NO DATASET</b></blockquote></div>';
my $MAX_QUERY_LENGTH = 25000;
my $terminate = 0;
my %CACHE_DNS = ();
my $DNSLookupTimeout = 1; # (in seconds)
my $EXPLAIN_URL = 'https://explain.depesz.com/';
my $EXPLAIN_POST = qq{<form method="POST" target="explain" action="%s"><input type="hidden" name="is_public" value="0"><input type="hidden" name="is_anon" value="0"><input type="hidden" name="plan" value=""></form>};
my $PID_DIR = $TMP_DIR;
my $PID_FILE = undef;
my %DBLIST = ();
my $DBALL = 'postgres';
my $LOG_EOL_TYPE = 'LF';

# Factor used to estimate the total size of compressed file
# when real size can not be obtained (bz2 or remote files)
my $BZ_FACTOR = 30;
my $GZ_FACTOR = 15;
my $XZ_FACTOR = 18;

my @E2A = (
   0,  1,  2,  3,156,  9,134,127,151,141,142, 11, 12, 13, 14, 15,
  16, 17, 18, 19,157, 10,  8,135, 24, 25,146,143, 28, 29, 30, 31,
 128,129,130,131,132,133, 23, 27,136,137,138,139,140,  5,  6,  7,
 144,145, 22,147,148,149,150,  4,152,153,154,155, 20, 21,158, 26,
  32,160,226,228,224,225,227,229,231,241,162, 46, 60, 40, 43,124,
  38,233,234,235,232,237,238,239,236,223, 33, 36, 42, 41, 59, 94,
  45, 47,194,196,192,193,195,197,199,209,166, 44, 37, 95, 62, 63,
 248,201,202,203,200,205,206,207,204, 96, 58, 35, 64, 39, 61, 34,
 216, 97, 98, 99,100,101,102,103,104,105,171,187,240,253,254,177,
 176,106,107,108,109,110,111,112,113,114,170,186,230,184,198,164,
 181,126,115,116,117,118,119,120,121,122,161,191,208, 91,222,174,
 172,163,165,183,169,167,182,188,189,190,221,168,175, 93,180,215,
 123, 65, 66, 67, 68, 69, 70, 71, 72, 73,173,244,246,242,243,245,
 125, 74, 75, 76, 77, 78, 79, 80, 81, 82,185,251,252,249,250,255,
  92,247, 83, 84, 85, 86, 87, 88, 89, 90,178,212,214,210,211,213,
  48, 49, 50, 51, 52, 53, 54, 55, 56, 57,179,219,220,217,218,159
);
if (EBCDIC && ord('^') == 106) { # as in the BS2000 posix-bc coded character set
     $E2A[74] = 96;   $E2A[95] = 159;  $E2A[106] = 94;  $E2A[121] = 168;
     $E2A[161] = 175; $E2A[173] = 221; $E2A[176] = 162; $E2A[186] = 172;
     $E2A[187] = 91;  $E2A[188] = 92;  $E2A[192] = 249; $E2A[208] = 166;
     $E2A[221] = 219; $E2A[224] = 217; $E2A[251] = 123; $E2A[253] = 125;
     $E2A[255] = 126;
}
elsif (EBCDIC && ord('^') == 176) { # as in codepage 037 on os400
  $E2A[21] = 133; $E2A[37] = 10;  $E2A[95] = 172; $E2A[173] = 221;
  $E2A[176] = 94; $E2A[186] = 91; $E2A[187] = 93; $E2A[189] = 168;
}

my $pgbadger_logo =
	'<img src="data:image/png;base64,
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
" class="pull-left" style="width:50px;height:auto">';
my $pgbadger_ico =
	'data:image/x-icon;base64,
AAABAAEAIyMQAAEABAA8BAAAFgAAACgAAAAjAAAARgAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAgAAGRsZACgqKQA2OTcASEpJAFpdWwBoa2kAeHt5AImMigCeoZ8AsLOxAMTHxQDR1NIA
5enmAPv+/AAAAAAA///////////////////////wAAD///////////H///////////AAAP//////
//9Fq7Yv////////8AAA////////8V7u7qD////////wAAD///////8B7qWN5AL///////AAAP//
///y8Avrc3rtMCH/////8AAA/////xABvbAAAJ6kAA/////wAAD////wAG5tQAAADp6RAP////AA
AP//MQBd7C2lRESOWe5xAD//8AAA//8APO7iC+7e7u4A3uxwBf/wAAD/9Aju7iAAvu7u0QAN7ukA
7/AAAP/wCe7kAAAF7ugAAAHO6xD/8AAA//AK7CAAAAHO1AAAABnrEP/wAAD/8ArAAAAAAc7kAAAA
AIwQ//AAAP/wCjAAAAAC3uQAAAAAHBCf8AAA//AIEBVnIATu5gAXZhAFEP/wAAD/8AIAqxdwBu7p
AFoX0QIQ//AAAP/wAAPsBCAL7u4QBwfmAAD/8AAA//AAA8owAC7u7lAAKbYAAJ/wAAD/8AAAAAAA
fu7uwAAAAAAA//AAAP/wAAAAAADu7u7jAAAAAAD/8AAA//AAAAAABe7u7uoAAAAAAP/wAAD/8AAA
AAAL7u7u7QAAAAAAn/AAAP/wAAAAAB3u7u7uYAAAAAD/8AAA//MAAAAATu7u7u6QAAAAAP/wAAD/
/wAAAAAM7u7u7TAAAAAD//AAAP//IQAAAAKu7u7UAAAAAB//8AAA////IAAAAAju7BAAAAAP///w
AAD////2AAA1je7ulUAAA/////AAAP/////xEAnO7u7pIAH/////8AAA//////9CABju6iACP///
///wAAD////////wAAggAP////////AAAP////////8wAAA/////////8AAA///////////w////
///////wAAD///////////////////////AAAP/////gAAAA//+//+AAAAD//Af/4AAAAP/4A//g
AAAA//AA/+AAAAD/oAA/4AAAAP8AAB/gAAAA/gAAD+AAAADwAAAB4AAAAPAAAADgAAAA4AAAAGAA
AADgAAAA4AAAAOAAAADgAAAA4AAAAOAAAADgAAAAYAAAAOAAAADgAAAA4AAAAOAAAADgAAAA4AAA
AOAAAABgAAAA4AAAAOAAAADgAAAA4AAAAOAAAADgAAAA4AAAAGAAAADgAAAA4AAAAOAAAADgAAAA
8AAAAOAAAADwAAAB4AAAAPwAAAfgAAAA/gAAD+AAAAD/gAA/4AAAAP/AAH/gAAAA//gD/+AAAAD/
/Af/4AAAAP//v//gAAAA/////+AAAAA
';

my %CLASS_ERROR_CODE = (
	'00' => 'Successful Completion',
	'01' => 'Warning',
	'02' => 'No Data (this is also a warning class per the SQL standard)',
	'03' => 'SQL Statement Not Yet Complete',
	'08' => 'Connection Exception',
	'09' => 'Triggered Action Exception',
	'0A' => 'Feature Not Supported',
	'0B' => 'Invalid Transaction Initiation',
	'0F' => 'Locator Exception',
	'0L' => 'Invalid Grantor',
	'0P' => 'Invalid Role Specification',
	'0Z' => 'Diagnostics Exception',
	'20' => 'Case Not Found',
	'21' => 'Cardinality Violation',
	'22' => 'Data Exception',
	'23' => 'Integrity Constraint Violation',
	'24' => 'Invalid Cursor State',
	'25' => 'Invalid Transaction State',
	'26' => 'Invalid SQL Statement Name',
	'27' => 'Triggered Data Change Violation',
	'28' => 'Invalid Authorization Specification',
	'2B' => 'Dependent Privilege Descriptors Still Exist',
	'2D' => 'Invalid Transaction Termination',
	'2F' => 'SQL Routine Exception',
	'34' => 'Invalid Cursor Name',
	'38' => 'External Routine Exception',
	'39' => 'External Routine Invocation Exception',
	'3B' => 'Savepoint Exception',
	'3D' => 'Invalid Catalog Name',
	'3F' => 'Invalid Schema Name',
	'40' => 'Transaction Rollback',
	'42' => 'Syntax Error or Access Rule Violation',
	'44' => 'WITH CHECK OPTION Violation',
	'53' => 'Insufficient Resources',
	'54' => 'Program Limit Exceeded',
	'55' => 'Object Not In Prerequisite State',
	'57' => 'Operator Intervention',
	'58' => 'System Error (errors external to PostgreSQL itself)',
	'72' => 'Snapshot Failure',
	'F0' => 'Configuration File Error',
	'HV' => 'Foreign Data Wrapper Error (SQL/MED)',
	'P0' => 'PL/pgSQL Error',
	'XX' => 'Internal Error',
);


####
# method used to fork as many child as wanted
##
sub spawn
{
	my $coderef = shift;

	unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
		print "usage: spawn CODEREF";
		exit 0;
	}

	my $pid;
	if (!defined($pid = fork)) {
		print STDERR "ERROR: cannot fork: $!\n";
		return;
	} elsif ($pid) {
		$RUNNING_PIDS{$pid} = $pid;
		return; # the parent
	}
	# the child -- go spawn
	$< = $>;
	$( = $); # suid progs only

	exit &$coderef();
}

# Command line options
my $journalctl_cmd          = '';
my $zcat_cmd                = 'gunzip -c';
my $zcat                    = $zcat_cmd;
my $bzcat                   = 'bunzip2 -c';
my $lz4cat                  = 'lz4cat';
my $ucat                    = 'unzip -p';
my $xzcat                   = 'xzcat';
my $zstdcat                 = 'zstdcat';
my $gzip_uncompress_size    = "gunzip -l \"%f\" | grep -E '^\\s*[0-9]+' | awk '{print \$2}'";

# lz4 archive can only contain one file.
# Original size can be retrieved only if --content-size has been used for compression
# it seems lz4 send output to stderr so redirect to stdout
my $lz4_uncompress_size     = " lz4 -v -c --list %f 2>&1 |tail -n 2|head -n1 | awk '{print \$6}'";

my $zip_uncompress_size     = "unzip -l %f | awk '{if (NR==4) print \$1}'";
my $xz_uncompress_size      = "xz --robot -l %f | grep totals | awk '{print \$5}'";
my $zstd_uncompress_size    = "zstd -v -l %f |grep Decompressed | awk  -F\"[ (]*\" '{print \$5}'";
my $format                  = '';
my @outfiles                = ();
my $outdir                  = '';
my $incremental             = '';
my $extra_files             = 0;
my $help                    = '';
my $ver                     = '';
my @dbname                  = ();
my @dbuser                  = ();
my @dbclient                = ();
my @dbappname               = ();
my @exclude_user            = ();
my @exclude_appname         = ();
my @exclude_db              = ();
my @exclude_client          = ();
my @exclude_line            = ();
my $ident                   = '';
my $top                     = 0;
my $sample                  = 3;
my $extension               = '';
my $maxlength               = 100000;
my $graph                   = 1;
my $nograph                 = 0;
my $debug                   = 0;
my $noprettify              = 0;
my $from                    = '';
my $to                      = '';
my $from_hour               = '';
my $to_hour                 = '';
my $quiet                   = 0;
my $progress                = 1;
my $error_only              = 0;
my @exclude_query           = ();
my @exclude_queryid         = ();
my @exclude_time            = ();
my @include_time            = ();
my $exclude_file            = '';
my @include_query           = ();
my $include_file            = '';
my $disable_error           = 0;
my $disable_hourly          = 0;
my $disable_type            = 0;
my $disable_query           = 0;
my $disable_session         = 0;
my $disable_connection      = 0;
my $disable_lock            = 0;
my $disable_temporary       = 0;
my $disable_checkpoint      = 0;
my $disable_autovacuum      = 0;
my $avg_minutes             = 5;
my $histo_avg_minutes       = 60;
my $last_parsed             = '';
my $report_title            = '';
my $log_line_prefix         = '';
my $compiled_prefix         = '';
my $project_url             = 'http://pgbadger.darold.net/';
my $t_min                   = 0;
my $t_max                   = 0;
my $remove_comment          = 0;
my $select_only             = 0;
my $queue_size              = 0;
my $job_per_file            = 0;
my $charset                 = 'utf-8';
my $csv_sep_char            = ',';
my %current_sessions        = ();
my %pgb_current_sessions    = ();
my $incr_date               = '';
my $last_incr_date          = '';
my $anonymize               = 0;
my $noclean                 = 0;
my $retention               = 0;
my $dns_resolv              = 0;
my $nomultiline             = 0;
my $noreport                = 0;
my $log_duration            = 0;
my $logfile_list            = '';
my $enable_checksum         = 0;
my $timezone                = 0;
my $opt_timezone            = 0;
my $pgbouncer_only          = 0;
my $rebuild                 = 0;
my $week_start_monday       = 0;
my $iso_week_number         = 0;
my $use_sessionid_as_pid    = 0;
my $dump_normalized_only    = 0;
my $log_timezone            = 0;
my $opt_log_timezone        = 0;
my $json_prettify           = 0;
my $report_per_database     = 0;
my $html_outdir             = '';
my $param_size_limit        = 24;
my $month_report            = 0;
my $day_report              = 0;
my $noexplain               = 0;
my $log_command             = '';
my $wide_char               = 0;
my $noweekreport            = 0;
my $query_numbering         = 0;
my $keep_comments           = 0;
my $no_progessbar           = 0;

my $NUMPROGRESS = 10;
my @DIMENSIONS  = (800, 300);
my $RESRC_URL   = '';
my $img_format  = 'png';
my @log_files   = ();
my %prefix_vars = ();
my $q_prefix    = '';
my @prefix_q_params = ();
my %last_execute_stmt = ();
my $disable_process_title = 0;
my $dump_all_queries = 0;
my $dump_raw_csv = 0;
my $header_done = 0;
my @include_pid = ();
my @include_session = ();

my $compress_extensions = qr/\.(zip|gz|xz|bz2|lz4|zst)$/i;

my $remote_host = '';
my $ssh_command = '';
my $ssh_bin = 'ssh';
my $ssh_port = 22;
my $ssh_identity = '';
my $ssh_user = '';
my $ssh_timeout = 10;
my $ssh_options = "-o ConnectTimeout=$ssh_timeout -o PreferredAuthentications=hostbased,publickey";
my $force_sample = 0;

my $curl_command = 'curl -k -s ';

my $sql_prettified = pgFormatter::Beautify->new('colorize' => 1, 'format' => 'html', 'uc_keywords' => 0);

# Flag for logs using UTC, in this case we don't autodetect the timezone
my $isUTC = 0;

# Do not display data in pie where percentage is lower than this value
# to avoid label overlapping.
my $pie_percentage_limit = 2;

# Get the decimal separator
my $n       = 5 / 2;
my $num_sep = ',';
$num_sep = ' ' if ($n =~ /,/);

# Set iso datetime pattern
my $time_pattern = qr/(\d{4})-(\d{2})-(\d{2})[\sT](\d{2}):(\d{2}):(\d{2})/;

# Inform the parent that it should stop iterate on parsing other files
sub stop_parsing
{
	&logmsg('DEBUG', "Received interrupt signal");
	$interrupt = 1;
}

# With multiprocess we need to wait for all children
sub wait_child
{
	my $sig = shift;

	$interrupt = 2;

	print STDERR "Received terminating signal ($sig).\n";
	1 while wait != -1;
	$SIG{INT} = \&wait_child;
	$SIG{TERM} = \&wait_child;
	foreach my $f (@tempfiles)
	{
		unlink("$f->[1]") if (-e "$f->[1]");
	}
	if ($report_per_database)
	{
		unlink("$tmp_dblist");
	}
	if ($last_parsed && -e "$tmp_last_parsed")
	{
		unlink("$tmp_last_parsed");
	}
	if ($last_parsed && -e "$last_parsed.tmp")
	{
		unlink("$last_parsed.tmp");
	}
	if (-e "$PID_FILE")
	{
		unlink("$PID_FILE");
	}
	_exit(2);
}
$SIG{INT} = \&wait_child;
$SIG{TERM} = \&wait_child;
if ($^O !~ /MSWin32|dos/i) {
	$SIG{USR2} = \&stop_parsing;
}

$| = 1;

my $histogram_query = '';
my $histogram_session = '';

# get the command line parameters
my $result = GetOptions(
	"a|average=i"              => \$avg_minutes,
	"A|histo-average=i"        => \$histo_avg_minutes,
	"b|begin=s"                => \$from,
	"c|dbclient=s"             => \@dbclient,
	"C|nocomment!"             => \$remove_comment,
	"d|dbname=s"               => \@dbname,
	"D|dns-resolv!"            => \$dns_resolv,
	"e|end=s"                  => \$to,
	"E|explode!"               => \$report_per_database,
	"f|format=s"               => \$format,
	"G|nograph!"               => \$nograph,
	"h|help!"                  => \$help,
	"H|html-outdir=s"          => \$html_outdir,
	"i|ident=s"                => \$ident,
	"I|incremental!"           => \$incremental,
	"j|jobs=i"                 => \$queue_size,
	"J|Jobs=i"                 => \$job_per_file,
	"l|last-parsed=s"          => \$last_parsed,
	"L|logfile-list=s"         => \$logfile_list,
	"m|maxlength=i"            => \$maxlength,
	"M|no-multiline!"          => \$nomultiline,
	"N|appname=s"              => \@dbappname,
	"o|outfile=s"              => \@outfiles,
	"O|outdir=s"               => \$outdir,
	"p|prefix=s"               => \$log_line_prefix,
	"P|no-prettify!"           => \$noprettify,
	"q|quiet!"                 => \$quiet,
	"Q|query-numbering!"       => \$query_numbering,
	"r|remote-host=s"          => \$remote_host,
	'R|retention=i'	           => \$retention,
	"s|sample=i"               => \$sample,
	"S|select-only!"           => \$select_only,
	"t|top=i"                  => \$top,
	"T|title=s"                => \$report_title,
	"u|dbuser=s"               => \@dbuser,
	"U|exclude-user=s"         => \@exclude_user,
	"v|verbose!"               => \$debug,
	"V|version!"               => \$ver,
	"w|watch-mode!"            => \$error_only,
	"W|wide-char!"             => \$wide_char,
	"x|extension=s"            => \$extension,
	"X|extra-files!"           => \$extra_files,
	"z|zcat=s"                 => \$zcat,
	"Z|timezone=f"             => \$opt_timezone,
	"pie-limit=i"              => \$pie_percentage_limit,
	"image-format=s"           => \$img_format,
	"exclude-query=s"          => \@exclude_query,
	"exclude-queryid=s"        => \@exclude_queryid,
	"exclude-file=s"           => \$exclude_file,
	"exclude-db=s"             => \@exclude_db,
	"exclude-client=s"         => \@exclude_client,
	"exclude-appname=s"        => \@exclude_appname,
	"include-query=s"          => \@include_query,
	"exclude-line=s"           => \@exclude_line,
	"include-file=s"           => \$include_file,
	"disable-error!"           => \$disable_error,
	"disable-hourly!"          => \$disable_hourly,
	"disable-type!"            => \$disable_type,
	"disable-query!"           => \$disable_query,
	"disable-session!"         => \$disable_session,
	"disable-connection!"      => \$disable_connection,
	"disable-lock!"            => \$disable_lock,
	"disable-temporary!"       => \$disable_temporary,
	"disable-checkpoint!"      => \$disable_checkpoint,
	"disable-autovacuum!"      => \$disable_autovacuum,
	"charset=s"                => \$charset,
	"csv-separator=s"          => \$csv_sep_char,
	"include-time=s"           => \@include_time,
	"exclude-time=s"           => \@exclude_time,
	'ssh-command=s'	           => \$ssh_command,
	'ssh-program=s'	           => \$ssh_bin,
	'ssh-port=i'	           => \$ssh_port,
	'ssh-identity=s'	   => \$ssh_identity,
	'ssh-option=s'	           => \$ssh_options,
	'ssh-user=s'	           => \$ssh_user,
	'ssh-timeout=i'	           => \$ssh_timeout,
	'anonymize!'	           => \$anonymize,
	'noclean!'		   => \$noclean,
	'noreport!'	           => \$noreport,
	'log-duration!'	           => \$log_duration,
	'enable-checksum!'	   => \$enable_checksum,
	'journalctl=s'	           => \$journalctl_cmd,
	'pid-dir=s'		   => \$PID_DIR,
	'pid-file=s'		   => \$PID_FILE,
	'rebuild!'		   => \$rebuild,
	'pgbouncer-only!'	   => \$pgbouncer_only,
	'start-monday!'	           => \$week_start_monday,
	'iso-week-number!'	   => \$iso_week_number,
	'normalized-only!'	   => \$dump_normalized_only,
	'log-timezone=f'	   => \$opt_log_timezone,
	'prettify-json!'	   => \$json_prettify,
	'month-report=s'	   => \$month_report,
	'day-report=s'	           => \$day_report,
	'noexplain!'               => \$noexplain,
	'command=s'                => \$log_command,
	'no-week!'                 => \$noweekreport,
	'explain-url=s'            => \$EXPLAIN_URL,
	'tempdir=s'                => \$TMP_DIR,
	'no-process-info!'         => \$disable_process_title,
	'dump-all-queries!'        => \$dump_all_queries,
	'keep-comments!'           => \$keep_comments,
	'no-progressbar!'          => \$no_progessbar,
	'dump-raw-csv!'            => \$dump_raw_csv,
	'include-pid=i'            => \@include_pid,
	'include-session=s'        => \@include_session,
	'histogram-query=s'        => \$histogram_query,
	'histogram-session=s'      => \$histogram_session,
);
die "FATAL: use pgbadger --help\n" if (not $result);

# Force rebuild mode when a month report is asked
$rebuild =  1 if ($month_report);
$rebuild =  2 if ($day_report);

# Set report title
$report_title = &escape_html($report_title) if $report_title;

# Show version and exit if asked
if ($ver) {
	print "pgBadger version $VERSION\n";
	exit 0;
}
&usage() if ($help);

# Create temporary file directory if not exists
mkdir("$TMP_DIR") if (!-d "$TMP_DIR");
if (!-d "$TMP_DIR")
{
	die("Can not use temporary directory $TMP_DIR.\n");
}

# Try to load Digest::MD5 when asked
if ($enable_checksum)
{
	if (eval {require Digest::MD5;1} ne 1) {
		die("Can not load Perl module Digest::MD5.\n");
	} else {
		Digest::MD5->import('md5_hex');
	}
}

# Check if another process is already running
unless ($PID_FILE) {
  $PID_FILE = $PID_DIR . '/pgbadger.pid';
}

if (-e "$PID_FILE")
{
	my $is_running = 2;
	if ($^O !~ /MSWin32|dos/i) {
		eval { $is_running = `ps auwx | grep pgbadger | grep -v grep | wc -l`; chomp($is_running); };
	}
	if (!$@ && ($is_running <= 1)) {
		unlink("$PID_FILE");
	} else {
		print "FATAL: another process is already started or remove the file, see $PID_FILE\n";
		exit 3;
	}
}

# Create pid file
if (open(my $out, '>', $PID_FILE))
{
	print $out $$;
	close($out);
}
else
{
	print "FATAL: can't create pid file $PID_FILE, $!\n";
	exit 3;
}

# Rewrite some command line arguments as lists
&compute_arg_list();

# If pgBadger must parse remote files set the ssh command
# If no user defined ssh command have been set
my $remote_command = '';
if ($remote_host && !$ssh_command) {
	$remote_command = &set_ssh_command($ssh_command, $remote_host);
}

# Add journalctl command to the file list if not already found
if ($journalctl_cmd)
{
	if (!grep(/^\Q$journalctl_cmd\E$/, @ARGV))
	{
		$journalctl_cmd .= " --output='short-iso'";
		push(@ARGV, $journalctl_cmd);
	}
}

# Add custom command to file list
if ($log_command)
{
	if (!grep(/^\Q$log_command\E$/, @ARGV)) {
		push(@ARGV, $log_command);
	}
}

# Log files to be parsed are passed as command line arguments
my $empty_files = 1;
if ($#ARGV >= 0)
{
	if (!$month_report) {
		foreach my $file (@ARGV) {
			push(@log_files, &set_file_list($file));
		}
	} elsif (!$outdir) { 
		$outdir = $ARGV[0];
	}
}

if (!$incremental && $html_outdir) {
	localdie("FATAL: parameter -H, --html-outdir can only be used with incremental mode.\n");
}

# Read list of log file to parse from a file
if ($logfile_list)
{
	if (!-e $logfile_list) {
		localdie("FATAL: logfile list $logfile_list must exist!\n");
	}
	my $in = undef;
	if (not open($in, "<", $logfile_list)) {
		localdie("FATAL: can not read logfile list $logfile_list, $!.\n");
	}
	my @files = <$in>;
	close($in);
	foreach my $file (@files)
	{
		chomp($file);
		$file =~ s/\r//;
		if ($file eq '-') {
			localdie("FATAL: stdin input - can not be used with logfile list.\n");
		}
		push(@log_files, &set_file_list($file));
	}
}

# Do not warn if all log files are empty
if (!$rebuild && $empty_files)
{
	&logmsg('DEBUG', "All log files are empty, exiting...");
	unlink("$PID_FILE");
	exit 0;
}

# Logfile is a mandatory parameter when journalctl command is not set.
if ( !$rebuild && ($#log_files < 0) && !$journalctl_cmd && !$log_command)
{
	if (!$quiet) {
		localdie("FATAL: you must give a log file at command line parameter.\n\n", 4);
	}
	else
	{
		unlink("$PID_FILE");
		exit 4;
	}
}

if ($#outfiles >= 1 && ($dump_normalized_only || $dump_all_queries)) {
	localdie("FATAL: dump of normalized queries can not ne used with multiple output.\n\n");
}

# Remove follow option from journalctl command to prevent infinit loop
if ($journalctl_cmd) {
	$journalctl_cmd =~ s/(-f|--follow)\b//;
}

# Quiet mode is forced with progress bar
$progress = 0 if ($quiet || $no_progessbar);

# Set the default number minutes for queries and connections average
$avg_minutes ||= 5;
$avg_minutes = 60 if ($avg_minutes > 60);
$avg_minutes = 1  if ($avg_minutes < 1);
$histo_avg_minutes ||= 60;
$histo_avg_minutes = 60 if ($histo_avg_minutes > 60);
$histo_avg_minutes = 1  if ($histo_avg_minutes < 1);
my @avgs   = ();
for (my $i = 0 ; $i < 60 ; $i += $avg_minutes) {
	push(@avgs, sprintf("%02d", $i));
}
my @histo_avgs = ();
for (my $i = 0 ; $i < 60 ; $i += $histo_avg_minutes) {
	push(@histo_avgs, sprintf("%02d", $i));
}

# Set the URL  to submit explain plan
$EXPLAIN_POST = sprintf($EXPLAIN_POST, $EXPLAIN_URL);

# Set error like log level regex
my $parse_regex      = qr/^(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|HINT|STATEMENT|CONTEXT|LOCATION)/;
my $full_error_regex = qr/^(WARNING|ERROR|FATAL|PANIC|DETAIL|HINT|STATEMENT|CONTEXT)/;
my $main_error_regex = qr/^(WARNING|ERROR|FATAL|PANIC)/;
my $main_log_regex = qr/^(LOG|WARNING|ERROR|FATAL|PANIC)/;

# Set syslog prefix regex
my $other_syslog_line = '';
my $pgbouncer_log_format =  '';
my $pgbouncer_log_parse1 = '';
my $pgbouncer_log_parse2 = '';
my $pgbouncer_log_parse3 = '';

# Variable to store parsed data following the line prefix
my @prefix_params = ();
my @pgb_prefix_params = ();
my @pgb_prefix_parse1 = ();
my @pgb_prefix_parse2 = ();
my @pgb_prefix_parse3 = ();

# Force incremental mode when rebuild mode is used
if ($rebuild && !$incremental) {
	print STDERR "WARNING: --rebuild require incremental mode, activating it.\n" if (!$month_report || !$day_report);
	$incremental = 1;
}

&logmsg('DEBUG', "pgBadger version $VERSION." );

# set timezone to use
&set_timezone(1);

# Set default top query
$top ||= 20;

# Set output file
my $outfile = '';
$outfile = $outfiles[0] if ($#outfiles >= 0);
if (($dump_normalized_only || $dump_all_queries) && $outfile && $outfile !~ /\.txt$/){
	localdie("FATAL: dump of normalized queries can be done in text output format, please use .txt extension.\n\n");
}

# With multiple output format we must use a temporary binary file
my $dft_extens = '';
if ($#outfiles >= 1)
{
	# We can not have multiple output in incremental mode
	if ($incremental)
	{
		localdie("FATAL: you can not use multiple output format with incremental mode.\n\n");
	}

	# Set temporary binary file.
	$outfile = $TMP_DIR . "/pgbadger_tmp_$$.bin";

	# Remove the default output format for the moment
	# otherwise all dump will have the same output
	$dft_extens = $extension;
	$extension = '';
}
elsif ($#outfiles == -1)
{
	$extension = 'txt' if ($dump_normalized_only || $dump_all_queries);
	($extension) ? push(@outfiles, 'out.' . $extension) : push(@outfiles, 'out.html');
	map { s/\.text/.txt/; } @outfiles;

}

# Set the default extension and output format, load JSON Perl module if required
# Force text output with normalized query list only and disable incremental report
# Set default filename of the output file
my ($current_out_file, $extens) = &set_output_extension($outdir, $outfile, $extension);

# Set default syslog ident name
$ident ||= 'postgres';

# Set default pie percentage limit or fix value
$pie_percentage_limit = 0   if ($pie_percentage_limit < 0);
$pie_percentage_limit = 2   if ($pie_percentage_limit eq '');
$pie_percentage_limit = 100 if ($pie_percentage_limit > 100);

# Set default download image format
$img_format = lc($img_format);
$img_format = 'jpeg' if ($img_format eq 'jpg');
$img_format = 'png' if ($img_format ne 'jpeg');

# Extract the output directory from outfile so that graphs will
# be created in the same directory
if ($current_out_file ne '-')
{
	if (!$html_outdir && !$outdir)
	{
		my @infs = fileparse($current_out_file);
		if ($infs[0] ne '')
		{
			$outdir = $infs[1];
		}
		else
		{
			# maybe a confusion between -O and -o
			localdie("FATAL: output file $current_out_file is a directory, should be a file\nor maybe you want to use -O | --outdir option instead.\n");
		}
	}
	elsif ($outdir && !-d "$outdir")
	{
		# An output directory has been passed as command line parameter
		localdie("FATAL: $outdir is not a directory or doesn't exist.\n");
	}
	elsif ($html_outdir && !-d "$html_outdir")
	{
		# An HTML output directory has been passed as command line parameter
		localdie("FATAL: $html_outdir is not a directory or doesn't exist.\n");
	}
	$current_out_file = basename($current_out_file);
	$current_out_file = ($html_outdir || $outdir) . '/' . $current_out_file;
	$current_out_file =~ s#//#/#g;
}

# Remove graph support if output is not html
$graph = 0 unless ($extens eq 'html' or $extens eq 'binary' or $extens eq 'json');
$graph = 0 if ($nograph);

# Set some default values
my $end_top = $top - 1;
$queue_size ||= 1;
$job_per_file ||= 1;

if ($^O =~ /MSWin32|dos/i) {
	if ( ($queue_size > 1) || ($job_per_file > 1) ) {
		print STDERR "WARNING: parallel processing is not supported on this platform.\n";
		$queue_size = 1;
		$job_per_file = 1;
	}
}

# Test file creation before going to parse log
my $tmpfh = new IO::File ">$current_out_file";
if (not defined $tmpfh) {
	localdie("FATAL: can't write to $current_out_file, $!\n");
}
$tmpfh->close();
unlink($current_out_file) if (-e $current_out_file);

# -w and --disable-error can't go together
if ($error_only && $disable_error) {
	localdie("FATAL: please choose between no event report and reporting events only.\n");
}

# Set default search pattern for database, user name, application name and host in log_line_prefix
my $regex_prefix_dbname = qr/(?:db|database)=([^,]*)/;
my $regex_prefix_dbuser = qr/(?:user|usr)=([^,]*)/;
my $regex_prefix_dbclient = qr/(?:client|remote|ip|host|connection_source)=([^,\(]*)/;
my $regex_prefix_dbappname = qr/(?:app|application|application_name)=([^,]*)/;
my $regex_prefix_queryid = qr/(?:queryid)=([^,]*)/;
my $regex_prefix_sqlstate = qr/(?:error_code|state|state_code)=([^,]*)/;
my $regex_prefix_backendtype = qr/(?:backend_type|btype)=([^,]*)/;

# Set pattern to look for query type
my $action_regex = qr/^[\s\(]*(DELETE|INSERT|UPDATE|SELECT|COPY|WITH|CREATE|DROP|ALTER|TRUNCATE|BEGIN|COMMIT|ROLLBACK|START|END|SAVEPOINT|DECLARE|CLOSE|FETCH|MOVE)/is;


# Loading excluded query from file if any
if ($exclude_file) {
	open(my $in, '<', $exclude_file) or localdie("FATAL: can't read file $exclude_file: $!\n");
	my @exclq = <$in>;
	close($in);
	chomp(@exclq);
	foreach my $r (@exclq) {
		$r =~ s/\r//;
		&check_regex($r, '--exclude-file');
	}
	push(@exclude_query, @exclq);
}

# Testing regex syntax
if ($#exclude_query >= 0) {
	foreach my $r (@exclude_query) {
		&check_regex($r, '--exclude-query');
	}
}

# Testing regex syntax
if ($#exclude_time >= 0) {
	foreach my $r (@exclude_time) {
		&check_regex($r, '--exclude-time');
	}
}
#
# Testing regex syntax
if ($#include_time >= 0) {
	foreach my $r (@include_time) {
		&check_regex($r, '--include-time');
	}
}

# Loading included query from file if any
if ($include_file) {
	open(my $in, '<', $include_file) or localdie("FATAL: can't read file $include_file: $!\n");
	my @exclq = <$in>;
	close($in);
	chomp(@exclq);
	foreach my $r (@exclq) {
		$r =~ s/\r//;
		&check_regex($r, '--include-file');
	}
	push(@include_query, @exclq);
}

# Testing regex syntax
if ($#include_query >= 0) {
	foreach my $r (@include_query) {
		&check_regex($r, '--include-query');
	}
}

# Check start/end date time
if ($from)
{
    if ( $from =~ /^(\d{2}):(\d{2}):(\d{2})([.]\d+([+-]\d+)?)?$/)
    {
        # only time, trick around the date part
        my $fractional_seconds = $4 || "0";
        $from_hour = "$1:$2:$3.$fractional_seconds";
        &logmsg('DEBUG', "Setting begin time to [$from_hour]" );
    }
    elsif( $from =~ /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})([.]\d+([+-]\d+)?)?$/ )
    {
        my $fractional_seconds = $7 || "0";
        $from = "$1-$2-$3 $4:$5:$6.$fractional_seconds";
        &logmsg('DEBUG', "Setting begin datetime to [$from]" );
    }
    else
    {
        localdie("FATAL: bad format for begin datetime/time, should be yyyy-mm-dd hh:mm:ss.l+tz or hh:mm:ss.l+tz\n");
    }
}

if ($to)
{
    if ( $to =~ /^(\d{2}):(\d{2}):(\d{2})([.]\d+([+-]\d+)?)?$/)
    {
        # only time, trick around the date part
        my $fractional_seconds = $4 || "0";
        $to_hour = "$1:$2:$3.$fractional_seconds";
        &logmsg('DEBUG', "Setting end time to [$to_hour]" );
    }
    elsif( $to =~ /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})([.]\d+([+-]\d+)?)?$/)
    {
        my $fractional_seconds = $7 || "0";
        $to = "$1-$2-$3 $4:$5:$6.$fractional_seconds";
        &logmsg('DEBUG', "Setting end time to [$to]" );
    }
    else
    {
        localdie("FATAL: bad format for ending datetime, should be yyyy-mm-dd hh:mm:ss.l+tz or hh:mm:ss.l+tz\n");
    }
}
if ($from && $to && ($from gt $to)) {
	localdie("FATAL: begin date is after end date!\n") ;
}

# Stores the last parsed line from log file to allow incremental parsing
my $LAST_LINE = '';

# Set the level of the data aggregator, can be minute, hour or day follow the
# size of the log file.
my $LEVEL = 'hour';

# Month names
my %month_abbr = (
	'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06',
	'Jul' => '07', 'Aug' => '08', 'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12'
);
my %abbr_month = (
	'01' => 'Jan', '02' => 'Feb', '03' => 'Mar', '04' => 'Apr', '05' => 'May', '06' => 'Jun',
	'07' => 'Jul', '08' => 'Aug', '09' => 'Sep', '10' => 'Oct', '11' => 'Nov', '12' => 'Dec'
);

# Inbounds of query times histogram
my @histogram_query_time = (0, 1, 5, 10, 25, 50, 100, 500, 1000, 10000);

# Inbounds of session times histogram
my @histogram_session_time = (0, 500, 1000, 30000, 60000, 600000, 1800000, 3600000, 28800000);

# Check histogram values user redefinition
if ($histogram_query)
{
	if ($histogram_query =~ /[^0-9\s,]+/) {
		die("Incorrect value for option --histogram_query\n");
	}
	@histogram_query_time = split(/\s*,\s*/, $histogram_query);
}
if ($histogram_session)
{
	if ($histogram_session =~ /[^0-9\s,]+/) {
		die("Incorrect value for option --histogram_session\n");
	}
	@histogram_session_time = split(/\s*,\s*/, $histogram_session);
}


# Where statistics are stored
my %overall_stat	= ();
my %pgb_overall_stat    = ();
my %overall_checkpoint  = ();
my %top_slowest	        = ();
my %normalyzed_info     = ();
my %error_info	        = ();
my %pgb_error_info      = ();
my %pgb_pool_info       = ();
my %logs_type	        = ();
my %errors_code	        = ();
my %per_minute_info     = ();
my %pgb_per_minute_info = ();
my %lock_info	        = ();
my %tempfile_info       = ();
my %cancelled_info      = ();
my %connection_info     = ();
my %pgb_connection_info = ();
my %database_info       = ();
my %application_info    = ();
my %user_info	        = ();
my %host_info	        = ();
my %session_info	= ();
my %pgb_session_info    = ();
my %conn_received       = ();
my %checkpoint_info     = ();
my %autovacuum_info     = ();
my %autoanalyze_info    = ();
my @graph_values	= ();
my %cur_info	        = ();
my %cur_temp_info       = ();
my %cur_plan_info       = ();
my %cur_cancel_info     = ();
my %cur_lock_info       = ();
my $nlines	        = 0;
my %last_line	        = ();
my %pgb_last_line       = ();
our %saved_last_line    = ();
our %pgb_saved_last_line= ();
my %top_locked_info     = ();
my %top_tempfile_info   = ();
my %top_cancelled_info  = ();
my %drawn_graphs	= ();
my %cur_bind_info       = ();
my %prepare_info        = ();
my %bind_info           = ();

# Global output filehandle
my $fh = undef;

my $t0 = Benchmark->new;

# Write resources files from __DATA__ section if they have not been already copied
# and return the HTML links to that files. If --extra-file is not used returns the
# CSS and JS code to be embeded in HTML files
my @jscode = &write_resources();

# Automatically set parameters with incremental mode
if ($incremental)
{
	# In incremental mode an output directory must be set
	if (!$html_outdir && !$outdir)
	{
		localdie("FATAL: you must specify an output directory with incremental mode, see -O or --outdir.\n")
	}
	# Ensure this is not a relative path
	if ($outdir && dirname($outdir) eq '.')
	{
		localdie("FATAL3: output directory ($outdir) is not an absolute path.\n");
	}
	if ($html_outdir && dirname($html_outdir) eq '.')
	{
		localdie("FATAL: output HTML directory ($html_outdir) is not an absolute path.\n");
	}
	# Ensure that the directory already exists
	if ($outdir && !-d $outdir)
	{
		localdie("FATAL: output directory $outdir does not exists.\n");
	}
	# Verify that the HTML outdir exixts when specified
	if ($html_outdir && !-d $html_outdir)
	{
		localdie("FATAL: output HTML directory $html_outdir does not exists.\n");
	}
	# Set default last parsed file in incremental mode
	if (!$last_parsed && $incremental)
	{
		$last_parsed = $outdir . '/LAST_PARSED';
	}
	$current_out_file = 'index.html';

	# Set default output format
	$extens = 'binary';

	if ($rebuild && !$month_report && !$day_report)
	{
		# Look for directory where report must be generated again
		my @build_directories = ();

		# Find directories that shoud be rebuilt
		unless(opendir(DIR, "$outdir"))
		{
			localdie("FATAL: can't opendir $outdir: $!\n");
		}
		my @dyears = grep { $_ =~ /^\d+$/ } readdir(DIR);
		closedir DIR;
		foreach my $y (sort { $a <=> $b } @dyears)
		{
			unless(opendir(DIR, "$outdir/$y"))
			{
				localdie("FATAL: can't opendir $outdir/$y: $!\n");
			}
			my @dmonths = grep { $_ =~ /^\d+$/ } readdir(DIR);
			closedir DIR;
			foreach my $m (sort { $a <=> $b } @dmonths)
			{
				unless(opendir(DIR, "$outdir/$y/$m"))
				{
					localdie("FATAL: can't opendir $outdir/$y/$m: $!\n");
				}
				my @ddays = grep { $_ =~ /^\d+$/ } readdir(DIR);
				closedir DIR;
				foreach my $d (sort { $a <=> $b } @ddays)
				{
					unless(opendir(DIR, "$outdir/$y/$m/$d"))
					{
						localdie("FATAL: can't opendir $outdir/$y/$m/$d: $!\n");
					}
					my @binfiles = grep { $_ =~ /\.bin$/ } readdir(DIR);
					closedir DIR;
					push(@build_directories, "$y-$m-$d") if ($#binfiles >= 0);
				}
			}
		}

		&build_incremental_reports(@build_directories);

		my $t2 = Benchmark->new;
		my $td = timediff($t2, $t0);
		&logmsg('DEBUG', "rebuilding reports took: " . timestr($td));

		# Remove pidfile
		unlink("$PID_FILE");

		exit 0;
	}
	elsif ($month_report)
	{
		# Look for directory where cumulative report must be generated
		my @build_directories = ();

		# Get year+month as a path
		$month_report =~ s#/#-#g;
		my $month_path = $month_report;
		$month_path =~ s#-#/#g;
		if ($month_path !~ m#^\d{4}/\d{2}$#)
		{
			localdie("FATAL: invalid format YYYY-MM for --month-report option: $month_report");
		}

		&logmsg('DEBUG', "building month report into $outdir/$month_path");

		# Find days directories that shoud be used to build the monthly report
		unless(opendir(DIR, "$outdir/$month_path"))
		{
			localdie("FATAL: can't opendir $outdir/$month_path: $!\n");
		}
		my @ddays = grep { $_ =~ /^\d+$/ } readdir(DIR);
		closedir DIR;
		foreach my $d (sort { $a <=> $b } @ddays)
		{
			unless(opendir(DIR, "$outdir/$month_path/$d"))
			{
				localdie("FATAL: can't opendir $outdir/$month_path/$d: $!\n");
			}
			my @binfiles = grep { $_ =~ /\.bin$/ } readdir(DIR);
			closedir DIR;
			push(@build_directories, "$month_report-$d") if ($#binfiles >= 0);
		}

		&build_month_reports($month_path, @build_directories);

		my $t2 = Benchmark->new;
		my $td = timediff($t2, $t0);
		&logmsg('DEBUG', "building month report took: " . timestr($td));

		# Remove pidfile
		unlink("$PID_FILE");

		exit 0;
	}
	elsif ($day_report)
	{
		# Look for directory where cumulative report must be generated
		my @build_directories = ();

		# Get year+month as a path
		$day_report =~ s#/#-#g;
		my $day_path = $day_report;
		$day_path =~ s#-#/#g;
		if ($day_path !~ m#^\d{4}/\d{2}\/\d{2}$#)
		{
			localdie("FATAL: invalid format YYYY-MM-DD for --day-report option: $day_report");
		}

		&logmsg('DEBUG', "building day report into $outdir/$day_path");

		# Find days directories that shoud be used to build the monthly report
		unless(opendir(DIR, "$outdir/$day_path"))
		{
			localdie("FATAL: can't opendir $outdir/$day_path: $!\n");
		}
		my @binfiles = grep { $_ =~ /\.bin$/ } readdir(DIR);
		closedir DIR;
		push(@build_directories, "$day_report") if ($#binfiles >= 0);

		&build_day_reports($day_path, @build_directories);

		my $t2 = Benchmark->new;
		my $td = timediff($t2, $t0);
		&logmsg('DEBUG', "building day report took: " . timestr($td));

		# Remove pidfile
		unlink("$PID_FILE");

		exit 0;
	}
}
else
{
	# Extra files for resources are not allowed without incremental mode
	$extra_files = 0;
}

# Reading last line parsed
if ($last_parsed && -e $last_parsed)
{
	if (open(my $in, '<', $last_parsed))
	{
		my @content = <$in>;
		close($in);
		foreach my $line (@content)
		{
			chomp($line);
			next if (!$line);
			my ($datetime, $current_pos, $orig, @others) = split(/\t/, $line);
			# Last parsed line with pgbouncer log starts with this keyword
			if ($datetime eq 'pgbouncer')
			{
				$pgb_saved_last_line{datetime} = $current_pos;
				$pgb_saved_last_line{current_pos} = $orig;
				$pgb_saved_last_line{orig} = join("\t", @others);
			}
			else
			{
				$saved_last_line{datetime} = $datetime;
				$saved_last_line{current_pos} = $current_pos;
				$saved_last_line{orig} = $orig;
			}
			&logmsg('DEBUG', "Found log offset " . ($saved_last_line{current_pos} || $pgb_saved_last_line{current_pos}) . " in file $last_parsed");
		}
		# Those two log format must be read from start of the file
		if ( ($format eq 'binary') || ($format eq 'csv') )
		{
			$saved_last_line{current_pos} = 0;
			$pgb_saved_last_line{current_pos} = 0 if ($format eq 'binary');
		}

	}
	else
	{
		localdie("FATAL: can't read last parsed line from $last_parsed, $!\n");
	}
}
$tmp_last_parsed = 'tmp_' . basename($last_parsed) if ($last_parsed);
$tmp_last_parsed = "$TMP_DIR/$tmp_last_parsed";
$tmp_dblist = "$TMP_DIR/dblist.tmp";

###
### Explanation:
###
### Logic for the BINARY storage ($outdir) SHOULD be:
### If ('noclean')
###   do nothing (keep everything)
### If (NO 'noclean') and (NO 'retention'):
###   use an arbitrary retention duration of: 5 weeks
###   remove BINARY files older than LAST_PARSED_MONTH-retention
###   DO NOT CHECK for HTML file existence as OLD HTML files may be deleted by external tools
###     which may lead to BINARY files NEVER deleted
### If (NO 'noclean') and ('retention'):
###   remove BINARY files older than LAST_PARSED_MONTH-retention
###   DO NOT CHECK for HTML file existence as OLD HTML files may be deleted by external tools
###     which may lead to BINARY files NEVER deleted
###
### Logic for the HTML storage ($html_outdir || $outdir) SHOULD be:
### DO NOT check 'noclean' as this flag is dedicated to BINARY files
### If (NO 'retention'):
###   do nothing (keep everything)
### If ('retention'):
###   remove HTML folders/files older than LAST_PARSED_MONTH-retention (= y/m/d):
###   days older than d in y/m/d
###   months older than m in y/m/d
###   years older than y in y/m/d
###

# Clear BIN/HTML storages in incremental mode
my @all_outdir = ();
push(@all_outdir, $outdir) if ($outdir);
push(@all_outdir, $html_outdir) if ($html_outdir);
### $retention_bin = 5 if (!$noclean && !$retention);
### $retention_bin = 0 if ($noclean && !$retention);
### $retention_bin = $retention if (!$noclean && $retention);
### $retention_bin = 0 if ($noclean && $retention);
### equivalent to:
my $retention_bin = $retention;
$retention_bin = 0 if ($noclean && $retention);
$retention_bin = 5 if (!$noclean && !$retention);
### $retention_html = 0 if (!$noclean && !$retention);
### $retention_html = 0 if ($noclean && !$retention);
### $retention_html = $retention if (!$noclean && $retention);
### $retention_html = $retention if ($noclean && $retention);
### equivalent to:
my $retention_html = $retention;
### We will handle noclean/!noclean and retention_xxx/!retention_xxx below
### Note: !retention_xxx equivalent to retention_xxx = 0

&logmsg('DEBUG', "BIN/HTML Retention cleanup: Initial cleanup flags - noclean=[$noclean] - retention_bin=[$retention_bin] - retention_html=[$retention_html] - saved_last_line{datetime}=[$saved_last_line{datetime}] - pgb_saved_last_line{datetime}=[$pgb_saved_last_line{datetime}] - all_outdir=[@all_outdir]");

if ( scalar(@all_outdir) && ($saved_last_line{datetime} || $pgb_saved_last_line{datetime}) )
{

	foreach my $ret_dir (@all_outdir)
	{
		if (($saved_last_line{datetime} =~ /^(\d+)\-(\d+)\-(\d+) /) ||
					($pgb_saved_last_line{datetime} =~ /^(\d+)\-(\d+)\-(\d+) /))
		{
			# Search the current week following the last parse date
			my $limit_yw_bin = $1;
			my $limit_yw_html = $1;
			my $wn = &get_week_number($1, $2, $3);
			# BIN: Case of year overlap
			if (($wn - $retention_bin) < 1)
			{
				# Rewind to previous year
				$limit_yw_bin--;
				# Get number of last week of previous year, can be 52 or 53
				my $prevwn = &get_week_number($limit_yw_bin, 12, 31);
				# Add week number including retention_bin to the previous year
				$limit_yw_bin .= sprintf("%02d", $prevwn - abs($wn - $retention_bin));
			} else {
				$limit_yw_bin .= sprintf("%02d", $wn - $retention_bin);
			}
			&logmsg('DEBUG', "BIN Retention cleanup: YearWeek Limit computation - YearWeek=<$limit_yw_bin> - This will help later removal");
			# HTML: Case of year overlap
			if (($wn - $retention_html) < 1)
			{
				# Rewind to previous year
				$limit_yw_html--;
				# Get number of last week of previous year, can be 52 or 53
				my $prevwn = &get_week_number($limit_yw_html, 12, 31);
				# Add week number including retention_html to the previous year
				$limit_yw_html .= sprintf("%02d", $prevwn - abs($wn - $retention_html));
			} else {
				$limit_yw_html .= sprintf("%02d", $wn - $retention_html);
			}
			&logmsg('DEBUG', "HTML Retention cleanup: YearWeek Limit computation - YearWeek=<$limit_yw_html> - This will help later removal");

			my @dyears = ();
			if ( opendir(DIR, "$ret_dir") ) {
				@dyears = grep { $_ =~ /^\d+$/ } readdir(DIR);
				closedir DIR;
			} else {
				&logmsg('ERROR', "BIN/HTML Retention cleanup: can't opendir $ret_dir: $!");
			}
			# Find obsolete weeks dir that shoud be cleaned
			foreach my $y (sort { $a <=> $b } @dyears) {
				my @weeks = ();
				if ( opendir(DIR, "$ret_dir/$y") ) {
					@weeks = grep { $_ =~ /^week-\d+$/ } readdir(DIR);
					closedir DIR;
				} else {
					&logmsg('ERROR', "BIN/HTML Retention cleanup: can't opendir $ret_dir/$y: $!");
				}
				foreach my $w (sort { $a <=> $b } @weeks) {
					$w =~ /^week-(\d+)$/;
					if ( (!$noclean) && $retention_bin ) {
						if ("$y$1" lt $limit_yw_bin) {
							&logmsg('DEBUG', "BIN Retention cleanup: Removing obsolete week directory $ret_dir/$y/week-$1");
							&cleanup_directory_bin("$ret_dir/$y/week-$1", 1);
						}
					}
					if ( $retention_html ) {
						if ("$y$1" lt $limit_yw_html) {
							&logmsg('DEBUG', "HTML Retention cleanup: Removing obsolete week directory $ret_dir/$y/week-$1");
							&cleanup_directory_html("$ret_dir/$y/week-$1", 1);
						}
					}
				}
			}
			# Find obsolete months and days
			foreach my $y (sort { $a <=> $b } @dyears) {
				my @dmonths = ();
				if ( opendir(DIR, "$ret_dir/$y") ) {
					@dmonths = grep { $_ =~ /^\d+$/ } readdir(DIR);
					closedir DIR;
				} else {
					&logmsg('ERROR', "BIN/HTML Retention cleanup: can't opendir $ret_dir/$y: $!");
				}

				# Now remove the HTML monthly reports
				if ( $retention_html ) {
					foreach my $m (sort { $a <=> $b } @dmonths) {
						my $diff_day = $retention_html * 7 * 86400;
						my $lastday = 0;
						if (($saved_last_line{datetime} =~ /^(\d+)\-(\d+)\-(\d+) /) ||
							($pgb_saved_last_line{datetime} =~ /^(\d+)\-(\d+)\-(\d+) /)) {
							$lastday = timelocal(1,1,1,$3,$2-1,$1-1900);
						}
						if ( $lastday ) {
							my $lastday_minus_retention = $lastday - $diff_day;
							my $lastday_minus_retention_Y = strftime('%Y', localtime($lastday_minus_retention));
							my $lastday_minus_retention_M = strftime('%m', localtime($lastday_minus_retention));

							my $lastday_minus_retention_prev_month_Y = $lastday_minus_retention_Y;
							my $lastday_minus_retention_prev_month_M = $lastday_minus_retention_M - 1;

							if ( $lastday_minus_retention_prev_month_M < 1 ) {
								$lastday_minus_retention_prev_month_Y -= 1;
								$lastday_minus_retention_prev_month_M = 12;
							}

							$lastday_minus_retention_prev_month_Y = sprintf("%04d", $lastday_minus_retention_prev_month_Y);
							$lastday_minus_retention_prev_month_M = sprintf("%02d", $lastday_minus_retention_prev_month_M);

							if ("$y$m" lt "$lastday_minus_retention_Y$lastday_minus_retention_M") {
								&logmsg('DEBUG', "HTML Retention cleanup: Removing obsolete month directory $ret_dir/$y/$m");
								&cleanup_directory_html("$ret_dir/$y/$m", 1);
							}
						}
					}
				}
				
				# Now remove the corresponding days
				foreach my $m (sort { $a <=> $b } @dmonths) {
					my @ddays = ();
					if ( opendir(DIR, "$ret_dir/$y/$m") ) {
						@ddays = grep { $_ =~ /^\d+$/ } readdir(DIR);
						closedir DIR;
					} else {
						&logmsg('ERROR', "BIN/HTML Retention cleanup: can't opendir $ret_dir/$y/$m: $!");
					}
					foreach my $d (sort { $a <=> $b } @ddays)
					{
						if ( (!$noclean) && $retention_bin ) {
							# Remove obsolete days when we are in binary mode
							# with noreport - there's no week-N directory
							my $diff_day = $retention_bin * 7 * 86400;
							my $oldday = timelocal(1,1,1,$d,$m-1,$y-1900);
							my $lastday = $oldday;
							if (($saved_last_line{datetime} =~ /^(\d+)\-(\d+)\-(\d+) /) ||
								($pgb_saved_last_line{datetime} =~ /^(\d+)\-(\d+)\-(\d+) /)) {
								$lastday = timelocal(1,1,1,$3,$2-1,$1-1900);
							}
							if (($lastday - $oldday) > $diff_day) {
								&logmsg('DEBUG', "BIN Retention cleanup: Removing obsolete day directory $ret_dir/$y/$m/$d");
								&cleanup_directory_bin("$ret_dir/$y/$m/$d", 1);
							}
						}
						if ( $retention_html ) {
							# Remove obsolete days when we are in binary mode
							# with noreport - there's no week-N directory
							my $diff_day = $retention_html * 7 * 86400;
							my $oldday = timelocal(1,1,1,$d,$m-1,$y-1900);
							my $lastday = $oldday;
							if (($saved_last_line{datetime} =~ /^(\d+)\-(\d+)\-(\d+) /) ||
								($pgb_saved_last_line{datetime} =~ /^(\d+)\-(\d+)\-(\d+) /)) {
								$lastday = timelocal(1,1,1,$3,$2-1,$1-1900);
							}
							if (($lastday - $oldday) > $diff_day) {
								&logmsg('DEBUG', "HTML Retention cleanup: Removing obsolete day directory $ret_dir/$y/$m/$d");
								&cleanup_directory_html("$ret_dir/$y/$m/$d", 1);
							}
						}
					}
					if ( rmdir("$ret_dir/$y/$m") ) {
						&logmsg('DEBUG', "BIN/HTML Retention cleanup: Removing obsolete empty directory $ret_dir/$y/$m");
					}
				}
				if ( rmdir("$ret_dir/$y") ) {
					&logmsg('DEBUG', "BIN/HTML Retention cleanup: Removing obsolete empty directory $ret_dir/$y");
				}
			}
		}
	}

}

# Main loop reading log files
my $global_totalsize = 0;
my @given_log_files = ( @log_files );
chomp(@given_log_files);

# Store globaly total size for each log files
my %file_size = ();
foreach my $logfile ( @given_log_files )
{
	$file_size{$logfile} = &get_file_size($logfile);
	$global_totalsize += $file_size{$logfile} if ($file_size{$logfile} > 0);
}

# Verify that the file has not changed for incremental move
if (($incremental || $last_parsed) && !$remote_host)
{
	my @tmpfilelist = ();
	# Removed files that have already been parsed during previous runs
	foreach my $f (@given_log_files)
	{
		if ($f eq '-')
		{
			&logmsg('DEBUG', "waiting for log entries from stdin.");
			$saved_last_line{current_pos} = 0;
			push(@tmpfilelist, $f);
		}
		elsif ($f =~ /\.bin$/)
		{
			&logmsg('DEBUG', "binary file \"$f\" as input, there is no log to parse.");
			$saved_last_line{current_pos} = 0;
			push(@tmpfilelist, $f);
		}
		elsif ( $journalctl_cmd && ($f eq $journalctl_cmd) )
		{
			my $since = '';
			if ( ($journalctl_cmd !~ /--since|-S/) &&
				($saved_last_line{datetime} =~ /^(\d+)-(\d+)-(\d+).(\d+):(\d+):(\d+)/) )
			{
				$since = " --since='$1-$2-$3 $4:$5:$6'";
			}
			&logmsg('DEBUG', "journalctl call will start since: $saved_last_line{datetime}");
			my $new_journalctl_cmd = "$f$since";
			push(@tmpfilelist, $new_journalctl_cmd);
			$file_size{$new_journalctl_cmd} = $file_size{$f};
		}
		elsif ( $log_command && ($f eq $log_command) )
		{
			&logmsg('DEBUG', "custom command waiting for log entries from stdin.");
			$saved_last_line{current_pos} = 0;
			push(@tmpfilelist, $f);
		}
		else
		{
			# Auto detect log format for proper parsing
			my $fmt = $format || 'stderr';
			$fmt = autodetect_format($f, $file_size{$f});
			$fmt ||= $format;

			# Set regex to parse the log file
			$fmt = set_parser_regex($fmt);

			if (($fmt ne 'pgbouncer') && ($saved_last_line{current_pos} > 0))
			{
				my ($retcode, $msg) = &check_file_changed($f, $file_size{$f}, $fmt, $saved_last_line{datetime}, $saved_last_line{current_pos});
				if (!$retcode)
				{
					&logmsg('DEBUG', "this file has already been parsed: $f, $msg");
				}
				else
				{
					push(@tmpfilelist, $f);
				}
			}
			elsif (($fmt eq 'pgbouncer') && ($pgb_saved_last_line{current_pos} > 0))
			{
				my ($retcode, $msg) = &check_file_changed($f, $file_size{$f}, $fmt, $pgb_saved_last_line{datetime}, $pgb_saved_last_line{current_pos});
				if (!$retcode)
				{
					&logmsg('DEBUG', "this file has already been parsed: $f, $msg");
				}
				else
				{
					push(@tmpfilelist, $f);
				}
			}
			else
			{
				push(@tmpfilelist, $f);
			}
		}
	}
	@given_log_files = ();
	push(@given_log_files, @tmpfilelist);
}

# Pipe used for progress bar in multiprocess
my $pipe = undef;

# Seeking to an old log position is not possible outside incremental mode
if (!$last_parsed || !exists $saved_last_line{current_pos}) {
	$saved_last_line{current_pos} = 0;
	$pgb_saved_last_line{current_pos} = 0;
}

if ($dump_all_queries)
{
	$fh = new IO::File;
	$fh->open($outfiles[0], '>') or localdie("FATAL: can't open output file $outfiles[0], $!\n");
}

####
# Start parsing all log files
####

# Number of running process
my $child_count = 0;
# Set max number of parallel process
my $parallel_process = 0;

# Open a pipe for interprocess communication
my $reader = new IO::Handle;
my $writer = new IO::Handle;
# Fork the logger process
if ($^O !~ /MSWin32|dos/i && $progress)
{
	$pipe = IO::Pipe->new($reader, $writer);
	$writer->autoflush(1);
	spawn sub
	{
		&multiprocess_progressbar($global_totalsize);
	};
}

# Initialise the list of reports to produce with the default report
# if $report_per_database is enabled there will be a report for each
# database. Information not related to a database (checkpoint, pgbouncer
# statistics, etc.) will be included in the default report which should
# be the postgres database to be read by the DBA of the PostgreSQL cluster.
$DBLIST{$DBALL} = 1;

# Prevent parallelism perl file to be higher than the number of files
$job_per_file = ($#given_log_files+1) if ( ($job_per_file > 1) && ($job_per_file > ($#given_log_files+1)) );

# Parse each log file following the multiprocess mode chosen (-j or -J)
foreach my $logfile ( @given_log_files )
{

	# If we just want to build incremental reports from binary files
	# just build the list of input directories with binary files
	if ($incremental && $html_outdir && !$outdir)
	{
		my $incr_date = '';
		my $binpath = '';
		if ($logfile =~ /^(.*\/)(\d+)\/(\d+)\/(\d+)\/[^\/]+\.bin$/)
		{
			$binpath = $1;
			$incr_date = "$2-$3-$4";
		}
		# Mark the directory as needing index update
		if (open(my $out, '>>', "$last_parsed.tmp")) {
			print $out "$binpath$incr_date\n";
			close($out);
		} else {
			&logmsg('ERROR', "can't save last parsed line into $last_parsed.tmp, $!");
		}
		next;
	}

	# Confirm if we can use multiprocess for this file
	my $pstatus = confirm_multiprocess($logfile);
	if ($pstatus >= 0)
	{
		if ($pstatus = 1 && $job_per_file > 1)
		{
			$parallel_process = $job_per_file;
		}
		else
		{
			$parallel_process = $queue_size;
		}
	}
	else
	{
		&logmsg('DEBUG', "parallel processing will not ne used.");
		$parallel_process = 1;
	}

	# Wait until a child dies if max parallel processes is reach
	while ($child_count >= $parallel_process)
	{
		my $kid = waitpid(-1, WNOHANG);
		if ($kid > 0)
		{
			$child_count--;
			delete $RUNNING_PIDS{$kid};
		}
		sleep(1);
	}

	# Get log format of the current file
	my $fmt = $format || 'stderr';
	my $logfile_orig = $logfile;
	if ($logfile ne '-' && !$journalctl_cmd && !$log_command)
	{
		$fmt = &autodetect_format($logfile, $file_size{$logfile});
		$fmt ||= $format;
		# Remove log format from filename if any
		$logfile =~ s/:(stderr|csv|syslog|pgbouncer|jsonlog|logplex|rds|redshift)\d*$//i;
		&logmsg('DEBUG', "pgBadger will use log format $fmt to parse $logfile.");
	}
	else
	{
		&logmsg('DEBUG', "Can not autodetect log format, assuming $fmt.");
	}

	# Set the timezone to use
	&set_timezone();

	# Set the regex to parse the log file following the format
	$fmt = set_parser_regex($fmt);

	# Do not use split method with remote and compressed files, stdin, custom or journalctl command
	if ( ($parallel_process > 1) && ($queue_size > 1) &&
			($logfile !~ $compress_extensions) &&
			($logfile !~ /\.bin$/i) && ($logfile ne '-') &&
			($logfile !~ /^(http[s]*|ftp[s]*|ssh):/i) &&
			(!$journalctl_cmd || ($logfile !~ /\Q$journalctl_cmd\E/)) &&
			(!$log_command || ($logfile !~ /\Q$log_command\E/))
		)
	{

		# Create multiple processes to parse one log file by chunks of data
		my @chunks = split_logfile($logfile, $file_size{$logfile_orig}, ($fmt eq 'pgbouncer') ? $pgb_saved_last_line{current_pos} : $saved_last_line{current_pos});
		&logmsg('DEBUG', "The following boundaries will be used to parse file $logfile, " . join('|', @chunks));
		for (my $i = 0; $i < $#chunks; $i++)
		{
			while ($child_count >= $parallel_process)
			{
				my $kid = waitpid(-1, WNOHANG);
				if ($kid > 0)
				{
					$child_count--;
					delete $RUNNING_PIDS{$kid};
				}
				sleep(1);
			}
			localdie("FATAL: Abort signal received when processing to next chunk\n") if ($interrupt == 2);
			last if ($interrupt);
			push(@tempfiles, [ tempfile('tmp_pgbadgerXXXX', SUFFIX => '.bin', DIR => $TMP_DIR, O_TEMPORARY => 1, UNLINK => 1 ) ]);
			spawn sub
			{
				&process_file($logfile, $file_size{$logfile_orig}, $fmt, $tempfiles[-1]->[0], $chunks[$i], $chunks[$i+1], $i);
			};
			$child_count++;
		}

	}
	else
	{
		# Start parsing one file per parallel process
		if ($^O !~ /MSWin32|dos/i)
		{
			push(@tempfiles, [ tempfile('tmp_pgbadgerXXXX', SUFFIX => '.bin', DIR => $TMP_DIR, UNLINK => 1 ) ]);
			spawn sub
			{
				&process_file($logfile, $file_size{$logfile_orig}, $fmt, $tempfiles[-1]->[0], ($fmt eq 'pgbouncer') ? $pgb_saved_last_line{current_pos} : $saved_last_line{current_pos});
			};
			$child_count++;
		}
		else
		{
			&process_file($logfile, $file_size{$logfile_orig}, $fmt, undef, ($fmt eq 'pgbouncer') ? $pgb_saved_last_line{current_pos} : $saved_last_line{current_pos});
		}
	}

	localdie("FATAL: Abort signal received when processing next file\n") if ($interrupt == 2);
	last if ($interrupt);
}

# Wait for all child processes to localdie except for the logger
# On Windows OS $progress is disabled so we don't go here
while (scalar keys %RUNNING_PIDS > $progress)
{
	my $kid = waitpid(-1, WNOHANG);
	if ($kid > 0) {
		delete $RUNNING_PIDS{$kid};
	}
	sleep(1);
}

# Terminate the process logger
if ($^O !~ /MSWin32|dos/i)
{
	foreach my $k (keys %RUNNING_PIDS)
	{
		kill('USR1', $k);
		%RUNNING_PIDS = ();
	}

	# Clear previous statistics
	&init_stats_vars();
}

# Load all data gathered by all the different processes
foreach my $f (@tempfiles)
{
	next if (!-e "$f->[1]" || -z "$f->[1]");
	my $fht = new IO::File;
	$fht->open("< $f->[1]") or localdie("FATAL: can't open temp file $f->[1], $!\n");
	load_stats($fht);
	$fht->close();
}

# Get last line parsed from all process
if ($last_parsed)
{
	&logmsg('DEBUG', "Reading temporary last parsed line from $tmp_last_parsed");
	if (open(my $in, '<', $tmp_last_parsed) )
	{
		while (my $line = <$in>)
		{
			chomp($line);
			$line =~ s/\r//;
			my ($d, $p, $l, @o) = split(/\t/, $line);
			if ($d ne 'pgbouncer')
			{
				if (!$last_line{datetime} || ($d gt $last_line{datetime}))
				{
					$last_line{datetime} = $d;
					$last_line{orig} = $l;
					$last_line{current_pos} = $p;
				}
			}
			else
			{
				$d = $p;
				$p = $l;
				$l = join("\t", @o);
				if (!$pgb_last_line{datetime} || ($d gt $pgb_last_line{datetime}))
				{
					$pgb_last_line{datetime} = $d;
					$pgb_last_line{orig} = $l;
					$pgb_last_line{current_pos} = $p;
				}
			}
		}
		close($in);
	}
	unlink("$tmp_last_parsed");
}

# Save last line parsed
if ($last_parsed && ($last_line{datetime} || $pgb_last_line{datetime})
	&& ($last_line{orig} || $pgb_last_line{orig}) )
{
	&logmsg('DEBUG', "Saving last parsed line into $last_parsed");
	if (open(my $out, '>', $last_parsed))
	{
		if ($last_line{datetime})
		{
			$last_line{current_pos} ||= 0;
			print $out "$last_line{datetime}\t$last_line{current_pos}\t$last_line{orig}\n";
		}
		elsif ($saved_last_line{datetime})
		{
			$saved_last_line{current_pos} ||= 0;
			print $out "$saved_last_line{datetime}\t$saved_last_line{current_pos}\t$saved_last_line{orig}\n";
		}
		if ($pgb_last_line{datetime})
		{
			$pgb_last_line{current_pos} ||= 0;
			print $out "pgbouncer\t$pgb_last_line{datetime}\t$pgb_last_line{current_pos}\t$pgb_last_line{orig}\n";
		}
		elsif ($pgb_saved_last_line{datetime})
		{
			$pgb_saved_last_line{current_pos} ||= 0;
			print $out "pgbouncer\t$pgb_saved_last_line{datetime}\t$pgb_saved_last_line{current_pos}\t$pgb_saved_last_line{orig}\n";
		}
		close($out);
	}
	else
	{
		&logmsg('ERROR', "can't save last parsed line into $last_parsed, $!");
	}
}

if ($terminate)
{
	unlink("$PID_FILE");
	exit 2;
}

####
# Generates statistics output
####
my $t1 = Benchmark->new;
my $td = timediff($t1, $t0);
&logmsg('DEBUG', "the log statistics gathering took:" . timestr($td));

if ($dump_all_queries)
{
	$fh->close();

	# Remove pidfile and temporary file
	unlink($tmp_dblist) if ($tmp_dblist);
	unlink("$PID_FILE");
	unlink("$last_parsed.tmp") if (-e "$last_parsed.tmp");
	unlink($TMP_DIR . "/pgbadger_tmp_$$.bin") if ($#outfiles >= 1);

	exit 0;
}

# Read the list of database we have proceeded in all child process
if ($report_per_database)
{
	%DBLIST = ();
	if (open(my $out, '<', "$tmp_dblist"))
	{
		my @data = <$out>;
		foreach my $tmp (@data)
		{
			chomp($tmp);
			my %dblist = split(/;/, $tmp);
			foreach my $d (keys %dblist)
			{
				next if ($#dbname >= 0 and !grep(/^$d$/i, @dbname));
				$DBLIST{$d} = 1;
				$overall_stat{nlines}{$d} += $dblist{$d};
			}
		}
		close($out);
		&logmsg('DEBUG', "looking for list of database retrieved from log: " . join(',', keys %DBLIST));
	}
	else
	{
		&logmsg('ERROR', "can't read list of database from file $tmp_dblist, $!");
	}
}

if ( !$incremental && ($#given_log_files >= 0) )
{
	my $chld_running = 0;
	foreach my $db (sort keys %DBLIST)
	{
		next if (!$db);

		if ($^O =~ /MSWin32|dos/i || $parallel_process <= 1) {
			&gen_database_report($db);
		}
		else
		{
			while ($chld_running >= $parallel_process)
			{
				my $kid = waitpid(-1, WNOHANG);
				if ($kid > 0)
				{
					$chld_running--;
					delete $RUNNING_PIDS{$kid};
				}
				sleep(1);
			}
			spawn sub
			{
				&gen_database_report($db);

			};
			$chld_running++;
		}
	}

	if ($^O !~ /MSWin32|dos/i && $parallel_process > 1)
	{
		while (scalar keys %RUNNING_PIDS > $progress)
		{
			my $kid = waitpid(-1, WNOHANG);
			if ($kid > 0) {
				delete $RUNNING_PIDS{$kid};
			}
			sleep(1);
		}
	}
}
elsif (!$incremental || !$noreport)
{
	# Look for directory where report must be generated
	my @build_directories = ();
	if (-e "$last_parsed.tmp") {
		if (open(my $in, '<', "$last_parsed.tmp")) {
			while (my $l = <$in>) {
				chomp($l);
				$l =~ s/\r//;
				push(@build_directories, $l) if (!grep(/^$l$/, @build_directories));
			}
			close($in);
			unlink("$last_parsed.tmp");
		} else {
			&logmsg('ERROR', "can't read file $last_parsed.tmp, $!");
		}

		&build_incremental_reports(@build_directories);
	} else {
		&logmsg('DEBUG', "no new entries in your log(s) since last run.");
	}
}

my $t2 = Benchmark->new;
$td = timediff($t2, $t1);
&logmsg('DEBUG', "building reports took: " . timestr($td));
$td = timediff($t2, $t0);
&logmsg('DEBUG', "the total execution time took: " . timestr($td));

# Remove pidfile and temporary file
unlink($tmp_dblist);
unlink("$PID_FILE");
unlink("$last_parsed.tmp") if (-e "$last_parsed.tmp");
unlink($TMP_DIR . "/pgbadger_tmp_$$.bin") if ($#outfiles >= 1);

exit 0;

#-------------------------------------------------------------------------------

# Show pgBadger command line usage
sub usage
{
	print qq{
Usage: pgbadger [options] logfile [...]

    PostgreSQL log analyzer with fully detailed reports and graphs.

Arguments:

    logfile can be a single log file, a list of files, or a shell command
    returning a list of files. If you want to pass log content from stdin
    use - as filename. Note that input from stdin will not work with csvlog.

Options:

    -a | --average minutes : number of minutes to build the average graphs of
			     queries and connections. Default 5 minutes.
    -A | --histo-average min: number of minutes to build the histogram graphs
                             of queries. Default 60 minutes.
    -b | --begin datetime  : start date/time for the data to be parsed in log
                             (either a timestamp or a time)
    -c | --dbclient host   : only report on entries for the given client host.
    -C | --nocomment       : remove comments like /* ... */ from queries.
    -d | --dbname database : only report on entries for the given database.
    -D | --dns-resolv      : client ip addresses are replaced by their DNS name.
                             Be warned that this can really slow down pgBadger.
    -e | --end datetime    : end date/time for the data to be parsed in log
                             (either a timestamp or a time)
    -E | --explode	   : explode the main report by generating one report
			     per database. Global information not related to a
			     database is added to the postgres database report.
    -f | --format logtype  : possible values: syslog, syslog2, stderr, jsonlog,
			     csv, pgbouncer, logplex, rds and redshift. Use this
			     option when pgBadger is not able to detect the log
			     format.
    -G | --nograph	   : disable graphs on HTML output. Enabled by default.
    -h | --help	           : show this message and exit.
    -H | --html-outdir path: path to directory where HTML report must be written
                             in incremental mode, binary files stay on directory
			     defined with -O, --outdir option.
    -i | --ident name      : programname used as syslog ident. Default: postgres
    -I | --incremental     : use incremental mode, reports will be generated by
			     days in a separate directory, --outdir must be set.
    -j | --jobs number     : number of jobs to run at same time for a single log
                             file. Run as single by default or when working with
			     csvlog format.
    -J | --Jobs number     : number of log files to parse in parallel. Process
			     one file at a time by default.
    -l | --last-parsed file: allow incremental log parsing by registering the
			     last datetime and line parsed. Useful if you want
			     to watch errors since last run or if you want one
			     report per day with a log rotated each week.
    -L | --logfile-list file:file containing a list of log files to parse.
    -m | --maxlength size  : maximum length of a query, it will be restricted to
			     the given size. Default truncate size is $maxlength.
    -M | --no-multiline    : do not collect multiline statements to avoid garbage
			     especially on errors that generate a huge report.
    -N | --appname name    : only report on entries for given application name
    -o | --outfile filename: define the filename for the output. Default depends
			     on the output format: out.html, out.txt, out.bin,
			     or out.json. This option can be used multiple times
			     to output several formats. To use json output, the
			     Perl module JSON::XS must be installed, to dump
			     output to stdout, use - as filename.
    -O | --outdir path     : directory where out files must be saved.
    -p | --prefix string   : the value of your custom log_line_prefix as
			     defined in your postgresql.conf. Only use it if you
			     aren't using one of the standard prefixes specified
			     in the pgBadger documentation, such as if your
			     prefix includes additional variables like client IP
			     or application name. MUST contain escape sequences
			     for time (%t, %m or %n) and processes (%p or %c).
			     See examples below.
    -P | --no-prettify     : disable SQL queries prettify formatter.
    -q | --quiet	   : don't print anything to stdout, not even a progress
			     bar.
    -Q | --query-numbering : add numbering of queries to the output when using
                             options --dump-all-queries or --normalized-only.
    -r | --remote-host ip  : set the host where to execute the cat command on
			     remote log file to parse the file locally.
    -R | --retention N     : number of weeks to keep in incremental mode. Defaults
			     to 0, disabled. Used to set the number of weeks to
			     keep in output directory. Older weeks and days
			     directories are automatically removed.
    -s | --sample number   : number of query samples to store. Default: 3.
    -S | --select-only     : only report SELECT queries.
    -t | --top number      : number of queries to store/display. Default: 20.
    -T | --title string    : change title of the HTML page report.
    -u | --dbuser username : only report on entries for the given user.
    -U | --exclude-user username : exclude entries for the specified user from
			     report. Can be used multiple time.
    -v | --verbose         : enable verbose or debug mode. Disabled by default.
    -V | --version         : show pgBadger version and exit.
    -w | --watch-mode      : only report errors just like logwatch could do.
    -W | --wide-char       : encode html output of queries into UTF8 to avoid
                             Perl message "Wide character in print".
    -x | --extension       : output format. Values: text, html, bin or json.
			     Default: html
    -X | --extra-files     : in incremental mode allow pgBadger to write CSS and
			     JS files in the output directory as separate files.
    -z | --zcat exec_path  : set the full path to the zcat program. Use it if
			     zcat, bzcat or unzip is not in your path.
    -Z | --timezone +/-XX  : Set the number of hours from GMT of the timezone.
			     Use this to adjust date/time in JavaScript graphs.
			     The value can be an integer, ex.: 2, or a float,
			     ex.: 2.5.
    --pie-limit num	   : pie data lower than num% will show a sum instead.
    --exclude-query regex  : any query matching the given regex will be excluded
			     from the report. For example: "^(VACUUM|COMMIT)"
			     You can use this option multiple times.
    --exclude-file filename: path of the file that contains each regex to use
			     to exclude queries from the report. One regex per
			     line.
    --include-query regex  : any query that does not match the given regex will
			     be excluded from the report. You can use this
			     option multiple times. For example: "(tbl1|tbl2)".
    --include-file filename: path of the file that contains each regex to the
			     queries to include from the report. One regex per
			     line.
    --disable-error	   : do not generate error report.
    --disable-hourly       : do not generate hourly report.
    --disable-type	   : do not generate report of queries by type, database
			     or user.
    --disable-query	   : do not generate query reports (slowest, most
			     frequent, queries by users, by database, ...).
    --disable-session      : do not generate session report.
    --disable-connection   : do not generate connection report.
    --disable-lock	   : do not generate lock report.
    --disable-temporary    : do not generate temporary report.
    --disable-checkpoint   : do not generate checkpoint/restartpoint report.
    --disable-autovacuum   : do not generate autovacuum report.
    --charset	           : used to set the HTML charset to be used.
			     Default: utf-8.
    --csv-separator	   : used to set the CSV field separator, default: ,
    --exclude-time  regex  : any timestamp matching the given regex will be
			     excluded from the report. Example: "2013-04-12 .*"
			     You can use this option multiple times.
    --include-time  regex  : only timestamps matching the given regex will be
			     included in the report. Example: "2013-04-12 .*"
			     You can use this option multiple times.
    --exclude-db name      : exclude entries for the specified database from
			     report. Example: "pg_dump". Can be used multiple
			     times.
    --exclude-appname name : exclude entries for the specified application name
			     from report.  Example: "pg_dump".  Can be used
			     multiple times.
    --exclude-line regex   : exclude any log entry that will match the given
    			     regex. Can be used multiple times.
    --exclude-client name  : exclude log entries for the specified client ip.
			     Can be used multiple times.
    --anonymize	           : obscure all literals in queries, useful to hide
			     confidential data.
    --noreport	           : no reports will be created in incremental mode.
    --log-duration	   : force pgBadger to associate log entries generated
			     by both log_duration = on and log_statement = 'all'
    --enable-checksum      : used to add an md5 sum under each query report.
    --journalctl command   : command to use to replace PostgreSQL logfile by
			     a call to journalctl. Basically it might be:
				journalctl -u postgresql-9.5
    --pid-dir path         : set the path where the pid file must be stored.
                             Default /tmp
    --pid-file file        : set the name of the pid file to manage concurrent
                             execution of pgBadger. Default: pgbadger.pid
    --rebuild              : used to rebuild all html reports in incremental
                             output directories where there's binary data files.
    --pgbouncer-only       : only show PgBouncer-related menus in the header.
    --start-monday	   : in incremental mode, calendar weeks start on
			     Sunday. Use this option to start on a Monday.
    --iso-week-number      : in incremental mode, calendar weeks start on
			     Monday and respect the ISO 8601 week number, range
			     01 to 53, where week 1 is the first week that has
			     at least 4 days in the new year.
    --normalized-only      : only dump all normalized queries to out.txt
    --log-timezone +/-XX   : Set the number of hours from GMT of the timezone
			     that must be used to adjust date/time read from
			     log file before beeing parsed. Using this option
			     makes log search with a date/time more difficult.
			     The value can be an integer, ex.: 2, or a float,
			     ex.: 2.5.
    --prettify-json	   : use it if you want json output to be prettified.
    --month-report YYYY-MM : create a cumulative HTML report over the specified
                             month. Requires incremental output directories and
                             the presence of all necessary binary data files
    --day-report YYYY-MM-DD: create an HTML report over the specified day.
                             Requires incremental output directories and the
                             presence of all necessary binary data files
    --noexplain            : do not process lines generated by auto_explain.
    --command CMD          : command to execute to retrieve log entries on
                             stdin. pgBadger will open a pipe to the command
                             and parse log entries generated by the command.
    --no-week              : inform pgbadger to not build weekly reports in
                             incremental mode. Useful if it takes too much time.
    --explain-url URL      : use it to override the url of the graphical explain
                             tool. Default: $EXPLAIN_URL
    --tempdir DIR          : set directory where temporary files will be written
                             Default: File::Spec->tmpdir() || '/tmp'
    --no-process-info      : disable changing process title to help identify
                             pgbadger process, some system do not support it.
    --dump-all-queries     : dump all queries found in the log file replacing
                             bind parameters included in the queries at their
			     respective placeholders positions.
    --keep-comments        : do not remove comments from normalized queries. It
                             can be useful if you want to distinguish between
			     same normalized queries.
    --no-progressbar       : disable progressbar.
    --dump-raw-csv         : parse the log and dump the information into CSV
                             format. No further processing is done, no report.
    --include-pid PID      : only report events related to the session pid (\%p).
                             Can be used multiple time.
    --include-session ID   : only report events related to the session id (\%c).
                             Can be used multiple time.
   --histogram-query VAL   : use custom inbound for query times histogram.
                             Default inbound in milliseconds:
			 0,1,5,10,25,50,100,500,1000,10000
   --histogram-session VAL : use custom inbound for session times histogram.
                             Default inbound in milliseconds:
			 0,500,1000,30000,60000,600000,1800000,3600000,28800000

pgBadger is able to parse a remote log file using a passwordless ssh connection.
Use -r or --remote-host to set the host IP address or hostname. There are also
some additional options to fully control the ssh connection.

    --ssh-program ssh	     path to the ssh program to use. Default: ssh.
    --ssh-port port          ssh port to use for the connection. Default: 22.
    --ssh-user username      connection login name. Defaults to running user.
    --ssh-identity file      path to the identity file to use.
    --ssh-timeout second     timeout to ssh connection failure. Default: 10 sec.
    --ssh-option  options    list of -o options to use for the ssh connection.
			     Options always used:
				 -o ConnectTimeout=\$ssh_timeout
				 -o PreferredAuthentications=hostbased,publickey

Log file to parse can also be specified using an URI, supported protocols are
http[s] and [s]ftp. The curl command will be used to download the file, and the
file will be parsed during download. The ssh protocol is also supported and will
use the ssh command like with the remote host use. See examples bellow.

Return codes:

    0: on success
    1: die on error
    2: if it has been interrupted using ctr+c for example
    3: the pid file already exists or can not be created
    4: no log file was given at command line

Examples:

    pgbadger /var/log/postgresql.log
    pgbadger /var/log/postgres.log.2.gz /var/log/postgres.log.1.gz /var/log/postgres.log
    pgbadger /var/log/postgresql/postgresql-2012-05-*
    pgbadger --exclude-query="^(COPY|COMMIT)" /var/log/postgresql.log
    pgbadger -b "2012-06-25 10:56:11" -e "2012-06-25 10:59:11" /var/log/postgresql.log
    cat /var/log/postgres.log | pgbadger -
    # Log line prefix with stderr log output
    pgbadger --prefix '%t [%p]: user=%u,db=%d,client=%h' /pglog/postgresql-2012-08-21*
    pgbadger --prefix '%m %u@%d %p %r %a : ' /pglog/postgresql.log
    # Log line prefix with syslog log output
    pgbadger --prefix 'user=%u,db=%d,client=%h,appname=%a' /pglog/postgresql-2012-08-21*
    # Use my 8 CPUs to parse my 10GB file faster, much faster
    pgbadger -j 8 /pglog/postgresql-10.1-main.log

Use URI notation for remote log file:

    pgbadger http://172.12.110.1//var/log/postgresql/postgresql-10.1-main.log
    pgbadger ftp://username\@172.12.110.14/postgresql-10.1-main.log
    pgbadger ssh://username\@172.12.110.14:2222//var/log/postgresql/postgresql-10.1-main.log*

You can use together a local PostgreSQL log and a remote pgbouncer log file to parse:

    pgbadger /var/log/postgresql/postgresql-10.1-main.log ssh://username\@172.12.110.14/pgbouncer.log

Reporting errors every week by cron job:

    30 23 * * 1 /usr/bin/pgbadger -q -w /var/log/postgresql.log -o /var/reports/pg_errors.html

Generate report every week using incremental behavior:

    0 4 * * 1 /usr/bin/pgbadger -q `find /var/log/ -mtime -7 -name "postgresql.log*"` -o /var/reports/pg_errors-`date +\\%F`.html -l /var/reports/pgbadger_incremental_file.dat

This supposes that your log file and HTML report are also rotated every week.

Or better, use the auto-generated incremental reports:

    0 4 * * * /usr/bin/pgbadger -I -q /var/log/postgresql/postgresql.log.1 -O /var/www/pg_reports/

will generate a report per day and per week.

In incremental mode, you can also specify the number of weeks to keep in the
reports:

    /usr/bin/pgbadger --retention 2 -I -q /var/log/postgresql/postgresql.log.1 -O /var/www/pg_reports/

If you have a pg_dump at 23:00 and 13:00 each day during half an hour, you can
use pgBadger as follow to exclude these periods from the report:

    pgbadger --exclude-time "2013-09-.* (23|13):.*" postgresql.log

This will help avoid having COPY statements, as generated by pg_dump, on top of
the list of slowest queries. You can also use --exclude-appname "pg_dump" to
solve this problem in a simpler way.

You can also parse journalctl output just as if it was a log file:

    pgbadger --journalctl 'journalctl -u postgresql-9.5'

or worst, call it from a remote host:

    pgbadger -r 192.168.1.159 --journalctl 'journalctl -u postgresql-9.5'

you don't need to specify any log file at command line, but if you have other
PostgreSQL log files to parse, you can add them as usual.

To rebuild all incremental html reports after, proceed as follow:

    rm /path/to/reports/*.js
    rm /path/to/reports/*.css
    pgbadger -X -I -O /path/to/reports/ --rebuild

it will also update all resource files (JS and CSS). Use -E or --explode
if the reports were built using this option.

pgBadger also supports Heroku PostgreSQL logs using logplex format:

    heroku logs -p postgres | pgbadger -f logplex -o heroku.html -

this will stream Heroku PostgreSQL log to pgbadger through stdin.

pgBadger can auto detect RDS and cloudwatch PostgreSQL logs using
rds format:

    pgbadger -f rds -o rds_out.html rds.log

Each CloudSQL Postgresql log is a fairly normal PostgreSQL log, but encapsulated
in JSON format. It is autodetected by pgBadger but in case you need to force
the log format use `jsonlog`:

    pgbadger -f jsonlog -o cloudsql_out.html cloudsql.log

This is the same as with the jsonlog extension, the json format is different
but pgBadger can parse both formats.

pgBadger also supports logs produced by CloudNativePG Postgres operator for Kubernetes:

    pgbadger -f jsonlog -o cnpg_out.html cnpg.log

To create a cumulative report over a month use command:

    pgbadger --month-report 2919-05 /path/to/incremental/reports/

this will add a link to the month name into the calendar view in
incremental reports to look at report for month 2019 May.
Use -E or --explode if the reports were built using this option.

};
# Note that usage must be terminated by an extra newline
# to not break POD documentation at make time.

	exit 0;
}

sub gen_database_report
{
	my $db = shift;

	foreach $outfile (@outfiles)
	{
		($current_out_file, $extens) = &set_output_extension($outdir, $outfile, $extension, $db);

		$extens = $dft_extens if ($current_out_file eq '-' && $dft_extens);

		if ($report_per_database)
		{
			&logmsg('LOG', "Ok, generating $extens report for database $db...");
		}
		else
		{
			&logmsg('LOG', "Ok, generating $extens report...");
		}

		$fh = new IO::File ">$current_out_file";
		if (not defined $fh) {
			localdie("FATAL: can't write to $current_out_file, $!\n");
		}
		if (($extens eq 'text') || ($extens eq 'txt'))
		{
			if ($error_only) {
				&dump_error_as_text($db);
			} else {
				&dump_as_text($db);
			}
		}
		elsif ($extens eq 'json')
		{
			if ($error_only) {
				&dump_error_as_json($db);
			} else {
				&dump_as_json($db);
			}
		}
		elsif ($extens eq 'binary')
		{
			&dump_as_binary($fh, $db);
		}
		else
		{
			&dump_as_html('.', $db);
		}
		$fh->close;
	}
}

####
# Function used to validate the possibility to use process on the given
# file. Returns 1 when all multiprocess can be used, 0 when we can not
# use multiprocess on a single file (remore file) and -1 when parallel
# process can not be used too (binary mode).
####
sub confirm_multiprocess
{
	my $file = shift;

	if ($remote_host || $file =~ /^(http[s]*|ftp[s]*|ssh):/) {

		# Disable multi process when using ssh to parse remote log
		if ($queue_size > 1) {
			&logmsg('DEBUG', "parallel processing is not supported with remote files.");
		}
		return 0;
	}

	# Disable parallel processing in binary mode
	if ($format eq 'binary') {
		if (($queue_size > 1) || ($job_per_file > 1)) {
			&logmsg('DEBUG', "parallel processing is not supported with binary format.") if (!$quiet);
		}
		return -1;
	}

	return 1;
}


sub set_ssh_command
{
	my ($ssh_cmd, $rhost) = @_;

	#http://www.domain.com:8080/file.log:format
	#ftp://www.domain.com/file.log:format
	#ssh:root@domain.com:file.log:format

	# Extract format part
	my $fmt = '';
	if ($rhost =~ s/\|([a-z2]+)$//) {
		$fmt = $1;
	}

	$ssh_cmd = $ssh_bin || 'ssh';
	$ssh_cmd .= " -p $ssh_port" if ($ssh_port);
	$ssh_cmd .= " -i $ssh_identity" if ($ssh_identity);
	$ssh_cmd .= " $ssh_options" if ($ssh_options);
	if ($ssh_user && $rhost !~ /\@/) {
		$ssh_cmd .= " $ssh_user\@$rhost";
	} else {
		$ssh_cmd .= " $rhost";
	}

	if (wantarray()) {
		return ($ssh_cmd, $fmt);
	} else {
		return $ssh_cmd;
	}
}

sub set_file_list
{
	my $file = shift;

	my @lfiles = ();

	my $file_orig = $file;
	my $fmt = '';
	# Remove log format from log file if any
	if ($file =~ s/(:(?:stderr|csv|syslog|pgbouncer|jsonlog|logplex|rds|redshift)\d*)$//i)
	{
		$fmt = $1;
	}

	# Store the journalctl command as is we will create a pipe from this command
	if ( $journalctl_cmd && ($file =~ m/\Q$journalctl_cmd\E/) )
	{
		push(@lfiles, $file_orig);
		$empty_files = 0;
	}
	# Store the journalctl command as is we will create a pipe from this command
	elsif ( $log_command && ($file =~ m/\Q$log_command\E/) )
	{
		push(@lfiles, $file_orig);
		$empty_files = 0;
	}
	# Input from stdin
	elsif ($file eq '-')
	{
		if ($logfile_list)
		{
			localdie("FATAL: stdin input - can not be used with logfile list (-L).\n");
		}
		push(@lfiles, $file_orig);
		$empty_files = 0;
	}
	# For input from other sources than stdin
	else
	{
		# if it is not a remote file store the file if it is not an empty file
		if (!$remote_host && $file !~ /^(http[s]*|[s]*ftp|ssh):/i)
		{
			localdie("FATAL: logfile \"$file\" must exist!\n") if (not -f $file);
			if (-z $file)
			{
				print "WARNING: file $file is empty\n" if (!$quiet);
				next;
			}
			push(@lfiles, $file_orig);
			$empty_files = 0;
		}
		# if this is a remote file extract the list of files using a ssh command
		elsif ($file !~ /^(http[s]*|[s]*ftp):/i)
		{
			# Get files from remote host
			if ($file !~ /^ssh:/)
			{
				my($filename, $dirs, $suffix) = fileparse($file);
				&logmsg('DEBUG', "Looking for remote filename using command: $remote_command \"ls '$dirs'$filename\"");
				my @rfiles = `$remote_command "ls '$dirs'$filename"`;
				foreach my $f (@rfiles)
				{
					push(@lfiles, "$f$fmt");
				}
			}
			elsif ($file =~ m#^ssh://([^\/]+)/(.*)#)
			{
				my $host_info = $1;
				my $file = $2;
				my $ssh = $ssh_command || 'ssh';
				if ($host_info =~ s/:(\d+)$//) {
					$host_info = "-p $1 $host_info";
				}
				$ssh .= " -i $ssh_identity" if ($ssh_identity);
				$ssh .= " $ssh_options" if ($ssh_options);
				my($filename, $dirs, $suffix) = fileparse($file);
				&logmsg('DEBUG', "Looking for remote filename using command: $ssh $host_info \"ls '$dirs'$filename\"");
				my @rfiles = `$ssh $host_info "ls '$dirs'$filename"`;
				$dirs = '' if ( $filename ne '' ); #ls returns relative paths for an directory but absolute ones for a file or filename pattern
				foreach my $f (@rfiles)
				{
					$host_info =~ s/-p (\d+) (.*)/$2:$1/;
					push(@lfiles, "ssh://$host_info/$dirs$f$fmt");
				}
			}
			$empty_files = 0;
		}
		# this is remote file extracted using http/ftp protocol, store the uri
		else
		{
			push(@lfiles, $file_orig);
			$empty_files = 0;
		}
	}

	return @lfiles;
}

# Get inbounds of query times histogram
sub get_hist_inbound
{
	my ($duration, @histogram) = @_;

	for (my $i = 0; $i <= $#histogram; $i++) {
		return $histogram[$i-1] if ($histogram[$i] > $duration);
	}

	return -1;
}

# Compile custom log line prefix prefix
sub set_parser_regex
{
	my $fmt = shift;

	@prefix_params = ();
	@prefix_q_params = ();

	if ($fmt eq 'pgbouncer')
	{
		$pgbouncer_log_format = qr/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+(?: [A-Z\+\-\d]{3,6})? (\d+) ([^\s]+) (.\-0x[0-9a-f\.]*): ([0-9a-zA-Z\_\[\]\-\.]*)\/([0-9a-zA-Z\_\[\]\-\.]*)\@([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)(?:\(\d+\))??[:\d]* (.*)/;
		@pgb_prefix_params = ('t_timestamp', 't_pid', 't_loglevel', 't_session_id', 't_dbname', 't_dbuser', 't_client', 't_query');
		$pgbouncer_log_parse1 = qr/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+(?: [A-Z\+\-\d]{3,6})? (\d+) ([^\s]+) (.\-0x[0-9a-f\.]+|[Ss]tats): (.*)/;
		@pgb_prefix_parse1 = ('t_timestamp', 't_pid', 't_loglevel', 't_session_id', 't_query');
		$pgbouncer_log_parse2 = qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+(?: [A-Z\+\-\d]{3,6})? \d+ [^\s]+ .\-0x[0-9a-f\.]*: ([0-9a-zA-Z\_\[\]\-\.]*)\/([0-9a-zA-Z\_\[\]\-\.]*)\@([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)?(?:\(\d+\))?(?:\(\d+\))?[:\d]* (.*)/;
		@pgb_prefix_parse2 = ('t_dbname', 't_dbuser', 't_client', 't_query');
		$pgbouncer_log_parse3 = qr/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+(?: [A-Z\+\-\d]{3,6})? (\d+) ([^\s]+) ([^:]+: .*)/;
		@pgb_prefix_parse3 = ('t_timestamp', 't_pid', 't_loglevel', 't_query');

	}
	elsif ($fmt eq 'pgbouncer1')
	{
		$pgbouncer_log_format = qr/^(...)\s+(\d+)\s(\d+):(\d+):(\d+)(?:\s[^\s]+)?\s([^\s]+)\s([^\s\[]+)\[(\d+)\]: (.\-0x[0-9a-f\.]*): ([0-9a-zA-Z\_\[\]\-\.]*)\/([0-9a-zA-Z\_\[\]\-\.]*)\@([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)?(?:\(\d+\))?[:\d]* (.*)/;
		@pgb_prefix_params = ('t_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_session_id', 't_dbname', 't_dbuser', 't_client', 't_query');

		$pgbouncer_log_parse1 = qr/^(...)\s+(\d+)\s(\d+):(\d+):(\d+)(?:\s[^\s]+)?\s([^\s]+)\s([^\s\[]+)\[(\d+)\]: (.\-0x[0-9a-f\.]+|[Ss]tats): (.*)/;
		@pgb_prefix_parse1 = ('t_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_session_id', 't_query');
		$pgbouncer_log_parse2 = qr/^...\s+\d+\s\d+:\d+:\d+(?:\s[^\s]+)?\s[^\s]+\s[^\s\[]+\[\d+\]: .\-0x[0-9a-f\.]*: ([0-9a-zA-Z\_\[\]\-\.]*)\/([0-9a-zA-Z\_\[\]\-\.]*)\@([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)?(?:\(\d+\))?[:\d]* (.*)/;
		@pgb_prefix_parse2 = ('t_dbname', 't_dbuser', 't_client', 't_query');
		$pgbouncer_log_parse3 = qr/^(...)\s+(\d+)\s(\d+):(\d+):(\d+)(?:\s[^\s]+)?\s([^\s]+)\s([^\s\[]+)\[(\d+)\]: ([^:]+: .*)/;
		@pgb_prefix_parse3 = ('t_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_query');

	}
	elsif ($fmt eq 'pgbouncer2')
	{
		$pgbouncer_log_format = qr/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:.[^\s]+)?\s([^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[(\d+)\]: (.\-0x[0-9a-f\.]*): ([0-9a-zA-Z\_\[\]\-\.]*)\/([0-9a-zA-Z\_\[\]\-\.]*)\@([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)?(?:\(\d+\))?[:\d]* (.*)/;
		@pgb_prefix_params = ('t_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_session_id', 't_dbname', 't_dbuser', 't_client', 't_query');

		$pgbouncer_log_parse1 = qr/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:.[^\s]+)?\s([^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[(\d+)\]: (.\-0x[0-9a-f\.]+|[Ss]tats): (.*)/;
		@pgb_prefix_parse1 = ('t_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_session_id', 't_query');
		$pgbouncer_log_parse2 = qr/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:.[^\s]+)?\s[^\s]+\s(?:[^\s]+\s)?(?:[^\s]+\s)?[^\s\[]+\[\d+\]: .\-0x[0-9a-f\.]*: ([0-9a-zA-Z\_\[\]\-\.]*)\/([0-9a-zA-Z\_\[\]\-\.]*)\@([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)?(?:\(\d+\))?[:\d]* (.*)/;
		@pgb_prefix_parse2 = ('t_dbname', 't_dbuser', 't_client', 't_query');
		$pgbouncer_log_parse3 = qr/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:.[^\s]+)?\s([^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[(\d+)\]: ([^:]+: .*)/;
		@pgb_prefix_parse3 = ('t_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_query');
	}
	elsif ($fmt eq 'pgbouncer3')
	{
		$pgbouncer_log_format = qr/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+(?: [A-Z\+\-\d]{3,6})? \[(\d+)\] ([^\s]+) (.\-0x[0-9a-f\.]*): ([0-9a-zA-Z\_\[\]\-\.]*)\/([0-9a-zA-Z\_\[\]\-\.]*)\@([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)(?:\(\d+\))??[:\d]* (.*)/;
		@pgb_prefix_params = ('t_timestamp', 't_pid', 't_loglevel', 't_session_id', 't_dbname', 't_dbuser', 't_client', 't_query');
		$pgbouncer_log_parse1 = qr/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+(?: [A-Z\+\-\d]{3,6})? \[(\d+)\] ([^\s]+) (.\-0x[0-9a-f\.]+|[Ss]tats): (.*)/;
		@pgb_prefix_parse1 = ('t_timestamp', 't_pid', 't_loglevel', 't_session_id', 't_query');
		$pgbouncer_log_parse2 = qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+(?: [A-Z\+\-\d]{3,6})? \[\d+\] [^\s]+ .\-0x[0-9a-f\.]*: ([0-9a-zA-Z\_\[\]\-\.]*)\/([0-9a-zA-Z\_\[\]\-\.]*)\@([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)?(?:\(\d+\))?(?:\(\d+\))?[:\d]* (.*)/;
		@pgb_prefix_parse2 = ('t_dbname', 't_dbuser', 't_client', 't_query');
		$pgbouncer_log_parse3 = qr/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+(?: [A-Z\+\-\d]{3,6})? \[(\d+)\] ([^\s]+) ([^:]+: .*)/;
		@pgb_prefix_parse3 = ('t_timestamp', 't_pid', 't_loglevel', 't_query');
	}
	elsif ($log_line_prefix)
	{
		# Build parameters name that will be extracted from the prefix regexp
		my %res = &build_log_line_prefix_regex($log_line_prefix);
		my $llp = $res{'llp'};
		@prefix_params = @{ $res{'param_list'} };
		$q_prefix = $res{'q_prefix'};
		@prefix_q_params = @{ $res{'q_param_list'} };

		if ($fmt eq 'syslog')
		{
			$llp =
				  '^(...)\s+(\d+)\s(\d+):(\d+):(\d+)(?:\.\d+)?(?:\s[^\s]+)?\s([^\s]+)\s([^\s\[]+)\[(\d+)\]:(?:\s\[[^\]]+\])?\s\[(\d+)(?:\-\d+)?\]\s*'
				. $llp
				. '\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(?:[0-9A-Z]{5}:\s+)?(.*)';
			$compiled_prefix = qr/$llp/;
			unshift(@prefix_params, 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_session_line');
			push(@prefix_params, 't_loglevel', 't_query');
			$other_syslog_line = qr/^(...)\s+(\d+)\s(\d+):(\d+):(\d+)(?:\s[^\s]+)?\s([^\s]+)\s([^\s\[]+)\[(\d+)\]:(?:\s\[[^\]]+\])?\s\[(\d+)(?:\-\d+)?\]\s*(.*)/;
		}
		elsif ($fmt eq 'syslog2')
		{
			$fmt = 'syslog';
			$llp =
				  '^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:.[^\s]+)?\s([^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[(\d+)\]:(?:\s\[[^\]]+\])?(?:\s\[(\d+)(?:\-\d+)?\])?\s*'
				. $llp
				. '\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(?:[0-9A-Z]{5}:\s+)?(.*)';
			$compiled_prefix = qr/$llp/;
			unshift(@prefix_params, 't_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_session_line');
			push(@prefix_params, 't_loglevel', 't_query');
			$other_syslog_line = qr/^(\d+-\d+)-(\d+)T(\d+):(\d+):(\d+)(?:.[^\s]+)?\s([^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[(\d+)\]:(?:\s\[[^\]]+\])?(?:\s\[(\d+)(?:\-\d+)?\])?\s*(.*)/;
	       }
	       elsif ($fmt eq 'logplex')
	       {
		       # The output format of the heroku pg logs is as follows: timestamp app[dyno]: message

		       $llp =
				 '^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:\.\d+)?[+\-]\d{2}:\d{2}\s+(?:[^\s]+)?\s*app\[postgres\.(\d+)\][:]?\s+\[([^\]]+)\]\s+\[\d+\-\d+\]\s+'
			       . $llp
			       . '\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)';
		       $compiled_prefix = qr/$llp/;
		       unshift(@prefix_params, 't_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_pid', 't_dbname');
		       push(@prefix_params, 't_loglevel', 't_query');
		       $other_syslog_line = qr/^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:\.\d+)?[+\-]\d{2}:\d{2}\s+(?:[^\s]+)?\s*app\[postgres\.\d+\][:]?\s+\[([^\]]+)\]\s+\[(\d+)\-(\d+)\]\s*(.*)/;
		}
		elsif ($fmt =~ /^rds$/)
		{
		       # The output format of the RDS pg logs is as follows: %t:%r:%u@%d:[%p]: message
		       # With Cloudwatch it is prefixed with another timestamp

		       $llp = '^' . $llp
			      . '(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)';
		       $compiled_prefix = qr/$llp/;
		       @prefix_params = ('t_timestamp', 't_client', 't_dbuser', 't_dbname', 't_pid', 't_loglevel', 't_query');
		}
		elsif ($fmt =~ /^redshift$/)
		{
		       # Look at format of the AWS redshift pg logs, for example:
		       # '2020-03-07T16:09:43Z UTC [ db=dev user=rdsdb pid=16929 userid=1 xid=7382 ]'

		       $llp = '^' . $llp
			      . '(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)';
		       $compiled_prefix = qr/$llp/;
		       @prefix_params = ('t_timestamp', 't_dbname', 't_dbuser', 't_pid', 't_loglevel', 't_query');
		}
		elsif ($fmt eq 'stderr' || $fmt eq 'default' || $fmt eq 'jsonlog')
		{
			$fmt = 'stderr' if ($fmt ne 'jsonlog');
			$llp = '^' . $llp . '\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(?:[0-9A-Z]{5}:\s+)?(.*)';
			$compiled_prefix = qr/$llp/;
			push(@prefix_params, 't_loglevel', 't_query');
		}
	}
	elsif ($fmt eq 'syslog')
	{
		$compiled_prefix =
	qr/^(...)\s+(\d+)\s(\d+):(\d+):(\d+)(?:\.\d+)?(?:\s[^\s]+)?\s([^\s]+)\s([^\s\[]+)\[(\d+)\]:(?:\s\[[^\]]+\])?\s\[(\d+)(?:\-\d+)?\]\s*(.*?)\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(?:[0-9A-Z]{5}:\s+)?(.*)/;
		push(@prefix_params, 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_session_line',
			't_logprefix', 't_loglevel', 't_query');
		$other_syslog_line = qr/^(...)\s+(\d+)\s(\d+):(\d+):(\d+)(?:\.\d+)?(?:\s[^\s]+)?\s([^\s]+)\s([^\s\[]+)\[(\d+)\]:(?:\s\[[^\]]+\])?\s\[(\d+)(?:\-\d+)?\]\s*(.*)/;
	}
	elsif ($fmt eq 'syslog2')
	{
		$fmt = 'syslog';
		$compiled_prefix =
	qr/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:.[^\s]+)?\s([^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[(\d+)\]:(?:\s\[[^\]]+\])?(?:\s\[(\d+)(?:\-\d+)?\])?\s*(.*?)\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(?:[0-9A-Z]{5}:\s+)?(.*)/;
		push(@prefix_params, 't_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_host', 't_ident', 't_pid', 't_session_line',
			't_logprefix', 't_loglevel', 't_query');
		$other_syslog_line = qr/^(\d+-\d+)-(\d+)T(\d+):(\d+):(\d+)(?:.[^\s]+)?\s([^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[(\d+)\]:(?:\s\[[^\]]+\])?(?:\s\[(\d+)(?:\-\d+)?\])?\s*(.*)/;
	}
	elsif ($fmt eq 'logplex')
	{
	       # The output format of the heroku pg logs is as follows: timestamp app[dyno]: message
	       $compiled_prefix =
			 qr/^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:\.\d+)?[+\-]\d{2}:\d{2}\s+(?:[^\s]+)?\s*app\[postgres\.(\d+)\][:]?\s+\[([^\]]+)\]\s+\[\d+\-\d+\]\s+(.*?)\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)/;
	       unshift(@prefix_params, 't_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_pid', 't_dbname');
	       push(@prefix_params, 't_logprefix', 't_loglevel', 't_query');
	       $other_syslog_line = qr/^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:\.\d+)?[+\-]\d{2}:\d{2}\s+(?:[^\s]+)?\s*app\[(postgres)\.(\d+)\][:]?\s+\[([^\]]+)\]\s+\[\d+\-\d+\]\s*(.*)/;
	}
	elsif ($fmt eq 'rds')
	{
	       # The output format of the RDS pg logs is as follows: %t:%r:%u@%d:[%p]: message
	       # With Cloudwatch it is prefixed with another timestamp

	       $compiled_prefix =
			 qr/^(?:\d+-\d+-\d+T\d+:\d+:\d+\.\d+Z)?\s*(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)\s*[^:]*:([^:]*):([^\@]*)\@([^:]*):\[(\d+)\]:(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)/;
	       unshift(@prefix_params, 't_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_client', 't_dbuser', 't_dbname', 't_pid', 't_loglevel', 't_query');
	}
	elsif ($fmt eq 'redshift')
	{
	       # Look at format of the AWS redshift pg logs, for example:
	       # '2020-03-07T16:09:43Z UTC [ db=dev user=rdsdb pid=16929 userid=1 xid=7382 ]'
	       $compiled_prefix =
			 qr/^'(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z [^\s]+ \[ db=(.*?) user=(.*?) pid=(\d+) userid=\d+ xid=(?:.*?) \]' (LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)/;
	       unshift(@prefix_params, 't_year', 't_month', 't_day', 't_hour', 't_min', 't_sec', 't_dbname', 't_dbuser', 't_pid', 't_loglevel', 't_query');
	}
	elsif ($fmt eq 'stderr')
	{
		$compiled_prefix =
	qr/^(\d{10}\.\d{3}|\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})[\.\d]*(?: [A-Z\+\-\d]{3,6})?\s\[([0-9a-f\.]+)\][:]*\s(?:\[\d+\-\d+\])?\s*(.*?)\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(?:[0-9A-Z]{5}:\s+)?(.*)/;
		push(@prefix_params, 't_timestamp', 't_pid', 't_logprefix', 't_loglevel', 't_query');
	}
	elsif ($fmt eq 'default')
	{
		$fmt = 'stderr';
		$compiled_prefix =
	qr/^(\d{10}\.\d{3}|\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})[\.\d]*(?: [A-Z\+\-\d]{3,6})?\s\[([0-9a-f\.]+)\][:]*\s(.*?)\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(?:[0-9A-Z]{5}:\s+)?(.*)/;
		push(@prefix_params, 't_timestamp', 't_pid', 't_logprefix', 't_loglevel', 't_query');
	}

	return $fmt;
}

sub check_regex
{
	my ($pattern, $varname) = @_;

	eval {m/$pattern/i;};
	if ($@) {
		localdie("FATAL: '$varname' invalid regex '$pattern', $!\n");
	}
}


sub build_incremental_reports
{
	my @build_directories = @_;

	my $destdir = $html_outdir || $outdir;

	my %weeks_directories = ();
	foreach my $bpath (sort @build_directories)
	{
		my $binpath = '';
		$binpath = $1 if ($bpath =~ s/^(.*\/)(\d+\-\d+\-\d+)$/$2/);
		&logmsg('DEBUG', "Building incremental report for " . $bpath);

		$incr_date = $bpath;
		$last_incr_date = $bpath;

		# Set the path to binary files
		$bpath =~ s/\-/\//g;

		# Get the week number following the date
		$incr_date =~ /^(\d+)-(\d+)\-(\d+)$/;
		my $wn = &get_week_number($1, $2, $3);
		if (!$noweekreport)
		{
			if ($rebuild || !exists $weeks_directories{$wn})
			{
				$weeks_directories{$wn}{dir} = "$1-$2";
				$weeks_directories{$wn}{prefix} = $binpath if ($binpath);
			}
		}

		# First clear previous stored statistics
		&init_stats_vars();

		# Load all data gathered by all the different processes
		$destdir = $binpath || $outdir;
		if (opendir(DIR, "$destdir/$bpath"))
		{
			my @mfiles = grep { !/^\./ && ($_ =~ /\.bin$/) } readdir(DIR);
			closedir DIR;
			foreach my $f (@mfiles)
			{
				my $fht = new IO::File;
				$fht->open("< $destdir/$bpath/$f") or localdie("FATAL: can't open file $destdir/$bpath/$f, $!\n");
				load_stats($fht);
				$fht->close();
			}
		}

		$destdir = $html_outdir || $outdir;
		foreach my $db (sort keys %DBLIST)
		{
			#next if ($#dbname >= 0 and !grep(/^$db$/i, @dbname));
			my $tmp_dir = "$destdir/$db";
			$tmp_dir = $destdir if (!$report_per_database);
			&logmsg('LOG', "Ok, generating HTML daily report into $tmp_dir/$bpath/...");
			# set path and create subdirectories
			mkdir("$tmp_dir") if (!-d "$tmp_dir");
			if ($bpath =~ m#^(\d+)/(\d+)/(\d+)#)
			{
				mkdir("$tmp_dir/$1") if (!-d "$tmp_dir/$1");
				mkdir("$tmp_dir/$1/$2") if (!-d "$tmp_dir/$1/$2");
				mkdir("$tmp_dir/$1/$2/$3") if (!-d "$tmp_dir/$1/$2/$3");
			}
			else
			{
				&logmsg('ERROR', "invalid path: $bpath, can not create subdirectories.");
			}

			$fh = new IO::File ">$tmp_dir/$bpath/$current_out_file";
			if (not defined $fh) {
				localdie("FATAL: can't write to $tmp_dir/$bpath/$current_out_file, $!\n");
			}
			&dump_as_html('../../..', $db);
			$fh->close;

		}
	}

	# Build a report per week
	foreach my $wn (sort { $a <=> $b } keys %weeks_directories)
	{
		&init_stats_vars();

		# Get all days of the current week
		my $getwnb = $wn;
		$getwnb-- if (!$iso_week_number);
		my @wdays = &get_wdays_per_month($getwnb, $weeks_directories{$wn}{dir});
		my $binpath = '';
		$binpath = $weeks_directories{$wn}{prefix} if (defined $weeks_directories{$wn}{prefix});
		my $wdir = '';

		# Load data per day
		foreach my $bpath (@wdays)
		{
			$incr_date = $bpath;
			$bpath =~ s/\-/\//g;
			$incr_date =~ /^(\d+)\-(\d+)\-(\d+)$/;
			$wdir = "$1/week-$wn";

			$destdir = $binpath || $outdir;
			# Load all data gathered by all the differents processes
			if (-e "$destdir/$bpath")
			{
				unless(opendir(DIR, "$destdir/$bpath")) {
					localdie("FATAL: can't opendir $destdir/$bpath: $!\n");
				}
				my @mfiles = grep { !/^\./ && ($_ =~ /\.bin$/) } readdir(DIR);
				closedir DIR;
				foreach my $f (@mfiles)
				{
					my $fht = new IO::File;
					$fht->open("< $destdir/$bpath/$f") or localdie("FATAL: can't open file $destdir/$bpath/$f, $!\n");
					load_stats($fht);
					$fht->close();
				}
			}
		}

		$destdir = $html_outdir || $outdir;
		foreach my $db (sort keys %DBLIST)
		{
			#next if ($#dbname >= 0 and !grep(/^$db$/i, @dbname));
			my $tmp_dir = "$destdir/$db";
			$tmp_dir = $destdir if (!$report_per_database);
			&logmsg('LOG', "Ok, generating HTML weekly report into $tmp_dir/$wdir/...");
			mkdir("$tmp_dir") if (!-d "$tmp_dir");
			my $path = $tmp_dir;
			foreach my $d (split('/', $wdir))
			{
				mkdir("$path/$d") if (!-d "$path/$d");
				$path .= "/$d";
			}

			$fh = new IO::File ">$tmp_dir/$wdir/$current_out_file";
			if (not defined $fh) {
				localdie("FATAL: can't write to $tmp_dir/$wdir/$current_out_file, $!\n");
			}
			&dump_as_html('../..', $db);
			$fh->close;
		}
	}

	# Generate global index to access incremental reports
	&build_global_index();
}

sub build_month_reports
{
	my ($month_path, @build_directories) = @_;

	# First clear previous stored statistics
	&init_stats_vars();

	foreach my $bpath (sort @build_directories) {

		$incr_date = $bpath;
		$last_incr_date = $bpath;

		# Set the path to binary files
		$bpath =~ s/\-/\//g;

		# Get the week number following the date
		$incr_date =~ /^(\d+)-(\d+)\-(\d+)$/;

		&logmsg('DEBUG', "reading month statistics from $outdir/$bpath");

		# Load all data gathered by all the different processes
		unless(opendir(DIR, "$outdir/$bpath")) {
			localdie("FATAL: can't opendir $outdir/$bpath: $!\n");
		}
		my @mfiles = grep { !/^\./ && ($_ =~ /\.bin$/) } readdir(DIR);
		closedir DIR;
		foreach my $f (@mfiles) {
			my $fht = new IO::File;
			$fht->open("< $outdir/$bpath/$f") or localdie("FATAL: can't open file $outdir/$bpath/$f, $!\n");
			load_stats($fht);
			$fht->close();
		}
	}

	my $dest_dir = $html_outdir || $outdir;
	foreach my $db (sort keys %DBLIST)
	{
		my $tmp_dir = "$dest_dir/$db";
		$tmp_dir = $dest_dir if (!$report_per_database);
		&logmsg('LOG', "Ok, generating HTML monthly report into $tmp_dir/$month_path/index.html");
		mkdir("$tmp_dir") if (!-d "$tmp_dir");
		my $path = $tmp_dir;
		foreach my $d (split('/', $month_path)) {
			mkdir("$path/$d") if (!-d "$path/$d");
			$path .= "/$d";
		}
		$fh = new IO::File ">$tmp_dir/$month_path/index.html";
		if (not defined $fh) {
			localdie("FATAL: can't write to $tmp_dir/$month_path/index.html, $!\n");
		}
		&dump_as_html('../..', $db);
		$fh->close;
	}
	# Generate global index to access incremental reports
	&build_global_index();
}

sub build_day_reports
{
	my ($day_path, @build_directories) = @_;

	# First clear previous stored statistics
	&init_stats_vars();

	foreach my $bpath (sort @build_directories) {

		$incr_date = $bpath;
		$last_incr_date = $bpath;

		# Set the path to binary files
		$bpath =~ s/\-/\//g;

		# Get the week number following the date
		$incr_date =~ /^(\d+)-(\d+)\-(\d+)$/;

		&logmsg('DEBUG', "reading month statistics from $outdir/$bpath");

		# Load all data gathered by all the different processes
		unless(opendir(DIR, "$outdir/$bpath")) {
			localdie("FATAL: can't opendir $outdir/$bpath: $!\n");
		}
		my @mfiles = grep { !/^\./ && ($_ =~ /\.bin$/) } readdir(DIR);
		closedir DIR;
		foreach my $f (@mfiles) {
			my $fht = new IO::File;
			$fht->open("< $outdir/$bpath/$f") or localdie("FATAL: can't open file $outdir/$bpath/$f, $!\n");
			load_stats($fht);
			$fht->close();
		}
	}

	my $dest_dir = $html_outdir || $outdir;
	foreach my $db (sort keys %DBLIST)
	{
		my $tmp_dir = "$dest_dir/$db";
		$tmp_dir = $dest_dir if (!$report_per_database);
		&logmsg('LOG', "Ok, generating HTML daily report into $tmp_dir/$day_path/index.html");
		mkdir("$tmp_dir") if (!-d "$tmp_dir");
		my $path = $tmp_dir;
		foreach my $d (split('/', $day_path))
		{
			mkdir("$path/$d") if (!-d "$path/$d");
			$path .= "/$d";
		}
		$fh = new IO::File ">$tmp_dir/$day_path/index.html";
		if (not defined $fh) {
			localdie("FATAL: can't write to $tmp_dir/$day_path/index.html, $!\n");
		}
		&dump_as_html('../..', $db);
		$fh->close;
	}
	# Generate global index to access incremental reports
	&build_global_index();
}


sub build_global_index
{
	&logmsg('LOG', "Ok, generating global index to access incremental reports...");

	my $dest_dir = $html_outdir || $outdir;

	# Get database directories
	unless(opendir(DIR, "$dest_dir")) {
		localdie("FATAL: can't opendir $dest_dir: $!\n");
	}
	my @dbs = grep { !/^\./ && !/^\d{4}$/ && -d "$dest_dir/$_" } readdir(DIR);
	closedir DIR;
	@dbs = ($DBALL) if (!$report_per_database);

	foreach my $db (@dbs)
	{
		#next if ($#dbname >= 0 and !grep(/^$db$/i, @dbname));
		my $tmp_dir = "$dest_dir/$db";
		$tmp_dir = $dest_dir if (!$report_per_database);
		&logmsg('DEBUG', "writing global index into $tmp_dir/index.html");
		$fh = new IO::File ">$tmp_dir/index.html";
		if (not defined $fh) {
			localdie("FATAL: can't write to $tmp_dir/index.html, $!\n");
		}
		my $date = localtime(time);
		my @tmpjscode = @jscode;
		my $path_prefix = '.';
		$path_prefix = '..' if ($report_per_database);
		for (my $i = 0; $i <= $#tmpjscode; $i++) {
			$tmpjscode[$i] =~ s/EDIT_URI/$path_prefix/;
		}
		my $local_title = 'Global Index on incremental reports';
		if ($report_title) {
			$local_title = 'Global Index - ' . $report_title;
		}
		print $fh qq{<!DOCTYPE html>
<html lang="en">
<head>
<title>pgBadger :: $local_title</title>
<meta http-equiv="Content-Type" content="text/html; charset=$charset" />
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="Expires" content="$date">
<meta http-equiv="Generator" content="pgBadger v$VERSION">
<meta http-equiv="Date" content="$date">
<link rel="shortcut icon" href="$pgbadger_ico" />
<meta name="viewport" content="user-scalable=no, initial-scale = 1, minimum-scale = 1, maximum-scale = 1, width=device-width">
@tmpjscode
</head>

<body>

<div class="navbar navbar-inverse navbar-fixed-top">
    <div class="container-fluid">
	<div class="navbar-header">
	<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
	  <span class="icon-bar"></span>
	  <span class="icon-bar"></span>
	  <span class="icon-bar"></span>
	</button>
	$pgbadger_logo
	<div class="pull-right"> <a title="PostgreSQL Log Analyzer" href="" id="pgbadger-brand" class="navbar-brand" data-original-title="PostgreSQL Log Analyzer">$local_title</a></div>
	</div>
    </div>
</div>

<div class="container" id="main-container">

<style type="text/css">
.btn-primary {
	font-size: 2.0em;
	font-weight: bold;
	height: 60px;
	width: 184px;
}
</style>

};
		# get year directories
		unless(opendir(DIR, "$tmp_dir")) {
			localdie("FATAL: can't opendir $tmp_dir: $!\n");
		}
		my @dyears = grep { !/^\./ && /^\d{4}$/ } readdir(DIR);
		closedir DIR;
		foreach my $y (sort { $b <=> $a } @dyears)
		{
			print $fh qq{
<h1>Year $y</h1>
	<table class="table table-condensed"><tr>
};
			# foreach year directory look for week directories
			unless(opendir(DIR, "$tmp_dir/$y")) {
				localdie("FATAL: can't opendir $tmp_dir/$y: $!\n");
			}

			my @ymonths = grep { /^\d{2}$/ } readdir(DIR);
			closedir DIR;
			my $i = 1;
			foreach my $m (sort {$a <=> $b } @ymonths)
			{
				print $fh "<td><span>", &get_calendar($db, $y, $m), "</span></td>\n";
				print $fh "</tr>\n<tr>\n" if ( ($i%4) == 0 );
				$i++;
			}
			print $fh qq{
	</tr></table>
};
		}
		print $fh qq{
</div>

<footer>
<div class="">
	<small class="pull-right">Report generated by <a href="$project_url" target="_new">pgBadger $VERSION.</a></small>
</div>
</footer>

<div id="littleToc">
	<div id="littleTocTitle"><a href="#top">&nbsp;^&nbsp;</a></div>
</div>

</body>
</html>
};
		$fh->close;
	}
}


sub cleanup_directory
{
	my ($dir, $remove_dir) = @_;

	unless(opendir(DIR, "$dir")) {
		localdie("FATAL: can't opendir $dir: $!\n");
	}
	my @todel = grep { !/^\./ } readdir(DIR);
	closedir DIR;
	map { unlink("$dir/$_"); } @todel;
	rmdir("$dir") if ($remove_dir);
}


sub cleanup_directory_bin
{
	my ($dir, $remove_dir) = @_;

	if (opendir(DIR, "$dir")) {
		my @todel = grep { $_ =~ /\.bin$/i } readdir(DIR);
		closedir DIR;
		map { unlink("$dir/$_"); } @todel;
		rmdir("$dir") if ($remove_dir);
	}
}


sub cleanup_directory_html
{
	my ($dir, $remove_dir) = @_;

	if (opendir(DIR, "$dir")) {
		my @todel = grep { $_ =~ /\.(html|txt|tsung|json)$/i } readdir(DIR);
		closedir DIR;
		map { unlink("$dir/$_"); } @todel;
		rmdir("$dir") if ($remove_dir);
	}
}


sub write_resources
{
	# Write resource file to report directory or return resources in and array of lines
	my $rscfh;
	my @contents = ();
	my $endfile = '';
	my $file = '';
	my $major_version = $VERSION;
	$major_version =~ s/\..*//;

	my $rscdir = $html_outdir || $outdir;
	while (my $l = <DATA>)
	{
		last if ($l =~ /^__END__$/);
		if ($l =~ /^WRFILE: ([^\s]+)/)
		{
			$file = $1;
			if (!$extra_files)
			{
				if ($#contents > 0) {
					push(@contents, $endfile);
				}
				if ($file =~ /\.css$/i)
				{
					push(@contents, "<style type=\"text/css\">\n");
					$endfile = "</style>";
				}
				elsif ($file =~ /\.js$/i)
				{
					push(@contents, "<script type=\"text/javascript\">\n");
					$endfile = "</script>";
				}
				next;
			}
			$rscfh->close() if (defined $rscfh);
			if ($file =~ /\.css$/i) {
				push(@contents, "<link href=\"EDIT_URI/$major_version/$file\" rel=\"stylesheet\">\n");
			} elsif ($file =~ /\.js$/i) {
					push(@contents, "<script type=\"text/javascript\" src=\"EDIT_URI/$major_version/$file\"></script>\n");
			}
			if ($extra_files)
			{
				if (!-e "$rscdir/$major_version") {
					mkdir("$rscdir/$major_version");
				}
				if (!-e "$rscdir/$major_version/$file")
				{
					$rscfh = new IO::File ">$rscdir/$major_version/$file";
					localdie("FATAL: can't write file $rscdir/$major_version/$file\n") if (not defined $rscfh);
				}
			}
			next;
		}
		if (!$extra_files) {
			push(@contents, $l);
		} else {
			$rscfh->print($l) if (defined $rscfh);
		}
	}

	$rscfh->close() if (defined $rscfh);

	# Return __DATA__ content if --extra-files is not used
	# or HTML links to resources files
	if (!$extra_files) {
		push(@contents, $endfile);
	}

	return @contents;
}

sub sort_by_week
{
	my $curr = shift;
	my $next = shift;

	$a =~ /week\-(\d+)/;
	$curr = $1;
	$b =~ /week\-(\d+)/;
	$next = $1;

	return $next <=> $curr;
}

sub init_stats_vars
{

	# Empty where statistics are stored
	%overall_stat	     = ();
	%pgb_overall_stat    = ();
	%overall_checkpoint  = ();
	%top_slowest	     = ();
	%top_tempfile_info   = ();
	%top_cancelled_info  = ();
	%top_locked_info     = ();
	%normalyzed_info     = ();
	%error_info	     = ();
	%pgb_error_info      = ();
	%pgb_pool_info       = ();
	%logs_type	     = ();
	%errors_code	     = ();
	%per_minute_info     = ();
	%pgb_per_minute_info = ();
	%lock_info	     = ();
	%tempfile_info       = ();
	%cancelled_info      = ();
	%connection_info     = ();
	%pgb_connection_info = ();
	%database_info       = ();
	%application_info    = ();
	%session_info	     = ();
	%pgb_session_info    = ();
	%conn_received       = ();
	%checkpoint_info     = ();
	%autovacuum_info     = ();
	%autoanalyze_info    = ();
	@graph_values	     = ();
	%cur_info	     = ();
	$nlines	             = 0;
}

####
# Main function called per each parser process
####
sub multiprocess_progressbar
{
	my $totalsize = shift;

	&logmsg('DEBUG', "Starting progressbar writer process");

	$0 = 'pgbadger logger' if (!$disable_process_title);

	# Terminate the process when we haven't read the complete file but must exit
	local $SIG{USR1} = sub {
		print STDERR "\n";
		exit 1;
	};
	my $timeout  = 3;
	my $cursize  = 0;
	my $nqueries = 0;
	my $nerrors  = 0;
	my $fmt      = 'stderr';
	$pipe->reader();
	while (my $r = <$pipe>)
	{
		chomp($r);
		my @infos = split(/\s+/, $r);
		last if ($infos[0] eq 'QUIT');
		$cursize  += $infos[0];
		$nqueries += $infos[1];
		$nerrors  += $infos[2];
		$fmt      = $infos[3] if ($#infos == 3);

		$cursize = $totalsize if ($totalsize > 0 && $cursize > $totalsize);
		print STDERR &progress_bar($cursize, $totalsize, 25, '=', $nqueries, $nerrors, $fmt);
	}
	print STDERR "\n";

	exit 0;
}

sub update_progress_bar
{
	my ($tmpoutfile, $nlines, $stop_offset, $totalsize, $cursize, $old_queries_count, $old_errors_count, $fmt) = @_;

	return if (!$progress);

	if (!$tmpoutfile || not defined $pipe)
	{
		if ($progress && (($nlines % $NUMPROGRESS) == 0)) {
			print STDERR &progress_bar($$cursize, $stop_offset || $totalsize, 25, '=', undef, undef, $fmt);
			$NUMPROGRESS *= 10 if ($NUMPROGRESS < 10000);
		}
	}
	else
	{
		if ($progress && ($nlines % $NUMPROGRESS) == 0)
		{
			$pipe->print("$$cursize " .
				($overall_stat{'queries_number'} + $pgb_overall_stat{'errors_number'} - $$old_queries_count) .
				" " .
				($overall_stat{'errors_number'} + $pgb_overall_stat{'errors_number'} - $$old_errors_count) .
				" $fmt\n");
			$$old_queries_count = $overall_stat{'queries_number'} + $pgb_overall_stat{'queries_number'};
			$$old_errors_count  = $overall_stat{'errors_number'}  + $pgb_overall_stat{'errors_number'};
			$$cursize = 0;
			$NUMPROGRESS *= 10 if ($NUMPROGRESS < 10000);
		}
	}
}

sub is_pgbouncer_error
{
	if ($_[0] =~ /(login|connect) failed /) {
		return 'FATAL';
	}

	return 'LOG';
}

sub set_current_db
{
	my $dbn = shift;

	# Don't collect stats on database if it is excluded
	return $dbn if (grep(/^$dbn$/i, @exclude_db));

	if (!$report_per_database || !$dbn || $dbn eq '[unknown]')
	{
		$overall_stat{nlines}{$DBALL}++;
		return $DBALL
	}

	$DBLIST{$dbn} = 1;
	$overall_stat{nlines}{$dbn}++;

	return $dbn;
}


####
# Main function called per each parser process
####
sub process_file
{
	my ($logfile, $totalsize, $fmt, $tmpoutfile, $start_offset, $stop_offset, $chunk_pos) = @_;

	my $old_queries_count = 0;
	my $old_errors_count  = 0;
	my $getout	      = 0;
	my $http_download     = ($logfile =~ /^(http[s]*:|[s]*ftp:)/i) ? 1 : 0;

	$start_offset       ||= 0;

	$0 = 'pgbadger parser' if (!$disable_process_title);

	&init_stats_vars() if ($tmpoutfile);

	if (!$remote_host) {
		&logmsg('DEBUG', "Processing log file: $logfile");
	} else {
		&logmsg('DEBUG', "Processing remote log file: $remote_host:$logfile");
	}

	local $SIG{INT} = sub { print STDERR "Received SIGINT abort parsing...\n"; unlink("$PID_FILE"); $terminate = 1; };
	local $SIG{TERM} = sub { print STDERR "Received SIGTERM abort parsing...\n"; unlink("$PID_FILE"); $terminate = 1; };

	my $curdate = localtime(time);

	# Syslog does not have year information, so take care of year overlapping
	my ($gsec, $gmin, $ghour, $gmday, $gmon, $gyear, $gwday, $gyday, $gisdst) = localtime(time);
	$gyear += 1900;
	my $CURRENT_DATE = $gyear . sprintf("%02d", $gmon + 1) . sprintf("%02d", $gmday);

	my $cursize = 0;

	# Get a filehandle to the log file
	my $lfile = &get_log_file($logfile, $totalsize);
	if (!defined $lfile)
	{
		&logmsg('ERROR', "cannot read file $logfile, no handle.");
		return;
	}

	$pipe->writer() if (defined $pipe);

	if ($logfile ne '-')
	{
		if ($progress && ($getout != 1))
		{
			if (!$tmpoutfile || not defined $pipe)
			{
				print STDERR &progress_bar(
					$cursize, $stop_offset || $totalsize, 25, '=',
					($overall_stat{'queries_number'} + $pgb_overall_stat{'queries_number'}),
					($overall_stat{'errors_number'}+$pgb_overall_stat{'errors_number'}),
					$fmt
				);
			}
			else
			{
				$pipe->print("$cursize " .
					($overall_stat{'queries_number'} + $pgb_overall_stat{'queries_number'} - $old_queries_count) .
					" " .
					($overall_stat{'errors_number'}  + $pgb_overall_stat{'errors_number'} - $old_errors_count) .
					" $fmt\n");
			}
		}
		if (!$totalsize && $tmpoutfile)
		{
			&dump_as_binary($tmpoutfile);
			$tmpoutfile->close();
		}
	}

	# Reset the start position if file is smaller that the current start offset
	if ($totalsize > -1 && $start_offset > $totalsize)
	{
		&logmsg('DEBUG', "Starting offset $start_offset is greater than total size $totalsize for file $logfile");
		&logmsg('DEBUG', "Reverting start offset $start_offset to 0 for file $logfile, stoppping offset is " . ($stop_offset || $totalsize));
		$start_offset = 0 ;
	}

	# Check if the first date in the log are after the last date saved
	if (($logfile ne '-') && ($fmt ne 'binary') && ($fmt ne 'csv') && !$http_download)
	{
		if ($start_offset && !$chunk_pos) {
			my ($retcode, $msg) = check_file_changed($logfile, $file_size{$logfile}, $fmt, ($fmt =~ /pgbouncer/) ? $pgb_saved_last_line{datetime} : $saved_last_line{datetime}, $start_offset, 0);
			if ($retcode != 1)
			{
				&logmsg('DEBUG', "This file should be parsed from the beginning: $logfile, $msg");
				&logmsg('DEBUG', "Reverting start offset $start_offset to 0 for file $logfile, stopping offset is " . ($stop_offset || $totalsize));
				$start_offset = 0;
			}
			$cursize = $start_offset;
		}
	}
	else
	{
		$start_offset = 0;
		$stop_offset = 0;
	}

	# Set some boolean to gain speed
	my $is_json_log = 0;
	$is_json_log = 1 if ($fmt =~ /jsonlog/);
	my $is_syslog = 0;
	$is_syslog = 1 if ($fmt =~ /syslog|logplex/);

	if ($stop_offset > 0)
	{
		$totalsize = $stop_offset - $start_offset;
	}

	my $current_offset = $start_offset || 0;

	if (!$remote_host)
	{
		&logmsg('DEBUG', "Starting reading file \"$logfile\"...");
	}
	else
	{
		&logmsg('DEBUG', "Starting reading file \"$remote_host:$logfile\"...");
	}

	# Parse pgbouncer logfile
	if ($fmt =~ /pgbouncer/)
	{
		my $cur_pid = '';
		my @matches = ();
		my $has_exclusion = 0;
		if ($#exclude_line >= 0)
		{
			$has_exclusion = 1;
		}
		&logmsg('DEBUG', "Start parsing pgbouncer log at offset $start_offset of " .
			( ($logfile ne '-') ? " file $logfile" : "stdin" ) . " to " .
			($stop_offset || ( ($totalsize > 0) ? $totalsize : 'end' ) ));
		if ($start_offset)
		{
			# Move to the starting offset position in file
			$lfile->seek($start_offset, 0);
		}

		# pgbouncer reports are forced in the postgres report.
		# There is no per database pgbouncer statitiscs collected
		my $curdb = set_current_db();

		while (my $line = <$lfile>)
		{
			# We received a signal
			last if ($terminate);

			# Get current size/offset in the log file
			$cursize += length($line) + (&get_eol_length() - 1);
			$current_offset += length($line) + (&get_eol_length() - 1);

			# Replace CR/LF by LF
			$line =~ s/\r//;

			# Start to exclude from parsing any desired lines
			if ($has_exclusion >= 0)
			{
				# Log line matches the excluded regex
				map { next if ($line =~ /$_/is); } @exclude_line;
			}

			chomp($line);
			$nlines++;
			next if (!$line);

			&update_progress_bar($tmpoutfile, $nlines, $stop_offset, $totalsize, \$cursize, \$old_queries_count, \$old_errors_count, $fmt);

			%prefix_vars = ();

			my $special_format = 0;
			@matches = ($line =~ $pgbouncer_log_parse1);
			if ($#matches == -1)
			{
				@matches = ($line =~ $pgbouncer_log_parse3);
				$special_format = 1 if ($#matches >= 0);
			}

			if ($#matches >= 0)
			{
				# Get all relevant fields extracted through the regexp
				if (!$special_format)
				{
					for (my $i = 0 ; $i <= $#pgb_prefix_parse1 ; $i++)
					{
						$prefix_vars{$pgb_prefix_parse1[$i]} = $matches[$i];
					}
				}
				else
				{
					for (my $i = 0 ; $i <= $#pgb_prefix_parse3 ; $i++)
					{
						$prefix_vars{$pgb_prefix_parse3[$i]} = $matches[$i];
					}
				}

				# Get detailled information from timestamp
				if (!$prefix_vars{'t_month'})
				{
					($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'},
						$prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = ($prefix_vars{'t_timestamp'} =~ $time_pattern);
					$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
				}
				else
				{
					# Standard syslog format does not have year information, months are
					# three letters and days are not always with 2 digits.
					if ($prefix_vars{'t_month'} !~ /\d/)
					{
						$prefix_vars{'t_year'}  = $gyear;
						$prefix_vars{'t_day'}   = sprintf("%02d", $prefix_vars{'t_day'});
						$prefix_vars{'t_month'} = $month_abbr{$prefix_vars{'t_month'}};
						# Take care of year overlapping
						if ("$prefix_vars{'t_year'}$prefix_vars{'t_month'}$prefix_vars{'t_day'}" > $CURRENT_DATE) {
							$prefix_vars{'t_year'} = substr($CURRENT_DATE, 0, 4) - 1;
						}
					}
					$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
					$prefix_vars{'t_timestamp'} =
					      "$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";
				}

				# Change log level for some relevant messages
				if ($prefix_vars{'t_loglevel'} !~ $main_error_regex)
				{
					$prefix_vars{'t_loglevel'} = is_pgbouncer_error($prefix_vars{'t_query'});
				}

				if ($prefix_vars{'t_session_id'} eq 'Stats')
				{
					$prefix_vars{'t_loglevel'} = 'STATS';
					$prefix_vars{'t_session_id'} = '';
					$prefix_vars{'t_query'} = 'Stats: ' . $prefix_vars{'t_query'};
				}

				# Skip unwanted lines
				my $res = &skip_unwanted_line();
				next if ($res == 1);
				if ($res == -1)
				{
					&update_progress_bar($tmpoutfile, $nlines, $stop_offset, $totalsize, \$cursize, \$old_queries_count, \$old_errors_count, $fmt);
					$getout = 2;
					last;
				}

				# Jump to the last line parsed if required
				next if (($incremental || $last_parsed) && !&check_incremental_position($fmt, $prefix_vars{'t_timestamp'}, $line));

				# Store the current timestamp of the log line
				&store_current_timestamp($prefix_vars{'t_timestamp'}, $prefix_vars{'t_pid'});

				# Override timestamp when we have to adjust datetime to the log timezone
				if ($log_timezone)
				{
					($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = change_timezone($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'});
					$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
					$prefix_vars{'t_timestamp'} =
						"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";
				}

				# Extract other information from the line
				@matches = ($line =~ $pgbouncer_log_parse2);
				if ($#matches >= 0)
				{
					for (my $i = 0 ; $i <= $#pgb_prefix_parse2 ; $i++)
					{
						$prefix_vars{$pgb_prefix_parse2[$i]} = $matches[$i];
					}
					$prefix_vars{'t_client'} = _gethostbyaddr($prefix_vars{'t_client'}) if ($dns_resolv && $prefix_vars{'t_client'});
				}
				else
				{
					# pgBouncer Statistics appear each minute in the log
					if ($prefix_vars{'t_query'} =~ /(\d+) req\/s, in (\d+) b\/s, out (\d+) b\/s,query (\d+) us, wait time (\d+) us/)
					{
						$prefix_vars{'t_loglevel'} = 'STATS';
						$prefix_vars{'t_req/s'} = $1;
						$prefix_vars{'t_inbytes/s'} = $2;
						$prefix_vars{'t_outbytes/s'} = $3;
						$prefix_vars{'t_avgduration'} = $4;
						$prefix_vars{'t_avgwaiting'} = $5;
					}
					elsif ($prefix_vars{'t_query'} =~ /(\d+) xacts\/s, (\d+) queries\/s, in (\d+) B\/s, out (\d+) B\/s, xact (\d+) us, query (\d+) us, wait time (\d+) us/)
					{
						$prefix_vars{'t_loglevel'} = 'STATS';
						$prefix_vars{'t_xact/s'} = $1;
						$prefix_vars{'t_req/s'} = $2;
						$prefix_vars{'t_inbytes/s'} = $3;
						$prefix_vars{'t_outbytes/s'} = $4;
						$prefix_vars{'t_avgtxduration'} = $5;
						$prefix_vars{'t_avgduration'} = $6;
						$prefix_vars{'t_avgwaiting'} = $7;
					}
					# pgbouncer 1.21
					elsif ($prefix_vars{'t_query'} =~ /(\d+) xacts\/s, (\d+) queries\/s, (\d+) client parses\/s, (\d+) server parses\/s, (\d+) binds\/s, in (\d+) B\/s, out (\d+) B\/s, xact (\d+) us, query (\d+) us, wait (\d+) us/)
					{
						$prefix_vars{'t_loglevel'} = 'STATS';
						$prefix_vars{'t_xact/s'} = $1;
						$prefix_vars{'t_req/s'} = $2;
						$prefix_vars{'t_client_parses/s'} = $3;
						$prefix_vars{'t_server_parses/s'} = $4;
						$prefix_vars{'t_binds/s'} = $5;
						$prefix_vars{'t_inbytes/s'} = $6;
						$prefix_vars{'t_outbytes/s'} = $7;
						$prefix_vars{'t_avgtxduration'} = $8;
						$prefix_vars{'t_avgduration'} = $9;
						$prefix_vars{'t_avgwaiting'} = $10;
					}
				}

				# Check if the log line should be excluded from the report
				if (&validate_log_line($prefix_vars{'t_pid'}))
				{
					$prefix_vars{'t_host'} = 'stderr'; # this unused variable is used to store format information when log format is not syslog

					# Process the log line
					&parse_pgbouncer($fmt);
				}

			}
			else
			{
				# unknown format
				&logmsg('DEBUG', "Unknown pgbouncer line format: $line");
			}

			last if (($stop_offset > 0) && ($current_offset >= $stop_offset));
		}
		if ($last_parsed) {
			$pgb_last_line{current_pos} = $current_offset;
		}
	}
	# Parse PostgreSQL log file with CSV format
	elsif ($fmt eq 'csv')
	{
		if ($queue_size > 1 || $job_per_file > 1) {
			&logmsg('WARNING', "parallel processing is disabled with csv format.");
		}

		require Text::CSV_XS;

		my $csv = Text::CSV_XS->new(
			{
				binary => 1,
				eol => $/,
				sep_char => $csv_sep_char,
				allow_loose_quotes => 1,
			}
		);

		# Parse csvlog lines
		CSVLOOP: while (!$csv->eof())
		{
			# CSV columns information:
			# ------------------------
			# timestamp with milliseconds
			# username
			# database name
			# Process id
			# Remote host and port
			# session id
			# Line number
			# PS display
			# session start timestamp
			# Virtual transaction id
			# Transaction id
			# Error severity
			# SQL state code
			# errmessage
			# errdetail or errdetail_log
			# errhint
			# internal query
			# internal pos
			# errcontext
			# user query
			# file error location
			# application name
			# backend type
			# leader PID
			# query id

			while (my $row = $csv->getline($lfile))
			{
				$row =~ s/\r//;

				# We received a signal
				last CSVLOOP if ($terminate);

				# Number of columns in csvlog (21 before 9.0, 22 before 13.0, 25 in 14.0)
				next if ( ($#{$row} < 21) && ($#{$row} > 24) );

				# Set progress statistics
				$cursize += length(join(',', @$row));
				$nlines++;
				&update_progress_bar($tmpoutfile, $nlines, $stop_offset, $totalsize, \$cursize, \$old_queries_count, \$old_errors_count, $fmt);

				next if ( ($row->[11] !~ $parse_regex)  || ($row->[11] eq 'LOCATION'));

				# Extract the date
				if ($row->[0] =~ m/^(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)\.(\d+)/)
				{
					$prefix_vars{'t_year'} = $1;
					$prefix_vars{'t_month'} = $2;
					$prefix_vars{'t_day'} = $3;
					$prefix_vars{'t_hour'} = $4;
					$prefix_vars{'t_min'} = $5;
					$prefix_vars{'t_sec'} = $6;
					my $milli = $7 || 0;
					$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
					$prefix_vars{'t_timestamp'} =
						"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";

					# Remove newline characters from queries but not explain plan
					if (!grep(/Query Text:/, @$row))
					{
						for (my $i = 0; $i <= $#$row; $i++) {
							$row->[$i] =~ s/[\r\n]+/ /gs;
						}
					}

					# Skip unwanted lines
					my $res = &skip_unwanted_line();
					next if ($res == 1);
					if ($res == -1)
					{
						&update_progress_bar($tmpoutfile, $nlines, $stop_offset, $totalsize, \$cursize, \$old_queries_count, \$old_errors_count, $fmt);
						$getout = 2;
						last CSVLOOP;
					}

					# Jump to the last line parsed if required
					next if (($incremental || $last_parsed) && !&check_incremental_position($fmt, $prefix_vars{'t_timestamp'}, join(',', @$row)));

					# Set query parameters as global variables
					$prefix_vars{'t_dbuser'}  = $row->[1] || '';
					$prefix_vars{'t_dbname'}  = $row->[2] || '';
					$prefix_vars{'t_appname'} = $row->[22] || '';
					$prefix_vars{'t_appname'} =~ s/[<>]/'/g;
					$prefix_vars{'t_client'}  = $row->[4] || '';
					$prefix_vars{'t_client'}  =~ s/:.*//;
					$prefix_vars{'t_client'} = _gethostbyaddr($prefix_vars{'t_client'}) if ($dns_resolv);
					$prefix_vars{'t_host'}    = 'csv'; # this unused variable is used to store format information when log format is not syslog
					$prefix_vars{'t_pid'}     = $row->[3];
					$prefix_vars{'t_session_line'} = $row->[5];
					$prefix_vars{'t_session_line'} =~ s/\..*//;
					$prefix_vars{'t_loglevel'} = $row->[11];
					$prefix_vars{'t_query'}    = $row->[13];
					# Set ERROR additional information
					$prefix_vars{'t_detail'} = $row->[14];
					$prefix_vars{'t_hint'} = $row->[15];
					$prefix_vars{'t_context'} = $row->[18];
					$prefix_vars{'t_statement'} = $row->[19];
					$prefix_vars{'t_queryid'} = $row->[24] if ($#{$row} >= 24);

					# Store the current timestamp of the log line
					&store_current_timestamp($prefix_vars{'t_timestamp'}, $prefix_vars{'t_pid'}, $prefix_vars{'t_dbname'});

					# Update current timestamp with the timezone wanted
					if ($log_timezone)
					{
						($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = change_timezone($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'});
						$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
						$prefix_vars{'t_timestamp'} =
							"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";
					}

					# Check if the log line should be excluded from the report
					if (&validate_log_line($prefix_vars{'t_pid'}))
					{
						# Parse the query now
						&parse_query($fmt);

						# The information can be saved immediately with csvlog
						if (exists $cur_info{$prefix_vars{'t_pid'}})
						{
							&store_queries($prefix_vars{'t_pid'});
							delete $cur_info{$prefix_vars{'t_pid'}};
						}
					}
				}
			}

			if (!$csv->eof())
			{
				warn "WARNING: cannot use CSV on $logfile, " . $csv->error_diag() . " at line " . ($nlines+1), "\n";
				print STDERR "DETAIL: " . $csv->error_input(), "\n" if ($csv->error_input());
				print STDERR "reset CSV parser\n";
				$csv->SetDiag(0);
			}
			else
			{
				$cursize = $totalsize;
			}
		}
	}
	elsif ($fmt eq 'binary')
	{
		return $getout if (!load_stats($lfile));
		$pipe->print("$totalsize 0 0 $fmt\n") if (defined $pipe);
	}
	# Format is not CSV and in incremental mode we are not at end of the file
	else
	{
		my $cur_pid = '';
		my @matches = ();
		my $goon = ($incremental) ? 1 : 0;
		my $has_exclusion = 0;
		if ($#exclude_line >= 0) {
			$has_exclusion = 1;
		}
		&logmsg('DEBUG', "Start parsing postgresql log at offset $start_offset of file \"$logfile\" to " . ($stop_offset || $totalsize));
		if (!$journalctl_cmd && !$log_command)
		{
			if ($start_offset) {
				# Move to the starting offset position in file
				$lfile->seek($start_offset, 0);
			} else {
				$lfile->seek(0, 0);
			}
		}
		while (my $line = <$lfile>)
		{
			# We received a signal
			last if ($terminate);

			# Get current size/offset in the log file
			$cursize += length($line) + (&get_eol_length() - 1);
			$current_offset += length($line) + (&get_eol_length() - 1);

			# Skip INFO line generated by other software
			next if ($line =~ /\bINFO: /);

			# Replace CR/LF by LF
			$line =~ s/\r//;

			# Start to exclude from parsing any desired lines
			if ($has_exclusion >= 0)
			{
				# Log line matches the excluded regex
				map { next if ($line =~ /$_/is); } @exclude_line;
			}

			chomp($line);
			$nlines++;
			next if (!$line);

			&update_progress_bar($tmpoutfile, $nlines, $stop_offset, $totalsize, \$cursize, \$old_queries_count, \$old_errors_count, $fmt);

			%prefix_vars = ();

			# Parse jsonlog lines
			if ($is_json_log)
			{
				%prefix_vars = parse_jsonlog_input($line);

				if (exists $prefix_vars{'t_textPayload'})
				{
					@matches = ($prefix_vars{'t_textPayload'} =~ $compiled_prefix);
					my $q_match = 0;
					if ($#matches < 0 && $q_prefix)
					{
						@matches = ($prefix_vars{'t_textPayload'} =~ $q_prefix);
						$q_match = 1;
					}
					if ($#matches >= 0)
					{
						if (!$q_match)
						{
							for (my $i = 0 ; $i <= $#prefix_params ; $i++) {
								$prefix_vars{$prefix_params[$i]} = $matches[$i];
							}
						}
						else
						{
							for (my $i = 0 ; $i <= $#prefix_q_params ; $i++) {
								$prefix_vars{$prefix_q_params[$i]} = $matches[$i];
							}
						}
					}
					delete $prefix_vars{'t_textPayload'};
					$prefix_vars{'t_query'} = unescape_jsonlog($prefix_vars{'t_query'});

					$prefix_vars{'t_pid'} = $prefix_vars{'t_session_id'} if ($use_sessionid_as_pid);

					# Skip location information
					next if ($prefix_vars{'t_loglevel'} eq 'LOCATION');

					if (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_mtimestamp'}) {
						$prefix_vars{'t_timestamp'} = $prefix_vars{'t_mtimestamp'};
					} elsif (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_session_timestamp'}) {
						$prefix_vars{'t_timestamp'} = $prefix_vars{'t_session_timestamp'};
					}
					elsif (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_epoch'})
					{
						$prefix_vars{'t_timestamp'} = strftime("%Y-%m-%d %H:%M:%S", CORE::localtime($prefix_vars{'t_epoch'}));
						if ($prefix_vars{'t_epoch'} =~ /^\d{10}(\.\d{3})$/) {
							$prefix_vars{'t_timestamp'} .= $1;
						}
					}
					elsif ($prefix_vars{'t_timestamp'} =~ /^\d{10}(\.\d{3})$/)
					{
						my $ms = $1;
						$prefix_vars{'t_epoch'} = $prefix_vars{'t_timestamp'};
						$prefix_vars{'t_timestamp'} = strftime("%Y-%m-%d %H:%M:%S", CORE::localtime($prefix_vars{'t_timestamp'}));
						 $prefix_vars{'t_timestamp'} .= $ms;
					}

					if ($prefix_vars{'t_timestamp'})
					{
						($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'},
							$prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = ($prefix_vars{'t_timestamp'} =~ $time_pattern);
					}
					elsif ($prefix_vars{'t_year'})
					{
						$prefix_vars{'t_timestamp'} = "$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
					}
					$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
					# Skip this line if there is no timestamp
					next if (!$prefix_vars{'t_timestamp'} || $prefix_vars{'t_timestamp'} eq '-- ::');

					if ($prefix_vars{'t_hostport'} && !$prefix_vars{'t_client'})
					{
						$prefix_vars{'t_client'} = $prefix_vars{'t_hostport'};
						# Remove the port part
						$prefix_vars{'t_client'} =~ s/\(.*//;
					}
				}

				$cur_pid = $prefix_vars{'t_pid'} if ($prefix_vars{'t_pid'});

				$prefix_vars{'t_query'} =~ s/^\\t//;
				# Collect orphaned lines of multiline queries
				if (!$prefix_vars{'t_loglevel'} && $cur_pid)
				{
					# Some log line may be written by applications
					next if ($line =~ /\bLOG:  /);

					# Parse orphan lines to append information to the right place
					&parse_orphan_line($cur_pid, $prefix_vars{'t_query'});
				}
				elsif ($cur_pid)
				{
					# Skip unwanted lines
					my $res = &skip_unwanted_line();
					next if ($res == 1);
					if ($res == -1)
					{
						&update_progress_bar($tmpoutfile, $nlines, $stop_offset, $totalsize, \$cursize, \$old_queries_count, \$old_errors_count, $fmt);
						$getout = 2;
						last;
					}

					# Jump to the last line parsed if required
					next if (($incremental || $last_parsed) && !&check_incremental_position($fmt, $prefix_vars{'t_timestamp'}, $line));

					# We have reach previous incremental position (or we not in increment mode)
					$goon = 1;

					# Store the current timestamp of the log line
					&store_current_timestamp($prefix_vars{'t_timestamp'}, $prefix_vars{'t_pid'}, $prefix_vars{'t_dbname'});

					# Update current timestamp with the timezone wanted
					if ($log_timezone)
					{
						($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = change_timezone($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'});
						$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
						$prefix_vars{'t_timestamp'} =
							"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";
					}

					# Check if the log line should be excluded from the report
					if (&validate_log_line($prefix_vars{'t_pid'}))
					{
						# The information can be saved when we are switching to a new main message
						if ($cur_pid && exists $cur_info{$cur_pid} && ($prefix_vars{'t_loglevel'} =~ /^(LOG|ERROR|FATAL|PANIC|WARNING)$/))
						{
							&store_queries($cur_pid);
							delete $cur_info{$cur_pid};
						}
						# Parse the query now
						&parse_query($fmt);
					}
				}
				elsif ($fmt ne 'jsonlog' && $line !~ /textpayload/i)
				{
					&logmsg('DEBUG', "Unknown $fmt line format: $line");
				}
			}
			# Parse syslog lines
			elsif ($is_syslog)
			{
				@matches = ($line =~ $compiled_prefix);

				my $q_match = 0;
				if ($#matches < 0 && $q_prefix)
				{
					@matches = ($line =~ $q_prefix);
					$q_match = 1;
				}
				if ($#matches >= 0)
				{
					if (!$q_match)
					{
						for (my $i = 0 ; $i <= $#prefix_params ; $i++) {
							$prefix_vars{$prefix_params[$i]} = $matches[$i];
						}
					}
					else
					{
						for (my $i = 0 ; $i <= $#prefix_q_params ; $i++) {
							$prefix_vars{$prefix_q_params[$i]} = $matches[$i];
						}
					}

					# skip non postgresql lines
					next if (exists $prefix_vars{'t_ident'} && $prefix_vars{'t_ident'} ne $ident);

					# Skip location information
					next if ($prefix_vars{'t_loglevel'} eq 'LOCATION');

					# Standard syslog format does not have year information, months are
					# three letters and days are not always with 2 digits.
					if ($prefix_vars{'t_month'} !~ /\d/)
					{
						$prefix_vars{'t_year'}  = $gyear;
						$prefix_vars{'t_day'}   = sprintf("%02d", $prefix_vars{'t_day'});
						$prefix_vars{'t_month'} = $month_abbr{$prefix_vars{'t_month'}};
						# Take care of year overlapping
						if ("$prefix_vars{'t_year'}$prefix_vars{'t_month'}$prefix_vars{'t_day'}" > $CURRENT_DATE) {
							$prefix_vars{'t_year'} = substr($CURRENT_DATE, 0, 4) - 1;
						}
					}
					$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
					$prefix_vars{'t_timestamp'} =
						"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";

					if ($prefix_vars{'t_hostport'} && !$prefix_vars{'t_client'})
					{
						$prefix_vars{'t_client'} = $prefix_vars{'t_hostport'};
						# Remove the port part
						$prefix_vars{'t_client'} =~ s/\(.*//;
					}

					# Skip unwanted lines
					my $res = &skip_unwanted_line();
					next if ($res == 1);
					if ($res == -1)
					{
						&update_progress_bar($tmpoutfile, $nlines, $stop_offset, $totalsize, \$cursize, \$old_queries_count, \$old_errors_count, $fmt);
						$getout = 2;
						last;
					}

					# Jump to the last line parsed if required
					next if (($incremental || $last_parsed) && !&check_incremental_position($fmt, $prefix_vars{'t_timestamp'}, $line));
					# We have reach previous incremental position (or we not in increment mode)
					$goon = 1;

					$prefix_vars{'t_client'} = _gethostbyaddr($prefix_vars{'t_client'}) if ($dns_resolv);

					# Store the current timestamp of the log line
					&store_current_timestamp($prefix_vars{'t_timestamp'}, $prefix_vars{'t_pid'}, $prefix_vars{'t_dbname'});

					# Update current timestamp with the timezone wanted
					if ($log_timezone)
					{
						($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = change_timezone($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'});
						$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
						$prefix_vars{'t_timestamp'} =
							"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";
					}

					# Extract information from log line prefix
					if (!$log_line_prefix) {
						&parse_log_prefix($prefix_vars{'t_logprefix'});
					}

					# Check if the log line should be excluded from the report
					if (&validate_log_line($prefix_vars{'t_pid'}))
					{
						# The information can be saved when we are switching to a new main message
						if ($cur_pid && exists $cur_info{$cur_pid} && ($prefix_vars{'t_loglevel'} =~ /^(LOG|ERROR|FATAL|PANIC|WARNING)$/))
						{
							&store_queries($cur_pid);
							delete $cur_info{$cur_pid} if (!$log_duration || ($cur_info{$cur_pid}{duration} ne '' && $cur_info{$cur_pid}{query} ne ''));
						}

						# Process the log line
						&parse_query($fmt);

						$cur_pid = $prefix_vars{'t_pid'};
					}
					else
					{
						$cur_pid = '';
					}

				}
				elsif ($goon && ($line =~ $other_syslog_line))
				{
					$cur_pid = $8;
					my $t_query = $10;
					if ($fmt eq 'logplex' && not exists $cur_info{$cur_pid}{cur_db}) {
						$cur_info{$cur_pid}{cur_db} = $9;
					}
					$t_query =~ s/#011/\t/g;
					next if ($t_query eq "\t");

					# Some log line may be written by applications
					next if ($t_query =~ /\bLOG:  /);

					# Parse orphan lines to append information to the right place
					&parse_orphan_line($cur_pid, $t_query);

				}
				# Collect orphaned lines of multiline queries
				elsif ($cur_pid)
				{
					if ($line =~ $other_syslog_line)
					{
						$cur_pid = $8;
						my $t_query = $10;
						if ($fmt eq 'logplex' && not exists $cur_info{$cur_pid}{cur_db}) {
							$cur_info{$cur_pid}{cur_db} = $9;
						}
						$t_query =~ s/#011/\t/g;
						next if ($t_query eq "\t");

						# Some log line may be written by applications
						next if ($t_query =~ /\bLOG:  /);

						# Parse orphan lines to append information to the right place
						&parse_orphan_line($cur_pid, $t_query);
					}
					else
					{
						# Some log line may be written by applications
						next if ($line =~ /\bLOG:  /);

						# Parse orphan lines to append information to the right place
						&parse_orphan_line($cur_pid, $line);
					}
				}
				else
				{
					&logmsg('DEBUG', "Unknown $fmt line format: $line");
				}

			}
			elsif ($fmt eq 'stderr' or $fmt eq 'rds' or $fmt eq 'redshift')
			{
				@matches = ($line =~ $compiled_prefix);

				my $q_match = 0;
				if ($#matches < 0 && $q_prefix) {
					@matches = ($line =~ $q_prefix);
					$q_match = 1;
				}

				if ($#matches >= 0)
				{
					if (!$q_match)
					{
						for (my $i = 0 ; $i <= $#prefix_params ; $i++) {
							$prefix_vars{$prefix_params[$i]} = $matches[$i];
						}
					}
					else
					{
						for (my $i = 0 ; $i <= $#prefix_q_params ; $i++) {
							$prefix_vars{$prefix_q_params[$i]} = $matches[$i];
						}
					}
					$prefix_vars{'t_client'} =~ s/\(.*// if ($fmt eq 'rds');
					$prefix_vars{'t_pid'} = $prefix_vars{'t_session_id'} if ($use_sessionid_as_pid);

					# Skip location information
					next if ($prefix_vars{'t_loglevel'} eq 'LOCATION');

					if (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_mtimestamp'}) {
						$prefix_vars{'t_timestamp'} = $prefix_vars{'t_mtimestamp'};
					} elsif (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_session_timestamp'}) {
						$prefix_vars{'t_timestamp'} = $prefix_vars{'t_session_timestamp'};
					}
					elsif (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_epoch'})
					{
						$prefix_vars{'t_timestamp'} = strftime("%Y-%m-%d %H:%M:%S", CORE::localtime($prefix_vars{'t_epoch'}));
						if ($prefix_vars{'t_epoch'} =~ /^\d{10}(\.\d{3})$/) {
							$prefix_vars{'t_timestamp'} .= $1;
						}
					}
					elsif ($prefix_vars{'t_timestamp'} =~ /^\d{10}(\.\d{3})$/)
					{
						my $ms = $1;
						$prefix_vars{'t_epoch'} = $prefix_vars{'t_timestamp'};
						$prefix_vars{'t_timestamp'} = strftime("%Y-%m-%d %H:%M:%S", CORE::localtime($prefix_vars{'t_timestamp'}));
						 $prefix_vars{'t_timestamp'} .= $ms;
					}

					if ($prefix_vars{'t_timestamp'})
					{
						($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'},
							$prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = ($prefix_vars{'t_timestamp'} =~ $time_pattern);
					}
					elsif ($prefix_vars{'t_year'})
					{
						$prefix_vars{'t_timestamp'} = "$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
					}
					$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
					# Skip this line if there is no timestamp
					next if (!$prefix_vars{'t_timestamp'} || $prefix_vars{'t_timestamp'} eq '-- ::');

					if ($prefix_vars{'t_hostport'} && !$prefix_vars{'t_client'})
					{
						$prefix_vars{'t_client'} = $prefix_vars{'t_hostport'};
						# Remove the port part
						$prefix_vars{'t_client'} =~ s/\(.*//;
					}

					$force_sample = 1 if ($fmt eq 'redshift'
									&& $prefix_vars{'t_loglevel'} eq 'LOG'
									&& $prefix_vars{'t_client'} !~ /duration: /);

					# Skip unwanted lines
					my $res = &skip_unwanted_line();
					next if ($res == 1);
					if ($res == -1)
					{
						&update_progress_bar($tmpoutfile, $nlines, $stop_offset, $totalsize, \$cursize, \$old_queries_count, \$old_errors_count, $fmt);
						$getout = 2;
						last;
					}
					# Jump to the last line parsed if required
					next if (($incremental || $last_parsed) && !&check_incremental_position($fmt, $prefix_vars{'t_timestamp'}, $line));

					# We have reach previous incremental position (or we not in increment mode)
					$goon = 1;

					$prefix_vars{'t_client'} = _gethostbyaddr($prefix_vars{'t_client'}) if ($dns_resolv);

					# Store the current timestamp of the log line
					&store_current_timestamp($prefix_vars{'t_timestamp'}, $prefix_vars{'t_pid'}, $prefix_vars{'t_dbname'});

					# Update current timestamp with the timezone wanted
					if ($log_timezone)
					{
						($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = change_timezone($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'}, $prefix_vars{'t_min'}, $prefix_vars{'t_sec'});
						$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
						$prefix_vars{'t_timestamp'} =
							"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";
					}

					# Extract information from log line prefix
					if (!$log_line_prefix) {
						&parse_log_prefix($prefix_vars{'t_logprefix'});
					}
					# Check if the log line should be excluded from the report
					if (&validate_log_line($prefix_vars{'t_pid'}))
					{
						# this unused variable is used to store format information
						# when log format is not syslog
						$prefix_vars{'t_host'} = 'stderr';

						# The information from previous loop can be saved
						# when we are switching to a new main message
						if ($cur_pid && exists $cur_info{$cur_pid} && $prefix_vars{'t_loglevel'} =~ /^(LOG|ERROR|FATAL|PANIC|WARNING)$/) {
							&store_queries($cur_pid);
							delete $cur_info{$cur_pid} if (!$log_duration || ($cur_info{$cur_pid}{duration} ne '' && $cur_info{$cur_pid}{query} ne ''));
						}

						# Process the log line
						&parse_query($fmt);

						$cur_pid = $prefix_vars{'t_pid'};
					}
					else
					{
						$cur_pid = '';
					}

				}
				# Collect additional query information
				elsif ($goon && $cur_pid)
				{
					# Some log line may be written by applications
					next if ($line =~ /\bLOG:  /);

					# Parse orphan lines to append information to the right place
					&parse_orphan_line($cur_pid, $line);
				}
				elsif ($goon)
				{

					# unknown format
					&logmsg('DEBUG', "Unknown $fmt log line format: $line");
				}
			}
			last if (($stop_offset > 0) && ($current_offset >= $stop_offset));
		}

		if ($goon && $last_parsed)
		{
			&logmsg('DEBUG', "setting current position in log to $current_offset");
			$last_line{current_pos} = $current_offset;
		}
	}
	close $lfile;

	# Inform the parent that it should stop parsing other files
	if ($terminate)
	{
		if ($^O !~ /MSWin32|dos/i) {
			kill('USR2', $parent_pid);
		} else {
			kill('TERM', $parent_pid);
		}
		return $terminate;
	}

	# Get stats from all pending temporary storage
	foreach my $pid (sort {$cur_info{$a}{date} <=> $cur_info{$b}{date}} keys %cur_info)
	{
		# Stores last query information
		&store_queries($pid, 1);
	}

	# Stores last temporary files and lock information
	foreach my $pid (keys %cur_temp_info) {
		&store_temporary_and_lock_infos($pid);
	}

	# Stores last cancelled queries information
	foreach my $pid (keys %cur_cancel_info) {
		&store_temporary_and_lock_infos($pid);
	}

	# Stores last temporary files and lock information
	foreach my $pid (keys %cur_lock_info) {
		&store_temporary_and_lock_infos($pid);
	}

	if ($progress && ($getout != 1))
	{

		# Bzip2 and remote download compressed files has an
		# estimated size. Force 100% at end of log parsing
		if (($http_download && $logfile =~ $compress_extensions )
			|| $logfile =~ /\.bz2$/i)
		{
			$cursize = $totalsize;
		}

		if (!$tmpoutfile || not defined $pipe)
		{
			print STDERR &progress_bar($cursize, $stop_offset || $totalsize, 25, '=',
				($overall_stat{'queries_number'} + $pgb_overall_stat{'queries_number'}),
				($overall_stat{'errors_number'} + $pgb_overall_stat{'errors_number'}),
				$fmt
			);
			print STDERR "\n";
		}
		else
		{
			$pipe->print("$cursize " .
				($overall_stat{'queries_number'} + $pgb_overall_stat{'queries_number'} - $old_queries_count) .
				" " .
				($overall_stat{'errors_number'} + $pgb_overall_stat{'errors_number'} - $old_errors_count) .
				" $fmt\n");
		}
	}

	# Case where we build reports from binary only with no new log entries.
	if ($incremental && $html_outdir && !$outdir)
	{
		if ($logfile =~ /\/(\d+)\/(\d+)\/(\d+)\/[^\/]+\.bin$/)
		{
			$last_line{datetime} = "$1-$2-$3";
		}
	}

	%cur_info = ();
	# In incremental mode data are saved to disk per day
	if ($incremental && ($last_line{datetime} || (($fmt =~ /pgbouncer/) && $pgb_last_line{datetime}))) {
		$incr_date = ($fmt =~ /pgbouncer/) ? $pgb_last_line{datetime} : $last_line{datetime};
		$incr_date =~ s/\s.*$//;
		# set path and create subdirectories
		if ($incr_date =~ /^(\d+)-(\d+)-(\d+)/) {
			mkdir("$outdir/$1") if (!-d "$outdir/$1");
			mkdir("$outdir/$1/$2") if (!-d "$outdir/$1/$2");
			mkdir("$outdir/$1/$2/$3") if (!-d "$outdir/$1/$2/$3");
		} else {
			&logmsg('ERROR', "invalid incremental date: $incr_date, can not create subdirectories.");
		}
		my $bpath = $incr_date;
		$bpath =~ s/\-/\//g;
		# Mark the directory as needing index update
		if (open(my $out, '>>', "$last_parsed.tmp")) {
			flock($out, 2) || return $getout;
			print $out "$incr_date\n";
			close($out);
		} else {
			&logmsg('ERROR', "can't save last parsed line into $last_parsed.tmp, $!");
		}

		# Save binary data
		if ($outdir)
		{
			my $filenum = $$;
			$filenum++ while (-e "$outdir/$bpath/$incr_date-$filenum.bin");
			my $fhb = new IO::File ">$outdir/$bpath/$incr_date-$filenum.bin";
			if (not defined $fhb) {
				localdie("FATAL: can't write to $outdir/$bpath/$incr_date-$filenum.bin, $!\n");
			}
			&dump_as_binary($fhb);
			$fhb->close;
		}

	}
	elsif (fileno($tmpoutfile))
	{
		&dump_as_binary($tmpoutfile);
		$tmpoutfile->close();
	}

	# Save last line into temporary file
	if ($last_parsed && (scalar keys %last_line || scalar keys %pgb_last_line))
	{
		if (open(my $out, '>>', "$tmp_last_parsed"))
		{
			flock($out, 2) || return $getout;
			if ($fmt =~ /pgbouncer/)
			{
				$pgb_last_line{current_pos} ||= 0;
				&logmsg('DEBUG', "Saving pgbouncer last parsed line into $tmp_last_parsed ($pgb_last_line{datetime}\t$pgb_last_line{current_pos})");
				print $out "pgbouncer\t$pgb_last_line{datetime}\t$pgb_last_line{current_pos}\t$pgb_last_line{orig}\n";
			}
			else
			{
				$last_line{current_pos} ||= 0;
				&logmsg('DEBUG', "Saving last parsed line into $tmp_last_parsed ($last_line{datetime}\t$last_line{current_pos})");
				print $out "$last_line{datetime}\t$last_line{current_pos}\t$last_line{orig}\n";
			}
			close($out);
		} else {
			&logmsg('ERROR', "can't save last parsed line into $tmp_last_parsed, $!");
		}
	}

	# Inform the parent that it should stop parsing other files
	if ($getout) {
		if ($^O !~ /MSWin32|dos/i) {
			kill('USR2', $parent_pid);
		} else {
			kill('TERM', $parent_pid);
		}
	}

	# Write the list of database we have proceeded in this process
	if ($report_per_database)
	{
		if (open(my $out, '>>', "$tmp_dblist")) {
			flock($out, 2) || return $getout;
			print $out join(';', %{ $overall_stat{nlines} }), "\n";
			close($out);
		} else {
			&logmsg('ERROR', "can't save last parsed line into $tmp_dblist, $!");
		}
	}

	&init_stats_vars() if ($tmpoutfile);

	return $getout;
}

sub unescape_jsonlog
{
	my $str = shift;

	while ($str =~ s/([^\\])\\"/$1"/g) {};
	while ($str =~ s/([^\\])\\t/$1\t/g) {};
	while ($str =~ s/\\r\\n/\n/gs) {};
	while ($str =~ s/([^\\])\\r/$1\n/gs) {};
	while ($str =~ s/([^\\])\\n/$1\n/gs) {};

	return $str;
}

sub parse_jsonlog_input
{
	my $str = shift;


	# This is Azure json log input
	return parse_jsonazure_input($str) if ($str =~ /"record_application_name_s"/);

	# This is CloudNativePG json log input
	return parse_jsoncnpg_input($str) if ($str =~ /"logging_pod"/);

	my %infos = ();

	# json columns information from jsonlog extension:
	# -------------------------------------------------
	# timestamp with milliseconds
	# username
	# database name
	# Process id
	# Remote host and port
	# session id
	# Line number*
	# PS display *
	# session start timestamp *
	# Virtual transaction id
	# Transaction id
	# Error severity
	# SQL state code
	# errdetail or errdetail_log
	# errhint
	# internal query
	# internal pos *
	# errcontext
	# user query
	# file error location
	# application name
	# errmessage
	# backend type *
	# leader PID *
	# query id *
	#
	# (*) information not available for the moment

	# Extract the date
	if ($str =~ m/[\{,]"timestamp":\s*"(\d+)-(\d+)-(\d+).(\d+):(\d+):(\d+)/)
	{
		$infos{'t_year'} = $1;
		$infos{'t_month'} = $2;
		$infos{'t_day'} = $3;
		$infos{'t_hour'} = $4;
		$infos{'t_min'} = $5;
		$infos{'t_sec'} = $6;
		$infos{'t_timestamp'} = "$infos{'t_year'}-$infos{'t_month'}-$infos{'t_day'} $infos{'t_hour'}:$infos{'t_min'}:$infos{'t_sec'}";
    $infos{'t_time'} = "$infos{'t_hour'}:$infos{'t_min'}:$infos{'t_sec'}";
	}

	# Set query parameters as global variables
	if ($str =~ m/"user":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_dbuser'}  = $1;
	} elsif ($str =~ m/,user=([^\s]*) /) {
		$infos{'t_dbuser'}  = $1;
	}
	if ($str =~ m/"dbname":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_dbname'}  = $1;
	} elsif ($str =~ m/ db=([^,]*),/) {
		$infos{'t_dbname'}  = $1;
	}
	if ($str =~ m/"application_name":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_appname'} = $1;
	} elsif ($str =~ m/"project_id":\s*"([^"])"/) {
		$infos{'t_appname'} = $1;
	}
	if ($str =~ m/"remote_host":\s*"(.*?)"(?:,"|\})/)
	{
		$infos{'t_client'}  = $1;
		$infos{'t_client'}  =~ s/:.*//;
		$infos{'t_client'} = _gethostbyaddr($infos{'t_client'}) if ($dns_resolv);
	}
	$infos{'t_host'}    = 'jsonlog'; # this unused variable is used to store format information when log format is not syslog

	# Try to extract the pid information
	if ($str =~ m/"pid":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_pid'} = $1;
	} elsif ($str =~ m/"pid":\s*([0-9]+)/) {
		$infos{'t_pid'} = $1;
	} elsif ($str =~ m/"textPayload":\s*"\[(\d+)\]:/) {
		$infos{'t_pid'} = $1;
	} elsif ($str =~ m/"textPayload":\s*"(\d+-\d+-\d+[T\s]\d+:\d+:\d+\.\d+\s[^\s]*\s+\[(\d+)\]:.*)",(?:"timestamp":.*)?$/) {
		$infos{'t_pid'} = $2;
		$infos{'t_textPayload'} = $1;
	} elsif ($str =~ m/"textPayload":\s*"(.*)","timestamp":"/) {
		$infos{'t_query'} = unescape_jsonlog($1);
	}

	if ($str =~ m/"error_severity":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_loglevel'} = $1;
	} elsif ($str =~ m/user=[^\s]* ([^:]+):\s{1,2}(.*)","timestamp":"/) {
		$infos{'t_loglevel'} = $1;
		$infos{'t_query'} = unescape_jsonlog($2);
	}
	if ($str =~ m/"state_code":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_sqlstate'} = $1;
	}
	if ($str =~ m/"message":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_query'} = unescape_jsonlog($1);
	} elsif ($str =~ m/"statement":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_query'} = unescape_jsonlog($1);
	}

	# Set ERROR additional information
	if ($str =~ m/"(?:detail_log|detail)":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_detail'} = unescape_jsonlog($1);
	}
	if ($str =~ m/"hint":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_hint'} = unescape_jsonlog($1);
	}
	if ($str =~ m/"context":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_context'} = unescape_jsonlog($1);
	}
	if ($str =~ m/"(?:statement|internal_query)":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_statement'} = unescape_jsonlog($1);
	}

	# Backend type information
	if ($str =~ m/"backend_type":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_backend_type'} = $1;
	}

	return %infos;
}

sub parse_jsonazure_input
{
	my $str = shift;

	my %infos = ();

	# json columns information from Azure Log Analytics Workspaces
	# ------------------------------------------------------------
	# TableName
	# record_application_name_s
	# record_backend_type_s
	# record_command_tag_s
	# record_connection_from_s
	# record_context_s
	# record_database_name_s
	# record_detail_s
	# record_error_severity_s
	# record_hint_s
	# record_log_time_s
	# record_message_s
	# record_process_id_s
	# record_query_id_s
	# record_query_pos_s
	# record_query_s
	# record_session_id_s
	# record_session_line_num_s
	# record_session_start_time_s
	# record_sql_state_code_s
	# record_transaction_id_s
	# record_user_name_s
	# record_virtual_transaction_id_s

	# Extract the date
	if ($str =~ m/"record_log_time_s":\s*"(\d+)-(\d+)-(\d+).(\d+):(\d+):(\d+)/)
	{
		$infos{'t_year'} = $1;
		$infos{'t_month'} = $2;
		$infos{'t_day'} = $3;
		$infos{'t_hour'} = $4;
		$infos{'t_min'} = $5;
		$infos{'t_sec'} = $6;
		$infos{'t_timestamp'} = "$infos{'t_year'}-$infos{'t_month'}-$infos{'t_day'} $infos{'t_hour'}:$infos{'t_min'}:$infos{'t_sec'}";
    $infos{'t_time'} = "$infos{'t_hour'}:$infos{'t_min'}:$infos{'t_sec'}";
	}

	if ($str =~ m/"record_user_name_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_dbuser'}  = $1;
	}
	if ($str =~ m/"record_database_name_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_dbname'}  = $1;
	}
	if ($str =~ m/"record_application_name_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_appname'} = $1;
	}
	if ($str =~ m/"record_connection_from_s":\s*"(.*?)"(?:,\s*"|\})/)
	{
		$infos{'t_client'}  = $1;
		$infos{'t_client'}  =~ s/:.*//;
		$infos{'t_client'} = _gethostbyaddr($infos{'t_client'}) if ($dns_resolv && $infos{'t_client'} ne '[local]');
	}
	$infos{'t_host'}    = 'jsonlog'; # this unused variable is used to store format information when log format is not syslog

	if ($str =~ m/"record_process_id_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_pid'} = $1;
	}

	if ($str =~ m/"record_error_severity_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_loglevel'} = $1;
	}
	if ($str =~ m/"record_sql_state_code_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_sqlstate'} = $1;
	}
	if ($str =~ m/"record_query_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_query'} = unescape_jsonlog($1);
	}

	# Set ERROR additional information
	if ($str =~ m/"record_detail_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_detail'} = unescape_jsonlog($1);
	}
	if ($str =~ m/"record_hint_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_hint'} = unescape_jsonlog($1);
	}
	if ($str =~ m/"record_context_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_context'} = unescape_jsonlog($1);
	}

	# Backend type information
	if ($str =~ m/"record_backend_type_s":\s*"(.*?)"(?:,\s*"|\})/) {
		$infos{'t_backend_type'} = $1;
	}

	return %infos;
}

sub parse_jsoncnpg_input
{
	my $str = shift;

	my %infos = ();

	# json log line from CloudNativePG Operator:
	# -------------------------------------------------
	# {
	#   "level": "info",
	#   "ts": 1619781249.7188137,
	#   "logger": "postgres",
	#   "msg": "record",
	#   "record": {
	#     "log_time": "2021-04-30 11:14:09.718 UTC",
	#     "user_name": "",
	#     "database_name": "",
	#     "process_id": "25",
	#     "connection_from": "",
	#     "session_id": "608be681.19",
	#     "session_line_num": "1",
	#     "command_tag": "",
	#     "session_start_time": "2021-04-30 11:14:09 UTC",
	#     "virtual_transaction_id": "",
	#     "transaction_id": "0",
	#     "error_severity": "LOG",
	#     "sql_state_code": "00000",
	#     "message": "database system was interrupted; last known up at 2021-04-30 11:14:07 UTC",
	#     "detail": "",
	#     "hint": "",
	#     "internal_query": "",
	#     "internal_query_pos": "",
	#     "context": "",
	#     "query": "",
	#     "query_pos": "",
	#     "location": "",
	#     "application_name": "",
	#     "backend_type": "startup"
	#   },
	#   "logging_pod": "cluster-example-1",
	# }

	# Extract the date
	if ($str =~ m/[\{,]"log_time":\s*"(\d+)-(\d+)-(\d+).(\d+):(\d+):(\d+)/)
	{
		$infos{'t_year'} = $1;
		$infos{'t_month'} = $2;
		$infos{'t_day'} = $3;
		$infos{'t_hour'} = $4;
		$infos{'t_min'} = $5;
		$infos{'t_sec'} = $6;
		$infos{'t_timestamp'} = "$infos{'t_year'}-$infos{'t_month'}-$infos{'t_day'} $infos{'t_hour'}:$infos{'t_min'}:$infos{'t_sec'}";
    $infos{'t_time'} = "$infos{'t_hour'}:$infos{'t_min'}:$infos{'t_sec'}";
	}

	# Set query parameters as global variables
	if ($str =~ m/"user_name":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_dbuser'}  = $1;
	}
	if ($str =~ m/"database_name":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_dbname'}  = $1;
	}
	if ($str =~ m/"application_name":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_appname'} = $1;
	}
	if ($str =~ m/"connection_from":\s*"(.*?)"(?:,"|\})/)
	{
		$infos{'t_client'}  = $1;
		$infos{'t_client'}  =~ s/:.*//;
		$infos{'t_client'} = _gethostbyaddr($infos{'t_client'}) if ($dns_resolv);
	}
	$infos{'t_host'}    = 'jsonlog'; # this unused variable is used to store format information when log format is not syslog

	if ($str =~ m/"process_id":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_pid'} = $1;
	}

	if ($str =~ m/"error_severity":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_loglevel'} = $1;
	}
	if ($str =~ m/"sql_state_code":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_sqlstate'} = $1;
	}
	if ($str =~ m/"message":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_query'} = unescape_jsonlog($1);
	}

	# Set ERROR additional information
	if ($str =~ m/"detail":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_detail'} = unescape_jsonlog($1);
	}
	if ($str =~ m/"hint":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_hint'} = unescape_jsonlog($1);
	}
	if ($str =~ m/"context":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_context'} = unescape_jsonlog($1);
	}
	if ($str =~ m/"internal_query":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_statement'} = unescape_jsonlog($1);
	}

	# Backend type information
	if ($str =~ m/"backend_type":\s*"(.*?)"(?:,"|\})/) {
		$infos{'t_backend_type'} = $1;
	}

	return %infos;
}

sub parse_orphan_line
{
	my ($cur_pid, $line, $t_dbname) = @_;

	my $date_part = "$cur_info{$cur_pid}{year}$cur_info{$cur_pid}{month}$cur_info{$cur_pid}{day}";

	my $curdb = undef;
	if (!exists $cur_info{$cur_pid} || !exists $cur_info{$cur_pid}{cur_db} || !$cur_info{$cur_pid}{cur_db}) {
		$curdb = set_current_db($t_dbname);
	} else {
		$curdb = $cur_info{$cur_pid}{cur_db};
	}
	if (!$report_per_database) {
		$curdb = $DBALL;
	}

	# Store vacuum related information
	if ($cur_info{$cur_pid}{vacuum} && ($line =~ /^[\s\t]*(pages|tuples|buffer usage|avg read rate|system usage|WAL usage):/))
	{
		if ($line =~ /(pages|tuples): (\d+) removed, (\d+) remain/) {
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{$1}{removed} += $2;
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{$1}{remain} += $3;
		}
		if ($line =~ /(\d+) are dead but not yet removable/) {
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{tuples}{notremovable} += $1;
		}
		if ($line =~ /^[\s\t]*system usage: CPU: user: (.*) (?:sec|s,) system: (.*) (?:sec|s,) elapsed: ([^\s]+)/)
		{
			# Add vacuum counts and duration to the $per_minute_info.
			# $per_minute_info{$curdb}{$date_part}{$cur_info{$cur_pid}{hour}}{$cur_info{$cur_pid}{min}}{autovacuum}{count}++; # Duplicate to parse_query() -> Store autovacuum information
			$per_minute_info{$curdb}{$date_part}{$cur_info{$cur_pid}{hour}}{$cur_info{$cur_pid}{min}}{autovacuum}{second}{$cur_info{$cur_pid}{second}} += $3;
			if ($3 > $autovacuum_info{$curdb}{peak}{system_usage}{elapsed})
			{
				$autovacuum_info{$curdb}{peak}{system_usage}{elapsed} = $3;
				$autovacuum_info{$curdb}{peak}{system_usage}{table} = $cur_info{$cur_pid}{vacuum};
				$autovacuum_info{$curdb}{peak}{system_usage}{date} =
					"$cur_info{$cur_pid}{year}-$cur_info{$cur_pid}{month}-$cur_info{$cur_pid}{day} " .
					"$cur_info{$cur_pid}{hour}:$cur_info{$cur_pid}{min}:$cur_info{$cur_pid}{sec}";
			}
		}
		if ($line =~ /, (\d+) skipped due to pins, (\d+) skipped frozen/)
		{
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{skip_pins} += $1;
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{skip_frozen} += $2;
		}
		if ($line =~ /buffer usage: (\d+) hits, (\d+) misses, (\d+) dirtied/)
		{
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{hits} += $1;
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{misses} += $2;
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{dirtied} += $3;
		}
		if ($line =~ /WAL usage: (\d+) records, (\d+) full page images, (\d+) bytes/)
		{
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{wal_record} += $1;
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{wal_full_page} += $2;
			$autovacuum_info{$curdb}{tables}{$cur_info{$cur_pid}{vacuum}}{wal_bytes} += $3;
		}
	}
	# stores bind parameters if parameter syntax is detected
	elsif ( $cur_info{$cur_pid}{parameters} || $cur_bind_info{$cur_pid})
	{
		if (!$error_only)
		{
			if ($cur_info{$cur_pid}{parameters})
			{
				if ($cur_info{$cur_pid}{parameters} =~ /=$/) {
					$cur_info{$cur_pid}{parameters} .= ' ';
					$cur_bind_info{$cur_pid}{'bind'}{'parameters'} .= ' ' if (exists $cur_bind_info{$cur_pid}{'bind'}{'parameters'});
				}
				$line =~ s/^\t+/\\n/;
				$cur_bind_info{$cur_pid}{'bind'}{'parameters'} .= $line if (exists $cur_bind_info{$cur_pid}{'bind'}{'parameters'});
				$cur_info{$cur_pid}{parameters} .= $line;
			}
			elsif (exists $cur_bind_info{$cur_pid}{bind}{'query'} && !exists $cur_info{$cur_pid}{query})
			{
				$cur_bind_info{$cur_pid}{bind}{'query'} .= $line;
			}
			else
			{
				$cur_info{$cur_pid}{query} .= $line;
			}
		}
	}
	# stores explain plan lines
	elsif (exists $cur_plan_info{$cur_pid}{plan})
	{
		$cur_plan_info{$cur_pid}{plan} .= "\n" . $line;
	}
	# If we have previously stored a temporary file query, append to that query
	elsif (exists $cur_temp_info{$cur_pid}{size})
	{
		$cur_temp_info{$cur_pid}{query} .= "\n" . $line;
	}
	# If we have previously stored a query that generates locks, append to that query
	elsif (exists $cur_lock_info{$cur_pid}{query})
	{
		$cur_lock_info{$cur_pid}{query} .= "\n" . $line;
	}
	# If we have previously stored a cancelled query, append to that query
	elsif (exists $cur_cancel_info{$cur_pid}{query})
	{
		$cur_cancel_info{$cur_pid}{query} .= "\n" . $line;
	}
	# Otherwise append the orphan line to the corresponding part of the query
	else
	{
		# Append to the error statement if one is defined
		if (exists $cur_info{$cur_pid}{statement}) {
			$cur_info{$cur_pid}{statement} .= "\n" . $line if (!$nomultiline);
		# Append to the bind parameters if one is defined
		} elsif (exists $cur_info{$cur_pid}{parameters}) {
			$cur_info{$cur_pid}{parameters} .= $line if (!$error_only);
		# Append to the error context if one is defined
		} elsif (exists $cur_info{$cur_pid}{context}) {
			$cur_info{$cur_pid}{context} .= "\n" . $line;
		# Append to the query detail if one is defined
		} elsif (exists $cur_info{$cur_pid}{detail}) {
			$cur_info{$cur_pid}{detail} .= "\n" . $line;
		# After all append to the query if one is defined
		} elsif (exists $cur_info{$cur_pid}{query}) {
			$cur_info{$cur_pid}{query} .= "\n" . $line if (!$nomultiline && !$error_only);
		# Associate to bind|prepare query now that we collect it too
		} elsif (exists $cur_bind_info{$cur_pid}{'bind'}) {
			$cur_bind_info{$cur_pid}{'bind'}{'query'} .= "\n" . $line;
		} elsif (exists $cur_bind_info{$cur_pid}{'prepare'}) {
			$cur_bind_info{$cur_pid}{'prepare'}{'query'} .= "\n" . $line;
		}
	}
}


# Store the current timestamp of the log line
sub store_current_timestamp
{
	my ($t_timestamp, $t_pid, $t_dbname) = @_;

	# Store current report name and list of database
	my $curdb = undef;
	if (!exists $cur_info{$t_pid} || !exists $cur_info{$t_pid}{cur_db}) {
		$curdb = set_current_db($t_dbname);
	} else {
		$curdb = $cur_info{$t_pid}{cur_db};
	}

	if (!$overall_stat{$curdb}{'first_log_ts'} || ($overall_stat{$curdb}{'first_log_ts'} gt $t_timestamp)) {
		$overall_stat{$curdb}{'first_log_ts'} = $t_timestamp;
	}
	if (!$overall_stat{$curdb}{'last_log_ts'} || ($overall_stat{$curdb}{'last_log_ts'} lt $t_timestamp)) {
		$overall_stat{$curdb}{'last_log_ts'} = $t_timestamp;
	}
}

sub detect_new_log_line
{
	my ($lfile, $fmt, $current_date, $gyear, $saved_date, $startoffset) = @_;

	my $more_lines = 0;
	my $num_line_checked = 0;

	while (my $line = <$lfile>)
	{
		$line =~ s/\r//;
		chomp($line);
		next if (!$line);
		$num_line_checked++;

		if ($fmt =~ /syslog|logplex/)
		{
			my @matches = ($line =~ $compiled_prefix);
			if ($#matches >= 0)
			{
				for (my $i = 0 ; $i <= $#prefix_params ; $i++) {
					$prefix_vars{$prefix_params[$i]} = $matches[$i];
				}
				# Standard syslog format does not have year information, months are
				# three letters and days are not always with 2 digits.
				if ($prefix_vars{'t_month'} !~ /\d/) {
					$prefix_vars{'t_year'}  = $gyear;
					$prefix_vars{'t_day'}   = sprintf("%02d", $prefix_vars{'t_day'});
					$prefix_vars{'t_month'} = $month_abbr{$prefix_vars{'t_month'}};
					# Take care of year overlapping
					if ("$prefix_vars{'t_year'}$prefix_vars{'t_month'}$prefix_vars{'t_day'}" > $current_date) {
						$prefix_vars{'t_year'} = substr($current_date, 0, 4) - 1;
					}
				}
				$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
				$prefix_vars{'t_timestamp'} =
					"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_time'}";
			}
		}
		elsif ($fmt eq 'jsonlog')
		{
			%prefix_vars = parse_jsonlog_input($line);

			if (!exists $prefix_vars{'t_year'})
			{
				($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'},
					$prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = ($prefix_vars{'t_timestamp'} =~ $time_pattern);
			}
			$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
		}
		elsif ($fmt =~ /pgbouncer/)
		{
			my @matches = ($line =~ $pgbouncer_log_parse1);
			if ($#matches >= 0) {
				for (my $i = 0 ; $i <= $#pgb_prefix_parse1 ; $i++) {
					$prefix_vars{$pgb_prefix_parse1[$i]} = $matches[$i];
				}
			}
		}
		else
		{
			%prefix_vars = ();
			my @matches = ($line =~ $compiled_prefix);
			if ($#matches >= 0)
			{
				for (my $i = 0 ; $i <= $#prefix_params ; $i++) {
					$prefix_vars{$prefix_params[$i]} = $matches[$i];
				}

				$prefix_vars{'t_client'} =~ s/\(.*// if ($fmt eq 'rds');
				if (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_mtimestamp'}) {
					$prefix_vars{'t_timestamp'} = $prefix_vars{'t_mtimestamp'};
				} elsif (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_session_timestamp'}) {
					$prefix_vars{'t_timestamp'} = $prefix_vars{'t_session_timestamp'};
				} elsif (!$prefix_vars{'t_timestamp'} && $prefix_vars{'t_epoch'}) {
					$prefix_vars{'t_timestamp'} = strftime("%Y-%m-%d %H:%M:%S", CORE::localtime($prefix_vars{'t_epoch'}));
					if ($prefix_vars{'t_epoch'} =~ /^\d{10}(\.\d{3})$/) {
						$prefix_vars{'t_timestamp'} .= $1;
					}
				} elsif ($prefix_vars{'t_timestamp'} =~ /^\d{10}(\.\d{3})$/) {
					my $ms = $1;
					$prefix_vars{'t_epoch'} = $prefix_vars{'t_timestamp'};
					$prefix_vars{'t_timestamp'} = strftime("%Y-%m-%d %H:%M:%S", CORE::localtime($prefix_vars{'t_timestamp'}));
					 $prefix_vars{'t_timestamp'} .= $ms;
				}
			}

			if ($prefix_vars{'t_timestamp'})
			{
				($prefix_vars{'t_year'}, $prefix_vars{'t_month'}, $prefix_vars{'t_day'}, $prefix_vars{'t_hour'},
					$prefix_vars{'t_min'}, $prefix_vars{'t_sec'}) = ($prefix_vars{'t_timestamp'} =~ $time_pattern);
			}
			elsif ($prefix_vars{'t_year'})
			{
				$prefix_vars{'t_timestamp'} = "$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} $prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
			}
			$prefix_vars{'t_time'} = "$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";

			# Skip this line if there is no timestamp
			next if (!$prefix_vars{'t_timestamp'} || $prefix_vars{'t_timestamp'} eq '-- ::');
		}

		# Unwanted line
		next if (!$prefix_vars{'t_timestamp'});

		# This file has already been parsed
		if ($saved_date gt $prefix_vars{'t_timestamp'})
		{
			close($lfile);
			return (0, "this file has already been parsed, timestamp $prefix_vars{'t_timestamp'} read at offset $startoffset is lower than saved timestamp: $saved_date");
		}
		elsif ($saved_date eq $prefix_vars{'t_timestamp'})
		{
			next;
		}
		else
		{
			$more_lines++;
			last;
		}
	}

	return ($more_lines, "more line after the saved position");
}


# Method used to check if the file stores logs after the last incremental position or not
# This position should have been saved in the incremental file and read in the $last_parsed at
# start up.
#
# How does pgBadger detect that a log file need not to be parsed?
#
# In process_file():
# 
# File LAST_PARSED is not present in the incremental output directory
#         => the log is fully parsed.
# 
# 
# File LAST_PARSED is present, read the size of the last parsed log and the timestamp from
# this file then for each log file provided
# 
# If the total size of the log (uncompressed) is smaller than the history size
# or we can not determine the real file size of a compressed file (ex: bzip2)
#         => read the log from start and exclude all lines older than the history timestamp
# 
# If logfile is input from stdin, in binary or csv format, it is download through an http request
#         => read the log from start and exclude all lines older than the history timestamp
# 
# Call check_file_changed(), return code:
#	- -1 : the file must be parsed from the beginning
# 	-  0 : the log has already be parsed
# 	-  1 : the log must be parsed from the history offset
# 
#   - If this is a remote log downloaded using http[s] or [s]ftp, we can not move/seek to the historical position/offset
#         => return -1, read the log from start and exclude all lines older than the history timestamp
# 
#   - If this is a compressed remote log we can not move/seek to the historical position/offset
#         => return -1, read the log from start and exclude all lines older than the history timestamp
#            Use of zhead and ztail can cost too much in remote mode, just return -1
# 
#   - If the log file is compressed we can not seek to history position, the entire file must be read
#         => return -1, this file must be parsed from start excluding all lines older than the history timestamp
# 
#   - If the history size is smaller than the total size fo the log file:
#         => move/seek to the history size/offset and look at the next line timestamp
#            though method detect_new_log_line().
#   - If the history size is equal to the total size fo the log file:
#         => rewind/seek to history size/offset - 8192
# 
#   - Then go through method detect_new_log_line():
# 
#         => if the history timestamp is newer than the current line parsed
#                 => return 0, this file has already been parsed
#         => if the current line parsed has the same timestamp than the history timestamp
#                 => go to next line
#         => if the next line is newer than the history timestamp
#                 => return 1, the log will be parsed starting from the history size/offset.
# 
#   - If more new line (1) has been returned by detect_new_log_line(), move/seek at the start of
#     of the log and check the timestamp of the first line.
#         => if the timestamp of the first line is newer than the history timestamp
#                 => return -1, "the file is new, the entire file must be parsed"
#         => else
#                 => return 1, "the file will parsed from history position and history date"
#   - else
#         => return 0, "no new line found in this log"
# 
sub check_file_changed
{
	my ($file, $totalsize, $fmt, $saved_date, $saved_pos, $look_at_beginning) = @_;

	# With http[s] or [s]ftp download we can not seek to the historical position
	if ($file =~ /^(http[s]*:|[s]*ftp:)/) {
		return (-1, "no incremental mode for http[s] or [s]ftp download");
	}

	my $ssh_download   = ($file =~ /^ssh:/i) ? 1 : 0;
	my $http_download  = ($file =~ /^(http[s]*:|[s]*ftp:)/i) ? 1 : 0;
	my $iscompressed   = ($file =~ $compress_extensions) ? 1 : 0;

	my $lfile = &get_log_file($file, $totalsize, $remote_host || $ssh_download);
	return (-1, "cannot open file $file") if (!defined $lfile);

	my ($gsec, $gmin, $ghour, $gmday, $gmon, $gyear, $gwday, $gyday, $gisdst) = localtime(time);
	$gyear += 1900;
	my $current_date = $gyear . sprintf("%02d", $gmon + 1) . sprintf("%02d", $gmday);
	my $startoffset = 0;

	# Compressed files do not allow seeking so we will return 0 or 2
	if ($iscompressed)
	{
		close($lfile);

		return (-1, "seek into compressed file is not supported, the entire file must be parsed");
	}

	%prefix_vars = ();
	
	# If seeking is not explicitely disabled
	if (!$look_at_beginning)
	{
		# do not seek if filesize is smaller than the seek position
		if ($saved_pos < $totalsize)
		{
			$lfile->seek($saved_pos || 0, 0);
			$startoffset = $saved_pos || 0;
		}
		# Case of file with same size
		elsif ($saved_pos == $totalsize)
		{
			# A log line can not be greater than 8192 so rewind to
			# previous line, we don't care if we rewind more line
			# before as if this is the same log they are in the past
			if ($saved_pos > 8192)
			{
				$lfile->seek($saved_pos - 8192, 0);
				$startoffset = $saved_pos - 8192;
			}
			else
			{
				$lfile->seek(0, 0);
				$startoffset = 0;
			}
		}
	}

	my ($more_lines, $msg) = detect_new_log_line($lfile, $fmt, $current_date, $gyear, $saved_date, $startoffset);
	if ($more_lines)
	{
		$lfile->seek(0, 0);
		$startoffset = 0;
		($more_lines, $msg) = detect_new_log_line($lfile, $fmt, $current_date, $gyear, $saved_date, $startoffset);
		close($lfile);
		if ($more_lines) {
			return (-1, "the file is new, the entire file must be parsed");
		}
	}
	else
	{
		close($lfile);
		return (0, "no new line found in this log");
	}

	return (1, "the file will parsed from history position $startoffset and history date: $saved_date") ;
}

# Method used to check if we have already reached the last parsing position in incremental mode
# This position should have been saved in the incremental file and read in the $last_parsed at
# start up.
sub check_incremental_position
{
	my ($fmt, $cur_date, $line) = @_;

	if ($last_parsed && ($fmt !~ /pgbouncer/))
	{
		if ($saved_last_line{datetime})
		{
			if ($cur_date lt $saved_last_line{datetime}) {
				return 0;
			} elsif (!$last_line{datetime} && ($cur_date eq $saved_last_line{datetime})) {
				return 0;
			}
		}
		$last_line{datetime} = $cur_date;
		$last_line{orig}     = $line;
	}
	elsif ($last_parsed)
	{
		if ($pgb_saved_last_line{datetime})
		{
			if ($cur_date lt $pgb_saved_last_line{datetime}) {
				return 0;
			} elsif (!$pgb_last_line{datetime} && ($cur_date eq $pgb_saved_last_line{datetime})) {
				return 0 if ($line ne $pgb_saved_last_line{orig});
			}
		}
		$pgb_last_line{datetime} = $cur_date;
		$pgb_last_line{orig}     = $line;
	}

	# In incremental mode data are saved to disk per day
	if ($incremental)
	{
		$cur_date =~ s/\s.*$//;
		# Check if the current day has changed, if so save data
		$incr_date = $cur_date if (!$incr_date);
		if ($cur_date gt $incr_date)
		{
			# Get stats from all pending temporary storage
			foreach my $pid (sort {$cur_info{$a}{date} <=> $cur_info{$b}{date}} keys %cur_info)
			{
				# Stores last queries information
				&store_queries($pid, 1);
			}
			# Stores last temporary files and lock information
			foreach my $pid (keys %cur_temp_info) {
				&store_temporary_and_lock_infos($pid);
			}
			# Stores last cancelled queries information
			foreach my $pid (keys %cur_cancel_info) {
				&store_temporary_and_lock_infos($pid);
			}
			# Stores last temporary files and lock information
			foreach my $pid (keys %cur_lock_info) {
				&store_temporary_and_lock_infos($pid);
			}

			# set path and create subdirectories
			if ($incr_date =~ /^(\d+)-(\d+)-(\d+)/)
			{
				mkdir("$outdir/$1") if (!-d "$outdir/$1");
				mkdir("$outdir/$1/$2") if (!-d "$outdir/$1/$2");
				mkdir("$outdir/$1/$2/$3") if (!-d "$outdir/$1/$2/$3");
			}
			else
			{
				&logmsg('ERROR', "invalid incremental date: $incr_date, can not create subdirectories.");
			}
			my $bpath = $incr_date;
			$bpath =~ s/\-/\//g;

			# Mark this directory as needing a reindex
			if (open(my $out, '>>' , "$last_parsed.tmp"))
			{
				flock($out, 2) || return 1;
				print $out "$incr_date\n";
				close($out);
			} else {
				&logmsg('ERROR', "can't save last parsed line into $last_parsed.tmp, $!");
			}

			# Save binary data
			my $filenum = $$;
			$filenum++ while (-e "$outdir/$bpath/$incr_date-$filenum.bin");
			my $fhb = new IO::File ">$outdir/$bpath/$incr_date-$filenum.bin";
			if (not defined $fhb) {
				localdie("FATAL: can't write to $outdir/$bpath/$incr_date-$filenum.bin, $!\n");
			}
			&dump_as_binary($fhb);
			$fhb->close;
			$incr_date = $cur_date;
			&init_stats_vars();
		}
	}

	return 1;
}

# Display message following the log level
sub logmsg
{
	my ($level, $str) = @_;

	return if ($quiet && !$debug && ($level ne 'FATAL'));
	return if (!$debug && ($level eq 'DEBUG'));

	if ($level =~ /(\d+)/) {
		print STDERR "\t" x $1;
	}

	print STDERR "$level: $str\n";
}

# Remove quote from alias for normalisation
sub remove_alias
{
	my $str = shift();

	$str =~ s/'//gs;

	return $str;
}

# Normalize SQL queries by removing parameters
sub normalize_query
{
	my $orig_query = shift;

	return if (!$orig_query);

	# Remove comments /* ... */
	if (!$keep_comments) {
		$orig_query =~ s/\/\*(.*?)\*\///gs;
	}

	# Keep case on object name between doublequote
	my %objnames = ();
	my $i = 0;
	while ($orig_query =~ s/("[^"]+")/%%OBJNAME$i%%/) {
		$objnames{$i} = $1;
		$i++;
	}
	# Set the entire query lowercase
	$orig_query = lc($orig_query);

	# Restore object name
	while ($orig_query =~ s/\%\%objname(\d+)\%\%/$objnames{$1}/gs) {};
	%objnames = ();

	# Remove string content
	$orig_query =~ s/\\'//gs;
	$orig_query =~ s/'[^']*'/\?/gs;
	$orig_query =~ s/\?(\?)+/\?/gs;

	# Remove comments starting with --
	if (!$keep_comments) {
		$orig_query =~ s/\s*--[^\n]+[\n]/\n/gs;
	}

	# Remove extra space, new line and tab characters by a single space
	$orig_query =~ s/\s+/ /gs;

	# Removed start of transaction
	if ($orig_query !~ /^\s*begin\s*;\s*$/) {
		$orig_query =~ s/^\s*begin\s*;\s*//gs
	}

	# Normalise alias with quote
	$orig_query =~ s/AS\s+"([^"]+)"/'AS "' . remove_alias($1) . '"'/eigs;

	# Remove NULL parameters
	$orig_query =~ s/=\s*null/= \?/gs;

	# remove temporary identifier between double quote
	my %identifiers = ();
	$i = 0;
	while ($orig_query =~ s/"([^"]+)"/\%sqlident$i\%/) {
		$identifiers{$i} = $1;
		$i++;
	}

	# Remove numbers
	$orig_query =~ s/([^a-z0-9_\$\-])-?\d+/$1\?/gs;

	# Remove hexadecimal numbers
	$orig_query =~ s/([^a-z_\$-])0x[0-9a-f]{1,10}/$1\?/gs;

	# Remove bind parameters
	$orig_query =~ s/\$\d+/\?/gs;

	# restore identifiers
	$orig_query =~ s/\%sqlident(\d+)\%/"$identifiers{$1}"/gs;

	# Remove IN values
	$orig_query =~ s/\bin\s*\([\'0x,\s\?]*\)/in (...)/gs;

	# Remove curor names in CURSOR and IN clauses
	$orig_query =~ s/\b(declare|in|deallocate|close)\s+"[^"]+"/$1 "..."/gs;

	# Normalise cursor name
	$orig_query =~ s/\bdeclare\s+[^"\s]+\s+cursor/declare "..." cursor/gs;
	$orig_query =~ s/\b(fetch\s+next\s+from)\s+[^\s]+/$1 "..."/gs;
	$orig_query =~ s/\b(deallocate|close)\s+[^"\s]+/$1 "..."/gs;

	# Remove any leading whitespace
	$orig_query =~ s/^\s+//;

	# Remove any trailing whitespace
	$orig_query =~ s/\s+$//;

	# Remove any whitespace before a semicolon
	$orig_query =~ s/\s+;/;/;

	return $orig_query;
}

sub anonymized_string
{
	my ( $before, $original, $after, $cache ) = @_;

	# Prevent dates from being anonymized
	return $original if $original =~ m{\A\d\d\d\d[/:-]\d\d[/:-]\d\d\z};
	return $original if $original =~ m{\A\d\d[/:-]\d\d[/:-]\d\d\d\d\z};

	# Prevent dates format like DD/MM/YYYY HH24:MI:SS from being anonymized
	return $original if $original =~ m{
		\A
		(?:FM|FX|TM)?
		(?:
		HH | HH12 | HH24
		| MI
		| SS
		| MS
		| US
		| SSSS
		| AM | A\.M\. | am | a\.m\.
		| PM | P\.M\. | pm | p\.m\.
		| Y,YYY | YYYY | YYY | YY | Y
		| IYYY | IYY | IY | I
		| BC | B\.C\. | bc | b\.c\.
		| AD | A\.D\. | ad | a\.d\.
		| MONTH | Month | month | MON | Mon | mon | MM
		| DAY | Day | day | DY | Dy | dy | DDD | DD | D
		| W | WW | IW
		| CC
		| J
		| Q
		| RM | rm
		| TZ | tz
		| [\s/:-]
		)+
		(?:TH|th|SP)?
		\z
	};

	# Prevent interval from being anonymized
	return $original if ($before && ($before =~ /interval/i));
	return $original if ($after && ($after =~ /^\)*::interval/i));

	# Range of characters to use in anonymized strings
	my @chars = ( 'A' .. 'Z', 0 .. 9, 'a' .. 'z', '-', '_', '.' );

	unless ( $cache->{ $original } )
	{
		# Actual anonymized version generation
		$cache->{ $original } = join( '', map { $chars[ rand @chars ] } 1 .. 10 );
	}

	return $cache->{ $original };
}

sub anonymized_number
{
	my ( $original, $cache ) = @_;

	# Range of number to use in anonymized strings
	my @numbers = ( 0 .. 9 );

	unless ( $cache->{ $original } )
	{
		# Actual anonymized version generation
		$cache->{ $original } = join( '', map { $numbers[ rand @numbers ] } 1 .. 4 );
	}

	return $cache->{ $original };
}

# Anonymize litteral in SQL queries by replacing parameters with fake values
sub anonymize_query
{
	my $orig_query = shift;

	return $orig_query if (!$orig_query || !$anonymize);

	# Variable to hold anonymized versions, so we can provide the same value
	# for the same input, within single query.
	my $anonymization_cache = {};

	# Remove comments
	if (!$keep_comments) {
		$orig_query =~ s/\/\*(.*?)\*\///gs;
	}

	# Clean query
	$orig_query =~ s/\\'//g;
	$orig_query =~ s/('')+/\$EMPTYSTRING\$/g;

	# Anonymize each values
	$orig_query =~ s{
		([^\s\']+[\s\(]*)       # before
		'([^']*)'               # original
		([\)]*::\w+)?           # after
		}{$1 . "'" . anonymized_string($1, $2, $3, $anonymization_cache) . "'" . ($3||'')}xeg;

	$orig_query =~ s/\$EMPTYSTRING\$/''/gs;

	# obfuscate numbers too if this is not parameter indices ($1 ...)
	$anonymization_cache = {};
	$orig_query =~ s{([^\$])\b(\d+)\b}{ $1 . anonymized_number($1, $anonymization_cache) }xeg;

	return $orig_query;
}

# Format numbers with comma for betterparam_cache reading
sub comma_numbers
{
	return 0 if ($#_ < 0);

	return 0 if (!$_[0]);

	my $text = reverse $_[0];

	$text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1$num_sep/g;

	return scalar reverse $text;
}

# Format numbers with comma for better reading
sub pretty_print_size
{
	my $val = shift;
	return 0 if (!$val);

	if ($val >= 1125899906842624) {
		$val = ($val / 1125899906842624);
		$val = sprintf("%0.2f", $val) . " PiB";
	} elsif ($val >= 1099511627776) {
		$val = ($val / 1099511627776);
		$val = sprintf("%0.2f", $val) . " TiB";
	} elsif ($val >= 1073741824) {
		$val = ($val / 1073741824);
		$val = sprintf("%0.2f", $val) . " GiB";
	} elsif ($val >= 1048576) {
		$val = ($val / 1048576);
		$val = sprintf("%0.2f", $val) . " MiB";
	} elsif ($val >= 1024) {
		$val = ($val / 1024);
		$val = sprintf("%0.2f", $val) . " KiB";
	} else {
		$val = $val . " B";
	}

	return $val;
}


# Format duration
sub convert_time
{
	my $time = shift;

	return '0ms' if (!$time);

	my $days = int($time / 86400000);
	$time -= ($days * 86400000);
	my $hours = int($time / 3600000);
	$time -= ($hours * 3600000);
	my $minutes = int($time / 60000);
	$time -= ($minutes * 60000);
	my $seconds = int($time / 1000);
	$time -= ($seconds * 1000);
	my $milliseconds = sprintf("%.3d", $time);

	$days    = $days < 1    ? '' : $days . 'd';
	$hours   = $hours < 1   ? '' : $hours . 'h';
	$minutes = $minutes < 1 ? '' : $minutes . 'm';
	$seconds = $seconds < 1 ? '' : $seconds . 's';
	$milliseconds = $milliseconds < 1 ? '' : $milliseconds . 'ms';

	if ($days || $hours || $minutes) {
		$milliseconds = '';
	} elsif ($seconds) {
		$milliseconds =~ s/\.\d+//;
	}
	$milliseconds =~ s/^[0]+// if ($milliseconds !~ /\./);


	$time = $days . $hours . $minutes . $seconds . $milliseconds;
	$time = '0ms' if ($time eq '');

	return $time;
}

# Stores the top N queries generating the biggest temporary file
sub set_top_tempfile_info
{
	my ($curdb, $q, $sz, $date, $db, $user, $remote, $app, $info, $queryid) = @_;

	push(@{$top_tempfile_info{$curdb}}, [($sz, $date, $q, $db, $user, $remote, $app, $info, $queryid)]);

	my @tmp_top_tempfile_info = sort {$b->[0] <=> $a->[0]} @{$top_tempfile_info{$curdb}};
	@{$top_tempfile_info{$curdb}} = ();
	for (my $i = 0; $i <= $#tmp_top_tempfile_info; $i++)
	{
		push(@{$top_tempfile_info{$curdb}}, $tmp_top_tempfile_info[$i]);
		last if ($i == $end_top);
	}
}

# Stores top N slowest sample queries
sub set_top_prepare_bind_sample
{
	my ($type, $q, $dt, $t, $param, $db, $user, $remote, $app, $queryid) = @_;

	return if ($sample <= 0);

	if ($type eq 'prepare') {
		$prepare_info{$db}{$q}{samples}{$dt}{query}     = $q;
		$prepare_info{$db}{$q}{samples}{$dt}{date}      = $t;
		$prepare_info{$db}{$q}{samples}{$dt}{db}        = $db;
		$prepare_info{$db}{$q}{samples}{$dt}{user}      = $user;
		$prepare_info{$db}{$q}{samples}{$dt}{remote}    = $remote;
		$prepare_info{$db}{$q}{samples}{$dt}{app}       = $app;
		$prepare_info{$db}{$q}{samples}{$dt}{queryid}   = $queryid;
		$prepare_info{$db}{$q}{samples}{$dt}{params}    = $param;
		my $i = 1;
		foreach my $k (sort {$b <=> $a} keys %{$prepare_info{$db}{$q}{samples}}) {
			if ($i > $sample) {
				delete $prepare_info{$db}{$q}{samples}{$k};
			}
			$i++;
		}
	}

	if ($type eq 'bind') {
		$bind_info{$db}{$q}{samples}{$dt}{query}        = $q;
		$bind_info{$db}{$q}{samples}{$dt}{date}         = $t;
		$bind_info{$db}{$q}{samples}{$dt}{db}           = $db;
		$bind_info{$db}{$q}{samples}{$dt}{user}         = $user;
		$bind_info{$db}{$q}{samples}{$dt}{remote}       = $remote;
		$bind_info{$db}{$q}{samples}{$dt}{app}          = $app;
		$bind_info{$db}{$q}{samples}{$dt}{queryid}      = $queryid;
		$bind_info{$db}{$q}{samples}{$dt}{params}       = $param;
		my $i = 1;
		foreach my $k (sort {$b <=> $a} keys %{$bind_info{$db}{$q}{samples}}) {
			if ($i > $sample) {
				delete $bind_info{$db}{$q}{samples}{$k};
			}
			$i++;
		}
	}
}

# Stores the top N queries cancelled
sub set_top_cancelled_info
{
	my ($curdb, $q, $sz, $date, $db, $user, $remote, $app, $queryid) = @_;

	push(@{$top_cancelled_info{$curdb}}, [($sz, $date, $q, $db, $user, $remote, $app, $queryid)]);

	my @tmp_top_cancelled_info = sort {$b->[0] <=> $a->[0]} @{$top_cancelled_info{$curdb}};
	@{$top_cancelled_info{$curdb}} = ();
	for (my $i = 0; $i <= $#tmp_top_cancelled_info; $i++) {
		push(@{$top_cancelled_info{$curdb}}, $tmp_top_cancelled_info[$i]);
		last if ($i == $end_top);
	}
}

# Stores the top N queries waiting the most
sub set_top_locked_info
{
	my ($curdb, $q, $dt, $date, $db, $user, $remote, $app, $queryid) = @_;

	push(@{$top_locked_info{$curdb}}, [($dt, $date, $q, $db, $user, $remote, $app, $queryid)]);

	my @tmp_top_locked_info = sort {$b->[0] <=> $a->[0]} @{$top_locked_info{$curdb}};
	@{$top_locked_info{$curdb}} = ();
	for (my $i = 0; $i <= $#tmp_top_locked_info; $i++) {
		push(@{$top_locked_info{$curdb}}, $tmp_top_locked_info[$i]);
		last if ($i == $end_top);
	}
}

# Stores the top N slowest queries
sub set_top_slowest
{
	my ($curdb, $q, $dt, $date, $db, $user, $remote, $app, $bind, $plan, $queryid) = @_;

	push(@{$top_slowest{$curdb}}, [($dt, $date, $q, $db, $user, $remote, $app, $bind, $plan, $queryid)]);

	my @tmp_top_slowest = sort {$b->[0] <=> $a->[0]} @{$top_slowest{$curdb}};
	@{$top_slowest{$curdb}} = ();
	for (my $i = 0; $i <= $#tmp_top_slowest; $i++) {
		push(@{$top_slowest{$curdb}}, $tmp_top_slowest[$i]);
		last if ($i == $end_top);
	}
}

# Stores top N slowest sample queries
sub set_top_sample
{
	my ($curdb, $norm, $q, $dt, $date, $db, $user, $remote, $app, $bind, $plan, $queryid) = @_;

	return if (!$norm || !$q || $sample <= 0);

	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{query}	= $q;
	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{date}	= $date;
	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{db}	= $db;
	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{user}	= $user;
	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{remote}	= $remote;
	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{app}	= $app;
	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{bind}	= $bind;
	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{plan}	= $plan;
	$normalyzed_info{$curdb}{$norm}{samples}{$dt}{queryid}	= $queryid;

	my $i = 1;
	foreach my $k (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$norm}{samples}}) {
		if ($i > $sample) {
			delete $normalyzed_info{$curdb}{$norm}{samples}{$k};
		}
		$i++;
	}
}

# Stores top N error sample queries
sub set_top_error_sample
{
	my ($curdb, $q, $date, $real_error, $detail, $context, $statement, $hint, $db, $user, $app, $remote, $sqlstate, $queryid) = @_;

	$errors_code{$curdb}{$sqlstate}++ if ($sqlstate);

	# Stop when we have our number of samples
	if (!exists $error_info{$curdb}{$q}{date} || ($#{$error_info{$curdb}{$q}{date}}+1 < $sample))
	{
		if ( $q =~ /deadlock detected/ || (!$statement && $detail && !grep(/^\Q$detail\E$/, @{$error_info{$curdb}{$q}{detail}})) || ($statement && !grep(/^\Q$statement\E$/, @{$error_info{$curdb}{$q}{statement}})) )
		{
			push(@{$error_info{$curdb}{$q}{date}},      $date);
			push(@{$error_info{$curdb}{$q}{detail}},    $detail);
			push(@{$error_info{$curdb}{$q}{context}},   $context);
			push(@{$error_info{$curdb}{$q}{statement}}, $statement);
			push(@{$error_info{$curdb}{$q}{hint}},      $hint);
			push(@{$error_info{$curdb}{$q}{error}},     $real_error);
			push(@{$error_info{$curdb}{$q}{db}},	$db);
			push(@{$error_info{$curdb}{$q}{user}},      $user);
			push(@{$error_info{$curdb}{$q}{app}},       $app);
			push(@{$error_info{$curdb}{$q}{remote}},    $remote);
			push(@{$error_info{$curdb}{$q}{sqlstate}},  $sqlstate);
			push(@{$error_info{$curdb}{$q}{queryid}},   $queryid);
		}
	}
}

# Stores top N error sample from pgbouncer log
sub pgb_set_top_error_sample
{
	my ($q, $date, $real_error, $db, $user, $remote) = @_;

	# Stop when we have our number of samples
	if (!exists $pgb_error_info{$q}{date} || ($#{$pgb_error_info{$q}{date}} < $sample)) {
		push(@{$pgb_error_info{$q}{date}},      $date);
		push(@{$pgb_error_info{$q}{error}},     $real_error);
		push(@{$pgb_error_info{$q}{db}},	$db);
		push(@{$pgb_error_info{$q}{user}},      $user);
		push(@{$pgb_error_info{$q}{remote}},    $remote);
	}
}

sub get_log_limit
{
	my $curdb = shift();

	$overall_stat{$curdb}{'first_log_ts'} =~ /^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/;
	my ($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s);
	if (!$log_timezone) {
		($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s) = ($1, $2, $3, $4, $5, $6);
	} else {
		($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s) = change_timezone($1, $2, $3, $4, $5, $6);
	}
	my $t_log_min = "$t_y-$t_mo-$t_d $t_h:$t_mi:$t_s";
	$overall_stat{$curdb}{'last_log_ts'} =~ /^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/;
	if (!$log_timezone) {
		($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s) = ($1, $2, $3, $4, $5, $6);
	} else {
		($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s) = change_timezone($1, $2, $3, $4, $5, $6);
	}
	my $t_log_max = "$t_y-$t_mo-$t_d $t_h:$t_mi:$t_s";

	return ($t_log_min, $t_log_max);
}

sub dump_as_text
{
	my $curdb = shift;

	# Global information
	my $curdate    = localtime(time);
	my $fmt_nlines = &comma_numbers($overall_stat{nlines}{$curdb});
	my $total_time = timestr($td);
	$total_time =~ s/^([\.0-9]+) wallclock.*/$1/;
	$total_time = &convert_time($total_time * 1000);
	my $logfile_str = $log_files[0];
	if ($#log_files > 0) {
		$logfile_str .= ', ..., ' . $log_files[-1];
	}
	# Set logs limits
	my ($t_log_min, $t_log_max) = get_log_limit($curdb);
	print $fh qq{
pgBadger :: $report_title

- Global information ---------------------------------------------------

Generated on $curdate
Log file: $logfile_str
Parsed $fmt_nlines log entries in $total_time
Log start from $t_log_min to $t_log_max

};

	# Dump normalized queries only if requested
	if ($dump_normalized_only)
	{
		if (!$query_numbering) {
			print $fh "Count\t\tQuery\n";
			print $fh '-'x70,"\n";
		} else {
			print $fh "#Num\tCount\t\tQuery\n";
			print $fh '-'x80,"\n";
		}
		foreach my $q (sort { $normalyzed_info{$curdb}{$b}{count} <=> $normalyzed_info{$curdb}{$a}{count} } keys %{$normalyzed_info{$curdb}}) {
			print $fh $query_numbering++, "\t" if ($query_numbering);
			print $fh "$normalyzed_info{$curdb}{$q}{count}\t$q\n";
		}
		print $fh "\n\n";
		print $fh "Report generated by pgBadger $VERSION ($project_url).\n";
		return;
	}

	# Overall statistics
	my $fmt_unique  = &comma_numbers(scalar keys %{$normalyzed_info{$curdb}});
	my $fmt_queries = &comma_numbers($overall_stat{$curdb}{'queries_number'});
	my $fmt_duration = &convert_time($overall_stat{$curdb}{'queries_duration'}{'execute'}+($overall_stat{$curdb}{'queries_duration'}{'prepare'}||0)+($overall_stat{$curdb}{'queries_duration'}{'bind'}||0));
	$overall_stat{$curdb}{'first_query_ts'} ||= '-';
	$overall_stat{$curdb}{'last_query_ts'} ||= '-';
	print $fh qq{

- Overall statistics ---------------------------------------------------

Number of unique normalized queries: $fmt_unique
Number of queries: $fmt_queries
Total query duration: $fmt_duration
First query: $overall_stat{$curdb}{'first_query_ts'}
Last query: $overall_stat{$curdb}{'last_query_ts'}
};
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{query} <=> $overall_stat{$curdb}{'peak'}{$a}{query}} keys %{$overall_stat{$curdb}{'peak'}}) {
		print $fh "Query peak: ", &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{query}), " queries/s at $_";
		last;
	}
	if (!$disable_error) {
		my $fmt_errors = &comma_numbers($overall_stat{$curdb}{'errors_number'});
		my $fmt_unique_error = &comma_numbers(scalar keys %{$error_info{$curdb}});
		print $fh qq{
Number of events: $fmt_errors
Number of unique normalized events: $fmt_unique_error
};
	}
	if ($tempfile_info{$curdb}{count}) {
		my $fmt_temp_maxsise = &pretty_print_size($tempfile_info{$curdb}{maxsize});
		my $fmt_temp_avsize = &pretty_print_size(sprintf("%.2f", ($tempfile_info{$curdb}{size} / $tempfile_info{$curdb}{count})));
		print $fh qq{Number temporary files: $tempfile_info{$curdb}{count}
Max size of temporary files: $fmt_temp_maxsise
Average size of temporary files: $fmt_temp_avsize
};
	}
	if ($cancelled_info{$curdb}{count}) {
		print $fh qq{Number cancelled queries: $cancelled_info{$curdb}{count}
};
	}
	if (!$disable_session && $session_info{$curdb}{count})
	{
		my $avg_session_duration = &convert_time($session_info{$curdb}{duration} / $session_info{$curdb}{count});
		my $tot_session_duration = &convert_time($session_info{$curdb}{duration});
		my $avg_queries = &comma_numbers(int($overall_stat{$curdb}{'queries_number'}/$session_info{$curdb}{count}));
		my $q_duration = $overall_stat{$curdb}{'queries_duration'}{'execute'}+($overall_stat{$curdb}{'queries_duration'}{'prepare'}||0)+($overall_stat{$curdb}{'queries_duration'}{'bind'}||0);
		my $avg_duration = &convert_time(int($q_duration/$session_info{$curdb}{count}));
		my $avg_idle_time = &convert_time( ($session_info{$curdb}{duration} - $q_duration) / ($session_info{$curdb}{count} || 1) );
		$avg_idle_time = 'n/a' if (!$session_info{$curdb}{count});

		print $fh qq{Total number of sessions: $session_info{$curdb}{count}
Total duration of sessions: $tot_session_duration
Average duration of sessions: $avg_session_duration
Average queries per sessions: $avg_queries
Average queries duration per sessions: $avg_duration
Average idle time per session: $avg_idle_time
};
		foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{session} <=> $overall_stat{$curdb}{'peak'}{$a}{session}} keys %{$overall_stat{$curdb}{'peak'}})
		{
			next if (!$session_info{$curdb}{count});
			print $fh "Session peak: ", &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{session}), " sessions at $_";
			last;
		}
	}
	if (!$disable_connection && $connection_info{$curdb}{count})
	{
		print $fh "Total number of connections: $connection_info{$curdb}{count}\n";
		foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{connection} <=> $overall_stat{$curdb}{'peak'}{$a}{connection}} keys %{$overall_stat{$curdb}{'peak'}})
		{
			if ($overall_stat{$curdb}{'peak'}{$_}{connection} > 0) {
				print $fh "Connection peak: ", &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{connection}), " conn/s at $_";
			}
			last;
		}
	}
	if (scalar keys %{$database_info{$curdb}} > 1) {
		print $fh "Total number of databases: ", scalar keys %{$database_info{$curdb}}, "\n";
	}
	if (!$disable_hourly && $overall_stat{$curdb}{'queries_number'}) {
		print $fh qq{

- Hourly statistics ----------------------------------------------------

Report not supported by text format

};
	}

	# INSERT/DELETE/UPDATE/SELECT repartition
	my $totala = 0;
	foreach my $a (@SQL_ACTION) {
		$totala += $overall_stat{$curdb}{lc($a)};
	}
	if (!$disable_type && $totala) {

		my $total = $overall_stat{$curdb}{'queries_number'} || 1;
		print $fh "\n- Queries by type ------------------------------------------------------\n\n";
		print $fh "Type     Count     Percentage\n";
		foreach my $a (@SQL_ACTION) {
			print $fh "$a: ", &comma_numbers($overall_stat{$curdb}{lc($a)}), " ", sprintf("%0.2f", ($overall_stat{$curdb}{lc($a)} * 100) / $total), "%\n";
		}
		print $fh "OTHERS: ", &comma_numbers($total - $totala), " ", sprintf("%0.2f", (($total - $totala) * 100) / $total), "%\n"
			if (($total - $totala) > 0);
		print $fh "\n";

		# Show request per database statistics
		if (scalar keys %{$database_info{$curdb}} > 1) {
			print $fh "\n- Request per database ------------------------------------------------------\n\n";
			print $fh "Database     Request type     Count    Duration\n";
			foreach my $d (sort keys %{$database_info{$curdb}}) {
				print $fh "$d - ", &comma_numbers($database_info{$curdb}{$d}{count}), " ", &convert_time($database_info{$curdb}{$d}{duration}), "\n";
				foreach my $r (sort keys %{$database_info{$curdb}{$d}}) {
					next if (($r eq 'count') || ($r =~ /duration/));
					print $fh "\t$r ", &comma_numbers($database_info{$curdb}{$d}{$r}), " ", &convert_time($database_info{$curdb}{$d}{"$r|duration"}), "\n";
				}
			}
		}

		# Show request per application statistics
		if (scalar keys %application_info > 1) {
			print $fh "\n- Request per application ------------------------------------------------------\n\n";
			print $fh "Application     Request type    Count    Duration\n";
			foreach my $d (sort keys %{$application_info{$curdb}}) {
				print $fh "$d - ", &comma_numbers($application_info{$curdb}{$d}{count}), " ", &convert_time($application_info{$curdb}{$d}{duration}), "\n";
				foreach my $r (sort keys %{$application_info{$curdb}{$d}}) {
					next if (($r eq 'count') || ($r =~ /duration/));
					print $fh "\t$r ", &comma_numbers($application_info{$curdb}{$d}{$r}), " ", &convert_time($application_info{$curdb}{$d}{"$r|duration"}), "\n";
				}
			}
		}

		# Show request per user statistics
		if (scalar keys %{$user_info{$curdb}} > 1) {
			print $fh "\n- Request per user ------------------------------------------------------\n\n";
			print $fh "User     Request type     Count    duration\n";
			foreach my $d (sort keys %{$user_info{$curdb}}) {
				print $fh "$d - ", &comma_numbers($user_info{$curdb}{$d}{count}), " ", &convert_time($user_info{$curdb}{$d}{duration}), "\n";
				foreach my $r (sort keys %{$user_info{$curdb}{$d}}) {
					next if (($r eq 'count') || ($r =~ /duration/));
					print $fh "\t$r ", &comma_numbers($user_info{$curdb}{$d}{$r}), " ", &convert_time($user_info{$curdb}{$d}{"$r|duration"}), "\n";
				}
			}
		}

		# Show request per host statistics
		if (scalar keys %{$host_info{$curdb}} > 1) {
			print $fh "\n- Request per host ------------------------------------------------------\n\n";
			print $fh "Host     Request type     Count   Duration\n";
			foreach my $d (sort keys %{$host_info{$curdb}}) {
				print $fh "$d - ", &comma_numbers($host_info{$curdb}{$d}{count}), " ", &convert_time($host_info{$curdb}{$d}{duration}), "\n";
				foreach my $r (sort keys %{$host_info{$curdb}{$d}}) {
					next if (($r eq 'count') || ($r =~ /duration/));
					print $fh "\t$r ", &comma_numbers($host_info{$curdb}{$d}{$r}), " ", &convert_time($host_info{$curdb}{$d}{"$r|duration"}), "\n";
				}
			}
		}
	}

	if (!$disable_lock && scalar keys %{$lock_info{$curdb}} > 0)
	{
		print $fh "\n- Locks by type ------------------------------------------------------\n\n";
		print $fh "Type     Object     Count     Total Duration     Avg duration (s)\n";
		my $total_count    = 0;
		my $total_duration = 0;
		foreach my $t (sort keys %{$lock_info{$curdb}}) {
			print $fh "$t\t\t", &comma_numbers($lock_info{$curdb}{$t}{count}), " ", &convert_time($lock_info{$curdb}{$t}{duration}), " ",
				&convert_time($lock_info{$curdb}{$t}{duration} / $lock_info{$curdb}{$t}{count}), "\n";
			foreach my $o (sort keys %{$lock_info{$curdb}{$t}}) {
				next if (($o eq 'count') || ($o eq 'duration') || ($o eq 'chronos'));
				print $fh "\t$o\t", &comma_numbers($lock_info{$curdb}{$t}{$o}{count}), " ", &convert_time($lock_info{$curdb}{$t}{$o}{duration}), " ",
					&convert_time($lock_info{$curdb}{$t}{$o}{duration} / $lock_info{$curdb}{$t}{$o}{count}), "\n";
			}
			$total_count    += $lock_info{$curdb}{$t}{count};
			$total_duration += $lock_info{$curdb}{$t}{duration};
		}
		print $fh "Total:\t\t\t", &comma_numbers($total_count), " ", &convert_time($total_duration), " ",
			&convert_time($total_duration / ($total_count || 1)), "\n";
	}

	# Show session per database statistics
	if (!$disable_session && exists $session_info{$curdb}{database}) {
		print $fh "\n- Sessions per database ------------------------------------------------------\n\n";
		print $fh "Database     Count     Total Duration     Avg duration (s)\n";
		foreach my $d (sort keys %{$session_info{$curdb}{database}}) {
			print $fh "$d - ", &comma_numbers($session_info{$curdb}{database}{$d}{count}), " ",
				&convert_time($session_info{$curdb}{database}{$d}{duration}), " ",
				&convert_time($session_info{$curdb}{database}{$d}{duration} / $session_info{$curdb}{database}{$d}{count}), "\n";
		}
	}

	# Show session per user statistics
	if (!$disable_session && exists $session_info{$curdb}{user}) {
		print $fh "\n- Sessions per user ------------------------------------------------------\n\n";
		print $fh "User     Count     Total Duration     Avg duration (s)\n";
		foreach my $d (sort keys %{$session_info{$curdb}{user}}) {
			print $fh "$d - ", &comma_numbers($session_info{$curdb}{user}{$d}{count}), " ", &convert_time($session_info{$curdb}{user}{$d}{duration}),
				" ", &convert_time($session_info{$curdb}{user}{$d}{duration} / $session_info{$curdb}{user}{$d}{count}), "\n";
		}
	}

	# Show session per host statistics
	if (!$disable_session && exists $session_info{$curdb}{host}) {
		print $fh "\n- Sessions per host ------------------------------------------------------\n\n";
		print $fh "User     Count     Total Duration     Avg duration (s)\n";
		foreach my $d (sort keys %{$session_info{$curdb}{host}}) {
			print $fh "$d - ", &comma_numbers($session_info{$curdb}{host}{$d}{count}), " ", &convert_time($session_info{$curdb}{host}{$d}{duration}),
				" ", &convert_time($session_info{$curdb}{host}{$d}{duration} / $session_info{$curdb}{host}{$d}{count}), "\n";
		}
	}

	# Show session per application statistics
	if (!$disable_session && exists $session_info{$curdb}{app}) {
		print $fh "\n- Sessions per application ------------------------------------------------------\n\n";
		print $fh "Application  Count     Total Duration     Avg duration (s)\n";
		foreach my $d (sort keys %{$session_info{$curdb}{app}}) {
			print $fh "$d - ", &comma_numbers($session_info{$curdb}{app}{$d}{count}), " ", &convert_time($session_info{$curdb}{app}{$d}{duration}),
				" ", &convert_time($session_info{$curdb}{app}{$d}{duration} / $session_info{$curdb}{app}{$d}{count}), "\n";
		}
	}

	# Show connection per database statistics
	if (!$disable_connection && exists $connection_info{$curdb}{database}) {
		print $fh "\n- Connections per database ------------------------------------------------------\n\n";
		print $fh "Database     User     Count\n";
		foreach my $d (sort keys %{$connection_info{$curdb}{database}}) {
			print $fh "$d - ", &comma_numbers($connection_info{$curdb}{database}{$d}), "\n";
			foreach my $u (sort keys %{$connection_info{$curdb}{user}}) {
				next if (!exists $connection_info{$curdb}{database_user}{$d}{$u});
				print $fh "\t$u ", &comma_numbers($connection_info{$curdb}{database_user}{$d}{$u}), "\n";
			}
		}
		print $fh "\nDatabase     Host     Count\n";
		foreach my $d (sort keys %{$connection_info{$curdb}{database}}) {
			print $fh "$d - ", &comma_numbers($connection_info{$curdb}{database}{$d}), "\n";
			foreach my $u (sort keys %{$connection_info{$curdb}{host}}) {
				next if (!exists $connection_info{$curdb}{database_host}{$d}{$u});
				print $fh "\t$u ", &comma_numbers($connection_info{$curdb}{database_host}{$d}{$u}), "\n";
			}
		}
	}

	# Show connection per user statistics
	if (!$disable_connection && exists $connection_info{$curdb}{user}) {
		print $fh "\n- Connections per user ------------------------------------------------------\n\n";
		print $fh "User     Count\n";
		foreach my $d (sort keys %{$connection_info{$curdb}{user}}) {
			print $fh "$d - ", &comma_numbers($connection_info{$curdb}{user}{$d}), "\n";
		}
	}

	# Show connection per host statistics
	if (!$disable_connection && exists $connection_info{$curdb}{host}) {
		print $fh "\n- Connections per host ------------------------------------------------------\n\n";
		print $fh "Host     Count\n";
		foreach my $d (sort keys %{$connection_info{$curdb}{host}}) {
			print $fh "$d - ", &comma_numbers($connection_info{$curdb}{host}{$d}), "\n";
		}
	}

	# Show lock wait detailed information
	if (!$disable_lock && scalar keys %{$lock_info{$curdb}} > 0) {

		my @top_locked_queries = ();
		foreach my $h (keys %{$normalyzed_info{$curdb}}) {
			if (exists($normalyzed_info{$curdb}{$h}{locks})) {
				push (@top_locked_queries, [$h, $normalyzed_info{$curdb}{$h}{locks}{count}, $normalyzed_info{$curdb}{$h}{locks}{wait},
				$normalyzed_info{$curdb}{$h}{locks}{minwait}, $normalyzed_info{$curdb}{$h}{locks}{maxwait}]);
			}
		}

		# Most frequent waiting queries (N)
		@top_locked_queries = sort {$b->[2] <=> $a->[2]} @top_locked_queries;
		print $fh "\n- Most frequent waiting queries (N) -----------------------------------------\n\n";
		print $fh "Rank  Count    Total wait time (s)    Min/Max/Avg duration (s)    Query\n";
		for (my $i = 0 ; $i <= $#top_locked_queries; $i++) {
			last if ($i > $end_top);
			print $fh ($i + 1), ")   ", $top_locked_queries[$i]->[1], " - ", &convert_time($top_locked_queries[$i]->[2]),
			" - ", &convert_time($top_locked_queries[$i]->[3]), "/", &convert_time($top_locked_queries[$i]->[4]), "/",
			&convert_time(($top_locked_queries[$i]->[2] / $top_locked_queries[$i]->[1])),
			" - ", $top_locked_queries[$i]->[0], "\n";
			print $fh "--\n";
			my $k = $top_locked_queries[$i]->[0];
			my $j = 1;
			foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
				last if ($j > $sample);
				my $ttl = $top_locked_queries[$i]->[1] || '';
				my $db = '';
				$db .= " - $normalyzed_info{$curdb}{$k}{samples}{$d}{date} - database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
				$db .= ", user: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
				$db .= ", remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
				$db .= ", app: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
				$db .= ", queryid: $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
				$db .= ", bind query: yes" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
				$db =~ s/^, / - /;
				print $fh "\t- Example $j: ", &convert_time($d), "$db - ", &anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}), "\n";
				$j++;
			}
		}
		print $fh "\n";
		@top_locked_queries = ();

		# Queries that waited the most
		@{$top_locked_info{$curdb}} = sort {$b->[1] <=> $a->[1]} @{$top_locked_info{$curdb}};
		print $fh "\n- Queries that waited the mosts ---------------------------------------------\n\n";
		print $fh "Rank   Wait time (s)    Query\n";
		for (my $i = 0 ; $i <= $#{$top_locked_info{$curdb}} ; $i++) {
			my $ttl = $top_locked_info{$curdb}[$i]->[1] || '';
			my $db = '';
			$db .= " - database: $top_locked_info{$curdb}[$i]->[3]" if ($top_locked_info{$curdb}[$i]->[3]);
			$db .= ", user: $top_locked_info{$curdb}[$i]->[4]" if ($top_locked_info{$curdb}[$i]->[4]);
			$db .= ", remote: $top_locked_info{$curdb}[$i]->[5]" if ($top_locked_info{$curdb}[$i]->[5]);
			$db .= ", app: $top_locked_info{$curdb}[$i]->[6]" if ($top_locked_info{$curdb}[$i]->[6]);
			$db .= ", queryid: $top_locked_info{$curdb}[$i]->[7]" if ($top_locked_info{$curdb}[$i]->[7]);
			$db =~ s/^, / - /;
			print $fh ($i + 1), ")   ", &convert_time($top_locked_info{$curdb}[$i]->[0]),
			"  $ttl$db - ", &anonymize_query($top_locked_info{$curdb}[$i]->[2]), "\n";
			print $fh "--\n";
		}
		print $fh "\n";
	}

	# Show temporary files detailed information
	if (!$disable_temporary && scalar keys %{$tempfile_info{$curdb}} > 0) {

		my @top_temporary = ();
		foreach my $h (keys %{$normalyzed_info{$curdb}}) {
			if (exists($normalyzed_info{$curdb}{$h}{tempfiles})) {
				push (@top_temporary, [$h, $normalyzed_info{$curdb}{$h}{tempfiles}{count}, $normalyzed_info{$curdb}{$h}{tempfiles}{size},
				$normalyzed_info{$curdb}{$h}{tempfiles}{minsize}, $normalyzed_info{$curdb}{$h}{tempfiles}{maxsize}]);
			}
		}

		# Queries generating the most temporary files (N)
		@top_temporary = sort {$b->[1] <=> $a->[1]} @top_temporary;
		print $fh "\n- Queries generating the most temporary files (N) ---------------------------\n\n";
		print $fh "Rank   Count   Total size    Min/Max/Avg size    Query\n";
		my $idx = 1;
		for (my $i = 0 ; $i <= $#top_temporary ; $i++) {
			last if ($i > $end_top);
			print $fh $idx, ")   ",
			$top_temporary[$i]->[1], " - ", &comma_numbers($top_temporary[$i]->[2]),
			" - ", &comma_numbers($top_temporary[$i]->[3]),
			"/", &comma_numbers($top_temporary[$i]->[4]), "/",
			&comma_numbers(sprintf("%.2f", $top_temporary[$i]->[2] / $top_temporary[$i]->[1])),
			" - ", &anonymize_query($top_temporary[$i]->[0]), "\n";
			print $fh "--\n";
			my $k = $top_temporary[$i]->[0];
			if (scalar keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
				my $j = 1;
				foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
					last if ($j > $sample);
					my $db = '';
					$db .= "$normalyzed_info{$curdb}{$k}{samples}{$d}{date} - database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
					$db .= ", user: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
					$db .= ", remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
					$db .= ", app: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
					$db .= ", queryid: $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
					$db .= ", bind query: yes" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
					$db =~ s/^, / - /;
					print $fh "\t- Example $j: ", &convert_time($d), " - $db - ", &anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}), "\n";
					$j++;
				}
			}
			$idx++;
		}
		@top_temporary = ();

		# Top queries generating the largest temporary files
		@{$top_tempfile_info{$curdb}} = sort {$b->[1] <=> $a->[1]} @{$top_tempfile_info{$curdb}};

		print $fh "\n- Queries generating the largest temporary files ----------------------------\n\n";
		print $fh "Rank   Size    Query\n";
		for (my $i = 0 ; $i <= $#{$top_tempfile_info{$curdb}} ; $i++) {
			my $ttl = $top_tempfile_info{$curdb}[$i]->[1] || '';
			my $db = '';
			$db .= " - database: $top_tempfile_info{$curdb}[$i]->[3]" if ($top_tempfile_info{$curdb}[$i]->[3]);
			$db .= ", user: $top_tempfile_info{$curdb}[$i]->[4]" if ($top_tempfile_info{$curdb}[$i]->[4]);
			$db .= ", remote: $top_tempfile_info{$curdb}[$i]->[5]" if ($top_tempfile_info{$curdb}[$i]->[5]);
			$db .= ", app: $top_tempfile_info{$curdb}[$i]->[6]" if ($top_tempfile_info{$curdb}[$i]->[6]);
			$db .= ", info: $top_tempfile_info{$curdb}[$i]->[7]" if ($top_tempfile_info{$curdb}[$i]->[7]);
			$db .= ", queryid: $top_tempfile_info{$curdb}[$i]->[8]" if ($top_tempfile_info{$curdb}[$i]->[8]);
			$db =~ s/^, / - /;
			print $fh ($i + 1), ")   ", &comma_numbers($top_tempfile_info{$curdb}[$i]->[0]),
			" - $ttl$db - ", &anonymize_query($top_tempfile_info{$curdb}[$i]->[2]), "\n";
		}
		print $fh "\n";
	}

	# Show cancelled queries detailed information
	if (!$disable_query && scalar keys %{$cancelled_info{$curdb}} > 0) {

		my @top_cancelled = ();
		foreach my $h (keys %{$normalyzed_info{$curdb}}) {
			if (exists($normalyzed_info{$curdb}{$h}{cancelled})) {
				push (@top_cancelled, [$h, $normalyzed_info{$curdb}{$h}{cancelled}{count}]);
			}
		}

		# Queries generating the most cancelled files (N)
		@top_cancelled = sort {$b->[1] <=> $a->[1]} @top_cancelled;
		print $fh "\n- Queries most cancelled (N) ---------------------------\n\n";
		print $fh "Rank   Count   Query\n";
		my $idx = 1;
		for (my $i = 0 ; $i <= $#top_cancelled ; $i++) {
			last if ($i > $end_top);
			print $fh $idx, ")   ",
			$top_cancelled[$i]->[1], " - ", $top_cancelled[$i]->[0], "\n";
			print $fh "--\n";
			my $k = $top_cancelled[$i]->[0];
			if (scalar keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
				my $j = 1;
				foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
					last if ($j > $sample);
					my $db = '';
					$db .= "$normalyzed_info{$curdb}{$k}{samples}{$d}{date} - database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}" if ($normalyzed_info{$k}{samples}{$d}{db});
					$db .= ", user: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
					$db .= ", remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
					$db .= ", app: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
					$db .= ", queryid: $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
					$db .= ", bind query: yes" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
					$db =~ s/^, / - /;
					print $fh "\t- Example $j: ", &convert_time($d), " - $db - ", &anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}), "\n";
					$j++;
				}
			}
			$idx++;
		}
		@top_cancelled = ();

		# Top queries generating the largest cancelled files
		@{$top_cancelled_info{$curdb}} = sort {$b->[1] <=> $a->[1]} @{$top_cancelled_info{$curdb}};

		print $fh "\n- Queries generating the most cancellation ----------------------------\n\n";
		print $fh "Rank   Times cancelled    Query\n";
		for (my $i = 0 ; $i <= $#{$top_cancelled_info{$curdb}} ; $i++) {
			my $ttl = $top_cancelled_info{$curdb}[$i]->[1] || '';
			my $db = '';
			$db .= " - database: $top_cancelled_info{$curdb}[$i]->[3]" if ($top_cancelled_info{$curdb}[$i]->[3]);
			$db .= ", user: $top_cancelled_info{$curdb}[$i]->[4]" if ($top_cancelled_info{$curdb}[$i]->[4]);
			$db .= ", remote: $top_cancelled_info{$curdb}[$i]->[5]" if ($top_cancelled_info{$curdb}[$i]->[5]);
			$db .= ", app: $top_cancelled_info{$curdb}[$i]->[6]" if ($top_cancelled_info{$curdb}[$i]->[6]);
			$db .= ", queryid: $top_cancelled_info{$curdb}[$i]->[7]" if ($top_cancelled_info{$curdb}[$i]->[7]);
			$db =~ s/^, / - /;
			print $fh ($i + 1), ")   ", &comma_numbers($top_cancelled_info{$curdb}[$i]->[0]),
			" - $ttl$db - ", &anonymize_query($top_cancelled_info{$curdb}[$i]->[2]), "\n";
		}
		print $fh "\n";
	}

	# Show top information
	if (!$disable_query && ($#{$top_slowest{$curdb}} >= 0)) {
		print $fh "\n- Slowest queries ------------------------------------------------------\n\n";
		print $fh "Rank     Duration (s)     Query\n";
		for (my $i = 0 ; $i <= $#{$top_slowest{$curdb}} ; $i++) {
			my $db = '';
			$db .= " database: $top_slowest{$curdb}[$i]->[3]" if ($top_slowest{$curdb}[$i]->[3]);
			$db .= ", user: $top_slowest{$curdb}[$i]->[4]" if ($top_slowest{$curdb}[$i]->[4]);
			$db .= ", remote: $top_slowest{$curdb}[$i]->[5]" if ($top_slowest{$curdb}[$i]->[5]);
			$db .= ", app: $top_slowest{$curdb}[$i]->[6]" if ($top_slowest{$curdb}[$i]->[6]);
			$db .= ", queryid: $top_slowest{$curdb}[$i]->[9]" if ($top_slowest{$curdb}[$i]->[9]);
			$db .= ", bind query: yes" if ($top_slowest{$curdb}[$i]->[7]);
			$db =~ s/^, //;
			print $fh $i + 1, ") " . &convert_time($top_slowest{$curdb}[$i]->[0]) . "$db - " . &anonymize_query($top_slowest{$curdb}[$i]->[2]) . "\n";
			print $fh "--\n";
		}

		print $fh "\n- Queries that took up the most time (N) -------------------------------\n\n";
		print $fh "Rank     Total duration      Times executed     Min/Max/Avg duration (s)     Query\n";
		my $idx = 1;
		foreach my $k (sort {$normalyzed_info{$curdb}{$b}{duration} <=> $normalyzed_info{$curdb}{$a}{duration}} keys %{$normalyzed_info{$curdb}}) {
			next if (!$normalyzed_info{$curdb}{$k}{count});
			last if ($idx > $top);
			my $q = $k;
			if ($normalyzed_info{$curdb}{$k}{count} == 1) {
				foreach (keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
					$q = $normalyzed_info{$curdb}{$k}{samples}{$_}{query};
					last;
				}
			}
			$q = &anonymize_query($q);
			$normalyzed_info{$curdb}{$k}{average} = $normalyzed_info{$curdb}{$k}{duration} / $normalyzed_info{$curdb}{$k}{count};
			print $fh "$idx) "
				. &convert_time($normalyzed_info{$curdb}{$k}{duration}) . " - "
				. &comma_numbers($normalyzed_info{$curdb}{$k}{count}) . " - "
				. &convert_time($normalyzed_info{$curdb}{$k}{min}) . "/"
				. &convert_time($normalyzed_info{$curdb}{$k}{max}) . "/"
				. &convert_time($normalyzed_info{$curdb}{$k}{average})
				. " - $q\n";
			print $fh "--\n";
			my $j = 1;
			foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
				last if ($j > $sample);
				my $db = '';
				$db .= " - database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
				$db .= ", user: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
				$db .= ", remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
				$db .= ", app: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
				$db .= ", queryid: $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
				$db .= ", bind query: yes" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
				$db =~ s/^, / - /;
				print $fh "\t- Example $j: ", &convert_time($d), "$db - ", &anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}), "\n";
				$j++;
			}
			$idx++;
		}
	}

	if (!$disable_query && (scalar keys %{$normalyzed_info{$curdb}} > 0)) {
		print $fh "\n- Most frequent queries (N) --------------------------------------------\n\n";
		print $fh "Rank     Times executed     Total duration     Min/Max/Avg duration (s)     Query\n";
		my $idx = 1;
		foreach my $k (sort {$normalyzed_info{$curdb}{$b}{count} <=> $normalyzed_info{$curdb}{$a}{count}} keys %{$normalyzed_info{$curdb}}) {
			next if (!$normalyzed_info{$curdb}{$k}{count});
			last if ($idx > $top);
			my $q = $k;
			if ($normalyzed_info{$curdb}{$k}{count} == 1) {
				foreach (keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
					$q = $normalyzed_info{$curdb}{$k}{samples}{$_}{query};
					last;
				}
			}
			$q = &anonymize_query($q);
			print $fh "$idx) "
				. &comma_numbers($normalyzed_info{$curdb}{$k}{count}) . " - "
				. &convert_time($normalyzed_info{$curdb}{$k}{duration}) . " - "
				. &convert_time($normalyzed_info{$curdb}{$k}{min}) . "/"
				. &convert_time($normalyzed_info{$curdb}{$k}{max}) . "/"
				. &convert_time($normalyzed_info{$curdb}{$k}{duration} / $normalyzed_info{$curdb}{$k}{count})
				. " - $q\n";
			print $fh "--\n";
			my $i = 1;
			foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
				last if ($i > $sample);
				my $db = '';
				$db .= " - database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
				$db .= ", user: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
				$db .= ", remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
				$db .= ", app: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
				$db .= ", queryid: $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
				$db .= ", bind query: yes" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
				$db =~ s/^, / - /;
				print $fh "\tExample $i: ", &convert_time($d), "$db - ", &anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}), "\n";
				$i++;
			}
			$idx++;
		}
	}

	if (!$disable_query && ($#{$top_slowest{$curdb}} >= 0)) {
		print $fh "\n- Slowest queries (N) --------------------------------------------------\n\n";
		print $fh "Rank     Min/Max/Avg duration (s)     Times executed     Total duration     Query\n";
		my $idx = 1;
		foreach my $k (sort {$normalyzed_info{$curdb}{$b}{average} <=> $normalyzed_info{$curdb}{$a}{average}} keys %{$normalyzed_info{$curdb}}) {
			next if (!$normalyzed_info{$curdb}{$k}{count});
			last if ($idx > $top);
			my $q = $k;
			if ($normalyzed_info{$curdb}{$k}{count} == 1) {
				foreach (keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
					$q = $normalyzed_info{$curdb}{$k}{samples}{$_}{query};
					last;
				}
			}
			$q = &anonymize_query($q);
			print $fh "$idx) "
				. &convert_time($normalyzed_info{$curdb}{$k}{min}) . "/"
				. &convert_time($normalyzed_info{$curdb}{$k}{max}) . "/"
				. &convert_time($normalyzed_info{$curdb}{$k}{average}) . " - "
				. &comma_numbers($normalyzed_info{$curdb}{$k}{count}) . " - "
				. &convert_time($normalyzed_info{$curdb}{$k}{duration})
				. " - $q\n";
			print $fh "--\n";
			my $i = 1;
			foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
				last if ($i > $sample);
				my $db = '';
				$db .= " - database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
				$db .= ", user: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
				$db .= ", remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
				$db .= ", app: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
				$db .= ", queryid: $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
				$db .= ", bind query: yes" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{yes});
				$db =~ s/^, / - /;
				print $fh "\tExample $i: ", &convert_time($d), "$db - ", &anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}), "\n";
				$i++;
			}
			$idx++;
		}
	}
	@{$top_slowest{$curdb}} = ();

	if (!$disable_error) {
		&show_error_as_text($curdb);
	}


	# Show pgbouncer session per database statistics
	if (exists $pgb_session_info{database}) {
		print $fh "\n- pgBouncer sessions per database --------------------------------------------\n\n";
		print $fh "Database     Count     Total Duration     Avg duration (s)\n";
		foreach my $d (sort keys %{$pgb_session_info{database}}) {
			print $fh "$d - ", &comma_numbers($pgb_session_info{database}{$d}{count}), " ",
				&convert_time($pgb_session_info{database}{$d}{duration}), " ",
				&convert_time($pgb_session_info{database}{$d}{duration} / $pgb_session_info{database}{$d}{count}), "\n";
		}
	}

	# Show pgbouncer session per user statistics
	if (exists $pgb_session_info{user}) {
		print $fh "\n- pgBouncer sessions per user ------------------------------------------------\n\n";
		print $fh "User     Count     Total Duration     Avg duration (s)\n";
		foreach my $d (sort keys %{$pgb_session_info{user}}) {
			print $fh "$d - ", &comma_numbers($pgb_session_info{user}{$d}{count}), " ", &convert_time($pgb_session_info{user}{$d}{duration}),
				" ", &convert_time($pgb_session_info{user}{$d}{duration} / $pgb_session_info{user}{$d}{count}), "\n";
		}
	}

	# Show pgbouncer session per host statistics
	if (exists $pgb_session_info{host}) {
		print $fh "\n- pgBouncer sessions per host ------------------------------------------------\n\n";
		print $fh "User     Count     Total Duration     Avg duration (s)\n";
		foreach my $d (sort keys %{$pgb_session_info{host}}) {
			print $fh "$d - ", &comma_numbers($pgb_session_info{host}{$d}{count}), " ", &convert_time($pgb_session_info{host}{$d}{duration}),
				" ", &convert_time($pgb_session_info{host}{$d}{duration} / $pgb_session_info{host}{$d}{count}), "\n";
		}
	}

	# Show pgbouncer session per application statistics
	if (exists $pgb_session_info{app}) {
		print $fh "\n- pgBouncer sessions per application -----------------------------------------\n\n";
		print $fh "Application  Count     Total Duration     Avg duration (s)\n";
		foreach my $d (sort keys %{$pgb_session_info{app}}) {
			print $fh "$d - ", &comma_numbers($pgb_session_info{app}{$d}{count}), " ", &convert_time($pgb_session_info{app}{$d}{duration}),
				" ", &convert_time($pgb_session_info{app}{$d}{duration} / $pgb_session_info{app}{$d}{count}), "\n";
		}
	}


	# Show pgbouncer connection per database statistics
	if (exists $pgb_connection_info{database}) {
		print $fh "\n- pgBouncer connections per database -----------------------------------------\n\n";
		print $fh "Database     User     Count\n";
		foreach my $d (sort keys %{$pgb_connection_info{database}}) {
			print $fh "$d - ", &comma_numbers($pgb_connection_info{database}{$d}), "\n";
			foreach my $u (sort keys %{$pgb_connection_info{user}}) {
				next if (!exists $pgb_connection_info{database_user}{$d}{$u});
				print $fh "\t$u ", &comma_numbers($pgb_connection_info{database_user}{$d}{$u}), "\n";
			}
		}
		print $fh "\nDatabase     Host     Count\n";
		foreach my $d (sort keys %{$pgb_connection_info{database}}) {
			print $fh "$d - ", &comma_numbers($pgb_connection_info{database}{$d}), "\n";
			foreach my $u (sort keys %{$pgb_connection_info{host}}) {
				next if (!exists $pgb_connection_info{database_host}{$d}{$u});
				print $fh "\t$u ", &comma_numbers($pgb_connection_info{database_host}{$d}{$u}), "\n";
			}
		}
	}

	# Show pgbouncer connection per user statistics
	if (exists $pgb_connection_info{user}) {
		print $fh "\n- pgBouncer connections per user ---------------------------------------------\n\n";
		print $fh "User     Count\n";
		foreach my $d (sort keys %{$pgb_connection_info{user}}) {
			print $fh "$d - ", &comma_numbers($pgb_connection_info{user}{$d}), "\n";
		}
	}

	# Show pgbouncer connection per host statistics
	if (exists $pgb_connection_info{host}) {
		print $fh "\n- pgBouncer connections per host --------------------------------------------\n\n";
		print $fh "Host     Count\n";
		foreach my $d (sort keys %{$pgb_connection_info{host}}) {
			print $fh "$d - ", &comma_numbers($pgb_connection_info{host}{$d}), "\n";
		}
	}

	if (!$disable_error) {
		&show_pgb_error_as_text();
	}

	print $fh "\n\n";
	print $fh "Report generated by pgBadger $VERSION ($project_url).\n";

}

sub dump_error_as_text
{
	my $curdb = shift;

	# Global information
	my $curdate    = localtime(time);
	my $fmt_nlines = &comma_numbers($overall_stat{nlines}{$curdb});
	my $total_time = timestr($td);
	$total_time =~ s/^([\.0-9]+) wallclock.*/$1/;
	$total_time = &convert_time($total_time * 1000);
	my $logfile_str = $log_files[0];
	if ($#log_files > 0) {
		$logfile_str .= ', ..., ' . $log_files[-1];
	}
	$report_title ||= 'PostgreSQL Log Analyzer';

	# Set logs limits
	my ($t_log_min, $t_log_max) = get_log_limit($curdb);
	print $fh qq{
pgBadger :: $report_title

- Global information ---------------------------------------------------

Generated on $curdate
Log file: $logfile_str
Parsed $fmt_nlines log entries in $total_time
Log start from $t_log_min to $t_log_max
};

	&show_error_as_text($curdb);

	print $fh "\n\n";

	&show_pgb_error_as_text();

	print $fh "\n\n";

	print $fh "Report generated by pgBadger $VERSION ($project_url).\n";

}

# We change temporary log level from LOG to ERROR
# to store these messages into the error report
sub change_log_level
{
	my $msg = shift;

	return 1 if ($msg =~ /parameter "[^"]+" changed to "[^"]+"/);
	return 1 if ($msg =~ /database system was/);
	return 1 if ($msg =~ /recovery has paused/);
	return 1 if ($msg =~ /ending cancel to blocking autovacuum/);
	return 1 if ($msg =~ /skipping analyze of/);
	return 1 if ($msg =~ /using stale statistics/);
	return 1 if ($msg =~ /replication command:/);
	return 1 if ($msg =~ /still waiting for/);
	return 1 if ($msg =~ /server process.*was terminated by signal/);
	return 1 if ($msg =~ /could not (receive|send) data (from|to) client/);
	return 1 if ($msg =~ /logical decoding found consistent point at/);
	return 1 if ($msg =~ /starting logical decoding for slot/);
	return 1 if ($msg =~ /unexpected EOF/);
	return 1 if ($msg =~ /incomplete startup packet/);
	return 1 if ($msg =~ /detected deadlock while waiting for/);

	return 0;
}

sub revert_log_level
{
	my $msg = shift;

	return ($msg, 1) if ($msg =~ s/ERROR:  (parameter "[^"]+" changed to)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (database system was)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (recovery has paused)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (sending cancel to blocking autovacuum)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (skipping analyze of)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (using stale statistics)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (received replication command:)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (.*still waiting for)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (server process.*was terminated by signal)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (could not (?:receive|send) data (?:from|to) client)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (logical decoding found consistent point at)/LOG:  $1/);
	return ($msg, 1) if ($msg =~ s/ERROR:  (starting logical decoding for slot)/LOG:  $1/);

	return ($msg, 0);
}

sub show_error_as_text
{
	my $curdb = shift;

	return if (scalar keys %error_info == 0);

	print $fh "\n- Most frequent events (N) ---------------------------------------------\n\n";
	my $idx = 1;
	foreach my $k (sort {$error_info{$curdb}{$b}{count} <=> $error_info{$curdb}{$a}{count}} keys %{$error_info{$curdb}})
	{
		next if (!$error_info{$curdb}{$k}{count});
		last if ($idx > $top);
		last if (!$error_info{$curdb}{$k}{count});

		my ($msg, $ret) = &revert_log_level($k);
		if ($error_info{$curdb}{$k}{count} > 1)
		{
			print $fh "$idx) " . &comma_numbers($error_info{$curdb}{$k}{count}) . " - $msg\n";
			print $fh "--\n";
			my $j = 1;
			for (my $i = 0 ; $i <= $#{$error_info{$curdb}{$k}{date}} ; $i++)
			{
				next if ($i == $sample);
				print $fh "\t- Example $j: $error_info{$curdb}{$k}{date}[$i] - $error_info{$curdb}{$k}{error}[$i]\n";
				print $fh "\t\tDetail: $error_info{$curdb}{$k}{detail}[$i]\n"       if ($error_info{$curdb}{$k}{detail}[$i]);
				print $fh "\t\tContext: $error_info{$curdb}{$k}{context}[$i]\n"     if ($error_info{$curdb}{$k}{context}[$i]);
				print $fh "\t\tHint: $error_info{$curdb}{$k}{hint}[$i]\n"	   if ($error_info{$curdb}{$k}{hint}[$i]);
				print $fh "\t\tStatement: ", &anonymize_query($error_info{$curdb}{$k}{statement}[$i]), "\n" if ($error_info{$curdb}{$k}{statement}[$i]);
				print $fh "\t\tQueryid: $error_info{$curdb}{$k}{queryid}[$i]\n" if ($error_info{$curdb}{$k}{queryid}[$i]);
				print $fh "\t\tDatabase: $error_info{$curdb}{$k}{db}[$i]\n" if ($error_info{$curdb}{$k}{db}[$i]);
				$j++;
			}
		}
		elsif ($error_info{$curdb}{$k}{error}[0])
		{
			($msg, $ret) = &revert_log_level($error_info{$curdb}{$k}{error}[0]);
			if ($sample)
			{
				print $fh "$idx) " . &comma_numbers($error_info{$curdb}{$k}{count}) . " - $error_info{$curdb}{$k}{error}[0]\n";
				print $fh "--\n";
				print $fh "\t- Date: $error_info{$curdb}{$k}{date}[0]\n";
				print $fh "\t\tDetail: $error_info{$curdb}{$k}{detail}[0]\n"       if ($error_info{$curdb}{$k}{detail}[0]);
				print $fh "\t\tContext: $error_info{$curdb}{$k}{context}[0]\n"     if ($error_info{$curdb}{$k}{context}[0]);
				print $fh "\t\tHint: $error_info{$curdb}{$k}{hint}[0]\n"	   if ($error_info{$curdb}{$k}{hint}[0]);
				print $fh "\t\tStatement: ", &anonymize_query($error_info{$curdb}{$k}{statement}[0]), "\n" if ($error_info{$curdb}{$k}{statement}[0]);
				print $fh "\t\tQueryid: $error_info{$curdb}{$k}{queryid}[0]\n" if ($error_info{$curdb}{$k}{queryid}[0]);
				print $fh "\t\tDatabase: $error_info{$curdb}{$k}{db}[0]\n" if ($error_info{$curdb}{$k}{db}[0]);
			}
			else
			{
				print $fh "$idx) " . &comma_numbers($error_info{$curdb}{$k}{count}) . " - $msg\n";
				print $fh "--\n";
			}
		}
		$idx++;
	}

	if (scalar keys %{$logs_type{$curdb}} > 0)
	{
		print $fh "\n- Logs per type ---------------------------------------------\n\n";

		my $total_logs = 0;
		foreach my $d (keys %{$logs_type{$curdb}}) {
			$total_logs += $logs_type{$curdb}{$d};
		}
		print $fh "Logs type	Count	Percentage\n";
		foreach my $d (sort keys %{$logs_type{$curdb}})
		{
			next if (!$logs_type{$curdb}{$d});
			print $fh "$d\t\t", &comma_numbers($logs_type{$curdb}{$d}), "\t", sprintf("%0.2f", ($logs_type{$curdb}{$d} * 100) / $total_logs), "%\n";
		}
	}

	if (scalar keys %{$errors_code{$curdb}} > 0)
	{
		print $fh "\n- Logs per type ---------------------------------------------\n\n";

		my $total_logs = 0;
		foreach my $d (keys %{$errors_code{$curdb}}) {
			$total_logs += $errors_code{$curdb}{$d};
		}
		print $fh "Errors class			code	Count	Percentage\n";
		foreach my $d (sort keys %{$errors_code{$curdb}})
		{
			next if (!$errors_code{$curdb}{$d});
			print $fh "$CLASS_ERROR_CODE{$d}\t$d\t\t", &comma_numbers($errors_code{$curdb}{$d}), "\t", sprintf("%0.2f", ($errors_code{$curdb}{$d} * 100) / $total_logs), "%\n";
		}
	}

}

sub show_pgb_error_as_text
{
	return if (scalar keys %pgb_error_info == 0);

	print $fh "\n- Most frequent events (N) ---------------------------------------------\n\n";
	my $idx = 1;
	foreach my $k (sort {$pgb_error_info{$b}{count} <=> $pgb_error_info{$a}{count}} keys %pgb_error_info)
	{
		next if (!$pgb_error_info{$k}{count});
		last if ($idx > $top);
		my $msg = $k;
		if ($pgb_error_info{$k}{count} > 1)
		{
			print $fh "$idx) " . &comma_numbers($pgb_error_info{$k}{count}) . " - $msg\n";
			print $fh "--\n";
			my $j = 1;
			for (my $i = 0 ; $i <= $#{$pgb_error_info{$k}{date}} ; $i++)
			{
				last if ($i == $sample);
				print $fh "\t- Example $j: $pgb_error_info{$k}{date}[$i] - $pgb_error_info{$k}{error}[$i]\n";
				print $fh "\t\tDatabase: $pgb_error_info{$k}{db}[$i]\n" if ($pgb_error_info{$k}{db}[$i]);
				print $fh "\t\tUser: $pgb_error_info{$k}{user}[$i]\n" if ($pgb_error_info{$k}{user}[$i]);
				print $fh "\t\tClient: $pgb_error_info{$k}{remote}[$i]\n" if ($pgb_error_info{$k}{remote}[$i]);
				$j++;
			}
		}
		else
		{
			if ($sample)
			{
				print $fh "$idx) " . &comma_numbers($pgb_error_info{$k}{count}) . " - $pgb_error_info{$k}{error}[0]\n";
				print $fh "--\n";
				print $fh "\t- Date: $pgb_error_info{$k}{date}[0]\n";
				print $fh "\t\tDatabase: $pgb_error_info{$k}{db}[0]\n" if ($pgb_error_info{$k}{db}[0]);
				print $fh "\t\tUser: $pgb_error_info{$k}{user}[0]\n" if ($pgb_error_info{$k}{user}[0]);
				print $fh "\t\tClient: $pgb_error_info{$k}{remote}[0]\n" if ($pgb_error_info{$k}{remote}[0]);
			}
			else
			{
				print $fh "$idx) " . &comma_numbers($pgb_error_info{$k}{count}) . " - $msg\n";
				print $fh "--\n";
			}
		}
		$idx++;
	}
}

sub html_header
{
	my $uri = shift;
	my $curdb = shift;

	my $date = localtime(time);
	my $global_info = &print_global_information($curdb);

	my @tmpjscode = @jscode;
	my $path_prefix = '';
	$path_prefix = '../' if ($report_per_database);
	for (my $i = 0; $i <= $#tmpjscode; $i++) {
		$tmpjscode[$i] =~ s/EDIT_URI/$path_prefix$uri/;
	}

	my $local_title = 'PostgreSQL Log Analyzer';
	if ($report_title) {
		$local_title = $report_title;
	}
	$report_title ||= 'pgBadger';

	print $fh qq{<!DOCTYPE html>
<html lang="en">
<head>
<title>pgBadger :: $local_title</title>
<meta http-equiv="Content-Type" content="text/html; charset=$charset" />
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="Expires" content="$date">
<meta http-equiv="Generator" content="pgBadger v$VERSION">
<meta http-equiv="Date" content="$date">
<link rel="shortcut icon" href="$pgbadger_ico" />
@tmpjscode
</head>
<body>
$EXPLAIN_POST
<div class="navbar navbar-inverse navbar-fixed-top">
    <div class="container-fluid">
	<div class="navbar-header">
	<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
	  <span class="icon-bar"></span>
	  <span class="icon-bar"></span>
	  <span class="icon-bar"></span>
	</button>
	<a data-placement="bottom" rel="tooltip" data-original-title="PostgreSQL Log Analyzer" href="" id="pgbadger-brand" class="navbar-brand">$pgbadger_logo $report_title</a>
	</div>
	<div class="collapse navbar-collapse">
	<ul class="nav navbar-nav" id="navigation">
};
	if (!$error_only && !$pgbouncer_only) {
		print $fh qq{
     		<li id="menu-overview" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Overview <span class="caret"></span></a>
			<ul class="dropdown-menu">
				<li><a href="#global-stats">Global Stats</a></li>
};
		if (!$disable_hourly) {
			print $fh qq{
				<li><a href="#sql-traffic">SQL Traffic</a></li>
				<li><a href="#select-traffic">Select Traffic</a></li>
				<li><a href="#write-traffic">Write Traffic</a></li>
				<li><a href="#duration-traffic">Queries duration</a></li>
				<li><a href="#prepared-queries-ratio">Prepared queries ratio</a></li>
				<li><a href="#general-activity">General Activity</a></li>
};
		}
		print $fh qq{
	  		</ul>
		</li>
};
		if (!$disable_connection) {
			print $fh qq{
     		<li id="menu-connections" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Connections <span class="caret"></span></a>
     			<ul class="dropdown-menu">
};
			if (!$disable_hourly) {
				print $fh qq{
     				<li><a href="#established-connections">Established connections</a></li>
};
			}
			print $fh qq{
     				<li><a href="#connections-per-database">Connections per database</a></li>
     				<li><a href="#connections-per-user">Connections per user</a></li>
     				<li><a href="#connections-per-host">Connections per host</a></li>
     			</ul>
     		</li>
};
		}

		if (!$disable_session) {
			print $fh qq{
     		<li id="menu-sessions" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Sessions <span class="caret"></span></a>
     			<ul class="dropdown-menu">
};
			if (!$disable_hourly) {
				print $fh qq{
     				<li><a href="#simultaneous-sessions">Simultaneous sessions</a></li>
};
			}
			print $fh qq{
     				<li><a href="#histogram-session-times">Histogram of sessions times</a></li>
     				<li><a href="#sessions-per-database">Sessions per database</a></li>
     				<li><a href="#sessions-per-user">Sessions per user</a></li>
     				<li><a href="#sessions-per-host">Sessions per host</a></li>
     				<li><a href="#sessions-per-app">Sessions per application</a></li>
     			</ul>
     		</li>
};
		}
		if (!$disable_checkpoint && (!$report_per_database || $curdb eq $DBALL)) {
			print $fh qq{
     		<li id="menu-checkpoints" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Checkpoints <span class="caret"></span></a>
     			<ul class="dropdown-menu">
     				<li><a href="#checkpoints-buffers">Checkpoints buffers</a></li>
     				<li><a href="#checkpoints-files">Checkpoints files</a></li>
     				<li><a href="#checkpoints-distance">Checkpoints distance</a></li>
     				<li><a href="#checkpoint-activity">Checkpoint activity</a></li>
     				<li><a href="#checkpoints-cause">Checkpoint causes</a></li>
     			</ul>
     		</li>
};
		}

		if (!$disable_temporary) {
			print $fh qq{
     		<li id="menu-tempfiles" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Temp Files <span class="caret"></span></a>
     			<ul class="dropdown-menu">
     				<li><a href="#tempfiles-size">Size of temporary files</a></li>
     				<li><a href="#tempfiles-number">Number of temporary files</a></li>
     				<li><a href="#tempfiles-activity">Temporary files activity</a></li>
				<li class="divider"></li>
     				<li><a href="#queries-generating-most-temporary-files">Queries generating the most files (N)</a></li>
     				<li><a href="#queries-generating-largest-temporary-files">Queries generating the largest files</a></li>
     			</ul>
		</li>
};
		}
		if (!$disable_autovacuum) {
			print $fh qq{
     		<li id="menu-vacuums" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Vacuums <span class="caret"></span></a>
     			<ul class="dropdown-menu">
     				<li><a href="#vacuums-count">Vacuums distribution</a></li>
     				<li><a href="#vacuums-activity">Vacuums activity</a></li>
     				<li><a href="#analyzes-per-table">Analyzes per Tables</a></li>
     				<li><a href="#vacuums-per-table">Vacuums per Tables</a></li>
     				<li><a href="#tuples-removed-per-table">Tuples removed</a></li>
     				<li><a href="#pages-removed-per-table">Page removed</a></li>
     			</ul>
		</li>
};
		}
		if (!$disable_lock) {
			print $fh qq{
     		<li id="menu-locks" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Locks <span class="caret"></span></a>
     			<ul class="dropdown-menu">
     				<li><a href="#locks-type">Locks by type</a></li>
				<li class="divider"></li>
     				<li><a href="#queries-most-frequent-waiting">Most frequent waiting queries (N)</a></li>
     				<li><a href="#queries-that-waited-most">Queries that waited the most</a></li>
     			</ul>
		</li>
};
		}
		if (!$disable_query) {
			if (!$disable_type) {
				print $fh qq{
     		<li id="menu-queries" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Queries <span class="caret"></span></a>
     			<ul class="dropdown-menu">
     				<li><a href="#queries-by-type">Queries by type</a></li>
     				<li><a href="#queries-by-database">Queries by database</a></li>
     				<li><a href="#queries-by-user">Queries by user</a></li>
     				<li><a href="#duration-by-user">Duration by user</a></li>
     				<li><a href="#queries-by-host">Queries by host</a></li>
     				<li><a href="#queries-by-application">Queries by application</a></li>
				<li class="divider"></li>
     				<li><a href="#queries-cancelled-number">Number of cancelled queries</a></li>
};
				if ($#{$top_cancelled_info{$curdb}} >= 0) {
					print $fh qq{
     				<li><a href="#queries-generating-most-cancellation">Queries generating the most cancellation (N)</a></li>
     				<li><a href="#queries-generating-most-cancelled">Most cancelled queries</a></li>
};
				}
				print $fh qq{
     			</ul>
     		</li>
};
			}
			print $fh qq{
     		<li id="menu-topqueries" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Top <span class="caret"></span></a>
     			<ul class="dropdown-menu">
     				<li><a href="#histogram-query-times">Histogram of query times</a></li>
     				<li><a href="#slowest-individual-queries">Slowest individual queries</a></li>
     				<li><a href="#time-consuming-queries">Time Consuming queries (N)</a></li>
     				<li><a href="#most-frequent-queries">Most frequent queries (N)</a></li>
     				<li><a href="#normalized-slowest-queries">Normalized slowest queries</a></li>
     				<li><a href="#time-consuming-prepare">Time consuming prepare</a></li>
     				<li><a href="#time-consuming-bind">Time consuming bind</a></li>
     			</ul>
     		</li>
};
		}
	}
	if (!$disable_error && !$pgbouncer_only) {
		my $sqlstate_report = '';
		$sqlstate_report = '<li><a href="#error-code">Error class distribution</a></li>' if (scalar keys %{$errors_code{$curdb}} > 0);
		print $fh qq{
     		<li id="menu-events" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Events <span class="caret"></span></a>
     			<ul class="dropdown-menu">
     				<li><a href="#log-levels">Log levels</a></li>
     				<li><a href="#minutes-errors-levels">Events distribution</a></li>
				$sqlstate_report
				<li class="divider"></li>
     				<li><a href="#most-frequent-errors-events">Most frequent errors/events</a></li>
     			</ul>
     		</li>
};
	}

	if (exists $pgb_overall_stat{peak}) {
		print $fh qq{
     		<li id="menu-pgbouncer" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">PgBouncer <span class="caret"></span></a>
     			<ul class="dropdown-menu">
};
		if (!$disable_hourly) {
			print $fh qq{
     				<li><a href="#pgbsql-traffic">Request Throughput</a></li>
     				<li><a href="#pgbbytes-traffic">Bytes I/O Throughput</a></li>
     				<li><a href="#pgbduration-traffic">Average Query Duration</a></li>
				<li class="divider"></li>
     				<li><a href="#pgbsimultaneous-sessions">Simultaneous sessions</a></li>
};
		}
		print $fh qq{
     				<li><a href="#pgbhistogram-session-times">Histogram of sessions times</a></li>
     				<li><a href="#pgbsessions-per-database">Sessions per database</a></li>
     				<li><a href="#pgbsessions-per-user">Sessions per user</a></li>
     				<li><a href="#pgbsessions-per-host">Sessions per host</a></li>
				<li class="divider"></li>
};
		if (!$disable_hourly) {
			print $fh qq{
     				<li><a href="#pgbestablished-connections">Established connections</a></li>
};
		}
		print $fh qq{
     				<li><a href="#pgbconnections-per-database">Connections per database</a></li>
     				<li><a href="#pgbconnections-per-user">Connections per user</a></li>
     				<li><a href="#pgbconnections-per-host">Connections per host</a></li>
				<li class="divider"></li>
     				<li><a href="#pgbmost-used-reserved-pool">Most used reserved pools</a></li>
     				<li><a href="#pgbmost-frequent-errors-events">Most Frequent Errors/Events</a></li>
     			</ul>
     		</li>
};
	}

	print $fh qq{
		<li id="menu-info" class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#global-stats"><i class="glyphicon icon-info-sign icon-large"></i></a>
		</li>
     	</ul>
	</div>
    </div>
</div>

<div class="container" id="main-container">

	<ul id="slides">

	<li class="slide" id="info-slide">

	    <div class="row analysis-item" id="global-info">
		<h2 class="col-md-12"><i class="glyphicon icon-info-sign"></i> Global information</h2>
		<div class="tab-content">
			<div class="tab-pane active" id="tab-info">
			$global_info
			</div>
		</div>
	    </div>
	</li>

};

}

sub html_footer
{
	print $fh qq{
		</li>
	</ul> <!-- end of slides -->

  <!-- Modal -->
  <div class="modal fade" id="pgbadgerModal">
    <div class="modal-dialog">

      <!-- Modal content-->
      <div class="modal-content">
	<div class="modal-header">
	  <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
	  <h4 class="modal-title">Right click + "Save image as ..." to save the graph as PNG image</h4>
	</div>
	<div class="modal-body">
	  <img src="" />
	</div>
	<div class="modal-footer">
	  <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
	</div>
      </div>

    </div>
  </div>

</div> <!-- End of main-container -->

<footer>
<div class="">
	<small class="pull-right">Report generated by <a href="$project_url" target="_new">pgBadger $VERSION.</a></small>
</div>
</footer>

<div id="littleToc">
	<div id="littleTocTitle"><a href="#top">&nbsp;^&nbsp;</a></div>
</div>

</body>
</html>
};

}


# Create global information section
sub print_global_information
{
	my $curdb = shift();

	my $curdate    = localtime(time);
	my $fmt_nlines = &comma_numbers($overall_stat{nlines}{$curdb});
	my $t3 = Benchmark->new;
	my $td = timediff($t3, $t0);
	my $total_time = timestr($td);
	$total_time =~ s/^([\.0-9]+) wallclock.*/$1/;
	$total_time = &convert_time($total_time * 1000);
	my $logfile_str = $log_files[0];
	if ($#log_files > 0) {
		$logfile_str .= ', ..., ' . $log_files[-1];
	}

	# Set logs limits
	my ($t_log_min, $t_log_max) = get_log_limit($curdb);
	return qq{
<ul>
<li>Generated on $curdate</li>
<li>Log file: $logfile_str</li>
<li>Parsed $fmt_nlines log entries in $total_time</li>
<li>Log start from $t_log_min to $t_log_max</li>
</ul>
};

}

sub print_overall_statistics
{
	my $curdb = shift();

	my $fmt_unique  = &comma_numbers(scalar keys %{$normalyzed_info{$curdb}});
	my $fmt_queries = &comma_numbers($overall_stat{$curdb}{'queries_number'});
	my $avg_queries = &comma_numbers(int($overall_stat{$curdb}{'queries_number'}/($session_info{$curdb}{count} || 1)));
	my $q_duration = ($overall_stat{$curdb}{'queries_duration'}{'execute'}||0)+($overall_stat{$curdb}{'queries_duration'}{'prepare'}||0)+($overall_stat{$curdb}{'queries_duration'}{'bind'}||0);
	my $fmt_duration_prepare = &convert_time($overall_stat{$curdb}{'queries_duration'}{'prepare'}||0);
	my $fmt_duration_bind = &convert_time($overall_stat{$curdb}{'queries_duration'}{'bind'}||0);
	my $fmt_duration_execute = &convert_time($overall_stat{$curdb}{'queries_duration'}{'execute'}||0);
	my $fmt_duration = &convert_time($q_duration);
	$overall_stat{$curdb}{'first_query_ts'} ||= '-';
	$overall_stat{$curdb}{'last_query_ts'} ||= '-';
	my $query_peak = 0;
	my $query_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{query} <=> $overall_stat{$curdb}{'peak'}{$a}{query}} keys %{$overall_stat{$curdb}{'peak'}}) {
		$query_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{query});
		$query_peak_date = $_ if ($query_peak);
		last;
	}
	my $avg_duration = &convert_time(int($q_duration/($session_info{$curdb}{count} || 1)));
	my $fmt_errors = &comma_numbers($overall_stat{$curdb}{'errors_number'});
	my $fmt_unique_error = &comma_numbers(scalar keys %{$error_info{$curdb}});
	my $autovacuum_count = &comma_numbers($autovacuum_info{$curdb}{count});
	my $autoanalyze_count = &comma_numbers($autoanalyze_info{$curdb}{count});
	my $tempfile_count = &comma_numbers($tempfile_info{$curdb}{count});
	my $cancelled_count = &comma_numbers($cancelled_info{$curdb}{count});
	my $fmt_temp_maxsise = &pretty_print_size($tempfile_info{$curdb}{maxsize});
	my $fmt_temp_avsize = &pretty_print_size(sprintf("%.2f", $tempfile_info{$curdb}{size} / ($tempfile_info{$curdb}{count} || 1)));
	my $session_count = &comma_numbers($session_info{$curdb}{count});
	my $avg_session_duration = &convert_time($session_info{$curdb}{duration} / ($session_info{$curdb}{count} || 1));
	my $tot_session_duration = &convert_time($session_info{$curdb}{duration});
	my $connection_count = &comma_numbers($connection_info{$curdb}{count});
	my $avg_idle_time = &convert_time( ($session_info{$curdb}{duration} - $q_duration) / ($session_info{$curdb}{count} || 1));
	$avg_idle_time = 'n/a' if (!$session_info{$curdb}{count});
	my $connection_peak = 0;
	my $connection_peak_date = '';
	my $session_peak = 0;
	my $session_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{connection} <=> $overall_stat{$curdb}{'peak'}{$a}{connection}} keys %{$overall_stat{$curdb}{'peak'}}) {
		$connection_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{connection});
		$connection_peak_date = $_ if ($connection_peak);
		last;
	}
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{session} <=> $overall_stat{$curdb}{'peak'}{$a}{session}} keys %{$overall_stat{$curdb}{'peak'}}) {
		next if (!$session_count);
		$session_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{session});
		$session_peak_date = $_ if ($session_peak);
		last;
	}
	my $main_error = 0;
	my $total = 0;
	foreach my $k (sort {$error_info{$curdb}{$b}{count} <=> $error_info{$curdb}{$a}{count}} keys %{$error_info{$curdb}}) {
		next if (!$error_info{$curdb}{$k}{count});
		$main_error = &comma_numbers($error_info{$curdb}{$k}{count}) if (!$main_error);
		$total += $error_info{$curdb}{$k}{count};
	}
	$total = &comma_numbers($total);

	my $db_count = scalar keys %{$database_info{$curdb}};
	print $fh qq{
	    <h1 class="page-header"><i class="glyphicon icon-eye-open"></i> Overview</h1>

	    <div class="row analysis-item" id="global-stats">
		<h2 class="col-md-12"><i class="glyphicon icon-dashboard"></i> Global Stats</h2>
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#tab-queries" data-toggle="tab"><i class="glyphicon icon-question-sign"></i> Queries</a></li>
					<li><a href="#tab-durations" data-toggle="tab"><i class="glyphicon icon-time"></i> Durations</a></li>
					<li><a href="#tab-events" data-toggle="tab"><i class="glyphicon icon-bullhorn"></i> Events</a></li>
					<li><a href="#tab-vacuums" data-toggle="tab"><i class="glyphicon icon-cogs"></i> Vacuums</a></li>
					<li><a href="#tab-tempfiles" data-toggle="tab"><i class="glyphicon icon-file"></i> Temporary files</a></li>
					<li><a href="#tab-sessions" data-toggle="tab"><i class="glyphicon icon-off"></i> Sessions</a></li>
					<li><a href="#tab-connections" data-toggle="tab"><i class="glyphicon icon-external-link-sign"></i> Connections</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="tab-queries">
						<ul>
							<li class="first"><span class="figure">$fmt_unique</span> <span class="figure-label">Number of unique normalized queries</span></li>
							<li><span class="figure">$fmt_queries</span> <span class="figure-label">Number of queries</span></li>
							<li><span class="figure">$fmt_duration</span> <span class="figure-label">Total query duration</span></li>
							<li><span class="figure">$overall_stat{$curdb}{'first_query_ts'}</span> <span class="figure-label">First query</span></li>
							<li><span class="figure">$overall_stat{$curdb}{'last_query_ts'}</span> <span class="figure-label">Last query</span></li>
							<li><span class="figure">$query_peak queries/s at $query_peak_date</span> <span class="figure-label">Query peak</span></li>
						</ul>
					</div>
					<div class="tab-pane" id="tab-durations">
						<ul>
							<li class="first"><span class="figure">$fmt_duration</span> <span class="figure-label">Total query duration</span></li>
							<li><span class="figure">$fmt_duration_prepare</span> <span class="figure-label">Prepare/parse total duration</span></li>
							<li><span class="figure">$fmt_duration_bind</span> <span class="figure-label">Bind total duration</span></li>
							<li><span class="figure">$fmt_duration_execute</span> <span class="figure-label">Execute total duration</span></li>
						</ul>
					</div>
					<div class="tab-pane" id="tab-events">
						<ul>
							<li class="first"><span class="figure">$fmt_errors</span> <span class="figure-label">Number of events</span></li>
							<li><span class="figure">$fmt_unique_error</span> <span class="figure-label">Number of unique normalized events</span></li>
							<li><span class="figure">$main_error</span> <span class="figure-label">Max number of times the same event was reported</span></li>
							<li><span class="figure">$cancelled_count</span> <span class="figure-label">Number of cancellation</span></li>
						</ul>
					</div>
					<div class="tab-pane" id="tab-vacuums">
						<ul>
							<li class="first"><span class="figure">$autovacuum_count</span> <span class="figure-label">Total number of automatic vacuums</span></li>
							<li><span class="figure">$autoanalyze_count</span> <span class="figure-label">Total number of automatic analyzes</span></li>
						</ul>
					</div>
					<div class="tab-pane" id="tab-tempfiles">
						<ul>
							<li class="first"><span class="figure">$tempfile_count</span> <span class="figure-label">Number temporary file</span></li>
							<li><span class="figure">$fmt_temp_maxsise</span> <span class="figure-label">Max size of temporary file</span></li>
							<li><span class="figure">$fmt_temp_avsize</span> <span class="figure-label">Average size of temporary file</span></li>
						</ul>
					</div>
					<div class="tab-pane" id="tab-sessions">
						<ul>
							<li class="first"><span class="figure">$session_count</span> <span class="figure-label">Total number of sessions</span></li>
							<li><span class="figure">$session_peak sessions at $session_peak_date</span> <span class="figure-label">Session peak</span></li>
							<li><span class="figure">$tot_session_duration</span> <span class="figure-label">Total duration of sessions</span></li>
							<li><span class="figure">$avg_session_duration</span> <span class="figure-label">Average duration of sessions</span></li>
							<li><span class="figure">$avg_queries</span> <span class="figure-label">Average queries per session</span></li>
							<li><span class="figure">$avg_duration</span> <span class="figure-label">Average queries duration per session</span></li>
							<li><span class="figure">$avg_idle_time</span> <span class="figure-label">Average idle time per session</span></li>

						</ul>
					</div>
					<div class="tab-pane" id="tab-connections">
						<ul>
							<li class="first"><span class="figure">$connection_count</span> <span class="figure-label">Total number of connections</span></li>
};
	if ($connection_count) {
		print $fh qq{
							<li><span class="figure">$connection_peak connections/s at $connection_peak_date</span> <span class="figure-label">Connection peak</span></li>
};
	}
	print $fh qq{
							<li><span class="figure">$db_count</span> <span class="figure-label">Total number of databases</span></li>
						</ul>
					</div>
				</div> <!-- end div tab-content -->
			</div> <!-- end div tabbable -->
		</div> <!-- end div global-stats -->
};

}

sub print_general_activity
{
	my $curdb = shift;

	my $queries = '';
	my $select_queries = '';
	my $write_queries = '';
	my $prepared_queries = '';
	my $connections = '';
	my $sessions = '';
	foreach my $d (sort {$a <=> $b} keys %{$per_minute_info{$curdb}})
	{
		my $c = 1;
		$d =~ /^\d{4}(\d{2})(\d{2})$/;
		my $zday = "$abbr_month{$1} $2";
		foreach my $h (sort {$a <=> $b} keys %{$per_minute_info{$curdb}{$d}})
		{
			my %cur_period_info = ();
			my $read_average_duration = 0;
			my $read_average_count = 0;
			my $write_average_duration = 0;
			my $write_average_count = 0;
			my %all_query_duration=();
			foreach my $m (keys %{$per_minute_info{$curdb}{$d}{$h}})
			{
				$cur_period_info{$curdb}{count} += ($per_minute_info{$curdb}{$d}{$h}{$m}{query}{count} || 0);
				$cur_period_info{$curdb}{duration} += ($per_minute_info{$curdb}{$d}{$h}{$m}{query}{duration} || 0);
				$cur_period_info{$curdb}{min} = $per_minute_info{$curdb}{$d}{$h}{$m}{query}{min} if (!exists $cur_period_info{$curdb}{min} || ($per_minute_info{$curdb}{$d}{$h}{$m}{query}{min} < $cur_period_info{$curdb}{min}));
				$cur_period_info{$curdb}{max} = $per_minute_info{$curdb}{$d}{$h}{$m}{query}{max} if (!exists $cur_period_info{$curdb}{max} || ($per_minute_info{$curdb}{$d}{$h}{$m}{query}{max} > $cur_period_info{$curdb}{max}));
				push(@{$all_query_duration{'query'}}, $per_minute_info{$curdb}{$d}{$h}{$m}{query}{duration}||0);

				foreach my $a (@SQL_ACTION)
				{
					$cur_period_info{$curdb}{$a}{count} += ($per_minute_info{$curdb}{$d}{$h}{$m}{lc($a)}{count} || 0);
					$cur_period_info{$curdb}{$a}{duration} += ($per_minute_info{$curdb}{$d}{$h}{$m}{lc($a)}{duration} || 0);
					push(@{$all_query_duration{$a}}, $per_minute_info{$curdb}{$d}{$h}{$m}{lc($a)}{duration}||0);
					$cur_period_info{$curdb}{usual} += ($per_minute_info{$curdb}{$d}{$h}{$m}{lc($a)}{count} || 0);
				}
				$cur_period_info{$curdb}{prepare} += ($per_minute_info{$curdb}{$d}{$h}{$m}{prepare} || 0);
				$cur_period_info{$curdb}{execute} += ($per_minute_info{$curdb}{$d}{$h}{$m}{execute} || 0);
			}

			$cur_period_info{$curdb}{average} = $cur_period_info{$curdb}{duration} / ($cur_period_info{$curdb}{count} || 1);

			$read_average_duration = ($cur_period_info{$curdb}{'SELECT'}{duration} +
					$cur_period_info{$curdb}{'COPY TO'}{duration});
			$read_average_count = ($cur_period_info{$curdb}{'SELECT'}{count} +
					$cur_period_info{$curdb}{'COPY TO'}{count});
			$cur_period_info{$curdb}{'SELECT'}{average} = $cur_period_info{$curdb}{'SELECT'}{duration} / ($cur_period_info{$curdb}{'SELECT'}{count} || 1);
			$write_average_duration = ($cur_period_info{$curdb}{'INSERT'}{duration} +
					$cur_period_info{$curdb}{'UPDATE'}{duration} +
					$cur_period_info{$curdb}{'DELETE'}{duration} +
					$cur_period_info{$curdb}{'COPY FROM'}{duration});
			$write_average_count = ($cur_period_info{$curdb}{'INSERT'}{count} +
					$cur_period_info{$curdb}{'UPDATE'}{count} +
					$cur_period_info{$curdb}{'DELETE'}{count} +
					$cur_period_info{$curdb}{'COPY FROM'}{count});
			$zday = "&nbsp;" if ($c > 1);
			$c++;

			my $count = &comma_numbers($cur_period_info{$curdb}{count});
			my $min = &convert_time($cur_period_info{$curdb}{min});
			my $max = &convert_time($cur_period_info{$curdb}{max});
			my $average = &convert_time($cur_period_info{$curdb}{average});
			my %percentile =  ();
			foreach my $lp (@LATENCY_PERCENTILE) {
				$cur_period_info{$curdb}{$lp}{percentileindex} = int(@{$all_query_duration{'query'}} * $lp / 100) ;
				@{$all_query_duration{'query'}}= sort{ $a <=> $b } @{$all_query_duration{'query'}};
				$cur_period_info{$curdb}{$lp}{percentile} = $all_query_duration{'query'}[$cur_period_info{$curdb}{$lp}{percentileindex}];
				$percentile{$lp} =  &convert_time($cur_period_info{$curdb}{$lp}{percentile});

				@{$all_query_duration{'READ'}}= sort{ $a <=> $b } (@{$all_query_duration{'SELECT'}}, @{$all_query_duration{'COPY TO'}});
				$cur_period_info{$curdb}{'READ'}{$lp}{percentileindex} = int(@{$all_query_duration{'READ'}} * $lp / 100) ;
				$cur_period_info{$curdb}{'READ'}{$lp}{percentile} = $all_query_duration{'READ'}[$cur_period_info{$curdb}{'READ'}{$lp}{percentileindex}];
				$percentile{'READ'}{$lp} =  &convert_time($cur_period_info{$curdb}{'READ'}{$lp}{percentile});

				@{$all_query_duration{'WRITE'}}=  sort{ $a <=> $b } (@{$all_query_duration{'INSERT'}},@{$all_query_duration{'UPDATE'}},@{$all_query_duration{'DELETE'}},@{$all_query_duration{'COPY FROM'}});
				$cur_period_info{$curdb}{'WRITE'}{$lp}{percentileindex} = int(@{$all_query_duration{'WRITE'}} * $lp / 100) ;
				$cur_period_info{$curdb}{'WRITE'}{$lp}{percentile} = $all_query_duration{'WRITE'}[$cur_period_info{$curdb}{'WRITE'}{$lp}{percentileindex}];
				$percentile{'WRITE'}{$lp} =  &convert_time($cur_period_info{$curdb}{'WRITE'}{$lp}{percentile});
			}
			$queries .= qq{
					<tr>
						<td>$zday</td>
						<td>$h</td>
						<td>$count</td>
						<td>$min</td>
						<td>$max</td>
						<td>$average</td>
};
			foreach my $lp (@LATENCY_PERCENTILE) {
				$queries .= "<td>$percentile{$lp}</td>\n";
			}
			$queries .= qq{
					</tr>};
			$count = &comma_numbers($cur_period_info{$curdb}{'SELECT'}{count});
			my $copyto_count = &comma_numbers($cur_period_info{$curdb}{'COPY TO'}{count});
			$average = &convert_time($read_average_duration / ($read_average_count || 1));
			$select_queries .= qq{
					<tr>
						<td>$zday</td>
						<td>$h</td>
						<td>$count</td>
						<td>$copyto_count</td>
						<td>$average</td>
};
			foreach my $lp (@LATENCY_PERCENTILE) {
				$select_queries .= "<td>$percentile{'READ'}{$lp}</td>\n";
			}
			$select_queries .= qq{
					</tr>};
			my $insert_count = &comma_numbers($cur_period_info{$curdb}{'INSERT'}{count});
			my $update_count = &comma_numbers($cur_period_info{$curdb}{'UPDATE'}{count});
			my $delete_count = &comma_numbers($cur_period_info{$curdb}{'DELETE'}{count});
			my $copyfrom_count = &comma_numbers($cur_period_info{$curdb}{'COPY FROM'}{count});
			my $write_average = &convert_time($write_average_duration / ($write_average_count || 1));
			$write_queries .= qq{
					<tr>
						<td>$zday</td>
						<td>$h</td>
						<td>$insert_count</td>
						<td>$update_count</td>
						<td>$delete_count</td>
						<td>$copyfrom_count</td>
						<td>$write_average</td>} ;
			foreach my $lp (@LATENCY_PERCENTILE) {
				$write_queries .= "<td>$percentile{'WRITE'}{$lp}</td>\n";
			}
			$write_queries .= qq{
					</tr>};
			my $prepare_count = &comma_numbers($cur_period_info{$curdb}{prepare});
			my $execute_count = &comma_numbers($cur_period_info{$curdb}{execute});
			my $bind_prepare = &comma_numbers(sprintf("%.2f", $cur_period_info{$curdb}{execute}/($cur_period_info{$curdb}{prepare}||1)));
			my $prepare_usual = &comma_numbers(sprintf("%.2f", ($cur_period_info{$curdb}{prepare}/($cur_period_info{$curdb}{usual}||1)) * 100)) . "%";
			$prepared_queries .= qq{
					<tr>
						<td>$zday</td>
						<td>$h</td>
						<td>$prepare_count</td>
						<td>$execute_count</td>
						<td>$bind_prepare</td>
						<td>$prepare_usual</td>
					</tr>};
			$count = &comma_numbers($connection_info{$curdb}{chronos}{"$d"}{"$h"}{count});
			$average = &comma_numbers(sprintf("%0.2f", $connection_info{$curdb}{chronos}{"$d"}{"$h"}{count} / 3600));
			$connections .= qq{
					<tr>
						<td>$zday</td>
						<td>$h</td>
						<td>$count</td>
						<td>$average/s</td>
					</tr>};
			$count = &comma_numbers($session_info{$curdb}{chronos}{"$d"}{"$h"}{count});
			$cur_period_info{$curdb}{'session'}{average} =
				$session_info{$curdb}{chronos}{"$d"}{"$h"}{duration} / ($session_info{$curdb}{chronos}{"$d"}{"$h"}{count} || 1);
			$average = &convert_time($cur_period_info{$curdb}{'session'}{average});
			my $avg_idle = &convert_time(($session_info{$curdb}{chronos}{"$d"}{"$h"}{duration} - $cur_period_info{$curdb}{duration}) / ($session_info{$curdb}{chronos}{"$d"}{"$h"}{count} || 1));
			$sessions .= qq{
					<tr>
						<td>$zday</td>
						<td>$h</td>
						<td>$count</td>
						<td>$average</td>
						<td>$avg_idle</td>
					</tr>};
		}
	}

	# Set default values
	$queries = qq{<tr><td colspan="6">$NODATA</td></tr>} if (!$queries);
	$select_queries = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$select_queries);
	$write_queries = qq{<tr><td colspan="6">$NODATA</td></tr>} if (!$write_queries);
	$prepared_queries = qq{<tr><td colspan="6">$NODATA</td></tr>} if (!$prepared_queries);
	$connections = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$connections);
	$sessions = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$sessions);

	print $fh qq{
<div class="analysis-item row" id="general-activity">
	<h2 class="col-md-12"><i class="glyphicon icon-calendar"></i> General Activity</h2>
	<div class="col-md-12 tabbable">
		<ul class="nav nav-tabs">
			<li class="active"><a href="#general-activity-queries" data-toggle="tab">Queries</a></li>
		    <li><a href="#general-activity-select-queries" data-toggle="tab">Read Queries</a></li>
			<li><a href="#general-activity-write-queries" data-toggle="tab">Write Queries</a></li>
			<li><a href="#general-activity-prepared-queries" data-toggle="tab">Prepared Queries</a></li>
			<li><a href="#general-activity-connections" data-toggle="tab">Connections</a></li>
			<li><a href="#general-activity-sessions" data-toggle="tab">Sessions</a></li>
		</ul>
		<div class="tab-content">
			<div class="active tab-pane" id="general-activity-queries">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Count</th>
							<th>Min duration</th>
							<th>Max duration</th>
							<th>Avg duration</th>
							<th>Latency Percentile(90)</th>
							<th>Latency Percentile(95)</th>
							<th>Latency Percentile(99)</th>
						</tr>
					</thead>
					<tbody>$queries
					</tbody>
				</table>
			</div>
			<div class="tab-pane" id="general-activity-select-queries">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>SELECT</th>
							<th>COPY TO</th>
							<th>Average Duration</th>
							<th>Latency Percentile(90)</th>
							<th>Latency Percentile(95)</th>
							<th>Latency Percentile(99)</th>
						</tr>
					</thead>
					<tbody>$select_queries
					</tbody>
				</table>
			</div>
			<div class="tab-pane" id="general-activity-write-queries">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>INSERT</th>
							<th>UPDATE</th>
							<th>DELETE</th>
							<th>COPY FROM</th>
							<th>Average Duration</th>
							<th>Latency Percentile(90)</th>
							<th>Latency Percentile(95)</th>
							<th>Latency Percentile(99)</th>
						</tr>
					</thead>
					<tbody>$write_queries
					</tbody>
				</table>
			</div>
			<div class="tab-pane" id="general-activity-prepared-queries">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Prepare</th>
							<th>Bind</th>
							<th>Bind/Prepare</th>
							<th>Percentage of prepare</th>
						</tr>
					</thead>
					<tbody>$prepared_queries
					</tbody>
				</table>
			</div>
			<div class="tab-pane" id="general-activity-connections">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Count</th>
							<th>Average / Second</th>
						</tr>
					</thead>
					<tbody>$connections
					</tbody>
				</table>
			</div>
			<div class="tab-pane" id="general-activity-sessions">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Count</th>
							<th>Average Duration</th>
							<th>Average idle time</th>
						</tr>
					</thead>
					<tbody>$sessions
					</tbody>
				</table>
			</div>
		</div> <!-- end of div tab-content -->
		<span class="pull-right">&uarr; <small><a href="#general-activity" class="">Back to the top of the <em>General Activity</em> table</a></small></span>
	</div>

</div><!-- end of general activity -->
};

}

sub print_sql_traffic
{
	my $curdb = shift;

	my $bind_vs_prepared = sprintf("%.2f", $overall_stat{$curdb}{'execute'} / ($overall_stat{$curdb}{'prepare'} || 1));
	my $total_usual_queries = 0;
	map { $total_usual_queries += $overall_stat{$curdb}{lc($_)}; } @SQL_ACTION;
	my $prepared_vs_normal = sprintf("%.2f", ($overall_stat{$curdb}{'execute'} / ($total_usual_queries || 1))*100);

	my $query_peak = 0;
	my $query_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{query} <=> $overall_stat{$curdb}{'peak'}{$a}{query}} keys %{$overall_stat{$curdb}{'peak'}}) {
		$query_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{query});
		$query_peak_date = $_ if ($query_peak);
		last;
	}
	my $select_peak = 0;
	my $select_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{select} <=> $overall_stat{$curdb}{'peak'}{$a}{select}} keys %{$overall_stat{$curdb}{'peak'}}) {
		$select_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{select});
		$select_peak_date = $_ if ($select_peak);
		last;
	}

	my $write_peak = 0;
	my $write_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{write} <=> $overall_stat{$curdb}{'peak'}{$a}{write}} keys %{$overall_stat{$curdb}{'peak'}}) {
		$write_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{write});
		$write_peak_date = $_ if ($write_peak);
		last;
	}

	my $fmt_duration = &convert_time($overall_stat{$curdb}{'queries_duration'}{'execute'}+($overall_stat{$curdb}{'queries_duration'}{'prepare'}||0)+($overall_stat{$curdb}{'queries_duration'}{'bind'}||0));

	print $fh qq{
	<div id="sql-traffic" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-road"></i> SQL Traffic</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$query_peak queries/s</span> <span class="figure-label">Query Peak</span></li>
					<li><span class="figure">$query_peak_date</span> <span class="figure-label">Date</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{queriespersecond_graph}
		</div>
	</div><!-- end of sql-traffic -->
};
	delete $drawn_graphs{queriespersecond_graph};

	print $fh qq{
	<div id="select-traffic" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-road"></i> SELECT Traffic</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$select_peak queries/s</span> <span class="figure-label">Query Peak</span></li>
					<li><span class="figure">$select_peak_date</span> <span class="figure-label">Date</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{selectqueries_graph}
		</div>
	</div><!-- end of select-traffic -->
};
	delete $drawn_graphs{selectqueries_graph};

	print $fh qq{
	<div id="write-traffic" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-road"></i> INSERT/UPDATE/DELETE Traffic</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$write_peak queries/s</span> <span class="figure-label">Query Peak</span></li>
					<li><span class="figure">$write_peak_date</span> <span class="figure-label">Date</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{writequeries_graph}
		</div>
	</div><!-- end of write-traffic -->
};
	delete $drawn_graphs{writequeries_graph};

	print $fh qq{
	<div id="duration-traffic" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-time"></i> Queries duration</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$fmt_duration</span> <span class="figure-label">Total query duration</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{durationqueries_graph}
		</div>
	</div><!-- end of duration-traffic -->
};
	delete $drawn_graphs{durationqueries_graph};

	print $fh qq{
	<div id="prepared-queries-ratio" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-cog"></i> Prepared queries ratio</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$bind_vs_prepared</span> <span class="figure-label">Ratio of bind vs prepare</span></li>
					<li><span class="figure">$prepared_vs_normal %</span> <span class="figure-label">Ratio between prepared and "usual" statements</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{bindpreparequeries_graph}
		</div>
	</div><!-- end of prepared-queries-ratio -->
};
	delete $drawn_graphs{bindpreparequeries_graph};

}

sub print_pgbouncer_stats
{
	my $curdb = shift;

	my $request_peak = 0;
	my $request_peak_date = '';
	foreach (sort {$pgb_overall_stat{'peak'}{$b}{t_req} <=> $pgb_overall_stat{'peak'}{$a}{t_req}} keys %{$pgb_overall_stat{'peak'}}) {
		$request_peak = &comma_numbers($pgb_overall_stat{'peak'}{$_}{t_req});
		$request_peak_date = $_;
		last;
	}

	my $inbytes_peak = 0;
	my $inbytes_peak_date = '';
	foreach (sort {$pgb_overall_stat{'peak'}{$b}{t_inbytes} <=> $pgb_overall_stat{'peak'}{$a}{t_inbytes}} keys %{$pgb_overall_stat{'peak'}}) {
		$inbytes_peak = &comma_numbers($pgb_overall_stat{'peak'}{$_}{t_inbytes});
		$inbytes_peak_date = $_;
		last;
	}

	my $outbytes_peak = 0;
	my $outbytes_peak_date = '';
	foreach (sort {$pgb_overall_stat{'peak'}{$b}{t_outbytes} <=> $pgb_overall_stat{'peak'}{$a}{t_outbytes}} keys %{$pgb_overall_stat{'peak'}}) {
		$outbytes_peak = &comma_numbers($pgb_overall_stat{'peak'}{$_}{t_outbytes});
		$outbytes_peak_date = $_;
		last;
	}

	my $avgduration_peak = 0;
	my $avgduration_peak_date = '';
	foreach (sort {$pgb_overall_stat{'peak'}{$b}{t_avgduration} <=> $pgb_overall_stat{'peak'}{$a}{t_avgduration}} keys %{$pgb_overall_stat{'peak'}}) {
		$avgduration_peak = &convert_time($pgb_overall_stat{'peak'}{$_}{t_avgduration});
		$avgduration_peak_date = $_;
		last;
	}

	my $avgwaiting_peak = 0;
	my $avgwaiting_peak_date = '';
	foreach (sort {$pgb_overall_stat{'peak'}{$b}{t_avgwaiting} <=> $pgb_overall_stat{'peak'}{$a}{t_avgwaiting}} keys %{$pgb_overall_stat{'peak'}}) {
		$avgwaiting_peak = &convert_time($pgb_overall_stat{'peak'}{$_}{t_avgwaiting});
		$avgwaiting_peak_date = $_;
		last;
	}

	print $fh qq{
	<div id="pgbsql-traffic" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-road"></i> Request Throughput</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$request_peak queries/s</span> <span class="figure-label">Request Peak</span></li>
					<li><span class="figure">$request_peak_date</span> <span class="figure-label">Date</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{pgb_requestpersecond_graph}
		</div>
	</div><!-- end of sql-traffic -->
};
	delete $drawn_graphs{pgb_requestpersecond_graph};

	print $fh qq{
	<div id="pgbbytes-traffic" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-road"></i> Bytes I/O Throughput</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$inbytes_peak Bytes/s</span> <span class="figure-label">In Bytes Peak</span></li>
					<li><span class="figure">$inbytes_peak_date</span> <span class="figure-label">Date</span></li>
					<li><span class="figure">$outbytes_peak Bytes/s</span> <span class="figure-label">Out Bytes Peak</span></li>
					<li><span class="figure">$outbytes_peak_date</span> <span class="figure-label">Date</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{pgb_bytepersecond_graph}
		</div>
	</div><!-- end of select-traffic -->
};
	delete $drawn_graphs{pgb_bytepersecond_graph};

	print $fh qq{
	<div id="pgbduration-traffic" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-time"></i> Average Query Duration</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$avgduration_peak</span> <span class="figure-label">Average Duration Peak</span></li>
					<li><span class="figure">$avgduration_peak_date</span> <span class="figure-label">Date</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{pgb_avgduration_graph}
		</div>
	</div><!-- end of duration-traffic -->
};
	delete $drawn_graphs{pgb_avgduration_graph};

	print $fh qq{
	<div id="pgbwaiting-traffic" class="analysis-item row">
		<h2 class="col-md-12"><i class="glyphicon icon-time"></i> Average Waiting Time</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$avgwaiting_peak</span> <span class="figure-label">Average Waiting Peak</span></li>
					<li><span class="figure">$avgwaiting_peak_date</span> <span class="figure-label">Date</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{pgb_avgwaiting_graph}
		</div>
	</div><!-- end of waiting-traffic -->
};
	delete $drawn_graphs{pgb_avgwaiting_graph};


}

sub compute_query_graphs
{
	my $curdb = shift;

	my %graph_data = ();
	if ($graph) {

		foreach my $tm (sort {$a <=> $b} keys %{$per_minute_info{$curdb}}) {
			$tm =~ /(\d{4})(\d{2})(\d{2})/;
			my $y  = $1 - 1900;
			my $mo = $2 - 1;
			my $d  = $3;
			foreach my $h ("00" .. "23") {
				next if (!exists $per_minute_info{$curdb}{$tm}{$h});
				my %q_dataavg = ();
				my %a_dataavg = ();
				my %c_dataavg = ();
				my %s_dataavg = ();
				my %p_dataavg = ();
				foreach my $m ("00" .. "59") {
					next if (!exists $per_minute_info{$curdb}{$tm}{$h}{$m});

					my $rd = &average_per_minutes($m, $avg_minutes);

					if (!exists $p_dataavg{prepare}{"$rd"}) {
						$p_dataavg{prepare}{"$rd"} = 0;
						$p_dataavg{execute}{"$rd"} = 0;

						$q_dataavg{count}{"$rd"} = 0;
						$q_dataavg{duration}{"$rd"} = 0;
						$q_dataavg{max}{"$rd"} = 0;
						$q_dataavg{min}{"$rd"} = 0;

						if (!$disable_query) {
							foreach my $action (@SQL_ACTION) {
								$a_dataavg{$action}{count}{"$rd"} = 0;
								$a_dataavg{$action}{duration}{"$rd"} = 0;
								$a_dataavg{$action}{max}{"$rd"} = 0;
								$a_dataavg{$action}{min}{"$rd"} = 0;
							}
							$a_dataavg{write}{count}{"$rd"} = 0;
							$a_dataavg{write}{duration}{"$rd"} = 0;
						}

						$c_dataavg{average}{"$rd"} = 0;
						$c_dataavg{max}{"$rd"} = 0;
						$c_dataavg{min}{"$rd"} = 0;
						$s_dataavg{average}{"$rd"} = 0;
						$s_dataavg{max}{"$rd"} = 0;
						$s_dataavg{min}{"$rd"} = 0;
					}
					if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{prepare}) {
						$p_dataavg{prepare}{"$rd"} += $per_minute_info{$curdb}{$tm}{$h}{$m}{prepare};
					} elsif (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{parse}) {
						$p_dataavg{prepare}{"$rd"} += $per_minute_info{$curdb}{$tm}{$h}{$m}{parse};
					}
					$p_dataavg{execute}{"$rd"} += $per_minute_info{$curdb}{$tm}{$h}{$m}{execute}
						if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{execute});

					if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{query}) {

						# Average per minute
						$q_dataavg{count}{"$rd"} += $per_minute_info{$curdb}{$tm}{$h}{$m}{query}{count};
						if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{query}{duration}) {
							$q_dataavg{duration}{"$rd"} += $per_minute_info{$curdb}{$tm}{$h}{$m}{query}{duration};
						}
						# Search minimum and maximum during this minute
						foreach my $s (keys %{$per_minute_info{$curdb}{$tm}{$h}{$m}{query}{second}}) {
							$q_dataavg{max}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{query}{second}{$s}
								if ($per_minute_info{$curdb}{$tm}{$h}{$m}{query}{second}{$s} > $q_dataavg{max}{"$rd"});
							$q_dataavg{min}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{query}{second}{$s}
								if ($per_minute_info{$curdb}{$tm}{$h}{$m}{query}{second}{$s} < $q_dataavg{min}{"$rd"});
						}

						if (!$disable_query) {
							foreach my $action (@SQL_ACTION)
							{
								$a_dataavg{$action}{count}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{count} || 0);
								$a_dataavg{$action}{duration}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{duration} || 0);
								if ( ($action ne 'SELECT') && exists $per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{count}) {
									$a_dataavg{write}{count}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{count} || 0);
									$a_dataavg{write}{duration}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{duration} || 0);
								}
								# Search minimum and maximum during this minute
								foreach my $s (keys %{$per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{second}}) {
									$a_dataavg{$action}{max}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{second}{$s}
										if ($per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{second}{$s} > $a_dataavg{$action}{max}{"$rd"});
									$a_dataavg{$action}{min}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{second}{$s}
										if ($per_minute_info{$curdb}{$tm}{$h}{$m}{lc($action)}{second}{$s} < $a_dataavg{$action}{min}{"$rd"});
								}
							}
						}
					}

					if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{connection}) {

						# Average per minute
						$c_dataavg{average}{"$rd"} += $per_minute_info{$curdb}{$tm}{$h}{$m}{connection}{count};

						# Search minimum and maximum during this minute
						foreach my $s (keys %{$per_minute_info{$curdb}{$tm}{$h}{$m}{connection}{second}}) {
							$c_dataavg{max}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{connection}{second}{$s}
								if ($per_minute_info{$curdb}{$tm}{$h}{$m}{connection}{second}{$s} > $c_dataavg{max}{"$rd"});
							$c_dataavg{min}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{connection}{second}{$s}
								if ($per_minute_info{$curdb}{$tm}{$h}{$m}{connection}{second}{$s} < $c_dataavg{min}{"$rd"});
						}
						delete $per_minute_info{$curdb}{$tm}{$h}{$m}{connection};
					}

					if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{session}) {

						# Average per minute
						$s_dataavg{average}{"$rd"} += $per_minute_info{$curdb}{$tm}{$h}{$m}{session}{count};

						# Search minimum and maximum during this minute
						foreach my $s (keys %{$per_minute_info{$curdb}{$tm}{$h}{$m}{session}{second}}) {
							$s_dataavg{max}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{session}{second}{$s}
								if ($per_minute_info{$curdb}{$tm}{$h}{$m}{session}{second}{$s} > $s_dataavg{max}{"$rd"});
							$s_dataavg{min}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{session}{second}{$s}
								if ($per_minute_info{$curdb}{$tm}{$h}{$m}{session}{second}{$s} < $s_dataavg{min}{"$rd"});
						}
						delete $per_minute_info{$curdb}{$tm}{$h}{$m}{session};
					}
				}

				foreach my $rd (@avgs) {
					my $t = timegm_nocheck(0, $rd, $h, $d, $mo, $y) * 1000;
					$t += ($timezone*1000);

					next if ($t < $t_min);
					last if ($t > $t_max);

					if (exists $q_dataavg{count}) {
						# Average queries per minute
						$graph_data{query} .= "[$t, " . int(($q_dataavg{count}{"$rd"} || 0) / (60 * $avg_minutes)) . "],";
						# Max queries per minute
						$graph_data{'query-max'} .= "[$t, " . ($q_dataavg{max}{"$rd"} || 0) . "],";
						# Min queries per minute
						$graph_data{'query-min'} .= "[$t, " . ($q_dataavg{min}{"$rd"} || 0) . "],";
						# Average duration per minute
						$graph_data{query4} .= "[$t, " . sprintf("%.3f", ($q_dataavg{duration}{"$rd"} || 0) / ($q_dataavg{count}{"$rd"} || 1)) . "],";
					}
					if (scalar keys %c_dataavg) {
						# Average connections per minute
						$graph_data{conn_avg} .= "[$t, " . int(($c_dataavg{average}{"$rd"} || 0) / (60 * $avg_minutes)) . "],";
						# Max connections per minute
						$graph_data{conn_max} .= "[$t, " . ($c_dataavg{max}{"$rd"} || 0) . "],";

						# Min connections per minute
						$graph_data{conn_min} .= "[$t, " . ($c_dataavg{min}{"$rd"} || 0) . "],";
					}
					if (scalar keys %s_dataavg) {
						# Average connections per minute
						$graph_data{sess_avg} .= "[$t, " . int(($s_dataavg{average}{"$rd"} || 0) / (60 * $avg_minutes)) . "],";
						# Max connections per minute
						$graph_data{sess_max} .= "[$t, " . ($s_dataavg{max}{"$rd"} || 0) . "],";

						# Min connections per minute
						$graph_data{sess_min} .= "[$t, " . ($s_dataavg{min}{"$rd"} || 0) . "],";
					}
					if (!$disable_query && (scalar keys %a_dataavg > 0))
					{
						foreach my $action (@SQL_ACTION)
						{
							next if ($select_only && ($action ne 'SELECT'));

							# Average queries per minute
							$graph_data{"$action"} .= "[$t, " . int(($a_dataavg{$action}{count}{"$rd"} || 0) / (60 * $avg_minutes)) . "],";
							if ($action eq 'SELECT') {
								# Max queries per minute
								$graph_data{"$action-max"} .= "[$t, " . ($a_dataavg{$action}{max}{"$rd"} || 0) . "],";
								# Min queries per minute
								$graph_data{"$action-min"} .= "[$t, " . ($a_dataavg{$action}{min}{"$rd"} || 0) . "],";
								# Average query duration
								$graph_data{"$action-2"} .= "[$t, " . sprintf("%.3f", ($a_dataavg{$action}{duration}{"$rd"} || 0) / ($a_dataavg{$action}{count}{"$rd"} || 1)) . "],";
							} elsif ($action eq 'DDL') {
								# Average query duration
								$graph_data{"write"} .= "[$t, " . sprintf("%.3f", ($a_dataavg{write}{duration}{"$rd"} || 0) / ($a_dataavg{write}{count}{"$rd"} || 1)) . "],";
							}
						}
					}
					if (!$disable_query && (scalar keys %p_dataavg> 0)) {
						$graph_data{prepare} .= "[$t, " . ($p_dataavg{prepare}{"$rd"} || 0) . "],";
						$graph_data{execute} .= "[$t, " . ($p_dataavg{execute}{"$rd"} || 0) . "],";
						$graph_data{ratio_bind_prepare} .= "[$t, " . sprintf("%.2f", ($p_dataavg{execute}{"$rd"} || 0) / ($p_dataavg{prepare}{"$rd"} || 1)) . "],";
					}
				}
			}
		}
		foreach (keys %graph_data) {
			$graph_data{$_} =~ s/,$//;
		}
	}
	$drawn_graphs{'queriespersecond_graph'} = &jqplot_linegraph( $graphid++, 'queriespersecond_graph', $graph_data{'query-max'},
		$graph_data{query}, $graph_data{'query-min'}, 'Queries per second (' . $avg_minutes . ' minutes average)',
		'Queries per second', 'Maximum', 'Average', 'Minimum'
	);

	$drawn_graphs{'connectionspersecond_graph'} = &jqplot_linegraph( $graphid++, 'connectionspersecond_graph', $graph_data{conn_max},
		$graph_data{conn_avg}, $graph_data{conn_min}, 'Connections per second (' . $avg_minutes . ' minutes average)',
		'Connections per second', 'Maximum', 'Average', 'Minimum'
	);

	$drawn_graphs{'sessionspersecond_graph'} = &jqplot_linegraph( $graphid++, 'sessionspersecond_graph', $graph_data{sess_max},
		$graph_data{sess_avg}, $graph_data{sess_min}, 'Number of sessions/second (' . $avg_minutes . ' minutes average)',
		'Sessions', 'Maximum', 'Average', 'Minimum'
	);

	$drawn_graphs{'selectqueries_graph'} = &jqplot_linegraph( $graphid++, 'selectqueries_graph', $graph_data{"SELECT-max"},
		$graph_data{"SELECT"}, $graph_data{"SELECT-min"},
		'SELECT queries (' . $avg_minutes . ' minutes period)',
		'Queries per second', 'Maximum', 'Average', 'Minimum'
	);

	$drawn_graphs{'writequeries_graph'} = &jqplot_linegraph(
		$graphid++, 'writequeries_graph', $graph_data{"DELETE"}, $graph_data{"INSERT"}, $graph_data{"UPDATE"}, 'Write queries (' . $avg_minutes . ' minutes period)',
		'Queries', 'DELETE queries', 'INSERT queries', 'UPDATE queries'
	);

	if (!$select_only) {
		$drawn_graphs{'durationqueries_graph'} = &jqplot_linegraph(
			$graphid++, 'durationqueries_graph', $graph_data{query4}, $graph_data{"SELECT-2"}, $graph_data{write}, 'Average queries duration (' . $avg_minutes . ' minutes average)',
			'Duration', 'All queries', 'Select queries', 'Write queries'
		);
	} else {
		$drawn_graphs{'durationqueries_graph'} = &jqplot_linegraph(
			$graphid++, 'durationqueries_graph', $graph_data{query4}, '', '', 'Average queries duration (' . $avg_minutes . ' minutes average)',
			'Duration', 'Select queries'
		);
	}

	$drawn_graphs{'bindpreparequeries_graph'} = &jqplot_linegraph(
		$graphid++, 'bindpreparequeries_graph', $graph_data{prepare}, $graph_data{"execute"}, $graph_data{ratio_bind_prepare}, 'Bind versus prepare statements (' . $avg_minutes . ' minutes average)',
		'Number of statements', 'Prepare/Parse', 'Execute/Bind', 'Bind vs prepare'
	);

}

sub compute_pgbouncer_graphs
{
	my %graph_data = ();
	if ($graph) {

		foreach my $tm (sort {$a <=> $b} keys %pgb_per_minute_info) {
			$tm =~ /(\d{4})(\d{2})(\d{2})/;
			my $y  = $1 - 1900;
			my $mo = $2 - 1;
			my $d  = $3;
			foreach my $h ("00" .. "23") {
				next if (!exists $pgb_per_minute_info{$tm}{$h});
				my %c_dataavg = ();
				my %s_dataavg = ();
				foreach my $m ("00" .. "59") {

					my $t = timegm_nocheck(0, $m, $h, $d, $mo, $y) * 1000;
					$t += ($timezone*1000);

					next if ($t < $t_min);
					last if ($t > $t_max);

					# pgBouncer stats are generate each minutes, always keep this interval
					$graph_data{'request'} .= "[$t, " . ($pgb_per_minute_info{$tm}{$h}{$m}{t_req} || 0) . "],";
					$graph_data{'inbytes'} .= "[$t, " . ($pgb_per_minute_info{$tm}{$h}{$m}{t_inbytes} || 0) . "],";
					$graph_data{'outbytes'} .= "[$t, " . ($pgb_per_minute_info{$tm}{$h}{$m}{t_outbytes} || 0) . "],";
					$graph_data{'avgduration'} .= "[$t, " . ($pgb_per_minute_info{$tm}{$h}{$m}{t_avgduration} || 0) . "],";
					$graph_data{'avgwaiting'} .= "[$t, " . ($pgb_per_minute_info{$tm}{$h}{$m}{t_avgwaiting} || 0) . "],";
					next if (!exists $pgb_per_minute_info{$tm}{$h}{$m});

					my $rd = &average_per_minutes($m, $avg_minutes);

					if (exists $pgb_per_minute_info{$tm}{$h}{$m}{connection}) {

						# Average per minute
						$c_dataavg{average}{"$rd"} += $pgb_per_minute_info{$tm}{$h}{$m}{connection}{count};

						# Search minimum and maximum during this minute
						foreach my $s (keys %{$pgb_per_minute_info{$tm}{$h}{$m}{connection}{second}}) {
							$c_dataavg{max}{"$rd"} = $pgb_per_minute_info{$tm}{$h}{$m}{connection}{second}{$s}
								if ($pgb_per_minute_info{$tm}{$h}{$m}{connection}{second}{$s} > $c_dataavg{max}{"$rd"});
							$c_dataavg{min}{"$rd"} = $pgb_per_minute_info{$tm}{$h}{$m}{connection}{second}{$s}
								if ($pgb_per_minute_info{$tm}{$h}{$m}{connection}{second}{$s} < $c_dataavg{min}{"$rd"});
						}
						delete $pgb_per_minute_info{$tm}{$h}{$m}{connection};
					}

					if (exists $pgb_per_minute_info{$tm}{$h}{$m}{session}) {

						# Average per minute
						$s_dataavg{average}{"$rd"} += $pgb_per_minute_info{$tm}{$h}{$m}{session}{count};

						# Search minimum and maximum during this minute
						foreach my $s (keys %{$pgb_per_minute_info{$tm}{$h}{$m}{session}{second}}) {
							$s_dataavg{max}{"$rd"} = $pgb_per_minute_info{$tm}{$h}{$m}{session}{second}{$s}
								if ($pgb_per_minute_info{$tm}{$h}{$m}{session}{second}{$s} > $s_dataavg{max}{"$rd"});
							$s_dataavg{min}{"$rd"} = $pgb_per_minute_info{$tm}{$h}{$m}{session}{second}{$s}
								if ($pgb_per_minute_info{$tm}{$h}{$m}{session}{second}{$s} < $s_dataavg{min}{"$rd"});
						}
						delete $pgb_per_minute_info{$tm}{$h}{$m}{session};
					}
				}

				foreach my $rd (@avgs) {
					my $t = timegm_nocheck(0, $rd, $h, $d, $mo, $y) * 1000;
					$t += ($timezone*1000);

					next if ($t < $t_min);
					last if ($t > $t_max);

					if (scalar keys %c_dataavg) {
						# Average connections per minute
						$graph_data{conn_avg} .= "[$t, " . int(($c_dataavg{average}{"$rd"} || 0) / (60 * $avg_minutes)) . "],";
						# Max connections per minute
						$graph_data{conn_max} .= "[$t, " . ($c_dataavg{max}{"$rd"} || 0) . "],";

						# Min connections per minute
						$graph_data{conn_min} .= "[$t, " . ($c_dataavg{min}{"$rd"} || 0) . "],";
					}
					if (scalar keys %s_dataavg) {
						# Average connections per minute
						$graph_data{sess_avg} .= "[$t, " . int(($s_dataavg{average}{"$rd"} || 0) / (60 * $avg_minutes)) . "],";
						# Max connections per minute
						$graph_data{sess_max} .= "[$t, " . ($s_dataavg{max}{"$rd"} || 0) . "],";

						# Min connections per minute
						$graph_data{sess_min} .= "[$t, " . ($s_dataavg{min}{"$rd"} || 0) . "],";
					}
				}
			}
		}
		foreach (keys %graph_data) {
			$graph_data{$_} =~ s/,$//;
		}
	}

	$drawn_graphs{'pgb_requestpersecond_graph'} = &jqplot_linegraph( $graphid++, 'pgb_requestpersecond_graph', $graph_data{request},'',,'','Request per seconds (1 minute average)', '', 'Request per second');

	$drawn_graphs{'pgb_bytepersecond_graph'} = &jqplot_linegraph( $graphid++, 'pgb_bytepersecond_graph', $graph_data{inbytes},$graph_data{'outbytes'},'','Bytes I/O per seconds (1 minute average)', 'size', 'In b/s', 'Out b/s');

	$drawn_graphs{'pgb_avgduration_graph'} = &jqplot_linegraph( $graphid++, 'pgb_avgduration_graph', $graph_data{avgduration},'','', 'Average query duration (1 minute average)', 'duration', 'Duration');

	$drawn_graphs{'pgb_avgwaiting_graph'} = &jqplot_linegraph( $graphid++, 'pgb_avgwaiting_graph', $graph_data{avgwaiting},'','', 'Average waiting time (1 minute average)', 'waiting', 'Waiting');

	$drawn_graphs{'pgb_connectionspersecond_graph'} = &jqplot_linegraph( $graphid++, 'pgb_connectionspersecond_graph', $graph_data{conn_max},
		$graph_data{conn_avg}, $graph_data{conn_min}, 'Connections per second (' . $avg_minutes . ' minutes average)',
		'Connections per second', 'Maximum', 'Average', 'Minimum'
	);

	$drawn_graphs{'pgb_sessionspersecond_graph'} = &jqplot_linegraph( $graphid++, 'pgb_sessionspersecond_graph', $graph_data{sess_max},
		$graph_data{sess_avg}, $graph_data{sess_min}, 'Number of sessions/second (' . $avg_minutes . ' minutes average)',
		'Sessions', 'Maximum', 'Average', 'Minimum'
	);

}

sub print_established_connection
{
	my $curdb = shift;

	my $connection_peak = 0;
	my $connection_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{connection} <=> $overall_stat{$curdb}{'peak'}{$a}{connection}} keys %{$overall_stat{$curdb}{'peak'}}) {
		$connection_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{connection});
		$connection_peak_date = $_ if ($connection_peak);
		last;
	}

	print $fh qq{
	<div id="established-connections" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-random"></i> Established Connections</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$connection_peak connections</span> <span class="figure-label">Connection Peak</span></li>
				<li><span class="figure">$connection_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{connectionspersecond_graph}
		</div>
	</div><!-- end of Established connections -->
};
	delete $drawn_graphs{connectionspersecond_graph};

}

sub print_established_pgb_connection
{

	my $connection_peak = 0;
	my $connection_peak_date = '';
	foreach (sort {$pgb_overall_stat{'peak'}{$b}{connection} <=> $pgb_overall_stat{'peak'}{$a}{connection}} keys %{$pgb_overall_stat{'peak'}}) {
		$connection_peak = &comma_numbers($pgb_overall_stat{'peak'}{$_}{connection});
		$connection_peak_date = $_;
		last;
	}

	print $fh qq{
	<div id="pgbestablished-connections" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-random"></i> Established Connections</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$connection_peak connections</span> <span class="figure-label">Connection Peak</span></li>
				<li><span class="figure">$connection_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{pgb_connectionspersecond_graph}
		</div>
	</div><!-- end of Established connections -->
};
	delete $drawn_graphs{pgb_connectionspersecond_graph};

}

sub print_user_connection
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $conn_user_info = '';
	my @main_user = ('unknown',0);
	foreach my $u (sort keys %{$connection_info{$curdb}{user}})
	{
		$conn_user_info .= "<tr><td>$u</td><td>" .
				   &comma_numbers($connection_info{$curdb}{user}{$u}) . "</td></tr>";
		$total_count += $connection_info{$curdb}{user}{$u};
		if ($main_user[1] < $connection_info{$curdb}{user}{$u})
		{
			$main_user[0] = $u;
			$main_user[1] = $connection_info{$curdb}{user}{$u};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$connection_info{$curdb}{user}})
		{
			if ((($connection_info{$curdb}{user}{$d} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $connection_info{$curdb}{user}{$d} || 0;
			} else {
				$infos{"Sum connections < $pie_percentage_limit%"} += $connection_info{$curdb}{user}{$d} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum connections < $pie_percentage_limit%"};
			delete $infos{"Sum connections < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{userconnections_graph} = &jqplot_piegraph($graphid++, 'graph_userconnections', 'Connections per user', %infos);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="connections-per-user">
		<h2 class="col-md-12"><i class="glyphicon icon-user"></i> Connections per user</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_user[0]</span> <span class="figure-label">Main User</span></li>
					<li><span class="figure">$total_count connections</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#connections-per-user-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#connections-per-user-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="connections-per-user-graph">
						$drawn_graphs{userconnections_graph}
					</div>
					<div class="tab-pane" id="connections-per-user-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>User</th>
									<th>Count</th>
								</tr>
							</thead>
							<tbody>
							$conn_user_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of connections per user -->
};
	delete $drawn_graphs{userconnections_graph};
}

sub print_user_pgb_connection
{

	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $conn_user_info = '';
	my @main_user = ('unknown',0);
	foreach my $u (sort keys %{$pgb_connection_info{user}}) {
		$conn_user_info .= "<tr><td>$u</td><td>" .
				   &comma_numbers($pgb_connection_info{user}{$u}) . "</td></tr>";
		$total_count += $pgb_connection_info{user}{$u};
		if ($main_user[1] < $pgb_connection_info{user}{$u}) {
			$main_user[0] = $u;
			$main_user[1] = $pgb_connection_info{user}{$u};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$pgb_connection_info{user}}) {
			if ((($pgb_connection_info{user}{$d} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $pgb_connection_info{user}{$d} || 0;
			} else {
				$infos{"Sum connections < $pie_percentage_limit%"} += $pgb_connection_info{user}{$d} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum connections < $pie_percentage_limit%"};
			delete $infos{"Sum connections < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{pgb_userconnections_graph} = &jqplot_piegraph($graphid++, 'graph_pgb_userconnections', 'Connections per user', %infos);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="pgbconnections-per-user">
		<h2 class="col-md-12"><i class="glyphicon icon-user"></i> Connections per user</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_user[0]</span> <span class="figure-label">Main User</span></li>
					<li><span class="figure">$total_count connections</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#pgbconnections-per-user-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#pgbconnections-per-user-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="pgbconnections-per-user-graph">
						$drawn_graphs{pgb_userconnections_graph}
					</div>
					<div class="tab-pane" id="pgbconnections-per-user-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>User</th>
									<th>Count</th>
								</tr>
							</thead>
							<tbody>
							$conn_user_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of connections per user -->
};
	delete $drawn_graphs{pgb_userconnections_graph};
}

sub print_host_connection
{
	my $curdb = shift();

	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $conn_host_info = '';
	my @main_host = ('unknown',0);
	foreach my $h (sort keys %{$connection_info{$curdb}{host}}) {
		$conn_host_info .= "<tr><td>$h</td><td>" .
				    &comma_numbers($connection_info{$curdb}{host}{$h}) . "</td></tr>";
		$total_count += $connection_info{$curdb}{host}{$h};
		if ($main_host[1] < $connection_info{$curdb}{host}{$h}) {
			$main_host[0] = $h;
			$main_host[1] = $connection_info{$curdb}{host}{$h};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$connection_info{$curdb}{host}}) {
			if ((($connection_info{$curdb}{host}{$d} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $connection_info{$curdb}{host}{$d} || 0;
			} else {
				$infos{"Sum connections < $pie_percentage_limit%"} += $connection_info{$curdb}{host}{$d} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum connections < $pie_percentage_limit%"};
			delete $infos{"Sum connections < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{hostconnections_graph} = &jqplot_piegraph($graphid++, 'graph_hostconnections', 'Connections per host', %infos);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="connections-per-host">
		<h2 class="col-md-12"><i class="glyphicon icon-sitemap"></i> Connections per host</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_host[0]</span> <span class="figure-label">Main host with $main_host[1] connections</span></li>
					<li><span class="figure">$total_count</span> <span class="figure-label">Total connections</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#connections-per-host-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#connections-per-host-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="connections-per-host-graph">
						$drawn_graphs{hostconnections_graph}
					</div>
					<div class="tab-pane" id="connections-per-host-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Host</th>
									<th>Count</th>
								</tr>
							</thead>
							<tbody>
							$conn_host_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of connections per host -->
};

	delete $drawn_graphs{hostconnections_graph};
}

sub print_host_pgb_connection
{
	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $conn_host_info = '';
	my @main_host = ('unknown',0);
	foreach my $h (sort keys %{$pgb_connection_info{host}}) {
		$conn_host_info .= "<tr><td>$h</td><td>" .
				    &comma_numbers($pgb_connection_info{host}{$h}) . "</td></tr>";
		$total_count += $pgb_connection_info{host}{$h};
		if ($main_host[1] < $pgb_connection_info{host}{$h}) {
			$main_host[0] = $h;
			$main_host[1] = $pgb_connection_info{host}{$h};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$pgb_connection_info{host}}) {
			if ((($pgb_connection_info{host}{$d} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $pgb_connection_info{host}{$d} || 0;
			} else {
				$infos{"Sum connections < $pie_percentage_limit%"} += $pgb_connection_info{host}{$d} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum connections < $pie_percentage_limit%"};
			delete $infos{"Sum connections < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{pgb_hostconnections_graph} = &jqplot_piegraph($graphid++, 'graph_pgb_hostconnections', 'Connections per host', %infos);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="pgbconnections-per-host">
		<h2 class="col-md-12"><i class="glyphicon icon-sitemap"></i> Connections per host</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_host[0]</span> <span class="figure-label">Main host with $main_host[1] connections</span></li>
					<li><span class="figure">$total_count</span> <span class="figure-label">Total connections</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#pgbconnections-per-host-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#pgbconnections-per-host-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="pgbconnections-per-host-graph">
						$drawn_graphs{pgb_hostconnections_graph}
					</div>
					<div class="tab-pane" id="pgbconnections-per-host-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Host</th>
									<th>Count</th>
								</tr>
							</thead>
							<tbody>
							$conn_host_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of connections per host -->
};

	delete $drawn_graphs{pgb_hostconnections_graph};
}

sub print_database_connection
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $conn_database_info = '';
	my @main_database = ('unknown',0);
	foreach my $d (sort keys %{$connection_info{$curdb}{database}}) {
		$conn_database_info .= "<tr><td>$d</td><td>&nbsp;</td><td>" .
					 &comma_numbers($connection_info{$curdb}{database}{$d}) . "</td></tr>";
		$total_count += $connection_info{$curdb}{database}{$d};
		if ($main_database[1] < $connection_info{$curdb}{database}{$d}) {
			$main_database[0] = $d;
			$main_database[1] = $connection_info{$curdb}{database}{$d};
		}
		foreach my $u (sort keys %{$connection_info{$curdb}{user}}) {
			next if (!exists $connection_info{$curdb}{database_user}{$d}{$u});
			$conn_database_info .= "<tr><td>&nbsp;</td><td>$u</td><td>" .
				&comma_numbers($connection_info{$curdb}{database_user}{$d}{$u}) . "</td></tr>";
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$connection_info{$curdb}{database}}) {
			if ((($connection_info{$curdb}{database}{$d} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $connection_info{$curdb}{database}{$d} || 0;
			} else {
				$infos{"Sum connections < $pie_percentage_limit%"} += $connection_info{$curdb}{database}{$d} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum connections < $pie_percentage_limit%"};
			delete $infos{"Sum connections < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{databaseconnections_graph} = &jqplot_piegraph($graphid++, 'graph_databaseconnections', 'Connections per database', %infos);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="connections-per-database">
		<h2 class="col-md-12"><i class="glyphicon icon-list-alt"></i> Connections per database</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_database[0]</span> <span class="figure-label">Main Database</span></li>
					<li><span class="figure">$total_count connections</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#connections-per-database-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#connections-per-database-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="connections-per-database-graph">
						$drawn_graphs{databaseconnections_graph}
					</div>
					<div class="tab-pane" id="connections-per-database-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Database</th>
									<th>User</th>
									<th>Count</th>
								</tr>
							</thead>
							<tbody>
							$conn_database_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of connections per database -->
};
	delete $drawn_graphs{databaseconnections_graph};
}

sub print_database_pgb_connection
{
	my %infos = ();
	my $total_count = 0;
	my $conn_database_info = '';
	my @main_database = ('unknown',0);
	foreach my $d (sort keys %{$pgb_connection_info{database}}) {
		$conn_database_info .= "<tr><td>$d</td><td>&nbsp;</td><td>" .
					 &comma_numbers($pgb_connection_info{database}{$d}) . "</td></tr>";
		$total_count += $pgb_connection_info{database}{$d};
		if ($main_database[1] < $pgb_connection_info{database}{$d}) {
			$main_database[0] = $d;
			$main_database[1] = $pgb_connection_info{database}{$d};
		}
		foreach my $u (sort keys %{$pgb_connection_info{user}}) {
			next if (!exists $pgb_connection_info{database_user}{$d}{$u});
			$conn_database_info .= "<tr><td>&nbsp;</td><td>$u</td><td>" .
				&comma_numbers($pgb_connection_info{database_user}{$d}{$u}) . "</td></tr>";
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$pgb_connection_info{database}}) {
			if ((($pgb_connection_info{database}{$d} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $pgb_connection_info{database}{$d} || 0;
			} else {
				$infos{"Sum connections < $pie_percentage_limit%"} += $pgb_connection_info{database}{$d} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum connections < $pie_percentage_limit%"};
			delete $infos{"Sum connections < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{pgb_databaseconnections_graph} = &jqplot_piegraph($graphid++, 'graph_pgb_databaseconnections', 'Connections per database', %infos);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="pgbconnections-per-database">
		<h2 class="col-md-12"><i class="glyphicon icon-list-alt"></i> Connections per database</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_database[0]</span> <span class="figure-label">Main Database</span></li>
					<li><span class="figure">$total_count connections</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#pgbconnections-per-database-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#pgbconnections-per-database-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="pgbconnections-per-database-graph">
						$drawn_graphs{pgb_databaseconnections_graph}
					</div>
					<div class="tab-pane" id="pgbconnections-per-database-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Database</th>
									<th>User</th>
									<th>Count</th>
								</tr>
							</thead>
							<tbody>
							$conn_database_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of connections per database -->
};
	delete $drawn_graphs{pgb_databaseconnections_graph};
}

sub print_simultaneous_session
{
	my $curdb = shift;

	my $session_peak = 0;
	my $session_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{session} <=> $overall_stat{$curdb}{'peak'}{$a}{session}} keys %{$overall_stat{$curdb}{'peak'}}) {
		$session_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{session});
		$session_peak_date = $_ if ($session_peak);
		last;
	}

	print $fh qq{
	<div id="simultaneous-sessions" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-random"></i> Simultaneous sessions</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$session_peak sessions</span> <span class="figure-label">Session Peak</span></li>
				<li><span class="figure">$session_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{sessionspersecond_graph}
		</div>
	</div><!-- end of Simultaneous sessions -->
};
	delete $drawn_graphs{sessionspersecond_graph};

}

sub print_simultaneous_pgb_session
{

	my $session_peak = 0;
	my $session_peak_date = '';
	foreach (sort {$pgb_overall_stat{'peak'}{$b}{session} <=> $pgb_overall_stat{'peak'}{$a}{session}} keys %{$pgb_overall_stat{'peak'}}) {
		$session_peak = &comma_numbers($pgb_overall_stat{'peak'}{$_}{session});
		$session_peak_date = $_;
		last;
	}

	print $fh qq{
	<div id="pgbsimultaneous-sessions" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-random"></i> Simultaneous sessions</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$session_peak sessions</span> <span class="figure-label">Session Peak</span></li>
				<li><span class="figure">$session_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{pgb_sessionspersecond_graph}
		</div>
	</div><!-- end of Simultaneous sessions -->
};
	delete $drawn_graphs{pgb_sessionspersecond_graph};

}

sub print_histogram_session_times
{
	my $curdb = shift;

	my %data = ();
	my $histogram_info = '';
	my $most_range = '';
	my $most_range_value = '';

	for (my $i = 1; $i <= $#histogram_session_time; $i++) {
		$histogram_info .= "<tr><td>" . &convert_time($histogram_session_time[$i-1]) . '-' . &convert_time($histogram_session_time[$i]) . "</td><td>" . &comma_numbers($overall_stat{$curdb}{histogram}{session_time}{$histogram_session_time[$i-1]}) .
			"</td><td>" . sprintf("%0.2f", ($overall_stat{$curdb}{histogram}{session_time}{$histogram_session_time[$i-1]} * 100) / ($overall_stat{$curdb}{histogram}{session_total}||1)) . "%</td></tr>";
		$data{"$histogram_session_time[$i-1]-$histogram_session_time[$i]ms"} = ($overall_stat{$curdb}{histogram}{session_time}{$histogram_session_time[$i-1]} || 0);
		if ($overall_stat{$curdb}{histogram}{session_time}{$histogram_session_time[$i-1]} > $most_range_value) {
			$most_range = "$histogram_session_time[$i-1]-$histogram_session_time[$i]ms";
			$most_range_value = $overall_stat{$curdb}{histogram}{session_time}{$histogram_session_time[$i-1]};
		}
	}
	if ($graph) {
		if ($overall_stat{$curdb}{histogram}{session_total} > 0) {
			$histogram_info .= "<tr><td> &gt; " . &convert_time($histogram_session_time[-1]) . "</td><td>" . &comma_numbers($overall_stat{$curdb}{histogram}{session_time}{'-1'}) .
				"</td><td>" . sprintf("%0.2f", ($overall_stat{$curdb}{histogram}{session_time}{'-1'} * 100) / ($overall_stat{$curdb}{histogram}{session_total}||1)) . "%</td></tr>";
			$data{"> $histogram_session_time[-1]ms"} = ($overall_stat{$curdb}{histogram}{session_time}{"-1"} || 0);
			if ($overall_stat{$curdb}{histogram}{session_time}{"-1"} > $most_range_value) {
				$most_range = "> $histogram_session_time[-1]ms";
				$most_range_value = $overall_stat{$curdb}{histogram}{session_time}{"-1"};
			}
			$drawn_graphs{histogram_session_times_graph} = &jqplot_duration_histograph($graphid++, 'graph_histogram_session_times', 'Sessions', \@histogram_session_time, %data);
		} else {
			$histogram_info = qq{<tr><td colspan="3">$NODATA</td></tr>};
			$drawn_graphs{histogram_session_times_graph} = qq{$NODATA};
		}
	} else {
		$histogram_info = qq{<tr><td colspan="3">$NODATA</td></tr>};
		$drawn_graphs{histogram_session_times_graph} = qq{$NODATA};
	}


	$most_range_value = &comma_numbers($most_range_value) if ($most_range_value);

	print $fh qq{
	<div class="analysis-item row" id="histogram-session-times">
		<h2 class="col-md-12"><i class="glyphicon icon-signal"></i> Histogram of session times</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$most_range_value</span> <span class="figure-label">$most_range duration</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#histogram-session-times-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#histogram-session-times-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="histogram-session-times-graph">
						$drawn_graphs{histogram_session_times_graph}
					</div>
					<div class="tab-pane" id="histogram-session-times-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Range</th>
									<th>Count</th>
									<th>Percentage</th>
								</tr>
							</thead>
							<tbody>
							$histogram_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of queries by type -->
};
	delete $drawn_graphs{histogram_session_times_graph};
}

sub print_histogram_pgb_session_times
{
	my %data = ();
	my $histogram_info = '';
	my $most_range = '';
	my $most_range_value = '';

	for (my $i = 1; $i <= $#histogram_session_time; $i++) {
		$histogram_info .= "<tr><td>" . &convert_time($histogram_session_time[$i-1]) . '-' . &convert_time($histogram_session_time[$i]) . "</td><td>" . &comma_numbers($pgb_overall_stat{histogram}{session_time}{$histogram_session_time[$i-1]}) .
			"</td><td>" . sprintf("%0.2f", ($pgb_overall_stat{histogram}{session_time}{$histogram_session_time[$i-1]} * 100) / ($pgb_overall_stat{histogram}{session_total}||1)) . "%</td></tr>";
		$data{"$histogram_session_time[$i-1]-$histogram_session_time[$i]ms"} = ($pgb_overall_stat{histogram}{session_time}{$histogram_session_time[$i-1]} || 0);
		if ($pgb_overall_stat{histogram}{session_time}{$histogram_session_time[$i-1]} > $most_range_value) {
			$most_range = "$histogram_session_time[$i-1]-$histogram_session_time[$i]ms";
			$most_range_value = $pgb_overall_stat{histogram}{session_time}{$histogram_session_time[$i-1]};
		}
	}
	if ($pgb_overall_stat{histogram}{session_total} > 0) {
		$histogram_info .= "<tr><td> &gt; " . &convert_time($histogram_session_time[-1]) . "</td><td>" . &comma_numbers($pgb_overall_stat{histogram}{session_time}{'-1'}) .
			"</td><td>" . sprintf("%0.2f", ($pgb_overall_stat{histogram}{session_time}{'-1'} * 100) / ($pgb_overall_stat{histogram}{session_total}||1)) . "%</td></tr>";
		$data{"> $histogram_session_time[-1]ms"} = ($pgb_overall_stat{histogram}{session_time}{"-1"} || 0);
		if ($pgb_overall_stat{histogram}{session_time}{"-1"} > $most_range_value) {
			$most_range = "> $histogram_session_time[-1]ms";
			$most_range_value = $pgb_overall_stat{histogram}{session_time}{"-1"};
		}
		$drawn_graphs{pgb_histogram_session_times_graph} = &jqplot_duration_histograph($graphid++, 'graph_pgb_histogram_session_times', 'Sessions', \@histogram_session_time, %data);
	} else {
		$histogram_info = qq{<tr><td colspan="3">$NODATA</td></tr>};
		$drawn_graphs{pgb_histogram_session_times_graph} = qq{$NODATA};
	}

	$most_range_value = &comma_numbers($most_range_value) if ($most_range_value);

	print $fh qq{
	<div class="analysis-item row" id="pgbhistogram-session-times">
		<h2 class="col-md-12"><i class="glyphicon icon-signal"></i> Histogram of session times</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$most_range_value</span> <span class="figure-label">$most_range duration</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#pgbhistogram-session-times-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#pgbhistogram-session-times-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="pgbhistogram-session-times-graph">
						$drawn_graphs{pgb_histogram_session_times_graph}
					</div>
					<div class="tab-pane" id="pgbhistogram-session-times-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Range</th>
									<th>Count</th>
									<th>Percentage</th>
								</tr>
							</thead>
							<tbody>
							$histogram_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of queries by type -->
};
	delete $drawn_graphs{pgb_histogram_session_times_graph};
}

sub print_user_session
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $sess_user_info = '';
	my @main_user = ('unknown',0);
	foreach my $u (sort keys %{$session_info{$curdb}{user}})
	{
		$session_info{$curdb}{user}{$u}{count} ||= 1;
		$sess_user_info .= "<tr><td>$u</td><td>" . &comma_numbers($session_info{$curdb}{user}{$u}{count}) .
				   "</td><td>" . &convert_time($session_info{$curdb}{user}{$u}{duration}) . "</td><td>" .
				   &convert_time($session_info{$curdb}{user}{$u}{duration} / $session_info{$curdb}{user}{$u}{count}) .
				   "</td></tr>";
		$total_count += $session_info{$curdb}{user}{$u}{count};
		if ($main_user[1] < $session_info{$curdb}{user}{$u}{count}) {
			$main_user[0] = $u;
			$main_user[1] = $session_info{$curdb}{user}{$u}{count};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$session_info{$curdb}{user}}) {
			if ((($session_info{$curdb}{user}{$d}{count} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $session_info{$curdb}{user}{$d}{count} || 0;
			} else {
				$infos{"Sum sessions < $pie_percentage_limit%"} += $session_info{$curdb}{user}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum sessions < $pie_percentage_limit%"};
			delete $infos{"Sum sessions < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{usersessions_graph} = &jqplot_piegraph($graphid++, 'graph_usersessions', 'Sessions per user', %infos);
	$sess_user_info = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$total_count);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="sessions-per-user">
		<h2 class="col-md-12"><i class="glyphicon icon-user"></i> Sessions per user</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_user[0]</span> <span class="figure-label">Main User</span></li>
					<li><span class="figure">$total_count sessions</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#sessions-per-user-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#sessions-per-user-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="sessions-per-user-graph">
						$drawn_graphs{usersessions_graph}
					</div>
					<div class="tab-pane" id="sessions-per-user-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>User</th>
									<th>Count</th>
									<th>Total Duration</th>
									<th>Average Duration</th>
								</tr>
							</thead>
							<tbody>
							$sess_user_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of sessions per user -->
};
	delete $drawn_graphs{usersessions_graph};
}

sub print_user_pgb_session
{
	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $sess_user_info = '';
	my @main_user = ('unknown',0);
	foreach my $u (sort keys %{$pgb_session_info{user}}) {
		$sess_user_info .= "<tr><td>$u</td><td>" . &comma_numbers($pgb_session_info{user}{$u}{count}) .
				   "</td><td>" . &convert_time($pgb_session_info{user}{$u}{duration}) . "</td><td>" .
				   &convert_time($pgb_session_info{user}{$u}{duration} / $pgb_session_info{user}{$u}{count}) .
				   "</td></tr>";
		$total_count += $pgb_session_info{user}{$u}{count};
		if ($main_user[1] < $pgb_session_info{user}{$u}{count}) {
			$main_user[0] = $u;
			$main_user[1] = $pgb_session_info{user}{$u}{count};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$pgb_session_info{user}}) {
			if ((($pgb_session_info{user}{$d}{count} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $pgb_session_info{user}{$d}{count} || 0;
			} else {
				$infos{"Sum sessions < $pie_percentage_limit%"} += $pgb_session_info{user}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum sessions < $pie_percentage_limit%"};
			delete $infos{"Sum sessions < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{pgb_usersessions_graph} = &jqplot_piegraph($graphid++, 'graph_pgb_usersessions', 'Sessions per user', %infos);
	$sess_user_info = qq{<tr><td colspan="5">$NODATA</td></tr>} if (!$total_count);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="pgbsessions-per-user">
		<h2 class="col-md-12"><i class="glyphicon icon-user"></i> Sessions per user</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_user[0]</span> <span class="figure-label">Main User</span></li>
					<li><span class="figure">$total_count sessions</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#pgbsessions-per-user-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#pgbsessions-per-user-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="pgbsessions-per-user-graph">
						$drawn_graphs{pgb_usersessions_graph}
					</div>
					<div class="tab-pane" id="pgbsessions-per-user-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>User</th>
									<th>Count</th>
									<th>Total Duration</th>
									<th>Average Duration</th>
								</tr>
							</thead>
							<tbody>
							$sess_user_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of sessions per user -->
};
	delete $drawn_graphs{pgb_usersessions_graph};
}

sub print_host_session
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $sess_host_info = '';
	my @main_host = ('unknown',0);
	foreach my $h (sort keys %{$session_info{$curdb}{host}})
	{
		$sess_host_info .= "<tr><td>$h</td><td>" . &comma_numbers($session_info{$curdb}{host}{$h}{count}) .
				   "</td><td>" . &convert_time($session_info{$curdb}{host}{$h}{duration}) . "</td><td>" .
				   &convert_time($session_info{$curdb}{host}{$h}{duration} / $session_info{$curdb}{host}{$h}{count}) .
				   "</td></tr>";
		$total_count += $session_info{$curdb}{host}{$h}{count};
		if ($main_host[1] < $session_info{$curdb}{host}{$h}{count}) {
			$main_host[0] = $h;
			$main_host[1] = $session_info{$curdb}{host}{$h}{count};
		}
	}
	if ($graph)
	{
		my @small = ();
		foreach my $d (sort keys %{$session_info{$curdb}{host}}) {
			if ((($session_info{$curdb}{host}{$d}{count} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $session_info{$curdb}{host}{$d}{count} || 0;
			} else {
				$infos{"Sum sessions < $pie_percentage_limit%"} += $session_info{$curdb}{host}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum sessions < $pie_percentage_limit%"};
			delete $infos{"Sum sessions < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{hostsessions_graph} = &jqplot_piegraph($graphid++, 'graph_hostsessions', 'Sessions per host', %infos);
	$sess_host_info = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$total_count);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="sessions-per-host">
		<h2 class="col-md-12"><i class="glyphicon icon-sitemap"></i> Sessions per host</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_host[0]</span> <span class="figure-label">Main Host</span></li>
					<li><span class="figure">$total_count sessions</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#sessions-per-host-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#sessions-per-host-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="sessions-per-host-graph">
						$drawn_graphs{hostsessions_graph}
					</div>
					<div class="tab-pane" id="sessions-per-host-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Host</th>
									<th>Count</th>
									<th>Total Duration</th>
									<th>Average Duration</th>
								</tr>
							</thead>
							<tbody>
							$sess_host_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of sessions per host -->
};

	delete $drawn_graphs{hostsessions_graph};
}

sub print_host_pgb_session
{
	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $sess_host_info = '';
	my @main_host = ('unknown',0);
	foreach my $h (sort keys %{$pgb_session_info{host}}) {
		$sess_host_info .= "<tr><td>$h</td><td>" . &comma_numbers($pgb_session_info{host}{$h}{count}) .
				   "</td><td>" . &convert_time($pgb_session_info{host}{$h}{duration}) . "</td><td>" .
				   &convert_time($pgb_session_info{host}{$h}{duration} / $pgb_session_info{host}{$h}{count}) .
				   "</td></tr>";
		$total_count += $pgb_session_info{host}{$h}{count};
		if ($main_host[1] < $pgb_session_info{host}{$h}{count}) {
			$main_host[0] = $h;
			$main_host[1] = $pgb_session_info{host}{$h}{count};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$pgb_session_info{host}}) {
			if ((($pgb_session_info{host}{$d}{count} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $pgb_session_info{host}{$d}{count} || 0;
			} else {
				$infos{"Sum sessions < $pie_percentage_limit%"} += $pgb_session_info{host}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum sessions < $pie_percentage_limit%"};
			delete $infos{"Sum sessions < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{pgb_hostsessions_graph} = &jqplot_piegraph($graphid++, 'graph_pgb_hostsessions', 'Sessions per host', %infos);
	$sess_host_info = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$total_count);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="pgbsessions-per-host">
		<h2 class="col-md-12"><i class="glyphicon icon-sitemap"></i> Sessions per host</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_host[0]</span> <span class="figure-label">Main Host</span></li>
					<li><span class="figure">$total_count sessions</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#pgbsessions-per-host-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#pgbsessions-per-host-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="pgbsessions-per-host-graph">
						$drawn_graphs{pgb_hostsessions_graph}
					</div>
					<div class="tab-pane" id="pgbsessions-per-host-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Host</th>
									<th>Count</th>
									<th>Total Duration</th>
									<th>Average Duration</th>
								</tr>
							</thead>
							<tbody>
							$sess_host_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of sessions per host -->
};

	delete $drawn_graphs{pgb_hostsessions_graph};
}

sub print_app_session
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $c	   = 0;
	my $sess_app_info = '';
	my @main_app = ('unknown',0);
	foreach my $h (sort keys %{$session_info{$curdb}{app}}) {
		$sess_app_info .= "<tr><td>$h</td><td>" . &comma_numbers($session_info{$curdb}{app}{$h}{count}) .
				   "</td><td>" . &convert_time($session_info{$curdb}{app}{$h}{duration}) . "</td><td>" .
				   &convert_time($session_info{$curdb}{app}{$h}{duration} / $session_info{$curdb}{app}{$h}{count}) .
				   "</td></tr>";
		$total_count += $session_info{$curdb}{app}{$h}{count};
		if ($main_app[1] < $session_info{$curdb}{app}{$h}{count}) {
			$main_app[0] = $h;
			$main_app[1] = $session_info{$curdb}{app}{$h}{count};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$session_info{$curdb}{app}}) {
			if ((($session_info{$curdb}{app}{$d}{count} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $session_info{$curdb}{app}{$d}{count} || 0;
			} else {
				$infos{"Sum sessions < $pie_percentage_limit%"} += $session_info{$curdb}{app}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum sessions < $pie_percentage_limit%"};
			delete $infos{"Sum sessions < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{appsessions_graph} = &jqplot_piegraph($graphid++, 'graph_appsessions', 'Sessions per application', %infos);
	$sess_app_info = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$total_count);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="sessions-per-app">
		<h2 class="col-md-12"><i class="glyphicon icon-sitemap"></i> Sessions per application</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_app[0]</span> <span class="figure-label">Main Application</span></li>
					<li><span class="figure">$total_count sessions</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#sessions-per-app-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#sessions-per-app-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="sessions-per-app-graph">
						$drawn_graphs{appsessions_graph}
					</div>
					<div class="tab-pane" id="sessions-per-app-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Application</th>
									<th>Count</th>
									<th>Total Duration</th>
									<th>Average Duration</th>
								</tr>
							</thead>
							<tbody>
							$sess_app_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of sessions per app -->
};

	delete $drawn_graphs{appsessions_graph};
}

sub print_database_session
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $sess_database_info = '';
	my @main_database = ('unknown',0);
	foreach my $d (sort keys %{$session_info{$curdb}{database}}) {
		$sess_database_info .=  "<tr><td>$d</td><td>" . &comma_numbers($session_info{$curdb}{database}{$d}{count}) .
					"</td><td>" . &convert_time($session_info{$curdb}{database}{$d}{duration}) . "</td><td>" .
					&convert_time($session_info{$curdb}{database}{$d}{duration} / $session_info{$curdb}{database}{$d}{count}) .
					"</td></tr>";
		$total_count += $session_info{$curdb}{database}{$d}{count};
		if ($main_database[1] < $session_info{$curdb}{database}{$d}{count}) {
			$main_database[0] = $d;
			$main_database[1] = $session_info{$curdb}{database}{$d}{count};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$session_info{$curdb}{database}}) {
			if ((($session_info{$curdb}{database}{$d}{count} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $session_info{$curdb}{database}{$d}{count} || 0;
			} else {
				$infos{"Sum sessions < $pie_percentage_limit%"} += $session_info{$curdb}{database}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum sessions < $pie_percentage_limit%"};
			delete $infos{"Sum sessions < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{databasesessions_graph} = &jqplot_piegraph($graphid++, 'graph_databasesessions', 'Sessions per database', %infos);
	$sess_database_info = qq{<tr><td colspan="5">$NODATA</td></tr>} if (!$total_count);

	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="sessions-per-database">
		<h2 class="col-md-12"><i class="glyphicon icon-list-alt"></i> Sessions per database</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_database[0]</span> <span class="figure-label">Main Database</span></li>
					<li><span class="figure">$total_count sessions</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#sessions-per-database-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#sessions-per-database-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="sessions-per-database-graph">
						$drawn_graphs{databasesessions_graph}
					</div>
					<div class="tab-pane" id="sessions-per-database-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Database</th>
									<th>Count</th>
									<th>Total Duration</th>
									<th>Average Duration</th>
								</tr>
							</thead>
							<tbody>
							$sess_database_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of sessions per database -->
};
	delete $drawn_graphs{databasesessions_graph};
}

sub print_database_pgb_session
{
	my %infos = ();
	my $total_count = 0;
	my $sess_database_info = '';
	my @main_database = ('unknown',0);
	foreach my $d (sort keys %{$pgb_session_info{database}}) {
		$sess_database_info .=  "<tr><td>$d</td><td>" . &comma_numbers($pgb_session_info{database}{$d}{count}) .
					"</td><td>" . &convert_time($pgb_session_info{database}{$d}{duration}) . "</td><td>" .
					&convert_time($pgb_session_info{database}{$d}{duration} / $pgb_session_info{database}{$d}{count}) .
					"</td></tr>";
		$total_count += $pgb_session_info{database}{$d}{count};
		if ($main_database[1] < $pgb_session_info{database}{$d}{count}) {
			$main_database[0] = $d;
			$main_database[1] = $pgb_session_info{database}{$d}{count};
		}
	}
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$pgb_session_info{database}}) {
			if ((($pgb_session_info{database}{$d}{count} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $pgb_session_info{database}{$d}{count} || 0;
			} else {
				$infos{"Sum sessions < $pie_percentage_limit%"} += $pgb_session_info{database}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum sessions < $pie_percentage_limit%"};
			delete $infos{"Sum sessions < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{pgb_databasesessions_graph} = &jqplot_piegraph($graphid++, 'graph_pgb_databasesessions', 'Sessions per database', %infos);
	$sess_database_info = qq{<tr><td colspan="5">$NODATA</td></tr>} if (!$total_count);

	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<div class="analysis-item row" id="pgbsessions-per-database">
		<h2 class="col-md-12"><i class="glyphicon icon-list-alt"></i> Sessions per database</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_database[0]</span> <span class="figure-label">Main Database</span></li>
					<li><span class="figure">$total_count sessions</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#pgbsessions-per-database-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#pgbsessions-per-database-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="pgbsessions-per-database-graph">
						$drawn_graphs{pgb_databasesessions_graph}
					</div>
					<div class="tab-pane" id="pgbsessions-per-database-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Database</th>
									<th>User</th>
									<th>Count</th>
									<th>Total Duration</th>
									<th>Average Duration</th>
								</tr>
							</thead>
							<tbody>
							$sess_database_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of sessions per database -->
};
	delete $drawn_graphs{pgb_databasesessions_graph};
}

sub print_checkpoint
{
	my $curdb = shift;

	# checkpoint
	my %graph_data = ();
	if ($graph)
	{
		foreach my $tm (sort {$a <=> $b} keys %{$per_minute_info{$curdb}})
		{
			$tm =~ /(\d{4})(\d{2})(\d{2})/;
			my $y  = $1 - 1900;
			my $mo = $2 - 1;
			my $d  = $3;
			foreach my $h ("00" .. "23")
			{
				next if (!exists $per_minute_info{$curdb}{$tm}{$h});
				my %chk_dataavg = ();
				my %t_dataavg = ();
				my %v_dataavg = ();
				foreach my $m ("00" .. "59")
				{
					next if (!exists $per_minute_info{$curdb}{$tm}{$h}{$m});

					my $rd = &average_per_minutes($m, $avg_minutes);

					if ($checkpoint_info{wbuffer})
					{
						$chk_dataavg{wbuffer}{"$rd"} = 0 if (!exists $chk_dataavg{wbuffer}{"$rd"});
						$chk_dataavg{file_added}{"$rd"} = 0 if (!exists $chk_dataavg{file_added}{"$rd"});
						$chk_dataavg{file_removed}{"$rd"} = 0 if (!exists $chk_dataavg{file_removed}{"$rd"});
						$chk_dataavg{file_recycled}{"$rd"} = 0 if (!exists $chk_dataavg{file_recycled}{"$rd"});
						if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint})
						{
							$chk_dataavg{wbuffer}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint}{wbuffer} || 0);
							$chk_dataavg{file_added}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint}{file_added} || 0);
							$chk_dataavg{file_removed}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint}{file_removed}  || 0);
							$chk_dataavg{file_recycled}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint}{file_recycled} || 0);
						}
					}
					if (exists $checkpoint_info{distance} || exists $checkpoint_info{estimate})
					{
						$chk_dataavg{distance}{"$rd"} = 0 if (!exists $chk_dataavg{distance}{"$rd"});
						$chk_dataavg{estimate}{"$rd"} = 0 if (!exists $chk_dataavg{estimate}{"$rd"});
						if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint})
						{
							$chk_dataavg{distance}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint}{distance} || 0) * 1000;
							$chk_dataavg{distance_count}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint}{distance_count} || 1);
							$chk_dataavg{estimate}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{checkpoint}{estimate} || 0) * 1000;
						}
					}
				}

				foreach my $rd (@avgs)
				{
					my $t = timegm_nocheck(0, $rd, $h, $d, $mo, $y) * 1000;
					$t += ($timezone*1000);

					next if ($t < $t_min);
					last if ($t > $t_max);

					# Average of written checkpoint buffers and wal files
					if (exists $chk_dataavg{wbuffer})
					{
						$graph_data{wbuffer} .= "[$t, " . ($chk_dataavg{wbuffer}{"$rd"} || 0) . "],";
						$graph_data{file_added} .= "[$t, " . ($chk_dataavg{file_added}{"$rd"} || 0) . "],";
						$graph_data{file_removed} .= "[$t, " . ($chk_dataavg{file_removed}{"$rd"} || 0) . "],";
						$graph_data{file_recycled} .= "[$t, " . ($chk_dataavg{file_recycled}{"$rd"} || 0) . "],";
					}
					if (exists $chk_dataavg{distance} || $chk_dataavg{estimate})
					{
						$graph_data{distance} .= "[$t, " . int(($chk_dataavg{distance}{"$rd"}/($chk_dataavg{distance_count}{"$rd"} || 1)) || 0) . "],";
						$graph_data{estimate} .= "[$t, " . int(($chk_dataavg{estimate}{"$rd"}/($chk_dataavg{distance_count}{"$rd"} || 1)) || 0) . "],";
					}
				}
			}
		}

		foreach (keys %graph_data) {
			$graph_data{$_} =~ s/,$//;
		}
	}
	# Checkpoint buffers and files
	$drawn_graphs{checkpointwritebuffers_graph} =
		&jqplot_linegraph($graphid++, 'checkpointwritebuffers_graph', $graph_data{wbuffer}, '', '',
				'Checkpoint write buffers (' . $avg_minutes . ' minutes period)',
				'Buffers', 'Write buffers', '',  ''
		);
	$drawn_graphs{checkpointfiles_graph} =
		&jqplot_linegraph($graphid++, 'checkpointfiles_graph', $graph_data{file_added},
			$graph_data{file_removed}, $graph_data{file_recycled}, 'Checkpoint Wal files usage (' . $avg_minutes . ' minutes period)',
			'Number of files', 'Added', 'Removed', 'Recycled'
		);

	$drawn_graphs{checkpointdistance_graph} =
		&jqplot_linegraph($graphid++, 'checkpointdistance_graph', $graph_data{distance},
			$graph_data{estimate}, '', 'Checkpoint mean distance and estimate (' . $avg_minutes . ' minutes period)',
			'Number of bytes', 'distance', 'estimate'
		);

	my $checkpoint_wbuffer_peak = 0;
	my $checkpoint_wbuffer_peak_date = '';
	foreach (sort {
			$overall_checkpoint{'peak'}{$b}{checkpoint_wbuffer} <=> $overall_checkpoint{'peak'}{$a}{checkpoint_wbuffer}
		} keys %{$overall_checkpoint{'peak'}})
	{
		$checkpoint_wbuffer_peak = &comma_numbers($overall_checkpoint{'peak'}{$_}{checkpoint_wbuffer});
		$checkpoint_wbuffer_peak_date = $_;
		last;
	}
	my $walfile_usage_peak = 0;
	my $walfile_usage_peak_date = '';
	foreach (sort {
			$overall_checkpoint{'peak'}{$b}{walfile_usage} <=> $overall_checkpoint{'peak'}{$a}{walfile_usage}
		} keys %{$overall_checkpoint{'peak'}})
	{
		$walfile_usage_peak = &comma_numbers($overall_checkpoint{'peak'}{$_}{walfile_usage});
		$walfile_usage_peak_date = $_;
		last;
	}
	my $checkpoint_distance_peak = 0;
	my $checkpoint_distance_peak_date = '';
	foreach (sort {
			$overall_checkpoint{'peak'}{$b}{distance} <=> $overall_checkpoint{'peak'}{$a}{distance}
		} keys %{$overall_checkpoint{'peak'}})
	{
		$checkpoint_distance_peak = &comma_numbers(sprintf("%.2f", $overall_checkpoint{'peak'}{$_}{distance}/1024));
		$checkpoint_distance_peak_date = $_;
		last;
	}

	print $fh qq{
	<h1 class="page-header"><i class="glyphicon icon-pencil"></i> Checkpoints / Restartpoints</h1>

	<div id="checkpoints-buffers" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-paste"></i> Checkpoints Buffers</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$checkpoint_wbuffer_peak buffers</span> <span class="figure-label">Checkpoint Peak</span></li>
				<li><span class="figure">$checkpoint_wbuffer_peak_date</span> <span class="figure-label">Date</span></li>
				<li><span class="figure">$overall_checkpoint{checkpoint_write} seconds</span> <span class="figure-label">Highest write time</span></li>
				<li><span class="figure">$overall_checkpoint{checkpoint_sync} seconds</span> <span class="figure-label">Sync time</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{checkpointwritebuffers_graph}
		</div>
	</div><!-- end of Checkpoints Buffers -->
};
	delete $drawn_graphs{checkpointwritebuffers_graph};

	print $fh qq{
	<div id="checkpoints-files" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-file-alt"></i> Checkpoints Wal files</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$walfile_usage_peak files</span> <span class="figure-label">Wal files usage Peak</span></li>
				<li><span class="figure">$walfile_usage_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{checkpointfiles_graph}
		</div>
	</div><!-- end of Checkpoints Files -->
};
	delete $drawn_graphs{checkpointfiles_graph};

	print $fh qq{
	<div id="checkpoints-distance" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-file-alt"></i> Checkpoints distance</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
			<li><span class="figure">$checkpoint_distance_peak Mo</span> <span class="figure-label">Distance Peak</span></li>
			<li><span class="figure">$checkpoint_distance_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{checkpointdistance_graph}
		</div>
	</div><!-- end of Checkpoints Files -->
};
	delete $drawn_graphs{checkpointdistance_graph};


	my $buffers = '';
	my $files = '';
	my $warnings = '';
	my $distance = '';
	foreach my $d (sort {$a <=> $b} keys %{$per_minute_info{$curdb}})
	{
		$d =~ /^\d{4}(\d{2})(\d{2})$/;
		my $zday = "$abbr_month{$1} $2";
		foreach my $h (sort {$a <=> $b} keys %{$per_minute_info{$curdb}{$d}})
		{
			$buffers .= "<tr><td>$zday</td><td>$h</td>";
			$files .= "<tr><td>$zday</td><td>$h</td>";
			$warnings .= "<tr><td>$zday</td><td>$h</td>";
			$distance .= "<tr><td>$zday</td><td>$h</td>";
			$zday = '';
			my %cinf = ();
			my %rinf = ();
			my %cainf = ();
			my %rainf = ();
			my %dinf = ();
			foreach my $m (keys %{$per_minute_info{$curdb}{$d}{$h}})
			{
				if (exists $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint})
				{
					$cinf{wbuffer} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{wbuffer};
					$cinf{file_added} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{file_added};
					$cinf{file_removed} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{file_removed};
					$cinf{file_recycled} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{file_recycled};
					$cinf{write} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{write};
					$cinf{sync} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{sync};
					$cinf{total} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{total};
					$cainf{sync_files} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{sync_files};
					$cainf{sync_avg} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{sync_avg};
					$cainf{sync_longest} = $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{sync_longest}
						if ($per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{sync_longest} > $cainf{sync_longest});
				}
				if (exists $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{warning})
				{
					$cinf{warning} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{warning};
					$cinf{warning_seconds} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{warning_seconds};
				}
				if (exists $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{distance}
					|| $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{estimate})
				{
					$dinf{distance}{sum} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{distance};
					$dinf{estimate}{sum} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{estimate};
					$dinf{distance}{count} += $per_minute_info{$curdb}{$d}{$h}{$m}{checkpoint}{distance_count};
				}
			}
			if (scalar keys %cinf)
			{
				$buffers .= "<td>" . &comma_numbers($cinf{wbuffer}) .
					"</td><td>" . &comma_numbers($cinf{write}) . 's' .
					"</td><td>" . &comma_numbers($cinf{sync}) . 's' .
					"</td><td>" . &comma_numbers($cinf{total}) . 's' .
					"</td></tr>";
				$files .= "<td>" . &comma_numbers($cinf{file_added}) .
					"</td><td>" . &comma_numbers($cinf{file_removed}) .
					"</td><td>" . &comma_numbers($cinf{file_recycled}) .
					"</td><td>" . &comma_numbers($cainf{sync_files}) .
					"</td><td>" . &comma_numbers($cainf{sync_longest}) . 's' .
					"</td><td>" . &comma_numbers($cainf{sync_avg}) . 's' .
					"</td></tr>";
			}
			else
			{
				$buffers .= "<td>0</td><td>0s</td><td>0s</td><td>0s</td></tr>";
				$files .= "<td>0</td><td>0</td><td>0</td><td>0</td><td>0s</td><td>0s</td></tr>";
			}
			if (exists $cinf{warning})
			{
				$warnings .= "<td>" . &comma_numbers($cinf{warning}) . "</td><td>" .
					&comma_numbers(sprintf( "%.2f", ($cinf{warning_seconds} || 0) / ($cinf{warning} || 1))) .
					 "s</td></tr>";
			}
			else {
				$warnings .= "<td>0</td><td>0s</td></tr>";
			}
			if (exists $dinf{distance} || $dinf{estimate})
			{
				$distance .= "<td>" . &comma_numbers(sprintf( "%.2f", $dinf{distance}{sum}/($dinf{distance}{count}||1))) . " kB</td><td>" .
					&comma_numbers(sprintf( "%.2f", $dinf{estimate}{sum}/($dinf{distance}{count}||1))) .
					 " kB</td></tr>";
			}
			else {
				$distance .= "<td>0</td><td>0</td></tr>";
			}
		}
	}

	$buffers = qq{<tr><td colspan="6">$NODATA</td></tr>} if (!$buffers);
	$files = qq{<tr><td colspan="8">$NODATA</td></tr>} if (!$files);
	$warnings = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$warnings);
	$distance = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$distance);

	print $fh qq{
<div class="analysis-item row" id="checkpoint-activity">
	<h2 class="col-md-12"><i class="glyphicon icon-calendar"></i> Checkpoints Activity</h2>
	<div class="col-md-12 tabbable">
		<ul class="nav nav-tabs">
			<li class="active"><a href="#checkpoint-activity-buffers" data-toggle="tab">Checkpoints Buffers</a></li>
			<li><a href="#checkpoint-activity-files" data-toggle="tab">Checkpoints files</a></li>
			<li><a href="#checkpoint-activity-warnings" data-toggle="tab">Checkpoints Warnings</a></li>
			<li><a href="#checkpoint-activity-distance" data-toggle="tab">Checkpoints distance</a></li>
		</ul>
		<div class="tab-content">
			<div class="active tab-pane" id="checkpoint-activity-buffers">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Written&nbsp;buffers</th>
							<th>Write&nbsp;time</th>
							<th>Sync&nbsp;time</th>
							<th>Total&nbsp;time</th>
						</tr>
					</thead>
					<tbody>$buffers
					</tbody>
				</table>
			</div>
			<div class="tab-pane" id="checkpoint-activity-files">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Added</th>
							<th>Removed</th>
							<th>Recycled</th>
							<th>Synced files</th>
							<th>Longest sync</th>
							<th>Average sync</th>
						</tr>
					</thead>
					<tbody>$files
					</tbody>
				</table>
			</div>
			<div class="tab-pane" id="checkpoint-activity-warnings">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Count</th>
							<th>Avg time (sec)</th>
						</tr>
					</thead>
					<tbody>$warnings
					</tbody>
				</table>
			</div>
			<div class="tab-pane" id="checkpoint-activity-distance">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Mean distance</th>
							<th>Mean estimate</th>
						</tr>
					</thead>
					<tbody>$distance
					</tbody>
				</table>
			</div>
		</div> <!-- end of div tab-content -->
		<span class="pull-right">&uarr; <small><a href="#checkpoint-activity" class="">Back to the top of the <em>Checkpoint Activity</em> table</a></small></span>
	</div>

</div><!-- end of checkpoint activity -->
};

}

sub print_checkpoint_cause
{
	my $curdb = shift;

	my %infos = ();
	my $total_count   = 0;
	my $chkp_info = '';
	my @main_checkpoint = ('unknown',0);
	foreach my $c (sort {
			$checkpoint_info{starting}{$b} <=> $checkpoint_info{starting}{$a}
		} keys %{$checkpoint_info{starting}})
	{
		$chkp_info .= "<tr><td>$c</td><td>" . &comma_numbers($checkpoint_info{starting}{$c}) . "</td></tr>";
		$total_count += $checkpoint_info{starting}{$c};
		if ($main_checkpoint[1] < $checkpoint_info{starting}{$c})
		{
			$main_checkpoint[0] = $c;
			$main_checkpoint[1] = $checkpoint_info{starting}{$c};
		}
	}
	$chkp_info .= "<tr><th>Total</th><td>" . &comma_numbers($total_count) . "</td></tr>";

	if ($graph)
	{
		my @small = ();
		foreach my $c (sort keys %{$checkpoint_info{starting}})
		{
			if ((($checkpoint_info{starting}{$c} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$c} = $checkpoint_info{starting}{$c} || 0;
			}
			else
			{
				$infos{"Sum checkpoints cause < $pie_percentage_limit%"} += $checkpoint_info{starting}{$c} || 0;
				push(@small, $c);
			}
		}
		if ($#small == 0)
		{
			$infos{$small[0]} = $infos{"Sum checkpoints cause < $pie_percentage_limit%"};
			delete $infos{"Sum checkpoints cause < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{checkpointcause_graph} = &jqplot_piegraph($graphid++, 'graph_checkpointcause', 'Checkpoint causes', %infos);
	$total_count = &comma_numbers($total_count);
	my $database = '';
	if ($main_checkpoint[0] =~ s/^([^\.]+)\.//) {
		$database = $1;
	}

	$chkp_info = qq{<tr><td colspan="2">$NODATA</td></tr>} if (!$total_count);

	print $fh qq{
	<div class="analysis-item row" id="checkpoints-cause">
		<h2 class="col-md-12"><i class="glyphicon icon-table"></i> Checkpoint causes</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_checkpoint[0] ($main_checkpoint[1])</span> <span class="figure-label">Main checkpoint cause</span></li>
					<li><span class="figure">$total_count checkpoints</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#checkpoints-cause-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#checkpoints-cause-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="checkpoints-cause-graph">
						$drawn_graphs{checkpointcause_graph}
					</div>
					<div class="tab-pane" id="checkpoints-cause-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Cause</th>
									<th>Number of checkpoints</th>
								</tr>
							</thead>
							<tbody>
							$chkp_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of checkpoints per table -->
};
	delete $drawn_graphs{checkpointcause_graph};

}


sub print_temporary_file
{
	my $curdb = shift;

	# checkpoint
	my %graph_data = ();
	if ($graph)
	{
		foreach my $tm (sort {$a <=> $b} keys %{$per_minute_info{$curdb}})
		{
			$tm =~ /(\d{4})(\d{2})(\d{2})/;
			my $y  = $1 - 1900;
			my $mo = $2 - 1;
			my $d  = $3;
			foreach my $h ("00" .. "23")
			{
				next if (!exists $per_minute_info{$curdb}{$tm}{$h});
				my %chk_dataavg = ();
				my %t_dataavg = ();
				my %v_dataavg = ();
				foreach my $m ("00" .. "59")
				{
					next if (!exists $per_minute_info{$curdb}{$tm}{$h}{$m});
					my $rd = &average_per_minutes($m, $avg_minutes);
					if ($tempfile_info{$curdb}{count})
					{
						$t_dataavg{size}{"$rd"} = 0 if (!exists $t_dataavg{size}{"$rd"});
						$t_dataavg{count}{"$rd"} = 0 if (!exists $t_dataavg{count}{"$rd"});
						if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{'tempfile'})
						{
							$t_dataavg{size}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{'tempfile'}{size} || 0);
							$t_dataavg{count}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{'tempfile'}{count} || 0);
						}
					}
				}

				foreach my $rd (@avgs)
				{
					my $t = timegm_nocheck(0, $rd, $h, $d, $mo, $y) * 1000;
					$t += ($timezone*1000);

					next if ($t < $t_min);
					last if ($t > $t_max);

					if (exists $t_dataavg{size})
					{
						$graph_data{size} .= "[$t, " . ($t_dataavg{size}{"$rd"} || 0) . "],";
						$graph_data{count} .= "[$t, " . ($t_dataavg{count}{"$rd"} || 0) . "],";
					}
				}
			}
		}
		foreach (keys %graph_data) {
			$graph_data{$_} =~ s/,$//;
		}
	}
	# Temporary file size
	$drawn_graphs{temporarydata_graph} =
		&jqplot_linegraph($graphid++, 'temporarydata_graph', $graph_data{size}, '', '',
			'Size of temporary files (' . $avg_minutes . ' minutes period)',
			'Size of files', 'Size of files'
		);
	# Temporary file number
	$drawn_graphs{temporaryfile_graph} =
		&jqplot_linegraph($graphid++, 'temporaryfile_graph', $graph_data{count}, '', '',
			'Number of temporary files (' . $avg_minutes . ' minutes period)',
			'Number of files', 'Number of files'
		);

	my $tempfile_size_peak = 0;
	my $tempfile_size_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{tempfile_size} <=> $overall_stat{$curdb}{'peak'}{$a}{tempfile_size}} keys %{$overall_stat{$curdb}{'peak'}})
	{
		$tempfile_size_peak = &pretty_print_size($overall_stat{$curdb}{'peak'}{$_}{tempfile_size});
		$tempfile_size_peak_date = $_ if ($tempfile_size_peak);
		last;
	}
	print $fh qq{
	<h1 class="page-header"><i class="glyphicon icon-pencil"></i> Temporary Files</h1>

	<div id="tempfiles-size" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-resize-full"></i> Size of temporary files</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$tempfile_size_peak</span> <span class="figure-label">Temp Files size Peak</span></li>
				<li><span class="figure">$tempfile_size_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{temporarydata_graph}
		</div>
	</div><!-- end of Size of temporary files -->
};
	delete $drawn_graphs{temporarydata_graph};

	my $tempfile_count_peak = 0;
	my $tempfile_count_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{tempfile_count} <=> $overall_stat{$curdb}{'peak'}{$a}{tempfile_count}} keys %{$overall_stat{$curdb}{'peak'}})
	{
		$tempfile_count_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{tempfile_count});
		$tempfile_count_peak_date = $_ if ($tempfile_count_peak);
		last;
	}
	print $fh qq{
	<div id="tempfiles-number" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-th"></i> Number of temporary files</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$tempfile_count_peak per second</span> <span class="figure-label">Temp Files Peak</span></li>
				<li><span class="figure">$tempfile_count_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{temporaryfile_graph}
		</div>
	</div><!-- end of Number of temporary files -->
};
	delete $drawn_graphs{temporaryfile_graph};

	my $tempfiles_activity = '';
	foreach my $d (sort {$a <=> $b} keys %{$per_minute_info{$curdb}})
	{
		$d =~ /^\d{4}(\d{2})(\d{2})$/;
		my $zday = "$abbr_month{$1} $2";
		foreach my $h (sort {$a <=> $b} keys %{$per_minute_info{$curdb}{$d}})
		{
			$tempfiles_activity .= "<tr><td>$zday</td><td>$h</td>";
			$zday = "";
			my %tinf = ();
			foreach my $m (keys %{$per_minute_info{$curdb}{$d}{$h}})
			{
				if (exists $per_minute_info{$curdb}{$d}{$h}{$m}{'tempfile'})
				{
					$tinf{size} += $per_minute_info{$curdb}{$d}{$h}{$m}{'tempfile'}{size};
					$tinf{count} += $per_minute_info{$curdb}{$d}{$h}{$m}{'tempfile'}{count};
				}
			}
			if (scalar keys %tinf)
			{
				my $temp_average = &pretty_print_size(sprintf("%.2f", $tinf{size} / $tinf{count}));
				$tempfiles_activity .=  "<td>" . &comma_numbers($tinf{count}) .
							"</td><td>" . &pretty_print_size($tinf{size}) . "</td>" .
							"</td><td>$temp_average</td>";
			}
			else
			{
				$tempfiles_activity .= "<td>0</td><td>0</td><td>0</td>";
			}
		}
	}

	$tempfiles_activity = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$tempfiles_activity);

	print $fh qq{
<div class="analysis-item row" id="tempfiles-activity">
	<h2 class="col-md-12"><i class="glyphicon icon-calendar"></i> Temporary Files Activity</h2>
	<div class="col-md-12 tabbable">
		<ul class="nav nav-tabs">
			<li class="active"><a href="#tempfiles-activity-count" data-toggle="tab">Temp Files</a></li>
		</ul>
		<div class="tab-content">
			<div class="active tab-pane" id="tempfiles-activity-count">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>Count</th>
							<th>Total size</th>
							<th>Average size</th>
						</tr>
					</thead>
					<tbody>$tempfiles_activity
					</tbody>
				</table>
			</div>
		</div> <!-- end of div tab-content -->
		<span class="pull-right">&uarr; <small><a href="#tempfiles-activity" class="">Back to the top of the <em>Temporary Files Activity</em> table</a></small></span>
	</div>

</div><!-- end of tempfile activity -->
};

}

sub print_cancelled_queries
{
	my $curdb = shift;

	my %graph_data = ();
	if ($graph) {

		foreach my $tm (sort {$a <=> $b} keys %{$per_minute_info{$curdb}}) {

			$tm =~ /(\d{4})(\d{2})(\d{2})/;
			my $y  = $1 - 1900;
			my $mo = $2 - 1;
			my $d  = $3;
			foreach my $h ("00" .. "23") {
				next if (!exists $per_minute_info{$curdb}{$tm}{$h});
				my %chk_dataavg = ();
				my %t_dataavg = ();
				my %v_dataavg = ();
				foreach my $m ("00" .. "59") {
					next if (!exists $per_minute_info{$curdb}{$tm}{$h}{$m});
					my $rd = &average_per_minutes($m, $avg_minutes);
					if ($cancelled_info{count}) {
						$t_dataavg{count}{"$rd"} = 0 if (!exists $t_dataavg{count}{"$rd"});
						if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{cancelled}) {
							$t_dataavg{count}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{cancelled}{count} || 0);
						}
					}
				}

				foreach my $rd (@avgs) {
					my $t = timegm_nocheck(0, $rd, $h, $d, $mo, $y) * 1000;
					$t += ($timezone*1000);

					next if ($t < $t_min);
					last if ($t > $t_max);

					if (exists $t_dataavg{count}) {
						$graph_data{count} .= "[$t, " . ($t_dataavg{count}{"$rd"} || 0) . "],";
					}
				}
			}
		}
		foreach (keys %graph_data) {
			$graph_data{$_} =~ s/,$//;
		}
	}
	# Number of cancelled queries graph
	$drawn_graphs{cancelledqueries_graph} =
		&jqplot_linegraph($graphid++, 'cancelledqueries_graph', $graph_data{count}, '', '',
			'Number of cancelled queries (' . $avg_minutes . ' minutes period)',
			'Number of cancellation', 'Number of cancellation'
		);

	my $cancelled_count_peak = 0;
	my $cancelled_count_peak_date = '';
	foreach (sort {$overall_stat{$curdb}{'peak'}{$b}{cancelled_count} <=> $overall_stat{$curdb}{'peak'}{$a}{cancelled_count}} keys %{$overall_stat{$curdb}{'peak'}}) {
		$cancelled_count_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{cancelled_count});
		$cancelled_count_peak_date = $_;
		last;
	}
	print $fh qq{
	<div id="queries-cancelled-number" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-th"></i> Number of cancelled queries</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$cancelled_count_peak per second</span> <span class="figure-label">Cancelled query Peak</span></li>
				<li><span class="figure">$cancelled_count_peak_date</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{cancelledqueries_graph}
		</div>
	</div><!-- end of Number of cancelled queries -->
};
	delete $drawn_graphs{cancelledqueries_graph};
}

sub print_analyze_per_table
{
	my $curdb = shift;

	# ANALYZE stats per table
	my %infos = ();
	my $total_count   = 0;
	my $analyze_info = '';
	my @main_analyze = ('unknown',0);
	foreach my $t (sort {
			$autoanalyze_info{$curdb}{tables}{$b}{analyzes} <=> $autoanalyze_info{$curdb}{tables}{$a}{analyzes}
		} keys %{$autoanalyze_info{$curdb}{tables}})
	{
		$analyze_info .= "<tr><td>$t</td><td>" . $autoanalyze_info{$curdb}{tables}{$t}{analyzes} .
			"</td></tr>";
		$total_count += $autoanalyze_info{$curdb}{tables}{$t}{analyzes};
		if ($main_analyze[1] < $autoanalyze_info{$curdb}{tables}{$t}{analyzes})
		{
			$main_analyze[0] = $t;
			$main_analyze[1] = $autoanalyze_info{$curdb}{tables}{$t}{analyzes};
		}
	}
	$analyze_info .= "<tr><th>Total</th><td>" . &comma_numbers($total_count) . "</td></tr>";

	if ($graph)
	{
		my @small = ();
		foreach my $d (sort keys %{$autoanalyze_info{$curdb}{tables}})
		{
			if ((($autoanalyze_info{$curdb}{tables}{$d}{analyzes} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$infos{$d} = $autoanalyze_info{$curdb}{tables}{$d}{analyzes} || 0;
			}
			else
			{
				$infos{"Sum analyzes < $pie_percentage_limit%"} += $autoanalyze_info{$curdb}{tables}{$d}{analyzes} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0)
		{
			$infos{$small[0]} = $infos{"Sum analyzes < $pie_percentage_limit%"};
			delete $infos{"Sum analyzes < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{tableanalyzes_graph} = &jqplot_piegraph($graphid++, 'graph_tableanalyzes', 'Analyzes per tables', %infos);
	$total_count = &comma_numbers($total_count);
	my $database = '';
	if ($main_analyze[0] =~ s/^([^\.]+)\.//) {
		$database = $1;
	}

	$analyze_info = qq{<tr><td colspan="2">$NODATA</td></tr>} if (!$total_count);

	print $fh qq{
	<div class="analysis-item row" id="analyzes-per-table">
		<h2 class="col-md-12"><i class="glyphicon icon-table"></i> Analyzes per table</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_analyze[0] ($main_analyze[1])</span> <span class="figure-label">Main table analyzed (database $database)</span></li>
					<li><span class="figure">$total_count analyzes</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#analyzes-per-table-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#analyzes-per-table-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="analyzes-per-table-graph">
						$drawn_graphs{tableanalyzes_graph}
					</div>
					<div class="tab-pane" id="analyzes-per-table-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Table</th>
									<th>Number of analyzes</th>
								</tr>
							</thead>
							<tbody>
							$analyze_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of analyzes per table -->
};
	delete $drawn_graphs{tableanalyzes_graph};

}

sub print_vacuum
{
	my $curdb = shift;

	# checkpoint
	my %graph_data = ();
	foreach my $tm (sort {$a <=> $b} keys %{$per_minute_info{$curdb}})
	{
		$tm =~ /(\d{4})(\d{2})(\d{2})/;
		my $y  = $1 - 1900;
		my $mo = $2 - 1;
		my $d  = $3;
		my $has_data = 0;
		foreach my $h ("00" .. "23")
		{
			next if (!exists $per_minute_info{$curdb}{$tm}{$h});
			my %chk_dataavg = ();
			my %t_dataavg = ();
			my %v_dataavg = ();
			foreach my $m ("00" .. "59")
			{
				next if (!exists $per_minute_info{$curdb}{$tm}{$h}{$m});

				my $rd = &average_per_minutes($m, $avg_minutes);
				$v_dataavg{acount}{"$rd"} = 0 if (!exists $v_dataavg{acount}{"$rd"});
				$v_dataavg{vcount}{"$rd"} = 0 if (!exists $v_dataavg{vcount}{"$rd"});
				$v_dataavg{vmax}{"$rd"} = 0 if (!exists $v_dataavg{vmax}{"$rd"});
				$v_dataavg{vmin}{"$rd"} = 0 if (!exists $v_dataavg{vmin}{"$rd"});

				if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{autovacuum}) {
					$v_dataavg{vcount}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{autovacuum}{count} || 0);

					# Search minimum and maximum during this minute
					foreach my $s (keys %{$per_minute_info{$curdb}{$tm}{$h}{$m}{autovacuum}{second}}) {
						$v_dataavg{vmax}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{autovacuum}{second}{$s}
							if ($per_minute_info{$curdb}{$tm}{$h}{$m}{autovacuum}{second}{$s} > $v_dataavg{vmax}{"$rd"});
						$v_dataavg{vmin}{"$rd"} = $per_minute_info{$curdb}{$tm}{$h}{$m}{autovacuum}{second}{$s}
							if ($per_minute_info{$curdb}{$tm}{$h}{$m}{autovacuum}{second}{$d} < $v_dataavg{vmin}{"$rd"});
					}
					# delete $per_minute_info{$curdb}{$tm}{$h}{$m}{autovacuum}; # Used in report printing the #vacuums-activity
				}
				if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{autoanalyze}) {
					$v_dataavg{acount}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{autoanalyze}{count} || 0);
				}
				if ($v_dataavg{acount}{"$rd"} || $v_dataavg{vcount}{"$rd"}) {
					$has_data = 1;
				}
			}
			if ($has_data)
			{
				foreach my $rd (@avgs)
				{
					my $t = timegm_nocheck(0, $rd, $h, $d, $mo, $y) * 1000;
					$t += ($timezone*1000);

					next if ($t < $t_min);
					last if ($t > $t_max);

					if (scalar keys %v_dataavg) {
						# Average autovacuums per minute
						$graph_data{autovacuum_avg} .= "[$t, " . int(($v_dataavg{vcount}{"$rd"} || 0) / (60 * $avg_minutes)) . "],";

						# Max autovacuums per minute
						$graph_data{autovacuum_max} .= "[$t, " . ($v_dataavg{vmax}{"$rd"} || 0) . "],";

						# Min autovacuums per minute
						$graph_data{autovacuum_min} .= "[$t, " . ($v_dataavg{vmin}{"$rd"} || 0) . "],";
					}
					if (exists $v_dataavg{vcount}{"$rd"}) {
						$graph_data{vcount} .= "[$t, " . ($v_dataavg{vcount}{"$rd"} || 0) . "],";
					}
					if (exists $v_dataavg{acount}{"$rd"}) {
						$graph_data{acount} .= "[$t, " . ($v_dataavg{acount}{"$rd"} || 0) . "],";
					}

				}
			}
		}
	}
	foreach (keys %graph_data) {
		$graph_data{$_} =~ s/,$//;
	}
	# VACUUMs vs ANALYZEs chart
	$drawn_graphs{autovacuum_graph} = $NODATA;
	$drawn_graphs{autovacuumpersecond_graph} = $NODATA;
	if ($graph)
	{
		$drawn_graphs{autovacuum_graph} = &jqplot_linegraph($graphid++, 'autovacuum_graph', $graph_data{vcount}, $graph_data{acount},
		'', 'Autovacuum actions (' . $avg_minutes . ' minutes period)', '', 'VACUUMs', 'ANALYZEs'
		);

		$drawn_graphs{autovacuumspersecond_graph} = &jqplot_linegraph($graphid++, 'autovacuumspersecond_graph', $graph_data{autovacuum_max},
		$graph_data{autovacuum_avg}, $graph_data{autovacuum_min}, 'Average Autovacuum Duration (' . $avg_minutes . ' minutes average)',
		'Average Autovacuum Duration', 'Maximum', 'Average', 'Mininum'
		);

	}

	my $vacuum_size_peak = 0;
	my $vacuum_size_peak_date = '';
	foreach (sort {
			$overall_stat{$curdb}{'peak'}{$b}{vacuum_size} <=> $overall_stat{$curdb}{'peak'}{$a}{vacuum_size}
		} keys %{$overall_stat{$curdb}{'peak'}})
	{
		$vacuum_size_peak = &comma_numbers($overall_stat{$curdb}{'peak'}{$_}{vacuum_size});
		$vacuum_size_peak_date = $_;
		last;
	}
	my $autovacuum_peak_system_usage_db = '';
	if ($autovacuum_info{$curdb}{peak}{system_usage}{table} =~ s/^([^\.]+)\.//) {
		$autovacuum_peak_system_usage_db = $1;
	}
	my $autoanalyze_peak_system_usage_db = '';
	if ($autoanalyze_info{$curdb}{peak}{system_usage}{table} =~ s/^([^\.]+)\.//) {
		$autoanalyze_peak_system_usage_db = $1;
	}
	$autovacuum_info{$curdb}{peak}{system_usage}{elapsed} ||= 0;
	$autoanalyze_info{$curdb}{peak}{system_usage}{elapsed} ||= 0;
	print $fh qq{
	<h1 class="page-header"><i class="glyphicon icon-cogs"></i> Vacuums</h1>

	<div id="vacuums-count" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-pencil"></i> Vacuums / Analyzes Distribution</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$autovacuum_info{$curdb}{peak}{system_usage}{elapsed} sec</span> <span class="figure-label">Highest CPU-cost vacuum <br />Table $autovacuum_info{$curdb}{peak}{system_usage}{table} <br />Database $autovacuum_peak_system_usage_db</span></li>
				<li><span class="figure">$autovacuum_info{$curdb}{peak}{system_usage}{date}</span> <span class="figure-label">Date</span></li>
				<li><span class="figure">$autoanalyze_info{$curdb}{peak}{system_usage}{elapsed} sec</span> <span class="figure-label">Highest CPU-cost analyze <br />Table $autoanalyze_info{$curdb}{peak}{system_usage}{table} <br />Database $autovacuum_peak_system_usage_db</span></li>
				<li><span class="figure">$autoanalyze_info{$curdb}{peak}{system_usage}{date}</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{autovacuum_graph}
		</div>
	</div><!-- end of Autovacuum actions -->
};
	delete $drawn_graphs{autovacuum_graph};

print $fh qq{
	<div id="autovacuums-per-second" class="analysis-item row">
	<h2 class="col-md-12"><i class="glyphicon icon-pencil"></i> Average Autovacuum Duration</h2>
	<div class="col-md-3">
		<h3 class="">Key values</h3>
		<div class="well key-figures">
			<ul>
				<li><span class="figure">$autovacuum_info{$curdb}{peak}{system_usage}{elapsed} sec</span> <span class="figure-label">Highest CPU-cost vacuum <br />Table $autovacuum_info{$curdb}{peak}{system_usage}{table} <br />Database $autovacuum_peak_system_usage_db</span></li>
				<li><span class="figure">$autovacuum_info{$curdb}{peak}{system_usage}{date}</span> <span class="figure-label">Date</span></li>
			</ul>
		</div>
	</div>
	<div class="col-md-9">
$drawn_graphs{autovacuumspersecond_graph}
		</div>
	</div><!-- end of autovacuums-per-second actions -->
};
	delete $drawn_graphs{autovacuum_graph};

	# ANALYZE stats per table
	&print_analyze_per_table($curdb);

	# VACUUM stats per table
	&print_vacuum_per_table($curdb);

	# Show tuples and pages removed per table
	&print_vacuum_tuple_removed($curdb);
	&print_vacuum_page_removed($curdb);

	my $vacuum_activity = '';
	foreach my $d (sort {$a <=> $b} keys %{$per_minute_info{$curdb}})
	{
		my $c = 1;
		$d =~ /^\d{4}(\d{2})(\d{2})$/;
		my $zday = "$abbr_month{$1} $2";
		foreach my $h (sort {$a <=> $b} keys %{$per_minute_info{$curdb}{$d}})
		{
			$vacuum_activity .= "<tr><td>$zday</td><td>$h</td>";
			$zday = "";
			my %ainf = ();
			foreach my $m (keys %{$per_minute_info{$curdb}{$d}{$h}})
			{
				if (exists $per_minute_info{$curdb}{$d}{$h}{$m}{autovacuum}{count}) {
					$ainf{vcount} += $per_minute_info{$curdb}{$d}{$h}{$m}{autovacuum}{count};
				}
				if (exists $per_minute_info{$curdb}{$d}{$h}{$m}{autoanalyze}{count}) {
					$ainf{acount} += $per_minute_info{$curdb}{$d}{$h}{$m}{autoanalyze}{count};
				}

			}
			if (scalar keys %ainf) {
				$vacuum_activity .= "<td>" . &comma_numbers($ainf{vcount}) . "</td>";
			} else {
				$vacuum_activity .= "<td>0</td>";
			}
			if (scalar keys %ainf) {
				$vacuum_activity .= "<td>" . &comma_numbers($ainf{acount}) . "</td>";
			} else {
				$vacuum_activity .= "<td>0</td>";
			}
		}
	}

	$vacuum_activity = qq{<tr><td colspan="4">$NODATA</td></tr>} if (!$vacuum_activity);

	print $fh qq{
<div class="analysis-item row" id="vacuums-activity">
	<h2 class="col-md-12"><i class="glyphicon icon-calendar"></i> Autovacuum Activity</h2>
	<div class="col-md-12 tabbable">
		<ul class="nav nav-tabs">
			<li class="active"><a href="#vacuums-activity-count" data-toggle="tab">Vacuums / Analyzes</a></li>
		</ul>
		<div class="tab-content">
			<div class="active tab-pane" id="vacuums-activity-count">
				<table class="table table-striped table-hover table-condensed">
					<thead>
						<tr>
							<th>Day</th>
							<th>Hour</th>
							<th>VACUUMs</th>
							<th>ANALYZEs</th>
						</tr>
					</thead>
					<tbody>$vacuum_activity
					</tbody>
				</table>
			</div>
		</div> <!-- end of div tab-content -->
		<span class="pull-right">&uarr; <small><a href="#vacuums-activity" class="">Back to the top of the <em>Autovacuum Activity</em> table</a></small></span>
	</div>

</div><!-- end of vacuum activity -->
};

}

sub print_vacuum_per_table
{
	my $curdb = shift;

	# VACUUM stats per table
	my $total_count   = 0;
	my $total_idxscan = 0;
	my $total_hits = 0;
	my $total_misses = 0;
	my $total_dirtied = 0;
	my $total_pins = 0;
	my $total_frozen = 0;
	my $total_records = 0;
	my $total_full_page = 0;
	my $total_bytes = 0;
	my $vacuum_info   = '';
	my @main_vacuum   = ('unknown',0);
	foreach my $t (sort {
			$autovacuum_info{$curdb}{tables}{$b}{vacuums} <=> $autovacuum_info{$curdb}{tables}{$a}{vacuums}
		} keys %{$autovacuum_info{$curdb}{tables}})
	{
		$vacuum_info .= "<tr><td>$t</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{vacuums}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{idxscans}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{hits}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{missed}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{dirtied}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{skip_pins}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{skip_frozen}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{wal_record}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{wal_full_page}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{wal_bytes}) .
			"</td></tr>";
		$total_count += $autovacuum_info{$curdb}{tables}{$t}{vacuums};
		$total_idxscan += $autovacuum_info{$curdb}{tables}{$t}{idxscans};
		$total_hits += $autovacuum_info{$curdb}{tables}{$t}{hits};
		$total_misses += $autovacuum_info{$curdb}{tables}{$t}{misses};
		$total_dirtied += $autovacuum_info{$curdb}{tables}{$t}{dirtied};
		$total_pins += $autovacuum_info{$curdb}{tables}{$t}{skip_pins};
		$total_frozen += $autovacuum_info{$curdb}{tables}{$t}{skip_frozen};
		$total_records += $autovacuum_info{$curdb}{tables}{$t}{wal_record};
		$total_full_page += $autovacuum_info{$curdb}{tables}{$t}{wal_full_page};
		$total_bytes += $autovacuum_info{$curdb}{tables}{$t}{wal_bytes};
		if ($main_vacuum[1] < $autovacuum_info{$curdb}{tables}{$t}{vacuums})
		{
			$main_vacuum[0] = $t;
			$main_vacuum[1] = $autovacuum_info{$curdb}{tables}{$t}{vacuums};
		}
	}
	$vacuum_info .= "<tr><th>Total</th><td>" . &comma_numbers($total_count);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_idxscan);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_hits);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_misses);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_dirtied);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_pins);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_frozen);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_records);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_full_page);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_bytes);
	$vacuum_info .= "</td></tr>";

	my %infos = ();
	my @small = ();
	foreach my $d (sort keys %{$autovacuum_info{$curdb}{tables}})
	{
		if ((($autovacuum_info{$curdb}{tables}{$d}{vacuums} * 100) / ($total_count||1)) > $pie_percentage_limit) {
			$infos{$d} = $autovacuum_info{$curdb}{tables}{$d}{vacuums} || 0;
		}
		else
		{
			$infos{"Sum vacuums < $pie_percentage_limit%"} += $autovacuum_info{$curdb}{tables}{$d}{vacuums} || 0;
			push(@small, $d);
		}
	}
	if ($#small == 0)
	{
		$infos{$small[0]} = $infos{"Sum vacuums < $pie_percentage_limit%"};
		delete $infos{"Sum vacuums < $pie_percentage_limit%"};
	}
	$drawn_graphs{tablevacuums_graph} = $NODATA;
	if ($graph) {
		$drawn_graphs{tablevacuums_graph} = &jqplot_piegraph($graphid++, 'graph_tablevacuums', 'Vacuums per tables', %infos);
	}
	$vacuum_info = qq{<tr><td colspan="3">$NODATA</td></tr>} if (!$total_count);
	$total_count = &comma_numbers($total_count);
	my $database = '';
	if ($main_vacuum[0] =~ s/^([^\.]+)\.//) {
		$database = $1;
	}
	print $fh qq{
	<div class="analysis-item row" id="vacuums-per-table">
		<h2 class="col-md-12"><i class="glyphicon icon-table"></i> Vacuums per table</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_vacuum[0] ($main_vacuum[1])</span> <span class="figure-label">Main table vacuumed on database $database</span></li>
					<li><span class="figure">$total_count vacuums</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#vacuums-per-table-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#vacuums-per-table-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="vacuums-per-table-graph">
						$drawn_graphs{tablevacuums_graph}
					</div>
					<div class="tab-pane" id="vacuums-per-table-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr><th colspan="2">&nbsp;</th><th style="text-align:center;">Index</th><th colspan="3" style="text-align:center;">Buffer usage</th><th colspan="2" style="text-align:center;">Skipped</th><th colspan="3" style="text-align:center;">WAL usage</th>
								<tr>
									<th>Table</th>
									<th>Vacuums</th>
									<th>scans</th>
									<th>hits</th>
									<th>misses</th>
									<th>dirtied</th>
									<th>pins</th>
									<th>frozen</th>
									<th>records</th>
									<th>full page</th>
									<th>bytes</th>
								</tr>
							</thead>
							<tbody>
							$vacuum_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of vacuums per table -->
};
	delete $drawn_graphs{tablevacuums_graph};

}

sub print_vacuum_tuple_removed
{
	my $curdb = shift;

	# VACUUM stats per table
	my $total_count   = 0;
	my $total_idxscan = 0;
	my $total_tuple_remove = 0;
	my $total_tuple_remain = 0;
	my $total_tuple_notremovable = 0;
	my $total_page_remove = 0;
	my $total_page_remain = 0;
	my $vacuum_info   = '';
	my @main_tuple   = ('unknown',0);
	foreach my $t (sort {
			$autovacuum_info{$curdb}{tables}{$b}{tuples}{removed} <=> $autovacuum_info{$curdb}{tables}{$a}{tuples}{removed}
		} keys %{$autovacuum_info{$curdb}{tables}})
	{
		$vacuum_info .= "<tr><td>$t</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{vacuums}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{idxscans}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{tuples}{removed}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{tuples}{remain}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{tuples}{notremovable}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{pages}{removed}) .
			"</td><td>" . &comma_numbers($autovacuum_info{$curdb}{tables}{$t}{pages}{remain}) .
			"</td></tr>";
		$total_count += $autovacuum_info{$curdb}{tables}{$t}{vacuums};
		$total_idxscan += $autovacuum_info{$curdb}{tables}{$t}{idxscans};
		$total_tuple_remove += $autovacuum_info{$curdb}{tables}{$t}{tuples}{removed};
		$total_tuple_remain += $autovacuum_info{$curdb}{tables}{$t}{tuples}{remain};
		$total_tuple_notremovable += $autovacuum_info{$curdb}{tables}{$t}{tuples}{notremovable};
		$total_page_remove += $autovacuum_info{$curdb}{tables}{$t}{pages}{removed};
		$total_page_remain += $autovacuum_info{$curdb}{tables}{$t}{pages}{remain};
		if ($main_tuple[1] < $autovacuum_info{$curdb}{tables}{$t}{tuples}{removed})
		{
			$main_tuple[0] = $t;
			$main_tuple[1] = $autovacuum_info{$curdb}{tables}{$t}{tuples}{removed};
		}
	}
	$vacuum_info .= "<tr><th>Total</th><td>" . &comma_numbers($total_count);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_idxscan);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_tuple_remove);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_tuple_remain);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_tuple_notremovable);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_page_remove);
	$vacuum_info .= "</td><td>" . &comma_numbers($total_page_remain);
	$vacuum_info .= "</td></tr>";

	my %infos_tuple = ();
	my @small = ();
	foreach my $d (sort keys %{$autovacuum_info{$curdb}{tables}})
	{
		if ((($autovacuum_info{$curdb}{tables}{$d}{tuples}{removed} * 100) / ($total_tuple_remove||1)) > $pie_percentage_limit) {
			$infos_tuple{$d} = $autovacuum_info{$curdb}{tables}{$d}{tuples}{removed} || 0;
		}
		else
		{
			$infos_tuple{"Sum tuples removed < $pie_percentage_limit%"} += $autovacuum_info{$curdb}{tables}{$d}{tuples}{removed} || 0;
			push(@small, $d);
		}
	}
	if ($#small == 0)
	{
		$infos_tuple{$small[0]} = $infos_tuple{"Sum tuples removed < $pie_percentage_limit%"};
		delete $infos_tuple{"Sum tuples removed < $pie_percentage_limit%"};
	}
	$drawn_graphs{tuplevacuums_graph} = $NODATA;
	if ($graph) {
		$drawn_graphs{tuplevacuums_graph} = &jqplot_piegraph($graphid++, 'graph_tuplevacuums', 'Tuples removed per tables', %infos_tuple);
	}
	$vacuum_info = qq{<tr><td colspan="5">$NODATA</td></tr>} if (!$total_count);
	$total_count = &comma_numbers($total_count);
	my $database = '';
	if ($main_tuple[0] =~ s/^([^\.]+)\.//) {
		$database = $1;
	}
	print $fh qq{
	<div class="analysis-item row" id="tuples-removed-per-table">
		<h2 class="col-md-12"><i class="glyphicon icon-table"></i> Tuples removed per table</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_tuple[0] ($main_tuple[1])</span> <span class="figure-label">Main table with removed tuples on database $database</span></li>
					<li><span class="figure">$total_tuple_remove tuples</span> <span class="figure-label">Total removed</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#tuples-removed-per-table-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#tuples-removed-per-table-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="tuples-removed-per-table-graph">
						$drawn_graphs{tuplevacuums_graph}
					</div>
					<div class="tab-pane" id="tuples-removed-per-table-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr><th colspan="2">&nbsp;</th><th style="text-align:center;">Index</th><th colspan="3" style="text-align:center;">Tuples</th><th colspan="2" style="text-align:center;">Pages</th></tr>
								<tr>
									<th>Table</th>
									<th>Vacuums</th>
									<th>scans</th>
									<th>removed</th>
									<th>remain</th>
									<th>not yet removable</th>
									<th>removed</th>
									<th>remain</th>
								</tr>
							</thead>
							<tbody>
							$vacuum_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of tuples removed per table -->
};
	delete $drawn_graphs{tuplevacuums_graph};

}

sub print_vacuum_page_removed
{
	my $curdb = shift;

	# VACUUM stats per table
	my $total_count   = 0;
	my $total_idxscan = 0;
	my $total_tuple = 0;
	my $total_page = 0;
	my $vacuum_info   = '';
	my @main_tuple   = ('unknown',0);
	my @main_page   = ('unknown',0);
	my %infos_page = ();
	my @small = ();
	foreach my $t (sort {
			$autovacuum_info{$curdb}{tables}{$b}{pages}{removed} <=> $autovacuum_info{$curdb}{tables}{$a}{pages}{removed}
		} keys %{$autovacuum_info{$curdb}{tables}})
	{
		$vacuum_info .= "<tr><td>$t</td><td>" . $autovacuum_info{$curdb}{tables}{$t}{vacuums} .
			"</td><td>" . $autovacuum_info{$curdb}{tables}{$t}{idxscans} .
			"</td><td>" . $autovacuum_info{$curdb}{tables}{$t}{tuples}{removed} .
			"</td><td>" . $autovacuum_info{$curdb}{tables}{$t}{pages}{removed} .
			"</td></tr>";
		$total_count += $autovacuum_info{$curdb}{tables}{$t}{vacuums};
		$total_idxscan += $autovacuum_info{$curdb}{tables}{$t}{idxscans};
		$total_tuple += $autovacuum_info{$curdb}{tables}{$t}{tuples}{removed};
		$total_page += $autovacuum_info{$curdb}{tables}{$t}{pages}{removed};
		if ($main_page[1] < $autovacuum_info{$curdb}{tables}{$t}{pages}{removed})
		{
			$main_page[0] = $t;
			$main_page[1] = $autovacuum_info{$curdb}{tables}{$t}{pages}{removed};
		}
		if ($autovacuum_info{$curdb}{tables}{$t}{pages}{removed} > 0)
		{
			if ((($autovacuum_info{$curdb}{tables}{$t}{pages}{removed} * 100) / ($total_page || 1)) > $pie_percentage_limit) {
				$infos_page{$t} = $autovacuum_info{$curdb}{tables}{$t}{pages}{removed} || 0;
			}
			else
			{
				$infos_page{"Sum pages removed < $pie_percentage_limit%"} += $autovacuum_info{$curdb}{tables}{$t}{pages}{removed} || 0;
				push(@small, $t);
			}
		}
	}
	$vacuum_info .= "<tr><th>Total</th><td>" . &comma_numbers($total_count) . "</td><td>" . &comma_numbers($total_idxscan) .
			"</td><td>" . &comma_numbers($total_tuple) . "</td><td>" . &comma_numbers($total_page) . "</td></tr>";

	if ($#small == 0)
	{
		$infos_page{$small[0]} = $infos_page{"Sum pages removed < $pie_percentage_limit%"};
		delete $infos_page{"Sum pages removed < $pie_percentage_limit%"};
	}
	$drawn_graphs{pagevacuums_graph} = $NODATA;
	if ($graph) {
		$drawn_graphs{pagevacuums_graph} = &jqplot_piegraph($graphid++, 'graph_pagevacuums', 'Pages removed per tables', %infos_page);
	}
	$vacuum_info = qq{<tr><td colspan="5">$NODATA</td></tr>} if (!$total_count);
	$total_count = &comma_numbers($total_count);
	my $database = 'unknown';
	if ($main_page[0] =~ s/^([^\.]+)\.//) {
		$database = $1;
	}
	print $fh qq{
	<div class="analysis-item row" id="pages-removed-per-table">
		<h2 class="col-md-12"><i class="glyphicon icon-table"></i> Pages removed per table</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_page[0] ($main_page[1])</span> <span class="figure-label">Main table with removed pages on database $database</span></li>
					<li><span class="figure">$total_page pages</span> <span class="figure-label">Total removed</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#pages-removed-per-table-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#pages-removed-per-table-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="pages-removed-per-table-graph">
						$drawn_graphs{pagevacuums_graph}
					</div>
					<div class="tab-pane" id="pages-removed-per-table-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Table</th>
									<th>Number of vacuums</th>
									<th>Index scans</th>
									<th>Tuples removed</th>
									<th>Pages removed</th>
								</tr>
							</thead>
							<tbody>
							$vacuum_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of pages removed per table -->
};
	delete $drawn_graphs{pagevacuums_graph};

}

sub print_lock_type
{
	my $curdb = shift;

	my %locktype = ();
	my $total_count = 0;
	my $total_duration = 0;
	my $locktype_info = '';
	my @main_locktype = ('unknown',0);
	foreach my $t (sort keys %{$lock_info{$curdb}}) {
		$locktype_info .= "<tr><td>$t</td><td></td><td>" . &comma_numbers($lock_info{$curdb}{$t}{count}) .
				  "</td><td>" . &convert_time($lock_info{$curdb}{$t}{duration}) . "</td><td>" .
				  &convert_time($lock_info{$curdb}{$t}{duration} / ($lock_info{$curdb}{$t}{count} || 1)) . "</td></tr>";
		$total_count += $lock_info{$curdb}{$t}{count};
		$total_duration += $lock_info{$curdb}{$t}{duration};
		if ($main_locktype[1] < $lock_info{$curdb}{$t}{count}) {
			$main_locktype[0] = $t;
			$main_locktype[1] = $lock_info{$curdb}{$t}{count};
		}
		foreach my $o (sort keys %{$lock_info{$curdb}{$t}}) {
			next if (($o eq 'count') || ($o eq 'duration') || ($o eq 'chronos'));
			$locktype_info .= "<tr><td></td><td>$o</td><td>" . &comma_numbers($lock_info{$curdb}{$t}{$o}{count}) .
					  "</td><td>" . &convert_time($lock_info{$curdb}{$t}{$o}{duration}) . "</td><td>" .
					  &convert_time($lock_info{$curdb}{$t}{$o}{duration} / $lock_info{$curdb}{$t}{$o}{count}) .
					  "</td></tr>\n";
		}
	}
	if ($total_count > 0) {
		$locktype_info .= "<tr><td></td><th>Total</th><td>" . &comma_numbers($total_count) .
				  "</td><td>" . &convert_time($total_duration) . "</td><td>" .
				  &convert_time($total_duration / ($total_count || 1)) . "</td></tr>";
	} else {
		$locktype_info = qq{<tr><td colspan="5">$NODATA</td></tr>};
	}
	if ($graph) {
		my @small    = ();
		foreach my $d (sort keys %{$lock_info{$curdb}}) {
			if ((($lock_info{$curdb}{$d}{count} * 100) / ($total_count||1)) > $pie_percentage_limit) {
				$locktype{$d} = $lock_info{$curdb}{$d}{count} || 0;
			} else {
				$locktype{"Sum lock types < $pie_percentage_limit%"} += $lock_info{$curdb}{$d}{count} || 0;
				push(@small, $d);

			}
		}
		if ($#small == 0) {
			$locktype{$small[0]} = $locktype{"Sum types < $pie_percentage_limit%"};
			delete $locktype{"Sum lock types < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{lockbytype_graph} = &jqplot_piegraph($graphid++, 'graph_lockbytype', 'Type of locks', %locktype);
	$total_count = &comma_numbers($total_count);
	print $fh qq{
	<h1 class="page-header"><i class="glyphicon icon-lock"></i> Locks</h1>
	<div class="analysis-item row" id="locks-type">
		<h2 class="col-md-12"><i class="glyphicon icon-lock"></i> Locks by types</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_locktype[0]</span> <span class="figure-label">Main Lock Type</span></li>
					<li><span class="figure">$total_count locks</span> <span class="figure-label">Total</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#locks-types-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#locks-types-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="locks-types-graph">
						$drawn_graphs{lockbytype_graph}
					</div>
					<div class="tab-pane" id="locks-types-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Type</th>
									<th>Object</th>
									<th>Count</th>
									<th>Total Duration</th>
									<th>Average Duration (s)</th>
								</tr>
							</thead>
							<tbody>
							$locktype_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of locks by type -->
};
	delete $drawn_graphs{lockbytype_graph};
}

sub print_query_type
{
	my $curdb = shift;

	my %data = ();
	my $total_queries = 0;
	my $total_select = 0;
	my $total_write = 0;
	foreach my $a (@SQL_ACTION) {
		$total_queries += $overall_stat{$curdb}{lc($a)};
		if ($a eq 'SELECT') {
			$total_select += $overall_stat{$curdb}{lc($a)};
		} elsif ($a ne 'OTHERS') {
			$total_write += $overall_stat{$curdb}{lc($a)};
		}
	}
	my $total = $overall_stat{$curdb}{'queries_number'};

	my $querytype_info = '';
	foreach my $a (@SQL_ACTION) {
		$querytype_info .= "<tr><td>$a</td><td>" . &comma_numbers($overall_stat{$curdb}{lc($a)}) .
			"</td><td>" . sprintf("%0.2f", ($overall_stat{$curdb}{lc($a)} * 100) / ($total||1)) . "%</td></tr>";
	}
	if (($total - $total_queries) > 0) {
		$querytype_info .= "<tr><td>OTHERS</td><td>" . &comma_numbers($total - $total_queries) .
			"</td><td>" . sprintf("%0.2f", (($total - $total_queries) * 100) / ($total||1)) . "%</td></tr>";
	}
	$querytype_info = qq{<tr><td colspan="3">$NODATA</td></tr>} if (!$total);

	if ($graph && $total) {
		foreach my $t (@SQL_ACTION) {
			if ((($overall_stat{$curdb}{lc($t)} * 100) / ($total||1)) > $pie_percentage_limit) {
				$data{$t} = $overall_stat{$curdb}{lc($t)} || 0;
			} else {
				$data{"Sum query types < $pie_percentage_limit%"} += $overall_stat{$curdb}{lc($t)} || 0;
			}
		}
		if (((($total - $total_queries) * 100) / ($total||1)) > $pie_percentage_limit) {
			$data{'Others'} = $total - $total_queries;
		} else {
			$data{"Sum query types < $pie_percentage_limit%"} += $total - $total_queries;
		}
	}
	$drawn_graphs{queriesbytype_graph} = &jqplot_piegraph($graphid++, 'graph_queriesbytype', 'Type of queries', %data);

	$total_select = &comma_numbers($total_select);
	$total_write = &comma_numbers($total_write);
	print $fh qq{
	<h1 class="page-header"><i class="glyphicon icon-question-sign"></i> Queries</h1>
	<div class="analysis-item row" id="queries-by-type">
		<h2 class="col-md-12"><i class="glyphicon icon-question-sign"></i> Queries by type</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$total_select</span> <span class="figure-label">Total read queries</span></li>
					<li><span class="figure">$total_write</span> <span class="figure-label">Total write queries</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#queries-by-type-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#queries-by-type-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="queries-by-type-graph">
						$drawn_graphs{queriesbytype_graph}
					</div>
					<div class="tab-pane" id="queries-by-type-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Type</th>
									<th>Count</th>
									<th>Percentage</th>
								</tr>
							</thead>
							<tbody>
							$querytype_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of queries by type -->
};
	delete $drawn_graphs{queriesbytype_graph};

}

sub print_query_per_database
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $query_database_info = '';
	my @main_database = ('unknown', 0);
	my @main_database_duration = ('unknown', 0);
	foreach my $d (sort keys %{$database_info{$curdb}}) {
		$query_database_info .= "<tr><td>$d</td><td>Total</td><td>" .
					&comma_numbers($database_info{$curdb}{$d}{count}) . "</td><td>" .
					&convert_time($database_info{$curdb}{$d}{duration}) . "</td></tr>";
		$total_count += $database_info{$curdb}{$d}{count};
		if ($main_database[1] < $database_info{$curdb}{$d}{count}) {
			$main_database[0] = $d;
			$main_database[1] = $database_info{$curdb}{$d}{count};
		}
		if ($main_database_duration[1] < $database_info{$curdb}{$d}{duration}) {
			$main_database_duration[0] = $d;
			$main_database_duration[1] = $database_info{$curdb}{$d}{duration};
		}
		foreach my $r (sort keys %{$database_info{$curdb}{$d}}) {
			next if (($r eq 'count') || ($r =~ /duration/));
			$query_database_info .= "<tr><td></td><td>$r</td><td>" .
						&comma_numbers($database_info{$curdb}{$d}{$r}) . "</td><td>" .
						&convert_time($database_info{$curdb}{$d}{"$r|duration"}) . "</td></tr>";
		}
	}

	$query_database_info = qq{<tr><td colspan="3">$NODATA</td></tr>} if (!$total_count);

	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$database_info{$curdb}}) {
			if ((($database_info{$curdb}{$d}{count} * 100) / ($total_count || 1)) > $pie_percentage_limit) {
				$infos{$d} = $database_info{$curdb}{$d}{count} || 0;
			} else {
				$infos{"Sum queries per databases < $pie_percentage_limit%"} += $database_info{$curdb}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum queries per databases < $pie_percentage_limit%"};
			delete $infos{"Sum queries per databases < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{queriesbydatabase_graph} = &jqplot_piegraph($graphid++, 'graph_queriesbydatabase', 'Queries per database', %infos);

	$main_database[1] = &comma_numbers($main_database[1]);
	$main_database_duration[1] = &convert_time($main_database_duration[1]);
	print $fh qq{
	<div class="analysis-item row" id="queries-by-database">
		<h2 class="col-md-12"><i class="glyphicon icon-question-sign"></i> Queries by database</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_database[0]</span> <span class="figure-label">Main database</span></li>
					<li><span class="figure">$main_database[1]</span> <span class="figure-label">Requests</span></li>
					<li><span class="figure">$main_database_duration[1] ($main_database_duration[0])</span></li>
					<li><span class="figure-label">Main time consuming database</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#queries-by-database-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#queries-by-database-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="queries-by-database-graph">
						$drawn_graphs{queriesbydatabase_graph}
					</div>
					<div class="tab-pane" id="queries-by-database-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Database</th>
									<th>Request type</th>
									<th>Count</th>
									<th>Duration</th>
								</tr>
							</thead>
							<tbody>
							$query_database_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of queries by database -->
};
	delete $drawn_graphs{queriesbydatabase_graph};
}

sub print_query_per_application
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $query_application_info = '';
	my @main_application = ('unknown', 0);
	my @main_application_duration = ('unknown', 0);
	foreach my $d (sort keys %{$application_info{$curdb}}) {
		$query_application_info .= "<tr><td>$d</td><td>Total</td><td>" .
					&comma_numbers($application_info{$curdb}{$d}{count}) . "</td><td>" .
					&convert_time($application_info{$curdb}{$d}{duration}) . "</td></tr>";
		$total_count += $application_info{$curdb}{$d}{count};
		if ($main_application[1] < $application_info{$curdb}{$d}{count}) {
			$main_application[0] = $d;
			$main_application[1] = $application_info{$curdb}{$d}{count};
		}
		if ($main_application_duration[1] < $application_info{$curdb}{$d}{duration}) {
			$main_application_duration[0] = $d;
			$main_application_duration[1] = $application_info{$curdb}{$d}{duration};
		}
		foreach my $r (sort keys %{$application_info{$curdb}{$d}}) {
			next if (($r eq 'count') || ($r =~ /duration/));
			$query_application_info .= "<tr><td></td><td>$r</td><td>" .
						&comma_numbers($application_info{$curdb}{$d}{$r}) . "</td><td>" .
						&convert_time($application_info{$curdb}{$d}{"$r|duration"}) . "</td></tr>";
		}
	}
	$query_application_info = qq{<tr><td colspan="3">$NODATA</td></tr>} if (!$total_count);
	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$application_info{$curdb}}) {
			if ((($application_info{$curdb}{$d}{count} * 100) / ($total_count || 1)) > $pie_percentage_limit) {
				$infos{$d} = $application_info{$curdb}{$d}{count} || 0;
			} else {
				$infos{"Sum queries per applications < $pie_percentage_limit%"} += $application_info{$curdb}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum queries per applications < $pie_percentage_limit%"};
			delete $infos{"Sum queries per applications < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{queriesbyapplication_graph} = &jqplot_piegraph($graphid++, 'graph_queriesbyapplication', 'Queries per application', %infos);

	$main_application[1] = &comma_numbers($main_application[1]);
	$main_application_duration[1] = &convert_time($main_application_duration[1]);
	print $fh qq{
	<div class="analysis-item row" id="queries-by-application">
		<h2 class="col-md-12"><i class="glyphicon icon-question-sign"></i> Queries by application</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_application[0]</span> <span class="figure-label">Main application</span></li>
					<li><span class="figure">$main_application[1]</span> <span class="figure-label">Requests</span></li>
					<li><span class="figure">$main_application_duration[1] ($main_application_duration[0])</span></li>
					<li><span class="figure-label">Main time consuming application</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#queries-by-application-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#queries-by-application-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="queries-by-application-graph">
						$drawn_graphs{queriesbyapplication_graph}
					</div>
					<div class="tab-pane" id="queries-by-application-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Application</th>
									<th>Request type</th>
									<th>Count</th>
									<th>Duration</th>
								</tr>
							</thead>
							<tbody>
							$query_application_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of queries by application -->
};
	delete $drawn_graphs{queriesbyapplication_graph};

}

sub print_query_per_user
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $total_duration = 0;
	my $query_user_info = '';
	my @main_user = ('unknown', 0);
	my @main_user_duration = ('unknown', 0);
	foreach my $d (sort keys %{$user_info{$curdb}}) {
		$query_user_info .= "<tr><td>$d</td><td>Total</td><td>" .
					&comma_numbers($user_info{$curdb}{$d}{count}) . "</td><td>" .
					&convert_time($user_info{$curdb}{$d}{duration}) . "</td></tr>";
		$total_count += $user_info{$curdb}{$d}{count};
		$total_duration += $user_info{$curdb}{$d}{duration};
		if ($main_user[1] < $user_info{$curdb}{$d}{count}) {
			$main_user[0] = $d;
			$main_user[1] = $user_info{$curdb}{$d}{count};
		}
		if ($main_user_duration[1] < $user_info{$curdb}{$d}{duration}) {
			$main_user_duration[0] = $d;
			$main_user_duration[1] = $user_info{$curdb}{$d}{duration};
		}
		foreach my $r (sort keys %{$user_info{$curdb}{$d}}) {
			next if (($r eq 'count') || ($r =~ /duration/));
			$query_user_info .= "<tr><td></td><td>$r</td><td>" .
						&comma_numbers($user_info{$curdb}{$d}{$r}) . "</td><td>" .
						&convert_time($user_info{$curdb}{$d}{"$r|duration"}) . "</td></tr>";
		}
	}
	$query_user_info = qq{<tr><td colspan="3">$NODATA</td></tr>} if (!$total_count);

	if ($graph) {
		my %small = ();
		foreach my $d (sort keys %{$user_info{$curdb}}) {
			if ((($user_info{$curdb}{$d}{count} * 100) / ($total_count || 1)) > $pie_percentage_limit) {
				$infos{queries}{$d} = $user_info{$curdb}{$d}{count} || 0;
			} else {
				$infos{queries}{"Sum queries per users < $pie_percentage_limit%"} += $user_info{$curdb}{$d}{count} || 0;
				push(@{$small{queries}}, $d);
			}
			if ((($user_info{$curdb}{$d}{duration} * 100) / ($total_duration || 1)) > $pie_percentage_limit) {
				$infos{duration}{$d} = $user_info{$curdb}{$d}{duration} || 0;
			} else {
				$infos{duration}{"Sum duration per users < $pie_percentage_limit%"} += $user_info{$curdb}{$d}{duration} || 0;
				push(@{$small{duration}}, $d);
			}
		}
		if ($#{$small{queries}} == 0) {
			$infos{queries}{$small{queries}[0]} = $infos{queries}{"Sum queries per users < $pie_percentage_limit%"};
			delete $infos{queries}{"Sum queries per users < $pie_percentage_limit%"};
		}
		if ($#{$small{duration}} == 0){
			$infos{duration}{$small{duration}[0]} = $infos{duration}{"Sum duration per users < $pie_percentage_limit%"};
			delete $infos{duration}{"Sum duration per users < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{queriesbyuser_graph} = &jqplot_piegraph($graphid++, 'graph_queriesbyuser', 'Queries per user', %{$infos{queries}});
	$drawn_graphs{durationbyuser_graph} = &jqplot_piegraph($graphid++, 'graph_durationbyuser', 'Duration per user', %{$infos{duration}});

	$main_user[1] = &comma_numbers($main_user[1]);
	$main_user_duration[1] = &convert_time($main_user_duration[1]);

	print $fh qq{
	<div class="analysis-item row" id="queries-by-user">
		<h2 class="col-md-12"><i class="glyphicon icon-question-sign"></i> Queries by user</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_user[0]</span> <span class="figure-label">Main user</span></li>
					<li><span class="figure">$main_user[1]</span> <span class="figure-label">Requests</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#queries-by-user-graph" data-toggle="tab">Queries Chart</a></li>
					<li><a href="#queries-by-user-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="queries-by-user-graph">
						$drawn_graphs{queriesbyuser_graph}
					</div>
					<div class="tab-pane" id="queries-by-user-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>User</th>
									<th>Request type</th>
									<th>Count</th>
									<th>Duration</th>
								</tr>
							</thead>
							<tbody>
							$query_user_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of queries by user -->
};
	delete $drawn_graphs{queriesbyuser_graph};

	print $fh qq{
	<div class="analysis-item row" id="duration-by-user">
		<h2 class="col-md-12"><i class="glyphicon icon-time"></i> Duration by user</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_user_duration[1] ($main_user_duration[0])</span> <span class="figure-label">Main time consuming user</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#duration-by-user-graph" data-toggle="tab">Duration Chart</a></li>
					<li><a href="#duration-by-user-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="duration-by-user-graph">
						$drawn_graphs{durationbyuser_graph}
					</div>
					<div class="tab-pane" id="duration-by-user-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>User</th>
									<th>Request type</th>
									<th>Count</th>
									<th>Duration</th>
								</tr>
							</thead>
							<tbody>
							$query_user_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of duration by user -->
};
	delete $drawn_graphs{durationbyuser_graph};

}

sub print_query_per_host
{
	my $curdb = shift;

	my %infos = ();
	my $total_count = 0;
	my $query_host_info = '';
	my @main_host = ('unknown', 0);
	my @main_host_duration = ('unknown', 0);
	foreach my $d (sort keys %{$host_info{$curdb}}) {
		$query_host_info .= "<tr><td>$d</td><td>Total</td><td>" .
					&comma_numbers($host_info{$curdb}{$d}{count}) . "</td><td>" .
					&convert_time($host_info{$curdb}{$d}{duration}) . "</td></tr>";
		$total_count += $host_info{$curdb}{$d}{count};
		if ($main_host[1] < $host_info{$curdb}{$d}{count}) {
			$main_host[0] = $d;
			$main_host[1] = $host_info{$curdb}{$d}{count};
		}
		if ($main_host_duration[1] < $host_info{$curdb}{$d}{duration}) {
			$main_host_duration[0] = $d;
			$main_host_duration[1] = $host_info{$curdb}{$d}{duration};
		}
		foreach my $r (sort keys %{$host_info{$curdb}{$d}}) {
			next if (($r eq 'count') || ($r =~ /duration/));
			$query_host_info .= "<tr><td></td><td>$r</td><td>" .
						&comma_numbers($host_info{$curdb}{$d}{$r}) . "</td><td>" .
						&convert_time($host_info{$curdb}{$d}{"$r|duration"}) . "</td></tr>";
		}
	}
	$query_host_info = qq{<tr><td colspan="3">$NODATA</td></tr>} if (!$total_count);

	if ($graph) {
		my @small = ();
		foreach my $d (sort keys %{$host_info{$curdb}}) {
			if ((($host_info{$curdb}{$d}{count} * 100) / ($total_count || 1)) > $pie_percentage_limit) {
				$infos{$d} = $host_info{$curdb}{$d}{count} || 0;
			} else {
				$infos{"Sum queries per hosts < $pie_percentage_limit%"} += $host_info{$curdb}{$d}{count} || 0;
				push(@small, $d);
			}
		}
		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum queries per hosts < $pie_percentage_limit%"};
			delete $infos{"Sum queries per hosts < $pie_percentage_limit%"};
		}
	}
	$drawn_graphs{queriesbyhost_graph} = &jqplot_piegraph($graphid++, 'graph_queriesbyhost', 'Queries per host', %infos);

	$main_host[1] = &comma_numbers($main_host[1]);
	$main_host_duration[1] = &convert_time($main_host_duration[1]);
	print $fh qq{
	<div class="analysis-item row" id="queries-by-host">
		<h2 class="col-md-12"><i class="glyphicon icon-question-sign"></i> Queries by host</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$main_host[0]</span> <span class="figure-label">Main host</span></li>
					<li><span class="figure">$main_host[1]</span> <span class="figure-label">Requests</span></li>
					<li><span class="figure">$main_host_duration[1] ($main_host_duration[0])</span></li>
					<li><span class="figure-label">Main time consuming host</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#queries-by-host-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#queries-by-host-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="queries-by-host-graph">
						$drawn_graphs{queriesbyhost_graph}
					</div>
					<div class="tab-pane" id="queries-by-host-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Host</th>
									<th>Request type</th>
									<th>Count</th>
									<th>Duration</th>
								</tr>
							</thead>
							<tbody>
							$query_host_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of queries by host -->
};
	delete $drawn_graphs{queriesbyhost_graph};

}

sub display_plan
{
	my ($id, $plan) = @_;

	# Only TEXT format plan can be sent to Depesz site.
	if ($plan !~ /Node Type:|"Node Type":|Node-Type/s) {
		return "<div id=\"$id\" class=\"sql sql-largesize\"><a href=\"#\" title=\"Click to beautify Explain Plan\" onclick=\"document.forms[0].plan.value='" . html_escape($plan) . "'; document.forms[0].submit(); return true;\"><i class=\"glyphicon icon-compass\"></i><b>Explain plan</b></a></div>\n<div style=\"width:900px;overflow:auto\">\n<pre id=\"explain_$id\">" . $plan . "</pre>\n</div>\n";
	} else {
		return "<div id=\"$id\" class=\"sql sql-largesize\"><i class=\"glyphicon icon-compass\"></i><b>Explain plan</b></a></div>\n<div style=\"width:900px;overflow:auto\">\n<pre id=\"explain_$id\">" . $plan . "</pre>\n</div>\n";
	}
}

sub print_lock_queries_report
{
	my $curdb = shift;

	my @top_locked_queries = ();
	foreach my $h (keys %{$normalyzed_info{$curdb}})
	{
		if (exists($normalyzed_info{$curdb}{$h}{locks}))
		{
			push (@top_locked_queries, [$h, $normalyzed_info{$curdb}{$h}{locks}{count}, $normalyzed_info{$curdb}{$h}{locks}{wait},
			$normalyzed_info{$curdb}{$h}{locks}{minwait}, $normalyzed_info{$curdb}{$h}{locks}{maxwait}]);
		}
	}

	# Most frequent waiting queries (N)
	@top_locked_queries = sort {$b->[2] <=> $a->[2]} @top_locked_queries;
	print $fh qq{
                <div class="analysis-item row" id="queries-most-frequent-waiting">
                        <h2 class="col-md-12"><i class="glyphicon icon-ban-circle"></i> Most frequent waiting queries (N)</h2>
                        <div class="col-md-12">
                                <table class="table table-striped" id="queries-most-frequent-waiting-table">
                                <thead>
                                        <tr>
                                                <th>Rank</th>
                                                <th>Count</th>
                                                <th>Total&nbsp;time</th>
                                                <th>Min&nbsp;time</th>
                                                <th>Max&nbsp;time</th>
                                                <th>Avg&nbsp;duration</th>
                                                <th>Query</th>
                                        </tr>
                                </thead>
                                <tbody>
};

	my $rank = 1;
	for (my $i = 0 ; $i <= $#top_locked_queries ; $i++)
	{
		my $count = &comma_numbers($top_locked_queries[$i]->[1]);
		my $total_time = &convert_time($top_locked_queries[$i]->[2]);
		my $min_time = &convert_time($top_locked_queries[$i]->[3]);
		my $max_time = &convert_time($top_locked_queries[$i]->[4]);
		my $avg_time = &convert_time($top_locked_queries[$i]->[2] / ($top_locked_queries[$i]->[1] || 1));
		my $query = &highlight_code(&anonymize_query($top_locked_queries[$i]->[0]));
		my $md5 = '';
		$md5 = 'md5: ' . md5_hex($top_locked_queries[$i]->[0]) if ($enable_checksum);
		my $example = qq{<p><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#queries-most-frequent-waiting-examples-rank-$rank">Examples</button></p>};
		my $k = $top_locked_queries[$i]->[0];
		$example = '' if (scalar keys %{$normalyzed_info{$curdb}{$k}{samples}} == 0);
		print $fh qq{
			<tr>
			<td>$rank</td>
			<td>$count</td>
			<td>$total_time</td>
			<td>$min_time</td>
			<td>$max_time</td>
			<td>$avg_time</td>
			<td id="queries-most-frequent-waiting-examples-details-rank-$rank">
				<div id="query-a-$rank" class="sql sql-mediumsize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
				 $example
			<!-- Examples collapse -->
			<div id="queries-most-frequent-waiting-examples-rank-$rank" class="collapse">
				<dl>
};
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{samples}})
		{
			my $idx = 1;
			foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}})
			{
				last if ($idx > $sample);
				$query = &highlight_code(&anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}));
				$md5 = '';
				$md5 = 'md5: ' . md5_hex($normalyzed_info{$curdb}{$k}{samples}{$d}{query}) if ($enable_checksum);
				my $details = "<b>Date:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{date}\n";
				$details .= "<b>Duration:</b> " . &convert_time($d) . "\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{duration});
				$details .= "<b>Database:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
				$details .= "<b>User:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
				$details .= "<b>Remote:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
				$details .= "<b>Application:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
				$details .= "<b>Queryid:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
				$details .= "<b>Bind query:</b> yes\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
				my $explain = '';
				if ($normalyzed_info{$curdb}{$k}{samples}{$d}{plan}) {
					$explain = &display_plan("query-a-explain-$rank", $normalyzed_info{$curdb}{$k}{samples}{$d}{plan});
				}
				print $fh qq{
					<dt>
						<div id="query-a-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
					<pre>$details</pre>
					$explain
					</dt>
};
				$idx++;

			}
			print $fh qq{
					</dl>
					<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#queries-most-frequent-waiting-examples-rank-$rank">x Hide</button></p>
				</div>
				<!-- end of example collapse -->
			</td>
		</tr>
};
		}
		$rank++;
	}
	if ($#top_locked_queries == -1) {
		print $fh qq{<tr><td colspan="7">$NODATA</td></tr>};
	}
	print $fh qq{
		</tbody>
		</table>
	</div>
</div><!-- end of queries-most-frequent-waiting -->
};

	@top_locked_queries = ();

	# Queries that waited the most
	@{$top_locked_info{$curdb}} = sort {$b->[1] <=> $a->[1]} @{$top_locked_info{$curdb}};
	print $fh qq{
		<div class="analysis-item row" id="queries-that-waited-most">
			<h2 class="col-md-12"><i class="glyphicon icon-ban-circle"></i> Queries that waited the most</h2>
			<div class="col-md-12">
				<table class="table table-striped" id="queries-that-waited-most-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Wait&nbsp;time</th>
						<th>Query</th>
					</tr>
				</thead>
				<tbody>
};

	$rank = 1;
	for (my $i = 0 ; $i <= $#{$top_locked_info{$curdb}} ; $i++)
	{
		my $query = &highlight_code(&anonymize_query($top_locked_info{$curdb}[$i]->[2]));
		my $md5 = '';
		$md5 = 'md5: ' . md5_hex($top_locked_info{$curdb}[$i]->[2]) if ($enable_checksum);
		my $details = "[ <b>Date:</b> " . ($top_locked_info{$curdb}[$i]->[1] || '');
		$details .= " - <b>Database</b>: $top_locked_info{$curdb}[$i]->[3]" if ($top_locked_info{$curdb}[$i]->[3]);
		$details .= " - <b>User:</b> $top_locked_info{$curdb}[$i]->[4]" if ($top_locked_info{$curdb}[$i]->[4]);
		$details .= " - <b>Remote:</b> $top_locked_info{$curdb}[$i]->[5]" if ($top_locked_info{$curdb}[$i]->[5]);
		$details .= " - <b>Application:</b> $top_locked_info{$curdb}[$i]->[6]" if ($top_locked_info{$curdb}[$i]->[6]);
		$details .= " - <b>Queryid:</b> $top_locked_info{$curdb}[$i]->[7]" if ($top_locked_info{$curdb}[$i]->[7]);
		$details .= " - <b>Bind query:</b> yes" if ($top_locked_info{$curdb}[$i]->[8]);
		$details .= " ]";
		my $time = &convert_time($top_locked_info{$curdb}[$i]->[0]);
		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$time</td>
				<td id="queries-that-waited-most-examples-details-rank-$rank">
					<div id="query-b-$rank" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
					<pre>$details</pre>
				</td>
				</tr>
};
		$rank++;
	}
	if ($#{$top_locked_info{$curdb}} == -1) {
		print $fh qq{<tr><td colspan="3">$NODATA</td></tr>};
	}
		print $fh qq{
		</tbody>
		</table>
	</div>
</div><!-- end of queries-that-waited-most -->
};

}

sub print_tempfile_report
{
	my $curdb = shift;

	my @top_temporary = ();
	foreach my $h (keys %{$normalyzed_info{$curdb}})
	{
		if (exists($normalyzed_info{$curdb}{$h}{tempfiles}))
		{
			push (@top_temporary, [$h, $normalyzed_info{$curdb}{$h}{tempfiles}{count}, $normalyzed_info{$curdb}{$h}{tempfiles}{size},
			$normalyzed_info{$curdb}{$h}{tempfiles}{minsize}, $normalyzed_info{$curdb}{$h}{tempfiles}{maxsize}]);
		}
	}

	# Queries generating the most temporary files (N)
	if ($#top_temporary >= 0)
	{
		@top_temporary = sort { $b->[1] <=> $a->[1] } @top_temporary;
		print $fh qq{
		<div class="analysis-item row" id="queries-generating-most-temporary-files">
			<h2 class="col-md-12"><i class="glyphicon icon-pencil"></i> Queries generating the most temporary files (N)</h2>
			<div class="col-md-12">
				<table class="table table-striped" id="queries-generating-most-temporary-files-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Count</th>
						<th>Total&nbsp;size</th>
						<th>Min&nbsp;size</th>
						<th>Max&nbsp;size</th>
						<th>Avg&nbsp;size</th>
						<th>Query</th>
					</tr>
				</thead>
				<tbody>
};
		my $rank = 1;
		for (my $i = 0 ; $i <= $#top_temporary ; $i++)
		{
			my $count = &comma_numbers($top_temporary[$i]->[1]);
			my $total_size = &pretty_print_size($top_temporary[$i]->[2]);
			my $min_size = &pretty_print_size($top_temporary[$i]->[3]);
			my $max_size = &pretty_print_size($top_temporary[$i]->[4]);
			my $avg_size = &pretty_print_size($top_temporary[$i]->[2] / ($top_temporary[$i]->[1] || 1));
			my $query = &highlight_code(&anonymize_query($top_temporary[$i]->[0]));
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($top_temporary[$i]->[0]) if ($enable_checksum);
			my $example = qq{<p><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#queries-generating-most-temporary-files-examples-rank-$rank">Examples</button></p>};
			my $k = $top_temporary[$i]->[0];
			$example = '' if (scalar keys %{$normalyzed_info{$curdb}{$k}{samples}} == 0);
			print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$count</td>
				<td>$total_size</td>
				<td>$min_size</td>
				<td>$max_size</td>
				<td>$avg_size</td>
				<td id="queries-generating-most-temporary-files-examples-details-rank-$rank">
					<div id="query-c-$rank" class="sql sql-mediumsize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
					$example
				<!-- Examples collapse -->
				<div id="queries-generating-most-temporary-files-examples-rank-$rank" class="collapse">
					<dl>
};
			if (scalar keys %{$normalyzed_info{$curdb}{$k}{samples}})
			{
				my $idx = 1;
				foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}})
				{
					last if ($idx > $sample);
					$query = &highlight_code(&anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}));
					my $md5 = '';
					$md5 = 'md5: ' . md5_hex($normalyzed_info{$curdb}{$k}{samples}{$d}{query}) if ($enable_checksum);
					my $details = "<b>Date:</b> " . $normalyzed_info{$curdb}{$k}{samples}{$d}{date} . "\n";
					$details .= "<b>Duration:</b> " . &convert_time($d) . "\n";
					$details .= "<b>Database:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
					$details .= "<b>User:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
					$details .= "<b>Remote:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
					$details .= "<b>Application:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
					$details .= "<b>Queryid:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
					if (exists $top_tempfile_info{$curdb} && $#{$top_tempfile_info{$curdb}} >= $i) {
						$details .= "<b>Info:</b> $top_tempfile_info{$curdb}[$i]->[7]" if ($top_tempfile_info{$curdb}[$i]->[7]);
					}
					print $fh qq{
						<dt>
						<div id="query-c-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5

						<pre>$details</pre>
						</dt>
};
					$idx++
				}
				print $fh qq{
					</dl>
					<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#queries-generating-most-temporary-files-examples-rank-$rank">x Hide</button></p>
				</div>
				<!-- end of example collapse -->
			</td>
		</tr>
};
			}
			$rank++;
		}
	print $fh qq{
		</tbody>
		</table>
	</div>
</div><!-- end of queries-generating-most-temporary-files -->
};

		@top_temporary = ();
	}

	# Top queries generating the largest temporary files
	if ($#{$top_tempfile_info{$curdb}} >= 0)
	{
		@{$top_tempfile_info{$curdb}} = sort {$b->[0] <=> $a->[0]} @{$top_tempfile_info{$curdb}};
		my $largest = &comma_numbers($top_temporary[0]->[0]);
		print $fh qq{
		<div class="analysis-item row" id="queries-generating-largest-temporary-files">
			<h2 class="col-md-12"><i class="glyphicon icon-pencil"></i> Queries generating the largest temporary files</h2>
			<div class="col-md-12">
				<table class="table table-striped" id="queries-generating-largest-temporary-files-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Size</th>
						<th>Query</th>
					</tr>
				</thead>
				<tbody>
};
		my $rank = 1;
		for (my $i = 0 ; $i <= $#{$top_tempfile_info{$curdb}} ; $i++)
		{
			my $size = &pretty_print_size($top_tempfile_info{$curdb}[$i]->[0]);
			my $details = "[ <b>Date:</b> $top_tempfile_info{$curdb}[$i]->[1]";
			$details .= " - <b>Database:</b> $top_tempfile_info{$curdb}[$i]->[3]" if ($top_tempfile_info{$curdb}[$i]->[3]);
			$details .= " - <b>User:</b> $top_tempfile_info{$curdb}[$i]->[4]" if ($top_tempfile_info{$curdb}[$i]->[4]);
			$details .= " - <b>Remote:</b> $top_tempfile_info{$curdb}[$i]->[5]" if ($top_tempfile_info{$curdb}[$i]->[5]);
			$details .= " - <b>Application:</b> $top_tempfile_info{$curdb}[$i]->[6]" if ($top_tempfile_info{$curdb}[$i]->[6]);
			$details .= " - <b>Queryid:</b> $top_tempfile_info{$curdb}[$i]->[8]" if ($top_tempfile_info{$curdb}[$i]->[8]);
			$details .= " ]";
			$details .= "\n<b>Info:</b> $top_tempfile_info{$curdb}[$i]->[7]" if ($top_tempfile_info{$curdb}[$i]->[7]);
			my $query = &highlight_code(&anonymize_query($top_tempfile_info{$curdb}[$i]->[2]));
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($top_tempfile_info{$curdb}[$i]->[2]) if ($enable_checksum);
			print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$size</td>
				<td id="queries-generating-largest-temporary-files-examples-details-rank-$rank">
					<div id="query-d-$rank" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
					<pre>$details</pre>
				</td>
				</tr>
};
			$rank++;
		}
		print $fh qq{
		</tbody>
		</table>
	</div>
</div><!-- end of queries-generating-largest-temporary-files -->
};
		@{$top_tempfile_info{$curdb}} = ();
	}
}

sub print_cancelled_report
{
	my $curdb = shift();

	my @top_cancelled = ();
	foreach my $h (keys %{$normalyzed_info{$curdb}}) {
		if (exists($normalyzed_info{$curdb}{$h}{cancelled})) {
			push (@top_cancelled, [$h, $normalyzed_info{$curdb}{$h}{cancelled}{count}]);
		}
	}

	# Queries generating the most cancellation (N)
	if ($#top_cancelled >= 0) {
		@top_cancelled = sort {$b->[1] <=> $a->[1]} @top_cancelled;
		print $fh qq{
		<div class="analysis-item row" id="queries-generating-most-cancellation">
			<h2 class="col-md-12"><i class="glyphicon icon-pencil"></i> Queries generating the most cancellation (N)</h2>
			<div class="col-md-12">
				<table class="table table-striped" id="queries-generating-most-cancellation-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Count</th>
						<th>Query</th>
					</tr>
				</thead>
				<tbody>
};
		my $rank = 1;
		for (my $i = 0 ; $i <= $#top_cancelled ; $i++) {
			my $count = &comma_numbers($top_cancelled[$i]->[1]);
			my $query = &highlight_code($top_cancelled[$i]->[0]);
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($top_cancelled[$i]->[0]) if ($enable_checksum);
			my $example = qq{<p><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#queries-generating-most-cancellation-examples-rank-$rank">Examples</button></p>};
			my $k = $top_cancelled[$i]->[0];
			$example = '' if (scalar keys %{$normalyzed_info{$curdb}{$k}{samples}} == 0);
			print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$count</td>
				<td id="queries-generating-most-cancellation-examples-details-rank-$rank">
					<div id="query-c-$rank" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
					$example
				<!-- Examples collapse -->
				<div id="queries-generating-most-cancellation-examples-rank-$rank" class="collapse">
					<dl>
};
			if (scalar keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
				my $idx = 1;
				foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) {
					last if ($idx > $sample);
					$query = &highlight_code($normalyzed_info{$curdb}{$k}{samples}{$d}{query});
					my $md5 = '';
					$md5 = 'md5: ' . md5_hex($normalyzed_info{$curdb}{$k}{samples}{$d}{query}) if ($enable_checksum);
					my $details = "Duration: " . &convert_time($d) . "<br />";
					$details .= "Database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}<br/>" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
					$details .= "User: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}<br/>" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
					$details .= "Remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}<br/>" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
					$details .= "Application: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}<br/>" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
					$details .= "Queryid: $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}<br/>" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
					$details .= "Bind query: yes<br/>" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
					print $fh qq{
						<dt>
						<div id="query-d-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5

						<pre>$details</pre>
						</dt>
};
				$idx++

				}
				print $fh qq{
					</dl>
					<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#queries-generating-most-cancellation-examples-rank-$rank">x Hide</button></p>
				</div>
				<!-- end of example collapse -->
			</td>
		</tr>
};
			}
			$rank++;
		}
	print $fh qq{
		</tbody>
		</table>
	</div>
</div><!-- end of queries-generating-most-cancellation -->
};

		@top_cancelled = ();
	}

	# Top queries generating the most cancellation
	if ($#{$top_cancelled_info{$curdb}} >= 0) {
		@{$top_cancelled_info{$curdb}} = sort {$b->[0] <=> $a->[0]} @{$top_cancelled_info{$curdb}};
		my $largest = &comma_numbers($top_cancelled_info{$curdb}[0]->[0]);
		print $fh qq{
		<div class="analysis-item row" id="queries-generating-most-cancelled">
			<h2 class="col-md-12"><i class="glyphicon icon-pencil"></i> Queries most cancelled</h2>
			<div class="col-md-12">
				<table class="table table-striped" id="queries-generating-most-cancelled-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Number</th>
						<th>Query</th>
					</tr>
				</thead>
				<tbody>
};
		my $rank = 1;
		for (my $i = 0 ; $i <= $#{$top_cancelled_info{$curdb}} ; $i++) {
			my $count = &comma_numbers($top_cancelled_info{$curdb}[$i]->[0]);
			my $details = "[ <b>Date:</b> $top_cancelled_info{$curdb}[$i]->[1]";
			$details .= " - <b>Database:</b> $top_cancelled_info{$curdb}[$i]->[3]" if ($top_cancelled_info{$curdb}[$i]->[3]);
			$details .= " - <b>User:</b> $top_cancelled_info{$curdb}[$i]->[4]" if ($top_cancelled_info{$curdb}[$i]->[4]);
			$details .= " - <b>Remote:</b> $top_cancelled_info{$curdb}[$i]->[5]" if ($top_cancelled_info{$curdb}[$i]->[5]);
			$details .= " - <b>Application:</b> $top_cancelled_info{$curdb}[$i]->[6]" if ($top_cancelled_info{$curdb}[$i]->[6]);
			$details .= " - <b>Queryid:</b> $top_cancelled_info{$curdb}[$i]->[7]" if ($top_cancelled_info{$curdb}[$i]->[7]);
			$details .= " - <b>Bind yes:</b> yes" if ($top_cancelled_info{$curdb}[$i]->[8]);
			$details .= " ]";
			my $query = &highlight_code(&anonymize_query($top_cancelled_info{$curdb}[$i]->[2]));
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($top_cancelled_info{$curdb}[$i]->[2]) if ($enable_checksum);
			print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$count</td>
				<td id="queries-generating-most-cancelled-examples-details-rank-$rank">
					<div id="query-d-$rank" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
					<pre>$details</pre>
				</td>
				</tr>
};
			$rank++;
		}
		print $fh qq{
		</tbody>
		</table>
	</div>
</div><!-- end of queries-generating-most-cancelled -->
};
		@{$top_cancelled_info{$curdb}} = ();
	}

}

sub print_histogram_query_times
{
	my $curdb = shift;

	my %data = ();
	my $histogram_info = '';
	my $most_range = '';
	my $most_range_value = '';

	for (my $i = 1; $i <= $#histogram_query_time; $i++) {
		$histogram_info .= "<tr><td>$histogram_query_time[$i-1]-$histogram_query_time[$i]ms</td><td>" . &comma_numbers($overall_stat{$curdb}{histogram}{query_time}{$histogram_query_time[$i-1]}) .
			"</td><td>" . sprintf("%0.2f", ($overall_stat{$curdb}{histogram}{query_time}{$histogram_query_time[$i-1]} * 100) / ($overall_stat{$curdb}{histogram}{query_total}||1)) . "%</td></tr>";
		$data{"$histogram_query_time[$i-1]-$histogram_query_time[$i]ms"} = ($overall_stat{$curdb}{histogram}{query_time}{$histogram_query_time[$i-1]} || 0);
		if ($overall_stat{$curdb}{histogram}{query_time}{$histogram_query_time[$i-1]} > $most_range_value) {
			$most_range = "$histogram_query_time[$i-1]-$histogram_query_time[$i]ms";
			$most_range_value = $overall_stat{$curdb}{histogram}{query_time}{$histogram_query_time[$i-1]};
		}
	}
	if ($overall_stat{$curdb}{histogram}{query_total} > 0) {

		$data{"> $histogram_query_time[-1]ms"} = ($overall_stat{$curdb}{histogram}{query_time}{"-1"} || 0);
		$histogram_info .= "<tr><td> &gt; $histogram_query_time[-1]ms</td><td>" . &comma_numbers($overall_stat{$curdb}{histogram}{query_time}{'-1'}) .
			"</td><td>" . sprintf("%0.2f", ($overall_stat{$curdb}{histogram}{query_time}{'-1'} * 100) / ($overall_stat{$curdb}{histogram}{query_total}||1)) . "%</td></tr>";
		$data{"> $histogram_query_time[-1]ms"} = $overall_stat{$curdb}{histogram}{query_time}{"-1"} if ($overall_stat{$curdb}{histogram}{query_time}{"-1"} > 0);
		if ($overall_stat{$curdb}{histogram}{query_time}{"-1"} > $most_range_value) {
			$most_range = "> $histogram_query_time[-1]ms";
			$most_range_value = $overall_stat{$curdb}{histogram}{query_time}{"-1"};
		}
	} else {
		$histogram_info = qq{<tr><td colspan="3">$NODATA</td></tr>};
	}
	$drawn_graphs{histogram_query_times_graph} = $NODATA;
	if ($graph) {
		$drawn_graphs{histogram_query_times_graph} = &jqplot_duration_histograph($graphid++, 'graph_histogram_query_times', 'Queries', \@histogram_query_time, %data);
	}

	$most_range_value = &comma_numbers($most_range_value) if ($most_range_value);

	print $fh qq{
	<h1 class="page-header"><i class="glyphicon icon-question-sign"></i> Top Queries</h1>
	<div class="analysis-item row" id="histogram-query-times">
		<h2 class="col-md-12"><i class="glyphicon icon-signal"></i> Histogram of query times</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$most_range_value</span> <span class="figure-label">$most_range duration</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#histogram-query-times-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#histogram-query-times-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="histogram-query-times-graph">
						$drawn_graphs{histogram_query_times_graph}
					</div>
					<div class="tab-pane" id="histogram-query-times-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Range</th>
									<th>Count</th>
									<th>Percentage</th>
								</tr>
							</thead>
							<tbody>
							$histogram_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of queries by type -->
};
	delete $drawn_graphs{histogram_query_times_graph};
}

sub print_slowest_individual_queries
{
	my $curdb = shift;

	print $fh qq{
		<div class="analysis-item row" id="slowest-individual-queries">
			<h2 class="col-md-12"><i class="glyphicon icon-spinner"></i> Slowest individual queries</h2>
			<div class="col-md-12">
				<table class="table table-striped" id="slowest-individual-queries-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Duration</th>
						<th>Query</th>
					</tr>
				</thead>
				<tbody>
};

	my $idx = 1;
	for (my $i = 0 ; $i <= $#{$top_slowest{$curdb}} ; $i++)
	{
		my $rank = $i + 1;
		my $duration = &convert_time($top_slowest{$curdb}[$i]->[0]);
		my $date = $top_slowest{$curdb}[$i]->[1] || '';
		my $details = "[ <b>Date:</b> " . ($top_slowest{$curdb}[$i]->[1] || '');
		$details .= " - <b>Database:</b> $top_slowest{$curdb}[$i]->[3]" if ($top_slowest{$curdb}[$i]->[3]);
		$details .= " - <b>User:</b> $top_slowest{$curdb}[$i]->[4]" if ($top_slowest{$curdb}[$i]->[4]);
		$details .= " - <b>Remote:</b> $top_slowest{$curdb}[$i]->[5]" if ($top_slowest{$curdb}[$i]->[5]);
		$details .= " - <b>Application:</b> $top_slowest{$curdb}[$i]->[6]" if ($top_slowest{$curdb}[$i]->[6]);
		$details .= " - <b>Queryid:</b> $top_slowest{$curdb}[$i]->[9]" if ($top_slowest{$curdb}[$i]->[9]);
		$details .= " - <b>Bind query:</b> yes" if ($top_slowest{$curdb}[$i]->[7]);
		$details .= " ]";
		my $explain = '';
		if ($top_slowest{$curdb}[$i]->[8]) {
			$explain = &display_plan("query-d-explain-$rank-$idx", $top_slowest{$curdb}[$i]->[8]);
		}
		my $query = &highlight_code(&anonymize_query($top_slowest{$curdb}[$i]->[2]));
		my $md5 = '';
		$md5 = 'md5: ' . md5_hex($top_slowest{$curdb}[$i]->[2]) if ($enable_checksum);
		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$duration</td>
				<td id="slowest-individual-queries-examples-rank-$rank">
					<div id="query-d-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
					<pre class="pre-smallfont">$details</pre>
					$explain
				</td>
				</tr>

			};
		$idx++;
	}
	if ($#{$top_slowest{$curdb}} == -1) {
		print $fh qq{<tr><td colspan="3">$NODATA</td></tr>};
	}
	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of slowest-individual-queries -->
};

}

sub print_time_consuming
{
	my $curdb = shift;

	print $fh qq{
		<div class="analysis-item row" id="time-consuming-queries">
			<h2 class="col-md-12"><i class="glyphicon icon-time"></i> Time consuming queries (N)</h2>
                        <div class="col-md-12">
                                <table class="table table-striped" id="time-consuming-queries-table">
                                <thead>
				<tr>
					<th>Rank</th>
					<th>Total duration</th>
					<th>Times executed</th>
					<th>Min duration</th>
					<th>Max duration</th>
					<th>Avg duration</th>
					<th>Query</th>
				</tr>
				</thead>
				<tbody>
};
	my $rank = 1;
	my $found = 0;
	foreach my $k (sort {$normalyzed_info{$curdb}{$b}{duration} <=> $normalyzed_info{$curdb}{$a}{duration}} keys %{$normalyzed_info{$curdb}})
	{
		next if (!$normalyzed_info{$curdb}{$k}{count} || !exists $normalyzed_info{$curdb}{$k}{duration});
		last if ($rank > $top);
		$found++;
		$normalyzed_info{$curdb}{$k}{average} = $normalyzed_info{$curdb}{$k}{duration} / $normalyzed_info{$curdb}{$k}{count};
		my $duration = &convert_time($normalyzed_info{$curdb}{$k}{duration});
		my $count = &comma_numbers($normalyzed_info{$curdb}{$k}{count});
		my $min = &convert_time($normalyzed_info{$curdb}{$k}{min});
		my $max = &convert_time($normalyzed_info{$curdb}{$k}{max});
		my $avg = &convert_time($normalyzed_info{$curdb}{$k}{average});
		my $query = &highlight_code($k);
		my $md5 = '';
		$md5 = 'md5: ' . md5_hex($k) if ($enable_checksum);
		my $details = '';
		my %hourly_count = ();
		my %hourly_duration = ();
		my $days = 0;
		foreach my $d (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}})
		{
			$d =~ /^(\d{4})(\d{2})(\d{2})$/;
			$days++;
			my $zday = "$abbr_month{$2} $3";
			my $dd = $3;
			my $mo = $2 -1 ;
			my $y = $1 - 1900;
			foreach my $h (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}{$d}})
			{
				my $t = timegm_nocheck(0, 0, $h, $dd, $mo, $y);
				$t += $timezone;
				my $ht = sprintf("%02d", (localtime($t))[2]);
				$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{average} =
					$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{duration} / ($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{count} || 1);
				$details .= "<tr><td>$zday</td><td>$ht</td><td>" .
					&comma_numbers($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{count}) .   "</td><td>" .
					&convert_time($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{duration}) . "</td><td>" .
					&convert_time($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{average}) .  "</td></tr>";
				$zday = "";
				foreach my $m (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min}})
				{
					my $rd = &average_per_minutes($m, $histo_avg_minutes);
					$hourly_count{"$ht:$rd"} += $normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min}{$m};
					$hourly_duration{"$ht:$rd"} += ($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min_duration}{$m} || 0);
				}
				if ($#histo_avgs > 0)
				{
					foreach my $rd (@histo_avgs)
					{
						next if (!exists $hourly_count{"$ht:$rd"});
						$details .= "<tr><td>$zday</td><td style=\"text-align: right\">$ht:$rd</td><td>" .
							&comma_numbers($hourly_count{"$ht:$rd"}) .   "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}) . "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}/($hourly_count{"$ht:$rd"}||1)) .  "</td></tr>";
					}
				}
			}
		}
		# Set graph dataset
		my %graph_data = ();
		foreach my $h ("00" .. "23")
		{
			foreach my $rd (@histo_avgs)
			{
				$graph_data{count} .= "['$h:$rd'," . ($hourly_count{"$h:$rd"} || 0) . "],";
				$graph_data{duration} .= "['$h:$rd'," . (int($hourly_duration{"$h:$rd"} / ($hourly_count{"$h:$rd"} || 1)) || 0) . "],";
			}
		}
		$graph_data{count} =~ s/,$//;
		$graph_data{duration} =~ s/,$//;
		%hourly_count = ();
		%hourly_duration = ();

		my $users_involved = '';
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{users}} > 0) {
			$users_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-queries-user-involved-rank-$rank">User(s) involved</button>};
		}
		my $apps_involved = '';
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{apps}} > 0) {
			$apps_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-queries-app-involved-rank-$rank">App(s) involved</button>};
		}
		my $query_histo = '';
		if ($graph) {
			$query_histo = &jqplot_histograph($graphid++, 'time_consuming_queries_details_'.$rank, $graph_data{count}, $graph_data{duration}, 'Queries', 'Avg. duration');
		}

		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$duration</td>
				<td>$count
					<p><a href="#Atime_consuming_queries_details_$rank" class="btn btn-default btn-xs" data-toggle="collapse">Details</a></p>
				</td>
				<td>$min</td>
				<td>$max</td>
				<td>$avg</td>
				<td id="time-consuming-queries-examples-details-rank-$rank">
					<div id="query-e-$rank" class="sql sql-mediumsize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
						<!-- Details collapse -->
					    <div id="Atime_consuming_queries_details_$rank" class="collapse">
						<h3>Times Reported <small>Time consuming queries #$rank</small></h3>
						$query_histo
								<table class="table table-stripped table-condensed">
									<thead>
										<tr>
											<th>Day</th>
											<th>Hour</th>
											<th>Count</th>
											<th>Duration</th>
											<th>Avg duration</th>
										</tr>
									</thead>
									<tbody>
										$details
									</tbody>
								</table>
						    <p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#Atime_consuming_queries_details_$rank">x Hide</button></p>
						</div><!-- end of details collapse -->
	<p> <button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-queries-examples-rank-$rank">Examples</button> $users_involved $apps_involved</p>
};
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{users}} > 0)
		{
			print $fh qq{
						<!-- Involved users list collapse -->
						<div id="time-consuming-queries-user-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$normalyzed_info{$curdb}{$k}{users}{$b}{duration} <=> $normalyzed_info{$curdb}{$k}{users}{$a}{duration}} keys %{$normalyzed_info{$curdb}{$k}{users}})
			{
				if ($normalyzed_info{$curdb}{$k}{users}{$u}{duration} > 0) {
					my $details = "[ <b>User:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($normalyzed_info{$curdb}{$k}{users}{$u}{duration});
					$details .= " - <b>Times executed:</b> $normalyzed_info{$curdb}{$k}{users}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-queries-user-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of user involved collapse -->
};
		}

		if (scalar keys %{$normalyzed_info{$curdb}{$k}{apps}} > 0)
		{
			print $fh qq{
						<!-- Involved apps list collapse -->
						<div id="time-consuming-queries-app-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$normalyzed_info{$curdb}{$k}{apps}{$b}{duration} <=> $normalyzed_info{$curdb}{$k}{apps}{$a}{duration}} keys %{$normalyzed_info{$curdb}{$k}{apps}})
			{
				if ($normalyzed_info{$curdb}{$k}{apps}{$u}{duration} > 0)
				{
					my $details = "[ <b>Application:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($normalyzed_info{$curdb}{$k}{apps}{$u}{duration});
					$details .= " - <b>Times executed:</b> $normalyzed_info{$curdb}{$k}{apps}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-queries-app-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of app involved collapse -->
};
		}
		print $fh qq{
						<!-- Examples collapse -->
						<div id="time-consuming-queries-examples-rank-$rank" class="collapse">
							<dl>
};

		my $idx = 1;
		foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}})
		{
			last if ($idx > $sample);
			my $details = "<b>Date:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{date}\n";
			$details .= "<b>Duration:</b> " . &convert_time($d) . "\n";
			$details .= "<b>Database:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
			$details .= "<b>User:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
			$details .= "<b>Remote:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
			$details .= "<b>Application:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
			$details .= "<b>Queryid:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
			$details .= "<b>Bind query:</b> yes\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
			my $explain = '';
			if ($normalyzed_info{$curdb}{$k}{samples}{$d}{plan}) {
				$explain = &display_plan("query-e-explain-$rank-$idx", $normalyzed_info{$curdb}{$k}{samples}{$d}{plan});
			}
			$query = &highlight_code(&anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}));
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($normalyzed_info{$curdb}{$k}{samples}{$d}{query}) if ($enable_checksum);
			print $fh qq{
								<dt>
								<div id="query-e-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
								<pre>$details</pre>
								$explain
								</dt>
};
			$idx++;
		}
		print $fh qq{
							</dl>
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-queries-examples-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of details collapse -->
					</td>
				</tr>
};
		$rank++;
	}
	if (!$found) {
		print $fh qq{<tr><td colspan="3">$NODATA</td></tr>};
	}
	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of time-consuming-queries -->
};

}

sub print_most_frequent
{
	my $curdb = shift;

        print $fh qq{
                <div class="analysis-item row" id="most-frequent-queries">
                        <h2 class="col-md-12"><i class="glyphicon icon-signal"></i> Most frequent queries (N)</h2>
                        <div class="col-md-12">
                                <table class="table table-striped" id="most-frequent-queries-table">
                                <thead>
                                <tr>
                                        <th>Rank</th>
                                        <th>Times executed</th>
                                        <th>Total duration</th>
                                        <th>Min duration</th>
                                        <th>Max duration</th>
                                        <th>Avg duration</th>
                                        <th>Query</th>
                                </tr>
                                </thead>
                                <tbody>
};
	my $rank = 1;
	foreach my $k (sort {
			$normalyzed_info{$curdb}{$b}{count} <=> $normalyzed_info{$curdb}{$a}{count}
				or $normalyzed_info{$curdb}{$b}{duration} <=> $normalyzed_info{$curdb}{$a}{duration}
		} keys %{$normalyzed_info{$curdb}})
	{
		next if (!$normalyzed_info{$curdb}{$k}{count});
		last if ($rank > $top);
		$normalyzed_info{$curdb}{$k}{average} = $normalyzed_info{$curdb}{$k}{duration} / $normalyzed_info{$curdb}{$k}{count};
		my $duration = &convert_time($normalyzed_info{$curdb}{$k}{duration});
		my $count = &comma_numbers($normalyzed_info{$curdb}{$k}{count});
		my $min = &convert_time($normalyzed_info{$curdb}{$k}{min});
		my $max = &convert_time($normalyzed_info{$curdb}{$k}{max});
		my $avg = &convert_time($normalyzed_info{$curdb}{$k}{average});
		my $query = &highlight_code($k);
		my $md5 = '';
		$md5 = 'md5: ' . md5_hex($k) if ($enable_checksum);
		my %hourly_count = ();
		my %hourly_duration = ();
		my $days = 0;
		my $details = '';
		foreach my $d (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}})
		{
			$d =~ /^(\d{4})(\d{2})(\d{2})$/;
			$days++;
			my $zday = "$abbr_month{$2} $3";
			my $dd = $3;
			my $mo = $2 - 1;
			my $y = $1 - 1900;
			foreach my $h (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}{$d}})
			{
				my $t = timegm_nocheck(0, 0, $h, $dd, $mo, $y);
				$t += $timezone;
				my $ht = sprintf("%02d", (localtime($t))[2]);
				$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{average} =
					$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{duration} / $normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{count};
				$details .= "<tr><td>$zday</td><td>$ht</td><td>" .
					&comma_numbers($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{count}) .   "</td><td>" .
					&convert_time($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{duration}) . "</td><td>" .
					&convert_time($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{average}) .  "</td></tr>";
				$zday = "";
				foreach my $m (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min}})
				{
					my $rd = &average_per_minutes($m, $histo_avg_minutes);
					$hourly_count{"$ht:$rd"} += $normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min}{$m};
					$hourly_duration{"$ht:$rd"} += ($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min_duration}{$m} || 0);
				}
				if ($#histo_avgs > 0)
				{
					foreach my $rd (@histo_avgs)
					{
						next if (!exists $hourly_count{"$ht:$rd"});
						$details .= "<tr><td>$zday</td><td style=\"text-align: right\">$ht:$rd</td><td>" .
							&comma_numbers($hourly_count{"$ht:$rd"}) .   "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}) . "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}/($hourly_count{"$ht:$rd"}||1)) .  "</td></tr>";
					}
				}
			}
		}
		# Set graph dataset
		my %graph_data = ();
		foreach my $h ("00" .. "23")
		{
			foreach my $rd (@histo_avgs)
			{
				$graph_data{count} .= "['$h:$rd'," . ($hourly_count{"$h:$rd"} || 0) . "],";
				$graph_data{duration} .= "['$h:$rd'," . (int($hourly_duration{"$h:$rd"} / ($hourly_count{"$h:$rd"} || 1)) || 0) . "],";
			}
		}
		$graph_data{count} =~ s/,$//;
		$graph_data{duration} =~ s/,$//;
		%hourly_count = ();
		%hourly_duration = ();

		my $query_histo = '';
		if ($graph) {
			$query_histo = &jqplot_histograph($graphid++, 'most_frequent_queries_details_'.$rank, $graph_data{count}, $graph_data{duration}, 'Queries', 'Avg. duration');
		}

		my $users_involved = '';
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{users}} > 0) {
			$users_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#most-frequent-queries-user-involved-rank-$rank">User(s) involved</button>};
		}
		my $apps_involved = '';
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{apps}} > 0) {
			$apps_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#most-frequent-queries-app-involved-rank-$rank">App(s) involved</button>};
		}

		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$count
					<p><a href="#Amost_frequent_queries_details_$rank" class="btn btn-default btn-xs" data-toggle="collapse">Details</a></p>
				</td>
				<td>$duration</td>
				<td>$min</td>
				<td>$max</td>
				<td>$avg</td>
				<td id="most-frequent-queries-examples-details-rank-$rank">
					<div id="query-f-$rank" class="sql sql-mediumsize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
						<!-- Details collapse -->
					    <div id="Amost_frequent_queries_details_$rank" class="collapse">
						<h3>Times Reported <small>Time consuming queries #$rank</small></h3>
						$query_histo
								<table class="table table-stripped table-condensed">
									<thead>
										<tr>
											<th>Day</th>
											<th>Hour</th>
											<th>Count</th>
											<th>Duration</th>
											<th>Avg duration</th>
										</tr>
									</thead>
									<tbody>
										$details
									</tbody>
								</table>
						    <p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#Amost_frequent_queries_details_$rank">x Hide</button></p>
						</div><!-- end of details collapse -->
	<p><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#most-frequent-queries-examples-rank-$rank">Examples</button> $users_involved $apps_involved</p>
};
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{users}} > 0)
		{
			print $fh qq{
						<!-- Involved users list collapse -->
						<div id="most-frequent-queries-user-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$normalyzed_info{$curdb}{$k}{users}{$b}{duration} <=> $normalyzed_info{$curdb}{$k}{users}{$a}{duration}} keys %{$normalyzed_info{$curdb}{$k}{users}})
			{
				if ($normalyzed_info{$curdb}{$k}{users}{$u}{duration} > 0)
				{
					my $details = "[ <b>User:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($normalyzed_info{$curdb}{$k}{users}{$u}{duration});
					$details .= " - <b>Times executed:</b> $normalyzed_info{$curdb}{$k}{users}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#most-frequent-queries-user-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of user involved collapse -->
};
		}
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{apps}} > 0)
		{
			print $fh qq{
						<!-- Involved apps list collapse -->
						<div id="most-frequent-queries-app-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$normalyzed_info{$curdb}{$k}{apps}{$b}{duration} <=> $normalyzed_info{$curdb}{$k}{apps}{$a}{duration}} keys %{$normalyzed_info{$curdb}{$k}{apps}})
			{
				if ($normalyzed_info{$curdb}{$k}{apps}{$u}{duration} > 0)
				{
					my $details = "[ <b>Application:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($normalyzed_info{$curdb}{$k}{apps}{$u}{duration});
					$details .= " - <b>Times executed:</b> $normalyzed_info{$curdb}{$k}{apps}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#most-frequent-queries-app-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of app involved collapse -->
};
		}
		print $fh qq{

						<!-- Examples collapse -->
						<div id="most-frequent-queries-examples-rank-$rank" class="collapse">
							<dl>
};

		my $idx = 1;
		foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}})
		{
			last if ($idx > $sample);
			my $details = "<b>Date:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{date}\n";
			$details .= "<b>Duration:</b> " . &convert_time($d) . "\n";
			$details .= "<b>Database:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
			$details .= "<b>User:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
			$details .= "<b>Remote:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
			$details .= "<b>Application:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
			$details .= "<b>Queryid:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
			$details .= "<b>Bind query:</b> yes\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
			my $explain = '';
			if ($normalyzed_info{$curdb}{$k}{samples}{$d}{plan}) {
				$explain = &display_plan("query-f-explain-$rank-$idx", $normalyzed_info{$curdb}{$k}{samples}{$d}{plan});
			}
			$query = &highlight_code(&anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}));
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($normalyzed_info{$curdb}{$k}{samples}{$d}{query}) if ($enable_checksum);
			print $fh qq{
								<dt>
								<div id="query-f-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
								<pre>$details</pre>
								$explain
								</dt>
};
			$idx++;
		}
		print $fh qq{
							</dl>
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#most-frequent-queries-examples-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of details collapse -->
					</td>
				</tr>
};
		$rank++;
	}
	if (scalar keys %{$normalyzed_info{$curdb}} == 0) {
		print $fh qq{<tr><td colspan="7">$NODATA</td></tr>};
	}
	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of most-frequent-queries -->
};

}

sub print_slowest_queries
{
	my $curdb = shift;

	print $fh qq{
		<div class="analysis-item row" id="normalized-slowest-queries">
			<h2 class="col-md-12"><i class="glyphicon icon-time"></i> Normalized slowest queries (N)</h2>
			<div class="col-md-12">
				<table class="table table-striped" id="normalized-slowest-queries-table">
				<thead>
				<tr>
					<th>Rank</th>
					<th>Min duration</th>
					<th>Max duration</th>
					<th>Avg duration</th>
					<th>Times executed</th>
					<th>Total duration</th>
					<th>Query</th>
				</tr>
				</thead>
				<tbody>
};
	my $rank = 1;
	my $found = 0;
	foreach my $k (sort {$normalyzed_info{$curdb}{$b}{average} <=> $normalyzed_info{$curdb}{$a}{average}} keys %{$normalyzed_info{$curdb}})
	{
		next if (!$k || !$normalyzed_info{$curdb}{$k}{count} || !exists $normalyzed_info{$curdb}{$k}{duration});
		last if ($rank > $top);
		$found++;
		$normalyzed_info{$curdb}{$k}{average} = $normalyzed_info{$curdb}{$k}{duration} / $normalyzed_info{$curdb}{$k}{count};
		my $duration = &convert_time($normalyzed_info{$curdb}{$k}{duration});
		my $count = &comma_numbers($normalyzed_info{$curdb}{$k}{count});
		my $min = &convert_time($normalyzed_info{$curdb}{$k}{min});
		my $max = &convert_time($normalyzed_info{$curdb}{$k}{max});
		my $avg = &convert_time($normalyzed_info{$curdb}{$k}{average});
		my $query = &highlight_code($k);
		my $md5 = '';
		$md5 = 'md5: ' . md5_hex($k) if ($enable_checksum);
		my $details = '';
		my %hourly_count = ();
		my %hourly_duration = ();
		my $days = 0;
		foreach my $d (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}})
		{
			my $c = 1;
			$d =~ /^(\d{4})(\d{2})(\d{2})$/;
			$days++;
			my $zday = "$abbr_month{$2} $3";
			my $dd = $3;
			my $mo = $2 - 1;
			my $y = $1 - 1900;
			foreach my $h (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}{$d}})
			{
				my $t = timegm_nocheck(0, 0, $h, $dd, $mo, $y);
				$t += $timezone;
				my $ht = sprintf("%02d", (localtime($t))[2]);
				$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{average} =
					$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{duration} / $normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{count};
				$details .= "<tr><td>$zday</td><td>$ht</td><td>" .
					&comma_numbers($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{count}) .   "</td><td>" .
					&convert_time($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{duration}) . "</td><td>" .
					&convert_time($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{average}) .  "</td></tr>";
				$zday = "";
				foreach my $m (sort keys %{$normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min}})
				{
					my $rd = &average_per_minutes($m, $histo_avg_minutes);
					$hourly_count{"$ht:$rd"} += $normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min}{$m};
					$hourly_duration{"$ht:$rd"} += ($normalyzed_info{$curdb}{$k}{chronos}{$d}{$h}{min_duration}{$m} || 0);
				}
				if ($#histo_avgs > 0)
				{
					foreach my $rd (@histo_avgs)
					{
						next if (!exists $hourly_count{"$ht:$rd"});
						$details .= "<tr><td>$zday</td><td style=\"text-align: right\">$ht:$rd</td><td>" .
							&comma_numbers($hourly_count{"$ht:$rd"}) .   "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}) . "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}/($hourly_count{"$ht:$rd"}||1)) .  "</td></tr>";
					}
				}
			}
		}
		# Set graph dataset
		my %graph_data = ();
		foreach my $h ("00" .. "23")
		{
			foreach my $rd (@histo_avgs)
			{
				$graph_data{count} .= "['$h:$rd'," . ($hourly_count{"$h:$rd"} || 0) . "],";
				$graph_data{duration} .= "['$h:$rd'," . (int($hourly_duration{"$h:$rd"} / ($hourly_count{"$h:$rd"} || 1)) || 0) . "],";
			}
		}
		$graph_data{count} =~ s/,$//;
		$graph_data{duration} =~ s/,$//;
		%hourly_count = ();
		%hourly_duration = ();

		my $query_histo = '';
		if ($graph) {
			$query_histo = &jqplot_histograph($graphid++, 'normalized_slowest_queries_details_'.$rank, $graph_data{count}, $graph_data{duration}, 'Queries', 'Avg. duration');
		}

		my $users_involved = '';
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{users}} > 0) {
			$users_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#normalized-slowest-queries-user-involved-rank-$rank">User(s) involved</button>};
		}
		my $apps_involved = '';
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{apps}} > 0) {
			$apps_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#normalized-slowest-queries-app-involved-rank-$rank">App(s) involved</button>};
		}

		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$min</td>
				<td>$max</td>
				<td>$avg</td>
				<td>$count
					<p><a href="#Anormalized_slowest_queries_details_$rank" class="btn btn-default btn-xs" data-toggle="collapse">Details</a></p>
				</td>
				<td>$duration</td>
				<td id="normalized-slowest-queries-examples-details-rank-$rank">
					<div id="query-g-$rank" class="sql sql-mediumsize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
						<!-- Details collapse -->
					    <div id="Anormalized_slowest_queries_details_$rank" class="collapse">
						<h3>Times Reported <small>Time consuming queries #$rank</small></h3>
						$query_histo
								<table class="table table-stripped table-condensed">
									<thead>
										<tr>
											<th>Day</th>
											<th>Hour</th>
											<th>Count</th>
											<th>Duration</th>
											<th>Avg duration</th>
										</tr>
									</thead>
									<tbody>
										$details
									</tbody>
								</table>
						    <p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#Anormalized_slowest_queries_details_$rank">x Hide</button></p>
						</div><!-- end of details collapse -->
	<p><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#normalized-slowest-queries-examples-rank-$rank">Examples</button> $users_involved</p>
};
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{users}} > 0)
		{
			print $fh qq{
						<!-- Involved users list collapse -->
						<div id="normalized-slowest-queries-user-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$normalyzed_info{$curdb}{$k}{users}{$b}{duration} <=> $normalyzed_info{$curdb}{$k}{users}{$a}{duration}} keys %{$normalyzed_info{$curdb}{$k}{users}})
			{
				if ($normalyzed_info{$curdb}{$k}{users}{$u}{duration} > 0)
				{
					my $details = "[ <b>User:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($normalyzed_info{$curdb}{$k}{users}{$u}{duration});
					$details .= " - <b>Times executed:</b> $normalyzed_info{$curdb}{$k}{users}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#normalized-slowest-queries-user-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of user involved collapse -->
};
		}
		if (scalar keys %{$normalyzed_info{$curdb}{$k}{apps}} > 0)
		{
			print $fh qq{
						<!-- Involved apps list collapse -->
						<div id="normalized-slowest-queries-app-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$normalyzed_info{$curdb}{$k}{apps}{$b}{duration} <=> $normalyzed_info{$curdb}{$k}{apps}{$a}{duration}} keys %{$normalyzed_info{$curdb}{$k}{apps}})
			{
				if ($normalyzed_info{$curdb}{$k}{apps}{$u}{duration} > 0)
				{
					my $details = "[ <b>Application:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($normalyzed_info{$curdb}{$k}{apps}{$u}{duration});
					$details .= " - <b>Times executed:</b> $normalyzed_info{$curdb}{$k}{apps}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#normalized-slowest-queries-app-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of app involved collapse -->
};
		}
		print $fh qq{

						<!-- Examples collapse -->
						<div id="normalized-slowest-queries-examples-rank-$rank" class="collapse">
							<dl>
};

		my $idx = 1;
		foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}})
		{
			last if ($idx > $sample);
			my $details = "<b>Date:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{date}\n";
			$details .= "<b>Duration:</b> " . &convert_time($d) . "\n";
			$details .= "<b>Database:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db});
			$details .= "<b>User:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user});
			$details .= "<b>Remote:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote});
			$details .= "<b>Application:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app});
			$details .= "<b>Queryid:</b> $normalyzed_info{$curdb}{$k}{samples}{$d}{queryid}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{queryid});
			$details .= "<b>Bind query:</b> yes\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind});
			my $explain = '';
			if ($normalyzed_info{$curdb}{$k}{samples}{$d}{plan}) {
				$explain = &display_plan("query-g-explain-$rank-$idx", $normalyzed_info{$curdb}{$k}{samples}{$d}{plan});
			}
			$query = &highlight_code(&anonymize_query($normalyzed_info{$curdb}{$k}{samples}{$d}{query}));
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($normalyzed_info{$curdb}{$k}{samples}{$d}{query}) if ($enable_checksum);
			print $fh qq{
								<dt>
								<div id="query-g-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
								<pre>$details</pre>
								$explain
								</dt>
};
			$idx++;
		}
		print $fh qq{
							</dl>
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#normalized-slowest-queries-examples-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of details collapse -->
					</td>
				</tr>
};
		$rank++;
	}
	if (!$found) {
		print $fh qq{<tr><td colspan="3">$NODATA</td></tr>};
	}
	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of normalized-slowest-queries -->
};

}

sub print_prepare_consuming
{
	my $curdb = shift;

	print $fh qq{
		<div class="analysis-item row" id="time-consuming-prepare">
			<h2 class="col-md-12"><i class="glyphicon icon-time"></i> Time consuming prepare</h2>
                        <div class="col-md-12">
                                <table class="table table-striped" id="time-consuming-prepare-table">
                                <thead>
				<tr>
					<th>Rank</th>
					<th>Total duration</th>
					<th>Times executed</th>
					<th>Min duration</th>
					<th>Max duration</th>
					<th>Avg duration</th>
					<th>Query</th>
				</tr>
				</thead>
				<tbody>
};
	my $rank = 1;
	my $found = 0;
	foreach my $k (sort {$prepare_info{$curdb}{$b}{duration} <=> $prepare_info{$curdb}{$a}{duration}} keys %{$prepare_info{$curdb}})
	{
		next if (!$prepare_info{$curdb}{$k}{count} || !exists $prepare_info{$curdb}{$k}{duration});
		last if ($rank > $top);
		$found++;
		$prepare_info{$curdb}{$k}{average} = $prepare_info{$curdb}{$k}{duration} / $prepare_info{$curdb}{$k}{count};
		my $duration = &convert_time($prepare_info{$curdb}{$k}{duration});
		my $count = &comma_numbers($prepare_info{$curdb}{$k}{count});
		my $min = &convert_time($prepare_info{$curdb}{$k}{min});
		my $max = &convert_time($prepare_info{$curdb}{$k}{max});
		my $avg = &convert_time($prepare_info{$curdb}{$k}{average});
		my $query = &highlight_code(&anonymize_query($k));
		my $md5 = '';
		$md5 = 'md5: ' . md5_hex($k) if ($enable_checksum);
		my $details = '';
		my %hourly_count = ();
		my %hourly_duration = ();
		my $days = 0;
		foreach my $d (sort keys %{$prepare_info{$curdb}{$k}{chronos}})
		{
			$d =~ /^(\d{4})(\d{2})(\d{2})$/;
			$days++;
			my $zday = "$abbr_month{$2} $3";
			my $dd = $3;
			my $mo = $2 -1 ;
			my $y = $1 - 1900;
			foreach my $h (sort keys %{$prepare_info{$curdb}{$k}{chronos}{$d}})
			{
				my $t = timegm_nocheck(0, 0, $h, $dd, $mo, $y);
				$t += $timezone;
				my $ht = sprintf("%02d", (localtime($t))[2]);
				$prepare_info{$curdb}{$k}{chronos}{$d}{$h}{average} =
					$prepare_info{$curdb}{$k}{chronos}{$d}{$h}{duration} / ($prepare_info{$curdb}{$k}{chronos}{$d}{$h}{count} || 1);
				$details .= "<tr><td>$zday</td><td>$ht</td><td>" .
					&comma_numbers($prepare_info{$curdb}{$k}{chronos}{$d}{$h}{count}) .   "</td><td>" .
					&convert_time($prepare_info{$curdb}{$k}{chronos}{$d}{$h}{duration}) . "</td><td>" .
					&convert_time($prepare_info{$curdb}{$k}{chronos}{$d}{$h}{average}) .  "</td></tr>";
				$zday = "";
				foreach my $m (sort keys %{$prepare_info{$curdb}{$k}{chronos}{$d}{$h}{min}})
				{
					my $rd = &average_per_minutes($m, $histo_avg_minutes);
					$hourly_count{"$ht:$rd"} += $prepare_info{$curdb}{$k}{chronos}{$d}{$h}{min}{$m};
					$hourly_duration{"$ht:$rd"} += ($prepare_info{$curdb}{$k}{chronos}{$d}{$h}{min_duration}{$m} || 0);
				}
				if ($#histo_avgs > 0)
				{
					foreach my $rd (@histo_avgs)
					{
						next if (!exists $hourly_count{"$ht:$rd"});
						$details .= "<tr><td>$zday</td><td style=\"text-align: right\">$ht:$rd</td><td>" .
							&comma_numbers($hourly_count{"$ht:$rd"}) .   "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}) . "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}/($hourly_count{"$ht:$rd"}||1)) .  "</td></tr>";
					}
				}
			}
		}
		# Set graph dataset
		my %graph_data = ();
		foreach my $h ("00" .. "23")
		{
			foreach my $rd (@histo_avgs)
			{
				$graph_data{count} .= "['$h:$rd'," . ($hourly_count{"$h:$rd"} || 0) . "],";
				$graph_data{duration} .= "['$h:$rd'," . (int($hourly_duration{"$h:$rd"} / ($hourly_count{"$h:$rd"} || 1)) || 0) . "],";
			}
		}
		$graph_data{count} =~ s/,$//;
		$graph_data{duration} =~ s/,$//;
		%hourly_count = ();
		%hourly_duration = ();

		my $users_involved = '';
		if (scalar keys %{$prepare_info{$curdb}{$k}{users}} > 0) {
			$users_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-prepare-user-involved-rank-$rank">User(s) involved</button>};
		}
		my $apps_involved = '';
		if (scalar keys %{$prepare_info{$curdb}{$k}{apps}} > 0) {
			$apps_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-prepare-app-involved-rank-$rank">App(s) involved</button>};
		}
		my $query_histo = '';
		if ($graph) {
			$query_histo = &jqplot_histograph($graphid++, 'time_consuming_prepare_details_'.$rank, $graph_data{count}, $graph_data{duration}, 'Queries', 'Avg. duration');
		}

		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$duration</td>
				<td>$count
					<p><a href="#Atime_consuming_prepare_details_$rank" class="btn btn-default btn-xs" data-toggle="collapse">Details</a></p>
				</td>
				<td>$min</td>
				<td>$max</td>
				<td>$avg</td>
				<td id="time-consuming-prepare-examples-details-rank-$rank">
					<div id="query-e-$rank" class="sql sql-mediumsize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
						<!-- Details collapse -->
					    <div id="Atime_consuming_prepare_details_$rank" class="collapse">
						<h3>Times Reported <small>Time consuming prepare #$rank</small></h3>
						$query_histo
								<table class="table table-stripped table-condensed">
									<thead>
										<tr>
											<th>Day</th>
											<th>Hour</th>
											<th>Count</th>
											<th>Duration</th>
											<th>Avg duration</th>
										</tr>
									</thead>
									<tbody>
										$details
									</tbody>
								</table>
						    <p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#Atime_consuming_prepare_details_$rank">x Hide</button></p>
						</div><!-- end of details collapse -->
	<p> <button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-prepare-examples-rank-$rank">Examples</button> $users_involved $apps_involved</p>
};
		if (scalar keys %{$prepare_info{$curdb}{$k}{users}} > 0)
		{
			print $fh qq{
						<!-- Involved users list collapse -->
						<div id="time-consuming-prepapre-user-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$prepare_info{$curdb}{$k}{users}{$b}{duration} <=> $prepare_info{$curdb}{$k}{users}{$a}{duration}} keys %{$prepare_info{$curdb}{$k}{users}})
			{
				if ($prepare_info{$curdb}{$k}{users}{$u}{duration} > 0)
				{
					my $details = "[ <b>User:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($prepare_info{$curdb}{$k}{users}{$u}{duration});
					$details .= " - <b>Times executed:</b> $prepare_info{$curdb}{$k}{users}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-prepare-user-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of user involved collapse -->
};
		}

		if (scalar keys %{$prepare_info{$curdb}{$k}{apps}} > 0)
		{
			print $fh qq{
						<!-- Involved apps list collapse -->
						<div id="time-consuming-prepare-app-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$prepare_info{$curdb}{$k}{apps}{$b}{duration} <=> $prepare_info{$curdb}{$k}{apps}{$a}{duration}} keys %{$prepare_info{$curdb}{$k}{apps}})
			{
				if ($prepare_info{$curdb}{$k}{apps}{$u}{duration} > 0)
				{
					my $details = "[ <b>Application:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($prepare_info{$curdb}{$k}{apps}{$u}{duration});
					$details .= " - <b>Times executed:</b> $prepare_info{$curdb}{$k}{apps}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-prepare-app-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of app involved collapse -->
};
		}
		print $fh qq{
						<!-- Examples collapse -->
						<div id="time-consuming-prepare-examples-rank-$rank" class="collapse">
							<dl>
};

		my $idx = 1;
		foreach my $d (sort {$b <=> $a} keys %{$prepare_info{$curdb}{$k}{samples}})
		{
			last if ($idx > $sample);
			my $details = "<b>Date:</b> $prepare_info{$curdb}{$k}{samples}{$d}{date}\n";
			$details .= "<b>Duration:</b> " . &convert_time($d) . "\n";
			$details .= "<b>Database:</b> $prepare_info{$curdb}{$k}{samples}{$d}{db}\n" if ($prepare_info{$curdb}{$k}{samples}{$d}{db});
			$details .= "<b>User:</b> $prepare_info{$curdb}{$k}{samples}{$d}{user}\n" if ($prepare_info{$curdb}{$k}{samples}{$d}{user});
			$details .= "<b>Remote:</b> $prepare_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($prepare_info{$curdb}{$k}{samples}{$d}{remote});
			$details .= "<b>Application:</b> $prepare_info{$curdb}{$k}{samples}{$d}{app}\n" if ($prepare_info{$curdb}{$k}{samples}{$d}{app});
			$details .= "<b>Queryid:</b> $prepare_info{$curdb}{$k}{samples}{$d}{queryid}\n" if ($prepare_info{$curdb}{$k}{samples}{$d}{queryid});
			$details .= "<b>parameters:</b> ". &anonymize_query($prepare_info{$curdb}{$k}{samples}{$d}{params}) . "\n" if ($prepare_info{$curdb}{$k}{samples}{$d}{params});
			$query = &highlight_code(&anonymize_query($prepare_info{$curdb}{$k}{samples}{$d}{query}));
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($prepare_info{$curdb}{$k}{samples}{$d}{query}) if ($enable_checksum);
			print $fh qq{
								<dt>
								<div id="query-e-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
								<pre>$details</pre>
								</dt>
};
			$idx++;
		}
		print $fh qq{
							</dl>
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-prepare-examples-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of details collapse -->
					</td>
				</tr>
};
		$rank++;
	}
	if (!$found) {
		print $fh qq{<tr><td colspan="3">$NODATA</td></tr>};
	}
	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of time-consuming-preapre -->
};

}

sub print_bind_consuming
{
	my $curdb = shift;

	print $fh qq{
		<div class="analysis-item row" id="time-consuming-bind">
			<h2 class="col-md-12"><i class="glyphicon icon-time"></i> Time consuming bind</h2>
                        <div class="col-md-12">
                                <table class="table table-striped" id="time-consuming-bind-table">
                                <thead>
				<tr>
					<th>Rank</th>
					<th>Total duration</th>
					<th>Times executed</th>
					<th>Min duration</th>
					<th>Max duration</th>
					<th>Avg duration</th>
					<th>Query</th>
				</tr>
				</thead>
				<tbody>
};
	my $rank = 1;
	my $found = 0;
	foreach my $k (sort {$bind_info{$curdb}{$b}{duration} <=> $bind_info{$curdb}{$a}{duration}} keys %{$bind_info{$curdb}})
	{
		next if (!$bind_info{$curdb}{$k}{count} || !exists $bind_info{$curdb}{$k}{duration});
		last if ($rank > $top);
		$found++;
		$bind_info{$curdb}{$k}{average} = $bind_info{$curdb}{$k}{duration} / $bind_info{$curdb}{$k}{count};
		my $duration = &convert_time($bind_info{$curdb}{$k}{duration});
		my $count = &comma_numbers($bind_info{$curdb}{$k}{count});
		my $min = &convert_time($bind_info{$curdb}{$k}{min});
		my $max = &convert_time($bind_info{$curdb}{$k}{max});
		my $avg = &convert_time($bind_info{$curdb}{$k}{average});
		my $query = &highlight_code(&anonymize_query($k));
		my $md5 = '';
		$md5 = 'md5: ' . md5_hex($k) if ($enable_checksum);
		my $details = '';
		my %hourly_count = ();
		my %hourly_duration = ();
		my $days = 0;
		foreach my $d (sort keys %{$bind_info{$curdb}{$k}{chronos}})
		{
			$d =~ /^(\d{4})(\d{2})(\d{2})$/;
			$days++;
			my $zday = "$abbr_month{$2} $3";
			my $dd = $3;
			my $mo = $2 -1 ;
			my $y = $1 - 1900;
			foreach my $h (sort keys %{$bind_info{$curdb}{$k}{chronos}{$d}})
			{
				my $t = timegm_nocheck(0, 0, $h, $dd, $mo, $y);
				$t += $timezone;
				my $ht = sprintf("%02d", (localtime($t))[2]);
				$bind_info{$curdb}{$k}{chronos}{$d}{$h}{average} =
					$bind_info{$curdb}{$k}{chronos}{$d}{$h}{duration} / ($bind_info{$curdb}{$k}{chronos}{$d}{$h}{count} || 1);
				$details .= "<tr><td>$zday</td><td>$ht</td><td>" .
					&comma_numbers($bind_info{$curdb}{$k}{chronos}{$d}{$h}{count}) .   "</td><td>" .
					&convert_time($bind_info{$curdb}{$k}{chronos}{$d}{$h}{duration}) . "</td><td>" .
					&convert_time($bind_info{$curdb}{$k}{chronos}{$d}{$h}{average}) .  "</td></tr>";
				$zday = "";
				foreach my $m (sort keys %{$bind_info{$curdb}{$k}{chronos}{$d}{$h}{min}})
				{
					my $rd = &average_per_minutes($m, $histo_avg_minutes);
					$hourly_count{"$ht:$rd"} += $bind_info{$curdb}{$k}{chronos}{$d}{$h}{min}{$m};
					$hourly_duration{"$ht:$rd"} += ($bind_info{$curdb}{$k}{chronos}{$d}{$h}{min_duration}{$m} || 0);
				}
				if ($#histo_avgs > 0)
				{
					foreach my $rd (@histo_avgs)
					{
						next if (!exists $hourly_count{"$ht:$rd"});
						$details .= "<tr><td>$zday</td><td style=\"text-align: right\">$ht:$rd</td><td>" .
							&comma_numbers($hourly_count{"$ht:$rd"}) .   "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}) . "</td><td>" .
							&convert_time($hourly_duration{"$ht:$rd"}/($hourly_count{"$ht:$rd"}||1)) .  "</td></tr>";
					}
				}
			}
		}
		# Set graph dataset
		my %graph_data = ();
		foreach my $h ("00" .. "23")
		{
			foreach my $rd (@histo_avgs)
			{
				$graph_data{count} .= "['$h:$rd'," . ($hourly_count{"$h:$rd"} || 0) . "],";
				$graph_data{duration} .= "['$h:$rd'," . (int($hourly_duration{"$h:$rd"} / ($hourly_count{"$h:$rd"} || 1)) || 0) . "],";
			}
		}
		$graph_data{count} =~ s/,$//;
		$graph_data{duration} =~ s/,$//;
		%hourly_count = ();
		%hourly_duration = ();

		my $users_involved = '';
		if (scalar keys %{$bind_info{$curdb}{$k}{users}} > 0) {
			$users_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-bind-user-involved-rank-$rank">User(s) involved</button>};
		}
		my $apps_involved = '';
		if (scalar keys %{$bind_info{$curdb}{$k}{apps}} > 0) {
			$apps_involved = qq{<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-bind-app-involved-rank-$rank">App(s) involved</button>};
		}
		my $query_histo = '';
		if ($graph) {
			$query_histo = &jqplot_histograph($graphid++, 'time_consuming_bind_details_'.$rank, $graph_data{count}, $graph_data{duration}, 'Queries', 'Avg. duration');
		}

		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$duration</td>
				<td>$count
					<p><a href="#Atime_consuming_bind_details_$rank" class="btn btn-default btn-xs" data-toggle="collapse">Details</a></p>
				</td>
				<td>$min</td>
				<td>$max</td>
				<td>$avg</td>
				<td id="time-consuming-bind-examples-details-rank-$rank">
					<div id="query-e-$rank" class="sql sql-mediumsize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
						<!-- Details collapse -->
					    <div id="Atime_consuming_bind_details_$rank" class="collapse">
						<h3>Times Reported <small>Time consuming bind #$rank</small></h3>
						$query_histo
								<table class="table table-stripped table-condensed">
									<thead>
										<tr>
											<th>Day</th>
											<th>Hour</th>
											<th>Count</th>
											<th>Duration</th>
											<th>Avg duration</th>
										</tr>
									</thead>
									<tbody>
										$details
									</tbody>
								</table>
						    <p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#Atime_consuming_bind_details_$rank">x Hide</button></p>
						</div><!-- end of details collapse -->
	<p> <button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-bind-examples-rank-$rank">Examples</button> $users_involved $apps_involved</p>
};
		if (scalar keys %{$bind_info{$curdb}{$k}{users}} > 0)
		{
			print $fh qq{
						<!-- Involved users list collapse -->
						<div id="time-consuming-prepapre-user-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$bind_info{$curdb}{$k}{users}{$b}{duration} <=> $bind_info{$curdb}{$k}{users}{$a}{duration}} keys %{$bind_info{$curdb}{$k}{users}})
			{
				if ($bind_info{$curdb}{$k}{users}{$u}{duration} > 0)
				{
					my $details = "[ <b>User:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($bind_info{$curdb}{$k}{users}{$u}{duration});
					$details .= " - <b>Times executed:</b> $bind_info{$curdb}{$k}{users}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-bind-user-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of user involved collapse -->
};
		}

		if (scalar keys %{$bind_info{$curdb}{$k}{apps}} > 0)
		{
			print $fh qq{
						<!-- Involved apps list collapse -->
						<div id="time-consuming-bind-app-involved-rank-$rank" class="collapse">
};
			my $idx = 1;
			foreach my $u (sort {$bind_info{$curdb}{$k}{apps}{$b}{duration} <=> $bind_info{$curdb}{$k}{apps}{$a}{duration}} keys %{$bind_info{$curdb}{$k}{apps}})
			{
				if ($bind_info{$curdb}{$k}{apps}{$u}{duration} > 0)
				{
					my $details = "[ <b>Application:</b> $u";
					$details .= " - <b>Total duration:</b> ".&convert_time($bind_info{$curdb}{$k}{apps}{$u}{duration});
					$details .= " - <b>Times executed:</b> $bind_info{$curdb}{$k}{apps}{$u}{count}";
					$details .= " ]\n";
					print $fh qq{
							<pre>$details</pre>
};
					$idx++;
				}
			}
			print $fh qq{
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-bind-app-involved-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of app involved collapse -->
};
		}
		print $fh qq{
						<!-- Examples collapse -->
						<div id="time-consuming-bind-examples-rank-$rank" class="collapse">
							<dl>
};

		my $idx = 1;
		foreach my $d (sort {$b <=> $a} keys %{$bind_info{$curdb}{$k}{samples}})
		{
			last if ($idx > $sample);
			my $details = "<b>Date:</b> $bind_info{$curdb}{$k}{samples}{$d}{date}\n";
			$details .= "<b>Duration:</b> " . &convert_time($d) . "\n";
			$details .= "<b>Database:</b> $bind_info{$curdb}{$k}{samples}{$d}{db}\n" if ($bind_info{$curdb}{$k}{samples}{$d}{db});
			$details .= "<b>User:</b> $bind_info{$curdb}{$k}{samples}{$d}{user}\n" if ($bind_info{$curdb}{$k}{samples}{$d}{user});
			$details .= "<b>Remote:</b> $bind_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($bind_info{$curdb}{$k}{samples}{$d}{remote});
			$details .= "<b>Application:</b> $bind_info{$curdb}{$k}{samples}{$d}{app}\n" if ($bind_info{$curdb}{$k}{samples}{$d}{app});
			$details .= "<b>Queryid:</b> $bind_info{$curdb}{$k}{samples}{$d}{queryid}\n" if ($bind_info{$curdb}{$k}{samples}{$d}{queryid});
			$details .= "<b>parameters:</b> " . &anonymize_query($bind_info{$curdb}{$k}{samples}{$d}{params}) . "\n" if ($bind_info{$curdb}{$k}{samples}{$d}{params});
			$query = &highlight_code(&anonymize_query($bind_info{$curdb}{$k}{samples}{$d}{query}));
			my $md5 = '';
			$md5 = 'md5: ' . md5_hex($bind_info{$curdb}{$k}{samples}{$d}{query}) if ($enable_checksum);
			print $fh qq{
								<dt>
								<div id="query-e-$rank-$idx" class="sql sql-largesize"><i class="glyphicon icon-copy" title="Click to select query"></i>$query</div>$md5
								<pre>$details</pre>
								</dt>
};
			$idx++;
		}
		print $fh qq{
							</dl>
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#time-consuming-bind-examples-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of details collapse -->
					</td>
				</tr>
};
		$rank++;
	}
	if (!$found) {
		print $fh qq{<tr><td colspan="3">$NODATA</td></tr>};
	}
	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of time-consuming-preapre -->
};

}

sub dump_as_html
{

	my $uri = shift;
	my $curdb = shift;

	# Dump the html header
	&html_header($uri, $curdb);

	# Set graphs limits
	if ($overall_stat{$curdb}{'first_log_ts'} =~ /^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/)
	{
		my ($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s);
		if (!$log_timezone) {
			($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s) = ($1, $2, $3, $4, $5, $6);
		} else {
			($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s) = change_timezone($1, $2, $3, $4, $5, $6);
		}
		$t_min = timegm_nocheck(0, $t_mi, $t_h, $t_d, $t_mo - 1, $t_y) * 1000;
		$t_min += ($timezone*1000);
		$t_min -= ($avg_minutes * 60000);
	}
	if ($overall_stat{$curdb}{'last_log_ts'} =~ /^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/)
	{
		my ($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s);
		if (!$log_timezone) {
			($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s) = ($1, $2, $3, $4, $5, $6);
		} else {
			($t_y, $t_mo, $t_d, $t_h, $t_mi, $t_s) = change_timezone($1, $2, $3, $4, $5, $6);
		}
		$t_max = timegm_nocheck(59, $t_mi, $t_h, $t_d, $t_mo - 1, $t_y) * 1000;
		$t_max += ($timezone*1000);
		$t_max += ($avg_minutes * 60000);
	}

	if (!$error_only)
	{
		if (!$pgbouncer_only)
		{
			# Overall statistics
			print $fh qq{
	<li class="slide active-slide" id="overview-slide">
};
			&print_overall_statistics($curdb);
		}

		if (!$disable_hourly && !$pgbouncer_only)
		{
			# Build graphs based on hourly stat
			&compute_query_graphs($curdb);

			# Show global SQL traffic
			&print_sql_traffic($curdb);

			# Show hourly statistics
			&print_general_activity($curdb);

		}

		if (!$disable_connection && !$pgbouncer_only)
		{
			print $fh qq{
		</li>
		<li class="slide" id="connections-slide" style="display:none;">
	<h1 class="page-header"><i class="glyphicon icon-external-link-sign"></i> Connections</h1>

};

			# Draw connections information
			&print_established_connection($curdb) if (!$disable_hourly);
			# Show per database/user connections
			&print_database_connection($curdb);
			# Show per user connections
			&print_user_connection($curdb);
			# Show per client ip connections
			&print_host_connection($curdb);
		}


		# Show session per database statistics
		if (!$disable_session && !$pgbouncer_only)
		{
			print $fh qq{
		</li>
		<li class="slide" id="sessions-slide" style="display:none;">
	<h1 class="page-header"><i class="glyphicon icon-off"></i> Sessions</h1>

};
			# Show number of simultaneous sessions
			&print_simultaneous_session($curdb);
			# Show histogram for session times
			&print_histogram_session_times($curdb);
			# Show per database sessions
			&print_database_session($curdb);
			# Show per user sessions
			&print_user_session($curdb);
			# Show per host sessions
			&print_host_session($curdb);
			# Show per application sessions
			&print_app_session($curdb);
		}

		# Display checkpoint and temporary files report
		if (!$disable_checkpoint && !$pgbouncer_only && (!$report_per_database || $curdb eq $DBALL)) {
			print $fh qq{
		</li>
		<li class="slide" id="checkpoints-slide" style="display:none;">
	};
			&print_checkpoint($curdb);
			&print_checkpoint_cause($curdb);
		}

		if (!$disable_temporary && !$pgbouncer_only)
		{
			print $fh qq{
		</li>
		<li class="slide" id="tempfiles-slide" style="display:none;">
};
			# Show temporary files detailed information
			&print_temporary_file($curdb);

			# Show information about queries generating temporary files
			&print_tempfile_report($curdb);
		}

		if (!$disable_autovacuum && !$pgbouncer_only)
		{
			print $fh qq{
		</li>
		<li class="slide" id="vacuums-slide" style="display:none;">
};
			# Show detailed vacuum/analyse information
			&print_vacuum($curdb);

		}

		if (!$disable_lock && !$pgbouncer_only)
		{
			print $fh qq{
		</li>
		<li class="slide" id="locks-slide" style="display:none;">
};
			# Lock stats per type
			&print_lock_type($curdb);

			# Show lock wait detailed information
			&print_lock_queries_report($curdb);
		}

		if (!$disable_query && !$pgbouncer_only)
		{
			print $fh qq{
		</li>
		<li class="slide" id="queries-slide" style="display:none;">
};
			# INSERT/DELETE/UPDATE/SELECT repartition
			if (!$disable_type)
			{
				&print_query_type($curdb);

				# Show requests per database
				&print_query_per_database($curdb);

				# Show requests per user
				&print_query_per_user($curdb);

				# Show requests per host
				&print_query_per_host($curdb);

				# Show requests per application
				&print_query_per_application($curdb);
;
				# Show cancelled queries detailed information
				&print_cancelled_queries($curdb);

				# Show information about cancelled queries
				&print_cancelled_report($curdb);

			}

			print $fh qq{
		</li>
		<li class="slide" id="topqueries-slide" style="display:none;">
};
			# Show histogram for query times
			&print_histogram_query_times($curdb);

			# Show top information
			&print_slowest_individual_queries($curdb);

			# Show queries that took up the most time
			&print_time_consuming($curdb);

			# Show most frequent queries
			&print_most_frequent($curdb);

			# Print normalized slowest queries
			&print_slowest_queries($curdb);

			# Show prepare that took up the most time
			&print_prepare_consuming($curdb);

			# Show bind that took up the most time
			&print_bind_consuming($curdb);
		}

		# Show pgbouncer sessions and connections statistics
		if (exists $pgb_overall_stat{peak} && (!$report_per_database || $curdb eq $DBALL))
		{
			# Build pgbouncer graph based on hourly stats
			&compute_pgbouncer_graphs();

			my $active = '';
			$active = ' active-slide' if ($pgbouncer_only);
			print $fh qq{
		</li>
		<li class="slide$active" id="pgbouncer-slide" style="display:none;">
	<h1 class="page-header"><i class="glyphicon icon-refresh"></i> pgBouncer</h1>

};
			# Draw pgbouncer own statistics
			&print_pgbouncer_stats() if (!$disable_hourly);

			# Draw connections information
			&print_established_pgb_connection() if (!$disable_hourly);

			# Show per database/user connections
			&print_database_pgb_connection();

			# Show per user connections
			&print_user_pgb_connection();

			# Show per client ip connections
			&print_host_pgb_connection();

			# Show number of simultaneous sessions
			&print_simultaneous_pgb_session();
			# Show histogram for session times
			&print_histogram_pgb_session_times();
			# Show per database sessions
			&print_database_pgb_session();
			# Show per user sessions
			&print_user_pgb_session();
			# Show per host sessions
			&print_host_pgb_session();

			# Show most used reserved pool
			&show_pgb_reserved_pool();
			# Show Most Frequent Errors/Events
			&show_pgb_error_as_html();
		}
	}

	# Show errors report
	if (!$disable_error)
	{
		if (!$error_only)
		{
			print $fh qq{
		</li>
		<li class="slide" id="events-slide" style="display:none;">
};
		} else {
			print $fh qq{
		<li class="slide active-slide" id="events-slide" style="display:none;">
};
		}
		# Show log level distribution
		&print_log_level($curdb);

		# Show error code distribution
		&print_error_code($curdb) if (scalar keys %errors_code > 0);

		# Show Most Frequent Errors/Events
		&show_error_as_html($curdb);
	}

	# Dump the html footer
	&html_footer($curdb);

}

sub url_escape
{
	my $toencode = shift;

	return if (!$toencode);

	utf8::encode($toencode) if (($] >= 5.008) && utf8::is_utf8($toencode));

	if (EBCDIC) {
		$toencode =~ s/([^a-zA-Z0-9_.~-])/uc sprintf("%%%02x",$E2A[ord($1)])/eg;
	} else {
		$toencode =~ s/([^a-zA-Z0-9_.~-])/uc sprintf("%%%02x",ord($1))/eg;
	}

	return $toencode;
}

sub escape_html
{
	$_[0] =~ s/<([\/a-zA-Z][\s\>]*)/\&lt;$1/sg;

	return $_[0];
}

sub print_log_level
{
	my $curdb = shift;

	my %infos = ();

	# Show log types
	my $total_logs = 0;
	foreach my $d (sort keys %{$logs_type{$curdb}}) {
		$total_logs += $logs_type{$curdb}{$d};
	}

	my $logtype_info = '';
	foreach my $d (sort keys %{$logs_type{$curdb}}) {
		next if (!$logs_type{$curdb}{$d});
		$logtype_info .= "<tr><td>$d</td><td>" . &comma_numbers($logs_type{$curdb}{$d}) .
			"</td><td>" . sprintf("%0.2f", ($logs_type{$curdb}{$d} * 100) / ($total_logs||1)) . "%</td></tr>";
	}
	my %graph_data = ();
	my %max_events = ();
	if ($graph){
		my @small = ();
		foreach my $d (sort keys %{$logs_type{$curdb}}) {
			if ((($logs_type{$curdb}{$d} * 100) / ($total_logs || 1)) > $pie_percentage_limit) {
				$infos{$d} = $logs_type{$curdb}{$d} || 0;
			} else {
				$infos{"Sum log types < $pie_percentage_limit%"} += $logs_type{$curdb}{$d} || 0;
				push(@small, $d);
			}
		}

		if ($#small == 0) {
			$infos{$small[0]} = $infos{"Sum log types < $pie_percentage_limit%"};
			delete $infos{"Sum log types < $pie_percentage_limit%"};
		}
		foreach my $l (qw(FATAL WARNING ERROR PANIC EVENTLOG)) {
			$max_events{$l} = 0;
		}
		my %e_dataavg = ();
		foreach my $tm (sort {$a <=> $b} keys %{$per_minute_info{$curdb}}) {
			foreach my $h ("00" .. "23") {
				next if (!exists $per_minute_info{$curdb}{$tm}{$h});
				foreach my $m ("00" .. "59") {
					next if (!exists $per_minute_info{$curdb}{$tm}{$h}{$m});
					if (exists $per_minute_info{$curdb}{$tm}{$h}{$m}{log_level}) {

						my $rd = &average_per_minutes($m, $avg_minutes);

						# Average per minute
						foreach my $l (qw(FATAL WARNING ERROR PANIC EVENTLOG)) {
							$e_dataavg{$l}{$tm}{$h}{"$rd"} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{log_level}{$l} || 0);
							$max_events{$l} += ($per_minute_info{$curdb}{$tm}{$h}{$m}{log_level}{$l} || 0);
						}
						delete $per_minute_info{$curdb}{$tm}{$h}{$m}{log_level};
					}
				}
			}
		}

		foreach my $l (qw(FATAL ERROR PANIC WARNING)) {
			foreach my $tm (sort {$a <=> $b} keys %{$e_dataavg{$l}}) {
				$tm =~ /(\d{4})(\d{2})(\d{2})/;
				my $y  = $1 - 1900;
				my $mo = $2 - 1;
				my $d  = $3;
				foreach my $h ("00" .. "23") {
					foreach my $rd (@avgs) {
						my $t = timegm_nocheck(0, $rd, $h, $d, $mo, $y) * 1000;
						$t += ($timezone*1000);

						next if ($t < $t_min);
						last if ($t > $t_max);

						$graph_data{$l} .= "[$t, " . ($e_dataavg{$l}{$tm}{$h}{"$rd"} || 0) . "],";
					}
				}
			}
		}

		foreach (keys %graph_data) {
			$graph_data{$_} =~ s/,$//;
		}

	}

	$drawn_graphs{'eventspersecond_graph'} = &jqplot_linegraph( $graphid++, 'eventspersecond_graph', $graph_data{'PANIC'},
		$graph_data{FATAL}, $graph_data{'ERROR'}, 'Events per ' . $avg_minutes . ' minutes',
		'Errors per ' . $avg_minutes . ' minutes', 'PANIC', 'FATAL', 'ERROR', '', $graph_data{'WARNING'}, 'WARNING'
	);

	$drawn_graphs{logstype_graph} = &jqplot_piegraph($graphid++, 'graph_logstype', 'Logs per type', %infos);
	if (!$total_logs) {
		$logtype_info = qq{<tr><td colspan="7">$NODATA</td></tr>};
	}
	$logs_type{$curdb}{ERROR} ||= 0;
	$logs_type{$curdb}{FATAL} ||= 0;
	$total_logs = &comma_numbers($total_logs);
	print $fh qq{
	<h1 class="page-header"><i class="glyphicon icon-bullhorn"></i> Events</h1>

	<div class="analysis-item row" id="log-levels">
		<h2 class="col-md-12"><i class="glyphicon icon-tags"></i> Log levels</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$total_logs</span> <span class="figure-label">Event entries</span></li>
					<li><span class="figure-label">(EVENTLOG entries are formaly LOG level entries that are not queries)</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#log-level-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#log-level-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="log-level-graph">
						$drawn_graphs{logstype_graph}
					</div>
					<div class="tab-pane" id="log-level-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Type</th>
									<th>Count</th>
									<th>Percentage</th>
								</tr>
							</thead>
							<tbody>
							$logtype_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of event flow -->

	<div class="analysis-item row" id="minutes-errors-levels">
		<h2 class="col-md-12"><i class="glyphicon icon-tags"></i> Events distribution (except queries)</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$max_events{PANIC}</span> <span class="figure-label">PANIC entries</span></li>
					<li><span class="figure">$max_events{FATAL}</span> <span class="figure-label">FATAL entries</span></li>
					<li><span class="figure">$max_events{ERROR}</span> <span class="figure-label">ERROR entries</span></li>
					<li><span class="figure">$max_events{WARNING}</span> <span class="figure-label">WARNING entries</span></li>
					<li><span class="figure">$max_events{EVENTLOG}</span> <span class="figure-label">EVENTLOG entries</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
$drawn_graphs{'eventspersecond_graph'}
		</div>
	</div><!-- end of errors per minutes -->

};
	delete $drawn_graphs{logstype_graph};
	delete $drawn_graphs{'eventspersecond_graph'};

}

sub print_error_code
{
	my $curdb = shift;

	my %infos = ();
	my %class_error = ();
	my $ret = 0;

	my $total_logs = 0;
	foreach my $d (sort keys %{$errors_code{$curdb}})
	{
		$total_logs += $errors_code{$curdb}{$d};
		$d =~ /^(..)/;
		$class_error{$1} += $errors_code{$curdb}{$d};
	}

	my $errorclass_info = '';
	foreach my $d (sort keys %class_error)
	{
		next if (!$class_error{$d});
		$errorclass_info .= "<tr><td>$CLASS_ERROR_CODE{$d}</td><td>$d</td><td>" . &comma_numbers($class_error{$d}) .
			"</td><td>" . sprintf("%0.2f", ($class_error{$d} * 100) / ($total_logs||1)) . "%</td></tr>";
	}
	my %graph_data = ();
	my %max_events = ();
	my $most_present = '';
	if ($graph)
	{
		my @small = ();
		foreach my $d (sort { $class_error{$b} <=> $class_error{$a} } keys %class_error)
		{
			$most_present = $CLASS_ERROR_CODE{$d} if (!$most_present);
			if ((($class_error{$d} * 100) / ($total_logs || 1)) > $pie_percentage_limit) {
				$infos{$CLASS_ERROR_CODE{$d}} = $class_error{$d} || 0;
			}
			else
			{
				$infos{"Sum error classes < $pie_percentage_limit%"} += $class_error{$d} || 0;
				push(@small, $CLASS_ERROR_CODE{$d});
			}
		}

		if ($#small == 0)
		{
			$infos{$small[0]} = $infos{"Sum error classes < $pie_percentage_limit%"};
			delete $infos{"Sum error classes < $pie_percentage_limit%"};
		}
	}

	$drawn_graphs{errorclass_graph} = &jqplot_piegraph($graphid++, 'graph_errorclass', 'Error class distribution', %infos);
	if (!$total_logs) {
		$errorclass_info = qq{<tr><td colspan="7">$NODATA</td></tr>};
	}
	$total_logs = &comma_numbers($total_logs);
	if (scalar keys %{$errors_code{$curdb}} > 0)
	{
		print $fh qq{
	<div class="analysis-item row" id="error-code">
		<h2 class="col-md-12"><i class="glyphicon icon-tags"></i> Error class distribution</h2>
		<div class="col-md-3">
			<h3 class="">Key values</h3>
			<div class="well key-figures">
				<ul>
					<li><span class="figure">$total_logs</span> <span class="figure-label">Errors count</span></li>
					<li><span class="figure">$most_present</span> <span class="figure-label">most present error class</span></li>
				</ul>
			</div>
		</div>
		<div class="col-md-9">
			<div class="tabbable">
				<ul class="nav nav-tabs">
					<li class="active"><a href="#error-code-graph" data-toggle="tab">Chart</a></li>
					<li><a href="#error-code-table" data-toggle="tab">Table</a></li>
				</ul>
				<div class="tab-content">
					<div class="tab-pane active" id="error-code-graph">
						$drawn_graphs{errorclass_graph}
					</div>
					<div class="tab-pane" id="error-code-table">
						<table class="table table-striped table-hover">
							<thead>
								<tr>
									<th>Class</th>
									<th>Code</th>
									<th>Count</th>
									<th>Percentage</th>
								</tr>
							</thead>
							<tbody>
							$errorclass_info
							</tbody>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div><!-- end of event flow -->

};
	}

	delete $drawn_graphs{errorclass_graph};
}


sub show_error_as_html
{
	my $curdb = shift;

	my $main_error = 0;
	my $total = 0;
	foreach my $k (sort {$error_info{$curdb}{$b}{count} <=> $error_info{$curdb}{$a}{count}} keys %{$error_info{$curdb}})
	{
		next if (!$error_info{$curdb}{$k}{count});
		$main_error = &comma_numbers($error_info{$curdb}{$k}{count}) if (!$main_error);
		$total += $error_info{$curdb}{$k}{count};
	}
	$total = &comma_numbers($total);

	print $fh qq{
		<div class="analysis-item row" id="most-frequent-errors-events">
  	  		<h2 class="col-md-12"><i class="glyphicon icon-warning-sign"></i> Most Frequent Errors/Events</h2>
			<div class="col-md-3">
				<h3 class="">Key values</h3>
				<div class="well key-figures">
					<ul>
						<li><span class="figure">$main_error</span> <span class="figure-label">Max number of times the same event was reported</span></li>
						<li><span class="figure">$total</span> <span class="figure-label">Total events found</span></li>
					</ul>
				</div>
  	  		</div>
  	  		<div class="col-md-9">
				<table class="table table-striped" id="most-frequent-errors-events-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Times reported</th>
						<th>Error</th>
					</tr>
				</thead>
				<tbody>
};
	my $rank = 1;
	foreach my $k (sort { $error_info{$curdb}{$b}{count} <=> $error_info{$curdb}{$a}{count} } keys %{$error_info{$curdb}})
	{
		next if (!$error_info{$curdb}{$k}{count});
		my $count = &comma_numbers($error_info{$curdb}{$k}{count});
		my ($msg, $ret) = &revert_log_level($k);
		my $error_level_class = 'text-danger';
		if ($msg =~ /^WARNING: /) {
			$error_level_class = 'text-warning';
		} elsif ($msg =~ /^LOG: /) {
			$error_level_class = 'text-success';
		} elsif ($msg =~ /^HINT: /) {
			$error_level_class = 'text-info';
		} elsif ($msg =~ /^FATAL: /) {
			$error_level_class = 'text-fatal';
		} elsif ($msg =~ /^PANIC: /) {
			$error_level_class = 'text-panic';
		}
		my $details = '';
		my %hourly_count = ();
		my $days = 0;
		foreach my $d (sort keys %{$error_info{$curdb}{$k}{chronos}})
		{
			my $c = 1;
			$d =~ /^(\d{4})(\d{2})(\d{2})$/;
			$days++;
			my $zday = "$abbr_month{$2} $3";
			my $y = $1 - 1900;
			my $mo = $2 - 1;
			my $dd = $3;
			foreach my $h (sort keys %{$error_info{$curdb}{$k}{chronos}{$d}})
			{
				my $t = timegm_nocheck(0, 0, $h, $dd, $mo, $y);
				$t += $timezone;
				my $ht = sprintf("%02d", (localtime($t))[2]);
				$details .= "<tr><td>$zday</td><td>$ht</td><td>" .
					&comma_numbers($error_info{$curdb}{$k}{chronos}{$d}{$h}{count}) . "</td></tr>";
				$zday = "";
				foreach my $m (sort keys %{$error_info{$curdb}{$k}{chronos}{$d}{$h}{min}})
				{
					my $rd = &average_per_minutes($m, $histo_avg_minutes);
					$hourly_count{"$ht:$rd"} += $error_info{$curdb}{$k}{chronos}{$d}{$h}{min}{$m};
				}
				if ($#histo_avgs > 0)
				{
					foreach my $rd (@histo_avgs)
					{
						next if (!exists $hourly_count{"$ht:$rd"});
						$details .= "<tr><td>$zday</td><td style=\"text-align: right\">$ht:$rd</td><td>" .
							&comma_numbers($hourly_count{"$ht:$rd"}) . "</td></tr>";
					}
				}
			}
		}
		# Set graph dataset
		my %graph_data = ();
		foreach my $h ("00" .. "23")
		{
			foreach my $rd (@histo_avgs) {
				$graph_data{count} .= "['$h:$rd'," . ($hourly_count{"$h:$rd"} || 0) . "],";
			}
		}
		$graph_data{count} =~ s/,$//;
		%hourly_count = ();

		my $error_histo = '';
		if ($graph) {
			$error_histo = &jqplot_histograph($graphid++, 'most_frequent_error_'.$rank, $graph_data{count}, '', 'Events', '');
		}
		# Escape HTML code in error message
		$msg = &escape_html($msg);
		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$count
					<p><a href="#Amost_frequent_error_$rank" class="btn btn-default btn-xs" data-toggle="collapse">Details</a></p>
				</td>
				<td id="most-frequent-errors-events-examples-details-rank-$rank">
					<div id="event-c-$rank" class="sql sql-mediumsize">
					<p class="error-pre"><span class="$error_level_class">$msg</span></p>
					</div>
						<!-- Details collapse -->
					    <div id="Amost_frequent_error_$rank" class="collapse">
						<h3>Times Reported <small>Most Frequent Error / Event #$rank</small></h3>
						$error_histo
								<table class="table table-stripped table-condensed">
									<thead>
										<tr>
											<th>Day</th>
											<th>Hour</th>
											<th>Count</th>
										</tr>
									</thead>
									<tbody>
										$details
									</tbody>
								</table>
						    <p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#Amost_frequent_error_$rank">x Hide</button></p>
						</div><!-- end of details collapse -->
};
		print $fh qq{
<p><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#most-frequent-errors-events-examples-rank-$rank">Examples</button></p>
} if (($sample > 0) && ($#{$error_info{$curdb}{$k}{date}} >= 0));
		print $fh qq{
						<!-- Examples collapse -->
						<div id="most-frequent-errors-events-examples-rank-$rank" class="collapse">
							<dl>
};

		for (my $i = 0 ; $i <= $#{$error_info{$curdb}{$k}{date}} ; $i++)
		{
			last if (($sample > 0) && ($i == $sample));
			# Escape HTML code in error message
			my ($msg, $ret) = &revert_log_level($error_info{$curdb}{$k}{error}[$i]);
			my $message = &escape_html($msg);
			my $details = "<b>Date:</b> " . $error_info{$curdb}{$k}{date}[$i] . "\n";
			my $info    = '';
			if ($error_info{$curdb}{$k}{detail}[$i]) {
				$info .= "<b>Detail:</b> " . &escape_html($error_info{$curdb}{$k}{detail}[$i]) . "<br/>";
			}
			if ($error_info{$curdb}{$k}{context}[$i]) {
				$info .= "<b>Context:</b> " . &escape_html($error_info{$curdb}{$k}{context}[$i]) . "<br/>";
			}
			if ($error_info{$curdb}{$k}{hint}[$i]) {
				$info .= "<b>Hint:</b> " . &escape_html($error_info{$curdb}{$k}{hint}[$i]) . "<br/>";
			}
			if ($error_info{$curdb}{$k}{statement}[$i]) {
				$info .= "<b>Statement:</b> " . &escape_html(&anonymize_query($error_info{$curdb}{$k}{statement}[$i])) . "<br/>";
			}
			if ($error_info{$curdb}{$k}{db}[$i])
			{
				$details .= "<b>Database:</b> $error_info{$curdb}{$k}{db}[$i]\n";
				$details .= "<b>Application:</b> $error_info{$curdb}{$k}{app}[$i]\n";
				$details .= "<b>Queryid:</b> $error_info{$curdb}{$k}{queryid}[$i]\n" if ($error_info{$curdb}{$k}{queryid}[$i]);
				$details .= "<b>User:</b> $error_info{$curdb}{$k}{user}[$i]\n";
				$details .= "<b>Remote:</b> $error_info{$curdb}{$k}{remote}[$i]\n";
				$details .= "<b>Code:</b> $error_info{$curdb}{$k}{sqlstate}[$i]\n" if ($error_info{$curdb}{$k}{sqlstate}[$i]);
			}
			$details =~ s/<br\/>$//s;
			if ($wide_char)
			{
				$info = encode('UTF-8', $info);
			}
			print $fh qq{
								<dt><span class="$error_level_class">$message</span></dt>
								<p>$info</p>
								<pre>$details</pre>
};
		}
		print $fh qq{
							</dl>
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#most-frequent-errors-events-examples-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of details collapse -->
					</td>
				</tr>
};
		$rank++;
	}
	if (scalar keys %{$error_info{$curdb}} == 0) {
		print $fh qq{<tr><td colspan="7">$NODATA</td></tr>};
	}

	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of most-frequent-errors-events -->
};

}

sub show_pgb_error_as_html
{

	my $main_error = 0;
	my $total = 0;
	foreach my $k (sort {$pgb_error_info{$b}{count} <=> $pgb_error_info{$a}{count}} keys %pgb_error_info) {
		next if (!$pgb_error_info{$k}{count});
		$main_error = &comma_numbers($pgb_error_info{$k}{count}) if (!$main_error);
		$total += $pgb_error_info{$k}{count};
	}
	$total = &comma_numbers($total);

	print $fh qq{
		<div class="analysis-item row" id="pgbmost-frequent-errors-events">
  	  		<h2 class="col-md-12"><i class="glyphicon icon-warning-sign"></i> Most Frequent Errors/Events</h2>
			<div class="col-md-3">
				<h3 class="">Key values</h3>
				<div class="well key-figures">
					<ul>
						<li><span class="figure">$main_error</span> <span class="figure-label">Max number of times the same event was reported</span></li>
						<li><span class="figure">$total</span> <span class="figure-label">Total events found</span></li>
					</ul>
				</div>
  	  		</div>
  	  		<div class="col-md-9">
				<table class="table table-striped" id="pgbmost-frequent-errors-events-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Times reported</th>
						<th>Error</th>
					</tr>
				</thead>
				<tbody>
};
	my $rank = 1;
	foreach my $k (sort {$pgb_error_info{$b}{count} <=> $pgb_error_info{$a}{count}} keys %pgb_error_info)
	{
		next if (!$pgb_error_info{$k}{count});
		my $count = &comma_numbers($pgb_error_info{$k}{count});
		my $msg = $k;
		my $error_level_class = 'text-danger';
		if ($msg =~ /^WARNING: /) {
			$error_level_class = 'text-warning';
		} elsif ($msg =~ /^LOG: /) {
			$error_level_class = 'text-success';
		} elsif ($msg =~ /^FATAL: /) {
			$error_level_class = 'text-fatal';
		} elsif ($msg =~ /^PANIC: /) {
			$error_level_class = 'text-panic';
		}
		my $details = '';
		my %hourly_count = ();
		my $days = 0;
		foreach my $d (sort keys %{$pgb_error_info{$k}{chronos}})
		{
			my $c = 1;
			$d =~ /^(\d{4})(\d{2})(\d{2})$/;
			$days++;
			my $zday = "$abbr_month{$2} $3";
			my $y = $1 - 1900;
			my $mo = $2 - 1;
			my $dd = $3;
			foreach my $h (sort keys %{$pgb_error_info{$k}{chronos}{$d}})
			{
				my $t = timegm_nocheck(0, 0, $h, $dd, $mo, $y);
				$t += $timezone;
				my $ht = sprintf("%02d", (localtime($t))[2]);
				$details .= "<tr><td>$zday</td><td>$ht</td><td>" .
					&comma_numbers($pgb_error_info{$k}{chronos}{$d}{$h}{count}) . "</td></tr>";
				$zday = "";
				foreach my $m (sort keys %{$pgb_error_info{$k}{chronos}{$d}{$h}{min}}) {
					my $rd = &average_per_minutes($m, $histo_avg_minutes);
					$hourly_count{"$ht:$rd"} += $pgb_error_info{$k}{chronos}{$d}{$h}{min}{$m};
				}
				if ($#histo_avgs > 0)
				{
					foreach my $rd (@histo_avgs)
					{
						next if (!exists $hourly_count{"$ht:$rd"});
						$details .= "<tr><td>$zday</td><td style=\"text-align: right\">$ht:$rd</td><td>" .
							&comma_numbers($hourly_count{"$ht:$rd"}) . "</td></tr>";
					}
				}
			}
		}
		# Set graph dataset
		my %graph_data = ();
		foreach my $h ("00" .. "23")
		{
			foreach my $rd (@histo_avgs) {
				$graph_data{count} .= "['$h:$rd'," . ($hourly_count{"$h:$rd"} || 0) . "],";
			}
		}
		$graph_data{count} =~ s/,$//;
		%hourly_count = ();

		my $error_histo = '';
		if ($graph) {
			$error_histo = &jqplot_histograph($graphid++, 'pgbmost_frequent_error_'.$rank, $graph_data{count}, '', 'Events', '');
		}

		# Escape HTML code in error message
		$msg = &escape_html($msg);
		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$count
					<p><a href="#Apgbmost_frequent_error_$rank" class="btn btn-default btn-xs" data-toggle="collapse">Details</a></p>
				</td>
				<td id="pgbmost-frequent-errors-events-examples-details-rank-$rank">
					<pre><span class="$error_level_class">$msg</span></pre>
						<!-- Details collapse -->
					    <div id="Apgbmost_frequent_error_$rank" class="collapse">
						<h3>Times Reported <small>Most Frequent Error / Event #$rank</small></h3>
						$error_histo
								<table class="table table-stripped table-condensed">
									<thead>
										<tr>
											<th>Day</th>
											<th>Hour</th>
											<th>Count</th>
										</tr>
									</thead>
									<tbody>
										$details
									</tbody>
								</table>
						    <p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#Apgbmost_frequent_error_$rank">x Hide</button></p>
						</div><!-- end of details collapse -->
};
		print $fh qq{
<p><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#pgbmost-frequent-errors-events-examples-rank-$rank">Examples</button></p>
} if (($sample > 0) && ($#{$pgb_error_info{$k}{date}} >= 0));
		print $fh qq{
						<!-- Examples collapse -->
						<div id="pgbmost-frequent-errors-events-examples-rank-$rank" class="collapse">
							<dl>
};

		for (my $i = 0 ; $i <= $#{$pgb_error_info{$k}{date}} ; $i++)
		{
			last if (($sample > 0) && ($i == $sample));
			# Escape HTML code in error message
			my $message = &escape_html($pgb_error_info{$k}{error}[$i]);
			my $details = "Date: " . $pgb_error_info{$k}{date}[$i] . "\n";
			if ($pgb_error_info{$k}{db}[$i]) {
				$details .= "<b>Database:</b> $pgb_error_info{$k}{db}[$i] <b>User:</b> $pgb_error_info{$k}{user}[$i] <b>Remote:</b> $pgb_error_info{$k}{remote}[$i] <br/>";
			}
			print $fh qq{
								<dt><span class="$error_level_class">$message</span></dt>
								<pre>$details</pre>
};
		}
		print $fh qq{
							</dl>
							<p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#pgbmost-frequent-errors-events-examples-rank-$rank">x Hide</button></p>
						</div>
						<!-- end of details collapse -->
					</td>
				</tr>
};
		$rank++;
	}
	if (scalar keys %pgb_error_info == 0) {
		print $fh qq{<tr><td colspan="7">$NODATA</td></tr>};
	}

	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of pgbmost-frequent-errors-events -->
};

}

sub show_pgb_reserved_pool
{

	my $main_pool = '';
	my $main_pool_val = 0;
	my $total = 0;
	foreach my $k (sort {$pgb_pool_info{$b}{count} <=> $pgb_pool_info{$a}{count}} keys %pgb_pool_info)
	{
		if (!$main_pool || ($pgb_pool_info{$k}{count} > $pgb_pool_info{$main_pool}{count}))
		{
			$main_pool = $k;
			$main_pool_val = &comma_numbers($pgb_pool_info{$k}{count});
		}
		$total += $pgb_pool_info{$k}{count};
	}
	$total = &comma_numbers($total);

	print $fh qq{
		<div class="analysis-item row" id="pgbmost-used-reserved-pool">
  	  		<h2 class="col-md-12"><i class="glyphicon icon-warning-sign"></i> Most used reserved pools</h2>
			<div class="col-md-3">
				<h3 class="">Key values</h3>
				<div class="well key-figures">
					<ul>
						<li><span class="figure">$main_pool</span> <span class="figure-label">Most used reserved pool</span></li>
						<li><span class="figure">$main_pool_val</span> <span class="figure-label">Time used</span></li>
						<li><span class="figure">$total</span> <span class="figure-label">Total time reserved pools was used</span></li>
					</ul>
				</div>
  	  		</div>
  	  		<div class="col-md-9">
				<table class="table table-striped" id="pgbmost-used-reserved-pool-table">
				<thead>
					<tr>
						<th>Rank</th>
						<th>Times used</th>
						<th>Reserved pool</th>
					</tr>
				</thead>
				<tbody>
};
	my $rank = 1;
	foreach my $k (sort {$pgb_pool_info{$b}{count} <=> $pgb_pool_info{$a}{count}} keys %pgb_pool_info)
	{
		next if (!$pgb_pool_info{$k}{count});
		my $count = &comma_numbers($pgb_pool_info{$k}{count});
		my $details = '';
		my %hourly_count = ();
		my $days = 0;
		foreach my $d (sort keys %{$pgb_pool_info{$k}{chronos}})
		{
			my $c = 1;
			$d =~ /^(\d{4})(\d{2})(\d{2})$/;
			$days++;
			my $zday = "$abbr_month{$2} $3";
			my $y = $1 - 1900;
			my $mo = $2 - 1;
			my $dd = $3;
			foreach my $h (sort keys %{$pgb_pool_info{$k}{chronos}{$d}})
			{
				my $t = timegm_nocheck(0, 0, $h, $dd, $mo, $y);
				$t += $timezone;
				my $ht = sprintf("%02d", (localtime($t))[2]);
				$details .= "<tr><td>$zday</td><td>$ht</td><td>" .
					&comma_numbers($pgb_pool_info{$k}{chronos}{$d}{$h}{count}) . "</td></tr>";
				$zday = "";
				foreach my $m (sort keys %{$pgb_pool_info{$k}{chronos}{$d}{$h}{min}})
				{
					my $rd = &average_per_minutes($m, $histo_avg_minutes);
					$hourly_count{"$ht:$rd"} += $pgb_pool_info{$k}{chronos}{$d}{$h}{min}{$m};
				}
				if ($#histo_avgs > 0)
				{
					foreach my $rd (@histo_avgs)
					{
						next if (!exists $hourly_count{"$ht:$rd"});
						$details .= "<tr><td>$zday</td><td style=\"text-align: right\">$ht:$rd</td><td>" .
							&comma_numbers($hourly_count{"$ht:$rd"}) . "</td></tr>";
					}
				}
			}
		}
		# Set graph dataset
		my %graph_data = ();
		foreach my $h ("00" .. "23")
		{
			foreach my $rd (@histo_avgs) {
				$graph_data{count} .= "['$h:$rd'," . ($hourly_count{"$h:$rd"} || 0) . "],";
			}
		}
		$graph_data{count} =~ s/,$//;
		%hourly_count = ();

		my $pool_histo = '';
		if ($graph) {
			$pool_histo = &jqplot_histograph($graphid++, 'pgbmost_used_reserved_pool_'.$rank, $graph_data{count}, '', 'Avg. used', '');
		}

		# Escape HTML code in pool message
		print $fh qq{
				<tr>
				<td>$rank</td>
				<td>$count
					<p><a href="#Apgbmost_used_reserved_pool_$rank" class="btn btn-default btn-xs" data-toggle="collapse">Details</a></p>
				</td>
				<td id="pgbmost-used-reserved-pool-examples-details-rank-$rank">
					<pre><span class="text-warning">$k</span></pre>
					<!-- Details collapse -->
					    <div id="Apgbmost_used_reserved_pool_$rank" class="collapse">
						<h3>Times Reported <small>Most used reserved pools #$rank</small></h3>
						$pool_histo
								<table class="table table-stripped table-condensed">
									<thead>
										<tr>
											<th>Day</th>
											<th>Hour</th>
											<th>Count</th>
										</tr>
									</thead>
									<tbody>
										$details
									</tbody>
								</table>
						    <p class="pull-right"><button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#Apgbmost_used_reserved_pool_$rank">x Hide</button></p>
						</div><!-- end of details collapse -->
					</td>
				</tr>
};
		$rank++;
	}
	if (scalar keys %pgb_pool_info == 0) {
		print $fh qq{<tr><td colspan="7">$NODATA</td></tr>};
	}

	print $fh qq{
			</tbody>
			</table>
		</div>
	</div><!-- end of pgbmost-used-reserved-pool -->
};

}

sub load_stats
{

	my $fd = shift;

	my %stats = %{ fd_retrieve($fd) };
	if (!exists $stats{version})
	{
		warn("can not load incompatible binary data, binary file is from version < 4.0.\n");
		return 0;
	}
	my %_overall_stat = %{$stats{overall_stat}};
	my %_pgb_overall_stat = %{$stats{pgb_overall_stat}};
	my %_overall_checkpoint = %{$stats{overall_checkpoint}};
	my %_normalyzed_info = %{$stats{normalyzed_info}};
	my %_error_info = %{$stats{error_info}};
	my %_pgb_error_info = %{$stats{pgb_error_info}};
	my %_pgb_pool_info = %{$stats{pgb_pool_info}};
	my %_connection_info = %{$stats{connection_info}};
	my %_pgb_connection_info = %{$stats{pgb_connection_info}};
	my %_database_info = %{$stats{database_info}};
	my %_application_info = %{$stats{application_info}};
	my %_user_info = %{$stats{user_info}};
	my %_host_info = %{$stats{host_info}};
	my %_checkpoint_info = %{$stats{checkpoint_info}};
	my %_session_info = %{$stats{session_info}};
	my %_pgb_session_info = %{$stats{pgb_session_info}};
	my %_tempfile_info = %{$stats{tempfile_info}};
	my %_cancelled_info = %{$stats{cancelled_info}};
	my %_logs_type = %{$stats{logs_type}};
	my %_errors_code = %{$stats{errors_code}};
	my %_lock_info = %{$stats{lock_info}};
	my %_per_minute_info = %{$stats{per_minute_info}};
	my %_pgb_per_minute_info = %{$stats{pgb_per_minute_info}};
	my %_top_slowest = %{$stats{top_slowest}};
	my $_nlines = $stats{nlines};
	my $_first_log_timestamp = $stats{first_log_timestamp};
	my $_last_log_timestamp = $stats{last_log_timestamp};
	my @_log_files = @{$stats{log_files}};
	my %_autovacuum_info = %{$stats{autovacuum_info}};
	my %_autoanalyze_info = %{$stats{autoanalyze_info}};
	my %_top_locked_info = %{$stats{top_locked_info}};
	my %_top_tempfile_info = %{$stats{top_tempfile_info}};
	my %_top_cancelled_info = %{$stats{top_cancelled_info}};
	my %_prepare_info = %{$stats{prepare_info}};
	my %_bind_info = %{$stats{bind_info}};

	### overall_stat ###
	# Those a used to update the progress bar and are not related to any database
	$overall_stat{'queries_number'} += $_overall_stat{'queries_number'};
	$overall_stat{'errors_number'} += $_overall_stat{'errors_number'};
	$pgb_overall_stat{'queries_number'} += $_pgb_overall_stat{'queries_number'};
	$pgb_overall_stat{'errors_number'} += $_pgb_overall_stat{'errors_number'};
	foreach my $d (keys %{ $_overall_stat{nlines} })
	{
		$overall_stat{'nlines'}{$d} += $_overall_stat{'nlines'}{$d};
	}

	foreach my $curdb (keys %_overall_stat)
	{
		next if (grep(/^$curdb$/, 'queries_number', 'errors_number', 'queries_number', 'errors_number', 'nlines'));
		if ($_overall_stat{$curdb}{'first_log_ts'})
		{
			$overall_stat{$curdb}{'first_log_ts'} = $_overall_stat{$curdb}{'first_log_ts'}
				if (!$overall_stat{$curdb}{'first_log_ts'} ||
					($overall_stat{$curdb}{'first_log_ts'} gt $_overall_stat{$curdb}{'first_log_ts'}));
		}

		$overall_stat{$curdb}{'last_log_ts'} = $_overall_stat{$curdb}{'last_log_ts'}
			if not $overall_stat{$curdb}{'last_log_ts'}
				or $overall_stat{$curdb}{'last_log_ts'} lt $_overall_stat{$curdb}{'last_log_ts'};

		$overall_stat{$curdb}{'queries_number'} += $_overall_stat{$curdb}{'queries_number'};
		$overall_stat{$curdb}{'errors_number'} += $_overall_stat{$curdb}{'errors_number'};
		$pgb_overall_stat{$curdb}{'queries_number'} += $_pgb_overall_stat{$curdb}{'queries_number'};
		$pgb_overall_stat{$curdb}{'errors_number'} += $_pgb_overall_stat{$curdb}{'errors_number'};

		if ($_overall_stat{$curdb}{'first_query_ts'})
		{
			$overall_stat{$curdb}{'first_query_ts'} = $_overall_stat{$curdb}{'first_query_ts'}
				if (!$overall_stat{$curdb}{'first_query_ts'} ||
					($overall_stat{$curdb}{'first_query_ts'} gt $_overall_stat{$curdb}{'first_query_ts'}));
		}

		$overall_stat{$curdb}{'last_query_ts'} = $_overall_stat{$curdb}{'last_query_ts'}
			if not $overall_stat{$curdb}{'last_query_ts'}
				or $overall_stat{$curdb}{'last_query_ts'} lt $_overall_stat{$curdb}{'last_query_ts'};

		if (exists $_overall_stat{$curdb}{'queries_duration'} && $_overall_stat{$curdb}{'queries_duration'} !~ /HASH/)
		{
			# Backward compatibility
			$overall_stat{$curdb}{'queries_duration'}{'execute'} += $_overall_stat{$curdb}{'queries_duration'};
		}
		else
		{
			$overall_stat{$curdb}{'queries_duration'}{'execute'} += $_overall_stat{$curdb}{'queries_duration'}{'execute'};
			$overall_stat{$curdb}{'queries_duration'}{'prepare'} += $_overall_stat{$curdb}{'queries_duration'}{'prepare'};
			$overall_stat{$curdb}{'queries_duration'}{'bind'} += $_overall_stat{$curdb}{'queries_duration'}{'bind'};
		}

		foreach my $a (@SQL_ACTION)
		{
			$overall_stat{$curdb}{lc($a)} += $_overall_stat{$curdb}{lc($a)}
				if exists $_overall_stat{$curdb}{lc($a)};
			$overall_stat{$curdb}{lc($a)} += $_overall_stat{$curdb}{$a}
				if exists $_overall_stat{$curdb}{$a};
		}

		foreach my $k (keys %{$_overall_stat{$curdb}{peak}})
		{
			$overall_stat{$curdb}{peak}{$k}{query} += $_overall_stat{$curdb}{peak}{$k}{query};
			$overall_stat{$curdb}{peak}{$k}{select} += $_overall_stat{$curdb}{peak}{$k}{select};
			$overall_stat{$curdb}{peak}{$k}{write} += $_overall_stat{$curdb}{peak}{$k}{write};
			$overall_stat{$curdb}{peak}{$k}{connection} += $_overall_stat{$curdb}{peak}{$k}{connection};
			$overall_stat{$curdb}{peak}{$k}{session} += $_overall_stat{$curdb}{peak}{$k}{session};
			$overall_stat{$curdb}{peak}{$k}{tempfile_size} += $_overall_stat{$curdb}{peak}{$k}{tempfile_size};
			$overall_stat{$curdb}{peak}{$k}{tempfile_count} += $_overall_stat{$curdb}{peak}{$k}{tempfile_count};
			$overall_stat{$curdb}{peak}{$k}{cancelled_size} += $_overall_stat{$curdb}{peak}{$k}{cancelled_size};
			$overall_stat{$curdb}{peak}{$k}{cancelled_count} += $_overall_stat{$curdb}{peak}{$k}{cancelled_count};
		}

		foreach my $k (keys %{$_overall_stat{$curdb}{histogram}{query_time}}) {
			$overall_stat{$curdb}{histogram}{query_time}{$k} += $_overall_stat{$curdb}{histogram}{query_time}{$k};
		}
		$overall_stat{$curdb}{histogram}{query_total} += $_overall_stat{$curdb}{histogram}{total};
		$overall_stat{$curdb}{histogram}{query_total} += $_overall_stat{$curdb}{histogram}{query_total};
		foreach my $k (keys %{$_overall_stat{$curdb}{histogram}{session_time}}) {
			$overall_stat{$curdb}{histogram}{session_time}{$k} += $_overall_stat{$curdb}{histogram}{session_time}{$k};
		}
		$overall_stat{$curdb}{histogram}{session_total} += $_overall_stat{$curdb}{histogram}{session_total};

		foreach my $k ('prepare', 'bind','execute') {
			$overall_stat{$curdb}{$k} += $_overall_stat{$curdb}{$k};
		}
	}

	$overall_checkpoint{checkpoint_warning} += $_overall_checkpoint{checkpoint_warning};
	$overall_checkpoint{checkpoint_write} = $_overall_checkpoint{checkpoint_write}
		if ($_overall_checkpoint{checkpoint_write} > $overall_checkpoint{checkpoint_write});
	$overall_checkpoint{checkpoint_sync} = $_overall_checkpoint{checkpoint_sync}
		if ($_overall_checkpoint{checkpoint_sync} > $overall_checkpoint{checkpoint_sync});
	foreach my $k (keys %{$_overall_checkpoint{peak}})
	{
		$overall_checkpoint{peak}{$k}{checkpoint_wbuffer} += $_overall_checkpoint{peak}{$k}{checkpoint_wbuffer};
		$overall_checkpoint{peak}{$k}{walfile_usage} += $_overall_checkpoint{peak}{$k}{walfile_usage};
		$overall_checkpoint{peak}{$k}{distance} += $_overall_checkpoint{peak}{$k}{distance};
		$overall_checkpoint{peak}{$k}{estimate} += $_overall_checkpoint{peak}{$k}{estimate};
	}

	### pgbouncer related overall stats ###
	foreach my $k (keys %{$_pgb_overall_stat{peak}})
	{
		$pgb_overall_stat{peak}{$k}{connection} += $_pgb_overall_stat{peak}{$k}{connection};
		$pgb_overall_stat{peak}{$k}{session} += $_pgb_overall_stat{peak}{$k}{session};
		$pgb_overall_stat{peak}{$k}{t_req} += $_pgb_overall_stat{peak}{$k}{t_req};
		$pgb_overall_stat{peak}{$k}{t_inbytes} += $_pgb_overall_stat{peak}{$k}{t_inbytes};
		$pgb_overall_stat{peak}{$k}{t_outbytes} += $_pgb_overall_stat{peak}{$k}{t_outbytes};
		$pgb_overall_stat{peak}{$k}{t_avgduration} += $_pgb_overall_stat{peak}{$k}{t_avgduration};
		$pgb_overall_stat{peak}{$k}{t_avgwaiting} += $_pgb_overall_stat{peak}{$k}{t_avgwaiting};
	}

	foreach my $k (keys %{$_pgb_overall_stat{histogram}{session_time}}) {
		$pgb_overall_stat{histogram}{session_time}{$k} += $_pgb_overall_stat{histogram}{session_time}{$k};
	}
	$pgb_overall_stat{histogram}{session_total} += $_pgb_overall_stat{histogram}{session_total};

	### Logs level ###
	foreach my $l (qw(LOG WARNING ERROR FATAL PANIC DETAIL HINT STATEMENT CONTEXT EVENTLOG))
	{
		foreach my $curdb (keys %_logs_type)
		{
			$logs_type{$curdb}{$l} += $_logs_type{$curdb}{$l} if exists $_logs_type{$curdb}{$l};
		}
	}

	### Errors code ###
	foreach my $curdb (keys %_errors_code)
	{
		foreach my $c (keys %{$_errors_code{$curdb}}) {
			$errors_code{$curdb}{$c} += $_errors_code{$curdb}{$c};
		}
	}

	### database_info ###
	foreach my $curdb (keys %_database_info)
	{
		foreach my $db (keys %{$_database_info{$curdb}}) {
			foreach my $k (keys %{ $_database_info{$curdb}{$db} }) {
				$database_info{$curdb}{$db}{$k} += $_database_info{$curdb}{$db}{$k};
			}
		}
	}

	### application_info ###
	foreach my $curdb (keys %_application_info)
	{
		foreach my $app (keys %{$_application_info{$curdb}}) {
			foreach my $k (keys %{ $_application_info{$curdb}{$app} }) {
				$application_info{$curdb}{$app}{$k} += $_application_info{$curdb}{$app}{$k};
			}
		}
	}

	### user_info ###
	foreach my $curdb (keys %_user_info)
	{
		foreach my $u (keys %{$_user_info{$curdb}}) {
			foreach my $k (keys %{ $_user_info{$curdb}{$u} }) {
				$user_info{$curdb}{$u}{$k} += $_user_info{$curdb}{$u}{$k};
			}
		}
	}

	### host_info ###
	foreach my $curdb (keys %_host_info)
	{
		foreach my $h (keys %{$_host_info{$curdb}}) {
			foreach my $k (keys %{ $_host_info{$curdb}{$h} }) {
				$host_info{$curdb}{$h}{$k} += $_host_info{$curdb}{$h}{$k};
			}
		}
	}


	### connection_info ###
	foreach my $curdb (keys %_connection_info)
	{
		foreach my $db (keys %{ $_connection_info{$curdb}{database} }) {
			$connection_info{$curdb}{database}{$db} += $_connection_info{$curdb}{database}{$db};
		}

		foreach my $db (keys %{ $_connection_info{$curdb}{database_user} }) {
			foreach my $user (keys %{ $_connection_info{$curdb}{database_user}{$db} }) {
				$connection_info{$curdb}{database_user}{$db}{$user} += $_connection_info{$curdb}{database_user}{$db}{$user};
			}
		}

		foreach my $db (keys %{ $_connection_info{$curdb}{database_host} }) {
			foreach my $user (keys %{ $_connection_info{$curdb}{database_host}{$db} }) {
				$connection_info{$curdb}{database_host}{$db}{$user} += $_connection_info{$curdb}{database_host}{$db}{$user};
			}
		}

		foreach my $user (keys %{ $_connection_info{$curdb}{user} }) {
			$connection_info{$curdb}{user}{$user} += $_connection_info{$curdb}{user}{$user};
		}

		foreach my $host (keys %{ $_connection_info{$curdb}{host} }) {
			$connection_info{$curdb}{host}{$host} += $_connection_info{$curdb}{host}{$host};
		}

		$connection_info{$curdb}{count} += $_connection_info{$curdb}{count};

		foreach my $day (keys %{ $_connection_info{$curdb}{chronos} })
		{
			foreach my $hour (keys %{ $_connection_info{$curdb}{chronos}{$day} }) {

				$connection_info{$curdb}{chronos}{$day}{$hour}{count} += $_connection_info{$curdb}{chronos}{$day}{$hour}{count};
			}
		}
	}

	### pgbouncer connection_info ###
	foreach my $db (keys %{ $_pgb_connection_info{database} }) {
		$pgb_connection_info{database}{$db} += $_pgb_connection_info{database}{$db};
	}

	foreach my $db (keys %{ $_pgb_connection_info{database_user} })
	{
		foreach my $user (keys %{ $_pgb_connection_info{database_user}{$db} }) {
			$pgb_connection_info{database_user}{$db}{$user} += $_pgb_connection_info{database_user}{$db}{$user};
		}
	}

	foreach my $db (keys %{ $_pgb_connection_info{database_host} })
	{
		foreach my $user (keys %{ $_pgb_connection_info{database_host}{$db} }) {
			$pgb_connection_info{database_host}{$db}{$user} += $_pgb_connection_info{database_host}{$db}{$user};
		}
	}

	foreach my $user (keys %{ $_pgb_connection_info{user} }) {
		$pgb_connection_info{user}{$user} += $_pgb_connection_info{user}{$user};
	}

	foreach my $host (keys %{ $_pgb_connection_info{host} }) {
		$pgb_connection_info{host}{$host} += $_pgb_connection_info{host}{$host};
	}

	$pgb_connection_info{count} += $_pgb_connection_info{count};

	foreach my $day (keys %{ $_pgb_connection_info{chronos} })
	{
		foreach my $hour (keys %{ $_pgb_connection_info{chronos}{$day} }) {
			$pgb_connection_info{chronos}{$day}{$hour}{count} += $_pgb_connection_info{chronos}{$day}{$hour}{count}
		}
	}

	### log_files ###
	foreach my $f (@_log_files) {
		push(@log_files, $f) if (!grep(m#^\Q$f\E$#, @_log_files));
	}

	### error_info ###
	foreach my $curdb (keys %_error_info)
	{
		foreach my $q (keys %{$_error_info{$curdb}})
		{
			$error_info{$curdb}{$q}{count} += $_error_info{$curdb}{$q}{count};
			foreach my $day (keys %{ $_error_info{$curdb}{$q}{chronos} })
			{
				foreach my $hour (keys %{$_error_info{$curdb}{$q}{chronos}{$day}})
				{
					$error_info{$curdb}{$q}{chronos}{$day}{$hour}{count} += $_error_info{$curdb}{$q}{chronos}{$day}{$hour}{count};
					foreach my $min (keys %{$_error_info{$curdb}{$q}{chronos}{$day}{$hour}{min}}) {
						$error_info{$curdb}{$q}{chronos}{$day}{$hour}{min}{$min} += $_error_info{$curdb}{$q}{chronos}{$day}{$hour}{min}{$min};
					}
				}
			}
			for (my $i = 0; $i <= $#{$_error_info{$curdb}{$q}{date}}; $i++)
			{
				&set_top_error_sample( $curdb, $q,
										$_error_info{$curdb}{$q}{date}[$i],
										$_error_info{$curdb}{$q}{error}[$i],
										$_error_info{$curdb}{$q}{detail}[$i],
										$_error_info{$curdb}{$q}{context}[$i],
										$_error_info{$curdb}{$q}{statement}[$i],
										$_error_info{$curdb}{$q}{hint}[$i],
										$_error_info{$curdb}{$q}{db}[$i],
										$_error_info{$curdb}{$q}{user}[$i],
										$_error_info{$curdb}{$q}{app}[$i],
										$_error_info{$curdb}{$q}{remote}[$i],
										$_error_info{$curdb}{$q}{sqlstate}[$i],
										$_error_info{$curdb}{$q}{queryid}[$i]
										);
			}
		}
	}

	### pgbouncer error_info ###
	foreach my $q (keys %_pgb_error_info)
	{
		$pgb_error_info{$q}{count} += $_pgb_error_info{$q}{count};
		foreach my $day (keys %{ $_pgb_error_info{$q}{chronos} })
		{
			foreach my $hour (keys %{$_pgb_error_info{$q}{chronos}{$day}})
			{
				$pgb_error_info{$q}{chronos}{$day}{$hour}{count} += $_pgb_error_info{$q}{chronos}{$day}{$hour}{count};
				foreach my $min (keys %{$_pgb_error_info{$q}{chronos}{$day}{$hour}{min}}) {
					$pgb_error_info{$q}{chronos}{$day}{$hour}{min}{$min} += $_pgb_error_info{$q}{chronos}{$day}{$hour}{min}{$min};
				}
			}
		}
		for (my $i = 0; $i <= $#{$_pgb_error_info{$q}{date}}; $i++)
		{
			&pgb_set_top_error_sample($q,
									$_pgb_error_info{$q}{date}[$i],
									$_pgb_error_info{$q}{error}[$i],
									$_pgb_error_info{$q}{db}[$i],
									$_pgb_error_info{$q}{user}[$i],
									$_pgb_error_info{$q}{remote}[$i]
									);
		}
	}

	### pgbouncer pool_info ###
	foreach my $q (keys %_pgb_pool_info)
	{
		$pgb_pool_info{$q}{count} += $_pgb_pool_info{$q}{count};
		foreach my $day (keys %{ $_pgb_pool_info{$q}{chronos} })
		{
			foreach my $hour (keys %{$_pgb_pool_info{$q}{chronos}{$day}})
			{
				$pgb_pool_info{$q}{chronos}{$day}{$hour}{count} += $_pgb_pool_info{$q}{chronos}{$day}{$hour}{count};
				foreach my $min (keys %{$_pgb_pool_info{$q}{chronos}{$day}{$hour}{min}}) {
					$pgb_pool_info{$q}{chronos}{$day}{$hour}{min}{$min} += $_pgb_pool_info{$q}{chronos}{$day}{$hour}{min}{$min};
				}
			}
		}
	}

	### per_minute_info ###
	foreach my $curdb (keys %_per_minute_info)
	{
		foreach my $day (keys %{$_per_minute_info{$curdb}})
		{
			foreach my $hour (keys %{ $_per_minute_info{$curdb}{$day} })
			{
				foreach my $min (keys %{ $_per_minute_info{$curdb}{$day}{$hour} })
				{
					$per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{count} +=
						($_per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{count} || 0);
					$per_minute_info{$curdb}{$day}{$hour}{$min}{session}{count} +=
						($_per_minute_info{$curdb}{$day}{$hour}{$min}{session}{count} || 0);
					$per_minute_info{$curdb}{$day}{$hour}{$min}{query}{count} +=
						($_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{count} || 0);
					$per_minute_info{$curdb}{$day}{$hour}{$min}{query}{duration} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{duration};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min} if (!exists $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min} || ($per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min} > $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min}));
					$per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max} if (!exists $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max} || ($per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max} < $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max}));

					foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{autovacuum}{second} })
					{
						$per_minute_info{$curdb}{$day}{$hour}{$min}{autovacuum}{second}{$sec} +=
							($_per_minute_info{$curdb}{$day}{$hour}{$min}{autovacuum}{second}{$sec} || 0);
					}
					foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{second} })
					{
						$per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{second}{$sec} +=
							($_per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{second}{$sec} || 0);
					}
					foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{session}{second} })
					{
						$per_minute_info{$curdb}{$day}{$hour}{$min}{session}{second}{$sec} +=
							($_per_minute_info{$curdb}{$day}{$hour}{$min}{session}{second}{$sec} || 0);
					}
					foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{second} })
					{
						$per_minute_info{$curdb}{$day}{$hour}{$min}{query}{second}{$sec} +=
							($_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{second}{$sec} || 0);
					}
					foreach my $action (@SQL_ACTION)
					{
						next if (!exists $_per_minute_info{$curdb}{$day}{$hour}{$min}{lc($action)});
						$per_minute_info{$curdb}{$day}{$hour}{$min}{lc($action)}{count} += ($_per_minute_info{$curdb}{$day}{$hour}{$min}{lc($action)}{count} || 0);
						$per_minute_info{$curdb}{$day}{$hour}{$min}{lc($action)}{duration} += ($_per_minute_info{$curdb}{$day}{$hour}{$min}{lc($action)}{duration} || 0);
						foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{lc($action)}{second} })
						{
							$per_minute_info{$curdb}{$day}{$hour}{$min}{lc($action)}{second}{$sec} +=
								($_per_minute_info{$curdb}{$day}{$hour}{$min}{lc($action)}{second}{$sec} || 0);
						}
					}
					foreach my $k ('prepare', 'bind','execute')
					{
						if (exists $_per_minute_info{$curdb}{$day}{$hour}{$min}{$k}) {
							$per_minute_info{$curdb}{$day}{$hour}{$min}{$k} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{$k};
						}
					}
					foreach my $log (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{log_level} })
					{
						$per_minute_info{$curdb}{$day}{$hour}{$min}{log_level}{$log} +=
							($_per_minute_info{$curdb}{$day}{$hour}{$min}{log_level}{$log} || 0);
					}

					$per_minute_info{$curdb}{$day}{$hour}{$min}{cancelled}{count} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{cancelled}{count}
							if defined $_per_minute_info{$curdb}{$day}{$hour}{$min}{cancelled}{count};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{count} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{count}
							if defined $_per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{count};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{size} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{size}
							if defined $_per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{size};

					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_removed} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_removed};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{wbuffer} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{wbuffer};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_recycled} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_recycled};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{total} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{total};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_added} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_added};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{write} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{write};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{autovacuum}{count} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{autovacuum}{count};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{autoanalyze}{count} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{autoanalyze}{count};

					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_files} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_files};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_avg} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_avg};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_longest} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_longest}
						if ($_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_longest} > $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_longest});
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{distance} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{distance};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{distance_count} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{distance_count};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{estimate} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{estimate};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{warnning} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{warning};
					$per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{warning_seconds} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{warning_seconds};
				}
			}
		}
	}

	### pgbouncer per_minute_info ###
	foreach my $day (keys %_pgb_per_minute_info)
	{
		foreach my $hour (keys %{ $_pgb_per_minute_info{$day} })
		{
			foreach my $min (keys %{ $_pgb_per_minute_info{$day}{$hour} })
			{
				$pgb_per_minute_info{$day}{$hour}{$min}{connection}{count} +=
					($_pgb_per_minute_info{$day}{$hour}{$min}{connection}{count} || 0);
				$pgb_per_minute_info{$day}{$hour}{$min}{session}{count} +=
					($_pgb_per_minute_info{$day}{$hour}{$min}{session}{count} || 0);
				$pgb_per_minute_info{$day}{$hour}{$min}{t_req} +=
					($_pgb_per_minute_info{$day}{$hour}{$min}{t_req} || 0);
				$pgb_per_minute_info{$day}{$hour}{$min}{t_inbytes} +=
					($_pgb_per_minute_info{$day}{$hour}{$min}{t_inbytes} || 0);
				$pgb_per_minute_info{$day}{$hour}{$min}{t_outbytes} +=
					($_pgb_per_minute_info{$day}{$hour}{$min}{t_outbytes} || 0);
				$pgb_per_minute_info{$day}{$hour}{$min}{t_avgduration} +=
					($_pgb_per_minute_info{$day}{$hour}{$min}{t_avgduration} || 0);
				$pgb_per_minute_info{$day}{$hour}{$min}{t_avgwaiting} +=
					($_pgb_per_minute_info{$day}{$hour}{$min}{t_avgwaiting} || 0);
			}
		}
	}

	### lock_info ###
	foreach my $curdb (keys %_lock_info)
	{
		foreach my $lock (keys %{$_lock_info{$curdb}})
		{
			$lock_info{$curdb}{$lock}{count} += $_lock_info{$curdb}{$lock}{count};

			foreach my $day (keys %{ $_lock_info{$curdb}{chronos} })
			{
				foreach my $hour (keys %{ $_lock_info{$curdb}{chronos}{$day} })
				{
					$lock_info{$curdb}{chronos}{$day}{$hour}{count} += $_lock_info{$curdb}{chronos}{$day}{$hour}{count};
					$lock_info{$curdb}{chronos}{$day}{$hour}{duration} += $_lock_info{$curdb}{chronos}{$day}{$hour}{duration};
				}
			}

			$lock_info{$curdb}{$lock}{duration} += $_lock_info{$curdb}{$lock}{duration};

			foreach my $type (keys %{$_lock_info{$curdb}{$lock}})
			{
				next if $type =~ /^(count|chronos|duration)$/;

				$lock_info{$curdb}{$lock}{$type}{count} += $_lock_info{$curdb}{$lock}{$type}{count};
				$lock_info{$curdb}{$lock}{$type}{duration} += $_lock_info{$curdb}{$lock}{$type}{duration};
			}
		}
	}

	### nlines ###
	$nlines += $_nlines;

	### normalyzed_info ###
	foreach my $curdb (keys %_normalyzed_info)
	{
		foreach my $stmt (keys %{$_normalyzed_info{$curdb}})
		{
			foreach my $dt (keys %{$_normalyzed_info{$curdb}{$stmt}{samples}} )
			{
				foreach my $k (keys %{$_normalyzed_info{$curdb}{$stmt}{samples}{$dt}} ) {
					$normalyzed_info{$curdb}{$stmt}{samples}{$dt}{$k} = $_normalyzed_info{$curdb}{$stmt}{samples}{$dt}{$k};
				}
			}

			# Keep only the top N samples
			my $i = 1;
			foreach my $k (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$stmt}{samples}})
			{
				if ($i > $sample) {
					delete $normalyzed_info{$curdb}{$stmt}{samples}{$k};
				}
				$i++;
			}

			$normalyzed_info{$curdb}{$stmt}{count} += $_normalyzed_info{$curdb}{$stmt}{count};

			# Set min / max duration for this query
			if (!exists $normalyzed_info{$curdb}{$stmt}{min} || ($normalyzed_info{$curdb}{$stmt}{min} > $_normalyzed_info{$curdb}{$stmt}{min})) {
				$normalyzed_info{$curdb}{$stmt}{min} = $_normalyzed_info{$curdb}{$stmt}{min};
			}
			if (!exists $normalyzed_info{$curdb}{$stmt}{max} || ($normalyzed_info{$curdb}{$stmt}{max} < $_normalyzed_info{$curdb}{$stmt}{max})) {
				$normalyzed_info{$curdb}{$stmt}{max} = $_normalyzed_info{$curdb}{$stmt}{max};
			}

			foreach my $day (keys %{$_normalyzed_info{$curdb}{$stmt}{chronos}} )
			{
				foreach my $hour (keys %{$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}} )
				{
					$normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{count} +=
						$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{count};
					$normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{duration} +=
						$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{duration};
					foreach my $min (keys %{$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}} )
					{
						$normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}{$min} +=
							$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}{$min};
					}
					foreach my $min (keys %{$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}} )
					{
						$normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}{$min} +=
							$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}{$min};
					}
				}
			}

			$normalyzed_info{$curdb}{$stmt}{duration} += $_normalyzed_info{$curdb}{$stmt}{duration};

			if (exists $_normalyzed_info{$curdb}{$stmt}{locks})
			{
				$normalyzed_info{$curdb}{$stmt}{locks}{count} += $_normalyzed_info{$curdb}{$stmt}{locks}{count};
				$normalyzed_info{$curdb}{$stmt}{locks}{wait} += $_normalyzed_info{$curdb}{$stmt}{locks}{wait};
				if (!exists $normalyzed_info{$curdb}{$stmt}{locks}{minwait} || ($normalyzed_info{$curdb}{$stmt}{locks}{minwait} > $_normalyzed_info{$stmt}{locks}{minwait})) {
					$normalyzed_info{$curdb}{$stmt}{locks}{minwait} = $_normalyzed_info{$curdb}{$stmt}{locks}{minwait};
				}
				if (!exists $normalyzed_info{$curdb}{$stmt}{locks}{maxwait} || ($normalyzed_info{$curdb}{$stmt}{locks}{maxwait} < $_normalyzed_info{$curdb}{$stmt}{locks}{maxwait})) {
					$normalyzed_info{$curdb}{$stmt}{locks}{maxwait} = $_normalyzed_info{$curdb}{$stmt}{locks}{maxwait};
				}
			}

			if (exists $_normalyzed_info{$curdb}{$stmt}{tempfiles})
			{
				$normalyzed_info{$curdb}{$stmt}{tempfiles}{count} += $_normalyzed_info{$curdb}{$stmt}{tempfiles}{count};
				$normalyzed_info{$curdb}{$stmt}{tempfiles}{size} += $_normalyzed_info{$curdb}{$stmt}{tempfiles}{size};
				if (!exists $normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize} || ($normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize} > $_normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize})) {
					$normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize} = $_normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize};
				}
				if (!exists $normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize} || ($normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize} < $_normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize})) {
					$normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize} = $_normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize};
				}
			}

			if (exists $_normalyzed_info{$curdb}{$stmt}{cancelled}) {
				$normalyzed_info{$curdb}{$stmt}{cancelled}{count} += $_normalyzed_info{$curdb}{$stmt}{cancelled}{count};
			}

			foreach my $u (keys %{$_normalyzed_info{$curdb}{$stmt}{users}} )
			{
				foreach my $k (keys %{$_normalyzed_info{$curdb}{$stmt}{users}{$u}} ) {
					$normalyzed_info{$curdb}{$stmt}{users}{$u}{$k} += $_normalyzed_info{$curdb}{$stmt}{users}{$u}{$k};
				}
			}
			foreach my $u (keys %{$_normalyzed_info{$curdb}{$stmt}{apps}} )
			{
				foreach my $k (keys %{$_normalyzed_info{$curdb}{$stmt}{apps}{$u}} ) {
					$normalyzed_info{$curdb}{$stmt}{apps}{$u}{$k} += $_normalyzed_info{$curdb}{$stmt}{apps}{$u}{$k};
				}
			}
		}
	}

	### session_info ###
	foreach my $curdb (keys %_session_info)
	{
		foreach my $db (keys %{ $_session_info{$curdb}{database}})
		{
			$session_info{$curdb}{database}{$db}{count} += $_session_info{$curdb}{database}{$db}{count};
			$session_info{$curdb}{database}{$db}{duration} += $_session_info{$curdb}{database}{$db}{duration};
		}

		$session_info{$curdb}{count} += $_session_info{$curdb}{count};

		foreach my $day (keys %{ $_session_info{$curdb}{chronos}})
		{
			foreach my $hour (keys %{ $_session_info{$curdb}{chronos}{$day}})
			{
				$session_info{$curdb}{chronos}{$day}{$hour}{count} += $_session_info{$curdb}{chronos}{$day}{$hour}{count};
				$session_info{$curdb}{chronos}{$day}{$hour}{duration} += $_session_info{$curdb}{chronos}{$day}{$hour}{duration};
			}
		}

		foreach my $user (keys %{ $_session_info{$curdb}{user}})
		{
			$session_info{$curdb}{user}{$user}{count}    += $_session_info{$curdb}{user}{$user}{count};
			$session_info{$curdb}{user}{$user}{duration} += $_session_info{$curdb}{user}{$user}{duration};
		}

		$session_info{$curdb}{duration} += $_session_info{$curdb}{duration};

		foreach my $host (keys %{ $_session_info{$curdb}{host}})
		{
			$session_info{$curdb}{host}{$host}{count}    += $_session_info{$curdb}{host}{$host}{count};
			$session_info{$curdb}{host}{$host}{duration} += $_session_info{$curdb}{host}{$host}{duration};
		}

		foreach my $app (keys %{ $_session_info{$curdb}{app}})
		{
			$session_info{$curdb}{app}{$app}{count}    += $_session_info{$curdb}{app}{$app}{count};
			$session_info{$curdb}{app}{$app}{duration} += $_session_info{$curdb}{app}{$app}{duration};
		}
	}

	### pgbouncer session_info ###
	foreach my $db (keys %{ $_pgb_session_info{database}})
	{
		$pgb_session_info{database}{$db}{count} += $_pgb_session_info{database}{$db}{count};
		$pgb_session_info{database}{$db}{duration} += $_pgb_session_info{database}{$db}{duration};
	}

	$pgb_session_info{count} += $_pgb_session_info{count};

	foreach my $day (keys %{ $_pgb_session_info{chronos}})
	{
		foreach my $hour (keys %{ $_pgb_session_info{chronos}{$day}})
		{
			$pgb_session_info{chronos}{$day}{$hour}{count} += $_pgb_session_info{chronos}{$day}{$hour}{count};
			$pgb_session_info{chronos}{$day}{$hour}{duration} += $_pgb_session_info{chronos}{$day}{$hour}{duration};
		}
	}

	foreach my $user (keys %{ $_pgb_session_info{user}})
	{
		$pgb_session_info{user}{$user}{count}    += $_pgb_session_info{user}{$user}{count};
		$pgb_session_info{user}{$user}{duration} += $_pgb_session_info{user}{$user}{duration};
	}

	$pgb_session_info{duration} += $_pgb_session_info{duration};

	foreach my $host (keys %{ $_pgb_session_info{host}})
	{
		$pgb_session_info{host}{$host}{count}    += $_pgb_session_info{host}{$host}{count};
		$pgb_session_info{host}{$host}{duration} += $_pgb_session_info{host}{$host}{duration};
	}


	### tempfile_info ###
	foreach my $curdb (keys %_tempfile_info)
	{
		$tempfile_info{$curdb}{count} += $_tempfile_info{$curdb}{count}
			if defined $_tempfile_info{$curdb}{count};
		$tempfile_info{$curdb}{size} += $_tempfile_info{$curdb}{size}
			if defined $_tempfile_info{$curdb}{size};
		$tempfile_info{$curdb}{maxsize} = $_tempfile_info{$curdb}{maxsize}
			if defined $_tempfile_info{$curdb}{maxsize} and ( not defined $tempfile_info{$curdb}{maxsize}
				or $tempfile_info{$curdb}{maxsize} < $_tempfile_info{$curdb}{maxsize} );
	}

	### top_slowest ###
	foreach my $curdb (keys %_top_slowest)
	{
		my @tmp_top_slowest = sort {$b->[0] <=> $a->[0]} (@{$top_slowest{$curdb}}, @{$_top_slowest{$curdb}});
		@{$top_slowest{$curdb}} = ();
		for (my $i = 0; $i <= $#tmp_top_slowest; $i++)
		{
			push(@{$top_slowest{$curdb}}, $tmp_top_slowest[$i]);
			last if ($i == $end_top);
		}
	}

	### top_locked ###
	foreach my $curdb (keys %_top_locked_info)
	{
		my @tmp_top_locked_info = sort {$b->[0] <=> $a->[0]} (@{$top_locked_info{$curdb}}, @{$_top_locked_info{$curdb}});
		@{$top_locked_info{$curdb}} = ();
		for (my $i = 0; $i <= $#tmp_top_locked_info; $i++)
		{
			push(@{$top_locked_info{$curdb}}, $tmp_top_locked_info[$i]);
			last if ($i == $end_top);
		}
	}

	### top_tempfile ###
	foreach my $curdb (keys %_top_tempfile_info)
	{
		my @tmp_top_tempfile_info = sort {$b->[0] <=> $a->[0]} (@{$top_tempfile_info{$curdb}}, @{$_top_tempfile_info{$curdb}});
		@{$top_tempfile_info{$curdb}} = ();
		for (my $i = 0; $i <= $#tmp_top_tempfile_info; $i++)
		{
			push(@{$top_tempfile_info{$curdb}}, $tmp_top_tempfile_info[$i]);
			last if ($i == $end_top);
		}
	}

	### checkpoint_info ###
	foreach my $c (keys %{ $_checkpoint_info{starting} }) {
		$checkpoint_info{starting}{$c} += $_checkpoint_info{starting}{$c};
	}
	$checkpoint_info{file_removed} += $_checkpoint_info{file_removed};
	$checkpoint_info{sync} += $_checkpoint_info{sync};
	$checkpoint_info{wbuffer} += $_checkpoint_info{wbuffer};
	$checkpoint_info{file_recycled} += $_checkpoint_info{file_recycled};
	$checkpoint_info{total} += $_checkpoint_info{total};
	$checkpoint_info{file_added} += $_checkpoint_info{file_added};
	$checkpoint_info{write} += $_checkpoint_info{write};
	$checkpoint_info{distance} += $_checkpoint_info{distance};
	$checkpoint_info{estimate} += $_checkpoint_info{estimate};
	$checkpoint_info{warning} += $_checkpoint_info{warning};
	$checkpoint_info{warning_seconds} += $_checkpoint_info{warning_seconds};

	#### Autovacuum info ####
	foreach my $curdb (keys %_autovacuum_info)
	{
		$autovacuum_info{$curdb}{count} += $_autovacuum_info{$curdb}{count};

		foreach my $day (keys %{ $_autovacuum_info{$curdb}{chronos} })
		{
			foreach my $hour (keys %{ $_autovacuum_info{$curdb}{chronos}{$day} }) {
				$autovacuum_info{$curdb}{chronos}{$day}{$hour}{count} += $_autovacuum_info{$curdb}{chronos}{$day}{$hour}{count};
			}
		}
		foreach my $table (keys %{ $_autovacuum_info{$curdb}{tables} })
		{
			$autovacuum_info{$curdb}{tables}{$table}{vacuums} += $_autovacuum_info{$curdb}{tables}{$table}{vacuums};
			$autovacuum_info{$curdb}{tables}{$table}{idxscans} += $_autovacuum_info{$curdb}{tables}{$table}{idxscans};
			$autovacuum_info{$curdb}{tables}{$table}{tuples}{removed} += $_autovacuum_info{$curdb}{tables}{$table}{tuples}{removed};
			$autovacuum_info{$curdb}{tables}{$table}{tuples}{remain} += $_autovacuum_info{$curdb}{tables}{$table}{tuples}{remain};
			$autovacuum_info{$curdb}{tables}{$table}{tuples}{notremovable} += $_autovacuum_info{$curdb}{tables}{$table}{tuples}{notremovable};
			$autovacuum_info{$curdb}{tables}{$table}{pages}{removed} += $_autovacuum_info{$curdb}{tables}{$table}{pages}{removed};
			$autovacuum_info{$curdb}{tables}{$table}{pages}{remain} += $_autovacuum_info{$curdb}{tables}{$table}{pages}{remain};
			$autovacuum_info{$curdb}{tables}{$table}{hits} += $_autovacuum_info{$curdb}{tables}{$table}{hits};
			$autovacuum_info{$curdb}{tables}{$table}{misses} += $_autovacuum_info{$curdb}{tables}{$table}{misses};
			$autovacuum_info{$curdb}{tables}{$table}{dirtied} += $_autovacuum_info{$curdb}{tables}{$table}{dirtied};
			$autovacuum_info{$curdb}{tables}{$table}{skip_pins} += $_autovacuum_info{$curdb}{tables}{$table}{skip_pins};
			$autovacuum_info{$curdb}{tables}{$table}{skip_frozen} += $_autovacuum_info{$curdb}{tables}{$table}{skip_frozen};
			$autovacuum_info{$curdb}{tables}{$table}{wal_record} += $_autovacuum_info{$curdb}{tables}{$table}{wal_record};
			$autovacuum_info{$curdb}{tables}{$table}{wal_full_page} += $_autovacuum_info{$curdb}{tables}{$table}{wal_full_page};
			$autovacuum_info{$curdb}{tables}{$table}{wal_bytes} += $_autovacuum_info{$curdb}{tables}{$table}{wal_bytes};
		}
		if ($_autovacuum_info{$curdb}{peak}{system_usage}{elapsed} > $autovacuum_info{$curdb}{peak}{system_usage}{elapsed})
		{
			$autovacuum_info{$curdb}{peak}{system_usage}{elapsed} = $_autovacuum_info{$curdb}{peak}{system_usage}{elapsed};
			$autovacuum_info{$curdb}{peak}{system_usage}{table} = $_autovacuum_info{$curdb}{peak}{system_usage}{table};
			$autovacuum_info{$curdb}{peak}{system_usage}{date} = $_autovacuum_info{$curdb}{peak}{system_usage}{date};
		}
	}

	#### Autoanalyze info ####
	foreach my $curdb (keys %_autoanalyze_info)
	{
		$autoanalyze_info{$curdb}{count} += $_autoanalyze_info{$curdb}{count};

		foreach my $day (keys %{ $_autoanalyze_info{$curdb}{chronos} })
		{
			foreach my $hour (keys %{ $_autoanalyze_info{$curdb}{chronos}{$day} }) {
				$autoanalyze_info{$curdb}{chronos}{$day}{$hour}{count} += $_autoanalyze_info{$curdb}{chronos}{$day}{$hour}{count};
			}
		}
		foreach my $table (keys %{ $_autoanalyze_info{$curdb}{tables} }) {
			$autoanalyze_info{$curdb}{tables}{$table}{analyzes} += $_autoanalyze_info{$curdb}{tables}{$table}{analyzes};
		}
		if ($_autoanalyze_info{$curdb}{peak}{system_usage}{elapsed} > $autoanalyze_info{$curdb}{peak}{system_usage}{elapsed})
		{
			$autoanalyze_info{$curdb}{peak}{system_usage}{elapsed} = $_autoanalyze_info{$curdb}{peak}{system_usage}{elapsed};
			$autoanalyze_info{$curdb}{peak}{system_usage}{table} = $_autoanalyze_info{$curdb}{peak}{system_usage}{table};
			$autoanalyze_info{$curdb}{peak}{system_usage}{date} = $_autoanalyze_info{$curdb}{peak}{system_usage}{date};
		}
	}

	### prepare_info ###
	foreach my $curdb (keys %_prepare_info)
	{
		foreach my $stmt (keys %{$_prepare_info{$curdb}})
		{
			foreach my $dt (keys %{$_prepare_info{$curdb}{$stmt}{samples}} )
			{
				foreach my $k (keys %{$_prepare_info{$curdb}{$stmt}{samples}{$dt}} ) {
					$prepare_info{$curdb}{$stmt}{samples}{$dt}{$k} = $_prepare_info{$curdb}{$stmt}{samples}{$dt}{$k};
				}
			}

			# Keep only the top N samples
			my $i = 1;
			foreach my $k (sort {$b <=> $a} keys %{$prepare_info{$curdb}{$stmt}{samples}})
			{
				if ($i > $sample) {
					delete $prepare_info{$curdb}{$stmt}{samples}{$k};
				}
				$i++;
			}

			$prepare_info{$curdb}{$stmt}{count} += $_prepare_info{$curdb}{$stmt}{count};

			# Set min / max duration for this query
			if (!exists $prepare_info{$curdb}{$stmt}{min} || ($prepare_info{$curdb}{$stmt}{min} > $_prepare_info{$curdb}{$stmt}{min})) {
				$prepare_info{$curdb}{$stmt}{min} = $_prepare_info{$curdb}{$stmt}{min};
			}
			if (!exists $prepare_info{$curdb}{$stmt}{max} || ($prepare_info{$curdb}{$stmt}{max} < $_prepare_info{$curdb}{$stmt}{max})) {
				$prepare_info{$curdb}{$stmt}{max} = $_prepare_info{$curdb}{$stmt}{max};
			}

			foreach my $day (keys %{$_prepare_info{$curdb}{$stmt}{chronos}} )
			{
				foreach my $hour (keys %{$_prepare_info{$curdb}{$stmt}{chronos}{$day}} )
				{
					$prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{count} +=
						$_prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{count};
					$prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{duration} +=
						$_prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{duration};
					foreach my $min (keys %{$_prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}} )
					{
						$prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}{$min} +=
							$_prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}{$min};
					}
					foreach my $min (keys %{$_prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}} )
					{
						$prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}{$min} +=
							$_prepare_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}{$min};
					}
				}
			}

			$prepare_info{$curdb}{$stmt}{duration} += $_prepare_info{$curdb}{$stmt}{duration};

			if (exists $_prepare_info{$curdb}{$stmt}{locks})
			{
				$prepare_info{$curdb}{$stmt}{locks}{count} += $_prepare_info{$curdb}{$stmt}{locks}{count};
				$prepare_info{$curdb}{$stmt}{locks}{wait} += $_prepare_info{$curdb}{$stmt}{locks}{wait};
				if (!exists $prepare_info{$curdb}{$stmt}{locks}{minwait} || ($prepare_info{$curdb}{$stmt}{locks}{minwait} > $_prepare_info{$stmt}{locks}{minwait})) {
					$prepare_info{$curdb}{$stmt}{locks}{minwait} = $_prepare_info{$curdb}{$stmt}{locks}{minwait};
				}
				if (!exists $prepare_info{$curdb}{$stmt}{locks}{maxwait} || ($prepare_info{$curdb}{$stmt}{locks}{maxwait} < $_prepare_info{$curdb}{$stmt}{locks}{maxwait})) {
					$prepare_info{$curdb}{$stmt}{locks}{maxwait} = $_prepare_info{$curdb}{$stmt}{locks}{maxwait};
				}
			}

			if (exists $_prepare_info{$curdb}{$stmt}{tempfiles})
			{
				$prepare_info{$curdb}{$stmt}{tempfiles}{count} += $_prepare_info{$curdb}{$stmt}{tempfiles}{count};
				$prepare_info{$curdb}{$stmt}{tempfiles}{size} += $_prepare_info{$curdb}{$stmt}{tempfiles}{size};
				if (!exists $prepare_info{$curdb}{$stmt}{tempfiles}{minsize} || ($prepare_info{$curdb}{$stmt}{tempfiles}{minsize} > $_prepare_info{$curdb}{$stmt}{tempfiles}{minsize})) {
					$prepare_info{$curdb}{$stmt}{tempfiles}{minsize} = $_prepare_info{$curdb}{$stmt}{tempfiles}{minsize};
				}
				if (!exists $prepare_info{$curdb}{$stmt}{tempfiles}{maxsize} || ($prepare_info{$curdb}{$stmt}{tempfiles}{maxsize} < $_prepare_info{$curdb}{$stmt}{tempfiles}{maxsize})) {
					$prepare_info{$curdb}{$stmt}{tempfiles}{maxsize} = $_prepare_info{$curdb}{$stmt}{tempfiles}{maxsize};
				}
			}

			if (exists $_prepare_info{$curdb}{$stmt}{cancelled}) {
				$prepare_info{$curdb}{$stmt}{cancelled}{count} += $_prepare_info{$curdb}{$stmt}{cancelled}{count};
			}

			foreach my $u (keys %{$_prepare_info{$curdb}{$stmt}{users}} )
			{
				foreach my $k (keys %{$_prepare_info{$curdb}{$stmt}{users}{$u}} ) {
					$prepare_info{$curdb}{$stmt}{users}{$u}{$k} += $_prepare_info{$curdb}{$stmt}{users}{$u}{$k};
				}
			}
			foreach my $u (keys %{$_prepare_info{$curdb}{$stmt}{apps}} )
			{
				foreach my $k (keys %{$_prepare_info{$curdb}{$stmt}{apps}{$u}} ) {
					$prepare_info{$curdb}{$stmt}{apps}{$u}{$k} += $_prepare_info{$curdb}{$stmt}{apps}{$u}{$k};
				}
			}
		}
	}

	### bind_info ###
	foreach my $curdb (keys %_bind_info)
	{
		foreach my $stmt (keys %{$_bind_info{$curdb}})
		{

			foreach my $dt (keys %{$_bind_info{$curdb}{$stmt}{samples}} )
			{
				foreach my $k (keys %{$_bind_info{$curdb}{$stmt}{samples}{$dt}} ) {
					$bind_info{$curdb}{$stmt}{samples}{$dt}{$k} = $_bind_info{$curdb}{$stmt}{samples}{$dt}{$k};
				}
			}

			# Keep only the top N samples
			my $i = 1;
			foreach my $k (sort {$b <=> $a} keys %{$bind_info{$curdb}{$stmt}{samples}})
			{
				if ($i > $sample) {
					delete $bind_info{$curdb}{$stmt}{samples}{$k};
				}
				$i++;
			}

			$bind_info{$curdb}{$stmt}{count} += $_bind_info{$curdb}{$stmt}{count};

			# Set min / max duration for this query
			if (!exists $bind_info{$curdb}{$stmt}{min} || ($bind_info{$curdb}{$stmt}{min} > $_bind_info{$curdb}{$stmt}{min})) {
				$bind_info{$curdb}{$stmt}{min} = $_bind_info{$curdb}{$stmt}{min};
			}
			if (!exists $bind_info{$curdb}{$stmt}{max} || ($bind_info{$curdb}{$stmt}{max} < $_bind_info{$curdb}{$stmt}{max})) {
				$bind_info{$curdb}{$stmt}{max} = $_bind_info{$curdb}{$stmt}{max};
			}

			foreach my $day (keys %{$_bind_info{$curdb}{$stmt}{chronos}} )
			{
				foreach my $hour (keys %{$_bind_info{$curdb}{$stmt}{chronos}{$day}} )
				{
					$bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{count} +=
						$_bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{count};
					$bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{duration} +=
						$_bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{duration};
					foreach my $min (keys %{$_bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}} )
					{
						$bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}{$min} +=
							$_bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}{$min};
					}
					foreach my $min (keys %{$_bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}} )
					{
						$bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}{$min} +=
							$_bind_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}{$min};
					}
				}
			}

			$bind_info{$curdb}{$stmt}{duration} += $_bind_info{$curdb}{$stmt}{duration};

			if (exists $_bind_info{$curdb}{$stmt}{locks})
			{
				$bind_info{$curdb}{$stmt}{locks}{count} += $_bind_info{$curdb}{$stmt}{locks}{count};
				$bind_info{$curdb}{$stmt}{locks}{wait} += $_bind_info{$curdb}{$stmt}{locks}{wait};
				if (!exists $bind_info{$curdb}{$stmt}{locks}{minwait} || ($bind_info{$curdb}{$stmt}{locks}{minwait} > $_bind_info{$stmt}{locks}{minwait})) {
					$bind_info{$curdb}{$stmt}{locks}{minwait} = $_bind_info{$curdb}{$stmt}{locks}{minwait};
				}
				if (!exists $bind_info{$curdb}{$stmt}{locks}{maxwait} || ($bind_info{$curdb}{$stmt}{locks}{maxwait} < $_bind_info{$curdb}{$stmt}{locks}{maxwait})) {
					$bind_info{$curdb}{$stmt}{locks}{maxwait} = $_bind_info{$curdb}{$stmt}{locks}{maxwait};
				}
			}

			if (exists $_bind_info{$curdb}{$stmt}{tempfiles})
			{
				$bind_info{$curdb}{$stmt}{tempfiles}{count} += $_bind_info{$curdb}{$stmt}{tempfiles}{count};
				$bind_info{$curdb}{$stmt}{tempfiles}{size} += $_bind_info{$curdb}{$stmt}{tempfiles}{size};
				if (!exists $bind_info{$curdb}{$stmt}{tempfiles}{minsize} || ($bind_info{$curdb}{$stmt}{tempfiles}{minsize} > $_bind_info{$curdb}{$stmt}{tempfiles}{minsize})) {
					$bind_info{$curdb}{$stmt}{tempfiles}{minsize} = $_bind_info{$curdb}{$stmt}{tempfiles}{minsize};
				}
				if (!exists $bind_info{$curdb}{$stmt}{tempfiles}{maxsize} || ($bind_info{$curdb}{$stmt}{tempfiles}{maxsize} < $_bind_info{$curdb}{$stmt}{tempfiles}{maxsize})) {
					$bind_info{$curdb}{$stmt}{tempfiles}{maxsize} = $_bind_info{$curdb}{$stmt}{tempfiles}{maxsize};
				}
			}

			if (exists $_bind_info{$curdb}{$stmt}{cancelled}) {
				$bind_info{$curdb}{$stmt}{cancelled}{count} += $_bind_info{$curdb}{$stmt}{cancelled}{count};
			}

			foreach my $u (keys %{$_bind_info{$curdb}{$stmt}{users}} )
			{
				foreach my $k (keys %{$_bind_info{$curdb}{$stmt}{users}{$u}} ) {
					$bind_info{$curdb}{$stmt}{users}{$u}{$k} += $_bind_info{$curdb}{$stmt}{users}{$u}{$k};
				}
			}
			foreach my $u (keys %{$_bind_info{$curdb}{$stmt}{apps}} )
			{
				foreach my $k (keys %{$_bind_info{$curdb}{$stmt}{apps}{$u}} ) {
					$bind_info{$curdb}{$stmt}{apps}{$u}{$k} += $_bind_info{$curdb}{$stmt}{apps}{$u}{$k};
				}
			}
		}
	}

	if (exists $overall_stat{nlines})
	{
		foreach my $db (sort keys %{$overall_stat{nlines}}) {
			$DBLIST{$db} = 1;
		}
	}

	return 1;
}

# Function used to dump all relevant objects in memory to a single binary file
sub dump_as_binary
{
	my $lfh = shift();

	store_fd({
		'version' => \$VERSION,
		'overall_stat' => \%overall_stat,
		'pgb_overall_stat' => \%pgb_overall_stat,
		'overall_checkpoint' => \%overall_checkpoint,
		'normalyzed_info' => \%normalyzed_info,
		'error_info' => \%error_info,
		'pgb_error_info' => \%pgb_error_info,
		'pgb_pool_info' => \%pgb_pool_info,
		'connection_info' => \%connection_info,
		'pgb_connection_info' => \%pgb_connection_info,
		'database_info' => \%database_info,
		'application_info' => \%application_info,
		'user_info' => \%user_info,
		'host_info' => \%host_info,
		'checkpoint_info' => \%checkpoint_info,
		'session_info' => \%session_info,
		'pgb_session_info' => \%pgb_session_info,
		'tempfile_info' => \%tempfile_info,
		'logs_type' => \%logs_type,
		'lock_info' => \%lock_info,
		'per_minute_info' => \%per_minute_info,
		'pgb_per_minute_info' => \%pgb_per_minute_info,
		'top_slowest' => \%top_slowest,
		'nlines' => $nlines,
		'log_files' => \@log_files,
		'autovacuum_info' => \%autovacuum_info,
		'autoanalyze_info' => \%autoanalyze_info,
		'top_tempfile_info' => \%top_tempfile_info,
		'top_locked_info' => \%top_locked_info,
		'prepare_info' => \%prepare_info,
		'bind_info' => \%bind_info,
	}, $lfh) || localdie ("Couldn't save binary data to \"$current_out_file\"!\n");
}

sub dump_error_as_json
{
	my $perl_hash = { 'error_info' => \%error_info };

	my $json = undef;
	if (!$json_prettify) {
		$json = encode_json($perl_hash) || localdie ("Encode events objects to JSON failed!\n");
	} else {
		my $coder = JSON::XS->new->ascii->pretty->allow_nonref(0);
		$json = $coder->encode($perl_hash) || localdie ("Encode events objects to prettified JSON failed!\n");
	}

	print $fh $json;
}

sub dump_as_json
{
	my $perl_hash = {
		'overall_stat' => \%overall_stat,
		'pgb_overall_stat' => \%pgb_overall_stat,
		'overall_checkpoint' => \%overall_checkpoint,
		'normalyzed_info' => \%normalyzed_info,
		'error_info' => \%error_info,
		'pgb_error_info' => \%pgb_error_info,
		'pgb_pool_info' => \%pgb_pool_info,
		'connection_info' => \%connection_info,
		'pgb_connection_info' => \%pgb_connection_info,
		'database_info' => \%database_info,
		'application_info' => \%application_info,
		'user_info' => \%user_info,
		'host_info' => \%host_info,
		'checkpoint_info' => \%checkpoint_info,
		'session_info' => \%session_info,
		'pgb_session_info' => \%pgb_session_info,
		'tempfile_info' => \%tempfile_info,
		'logs_type' => \%logs_type,
		'lock_info' => \%lock_info,
		'per_minute_info' => \%per_minute_info,
		'pgb_per_minute_info' => \%pgb_per_minute_info,
		'top_slowest' => \%top_slowest,
		'nlines' => $nlines,
		'log_files' => \@log_files,
		'autovacuum_info' => \%autovacuum_info,
		'autoanalyze_info' => \%autoanalyze_info,
		'top_tempfile_info' => \%top_tempfile_info,
		'top_locked_info' => \%top_locked_info
	};
	my $json = undef;
	if (!$json_prettify) {
		$json = encode_json($perl_hash) || localdie ("Encode stats objects to JSON failed!\n");
	} else {
		my $coder = JSON::XS->new->ascii->pretty->allow_nonref(0);
		$json = $coder->encode($perl_hash) || localdie ("Encode stats objects to prettified JSON failed!\n");
	}

	print $fh $json;
}

# Highlight SQL code
sub highlight_code
{
	my $code = shift;

	# Escape HTML code into SQL values
	$code = &escape_html($code);

	# Do not try to prettify queries longer
	# than 10KB as this will take too much time
	return $code if (length($code) > $MAX_QUERY_LENGTH);

	# prettify SQL query
	if (!$noprettify) {
		$sql_prettified->query($code);
		$sql_prettified->beautify();
		$code = $sql_prettified->content();
	}

	if ($wide_char)
	{
		$code = encode('UTF-8', $code);
	}
	return $code;
}

sub compute_arg_list
{

	# Some command line arguments can be used multiple times or written
	# as a comma-separated list.
	# For example: --dbuser=postgres --dbuser=joe or --dbuser=postgres,joe
	# So we have to aggregate all the possible values
	my @tmp = ();
	foreach my $v (@exclude_user) {
		push(@tmp, split(/,/, $v));
	}
	@exclude_user = ();
	push(@exclude_user, @tmp);

	@tmp = ();
	foreach my $v (@dbname) {
		push(@tmp, split(/,/, $v));
	}
	@dbname = ();
	push(@dbname, @tmp);

	@tmp = ();
	foreach my $v (@dbuser) {
		push(@tmp, split(/,/, $v));
	}
	@dbuser = ();
	push(@dbuser, @tmp);

	@tmp = ();
	foreach my $v (@dbclient) {
		push(@tmp, split(/,/, $v));
	}
	@dbclient = ();
	push(@dbclient, @tmp);

	@tmp = ();
	foreach my $v (@dbappname) {
		push(@tmp, split(/,/, $v));
	}
	@dbappname = ();
	push(@dbappname, @tmp);

	@tmp = ();
	foreach my $v (@exclude_appname) {
		push(@tmp, split(/,/, $v));
	}
	@exclude_appname = ();
	push(@exclude_appname, @tmp);

	@tmp = ();
	foreach my $v (@exclude_db) {
		push(@tmp, split(/,/, $v));
	}
	@exclude_db = ();
	push(@exclude_db, @tmp);

	@tmp = ();
	foreach my $v (@exclude_line) {
		push(@tmp, split(/,/, $v));
	}
	@exclude_line = ();
	push(@exclude_line, @tmp);

	@tmp = ();
	foreach my $v (@exclude_client) {
		push(@tmp, split(/,/, $v));
	}
	@exclude_client = ();
	push(@exclude_client, @tmp);

	@tmp = ();
	foreach my $v (@exclude_queryid) {
		push(@tmp, split(/,/, $v));
	}
	@exclude_queryid = ();
	push(@exclude_queryid, @tmp);

}

sub validate_log_line
{
	my ($t_pid) = @_;

	# Set details about connection if prefix doesn't included them
	# and log_connection is enabled
	if ($prefix_vars{'t_loglevel'} eq 'LOG')
	{
		if ( !$prefix_vars{'t_client'} && ($prefix_vars{'t_query'} =~ /connection received: host=([^\s]+)(?: port=(\d+))?/) ) {
			$current_sessions{$prefix_vars{'t_pid'}}{host} = $1;
			return 1;
		} elsif ( !$prefix_vars{'t_dbname'} && ($prefix_vars{'t_query'} =~ /connection authorized: user=([^\s]+)(?: database=([^\s]+))?/) ) {
			$current_sessions{$prefix_vars{'t_pid'}}{user} = $1;
			$current_sessions{$prefix_vars{'t_pid'}}{database} = $2;
			if ($prefix_vars{'t_query'} =~ /application_name=(.*)/)
			{
				if ($1)
				{
					$prefix_vars{'t_appname'} = $1;
					$prefix_vars{'t_appname'} =~ s/[<>]/'/g;
					$current_sessions{$prefix_vars{'t_pid'}}{appname} = $1;
				}
			}
		}
		if ( !$prefix_vars{'t_appname'} && ($prefix_vars{'t_query'} =~ /connection authorized: user=([^\s]+) application_name=([^\s]+)/) ) {
			$prefix_vars{'t_appname'} = $2;
			$prefix_vars{'t_appname'} =~ s/[<>]/'/g;
			$current_sessions{$prefix_vars{'t_pid'}}{appname} = $2;
		}
	}

	# Set details from previous connection line
	$prefix_vars{'t_dbname'} = $current_sessions{$t_pid}{database}
		if (!$prefix_vars{'t_dbname'} && exists $current_sessions{$t_pid}{database});
	$prefix_vars{'t_dbuser'} = $current_sessions{$t_pid}{user}
		if (!$prefix_vars{'t_dbuser'} && exists $current_sessions{$t_pid}{user});
	$prefix_vars{'t_client'} = $current_sessions{$t_pid}{host}
		if (!$prefix_vars{'t_client'} && exists $current_sessions{$t_pid}{host});
	$prefix_vars{'t_appname'} = $current_sessions{$t_pid}{appname}
		if (!$prefix_vars{'t_appname'} && exists $current_sessions{$t_pid}{appname});
	# Clear storage, the authorized session will be reparsed after
	delete $current_sessions{$prefix_vars{'t_pid'}};

	# Look at particular cases of vacuum/analyze that have the database
	# name inside the log message so that they could be associated
	if ($prefix_vars{'t_query'} =~ / of table "([^\.]+)\.[^\.]+\.[^\.]+":/) {
		$prefix_vars{'t_dbname'}  = $1;
	}

	# Check user and/or database if required
	if ($#dbname >= 0)
	{
		# Log line does not match the required dbname
		if (!$prefix_vars{'t_dbname'} || !grep(/^$prefix_vars{'t_dbname'}$/i, @dbname))
		{
			delete $current_sessions{$prefix_vars{'t_pid'}};
			delete $last_execute_stmt{$prefix_vars{'t_pid'}};
			%prefix_vars = ();
			return 0;
		}
	}
	if ($#dbuser >= 0)
	{
		# Log line does not match the required dbuser
		if (!$prefix_vars{'t_dbuser'} || !grep(/^$prefix_vars{'t_dbuser'}$/i, @dbuser))
		{
			delete $current_sessions{$prefix_vars{'t_pid'}};
			delete $last_execute_stmt{$prefix_vars{'t_pid'}};
			return 0;
		}
	}
	if ($#dbclient >= 0)
	{
		# Log line does not match the required dbclient
		if (!$prefix_vars{'t_client'} || !grep(/^$prefix_vars{'t_client'}$/i, @dbclient))
		{
			delete $current_sessions{$prefix_vars{'t_pid'}};
			delete $last_execute_stmt{$prefix_vars{'t_pid'}};
			return 0;
		}
	}
	if ($#dbappname >= 0)
	{
		# Log line does not match the required dbname
		if (!$prefix_vars{'t_appname'} || !grep(/^\Q$prefix_vars{'t_appname'}\E$/i, @dbappname))
		{
			delete $current_sessions{$prefix_vars{'t_pid'}};
			delete $last_execute_stmt{$prefix_vars{'t_pid'}};
			return 0;
		}
	}
	if ($#exclude_db >= 0)
	{
		# Log line matches the excluded db
		if ($prefix_vars{'t_dbname'} && grep(/^\Q$prefix_vars{'t_dbname'}\E$/i, @exclude_db))
		{
			delete $current_sessions{$prefix_vars{'t_pid'}};
			delete $last_execute_stmt{$prefix_vars{'t_pid'}};
			return 0;
		}
	}
	if ($#exclude_user >= 0)
	{
		# Log line matches the excluded dbuser
		if ($prefix_vars{'t_dbuser'} && grep(/^$prefix_vars{'t_dbuser'}$/i, @exclude_user))
		{
			delete $current_sessions{$prefix_vars{'t_pid'}};
			delete $last_execute_stmt{$prefix_vars{'t_pid'}};
			return 0;
		}
	}
	if ($#exclude_appname >= 0 && $prefix_vars{'t_appname'})
	{
		# Log line matches the excluded appname
		foreach my $p (@exclude_appname)
		{
			if ($prefix_vars{'t_appname'} =~ /^$p$/i)
			{
				delete $current_sessions{$prefix_vars{'t_pid'}};
				delete $last_execute_stmt{$prefix_vars{'t_pid'}};
				return 0;
			}
		}
	}
	if ($#exclude_client >= 0 && $prefix_vars{'t_client'})
	{
		# Log line matches the excluded dbclient
		foreach my $p (@exclude_client)
		{
			if ($prefix_vars{'t_client'} =~ /^$p$/i)
			{
				delete $current_sessions{$prefix_vars{'t_pid'}};
				delete $last_execute_stmt{$prefix_vars{'t_pid'}};
				return 0;
			}
		}
	}
	if ($#exclude_queryid >= 0)
	{
		# Log line matches the excluded queryid
		if ($prefix_vars{'t_queryid'} && grep(/^$prefix_vars{'t_queryid'}$/i, @exclude_queryid))
		{
			delete $current_sessions{$prefix_vars{'t_pid'}};
			delete $last_execute_stmt{$prefix_vars{'t_pid'}};
			return 0;
		}
	}
	return 1;
}

sub parse_log_prefix
{
	my ($t_logprefix) = @_;

	# Extract user and database information from the logprefix part
	if ($t_logprefix)
	{
		# Search for database user
		if ($t_logprefix =~ $regex_prefix_dbuser) {
			$prefix_vars{'t_dbuser'} = $1;
			$prefix_vars{'t_dbuser'} =~ s/^"([^"]+)".*/$1/;
		}

		# Search for database name
		if ($t_logprefix =~ $regex_prefix_dbname) {
			$prefix_vars{'t_dbname'} = $1;
			$prefix_vars{'t_dbname'} =~ s/^"([^"]+)".*/$1/;
		}

		# Search for client host name
		if ($t_logprefix =~ $regex_prefix_dbclient) {
			$prefix_vars{'t_dbclient'} = $1;
			$prefix_vars{'t_dbclient'} =~ s/^"//;
			$prefix_vars{'t_dbclient'} = _gethostbyaddr($prefix_vars{'t_dbclient'}) if ($dns_resolv);
		}

		# Search for application name
		if ($t_logprefix =~ $regex_prefix_dbappname) {
			$prefix_vars{'t_appname'} = $1;
			$prefix_vars{'t_appname'} =~ s/^"([^"]+)".*/$1/;
			$prefix_vars{'t_appname'} =~ s/[<>]/'/g;
		}

		# Search for queryid
		if ($t_logprefix =~ $regex_prefix_queryid) {
				$prefix_vars{'t_queryid'} = $1;
		}

		# Search for sql state code
		if ($t_logprefix =~ $regex_prefix_sqlstate) {
			$prefix_vars{'t_sqlstate'} = $1;
		}

		# Search for backend type
		if ($t_logprefix =~ $regex_prefix_backendtype) {
			$prefix_vars{'t_backend_type'} = $1;
		}

	}
}

sub is_excluded_query
{
	my $query = shift;

	foreach (@exclude_query)
	{
		if ($query =~ /$_/i)
		{
			$query = '';
			return 1;
		}
	}

	return 0;
}

sub is_included_query
{
	my $query = shift;
	foreach (@include_query)
	{
		if ($query =~ /$_/i)
		{
			$query = '';
			return 1;
		}
	}
	return 0;
}

sub parse_query
{
	my $fmt = shift;

	my $is_log_level = 0;

	my $t_pid = $prefix_vars{'t_pid'};

	my $curdb = $DBALL;
	if (exists $cur_info{$t_pid} && exists $cur_info{$t_pid}{cur_db})
	{
       		$curdb = $cur_info{$t_pid}{cur_db};
	}
	else
	{
		$curdb = set_current_db($prefix_vars{'t_dbname'});
	}

	my $date_part = "$prefix_vars{'t_year'}$prefix_vars{'t_month'}$prefix_vars{'t_day'}";
	my $cur_last_log_timestamp = "$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} " .
				     "$prefix_vars{t_hour}:$prefix_vars{t_min}:$prefix_vars{t_sec}";

	# Delete old bind query temporary storage
	foreach my $p (keys %last_execute_stmt) {
		delete $last_execute_stmt{$p} if ($p > $t_pid);
	}

	####
	# Force some LOG messages to be ERROR messages so that they will appear
	# in the event/error/warning messages report.
	####
	if ($prefix_vars{'t_loglevel'} eq 'LOG')
	{
		if (&change_log_level($prefix_vars{'t_query'}))
		{
			$prefix_vars{'t_origloglevel'} = 'EVENTLOG';
			$prefix_vars{'t_loglevel'} = 'ERROR';
		}
		else
		{
			$is_log_level = 1;
		}
	}
	elsif (($prefix_vars{'t_loglevel'} eq 'ERROR') && !$error_only)
	{
		if ($prefix_vars{'t_query'} =~ /canceling statement due to statement timeout/)
		{
			# Stores cancelled queries
			return if ($disable_query);
			$cancelled_info{$curdb}{count}++;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{cancelled}{count}++;
			# Store current cancelled query information that will be used later
			# when we will parse the query that has been killed
			$overall_stat{$curdb}{'peak'}{$cur_last_log_timestamp}{cancelled_count}++;
			$cur_cancel_info{$t_pid}{count}++;
			if ($fmt eq 'csv') {
				$cur_cancel_info{$t_pid}{query}     = $prefix_vars{'t_statement'};
			}
			$cur_cancel_info{$t_pid}{timestamp} = $prefix_vars{'t_timestamp'};
			$cur_cancel_info{$t_pid}{dbname}    = $prefix_vars{'t_dbname'};
			$cur_cancel_info{$t_pid}{dbuser}    = $prefix_vars{'t_dbuser'};
			$cur_cancel_info{$t_pid}{dbclient}  = $prefix_vars{'t_client'} || $prefix_vars{'t_dbclient'};
			$cur_cancel_info{$t_pid}{dbappname} = $prefix_vars{'t_appname'};
			$cur_cancel_info{$t_pid}{cur_db}    = $curdb;
		}
		elsif (exists $cur_cancel_info{$t_pid})
		{
			&store_temporary_and_lock_infos($t_pid);
		}
	}

	# Remove session failure from current workload because there is no disconnection entry
	if (!$disable_session && ($prefix_vars{'t_loglevel'} eq 'FATAL'))
	{
		delete $current_sessions{$t_pid};
		delete $last_execute_stmt{$t_pid};
	}
	elsif (!$disable_session && ($prefix_vars{'t_loglevel'} eq 'WARNING'))
	{
		if ($prefix_vars{'t_query'} =~ /terminating connection/)
		{
			delete $current_sessions{$t_pid};
			delete $last_execute_stmt{$t_pid};
		}
	}

	# Do not process DEALLOCATE lines
	if ($prefix_vars{'t_query'} =~ /statement: DEALLOCATE/) {
		return;
	}

	# Store a counter of logs type
	if (!exists $prefix_vars{'t_origloglevel'}) {
		$logs_type{$curdb}{$prefix_vars{'t_loglevel'}}++;
	} else {
		$logs_type{$curdb}{$prefix_vars{'t_origloglevel'}}++;
	}

	# Do not parse lines that are not an error message when error only report is requested
	if ($error_only && ($prefix_vars{'t_loglevel'} !~ $full_error_regex)) {
		return;
	}

	# Do not parse lines that are an error-like message when error reports are not wanted
	if ($disable_error && ($prefix_vars{'t_loglevel'} =~ $full_error_regex)) {
		return;
	}

	# Replace syslog tabulation rewrite
	if ($fmt =~ /syslog|logplex/) {
		$prefix_vars{'t_query'} =~ s/#011/\t/g;
	}

	# Save previous temporary file information with same pid to not overwrite it
	if ($prefix_vars{'t_loglevel'} =~ $main_log_regex)
	{
		if ($prefix_vars{'t_query'} !~ /temporary file: path .*, size \d+/
			&& exists $cur_temp_info{$t_pid})
		{
			&store_temporary_and_lock_infos($t_pid);
		# When only log_temp_files is enabled
		} elsif ($prefix_vars{'t_query'} =~ /temporary file: path .*, size \d+/
			&& exists $cur_temp_info{$t_pid})
		{
			&store_temporary_and_lock_infos($t_pid);
		}
		if (($prefix_vars{'t_query'} !~ /acquired [^\s]+ on [^\s]+ .* after [0-9\.]+ ms/)
			&& exists $cur_lock_info{$t_pid})
		{
			&store_temporary_and_lock_infos($t_pid);
		}
	}

	# Stores the error's detail if previous line was an error
	if (exists $cur_info{$t_pid} && ($prefix_vars{'t_loglevel'} =~ /(DETAIL|STATEMENT|CONTEXT|HINT)/)
		&& ($cur_info{$t_pid}{loglevel} =~ $main_error_regex))
	{
		if (($prefix_vars{'t_loglevel'} ne 'DETAIL') || ($prefix_vars{'t_query'} !~ /parameters: (.*)/)) {
			# Store error details only if this is not a parameter list (never present with errors)
			$cur_info{$t_pid}{"\L$prefix_vars{'t_loglevel'}\E"} .= $prefix_vars{'t_query'};
		}
		if (($prefix_vars{'t_loglevel'} eq 'STATEMENT') && exists $cur_temp_info{$t_pid} && ($cur_temp_info{$t_pid}{query} eq '')) {
			$cur_temp_info{$t_pid}{query} = $prefix_vars{'t_query'};
		}
		#return;
	}

	# Special cases when a STATEMENT is parsed
	if ($prefix_vars{'t_loglevel'} eq 'STATEMENT')
	{
		# Stores temporary file statement if a temporary record with the same pid exists
		if ( exists $cur_temp_info{$t_pid}{size})
		{
			# Store query of the last temporary file found.
			$cur_temp_info{$t_pid}{query} = $prefix_vars{'t_query'};
			return;
		}

		# Stores query related to last lock information
		if (exists $cur_lock_info{$t_pid}{wait})
		{
			$cur_lock_info{$t_pid}{query}     = $prefix_vars{'t_query'};
			$cur_lock_info{$t_pid}{timestamp} = $prefix_vars{'t_timestamp'};
			$cur_lock_info{$t_pid}{dbname}    = $prefix_vars{'t_dbname'};
			$cur_lock_info{$t_pid}{dbuser}    = $prefix_vars{'t_dbuser'};
			$cur_lock_info{$t_pid}{dbclient}  = $prefix_vars{'t_client'} || $prefix_vars{'t_dbclient'};
			$cur_lock_info{$t_pid}{dbappname} = $prefix_vars{'t_appname'};
			$cur_lock_info{$t_pid}{queryid}   = $prefix_vars{'t_queryid'};
			$cur_lock_info{$t_pid}{cur_db}    = $curdb;
			return;
		}

		# Stores query related to cancelled queries information
		if (exists $cur_cancel_info{$t_pid}{count})
		{
			$cur_cancel_info{$t_pid}{query}     = $prefix_vars{'t_query'};
			$cur_cancel_info{$t_pid}{timestamp} = $prefix_vars{'t_timestamp'};
			$cur_cancel_info{$t_pid}{dbname}    = $prefix_vars{'t_dbname'};
			$cur_cancel_info{$t_pid}{dbuser}    = $prefix_vars{'t_dbuser'};
			$cur_cancel_info{$t_pid}{dbclient}  = $prefix_vars{'t_client'} || $prefix_vars{'t_dbclient'};
			$cur_cancel_info{$t_pid}{dbappname} = $prefix_vars{'t_appname'};
			$cur_cancel_info{$t_pid}{queryid}   = $prefix_vars{'t_queryid'};
			$cur_cancel_info{$t_pid}{cur_db}    = $curdb;
			return;
		}

	}

	# set current session workload
	if ( !$disable_session )
	{
		my $sess_count = scalar keys %current_sessions;
		$overall_stat{$curdb}{'peak'}{$cur_last_log_timestamp}{session} = $sess_count;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{"$prefix_vars{'t_min'}"}{session}{count} = $sess_count;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{"$prefix_vars{'t_min'}"}{session}{second}{$prefix_vars{'t_sec'}} = $sess_count;
	}

	# Stores lock activity
	if ($is_log_level && ($prefix_vars{'t_query'} =~ /acquired ([^\s]+) on ([^\s]+) .* after ([0-9\.]+) ms/))
	{
		return if ($disable_lock);
		$lock_info{$curdb}{$1}{count}++;
		$lock_info{$curdb}{$1}{duration} += $3;
		$lock_info{$curdb}{$1}{$2}{count}++;
		$lock_info{$curdb}{$1}{$2}{duration} += $3;
		$lock_info{$curdb}{$1}{chronos}{$date_part}{$prefix_vars{'t_hour'}}{count}++;
		$lock_info{$curdb}{$1}{chronos}{$date_part}{$prefix_vars{'t_hour'}}{duration}++;
		# Store current lock information that will be used later
		# when we will parse the query responsible for the locks
		$cur_lock_info{$t_pid}{wait} = $3;
		if ($fmt eq 'csv') {
			$cur_lock_info{$t_pid}{query}     = $prefix_vars{'t_statement'};
			$cur_lock_info{$t_pid}{timestamp} = $prefix_vars{'t_timestamp'};
			$cur_lock_info{$t_pid}{dbname}    = $prefix_vars{'t_dbname'};
			$cur_lock_info{$t_pid}{dbuser}    = $prefix_vars{'t_dbuser'};
			$cur_lock_info{$t_pid}{dbclient}  = $prefix_vars{'t_client'} || $prefix_vars{'t_dbclient'};
			$cur_lock_info{$t_pid}{dbappname} = $prefix_vars{'t_appname'};
			$cur_lock_info{$t_pid}{queryid}   = $prefix_vars{'t_queryid'};
			$cur_lock_info{$t_pid}{cur_db}    = $curdb;
		}
		return;
	}

	# Stores temporary files activity
	if ($is_log_level && ($prefix_vars{'t_query'} =~ /temporary file: path (.*), size (\d+)/)) {
		return if ($disable_temporary);
		my $filepath = $1;
		my $size = $2;
		$tempfile_info{$curdb}{count}++;
		$tempfile_info{$curdb}{size} += $size;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{'tempfile'}{count}++;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{'tempfile'}{size} += $size;

		# Store current temporary file information that will be used later
		# when we will parse the query responsible for the tempfile
		$cur_temp_info{$t_pid}{size} += $size;
		$cur_temp_info{$t_pid}{query} = ''; # initialyze the query
		$tempfile_info{$curdb}{maxsize} = $cur_temp_info{$t_pid}{size} if ($tempfile_info{$curdb}{maxsize} < $cur_temp_info{$t_pid}{size});
		$overall_stat{$curdb}{'peak'}{$cur_last_log_timestamp}{tempfile_size} += $size;
		$overall_stat{$curdb}{'peak'}{$cur_last_log_timestamp}{tempfile_count}++;
		if ($fmt eq 'csv') {
			$cur_temp_info{$t_pid}{query} = $prefix_vars{'t_statement'};
		} elsif (exists $last_execute_stmt{$t_pid}) {
			$cur_temp_info{$t_pid}{query} = $last_execute_stmt{$t_pid}{query};
		}
		# Stores information related to first created temporary file
		if (!exists $cur_temp_info{$t_pid}{timestamp}) {
			$cur_temp_info{$t_pid}{timestamp} = $prefix_vars{'t_timestamp'} || '';
			$cur_temp_info{$t_pid}{dbname}    = $prefix_vars{'t_dbname'} || '';
			$cur_temp_info{$t_pid}{dbuser}    = $prefix_vars{'t_dbuser'} || '';
			$cur_temp_info{$t_pid}{dbclient}  = $prefix_vars{'t_client'} || $prefix_vars{'t_dbclient'};
			$cur_temp_info{$t_pid}{dbappname} = $prefix_vars{'t_appname'} || '';
			$cur_temp_info{$t_pid}{queryid}   = $prefix_vars{'t_queryid'} || '';
			$cur_temp_info{$t_pid}{cur_db}    = $curdb;
		}
		return;
	}

	# Stores pre-connection activity
	if ($is_log_level && ($prefix_vars{'t_query'} =~ /connection received: host=([^\s]+)(?: port=(\d+))?/))
	{
		$current_sessions{$t_pid}{host} = $1;
		return if ($disable_connection);
		$conn_received{$t_pid} = $1;
		$conn_received{$t_pid} = _gethostbyaddr($conn_received{$t_pid}) if ($dns_resolv);
		return;
	}

	# Stores connection activity
	if (   $is_log_level
		&& ($prefix_vars{'t_query'} =~ /connection authorized: user=([^\s]+)(?: database=([^\s]+))?/))
	{
		$current_sessions{$t_pid}{user} = $1;
		$current_sessions{$t_pid}{database} = $2;
		if ($prefix_vars{'t_query'} =~ /connection authorized: user=([^\s]+) application_name=([^\s]+)/
			|| $prefix_vars{'t_query'} =~ /(.*)application_name=(.*)/)
		{
			$prefix_vars{'t_appname'} = $2;
			$prefix_vars{'t_appname'} =~ s/[<>]/'/g;
			$current_sessions{$t_pid}{appname} = $2;
		}

		return if ($disable_connection || $prefix_vars{'t_query'} =~ /connection authorized: user=([^\s]+) application_name=([^\s]+)/);

		my $usr = $current_sessions{$t_pid}{user} || '';
		my $db  = $current_sessions{$t_pid}{database} || 'unknown';
		my $host  = '';
		if ($prefix_vars{'t_query'} =~ / database=([^\s]+)/) {
			$db = $1;
		} elsif ($prefix_vars{'t_dbname'}) {
			$db = $prefix_vars{'t_dbname'};
		}
		if ($prefix_vars{'t_query'} =~ / host=([^\s]+)/) {
			$host = $1;
			$host = _gethostbyaddr($host) if ($dns_resolv);
		} elsif ($prefix_vars{'t_client'} || $prefix_vars{'t_dbclient'}) {
			$host = $prefix_vars{'t_client'} || $prefix_vars{'t_dbclient'};
			$host = _gethostbyaddr($host) if ($dns_resolv);
		}
		$overall_stat{$curdb}{'peak'}{$cur_last_log_timestamp}{connection}++;

		$connection_info{$curdb}{count}++;
		$connection_info{$curdb}{user}{$usr}++;
		$connection_info{$curdb}{database}{$db}++;
		$connection_info{$curdb}{database_user}{$db}{$usr}++;
		$connection_info{$curdb}{database_host}{$db}{$host}++;
		$connection_info{$curdb}{chronos}{$date_part}{$prefix_vars{'t_hour'}}{count}++;

		if ($graph) {
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{"$prefix_vars{'t_min'}"}{connection}{count}++;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{"$prefix_vars{'t_min'}"}{connection}{second}{$prefix_vars{'t_sec'}}++;
		}
		if (exists $conn_received{$t_pid}) {
			$connection_info{$curdb}{host}{$conn_received{$t_pid}}++;
			delete $conn_received{$t_pid};
		} elsif ($host) {
			$connection_info{$curdb}{host}{$host}++;
		}

		return;
	}

	# Store session duration
	if (    $is_log_level
		&& ($prefix_vars{'t_query'} =~
			/disconnection: session time: ([^\s]+) user=([^\s]+) database=([^\s]+) host=([^\s]+)/))
	{
		return if ($disable_session);

		my $time = $1;
		my $usr  = $2;
		my $db   = $3;
		my $host = $4;
		$host = _gethostbyaddr($host) if ($dns_resolv);

		delete $current_sessions{$t_pid};
		delete $last_execute_stmt{$t_pid};

		# Store time in milliseconds
		$time =~ /(\d+):(\d+):(\d+\.\d+)/;
		$time = ($3 * 1000) + ($2 * 60 * 1000) + ($1 * 60 * 60 * 1000);
		$session_info{$curdb}{count}++;
		$session_info{$curdb}{duration} += $time;
		$session_info{$curdb}{chronos}{$date_part}{$prefix_vars{'t_hour'}}{count}++;
		$session_info{$curdb}{chronos}{$date_part}{$prefix_vars{'t_hour'}}{duration} += $time;
		$session_info{$curdb}{database}{$db}{count}++;
		$session_info{$curdb}{database}{$db}{duration} += $time;
		$session_info{$curdb}{user}{$usr}{count}++;
		$session_info{$curdb}{user}{$usr}{duration} += $time;
		$session_info{$curdb}{host}{$host}{count}++;
		$session_info{$curdb}{host}{$host}{duration} += $time;
		my $app = 'unknown';
		$app = $prefix_vars{'t_appname'} if (exists $prefix_vars{'t_appname'});
		$session_info{$curdb}{app}{$app}{count}++;
		$session_info{$curdb}{app}{$app}{duration} += $time;
		my $k = &get_hist_inbound($time, @histogram_session_time);
		$overall_stat{$curdb}{histogram}{session_time}{$k}++;
		$overall_stat{$curdb}{histogram}{session_total}++;
		return;
	}

	# Store autovacuum information
	if (
		$is_log_level
		&& ($prefix_vars{'t_query'} =~
/automatic (aggressive )?vacuum (to prevent wraparound )?of table "([^\s]+)": index scans: (\d+)/
		   )
	   )
	{
		return if ($disable_autovacuum);

		$cur_info{$t_pid}{vacuum} = $3;

		my $idxscan = $4;
		$cur_info{$t_pid}{vacuum} =~ /^([^\.]+)\./;
		$curdb = $3;

		if (!$report_per_database) {
			$curdb = $DBALL;
		}
		$autovacuum_info{$curdb}{count}++;
		$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{vacuums} += 1;
		$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{idxscans} += $idxscan;
		$autovacuum_info{$curdb}{chronos}{$date_part}{$prefix_vars{'t_hour'}}{count}++;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{autovacuum}{count}++;

		if ($fmt eq 'csv' || $fmt eq 'jsonlog')
		{
			if ($prefix_vars{'t_query'} =~ /(pages): (\d+) removed, (\d+) remain/)
			{
					$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{$1}{removed} += $2;
					$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{$1}{remain} += $3;
			}
			if ($prefix_vars{'t_query'} =~ /(tuples): (\d+) removed, (\d+) remain/)
			{
					$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{$1}{removed} += $2;
					$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{$1}{remain} += $3;
			}
			if ($prefix_vars{'t_query'} =~ /(\d+) are dead but not yet removable/) {
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{tuples}{notremovable} += $1;
			}
			if ($prefix_vars{'t_query'} =~ /system usage: CPU: user: (.*) (?:sec|s,) system: (.*) (?:sec|s,) elapsed: ([^\s]+)/)
			{
				$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{autovacuum}{second}{$prefix_vars{'t_sec'}{second}} += $3;
				if ($3 > $autovacuum_info{$curdb}{peak}{system_usage}{elapsed})
				{
					$autovacuum_info{$curdb}{peak}{system_usage}{elapsed} = $3;
					$autovacuum_info{$curdb}{peak}{system_usage}{table} = $cur_info{$t_pid}{vacuum};
					$autovacuum_info{$curdb}{peak}{system_usage}{date} =
						"$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} " .
						"$prefix_vars{'t_hour'}:$prefix_vars{'t_min'}:$prefix_vars{'t_sec'}";
				}
			}
			if ($prefix_vars{'t_query'} =~ /, (\d+) skipped due to pins, (\d+) skipped frozen/)
			{
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{skip_pins} += $1;
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{skip_frozen} += $2;
			}
			if ($prefix_vars{'t_query'} =~ /buffer usage: (\d+) hits, (\d+) misses, (\d+) dirtied/)
			{
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{hits} += $1;
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{misses} += $2;
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{dirtied} += $3;
			}
			if ($prefix_vars{'t_query'} =~ /WAL usage: (\d+) records, (\d+) full page images, (\d+) bytes/)
			{
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{wal_record} += $1;
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{wal_full_page} += $2;
				$autovacuum_info{$curdb}{tables}{$cur_info{$t_pid}{vacuum}}{wal_bytes} += $3;
			}
		}
		$cur_info{$t_pid}{cur_db} = $curdb;
		$cur_info{$t_pid}{year}   = $prefix_vars{'t_year'};
		$cur_info{$t_pid}{month}  = $prefix_vars{'t_month'};
		$cur_info{$t_pid}{day}    = $prefix_vars{'t_day'};
		$cur_info{$t_pid}{hour}   = $prefix_vars{'t_hour'};
		$cur_info{$t_pid}{min}    = $prefix_vars{'t_min'};
		$cur_info{$t_pid}{sec}    = $prefix_vars{'t_sec'};
		return;
	}

	# Store autoanalyze information
	if (
		$is_log_level
		&& ($prefix_vars{'t_query'} =~ /automatic analyze of table "([^\s]+)"( system usage: CPU: user: (.*) (?:sec|s,) system: (.*) (?:sec|s,) elapsed: (.*) (?:sec|s))?/))
	{
		return if ($disable_autovacuum);
		my $table = $1;
		my $user_time = $2;
		my $system_time = $3;
		my $elapsed_time = $4;
		$table =~ /^([^.]+)\./;
		$curdb = $1;
		if (!$report_per_database) {
			$curdb = $DBALL;
		}
		$autoanalyze_info{$curdb}{count}++;
		$autoanalyze_info{$curdb}{tables}{$table}{analyzes} += 1;
		$autoanalyze_info{$curdb}{chronos}{$date_part}{$prefix_vars{'t_hour'}}{count}++;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{autoanalyze}{count}++;
		if ($elapsed_time > $autoanalyze_info{$curdb}{peak}{system_usage}{elapsed}) {
			$autoanalyze_info{$curdb}{peak}{system_usage}{elapsed} = $elapsed_time;
			$autoanalyze_info{$curdb}{peak}{system_usage}{table} = $table;
			$autoanalyze_info{$curdb}{peak}{system_usage}{date} = $cur_last_log_timestamp;
		}
	}

	# Store checkpoint or restartpoint information
	if (
		$is_log_level
		&& ($prefix_vars{'t_query'} =~
/point complete: wrote (\d+) buffers \(([^\)]+)\); (\d+) (?:transaction log|WAL) file\(s\) added, (\d+) removed, (\d+) recycled; write=([0-9\.]+) s, sync=([0-9\.]+) s, total=([0-9\.]+) s/
		   )
	   )
	{
		# Example: LOG:  checkpoint complete: wrote 8279 buffers (50.5%); 0 transaction log file(s) added, 0 removed, 0 recycled; write=2.277 s, sync=0.194 s, total=2.532 s; sync files=13, longest=0.175 s, average=0.014 s; distance=402024 kB, estimate=402024 kB
		# checkpoint complete: wrote 38 buffers (0.1%); 0 WAL file(s) added, 0 removed, 0 recycled; write=4.160 s, sync=0.096 s, total=4.338 s; sync files=29, longest=0.018 s, average=0.003 s; distance=79 kB, estimate=79 kB
		return if ($disable_checkpoint);

		$checkpoint_info{wbuffer} += $1;

		#$checkpoint_info{percent_wbuffer} += $2;
		$checkpoint_info{file_added}    += $3;
		$checkpoint_info{file_removed}  += $4;
		$checkpoint_info{file_recycled} += $5;
		$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{walfile_usage} += ($3 + $5);
		$checkpoint_info{write}	 += $6;
		$checkpoint_info{sync}	  += $7;
		$checkpoint_info{total}	 += $8;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{wbuffer} += $1;
		#$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{percent_wbuffer} += $2;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{file_added}    += $3;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{file_removed}  += $4;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{file_recycled} += $5;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{write}	 += $6;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{sync}	  += $7;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{total}	 += $8;

		$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{checkpoint_wbuffer} += $1;
		if ($6 > $overall_checkpoint{checkpoint_write}) {
			$overall_checkpoint{checkpoint_write} = $6;
		}
		if ($7 > $overall_checkpoint{checkpoint_sync}) {
			$overall_checkpoint{checkpoint_sync} = $7;
		}

		if ($prefix_vars{'t_query'} =~ /sync files=(\d+), longest=([0-9\.]+) s, average=([0-9\.]+) s/)
		{
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{sync_files} += $1;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{sync_longest} = $2
				if ($2 > $per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{sync_longest});
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{sync_avg} += $3;
		}

		# 9.6: LOG: checkpoint complete: wrote 0 buffers (0.0%); 0 transaction log file(s) added, 1 removed, 0 recycled; write=0.016 s, sync=0.000 s, total=0.054 s; sync files=0, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=14744 kB
		if ($prefix_vars{'t_query'} =~ /; distance=(\d+) kB, estimate=(\d+) kB/)
		{
			$checkpoint_info{distance}    += $1;
			$checkpoint_info{estimate}    += $2;
			$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{distance} += $1;
			$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{estimate} += $1;
			if ($1 > $overall_checkpoint{distance}) {
				$overall_checkpoint{distance} = $1;
			}
			if ($2 > $overall_checkpoint{estimate}) {
				$overall_checkpoint{estimate} = $2;
			}
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{distance} += $1;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{distance_count}++;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{estimate} += $2;
			$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{distance} += $1;
			$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{estimate} += $2;
		}
		return;
	}

	# Store starting reason
	if ($is_log_level
		&& $prefix_vars{'t_query'} =~ /point starting: (.*)/)
	{
		$checkpoint_info{starting}{$1}++;
		return;
	}

	# Store checkpoint warning information
	if (   $is_log_level
		&& ($prefix_vars{'t_query'} =~ /checkpoints are occurring too frequently \((\d+) seconds apart\)/))
	{
		return if ($disable_checkpoint);
		$checkpoint_info{warning}++;
		$checkpoint_info{warning_seconds} += $1;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{warning}++;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{warning_seconds} += $1;
		$overall_checkpoint{checkpoint_warning}++;
		return;
	}

	# Store old restartpoint information
	if (
		$is_log_level
		&& ($prefix_vars{'t_query'} =~
/restartpoint complete: wrote (\d+) buffers \(([^\)]+)\); write=([0-9\.]+) s, sync=([0-9\.]+) s, total=([0-9\.]+) s/
		   )
	   )
	{
		# Example: LOG:  restartpoint complete: wrote 1568 buffers (0.3%); write=146.237 s, sync=0.251 s, total=146.489 s
		return if ($disable_checkpoint);

		$checkpoint_info{wbuffer} += $1;

		#$checkpoint_info{percent_wbuffer} += $2;
		$checkpoint_info{write}	 += $6;
		$checkpoint_info{sync}	  += $7;
		$checkpoint_info{total}	 += $8;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{wbuffer} += $1;
		#$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{percent_wbuffer} += $2;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{write}	 += $6;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{sync}	  += $7;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{total}	 += $8;

		$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{checkpoint_wbuffer} += $1;
		if ($6 > $overall_checkpoint{checkpoint_write}) {
			$overall_checkpoint{checkpoint_write} = $6;
		}
		if ($7 > $overall_checkpoint{checkpoint_sync}) {
			$overall_checkpoint{checkpoint_sync} = $7;
		}
		if ($prefix_vars{'t_query'} =~ /distance=(\d+) kB, estimate=(\d+) kB/) {
			$checkpoint_info{distance}    += $1;
			$checkpoint_info{estimate}    += $2;
			$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{distance} += $1;
			$overall_checkpoint{'peak'}{$cur_last_log_timestamp}{estimate} += $2;
			if ($1 > $overall_checkpoint{distance}) {
				$overall_checkpoint{distance} = $1;
			}
			if ($2 > $overall_checkpoint{estimate}) {
				$overall_checkpoint{estimate} = $2;
			}
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{distance} += $1;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{distance_count}++;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{checkpoint}{estimate} += $2;
		}
		return;
	}

	# Look at bind/execute parameters if any
	if ($cur_info{$t_pid}{query})
	{
		# Remove obsolete connection storage
		delete $conn_received{$cur_info{$t_pid}{pid}};

		# The query is complete but we are missing some debug/info/bind parameter logs
		if ($cur_info{$t_pid}{loglevel} eq 'LOG' && $prefix_vars{'t_loglevel'} eq 'DETAIL')
		{
			# Apply bind parameters if any
			if ($prefix_vars{'t_query'} =~ /parameters: (.*)/)
			{
				$cur_bind_info{$t_pid}{'bind'}{'parameters'} = $1 if (exists $cur_bind_info{$t_pid});
				$cur_info{$t_pid}{parameters} = "$1";
				# go look at other params
				return;
			# replace the execute statements with the prepared query and set the parameters
			}
			elsif ($prefix_vars{'t_query'} =~ s/prepare: PREPARE\s+([^\s]+)(\s*\([^\)]*\))?\s+AS\s*(.*)/[ EXECUTE $1 (PARAM) ]/is)
			{
				my $q_name = $1;
				my $real_query = $3;
				if ($cur_info{$t_pid}{query} =~ /\b$q_name\b/)
				{
					$cur_info{$t_pid}{query} =~ s/EXECUTE\s+$q_name\s*\((.*)\)[;]*$//is;
					$cur_info{$t_pid}{parameters} = $1;
					$prefix_vars{'t_query'} =~ s/\(PARAM\)/($cur_info{$t_pid}{parameters})/;
					$cur_info{$t_pid}{query} = $prefix_vars{'t_query'} . ' - ' . $real_query;
					$cur_info{$t_pid}{'bind'} = 1;
					my @t_res = split(/[\s]*,[\s]*/, $cur_info{$t_pid}{parameters});
					$cur_info{$t_pid}{query} =~ s/\$(\d+)/$t_res[$1-1]/gs;
				}
				# go look at other params
				return;
			}
		}
	}

	# Apply bind parameters if any
	if ($prefix_vars{'t_detail'} =~ /parameters: (.*)/)
	{
		$cur_bind_info{$t_pid}{'bind'}{'parameters'} = $1 if (exists $cur_bind_info{$t_pid});
		$cur_info{$t_pid}{parameters} = "$1";
		# go look at other params
	}

	####
	# Store current query information
	####

	# Log lines with duration only, generated by log_duration = on in postgresql.conf
	if ($prefix_vars{'t_query'} =~ s/duration: ([0-9\.]+) ms$//s)
	{
		$prefix_vars{'t_duration'} = $1;
		$prefix_vars{'t_query'} = '';
		my $k = &get_hist_inbound($1, @histogram_query_time);
		$overall_stat{$curdb}{histogram}{query_time}{$k}++;
		$overall_stat{$curdb}{histogram}{query_total}++;
		&set_current_infos($t_pid);
		return;
	}

	my $t_action = '';
	# Store query duration generated by log_min_duration >= 0 in postgresql.conf
	if ($prefix_vars{'t_query'} =~ s/duration: ([0-9\.]+) ms\s+(?:rows: \d+\s+size: \d+ bytes\s+)?(query|statement):\s*//s)
	{
		$prefix_vars{'t_duration'} = $1;
		$t_action   = $2;
		my $k = &get_hist_inbound($1, @histogram_query_time);
		$overall_stat{$curdb}{histogram}{query_time}{$k}++;
		$overall_stat{$curdb}{histogram}{query_total}++;
		if (($t_action eq 'statement') && $prefix_vars{'t_query'} =~ /^(PREPARE|EXECUTE)/i) {
			$overall_stat{lc($1)}++;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{lc($1)}++;

			if ($prefix_vars{'t_query'} =~ /^PREPARE$/i) {
				$t_action = 'prepare';
				$overall_stat{$curdb}{'queries_duration'}{$t_action} += $prefix_vars{'t_duration'} if ($prefix_vars{'t_duration'});
				$cur_bind_info{$t_pid}{$t_action}{'query'} = $prefix_vars{'t_query'};
				$cur_bind_info{$t_pid}{$t_action}{'duration'} = $prefix_vars{'t_duration'};
				$cur_bind_info{$t_pid}{$t_action}{'timestamp'} = $cur_last_log_timestamp,
				return;
			}
		}
	}
	# Log line with duration and statement from prepared queries
	elsif ($prefix_vars{'t_query'} =~ s/duration: ([0-9\.]+) ms\s+(?:rows: \d+\s+size: \d+ bytes\s+)?(prepare|parse|bind|execute from fetch|execute)\s+[^:]+:(?:[^\s]+:)?\s//s)
	{
		$prefix_vars{'t_duration'} = $1;
		$t_action = $2;
		$t_action =~ s/ from fetch//;
		$t_action = 'prepare' if ($t_action eq 'parse');

		# Should we have to exclude some queries
		return 1 if ($#exclude_query >= 0 && &is_excluded_query($prefix_vars{'t_query'}));

		# Should we have to include only some queries
		return 1 if ($#include_query >= 0 && !&is_included_query($prefix_vars{'t_query'}));

		$overall_stat{$t_action}++;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{$t_action}++;
		if ($t_action !~ /query|statement|execute/)
		{
			if ($prefix_vars{'t_duration'}) {
				$overall_stat{$curdb}{'queries_duration'}{$t_action} += $prefix_vars{'t_duration'};
				$cur_bind_info{$t_pid}{$t_action}{'query'} = $prefix_vars{'t_query'};
				$cur_bind_info{$t_pid}{$t_action}{'duration'} = $prefix_vars{'t_duration'};
				$cur_bind_info{$t_pid}{$t_action}{'timestamp'} = $cur_last_log_timestamp,
			}
			return;
		}
		my $k = &get_hist_inbound($prefix_vars{'t_duration'}, @histogram_query_time);
		$overall_stat{$curdb}{histogram}{query_time}{$k}++;
		$overall_stat{$curdb}{histogram}{query_total}++;
		$prefix_vars{'t_bind'} = 1;
		# Stores execute query in case of temporary file
		# only if log_disconnection is enabled otherwise
		# the risk is to fill memory with this storage.
		if (scalar keys %session_info)
		{
			$last_execute_stmt{$t_pid}{query} = $prefix_vars{'t_query'};
			$last_execute_stmt{$t_pid}{timestamp} = $cur_last_log_timestamp;
		}
	}
	# Activate storage of the explain plan generated by auto_explain
	elsif (!$noexplain && $prefix_vars{'t_query'} =~ s/duration: ([0-9\.]+) ms\s+(?:rows: \d+\s+size: \d+ bytes\s+)?plan://s)
	{
		$cur_plan_info{$t_pid}{duration} = $1;
		$cur_plan_info{$t_pid}{plan} = '';
		$prefix_vars{'t_duration'} = $1; # needed to be saved later
	}
	# Log line without duration at all
	elsif ($prefix_vars{'t_query'} =~ s/(query|statement): //is)
	{
		$t_action = $1;
		if (($t_action eq 'statement') && $prefix_vars{'t_query'} =~ /^(PREPARE|EXECUTE)\b/i) {
			$overall_stat{lc($1)}++;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{lc($1)}++;
		}
	}
	# Log line without duration at all from prepared queries
	elsif ($prefix_vars{'t_query'} =~ s/(prepare|parse|bind|execute from fetch|execute)\s+[^:]+:(?:[^\s]+:)?\s//s)
	{
		$t_action = $1;
		$t_action =~ s/ from fetch//;
		$t_action = 'prepare' if ($t_action eq 'parse');

		# Should we have to exclude some queries
		return 1 if ($#exclude_query >= 0 && &is_excluded_query($prefix_vars{'t_query'}));

		# Should we have to include only some queries
		return 1 if ($#include_query >= 0 && !&is_included_query($prefix_vars{'t_query'}));

		$overall_stat{$t_action}++;
		$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{$t_action}++;
		# Skipping parse and bind logs but after storing their duration time
		return if ($t_action !~ /query|statement|execute/);
		$prefix_vars{'t_bind'} = 1;
		# Stores execute query in case of temporary file
		$last_execute_stmt{$t_pid} = $prefix_vars{'t_query'};
	}
	# Log line without duration at all
	elsif ($fmt eq 'redshift' and $prefix_vars{'t_query'})
	{
		$t_action = 'statement';
		if (($t_action eq 'statement') && $prefix_vars{'t_query'} =~ /^(PREPARE|EXECUTE)\b/i) {
			$overall_stat{lc($1)}++;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{lc($1)}++;
		}
		$overall_stat{$curdb}{histogram}{query_total}++;
		if (($t_action eq 'statement') && $prefix_vars{'t_query'} =~ /^(PREPARE|EXECUTE)/i) {
			$overall_stat{lc($1)}++;
			$per_minute_info{$curdb}{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{lc($1)}++;

			if ($prefix_vars{'t_query'} =~ /^PREPARE$/i) {
				$t_action = 'prepare';
				$cur_bind_info{$t_pid}{$t_action}{'query'} = $prefix_vars{'t_query'};
				$cur_bind_info{$t_pid}{$t_action}{'timestamp'} = $cur_last_log_timestamp,
				return;
			}
		}
	}
	# Log line that could not be parsed
	elsif ($is_log_level)
	{
		if ($prefix_vars{'t_query'} !~
/incomplete startup packet|connection|unexpected EOF|parameter .*configuration file|autovacuum launcher|automatic (analyze|vacuum)|detected deadlock while waiting for/
		   )
		{
			#&logmsg('DEBUG', "Unrecognized line: $prefix_vars{'t_loglevel'}: $prefix_vars{'t_query'} at line $nlines");
		}
		return;
	}

	if (($fmt =~ /csv|jsonlog/) && ($prefix_vars{'t_loglevel'} ne 'LOG'))
	{
		$cur_info{$t_pid}{detail} = $prefix_vars{'t_detail'};
		$cur_info{$t_pid}{hint} = $prefix_vars{'t_hint'};
		$cur_info{$t_pid}{context} = $prefix_vars{'t_context'};
		$cur_info{$t_pid}{statement} = $prefix_vars{'t_statement'}
	}

	&set_current_infos($t_pid);

	return 1;
}

sub parse_pgbouncer
{
	my $fmt = shift;

	my $t_pid = $prefix_vars{'t_pid'};
	my $t_session_id = $prefix_vars{'t_session_id'};

	my $date_part = "$prefix_vars{'t_year'}$prefix_vars{'t_month'}$prefix_vars{'t_day'}";
	my $cur_last_log_timestamp = "$prefix_vars{'t_year'}-$prefix_vars{'t_month'}-$prefix_vars{'t_day'} " .
				     "$prefix_vars{t_hour}:$prefix_vars{t_min}:$prefix_vars{t_sec}";

	# Do not parse lines that are not an error message when error only report is requested
	if ($error_only && ($prefix_vars{'t_loglevel'} !~ $full_error_regex)) {
		return;
	}

	# Do not parse lines that are an error-like message when error reports are not wanted
	if ($disable_error && ($prefix_vars{'t_loglevel'} =~ $full_error_regex)) {
		return;
	}

	if ($prefix_vars{'t_loglevel'} eq 'STATS') {

		$pgb_overall_stat{'queries_number'}++;

		$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{t_req} = $prefix_vars{'t_req/s'};
		$pgb_overall_stat{'peak'}{$cur_last_log_timestamp}{t_req} = $prefix_vars{'t_req/s'};
		$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{t_inbytes} = $prefix_vars{'t_inbytes/s'};
		$pgb_overall_stat{'peak'}{$cur_last_log_timestamp}{t_inbytes} = $prefix_vars{'t_inbytes/s'};

		$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{t_outbytes} = $prefix_vars{'t_outbytes/s'};
		$pgb_overall_stat{'peak'}{$cur_last_log_timestamp}{t_outbytes} = $prefix_vars{'t_outbytes/s'};

		# We need millisecond instead of microsecond from pgbouncer
		my $duration = int($prefix_vars{'t_avgduration'}/1000);
		$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{t_avgduration} = $duration;
		$pgb_overall_stat{'peak'}{$cur_last_log_timestamp}{t_avgduration} = $duration;

		my $waiting = int($prefix_vars{'t_avgwaiting'}/1000);
		$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{$prefix_vars{'t_min'}}{t_avgwaiting} = $waiting;
		$pgb_overall_stat{'peak'}{$cur_last_log_timestamp}{t_avgwaiting} = $waiting;

		return;

	} elsif ($prefix_vars{'t_loglevel'} =~ $main_error_regex) {

		if (grep(/^$prefix_vars{'t_loglevel'}$/,  'WARNING', 'ERROR', 'FATAL')) {

			if ($prefix_vars{'t_query'} =~ /dropping database '([^']+)' as it does not exist anymore/) {
				$prefix_vars{t_dbname} = $1;
			} elsif ($prefix_vars{'t_query'} =~ /^([^:]+): (.*?)\/(.*?)\@([^:]+):\d+ (.*)/) {
				$prefix_vars{t_query} = $5;
				$prefix_vars{t_dbname} = $2;
				$prefix_vars{t_dbuser} = $3;
				$prefix_vars{t_dbclient} = $4;
				$prefix_vars{t_session_id} = $1;
			} else {
				$prefix_vars{'t_query'} =~ s/^S: //;
			}

			# Add log level at beginning of the query and normalize it
			$prefix_vars{'t_query'} = $prefix_vars{'t_loglevel'} . ":  " . $prefix_vars{'t_query'};
			my $normalized_error = &pgb_normalize_error($prefix_vars{'t_query'});

			# Stores total and normalized error count
			$pgb_overall_stat{'errors_number'}++;
			$pgb_error_info{$normalized_error}{count}++;

			# Stores normalized error count per time
			my $cur_day_str = "$prefix_vars{t_year}$prefix_vars{t_month}$prefix_vars{t_day}";
			my $cur_hour_str = "$prefix_vars{t_hour}";
			$pgb_error_info{$normalized_error}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{count}++;
			$pgb_error_info{$normalized_error}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{min}{$prefix_vars{t_min}}++;

			# Stores normalized query samples
			if ($sample > 0) {
				&pgb_set_top_error_sample(  $normalized_error,
										$cur_last_log_timestamp,
										$prefix_vars{t_query},
										$prefix_vars{t_dbname},
										$prefix_vars{t_dbuser},
										$prefix_vars{t_client} || $prefix_vars{t_dbclient}
				);
			}

			# Stores taken reserved pool
			if ($prefix_vars{'t_query'} =~ /Taking connection from reserve_pool/) {
				my $pool = "$prefix_vars{t_dbuser}\@$prefix_vars{t_dbname}";
				$pgb_pool_info{$pool}{count}++;
				$pgb_pool_info{$pool}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{count}++;
				$pgb_pool_info{$pool}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{min}{$prefix_vars{t_min}}++;
			}

		} else {
			print STDERR "UNPARSED LOG LEVEL: $prefix_vars{'t_loglevel'} => $prefix_vars{'t_query'}\n";
		}
	} elsif ($prefix_vars{'t_loglevel'} ne 'LOG') {
		print STDERR "UNRECOGNIZED LOG LEVEL: $prefix_vars{'t_loglevel'} => $prefix_vars{'t_query'}\n";
	}

	# Stores connection activity
	if (   ($prefix_vars{'t_loglevel'} eq 'LOG')
		&& ($prefix_vars{'t_query'} =~ /login attempt: db=([^\s]+) user=([^\s]+)/))
	{
		return if ($disable_connection);

		my $usr = $prefix_vars{'t_dbuser'} || $2;
		my $db  = $prefix_vars{'t_dbname'} || $1;
		my $host= $prefix_vars{'t_client'} || $prefix_vars{t_dbclient} || '';
		$host = _gethostbyaddr($host) if ($dns_resolv);
		$pgb_overall_stat{'peak'}{$cur_last_log_timestamp}{connection}++;

		$pgb_connection_info{count}++;
		$pgb_connection_info{user}{$usr}++;
		$pgb_connection_info{host}{$host}++;
		$pgb_connection_info{database}{$db}++;
		$pgb_connection_info{database_user}{$db}{$usr}++;
		$pgb_connection_info{database_host}{$db}{$host}++;
		$pgb_connection_info{chronos}{$date_part}{$prefix_vars{'t_hour'}}{count}++;

		if ($graph)
		{
			$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{"$prefix_vars{'t_min'}"}{connection}{count}++;
			$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{"$prefix_vars{'t_min'}"}{connection}{second}{$prefix_vars{'t_sec'}}++;
		}

		# set current session workload
		if ( !$disable_session && $t_session_id)
		{
			$pgb_current_sessions{$t_session_id} = $prefix_vars{'t_timestamp'};
			my $sess_count = scalar keys %pgb_current_sessions;
			$pgb_overall_stat{'peak'}{$cur_last_log_timestamp}{session} = $sess_count;
			$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{"$prefix_vars{'t_min'}"}{session}{count} = $sess_count;
			$pgb_per_minute_info{$date_part}{$prefix_vars{'t_hour'}}{"$prefix_vars{'t_min'}"}{session}{second}{$prefix_vars{'t_sec'}} = $sess_count;
		}

		return;
	}

	# Store session duration
	if (($prefix_vars{'t_loglevel'} eq 'LOG')
		&& ($prefix_vars{'t_query'} =~ /\(age=(\d+)[a-z]*\)$/))
	{
		return if ($disable_session);

		# Use millisecond for session duration
		my $time = $1*1000;

		my $usr = $prefix_vars{'t_dbuser'} || '(nousr)';
		my $db  = $prefix_vars{'t_dbname'} || '(nodb)';
		my $host= $prefix_vars{'t_client'} || $prefix_vars{t_dbclient} || '';
		$host = _gethostbyaddr($host) if ($dns_resolv && $host);

		# Store time in milliseconds since the connection attempt
		if ($pgb_current_sessions{$t_session_id} =~ /(\d+):(\d+):(\d+\.\d+)$/)
		{
			my $time1 = ($3 * 1000) + ($2 * 60 * 1000) + ($1 * 60 * 60 * 1000);
			$prefix_vars{'t_timestamp'} =~ /(\d+):(\d+):(\d+\.\d+)$/;
			my $time2 = ($3 * 1000) + ($2 * 60 * 1000) + ($1 * 60 * 60 * 1000);
			$time = $time2 - $time1;
		}
		$pgb_session_info{count}++;
		$pgb_session_info{duration} += $time;
		$pgb_session_info{chronos}{$date_part}{$prefix_vars{'t_hour'}}{count}++;
		$pgb_session_info{chronos}{$date_part}{$prefix_vars{'t_hour'}}{duration} += $time;
		$pgb_session_info{database}{$db}{count}++;
		$pgb_session_info{database}{$db}{duration} += $time;
		$pgb_session_info{user}{$usr}{count}++;
		$pgb_session_info{user}{$usr}{duration} += $time;
		$pgb_session_info{host}{$host}{count}++;
		$pgb_session_info{host}{$host}{duration} += $time;
		my $k = &get_hist_inbound($time, @histogram_session_time);
		$pgb_overall_stat{histogram}{session_time}{$k}++;
		$pgb_overall_stat{histogram}{session_total}++;

		delete $pgb_current_sessions{$t_session_id};

		return;
	}

	return 1;
}

# Remain current parsed information into memory for subsequent use
sub set_current_infos
{

	my $t_pid = shift;

	$cur_info{$t_pid}{year}      = $prefix_vars{'t_year'} if (!$cur_info{$t_pid}{year});
	$cur_info{$t_pid}{month}     = $prefix_vars{'t_month'} if (!$cur_info{$t_pid}{month});
	$cur_info{$t_pid}{day}       = $prefix_vars{'t_day'} if (!$cur_info{$t_pid}{day});
	$cur_info{$t_pid}{hour}      = $prefix_vars{'t_hour'} if (!exists $cur_info{$t_pid}{sec} || ($cur_info{$t_pid}{hour} eq ''));
	$cur_info{$t_pid}{min}       = $prefix_vars{'t_min'} if (!exists $cur_info{$t_pid}{sec} || ($cur_info{$t_pid}{min} eq ''));
	$cur_info{$t_pid}{sec}       = $prefix_vars{'t_sec'} if (!exists $cur_info{$t_pid}{sec} || ($cur_info{$t_pid}{sec} eq ''));
	$cur_info{$t_pid}{timestamp} = $prefix_vars{'t_timestamp'} if (!$cur_info{$t_pid}{timestamp});
	$cur_info{$t_pid}{ident}     = $prefix_vars{'t_ident'} if (!$cur_info{$t_pid}{ident});
	$cur_info{$t_pid}{query}     = $prefix_vars{'t_query'} if (!$cur_info{$t_pid}{query});
	$cur_info{$t_pid}{queryid}   = $prefix_vars{'t_queryid'} if (!$cur_info{$t_pid}{queryid});
	$cur_info{$t_pid}{duration}  = $prefix_vars{'t_duration'} if (!$cur_info{$t_pid}{duration});
	$cur_info{$t_pid}{pid}       = $prefix_vars{'t_pid'} if (!$cur_info{$t_pid}{pid});
	$cur_info{$t_pid}{session}   = $prefix_vars{'t_session_line'} if (!$cur_info{$t_pid}{session});
	$cur_info{$t_pid}{loglevel}  = $prefix_vars{'t_loglevel'} if (!$cur_info{$t_pid}{loglevel});
	$cur_info{$t_pid}{origloglevel}= $prefix_vars{'t_origloglevel'} if (exists $prefix_vars{'t_origloglevel'});
	$cur_info{$t_pid}{dbname}    = $prefix_vars{'t_dbname'} if (!$cur_info{$t_pid}{dbname});
	$cur_info{$t_pid}{dbuser}    = $prefix_vars{'t_dbuser'} if (!$cur_info{$t_pid}{dbuser});
	$cur_info{$t_pid}{dbclient}  = $prefix_vars{'t_client'} || $prefix_vars{'t_dbclient'} if (!$cur_info{$t_pid}{dbclient});
	$cur_info{$t_pid}{dbappname} = $prefix_vars{'t_appname'} if (!$cur_info{$t_pid}{dbappname});
	$cur_info{$t_pid}{bind}      = $prefix_vars{'t_bind'} if (!$cur_info{$t_pid}{bind});
	$cur_info{$t_pid}{sqlstate}  = $prefix_vars{'t_sqlstate'} if (!$cur_info{$t_pid}{sqlstate});
	$cur_info{$t_pid}{backendtype}  = $prefix_vars{'t_backend_type'} if (!$cur_info{$t_pid}{backendtype});
	# Store current report name and list of database
	$cur_info{$t_pid}{cur_db} = set_current_db($cur_info{$t_pid}{dbname});
}

sub store_queries
{
	my ($t_pid, $end, $line)  = @_;

	# Incomplete statement will be treated next loop
	return 0 if (!exists $cur_info{$t_pid} || scalar keys %{$cur_info{$t_pid}} == 0);

	# With separate log_duration and log_statement wait duration before storing the entry
	return 0 if (!$end && $log_duration
		&& (!exists $cur_info{$t_pid}{duration} || $cur_info{$t_pid}{duration} eq '')
		&& (!exists $cur_info{$t_pid}{query} || $cur_info{$t_pid}{query} ne ''));

	# Remove comments if required
	if ($remove_comment) {
		$cur_info{$t_pid}{query} =~ s/\/\*(.*?)\*\///gs;
	}

	if ($#include_pid >= 0) {
		return 1 if (!grep(/^$t_pid$/, @include_pid));
	}
	if ($#include_session >= 0) {
		return 1 if (!grep(/^$cur_info{$t_pid}{session}$/, @include_session));
	}

	# In dump all queries mode we just print the query to output file
	if ($dump_all_queries && $cur_info{$t_pid}{loglevel} eq 'LOG')
	{
		# Replace bind parameters values in the query if any
		if (exists $cur_info{$t_pid}{parameters} && ($cur_info{$t_pid}{parameters} =~ /[,\s]*\$(\d+)\s=\s/))
		{
			my @t_res = $cur_info{$t_pid}{parameters} =~ /\$\d+\s=\s(.*?)(?:, |$)/g;
			$cur_info{$t_pid}{query} =~ s/\$(\d+)/$t_res[$1-1]/gs;
		}
		else
		{
			# parameters from EXECUTE statements
			my @t_res = split(/[\s]*,[\s]*/, $cur_info{$t_pid}{parameters});
			$cur_info{$t_pid}{query} =~ s/\$(\d+)/$t_res[$1-1]/gs;
		}
		return if ($cur_info{$t_pid}{query} =~ /^parameters:/);
		print $fh "# Query #", $query_numbering++, "\n" if ($query_numbering);
		$cur_info{$t_pid}{query} .= ';' if ($cur_info{$t_pid}{query} !~ /;\s*$/s);
		print $fh "$cur_info{$t_pid}{query}\n";
		$overall_stat{'queries_number'}++;
		return 1;
	}
	elsif ($dump_raw_csv)
	{
		&dump_raw_csv($t_pid);
		return 1;
	}

	# Cleanup and pre-normalize the current query
	$cur_info{$t_pid}{query} =~ s/^\s+//s;
	$cur_info{$t_pid}{query} =~ s/[\s;]+$//s;

	# Just store normalized query when --normalized-only is used
	if ($dump_normalized_only && $cur_info{$t_pid}{query})
	{
		# Add a semi-colon at end of the query
		$cur_info{$t_pid}{query} .= ';' if ($cur_info{$t_pid}{query} !~ /;\s*$/s);

		# Normalize query
		my $normalized = &normalize_query($cur_info{$t_pid}{query});

		# Store normalized query count
		$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{count}++;

		return 1;
	}

	# Replace bind parameters values in the query if any
	if (exists $cur_info{$t_pid}{parameters} && ($cur_info{$t_pid}{parameters} =~ /[,\s]*\$(\d+)\s=\s/))
	{
		my @t_res = $cur_info{$t_pid}{parameters} =~ /\$\d+\s=\s(.*?)(?:, |$)/g;
		$cur_info{$t_pid}{query} =~ s/\$(\d+)/$t_res[$1-1]/gs;
	}
	else
	{
		# parameters from EXECUTE statements
		my @t_res = split(/[\s]*,[\s]*/, $cur_info{$t_pid}{parameters});
		$cur_info{$t_pid}{query} =~ s/\$(\d+)/$t_res[$1-1]/gs;
	}

	# We only process stored object with query here
	if ($cur_info{$t_pid}{query})
	{
		# Should we just want select queries
		if ($select_only) {
			return 1 if ($cur_info{$t_pid}{query} !~ /^SELECT/is);
		}

		# Should we have to exclude some queries
		return 1 if ($#exclude_query >= 0 && &is_excluded_query($cur_info{$t_pid}{query}));

		# Should we have to include only some queries
		return 1 if ($#include_query >= 0 && !&is_included_query($cur_info{$t_pid}{query}));

		# Truncate the query if requested by the user
		if ($maxlength > 0) {
			&maxlen_truncate($cur_info{$t_pid}{query});
		}
	}

	# We only process stored object with query here
	if ($cur_info{$t_pid}{statement})
	{
		# Truncate the statement if requested by the user
		if ($maxlength > 0) {
			&maxlen_truncate($cur_info{$t_pid}{statement});
		}
	}

	my $cur_day_str = "$cur_info{$t_pid}{year}$cur_info{$t_pid}{month}$cur_info{$t_pid}{day}";
	my $cur_hour_str = "$cur_info{$t_pid}{hour}";

	# Store the collected information into global statistics
	if ($cur_info{$t_pid}{loglevel} =~ $main_error_regex)
	{
		# Add log level at beginning of the query and normalize it
		$cur_info{$t_pid}{query} = $cur_info{$t_pid}{loglevel} . ":  " . $cur_info{$t_pid}{query};
		my $normalized_error = &normalize_error($cur_info{$t_pid}{query});

		# Stores total and normalized error count
		$overall_stat{'errors_number'}++;
		$overall_stat{$cur_info{$t_pid}{cur_db}}{'errors_number'}++;
		$error_info{$cur_info{$t_pid}{cur_db}}{$normalized_error}{count}++;

		# Stores normalized error count per time
		$error_info{$cur_info{$t_pid}{cur_db}}{$normalized_error}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{count}++;
		$error_info{$cur_info{$t_pid}{cur_db}}{$normalized_error}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{min}{$cur_info{$t_pid}{min}}++;

		# Stores log level count per minute
		if (!exists $cur_info{$t_pid}{origloglevel}) {
			$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{log_level}{$cur_info{$t_pid}{loglevel}}++;
		} else {
			$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{log_level}{$cur_info{$t_pid}{origloglevel}}++;
		}

		# Stores normalized query samples
		if ($sample > 0)
		{
			my $cur_last_log_timestamp = "$cur_info{$t_pid}{year}-$cur_info{$t_pid}{month}-$cur_info{$t_pid}{day} " .
							"$cur_info{$t_pid}{hour}:$cur_info{$t_pid}{min}:$cur_info{$t_pid}{sec}";
			&set_top_error_sample( $cur_info{$t_pid}{cur_db},	$normalized_error,
									$cur_last_log_timestamp,
									$cur_info{$t_pid}{query},
									$cur_info{$t_pid}{detail},
									$cur_info{$t_pid}{context},
									$cur_info{$t_pid}{statement},
									$cur_info{$t_pid}{hint},
									$cur_info{$t_pid}{dbname},
									$cur_info{$t_pid}{dbuser},
									$cur_info{$t_pid}{dbappname},
									$cur_info{$t_pid}{dbclient},
									$cur_info{$t_pid}{sqlstate},
									$cur_info{$t_pid}{queryid},
			);
		}

	}
	elsif ($cur_info{$t_pid}{loglevel} eq 'LOG')
	{
		# Special case for auto_explain plan with csv and json logs
		if ((!exists $cur_plan_info{$t_pid}{plan} || $cur_plan_info{$t_pid}{plan} eq '') && $cur_info{$t_pid}{query} =~ s/^Query Text: ([^;]+);(.*)/$1/s)
		{
			$cur_plan_info{$t_pid}{plan} = $2;
		}

		# Store auto explain plan when switching to another log entry
		if (exists $cur_plan_info{$t_pid}{plan})
		{
			$cur_plan_info{$t_pid}{plan} =~ s/^\s+//s;
			$cur_plan_info{$t_pid}{plan} =~ s/\s+$//s;
			# Extract the query part from the plan, then the plan itself
			if ($cur_plan_info{$t_pid}{plan})
			{
				my $key = 'query';
				my @plan = split("\n", $cur_plan_info{$t_pid}{plan});
				foreach my $l (@plan) {
					# In TEXT format
					if ($l =~ /\(cost=\d+.*rows=\d+/) {
						$key = 'plan' ;
					# In JSON or YAML format
					} elsif ($l =~ /"Plan": \{|Plan:/) {
						$key = 'plan' ;
					# In XML format
					} elsif ($l =~ /<Plan>/) {
						$key = 'plan' ;
					}
					$cur_info{$t_pid}{$key} .= "$l\n";
				}
				# YAML format
				if ($cur_info{$t_pid}{query} =~ s/Query Text: "//s) {
					$cur_info{$t_pid}{query} =~ s/"$//s;
					$cur_info{$t_pid}{plan} .= "\n";
				# TEXT format
				} elsif ($cur_info{$t_pid}{query} =~ s/Query Text: ([^"]+)/$1/s) {
					$cur_info{$t_pid}{plan} .= "\n";
				# JSON format
				} elsif ($cur_info{$t_pid}{query} =~ s/.*"Query Text": "//s) {
					$cur_info{$t_pid}{query} =~ s/"$//s;
					$cur_info{$t_pid}{plan} = "  [\n    {\n" . $cur_info{$t_pid}{plan} . "  ]\n";
				} elsif ($cur_info{$t_pid}{query} =~ s/.*<Query-Text>//s) {
					$cur_info{$t_pid}{query} =~ s/<\/Query-Text>//s;
					$cur_info{$t_pid}{plan} .= "\n";
					if ($extens eq 'html') {
						$cur_info{$t_pid}{plan} =~ s/</&lt;/gs;
						$cur_info{$t_pid}{plan} =~ s/>/&gt;/gs;
					}
				}
			}
			delete $cur_plan_info{$t_pid};
		}

		# Stores global statistics

		$overall_stat{'queries_number'}++;
		$overall_stat{$cur_info{$t_pid}{cur_db}}{'queries_number'}++;
		$overall_stat{$cur_info{$t_pid}{cur_db}}{'queries_duration'}{'execute'} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});

		my $cur_last_log_timestamp = "$cur_info{$t_pid}{year}-$cur_info{$t_pid}{month}-$cur_info{$t_pid}{day} " .
						"$cur_info{$t_pid}{hour}:$cur_info{$t_pid}{min}:$cur_info{$t_pid}{sec}";
		if (!$overall_stat{$cur_info{$t_pid}{cur_db}}{'first_query_ts'} || ($overall_stat{$cur_info{$t_pid}{cur_db}}{'first_query_ts'} gt $cur_last_log_timestamp)) {
			$overall_stat{$cur_info{$t_pid}{cur_db}}{'first_query_ts'}   = $cur_last_log_timestamp;
		}
		if (!$overall_stat{$cur_info{$t_pid}{cur_db}}{'last_query_ts'} || ($overall_stat{$cur_info{$t_pid}{cur_db}}{'last_query_ts'} lt $cur_last_log_timestamp)) {
			$overall_stat{$cur_info{$t_pid}{cur_db}}{'last_query_ts'} = $cur_last_log_timestamp;
		}
		$overall_stat{$cur_info{$t_pid}{cur_db}}{'peak'}{$cur_last_log_timestamp}{query}++;

		if ($graph) {
			$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{count}++;
			$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{second}{$cur_info{$t_pid}{sec}}++;
			# Store min / max duration
			if ($cur_info{$t_pid}{duration}) {
				$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
				if (!exists $per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{min} || ($per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{min} > $cur_info{$t_pid}{duration})) {
					$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{min} = $cur_info{$t_pid}{duration};
				}
				if (!exists $per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{max} || ($per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{max} < $cur_info{$t_pid}{duration})) {
					$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{query}{max} = $cur_info{$t_pid}{duration};
				}
			}
		}

		# Counter per database and application name
		if ($cur_info{$t_pid}{dbname}) {
			$database_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbname}}{count}++;
			$database_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbname}}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
		} else {
			$database_info{$cur_info{$t_pid}{cur_db}}{unknown}{count}++;
			$database_info{$cur_info{$t_pid}{cur_db}}{unknown}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
		}
		if ($cur_info{$t_pid}{dbappname}) {
			$application_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbappname}}{count}++;
			$application_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbappname}}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
		} else {
			$application_info{$cur_info{$t_pid}{cur_db}}{unknown}{count}++;
			$application_info{$cur_info{$t_pid}{cur_db}}{unknown}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
		}
		if ($cur_info{$t_pid}{dbuser}) {
			$user_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbuser}}{count}++;
			$user_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbuser}}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
		} else {
			$user_info{$cur_info{$t_pid}{cur_db}}{unknown}{count}++;
			$user_info{$cur_info{$t_pid}{cur_db}}{unknown}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
		}
		if ($cur_info{$t_pid}{dbclient}) {
			$host_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbclient}}{count}++;
			$host_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbclient}}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
		} else {
			$host_info{$cur_info{$t_pid}{cur_db}}{unknown}{count}++;
			$host_info{$cur_info{$t_pid}{cur_db}}{unknown}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
		}

		if ($cur_info{$t_pid}{query}) {

			# add a semi-colon at end of the query
			$cur_info{$t_pid}{query} .= ';' if ($cur_info{$t_pid}{query} !~ /;\s*$/s);

			# normalize query
			my $normalized = &normalize_query($cur_info{$t_pid}{query});
			my $action = uc($1);
			if ($normalized =~ $action_regex) {
				$action = lc($1);
				$action = 'cte' if ($action eq 'with');
				# if this is a copy statement try to find if this is a write or read statement
				if (($action eq 'copy') && (($normalized =~ /from\s+stdin/i) || ($normalized =~ /from\s+\?/is))) {
					$action = 'copy from';
				} elsif ($action eq 'copy') {
					$action = 'copy to';
				} elsif ($action eq 'with') {
					$action = 'cte';
				} elsif ($action eq 'create' || $action eq 'drop' || $action eq 'alter' || $action eq 'truncate') {
					$action = 'ddl';
				} elsif ($action eq 'begin' || $action eq 'commit' || $action eq 'rollback' || $action eq 'start' || $action eq 'end' || $action eq 'savepoint') {
					$action = 'tcl';
				} elsif ($action eq 'declare' || $action eq 'close' || $action eq 'fetch' || $action eq 'move') {
					$action = 'cursor';
				}
			} else {
				$action = 'others';
			}
			$overall_stat{$cur_info{$t_pid}{cur_db}}{$action}++;
			if ($action eq 'select') {
				$overall_stat{$cur_info{$t_pid}{cur_db}}{'peak'}{$cur_last_log_timestamp}{select}++;
			} elsif ($action ne 'others') {
				$overall_stat{$cur_info{$t_pid}{cur_db}}{'peak'}{$cur_last_log_timestamp}{write}++;
			}
			$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{$action}{count}++;
			$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{$action}{second}{$cur_info{$t_pid}{sec}}++;
			$per_minute_info{$cur_info{$t_pid}{cur_db}}{"$cur_day_str"}{"$cur_hour_str"}{$cur_info{$t_pid}{min}}{$action}{duration} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			if ($cur_info{$t_pid}{dbname}) {
				$database_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbname}}{$action}++;
				$database_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbname}}{"$action|duration"} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			} else {
				$database_info{$cur_info{$t_pid}{cur_db}}{unknown}{$action}++;
				$database_info{$cur_info{$t_pid}{cur_db}}{unknown}{"$action|duration"} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			}
			if ($cur_info{$t_pid}{dbappname}) {
				$application_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbappname}}{$action}++;
				$application_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbappname}}{"$action|duration"} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			} else {
				$application_info{$cur_info{$t_pid}{cur_db}}{unknown}{$action}++;
				$application_info{$cur_info{$t_pid}{cur_db}}{unknown}{"$action|duration"} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			}
			if ($cur_info{$t_pid}{dbuser}) {
				$user_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbuser}}{$action}++;
				$user_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbuser}}{"$action|duration"} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			} else {
				$user_info{$cur_info{$t_pid}{cur_db}}{unknown}{$action}++;
				$user_info{$cur_info{$t_pid}{cur_db}}{unknown}{"$action|duration"} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			}
			if ($cur_info{$t_pid}{dbclient}) {
				$host_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbclient}}{$action}++;
				$host_info{$cur_info{$t_pid}{cur_db}}{$cur_info{$t_pid}{dbclient}}{"$action|duration"} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			} else {
				$host_info{$cur_info{$t_pid}{cur_db}}{unknown}{$action}++;
				$host_info{$cur_info{$t_pid}{cur_db}}{unknown}{"$action|duration"} += $cur_info{$t_pid}{duration} if ($cur_info{$t_pid}{duration});
			}

			# store normalized query count
			$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{count}++;

			# store normalized query count and duration per time
			$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{count}++;
			$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{min}{$cur_info{$t_pid}{min}}++;

			if ($cur_info{$t_pid}{duration} || $force_sample)
			{
				# update top slowest queries statistics
				&set_top_slowest($cur_info{$t_pid}{cur_db}, 	$cur_info{$t_pid}{query},
										$cur_info{$t_pid}{duration},
										$cur_last_log_timestamp,
										$cur_info{$t_pid}{dbname},
										$cur_info{$t_pid}{dbuser},
										$cur_info{$t_pid}{dbclient},
										$cur_info{$t_pid}{dbappname},
										$cur_info{$t_pid}{bind},
										$cur_info{$t_pid}{plan},
										$cur_info{$t_pid}{queryid}
									);

				# store normalized query total duration
				$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{duration} += $cur_info{$t_pid}{duration};
				$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{min_duration}{$cur_info{$t_pid}{min}} += $cur_info{$t_pid}{duration};

				# store min / max duration
				if (!exists $normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{min} || ($normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{min} > $cur_info{$t_pid}{duration})) {
					$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{min} = $cur_info{$t_pid}{duration};
				}
				if (!exists $normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{max} || ($normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{max} < $cur_info{$t_pid}{duration})) {
					$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{max} = $cur_info{$t_pid}{duration};
				}

				# stores query/user information
				if ($cur_info{$t_pid}{dbuser}) {
					$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{users}{$cur_info{$t_pid}{dbuser}}{duration} += $cur_info{$t_pid}{duration};
					$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{users}{$cur_info{$t_pid}{dbuser}}{count}++;
				}

				# stores query/app information
				if ($cur_info{$t_pid}{dbappname}) {
					$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{apps}{$cur_info{$t_pid}{dbappname}}{duration} += $cur_info{$t_pid}{duration};
					$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{apps}{$cur_info{$t_pid}{dbappname}}{count}++;
				}

				# store normalized query count and duration per time
				$normalyzed_info{$cur_info{$t_pid}{cur_db}}{$normalized}{chronos}{"$cur_day_str"}{"$cur_hour_str"}{duration} += $cur_info{$t_pid}{duration};

				# store normalized query samples
				&set_top_sample($cur_info{$t_pid}{cur_db}, 	$normalized,
										$cur_info{$t_pid}{query},
										$cur_info{$t_pid}{duration},
										$cur_last_log_timestamp,
										$cur_info{$t_pid}{dbname},
										$cur_info{$t_pid}{dbuser},
										$cur_info{$t_pid}{dbclient},
										$cur_info{$t_pid}{dbappname},
										$cur_info{$t_pid}{bind},
										$cur_info{$t_pid}{plan},
										$cur_info{$t_pid}{queryid}
									);
			}
		}

		if (exists $cur_bind_info{$t_pid})
		{

			if (exists $cur_bind_info{$t_pid}{'prepare'})
			{
				my $duration = $cur_bind_info{$t_pid}{'prepare'}{duration} || 0;
				my $query = $cur_bind_info{$t_pid}{'prepare'}{query} || '';
				my $timestamp = $cur_bind_info{$t_pid}{'prepare'}{timestamp} || '';

				my $cur_day = "$cur_info{$t_pid}{year}$cur_info{$t_pid}{month}$cur_info{$t_pid}{day}";
				my $cur_hour = "$cur_info{$t_pid}{hour}";
				if ($timestamp =~ /^(\d{4}-\d{2}-\d{2}) (\d{2}):\d{2}:\d{2}/)
				{
					$cur_day = $1;
					$cur_hour = $2;
				}

				# add a semi-colon at end of the query
				$query .= ';' if ($query !~ /;\s*$/s);

				# store normalized query count
				$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{count}++;

				# store normalized query count and duration per time
				$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{chronos}{"$cur_day"}{"$cur_hour_str"}{count}++;
				$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{chronos}{"$cur_day"}{"$cur_hour_str"}{min}{$cur_info{$t_pid}{min}}++;

				if ($duration)
				{
					# store normalized query total duration
					$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{duration} += $duration;
					$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{chronos}{"$cur_day"}{"$cur_hour_str"}{min_duration}{$cur_info{$t_pid}{min}} += $duration;

					# store min / max duration
					if (!exists $prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{min} || ($prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{min} > $duration)) {
						$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{min} = $duration;
					}
					if (!exists $prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{max} || ($prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{max} < $duration)) {
						$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{max} = $duration;
					}

					# store normalized query count and duration per time
					$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{chronos}{"$cur_day"}{"$cur_hour_str"}{duration} += $duration;
				}
				# stores query/user information
				if ($cur_info{$t_pid}{dbuser}) {
					$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{users}{$cur_info{$t_pid}{dbuser}}{duration} += $cur_info{$t_pid}{duration};
					$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{users}{$cur_info{$t_pid}{dbuser}}{count}++;
				}

				# stores query/app information
				if ($cur_info{$t_pid}{dbappname}) {
					$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{apps}{$cur_info{$t_pid}{dbappname}}{duration} += $cur_info{$t_pid}{duration};
					$prepare_info{$cur_info{$t_pid}{cur_db}}{$query}{apps}{$cur_info{$t_pid}{dbappname}}{count}++;
				}

				# store prepare query samples
				&set_top_prepare_bind_sample('prepare', $query, $duration, $timestamp, $cur_bind_info{$t_pid}{'prepare'}{'parameters'},
									$cur_info{$t_pid}{cur_db},
									$cur_info{$t_pid}{'dbname'},
									$cur_info{$t_pid}{'dbuser'},
									$cur_info{$t_pid}{'dbclient'},
									$cur_info{$t_pid}{'dbappname'},
									$cur_info{$t_pid}{'queryid'}
							);
			}

			if (exists $cur_bind_info{$t_pid}{'bind'})
			{
				my $duration = $cur_bind_info{$t_pid}{'bind'}{duration} || 0;
				my $query = $cur_bind_info{$t_pid}{'bind'}{query} || '';
				my $timestamp = $cur_bind_info{$t_pid}{'bind'}{timestamp} || '';

				my $cur_day = "$cur_info{$t_pid}{year}$cur_info{$t_pid}{month}$cur_info{$t_pid}{day}";
				my $cur_hour = "$cur_info{$t_pid}{hour}";
				if ($timestamp =~ /^(\d{4}-\d{2}-\d{2}) (\d{2}):\d{2}:\d{2}/)
				{
					$cur_day = $1;
					$cur_hour = $2;
				}

				# add a semi-colon at end of the query
				$query .= ';' if ($query !~ /;\s*$/s);

				# store normalized query count
				$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{count}++;

				# store normalized query count and duration per time
				$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{chronos}{"$cur_day"}{"$cur_hour_str"}{count}++;
				$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{chronos}{"$cur_day"}{"$cur_hour_str"}{min}{$cur_info{$t_pid}{min}}++;

				if ($duration)
				{
					# store normalized query total duration
					$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{duration} += $duration;
					$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{chronos}{"$cur_day"}{"$cur_hour_str"}{min_duration}{$cur_info{$t_pid}{min}} += $duration;

					# store min / max duration
					if (!exists $bind_info{$cur_info{$t_pid}{cur_db}}{$query}{min} || ($bind_info{$cur_info{$t_pid}{cur_db}}{$query}{min} > $duration)) {
						$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{min} = $duration;
					}
					if (!exists $bind_info{$cur_info{$t_pid}{cur_db}}{$query}{max} || ($bind_info{$cur_info{$t_pid}{cur_db}}{$query}{max} < $duration)) {
						$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{max} = $duration;
					}

					# store normalized query count and duration per time
					$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{chronos}{"$cur_day"}{"$cur_hour_str"}{duration} += $duration;
				}
				# stores query/user information
				if ($cur_info{$t_pid}{dbuser}) {
					$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{users}{$cur_info{$t_pid}{dbuser}}{duration} += $cur_info{$t_pid}{duration};
					$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{users}{$cur_info{$t_pid}{dbuser}}{count}++;
				}

				# stores query/app information
				if ($cur_info{$t_pid}{dbappname}) {
					$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{apps}{$cur_info{$t_pid}{dbappname}}{duration} += $cur_info{$t_pid}{duration};
					$bind_info{$cur_info{$t_pid}{cur_db}}{$query}{apps}{$cur_info{$t_pid}{dbappname}}{count}++;
				}

				# store bind query samples
				&set_top_prepare_bind_sample('bind', $query, $duration, $timestamp, $cur_bind_info{$t_pid}{'bind'}{'parameters'},
									$cur_info{$t_pid}{cur_db},
									$cur_info{$t_pid}{'dbname'},
									$cur_info{$t_pid}{'dbuser'},
									$cur_info{$t_pid}{'dbclient'},
									$cur_info{$t_pid}{'dbappname'},
									$cur_info{$t_pid}{'queryid'}
							);
			}
			delete $cur_bind_info{$t_pid};
		}
	}

	return 1;
}

sub store_temporary_and_lock_infos
{
	my $t_pid = shift;

	return if (!$t_pid);

	# Store normalized query temp file size if required
	if (exists $cur_temp_info{$t_pid} && ($cur_temp_info{$t_pid}{query} ne '')
		&& $cur_temp_info{$t_pid}{size})
	{
		# Remove additional information generated by log function call
		if ($cur_temp_info{$t_pid}{query} =~ s/(\s*PL\/pgSQL function.*)//s)
		{
			$cur_temp_info{$t_pid}{info} = $1;
		}

		# Add a semi-colon at end of the query
		$cur_temp_info{$t_pid}{query} .= ';' if ($cur_temp_info{$t_pid}{query} !~ /;\s*$/s);

		# Truncate the query if requested by the user
		if ($maxlength > 0) {
			&maxlen_truncate($cur_temp_info{$t_pid}{query});
		}

		# Normalize query
		my $normalized = &normalize_query($cur_temp_info{$t_pid}{query});

		$normalyzed_info{$cur_temp_info{$t_pid}{cur_db}}{$normalized}{tempfiles}{size} += $cur_temp_info{$t_pid}{size};
		$normalyzed_info{$cur_temp_info{$t_pid}{cur_db}}{$normalized}{tempfiles}{count}++;

		if ($normalyzed_info{$cur_temp_info{$t_pid}{cur_db}}{$normalized}{tempfiles}{maxsize} < $cur_temp_info{$t_pid}{size})
		{
			$normalyzed_info{$cur_temp_info{$t_pid}{cur_db}}{$normalized}{tempfiles}{maxsize} = $cur_temp_info{$t_pid}{size};
		}
		if (!exists($normalyzed_info{$cur_temp_info{$t_pid}{cur_db}}{$normalized}{tempfiles}{minsize})
		    || $normalyzed_info{$cur_temp_info{$t_pid}{cur_db}}{$normalized}{tempfiles}{minsize} > $cur_temp_info{$t_pid}{size})
		{
			$normalyzed_info{$cur_temp_info{$t_pid}{cur_db}}{$normalized}{tempfiles}{minsize} = $cur_temp_info{$t_pid}{size};
		}
		&set_top_tempfile_info($cur_temp_info{$t_pid}{cur_db},  $cur_temp_info{$t_pid}{query},
									$cur_temp_info{$t_pid}{size},
									$cur_temp_info{$t_pid}{timestamp},
									$cur_temp_info{$t_pid}{dbname},
									$cur_temp_info{$t_pid}{dbuser},
									$cur_temp_info{$t_pid}{dbclient},
									$cur_temp_info{$t_pid}{dbappname},
									$cur_temp_info{$t_pid}{info},
									$cur_temp_info{$t_pid}{queryid});

		# Check if we don't have sample for this query (occurs when log_min_duration_statement doesn't logged the query)
		if (!exists $normalyzed_info{$cur_temp_info{$t_pid}{cur_db}}{$normalized}{samples})
		{
			&set_top_sample($cur_temp_info{$t_pid}{cur_db}, $normalized,
									$cur_temp_info{$t_pid}{query},
									$cur_temp_info{$t_pid}{duration},
									$cur_temp_info{$t_pid}{timestamp},
									$cur_temp_info{$t_pid}{dbname},
									$cur_temp_info{$t_pid}{dbuser},
									$cur_temp_info{$t_pid}{dbclient},
									$cur_temp_info{$t_pid}{dbappname},
									$cur_temp_info{$t_pid}{bind},
									$cur_temp_info{$t_pid}{plan},
									$cur_temp_info{$t_pid}{queryid});
		}
		delete $cur_temp_info{$t_pid};
	}

	# Store normalized query that waited the most if required
	if (exists $cur_lock_info{$t_pid}{wait} && ($cur_lock_info{$t_pid}{query} ne ''))
	{

		# Add a semi-colon at end of the query
		$cur_lock_info{$t_pid}{query} .= ';' if ($cur_lock_info{$t_pid}{query} !~ /;\s*$/s);

		# Truncate the query if requested by the user
		if ($maxlength > 0) {
			&maxlen_truncate($cur_lock_info{$t_pid}{query});
		}

		# Normalize query
		my $normalized = &normalize_query($cur_lock_info{$t_pid}{query});

		$normalyzed_info{$cur_lock_info{$t_pid}{cur_db}}{$normalized}{locks}{wait} += $cur_lock_info{$t_pid}{wait};
		$normalyzed_info{$cur_lock_info{$t_pid}{cur_db}}{$normalized}{locks}{count}++;
		if ($normalyzed_info{$cur_lock_info{$t_pid}{cur_db}}{$normalized}{locks}{maxwait} < $cur_lock_info{$t_pid}{wait}) {
			$normalyzed_info{$cur_lock_info{$t_pid}{cur_db}}{$normalized}{locks}{maxwait} = $cur_lock_info{$t_pid}{wait};
		}
		if (!exists($normalyzed_info{$cur_lock_info{$t_pid}{cur_db}}{$normalized}{locks}{minwait})
		    || $normalyzed_info{$cur_lock_info{$t_pid}{cur_db}}{$normalized}{locks}{minwait} > $cur_lock_info{$t_pid}{wait}) {
			$normalyzed_info{$cur_lock_info{$t_pid}{cur_db}}{$normalized}{locks}{minwait} = $cur_lock_info{$t_pid}{wait};
		}
		&set_top_locked_info($cur_lock_info{$t_pid}{cur_db},    $cur_lock_info{$t_pid}{query},
									$cur_lock_info{$t_pid}{wait},
									$cur_lock_info{$t_pid}{timestamp},
									$cur_lock_info{$t_pid}{dbname},
									$cur_lock_info{$t_pid}{dbuser},
									$cur_lock_info{$t_pid}{dbclient},
									$cur_lock_info{$t_pid}{dbappname},
									$cur_lock_info{$t_pid}{queryid});

		# Check if we don't have sample for this query (occurs when log_min_duration_statement doesn't logged the query)
		if (!exists $normalyzed_info{$cur_lock_info{$t_pid}{cur_db}}{$normalized}{samples}) {
			&set_top_sample($cur_lock_info{$t_pid}{cur_db}, $normalized,
									$cur_lock_info{$t_pid}{query},
									$cur_lock_info{$t_pid}{duration},
									$cur_lock_info{$t_pid}{timestamp},
									$cur_lock_info{$t_pid}{dbname},
									$cur_lock_info{$t_pid}{dbuser},
									$cur_lock_info{$t_pid}{dbclient},
									$cur_lock_info{$t_pid}{dbappname},
									$cur_lock_info{$t_pid}{bind},
									$cur_lock_info{$t_pid}{plan},
									$cur_lock_info{$t_pid}{queryid});
		}
		delete $cur_lock_info{$t_pid};
	}

	# Store normalized query temp file size if required
	if (exists $cur_cancel_info{$t_pid} && ($cur_cancel_info{$t_pid}{query} ne ''))
	{

		# Add a semi-colon at end of the query
		$cur_cancel_info{$t_pid}{query} .= ';' if ($cur_cancel_info{$t_pid}{query} !~ /;\s*$/s);

		# Truncate the query if requested by the user
		if ($maxlength > 0) {
			&maxlen_truncate($cur_cancel_info{$t_pid}{query});
		}

		# Normalize query
		my $normalized = &normalize_query($cur_cancel_info{$t_pid}{query});

		$normalyzed_info{$cur_cancel_info{$t_pid}{cur_db}}{$normalized}{cancelled}{count}++;

		&set_top_cancelled_info($cur_cancel_info{$t_pid}{cur_db}, 	$cur_cancel_info{$t_pid}{query},
									$cur_cancel_info{$t_pid}{count},
									$cur_cancel_info{$t_pid}{timestamp},
									$cur_cancel_info{$t_pid}{dbname},
									$cur_cancel_info{$t_pid}{dbuser},
									$cur_cancel_info{$t_pid}{dbclient},
									$cur_cancel_info{$t_pid}{dbappname},
									$cur_cancel_info{$t_pid}{queryid}
								);

		delete $cur_cancel_info{$t_pid};
	}
}

# Normalize error messages
sub normalize_error
{
	my $orig_query = shift;

	return if (!$orig_query);

	# Remove character position
	$orig_query =~ s/ at character \d+.*//s;

	# Remove encoding detail
	$orig_query =~ s/(byte sequence for encoding).*/$1/;

	# Replace changing parameter by ...
	$orig_query =~ s/"[^"]+"/"..."/g;
	$orig_query =~ s/""...""/"..."/g;
	$orig_query =~ s/\([^\)]+\)/\(...\)/g;
	$orig_query =~ s/column .* does not exist/column "..." does not exist/;
	$orig_query =~ s/(database system was.* at (?:log time )?).*/$1 .../;
	$orig_query =~ s/[0-9A-F]{24}/.../g; # Remove WAL filename
	$orig_query =~ s/, u_uuid: [^,]+, file_path:.*/. Retrying/;
	$orig_query =~ s/( for)? PID \d+//;
	$orig_query =~ s/ TIMELINE \d+/ TIMELINE n/;
	$orig_query =~ s/ [0-9A-F]+\/[0-9A-F]+ / x\/x /;
	$orig_query =~ s/ BASE_BACKUP LABEL '[^']*'.*/ BASE_BACKUP LABEL '...'/;
	$orig_query =~ s/(transaction|relation|database|process) \d+/$1 .../g;
	$orig_query =~ s/after \d+\.\d+/after .../;
	$orig_query =~ s/cannot drop ([^\s]+) [^\s]+ /cannot drop $1 ... /;
	$orig_query =~ s/\[[^\]]+\]/.../g;
	$orig_query =~ s/(character with byte sequence) .* (in encoding)/$1 ... $2/;
	$orig_query =~ s/(invalid input syntax for [^:]+:).*/$1 .../;
	$orig_query =~ s/character (.*?) of encoding/character ... of encoding/;
	$orig_query =~ s/(unterminated quoted string at or near) "[^"]+"/$1 "..."/;
	$orig_query =~ s/on page \d+ of relation/on page ... of relation/;
	$orig_query =~ s/(side location conflict at ).*/$1 .../;
	$orig_query =~ s/(permission denied for [^\s]+) .*/$1 .../;
	$orig_query =~ s/(database) (?:.*)? (must be vacuumed within) \d+ (transactions)/$1 "..." $2 ... $3/;
	$orig_query =~ s/(logical decoding found consistent point at).*/$1 "..."/;
	$orig_query =~ s/(starting logical decoding for slot).*/$1 "..."/;

	# Need more normalization stuff here
	return $orig_query;
}

# Normalize pgbouncer error messages
sub pgb_normalize_error
{
	my $orig_query = shift;

	return if (!$orig_query);

	# Replace changing parameter by ...
	$orig_query =~ s/"[^"]*"/"..."/g;
	$orig_query =~ s/'[^']*'/'...'/g;
	$orig_query =~ s/\([^\)]+\)/\(...\)/g;
	$orig_query =~ s/[\d\.]+:\d+/.../g;
	$orig_query =~ s/(no such database: ) .*/$1 .../;
	$orig_query =~ s/db=[^\s]+ user=[^\s]+/db=... user=.../;
	$orig_query =~ s/(no more connections allowed) .*/$1/;

	# Need more normalization stuff here
	return $orig_query;
}

sub average_per_minutes
{
	my $val = shift;
	my $idx = shift;

	my @lavgs = ();
	for (my $i = 0 ; $i < 60 ; $i += $idx) {
		push(@lavgs, sprintf("%02d", $i));
	}

	for (my $i = 0 ; $i <= $#lavgs ; $i++) {
		if ($val == $lavgs[$i]) {
			return "$lavgs[$i]";
		} elsif ($i == $#lavgs) {
			return "$lavgs[$i]";
		} elsif (($val > $lavgs[$i]) && ($val < $lavgs[$i + 1])) {
			return "$lavgs[$i]";
		}
	}
	return $val;
}

sub autodetect_format
{
	my ($file, $totalsize) = @_;

	# a file must be passed
	return if (!$file);

	# Open log file for reading
	my $nfound = 0;
	my $nline  = 0;
	my $fmt    = '';
	my %ident_name = ();
	my $fltf;
	my $http_download  = ($file =~ /^(http[s]*:|[s]*ftp:)/i) ? 1 : 0;
	my $ssh_download   = ($file =~ /^ssh:/i) ? 1 : 0;

	# If log format is given at end of the filename, remove it and return the format
	# Ex: ssh://remotehost/postgresql-10.log:csv
	if ($file =~ s#:(syslog|csv|stderr|pgbouncer)\d*$##)
	{
		&logmsg('DEBUG', "Autodetected log format '$1' from URI '$file'");
		return $1;
	}

	# the format have been forced at command line
	return $format if ($format);

	if (!$remote_host && !$http_download && !$ssh_download)
	{
		if (open(my $in, '<', $file))
		{
			$fltf = <$in>;
			close($in);
		}
		else
		{
			localdie("FATAL: when looking for log file format, can't open file $file, $!\n");
		}
	}

	# is file in binary format ?
	if ( $fltf =~ /^pst\d/ )
	{
		&logmsg('DEBUG', "found binary file with $file");
		$fmt = 'binary';
	}
	elsif (!$http_download && !$log_command && !$journalctl_cmd)
	{
		# try to detect syslogs, stderr, csv, jsonlog or pgbouncer format
		my $tfile = &get_log_file($file, $totalsize, $remote_host || $ssh_download);
		if (defined $tfile)
		{
			while (my $line = <$tfile>)
			{
				chomp($line);
				$line =~ s/\r//;
				next if (!$line);
				$nline++;

				my ($f, $i) = search_log_format($line);
				$nfound++ if ($f);
				$fmt = $f;
				$ident_name{$i}++ if ($i);
				last if (($nfound > 10) || ($nline > 5000));
			}
			$tfile->close();
		}
		else
		{
			&logmsg('DEBUG', "Can not autodetect log format from $file, using default");
			return 'default';
		}

	}
	elsif (!$format)
	{
		if (!$http_download)
		{
			localdie("FATAL: you need to specify the log format, please use -f option.\n");
		}
		else
		{
			localdie("FATAL: with http files you need to specify the log format, append it to the uri.\n");
		}
	}

	# When --pgbouncer-only is used force the format
	if (!$format && !$fmt && $pgbouncer_only)
	{
		$pgbouncer_only = 1;
		$fmt = 'pgbouncer';
	}
	elsif (!$format)
	{
		# we make exception for binary and jsonlog as
		# the format can be deduced with just one line.
		if (!$fmt || ($nfound < 10 && $fmt ne 'binary' && $fmt ne 'jsonlog'))
		{
			if ($log_line_prefix =~ /\%(t|m|n).*\%(c|p)/)
			{
				# when log line prefix is set and have mandatory
				# placeholders we considere format is stderr
				$fmt = 'stderr';
			}
			else
			{
				localdie("FATAL: unable to detect log file format from $file, please use -f option.\n");
			}
		}
	}
	elsif (!$fmt)
	{
		# Force format if forced as parameter with -f
		$fmt = $format;
	}

	if (($fmt =~ /syslog/) && !$ident && (scalar keys %ident_name == 1))
	{
		$ident = (keys %ident_name)[0];
	}

	&logmsg('DEBUG', "Autodetected log format '$fmt' from $file");
	&logmsg('DEBUG', "Autodetected UTC timestamp") if ($isUTC);

	return $fmt;
}

sub search_log_format
{
	my $line = shift;

	my $fmt = '';
	my $ident_name = '';

	$isUTC = 0;


	# jsonlog lines
	if ($line =~ /\{"(timestamp|insertId)":"/)
	{
		$fmt = 'jsonlog';
	}
	# cloudsql lines
	elsif ($line =~ /"textPayload":\s*"(?:\d+-\d+-\d+[T\s]\d+:\d+:\d+\.\d+\s[^\s]*\s+\[(\d+)\]:.*)",$/)
	{
		$fmt = 'jsonlog';
	}
	# cnpg lines
	elsif ($line =~ /"logging_pod":\s*.+"record":/)
	{
		$fmt = 'jsonlog';
	}
	# Are pgbouncer syslog lines ?
	elsif ($line =~
/^[A-Z][a-z]{2}\s+\d+ \d+:\d+:\d+( [^\s]+)? [^\s]+ [^\s\[]+\[\d+\]: (?:.\-0x[0-9a-f\.]+|Stats):/
	   )
	{
		$fmt = 'pgbouncer1';
		# If we just have one single pgbouncer file, force pgbouncer_only to 1
		$pgbouncer_only = 1 if ($#log_files == 0);
		$isUTC =  1 if ($1 eq ' UTC');

	}
	elsif ($line =~
/^\d+-\d+-\d+T\d+:\d+:\d+(?:.[^\s]+)?(\s[^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[\d+\]: (.\-0x[0-9a-f\.]*|Stats):/
	   )
	{
		$fmt = 'pgbouncer2';
		# If we just have one single pgbouncer file, force pgbouncer_only to 1
		$pgbouncer_only = 1 if ($#log_files == 0);
		$isUTC =  1 if ($1 eq ' UTC');

	# Are syslog lines ?
	}
	elsif ($line =~
/^[A-Z][a-z]{2}\s+\d+\s\d+:\d+:\d+(?:\.\d+)?(\s[^\s]+)?\s[^\s]+\s([^\s\[]+)\[\d+\]:(?:\s\[[^\]]+\])?\s\[\d+(?:\-\d+)?\].*?(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT):/
	   )
	{
		$fmt = 'syslog';
		$ident_name = $2;
		$isUTC =  1 if ($1 eq ' UTC');

	}
	elsif ($line =~
/^\d+-\d+-\d+T\d+:\d+:\d+(?:.[^\s]+)?(\s[^\s]+)\s(?:[^\s]+\s)?(?:[^\s]+\s)?([^\s\[]+)\[\d+\]:(?:\s\[[^\]]+\])?\s\[\d+(?:\-\d+)?\].*?(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT):/
	   )
	{
		$fmt = 'syslog2';
		$ident_name = $2;
		$isUTC =  1 if ($1 eq ' UTC');

	}
	elsif ($line =~
		 /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:\.\d+)?[+\-]\d{2}:\d{2}\s+(?:[^\s]+)?\s*app\[postgres\.(\d+)\][:]?\s+\[[^\]]+\]\s+\[(\d+)\-\d+\]\s+(.*?)\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)/
	  )
	{
	       $fmt = 'logplex';
	       $ident_name = 'postgres';

	}
	elsif ($line =~
	       /^(?:\d+-\d+-\d+T\d+:\d+:\d+\.\d+Z)?\s*\d+-\d+-\d+ \d+:\d+:\d+(\s[^:]+)?:[^:]*:[^\@]*\@[^:]*:\[\d+\]:(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)/
	  )
	{
		$fmt = 'rds';
		$isUTC =  1 if ($1 eq ' UTC');

	}
	elsif ($line =~
			 /^'\d+-\d+-\d+T\d+:\d+:\d+Z( [^\s]+) \[ db=(.*?) user=(.*?) pid=\d+ userid=\d+ xid=(.*?) \]' (LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(.*)/
	  )
	{
		$fmt = 'redshift';
		$isUTC =  1 if ($1 eq ' UTC');

	}
	# Are csv lines ?
	elsif (
		(
			$line =~
			/^\d+-\d+-\d+ \d+:\d+:\d+\.\d+( [A-Z\+\-\d]{3,6})?,.*,(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT),/
		)
		&& ($line =~ tr/,/,/ >= 12)
		)
	{
		$fmt = 'csv';
		$isUTC =  1 if ($1 eq ' UTC');

	# Are stderr lines ?
	} elsif ($line =~
/(?:\d{10}\.\d{3}|\d+-\d+-\d+ \d+:\d+:\d+)[\.0-9]*( [A-Z\+\-\d]{3,6})? \[([0-9a-f\.]+)\]: \[\d+-\d+\] (.*?)\s+(.*?)(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT):\s+/
		)
	{
		$fmt = 'stderr';
		$isUTC =  1 if ($1 eq ' UTC');

	# Are default stderr lines since 10.0 or minimal prefix for pgbadger?
	} elsif ($line =~
/(?:\d{10}\.\d{3}|\d+-\d+-\d+ \d+:\d+:\d+)[\.0-9]*( [A-Z\+\-\d]{3,6}) \[([0-9a-f\.]+)\][:]*\s+(.*?)(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT):\s+/
		)
	{
		$fmt = 'default';
		$isUTC =  1 if ($1 eq ' UTC');

	# Are pgbouncer lines ?
	} elsif ($line =~ /^(?:\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+( [A-Z\+\-\d]{3,6})? (\d+) (LOG|ERROR) (.\-0x[0-9a-f\.]+|Stats):/) {
		$fmt = 'pgbouncer';
		# If we just have one single pgbouncer file, force pgbouncer_only to 1
		$pgbouncer_only = 1 if ($#log_files == 0);
		$isUTC =  1 if ($1 eq ' UTC');

	} elsif ($line =~ /^(?:\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+( [A-Z\+\-\d]{3,6})? \[(\d+)\] (LOG|ERROR) (.\-0x[0-9a-f\.]+|Stats):/) {
		$fmt = 'pgbouncer3';
		# If we just have one single pgbouncer file, force pgbouncer_only to 1
		$pgbouncer_only = 1 if ($#log_files == 0);
		$isUTC =  1 if ($1 eq ' UTC');
	}
	return ($fmt, $ident_name);
}

sub progress_bar
{
	my ($got, $total, $width, $char, $queries, $errors, $fmt) = @_;

	return if (!$progress);

	#my ($package, $filename, $line) = caller;
	$width ||= 25;
	$char  ||= '=';

	my $num_width = length $total;
	my $nchars = (($width - 1) * $got / ($total||1));
	$nchars = ($width - 1) if ($nchars >= $width);
	$got = 0 if ($got < 0);
	my $lbl = 'queries';
	$lbl = 'stats' if ($fmt =~ /pgbouncer/);

	if ($format eq 'binary')
	{
		my $file = $_[-1];
		sprintf(
			"Loaded %d $lbl and %d events, reading binary file %s...\r",
			($overall_stat{'queries_number'} + $pgb_overall_stat{'queries_number'}),
			($overall_stat{'errors_number'} + $pgb_overall_stat{'errors_number'}),
			$file
		);
	}
	else
	{
		if ($total)
		{
			sprintf(
				"[%-${width}s] Parsed %${num_width}s bytes of %s (%.2f%%), $lbl: %d, events: %d\r",
				$char x $nchars . '>',
				$got, $total, 100 * $got / (+$total||1),
				($queries || ($overall_stat{'queries_number'}+$pgb_overall_stat{'queries_number'})),
				($errors  || ($overall_stat{'errors_number'} + $pgb_overall_stat{'errors_number'}))
			);
		}
		else
		{
			$char = '+';
			sprintf(
				"[%s] Parsed %d bytes, $lbl: %d, events: %d\r",
				$char,
				$got,
				($queries || ($overall_stat{'queries_number'} + $pgb_overall_stat{'queries_number'})),
				($errors || ($overall_stat{'errors_number'} + $pgb_overall_stat{'errors_number'}))
			);
		}
	}
}

sub jqplot_linegraph
{
	my ($buttonid, $divid, $data1, $data2, $data3, $title, $ytitle, $legend1, $legend2, $legend3, $ytitle2, $data4, $legend4) = @_;

	if (!$data1) {
		return qq{
<h3 class="">$title</h3>
<div id="$divid" class="jqplot-graph linegraph"><blockquote><b>NO DATASET</b></blockquote></div>
};
	}
	my $options_series = '';
	if ($legend1) {
		$options_series .= "{ label: \"$legend1\", color: \"#6e9dc9\" },";
	}
	if ($legend2) {
		$options_series .= "{ label: \"$legend2\", color: \"#f4ab3a\" },";
	}
	if ($legend3) {
		$options_series .= "{ label: \"$legend3\", color: \"#ac7fa8\" },";
	}
	if ($legend4) {
		if ($ytitle2) {
			$options_series .= "{ label: \"$legend4\", color: \"#8dbd0f\", yaxis: 'y2axis'},";
		} else {
			$options_series .= "{ label: \"$legend4\", color: \"#8dbd0f\" },";
		}
	}
	$options_series =~ s/,$//;

	my $dateTracker_dataopts = '';
	if ($data1) {
		$data1 = "var ${divid}_${buttonid}_d1 = [$data1];";
		$dateTracker_dataopts .= "${divid}_${buttonid}_d1,";
	}
	if ($data2) {
		$data2 = "var ${divid}_${buttonid}_d2 = [$data2];";
		$dateTracker_dataopts .= "${divid}_${buttonid}_d2,";
	}
	if ($data3) {
		$data3 = "var ${divid}_${buttonid}_d3 = [$data3];";
		$dateTracker_dataopts .= "${divid}_${buttonid}_d3,";
	}
	if ($data4) {
		$data4 = "var ${divid}_${buttonid}_d4 = [$data4];";
		$dateTracker_dataopts .= "${divid}_${buttonid}_d4,";
	}
	$dateTracker_dataopts =~ s/,$//;

	return <<EOF;
<div id="$divid" class="jqplot-graph linegraph"></div>
<script type="text/javascript">
/* <![CDATA[ */
$data1
$data2
$data3
$data4
var series_arr = [ $options_series ];

charts = window.charts || [];
create_download_button($buttonid, 'btn btn-default');
charts.push(['linegraph', '$divid', '$title', '$ytitle', series_arr, [$dateTracker_dataopts]]);
add_download_button_event($buttonid, '$divid');
/* ]]> */
</script>
EOF

}

sub jqplot_piegraph
{
	my ($buttonid, $divid, $title, %data) = @_;

	if (scalar keys %data == 0) {
		return qq{
<h3 class="">$title</h3>
<div id="$divid" class="jqplot-graph piegraph"><blockquote><b>NO DATASET</b></blockquote></div>
};
	}

	my $datadef = '';
	foreach my $k (sort keys %data) {
		$datadef .= "['$k', $data{$k}],";
	}
	$datadef =~ s/,$//;

	return <<EOF;
<div id="$divid" class="jqplot-graph piegraph"></div>
<script type="text/javascript">
/* <![CDATA[ */
var data_${buttonid} = [ $datadef ];

charts = window.charts || [];
create_download_button($buttonid, 'btn btn-default');
charts.push(['piechart', '$divid', '$title', data_${buttonid}]);
add_download_button_event($buttonid, '$divid');
/* ]]> */
</script>
EOF

}

sub jqplot_histograph
{
	my ($buttonid, $divid, $data1, $data2, $legend1, $legend2) = @_;

	if (!$data1) {
		return qq{
<div id="$divid" class="jqplot-graph histo-graph"><blockquote><b>NO DATASET</b></blockquote></div>
};
	}
	$legend1 ||= 'Queries';
	my $y2decl = '';
	my $y2vals = '';
	if ($data2) {
		$legend2 ||= 'Avg. duration';
		$y2decl = "var lines_${buttonid} = [$data2];";
		$y2vals = ", lines_${buttonid}";
	}
	my $title = '';

	return <<EOF;
<div id="$divid" class="jqplot-graph histo-graph"></div>
<script type="text/javascript">
/* <![CDATA[ */
\$('#A$divid').on("shown.bs.collapse",function(){
	var bars_${buttonid} = [$data1];
	$y2decl
	var $divid = create_bargraph('$divid', '$title', '$legend1', [ bars_${buttonid}$y2vals ], '$legend2');
});
create_download_button($buttonid, 'btn btn-default btn-xs');
add_download_button_event($buttonid, '$divid');
/* ]]> */
</script>
EOF

}

sub jqplot_duration_histograph
{
	my ($buttonid, $divid, $legend, $range, %data) = @_;

	if (scalar keys %data == 0) {
		return qq{
<div id="$divid" class="jqplot-graph duration-histo-graph"><blockquote><b>NO DATASET</b></blockquote></div>
};
	}
	$legend ||= 'Queries';

	my $bars = '';
	for (my $i = 1; $i <= $#{$range}; $i++) {
		my $k = "$range->[$i-1]-$range->[$i]ms";
		my $lbl = "'" . &convert_time($range->[$i-1]) . '-' . &convert_time($range->[$i]) . "'";
		$bars .= "[ $lbl, $data{$k}],";
	}
	my $k = "> $range->[-1]ms";
	$bars .= "[ '> " . &convert_time($range->[-1]) . "', $data{$k}]";
	my $title = '';

	return <<EOF;
<div id="$divid" class="jqplot-graph duration-histo-graph"></div>
<script type="text/javascript">
/* <![CDATA[ */
charts = window.charts || [];
var bars_${buttonid} = [$bars];
create_download_button($buttonid, 'btn btn-default');
charts.push(['bargraph', '$divid', '$title', '$legend', [ bars_${buttonid} ]]);
add_download_button_event($buttonid, '$divid');
/* ]]> */
</script>
EOF

}

sub build_log_line_prefix_regex
{
	my $llp = shift;

	my %regex_map = (
		'%a' => [('t_appname',      '(.*?)')],				   # application name
		'%u' => [('t_dbuser',       '([0-9a-zA-Z\_\[\]\-\.]*)')],					 # user name
		'%d' => [('t_dbname',       '([0-9a-zA-Z\_\[\]\-\.]*)')],					 # database name
		'%r' => [('t_hostport',     '([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)?[\(\d\)]*')],     # remote host and port
		'%h' => [('t_client',       '([a-zA-Z0-9\-\.]+|\[local\]|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)?')],	      # remote host
		'%p' => [('t_pid',	  '(\d+)')],		# process ID
		'%Q' => [('t_queryid',	  '([\-]*\d+)')],	# Query ID
		'%n' => [('t_epoch',    '(\d{10}\.\d{3})')],    # timestamp as Unix epoch
		'%t' => [('t_timestamp',    '(\d{4}-\d{2}-\d{2}[\sT]\d{2}:\d{2}:\d{2})[Z]*(?:[ \+\-][A-Z\+\-\d]{3,6})?')],      # timestamp without milliseconds
		'%m' => [('t_mtimestamp',   '(\d{4}-\d{2}-\d{2}[\sT]\d{2}:\d{2}:\d{2})\.\d+(?:[ \+\-][A-Z\+\-\d]{3,6})?')], # timestamp with milliseconds
		'%l' => [('t_session_line', '(\d+)')],							# session line number
		'%s' => [('t_session_timestamp', '(\d{4}-\d{2}-\d{2}[\sT]\d{2}):\d{2}:\d{2}(?:[ \+\-][A-Z\+\-\d]{3,6})?')],    # session start timestamp
		'%c' => [('t_session_id',	'([0-9a-f\.]*)')],					       # session ID
		'%v' => [('t_virtual_xid',       '([0-9a-f\.\/]*)')],					     # virtual transaction ID
		'%x' => [('t_xid',	       '([0-9a-f\.\/]*)')],					     # transaction ID
		'%i' => [('t_command',	   '([0-9a-zA-Z\.\-\_\s]*)')],					# command tag
		'%e' => [('t_sqlstate',	  '([0-9a-zA-Z]+)')],					      # SQL state
		'%b' => [('t_backend_type',	  '(.*?)')],					      # backend type
	);
	my $param_list = [];
	$llp =~ s/([\[\]\|\(\)\{\}])/\\$1/g;
	$llp =~ s/\%l([^\d])\d+/\%l$1\\d\+/;
	my $q_prefix = '';
	if ($llp =~ s/(.*)\%q(.*)/$1$2/) {
		$q_prefix =  $1;
	}
	while ($llp =~ s/(\%[audrhpQntmlscvxieb])/$regex_map{"$1"}->[1]/) {
		push(@$param_list, $regex_map{"$1"}->[0]);
	}
	my $q_prefix_param = [];
		if ($q_prefix) {
		while ($q_prefix =~ s/(\%[audrhpQntmlscvxieb])/$regex_map{"$1"}->[1]/) {
			push(@$q_prefix_param, $regex_map{"$1"}->[0]);
		}
		push(@$q_prefix_param, 't_loglevel', 't_query');
	}

	# replace %% by a single %
	$llp =~ s/\%\%/\%/g;
	$q_prefix =~ s/\%\%/\%/g;
	$q_prefix = qr/$q_prefix\s*(LOG|WARNING|ERROR|FATAL|PANIC|DETAIL|STATEMENT|HINT|CONTEXT|LOCATION):\s+(?:[0-9A-Z]{5}:\s+)?(.*)/;

	# t_session_id (%c) can naturaly replace pid as unique session id
	# when it is given in log_line_prefix and pid is not present.
	$use_sessionid_as_pid = 1 if ( grep(/t_session_id/, @$param_list) && !grep(/t_pid/, @$param_list) );

	# Check regex in log line prefix from command line
	&check_regex($llp, '--prefix');
	return (
		'llp' => $llp, 'param_list' => $param_list,
		'q_prefix' => $q_prefix, 'q_param_list' => $q_prefix_param
	);
}

####
# get_file_size: in scalar context returns the size of the file,
#       in list context returns the size of the file and a boolean
#       to indicate if the file is compressed.
#       The total size returnied is set to -1 when pgbadger can not
#       determine the file size (remote file, bzip2 conmpressed file
#       and privilege issue). Outside these cases if we can't get size
#       of a remote file pgbadger exit with a fatal error.
####
sub get_file_size
{
	my $logf = shift;

	# Remove log format from log file if any
	$logf =~ s/[\r\n]+//sg;
	$logf =~ s/:(stderr|csv|syslog|pgbouncer|jsonlog|logplex|rds|redshift)\d*$//i;

	my $http_download  = ($logf =~ /^(http[s]*:|[s]*ftp:)/i) ? 1 : 0;
	my $ssh_download   = ($logf =~ /^ssh:/i) ? 1 : 0;
	my $iscompressed   = ($logf =~ $compress_extensions) ? 1 : 0;

	# Get file size
	my $totalsize = 0;

	# Log entries extracted from journalctl command are of indetermined size
	if ( $journalctl_cmd && ($logf =~ m/\Q$journalctl_cmd\E/) )
	{
		$totalsize = -1;
	}

	# Log entries extracted from cust command are of indetermined size
	elsif ( $log_command && ($logf =~ m/\Q$log_command\E/) )
	{
		$totalsize = -1;
	}

	# Same from stdin
	elsif ($logf eq '-')
	{
		$totalsize = -1;
	}

	# Regular local files can be "stated" if they are not compressed
	elsif (!$remote_host && !$http_download && !$ssh_download && !$iscompressed)
	{
		eval {
			$totalsize = (stat($logf))[7];
		};
		$totalsize = -1 if ($@);
	}

	# For uncompressed files try to get the size following the remote access protocol
	elsif (!$iscompressed)
	{
		# Use curl to try to get remote file size if it is not compressed
		if ($http_download) {
			&logmsg('DEBUG', "Looking for file size using command: $curl_command --head \"$logf\" | grep \"Content-Length:\" | awk '{print \$2}'");
			$totalsize = `$curl_command --head "$logf" | grep "Content-Length:" | awk '{print \$2}'`;
			chomp($totalsize);
			localdie("FATAL: can't get size of remote file, please check what's going wrong with command: $curl_command --head \"$logf\" | grep \"Content-Length:\"\n") if ($totalsize eq '');
		} elsif ($ssh_download && $logf =~ m#^ssh:\/\/([^\/]+)/(.*)#i) {
			my $host_info = $1;
			my $file = $2;
			$file =~ s/[\r\n]+//sg;
			$file =~ s/:(stderr|csv|syslog|pgbouncer|jsonlog|logplex|rds|redshift)\d*$//i;
			my $ssh = $ssh_command || 'ssh';
			if ($host_info =~ s/:(\d+)$//) {
				$host_info = "-p $1 $host_info";
			}
			$ssh .= " -i $ssh_identity" if ($ssh_identity);
			$ssh .= " $ssh_options" if ($ssh_options);
			&logmsg('DEBUG', "Looking for file size using command: $ssh $host_info \"ls -l '$file'\" | awk '{print \$5}'");
			$totalsize = `$ssh $host_info "ls -l '$file'" | awk '{print \$5}'`;
			chomp($totalsize);
			localdie("FATAL: can't get size of remote file, please check what's going wrong with command: $ssh $host_info \"ls -l '$file'\"\n") if ($totalsize eq '');
		} elsif ($remote_host) {
			&logmsg('DEBUG', "Looking for file size using command: $remote_command \"ls -l '$logf'\" | awk '{print \$5}'");
			$totalsize = `$remote_command "ls -l '$logf'" | awk '{print \$5}'`;
			chomp($totalsize);
			localdie("FATAL: can't get size of remote file, please check what's going wrong with command: $ssh_command \"ls -l '$logf'\"\n") if ($totalsize eq '');
		}
		chomp($totalsize);

		&logmsg('DEBUG', "Remote file size: $totalsize");
	}

	# Real size of the file is unknown with compressed file, try to find
	# size using uncompress command (bz2 does not report real size)
	elsif (!$http_download && $logf =~ $compress_extensions)
	{

		my $cmd_file_size = $gzip_uncompress_size;
		if ($logf =~ /\.zip$/i) {
			$cmd_file_size = $zip_uncompress_size;
		} elsif ($logf =~ /\.xz$/i) {
			$cmd_file_size = $xz_uncompress_size;
		} elsif ($logf =~ /\.lz4$/i) {
			$cmd_file_size = $lz4_uncompress_size;
		} elsif ($logf =~ /\.zst$/i) {
			$cmd_file_size = $zstd_uncompress_size;
		} elsif ($logf =~ /\.bz2$/i) {
			$cmd_file_size = "ls -l '%f' | awk '{print \$5}'";
		}

		if (!$remote_host && !$http_download && !$ssh_download) {
			$cmd_file_size =~ s/\%f/$logf/g;
			&logmsg('DEBUG', "Looking for file size using command: $cmd_file_size");
			$totalsize = `$cmd_file_size`;

			chomp($totalsize);
			if ($totalsize !~ /\d+/) {
				if ($logf =~ /\.lz4$/i) {
					# lz4 archive must be compressed with --content-size option to determine size. If not $totalsize is '-'
					&logmsg('DEBUG', "Can't determine lz4 file size. Maybe file compressed without --content-size option ?");
				} else {
					&logmsg('DEBUG', "Can't determine uncompressed file size. Guess with compressed size * $XZ_FACTOR");
				}
				# Thus we use a hack to determine size
				$cmd_file_size = "ls -l '%f' | awk '{print \$5}'";
				$cmd_file_size =~ s/\%f/$logf/g;
				$totalsize = `$cmd_file_size`;
				$totalsize *= $XZ_FACTOR;
			}
		} elsif ($ssh_download && $logf =~ m#^ssh://([^\/]+)/(.*)#i) {
			my $host_info = $1;
			my $file = $2;
			my $ssh = $ssh_command || 'ssh';
			if ($host_info =~ s/:(\d+)$//) {
				$host_info = "-p $1 $host_info";
			}
			$ssh .= " -i $ssh_identity" if ($ssh_identity);
			$ssh .= " $ssh_options" if ($ssh_options);
			$cmd_file_size =~ s/\%f/$file/g;
			$cmd_file_size =~ s/\$/\\\$/g;
			&logmsg('DEBUG', "Looking for file size using command: $ssh $host_info \"$cmd_file_size\"");
			$totalsize = `$ssh $host_info \"$cmd_file_size\"`;
		} else {
			$cmd_file_size =~ s/\%f/$logf/g;
			$cmd_file_size =~ s/\$/\\\$/g;
			&logmsg('DEBUG', "Looking for remote file size using command: $remote_command \"$cmd_file_size\"");
			$totalsize = `$remote_command \"$cmd_file_size\"`;
		}
		chomp($totalsize);
		# For bz2 compressed file we don't know the real size
		if ($logf =~ /\.bz2$/i) {
			# apply deflate estimation factor
			$totalsize *= $BZ_FACTOR;
		}

	}

	# Bzip2 and remote download compressed files can't report real size, get compressed
	# file size and estimate the real size by using bzip2, gzip and xz factors.
	elsif ($http_download)
	{
		&logmsg('DEBUG', "Looking for file size using command: $curl_command --head \"$logf\" | grep \"Content-Length:\" | awk '{print \$2}'");
		$totalsize = `$curl_command --head \"$logf\" | grep "Content-Length:" | awk '{print \$2}'`;
		chomp($totalsize);
		localdie("FATAL: can't get size of remote file, please check what's going wrong with command: $curl_command --head \"$logf\" | grep \"Content-Length:\"\n") if ($totalsize eq '');
		&logmsg('DEBUG', "With http access size real size of a compressed file is unknown but use Content-Length wirth compressed side.");
		# For all compressed file we don't know the
		# real size apply deflate estimation factor
		if ($logf =~ /\.bz2$/i)
		{
			# apply deflate estimation factor
			$totalsize *= $BZ_FACTOR;
		}
		elsif ($logf =~ /\.(zip|gz)$/i)
		{
			$totalsize *= $GZ_FACTOR;
		}
		elsif ($logf =~ /\.(xz|lz4|zst)$/i)
		{
			$totalsize *= $XZ_FACTOR;
		}
	}

	return $totalsize;
}

sub uncompress_commands
{
	my $file = shift();

	return if (!$file);

	my $uncompress = $zcat;
	my $sample_cmd = 'zgrep';
	if (($file =~ /\.bz2/i) && ($zcat =~ /^$zcat_cmd$/))
	{
		$uncompress = $bzcat;
		$sample_cmd = 'bzgrep';
	} elsif (($file =~ /\.zip/i) && ($zcat =~ /^$zcat_cmd$/)) {
		$uncompress = $ucat;
	} elsif (($file =~ /\.lz4/i) && ($zcat =~ /^$zcat_cmd$/)) {
		$uncompress = $lz4cat;
	} elsif (($file =~ /\.zst/i) && ($zcat =~ /^$zcat_cmd$/)) {
		$uncompress = $zstdcat;
	}
	elsif (($file =~ /\.xz/i) && ($zcat =~ /^$zcat_cmd$/))
	{
		$uncompress = $xzcat;
		$sample_cmd = 'xzgrep';
	}

	return ($uncompress, $sample_cmd);
}

sub get_log_file
{
	my ($logf, $totalsize, $sample_only) = @_;

	my $lfile = undef;

	$LOG_EOL_TYPE = 'LF';

	return $lfile if ($totalsize == 0);

	$logf =~ s/:(stderr|csv|syslog|pgbouncer|jsonlog|logplex|rds|redshift)\d*$//i;

	my $http_download  = ($logf =~ /^(http[s]*:|[s]*ftp:)/i) ? 1 : 0;
	my $ssh_download   = ($logf =~ /^ssh:/i) ? 1 : 0;
	my $iscompressed   = ($logf =~ $compress_extensions) ? 1 : 0;

	chomp($logf);

	# Open and return a file handle to parse the log
	if ( $journalctl_cmd && ($logf =~ m/\Q$journalctl_cmd\E/) )
	{
		# For journalctl command we need to use a pipe as file handle
		if (!$remote_host) {
			open($lfile, '-|', $logf) || localdie("FATAL: cannot read output of command: $logf. $!\n");
		}
		else
		{
			if (!$sample_only)
			{
				&logmsg('DEBUG', "Retrieving log entries using command: $remote_command \"$logf\" |");
				# Open a pipe to remote journalctl program
				open($lfile, '-|', "$remote_command \"$logf\"") || localdie("FATAL: cannot read from pipe to $remote_command \"$logf\". $!\n");
			}
			else
			{
				&logmsg('DEBUG', "Retrieving log entries using command: $remote_command \"'$logf' -n 100\" |");
				# Open a pipe to remote journalctl program
				open($lfile, '-|', "$remote_command \"'$logf' -n 100\"") || localdie("FATAL: cannot read from pipe to $remote_command \"'$logf' -n 100\". $!\n");
			}
		}
	}
	elsif ( $log_command && ($logf =~ m/\Q$log_command\E/) )
	{
		# For custom command we need to use a pipe as file handle
		if (!$remote_host) {
			open($lfile, '-|', $logf) || localdie("FATAL: cannot read output of command: $logf. $!\n");
		}
		else
		{
			if (!$sample_only)
			{
				&logmsg('DEBUG', "Retrieving log entries using command: $remote_command \"$logf\" |");
				# Open a pipe to remote custom program
				open($lfile, '-|', "$remote_command \"$logf\"") || localdie("FATAL: cannot read from pipe to $remote_command \"$logf\". $!\n");
			}
			else
			{
				&logmsg('DEBUG', "Retrieving log entries using command: $remote_command \"'$logf' -n 100\" |");
				# Open a pipe to remote custom program
				open($lfile, '-|', "$remote_command \"'$logf' -n 100\"") || localdie("FATAL: cannot read from pipe to $remote_command \"'$logf' -n 100\". $!\n");
			}
		}
	}
	elsif (!$iscompressed)
	{
		if (!$remote_host && !$http_download && !$ssh_download)
		{
			if ($logf ne '-')
			{
				$LOG_EOL_TYPE = &get_eol_type($logf);
				open($lfile, '<', $logf) || localdie("FATAL: cannot read log file $logf. $!\n");
			}
			else
			{
				 $lfile = *STDIN;
			}
		}
		else
		{
			if (!$sample_only)
			{
				if (!$http_download)
				{
					if ($ssh_download && $logf =~ m#^ssh://([^\/]+)/(.*)#i)
					{
						my $host_info = $1;
						my $file = $2;
						if ($host_info =~ s/:(\d+)$//) {
							$host_info = "-p $1 $host_info";
						}
						my $ssh = $ssh_command || 'ssh';
						$ssh .= " -i $ssh_identity" if ($ssh_identity);
						$ssh .= " $ssh_options" if ($ssh_options);
						&logmsg('DEBUG', "Retrieving log entries using command: $ssh $host_info \"cat '$file'\" |");
						# Open a pipe to cat program
						open($lfile, '-|', "$ssh $host_info \"cat '$file'\"") || localdie("FATAL: cannot read from pipe to $ssh $host_info \"cat '$file'\". $!\n");
					}
					else
					{
						&logmsg('DEBUG', "Retrieving log entries using command: $remote_command \" cat '$logf'\" |");
						# Open a pipe to cat program
						open($lfile, '-|', "$remote_command \"cat '$logf'\"") || localdie("FATAL: cannot read from pipe to $remote_command \"cat '$logf'\". $!\n");
					}
				}
				else
				{
					&logmsg('DEBUG', "Retrieving log entries using command: $curl_command --data-binary \"$logf\" |");
					# Open a pipe to GET program
					open($lfile, '-|', "$curl_command \"$logf\"") || localdie("FATAL: cannot read from pipe to $curl_command --data-binary \"$logf\". $!\n");
				}
			}
			elsif (!$http_download)
			{
				if ($ssh_download && $logf =~ m#^ssh://([^\/]+)/(.*)#i)
				{
					my $host_info = $1;
					my $file = $2;
					my $ssh = $ssh_command || 'ssh';
					if ($host_info =~ s/:(\d+)$//) {
						$host_info = "-p $1 $host_info";
					}
					$ssh .= " -i $ssh_identity" if ($ssh_identity);
					$ssh .= " $ssh_options" if ($ssh_options);
					&logmsg('DEBUG', "Retrieving log sample using command: $ssh $host_info \"tail -n 100 '$file'\" |");
					# Open a pipe to cat program
					open($lfile, '-|', "$ssh $host_info \"tail -n 100 '$file'\"") || localdie("FATAL: cannot read from pipe to $remote_command \"tail -n 100 '$logf'\". $!\n");
				}
				else
				{
					&logmsg('DEBUG', "Retrieving log sample using command: $remote_command \"tail -n 100 '$logf'\" |");
					# Open a pipe to cat program
					open($lfile, '-|', "$remote_command \"tail -n 100 '$logf'\"") || localdie("FATAL: cannot read from pipe to $remote_command \"tail -n 100 '$logf'\". $!\n");
				}
			}
			else
			{
				&logmsg('DEBUG', "Retrieving log sample using command: $curl_command --data-binary --max-filesize 102400 \"$logf\" |");
				# Open a pipe to GET program
				open($lfile, '-|', "$curl_command --data-binary --max-filesize 102400 \"$logf\"") || localdie("FATAL: cannot read from pipe to $curl_command --data-binary --max-filesize 102400 \"$logf\". $!\n");

			}
		}
	}
	else
	{
		my ($uncompress, $sample_cmd) = &uncompress_commands($logf);

		if (!$remote_host && !$http_download && !$ssh_download)
		{
			&logmsg('DEBUG', "Compressed log file, will use command: $uncompress \"$logf\"");
			# Open a pipe to zcat program for compressed log
			open($lfile, '-|', "$uncompress \"$logf\"") || localdie("FATAL: cannot read from pipe to $uncompress \"$logf\". $!\n");
		}
		else
		{
			if (!$sample_only)
			{
				if (!$http_download)
				{
					if ($ssh_download && $logf =~ m#^ssh://([^\/]+)/(.*)#i)
					{
						my $host_info = $1;
						my $file = $2;
						my $ssh = $ssh_command || 'ssh';
						if ($host_info =~ s/:(\d+)$//) {
							$host_info = "-p $1 $host_info";
						}
						$ssh .= " -i $ssh_identity" if ($ssh_identity);
						$ssh .= " $ssh_options" if ($ssh_options);
						&logmsg('DEBUG', "Compressed log file, will use command: $ssh $host_info \"$uncompress '$file'\"");
						# Open a pipe to zcat program for compressed log
						open($lfile, '-|', "$ssh $host_info \"$uncompress '$file'\"") || localdie("FATAL: cannot read from pipe to $remote_command \"$uncompress '$logf'\". $!\n");
					}
					else
					{
						&logmsg('DEBUG', "Compressed log file, will use command: $remote_command \"$uncompress '$logf'\"");
						# Open a pipe to zcat program for compressed log
						open($lfile, '-|', "$remote_command \"$uncompress '$logf'\"") || localdie("FATAL: cannot read from pipe to $remote_command \"$uncompress '$logf'\". $!\n");
					}
				}
				else
				{
					&logmsg('DEBUG', "Retrieving log entries using command: $curl_command \"$logf\" | $uncompress |");
					# Open a pipe to GET program
					open($lfile, '-|', "$curl_command \"$logf\" | $uncompress") || localdie("FATAL: cannot read from pipe to $curl_command \"$logf\". $!\n");
				}
			}
			elsif (!$http_download)
			{
				if ($ssh_download && $logf =~ m#^ssh://([^\/]+)/(.*)#i)
				{
					my $host_info = $1;
					my $file = $2;
					my $ssh = $ssh_command || 'ssh';
					if ($host_info =~ s/:(\d+)$//) {
						$host_info = "-p $1 $host_info";
					}
					$ssh .= " -i $ssh_identity" if ($ssh_identity);
					$ssh .= " $ssh_options" if ($ssh_options);
					&logmsg('DEBUG', "Compressed log file, will use command: $ssh $host_info \"$uncompress '$file'\"");
					# Open a pipe to zcat program for compressed log
					open($lfile, '-|', "$ssh $host_info \"$sample_cmd -m 100 '[1234567890]' '$file'\"") || localdie("FATAL: cannot read from pipe to $ssh $host_info \"$sample_cmd -m 100 '' '$file'\". $!\n");
				}
				else
				{
					&logmsg('DEBUG', "Compressed log file, will use command: $remote_command \"$uncompress '$logf'\"");
					# Open a pipe to zcat program for compressed log
					open($lfile, '-|', "$remote_command \"$sample_cmd -m 100 '[1234567890]' '$logf'\"") || localdie("FATAL: cannot read from pipe to $remote_command \"$sample_cmd -m 100 '' '$logf'\". $!\n");
				}
			}
			else
			{
				# Open a pipe to GET program
				open($lfile, '-|', "$curl_command --max-filesize 102400 \"$logf\" | $uncompress") || localdie("FATAL: cannot read from pipe to $curl_command --max-filesize 102400 \"$logf\" | $uncompress . $!\n");
			}
		}
	}

	return $lfile;
}

sub split_logfile
{
	my $logf = shift;
	my $totalsize = shift;
	my $saved_pos = shift;

	# CSV file can't be parsed using multiprocessing
	return (0, -1) if ( $format eq 'csv' );

	# Do not split the file if we don't know his size
	return (0, -1) if ($totalsize <= 0);

	my @chunks = (0);
	# Seek to the last saved position
	if ($last_parsed && $saved_pos) {
		if ($saved_pos < $totalsize) {
			$chunks[0] = $saved_pos;
		}
	}
	# With small files < 16MB splitting is inefficient
	if ($totalsize <= 16777216) {
		return ($chunks[0], $totalsize);
	}
	my $i = 1;
	my $lfile = &get_log_file($logf, $totalsize); # Get file handle to the file
	if (defined $lfile)
	{
		while ($i < $queue_size)
		{
			my $pos = int(($totalsize/$queue_size) * $i);
			if ($pos > $chunks[0])
			{
				$lfile->seek($pos, 0);
				# Move the offset to the BEGINNING of each line, because
				# the logic in process_file requires so
				$pos= $pos + length(<$lfile>) - 1;
				push(@chunks, $pos) if ($pos < $totalsize);
			}
			last if ($pos >= $totalsize);
			$i++;
		}
		$lfile->close();
	}
	push(@chunks, $totalsize);

	return @chunks;
}

# Return the week number of the year for a given date
sub get_week_number
{
	my ($year, $month, $day) = @_;

#       %U     The week number of the current year as a decimal number, range 00 to 53, starting with the first
#	      Sunday as the first day of week 01.
#       %V     The ISO 8601 week number (see NOTES) of the current year as a decimal number, range 01 to 53,
#	      where week 1 is the first week that has at least 4 days in the new year.
#       %W     The week number of the current year as a decimal number, range 00 to 53, starting with the first
#	      Monday as the first day of week 01.

	# Check if the date is valid first
	my $datefmt = POSIX::strftime("%Y-%m-%d", 1, 1, 1, $day, $month - 1, $year - 1900);
	if ($datefmt ne "$year-$month-$day") {
		return -1;
	}
	my $weekNumber = '';
	if (!$iso_week_number)
	{
		if (!$week_start_monday) {
			$weekNumber = POSIX::strftime("%U", 1, 1, 1, $day, $month - 1, $year - 1900);
		} else {
			$weekNumber = POSIX::strftime("%W", 1, 1, 1, $day, $month - 1, $year - 1900);
		}
	}
	else
	{
		$weekNumber = POSIX::strftime("%V", 1, 1, 1, $day, $month - 1, $year - 1900);
	}

	return sprintf("%02d", (!$iso_week_number) ? $weekNumber+1 : $weekNumber);
}

# Returns day number of the week of a given days
sub get_day_of_week
{
	my ($year, $month, $day) = @_;

#       %w     The day of the week as a decimal, range 0 to 6, Sunday being 0.

	my $weekDay = '';
	if (!$week_start_monday && !$iso_week_number) {
		# Start on sunday = 0
		$weekDay = POSIX::strftime("%w", 1,1,1,$day,--$month,$year-1900);
	} else {
		# Start on monday = 1
		$weekDay = POSIX::strftime("%w", 1,1,1,$day,--$month,$year-1900);
		$weekDay = (($weekDay+7)-1) % 7;
	}

	return $weekDay;
}

# Returns all days following the week number
sub get_wdays_per_month
{
	my $wn = shift;
	my ($year, $month) = split(/\-/, shift);
	my @months = ();
	my @retdays = ();

	$month ||= '01';
	push(@months, "$year$month");
	my $start_month = $month;
	if ($month eq '01') {
		unshift(@months, ($year - 1) . "12");
	} else {
		unshift(@months, $year . sprintf("%02d", $month - 1));
	}
	if ($month == 12) {
		push(@months, ($year+1) . "01");
	} else {
		push(@months, $year . sprintf("%02d", $month + 1));
	}

	foreach my $d (@months)
	{
		$d =~ /^(\d{4})(\d{2})$/;
		my $y = $1;
		my $m = $2;
		foreach my $day ("01" .. "31")
		{
			# Check if the date is valid first
			my $datefmt = POSIX::strftime("%Y-%m-%d", 1, 1, 1, $day, $m - 1, $y - 1900);
			if ($datefmt ne "$y-$m-$day") {
				next;
			}
			my $weekNumber = '';
			if (!$iso_week_number)
			{
				if (!$week_start_monday) {
					$weekNumber = POSIX::strftime("%U", 1, 1, 1, $day, $m - 1, $y - 1900);
				} else {
					$weekNumber = POSIX::strftime("%W", 1, 1, 1, $day, $m - 1, $y - 1900);
				}
			}
			else
			{
				$weekNumber = POSIX::strftime("%V", 1, 1, 1, $day, $m - 1, $y - 1900);
			}
			if (!$iso_week_number)
			{
				if ( ($weekNumber == $wn) || ( ($weekNumber eq '00') && (($wn == 1) || ($wn >= 52)) ) )
				{
					push(@retdays, "$year-$m-$day");
					return @retdays if ($#retdays == 6);
				}
			}
			else
			{
				if ( ($weekNumber == $wn) || ( ($weekNumber eq '01') && (($wn == 1) || ($wn >= 53)) ) )
				{
					push(@retdays, "$year-$m-$day");
					return @retdays if ($#retdays == 6);
				}
			}
			next if ($weekNumber > $wn);
		}
	}

	return @retdays;
}

sub IsLeapYear
{
	return ((($_[0] & 3) == 0) && (($_[0] % 100 != 0) || ($_[0] % 400 == 0)));
}

####
# Display calendar
####
sub get_calendar
{
	my ($curdb, $year, $month) = @_;

	my $str = "<table class=\"table table-striped table-hover table-condensed\">\n";
	my @wday = qw(Su Mo Tu We Th Fr Sa);
	my @std_day = qw(Su Mo Tu We Th Fr Sa);
	if ($week_start_monday || $iso_week_number) {
		@wday = qw(Mo Tu We Th Fr Sa Su);
		@std_day = qw(Mo Tu We Th Fr Sa Su);
	}
	my %day_lbl = ();
	for (my $i = 0; $i <= $#wday; $i++) {
		$day_lbl{$wday[$i]} = $wday[$i];
	}
	$str .= "<thead><tr><td>&nbsp;</td>";
	map { $str .= '<th>' . $day_lbl{$_} . '</th>'; } @wday;
	$str .= "</tr></thead>\n<tbody>\n";
	my @currow = ('','','','','','','');
	my $wd = 0;
	my $wn = 0;
	my $week = '';
	my $dest_dir = $html_outdir || $outdir;
	my $tmp_dir = "$dest_dir/$curdb";
	$tmp_dir = $dest_dir if (!$report_per_database);
	for my $d ("01" .. "31") {
		last if (($d == 31) && grep(/^$month$/, '04','06','09','11'));
		last if (($d == 30) && ($month eq '02'));
		last if (($d == 29) && ($month eq '02') && !&IsLeapYear($year));
		$wd = &get_day_of_week($year,$month,$d);
		$wn =  &get_week_number($year,$month,$d);
		next if ($wn == -1);
		if ( !-e "$tmp_dir/$year/$month/$d/index.html" ) {
			$currow[$wd] = "<td>$d</td>";
		} else {
			$currow[$wd] = "<td><a href=\"$year/$month/$d/index.html\" target=\"new\">$d</a></td>";
		}
		if ($wd == 6) {
			$week = sprintf("%02d", $wn);
			if (-e "$tmp_dir/$year/week-$week/index.html") {
				$week = "<th><a href=\"$year/week-$week/index.html\" target=\"new\">$week</a>&nbsp;</th>";
			} else {
				$week = "<th>$week</th>";
			}
			for (my $i = 0; $i <= $#currow; $i++) {
				$currow[$i] = "<td>&nbsp;</td>" if ($currow[$i] eq '');
			}
			$str .= "<tr>$week" . join('', @currow) . "</tr>\n";
			@currow = ('','','','','','','');
		}
	}
	if ( ($wd != 6) || ($currow[0] ne '') ) {
		$week = sprintf("%02d", $wn);
		if (-e "$tmp_dir/$year/week-$week/index.html") {
			$week = "<th><a href=\"$year/week-$week/index.html\" target=\"new\">$week</a>&nbsp;</th>";
		} else {
			$week = "<th>$week</th>";
		}
		for (my $i = 0; $i <= $#currow; $i++) {
			$currow[$i] = "<td>&nbsp;</td>" if ($currow[$i] eq '');
		}
		$str .= "<tr>$week" . join('', @currow) . "</tr>\n";
		@currow = ('','','','','','','');
	}
	$str .=  "</tbody>\n</table>\n";

	my %month_name = (
		'01' => 'January', '02' => 'February', '03' => 'March', '04' => 'April',
		'05' => 'May', '06' => 'June', '07' => 'July', '08' => 'August',
		'09' => 'September', '10' => 'October', '11' => 'November', '12' => 'December'
	);
	my $month_title = $month_name{$month};
	if (-f "$tmp_dir/$year/$month/index.html") {
		$month_title = "<a href=\"$year/$month/index.html\" target=\"new\">$month_name{$month}</a>";
	}
	return qq{
	      <div class="panel panel-default">
		<div class="panel-heading">
		<i class="fa fa-cogs fa-2x pull-left fa-border"></i>&nbsp;<h2>$month_title</h2>
		</div>
		<div class="panel-body">
		$str
		</div>
	      </div>
};

}

sub _gethostbyaddr
{
	my $ip = shift;

	my $host = undef;
	unless(exists $CACHE_DNS{$ip}) {
		eval {
			local $SIG{ALRM} = sub { die "DNS lookup timeout.\n"; };
			alarm($DNSLookupTimeout);
			$host = gethostbyaddr(inet_aton($ip), AF_INET);
			alarm(0);
		};
		if ($@) {
			$CACHE_DNS{$ip} = undef;
			#printf "_gethostbyaddr timeout : %s\n", $ip;
		}
		else {
			$CACHE_DNS{$ip} = $host;
			#printf "_gethostbyaddr success : %s (%s)\n", $ip, $host;
		}
	}

	return $CACHE_DNS{$ip} || $ip;

}

sub localdie
{
	my ($msg, $code) = @_;

	my ($package, $filename, $line) = caller;
	print STDERR "$msg    - Error at line $line\n";
	unlink("$PID_FILE");

	exit($code || 1);
}

####
# Skip unwanted lines
# Return 1 when the line must be excluded
# Return 1 if we are after the end timestamp
# Return 0 if this is a wanted line
####
sub skip_unwanted_line
{
	# do not report lines which are not at the specific times
	if ($#exclude_time >= 0)
	{
		my $found = 0;
		foreach (@exclude_time)
		{
			if ($prefix_vars{'t_timestamp'} =~ /$_/)
			{
				$found = 1;
				last;
			}
		}
		return 1 if ($found);
	}

	# Only reports lines that are at the specific times
	if ($#include_time >= 0)
	{
		my $found = 0;
		foreach (@include_time)
		{
			if ($prefix_vars{'t_timestamp'} !~ /$_/)
			{
				$found = 1;
				last;
			}
		}
		return 1 if ( $found );
	}

	# check begin or end time without the date
	# and extract the hour here, late, to get the timezone
	# already applied
	if ( $from_hour || $to_hour )
	{
		return 1 if ( $from_hour && ( $from_hour gt $prefix_vars{'t_time'} ) );
		return 1 if ( $to_hour   && ( $to_hour lt $prefix_vars{'t_time'} ) );
	}
	else
	{
		# check against date/timestamp
		return  1 if ($from && ($from gt $prefix_vars{'t_timestamp'}));
		return -1 if ($to   && ($to   lt $prefix_vars{'t_timestamp'}));
	}

	return 0;
}

sub change_timezone
{
	my ($y, $mo, $d, $h, $mi, $s) = @_;

	my $t = timegm_nocheck($s, $mi, $h, $d, $mo-1, $y-1900);
	$t += $log_timezone;
	($s, $mi, $h, $d, $mo, $y) = gmtime($t);

	return ($y+1900, sprintf("%02d", ++$mo), sprintf("%02d", $d), sprintf("%02d", $h), sprintf("%02d", $mi), sprintf("%02d", $s));
}

# Set the default extension and output format, load JSON Perl podule if required
# Force text output with normalized query list only and disable incremental report
# Set default filename of the output file
sub set_output_extension
{
	my ($od, $of, $ext, $db) = @_;

	if (!$ext)
	{
		if ($of =~ /\.bin/i)
		{
			$ext = 'binary';
		}
		elsif ($of =~ /\.json/i)
		{
			if (eval {require JSON::XS;1;} ne 1)
			{
				localdie("Can not save output in json format, please install Perl module JSON::XS first.\n");
			}
			else
			{
				JSON::XS->import();
			}
			$ext = 'json';
		}
		elsif ($of =~ /\.htm[l]*/i)
		{
			$ext = 'html';
		}
		elsif ($of)
		{
			$ext = 'txt';
		}
		else
		{
			$ext = 'html';
		}
	}
	elsif (lc($ext) eq 'json')
	{
		if (eval {require JSON::XS;1;} ne 1)
		{
			localdie("Can not save output in json format, please install Perl module JSON::XS first.\n");
		}
		else
		{
			JSON::XS->import();
		}
	}

	if ($dump_normalized_only || $dump_all_queries)
	{
		$ext = 'txt';
		$incremental = 0;
		$report_title = 'Normalized query report' if (!$report_title && !$dump_all_queries);
	}

	$of ||= 'out.' . $ext;

	# Append the current database name to the output file.
	$of = $db . '_' . $of if ($db && $report_per_database && $db ne $DBALL && $of ne '-');

	# Add the destination directory
	$of = $od . '/' . $of if ($od && $of !~ m#^\Q$od\E# && $of ne '-');

	&logmsg('DEBUG', "Output '$ext' reports will be written to $of") if (!$rebuild && !$report_per_database);

	return ($of, $ext);
}

# Set timezone
sub set_timezone
{
	my $init = shift;

	$timezone = ((0-$opt_timezone)*3600);
	$log_timezone = ((0-$opt_log_timezone)*3600);

	return if ($init);

	if (!$timezone && !$isUTC) {
		my @lt = localtime();
		# count TimeZone and Daylight Saving Time
		$timezone = timelocal(@lt) - timegm(@lt);
		&logmsg('DEBUG', "timezone not specified, using $timezone seconds" );
	}
}

sub maxlen_truncate
{
	if ($maxlength && length($_[0]) > $maxlength)
	{
		$_[0] = substr($_[0], 0, $maxlength);
		$_[0] =~ s/((?:[,\(=\~]|LIKE)\s*'[^']*)$/$1'/is if ($anonymize);
		$_[0] .= '[...]';
	}
}

# return 1 or 2 following the EOL type (CR, LF or CRLF)
sub get_eol_length
{
	return length($LOG_EOL_TYPE)/2;
}

####
# Return the type of EOL of a file: Mac (CR), Windows (CRLF), Linux (LF)
# Assume LF by default
####
sub get_eol_type
{
	my $file = shift;
	if (open(my $in, '<', $file))
	{
		binmode($in);  ## (added as an update)
		my ( $cr, $lf, $crlf ) = ( 0 ) x 3;
		my $c = '';
		while ( read($in, $c, 65536, 1) )
		{
			$lf += $c=~ tr/\x0A/\x0A/;
			$cr += $c =~ tr/\x0D/\x0D/;
			$crlf += $c =~ s/\x0D\x0A/xx/g ;
			$c = chop;
			$cr-- if ( $c eq "\x0D" );  # a final CR or LF will get counted
			$lf-- if ( $c eq "\x0A" );  #   again on the next iteration
		}
		close($in);
		$cr++ if ( $c eq "\x0D" );
		$lf++ if ( $c eq "\x0A" );

		if ($lf && !$cr) {
			return 'LF';
		} elsif ($cr && !$lf) {
			return 'CR';
		} elsif ($crlf) {
			return 'CRLF';
		}
	}
	else
	{
		print "WARNING: can't read file $file, $!\n";
	}
	return 'LF';
}

sub html_escape
{
	my $toencode = shift;

	return undef unless defined($toencode);

	utf8::encode($toencode) if utf8::is_utf8($toencode);
	$toencode=~s/([^a-zA-Z0-9_.~-])/uc sprintf("%%%02x",ord($1))/eg;

	return $toencode;
}

sub dump_raw_csv
{

	my $t_pid = shift;

	my $sep = ';';
	if ($csv_sep_char) {
		$sep = $csv_sep_char;
	}

	# CSV columns information:
	# ------------------------
	# timestamp without milliseconds
	# username
	# database name
	# Process id
	# Remote host
	# session id
	# Error severity
	# SQL state code
	# Query duration
	# user query / error message
	# bind parameters
	# application name
	# backend type
	# query id

	print "timestamp${sep}username${sep}dbname${sep}pid${sep}client${sep}sessionid${sep}loglevel${sep}sqlstate${sep}duration${sep}query/error${sep}parameters${sep}appname${sep}backendtype${sep}queryid\n" if (!$header_done);
	$header_done = 1;
	print "$cur_info{$t_pid}{timestamp}${sep}$cur_info{$t_pid}{dbuser}${sep}$cur_info{$t_pid}{dbname}${sep}";
	print "$cur_info{$t_pid}{pid}${sep}$cur_info{$t_pid}{dbclient}${sep}$cur_info{$t_pid}{session}${sep}";
	print "$cur_info{$t_pid}{loglevel}${sep}$cur_info{$t_pid}{sqlstate}${sep}$cur_info{$t_pid}{duration}${sep}";
	my $query = ($cur_info{$t_pid}{query} || $cur_lock_info{$t_pid}{query} || $cur_temp_info{$t_pid}{query}
	        || $cur_cancel_info{$t_pid}{query} || "plan:\n" .$cur_plan_info{$t_pid}{plan});
	$query =~ s/[\r\n]/\\n/gs;
	if ($query =~ /${sep}/) {
		$query =~ s/"/""/g;
		$query = '"' . $query . '"';
	}
	print $query . "${sep}";
	($cur_info{$t_pid}{parameters}) ? print "\"$cur_info{$t_pid}{parameters}\"${sep}" : print "${sep}";
	($cur_info{$t_pid}{dbappname}) ? print "\"$cur_info{$t_pid}{dbappname}\"${sep}" : print "${sep}";
	print "$cur_info{$t_pid}{backendtype}${sep}$cur_info{$t_pid}{queryid}\n";
}


# Inclusion of Perl package pgFormatter::Beautify.
{

package pgFormatter::Beautify;

use strict;
use warnings;
use warnings qw( FATAL );
use Encode qw( decode );
use utf8;

binmode STDIN, ':utf8';
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';

use Text::Wrap;

our $DEBUG = 0;
our $DEBUG_SP = 0;

# PostgreSQL functions that use a FROM clause
our @have_from_clause = qw( extract overlay substring trim );
our @extract_keywords = qw(century day decade dow doy epoch hour isodow isoyear microseconds millennium minute month quarter second timezone timezone_minute week year);

our $math_operators = qr{^(?:\+|\-|\*|\/|\%|\^|\|\/|\|\|\/|\!|\!\!|\@|\&|\||\#|\~|<<|>>)$};

=head1 NAME

pgFormatter::Beautify - Library for pretty-printing SQL queries

=head1 VERSION

Version 5.5

=cut

# Version of pgFormatter
our $VERSION = '5.5';

# Inclusion of code from Perl package SQL::Beautify
# Copyright (C) 2009 by Jonas Kramer
# Published under the terms of the Artistic License 2.0.

=head1 SYNOPSIS

This module can be used to reformat given SQL query, optionally anonymizing parameters.

Output can be either plain text, or it can be HTML with appropriate styles so that it can be displayed on a web page.

Example usage:

    my $beautifier = pgFormatter::Beautify->new();
    $beautifier->query( 'select a,b,c from d where e = f' );

    $beautifier->beautify();
    my $nice_txt = $beautifier->content();

    $beautifier->format('html');
    $beautifier->beautify();
    my $nice_html = $beautifier->content();

    $beautifier->format('html');
    $beautifier->anonymize();
    $beautifier->beautify();
    my $nice_anonymized_html = $beautifier->content();

    $beautifier->format();
    $beautifier->beautify();
    $beautifier->wrap_lines()
    my $wrapped_txt = $beautifier->content();

=head1 FUNCTIONS

=head2 new

Generic constructor - creates object, sets defaults, and reads config from given hash with options.

Takes options as hash. Following options are recognized:

=over

=item * break - String that is used for linebreaks. Default is "\n".

=item * colorize - if set to false CSS style will not be applied to html output. Used internally to display errors in CGI mode withour style.

=item * comma - set comma at beginning or end of a line in a parameter list

=over

=item end - put comma at end of the list (default)

=item start - put comma at beginning of the list

=back

=item * comma_break - add new-line after each comma in INSERT statements

=item * format - set beautify format to apply to the content (default: text)

=over

=item text - output content as plain/text (command line mode default)

=item html - output text/html with CSS style applied to content (CGI mode default)

=back

=item * functions - list (arrayref) of strings that are function names

=item * keywords - list (arrayref) of strings that are keywords

=item * multiline - use multi-line search for placeholder regex, see placeholder.

=item * no_comments - if set to true comments will be removed from query

=item * no_grouping - if set to true statements will not be grouped in a transaction, an extra newline character will be added between statements like outside a transaction.

=item * placeholder - use the specified regex to find code that must not be changed in the query.

=item * query - query to beautify

=item * rules - hash of rules - uses rule semantics from SQL::Beautify

=item * space - character(s) to be used as space for indentation

=item * spaces - how many spaces to use for indentation

=item * uc_functions - what to do with function names:

=over

=item 0 - do not change

=item 1 - change to lower case

=item 2 - change to upper case

=item 3 - change to Capitalized

=back

=item * separator - string used as dynamic code separator, default is single quote

=item * uc_keywords - what to do with keywords - meaning of value like with uc_functions

=item * uc_types - what to do with data types - meaning of value like with uc_functions

=item * wrap - wraps given keywords in pre- and post- markup. Specific docs in SQL::Beautify

=item * format_type - try an other formatting

=item * wrap_limit - wrap queries at a certain length

=item * wrap_after - number of column after which lists must be wrapped

=item * wrap_comment - apply wrapping to comments starting with --

=item * numbering - statement numbering as a comment before each query

=item * redshift - add Redshift keywords (obsolete, use --extra-keyword)

=item * no_extra_line - do not add an extra empty line at end of the output

=item * keep_newline - preserve empty line in plpgsql code 

=item * no_space_function - remove space before function call and open parenthesis

=back

For defaults, please check function L<set_defaults>.

=cut

sub new
{
    my $class   = shift;
    my %options = @_;

    our @have_from_clause = qw( extract overlay substring trim );
    our @extract_keywords = qw(century day decade dow doy epoch hour isodow isoyear microseconds millennium minute month quarter second timezone timezone_minute week year);
    our $math_operators = qr{^(?:\+|\-|\*|\/|\%|\^|\|\/|\|\|\/|\!|\!\!|\@|\&|\||\#|\~|<<|>>)$};

    my $self = bless {}, $class;
    $self->set_defaults();

    for my $key ( qw( query spaces space break wrap keywords functions rules uc_keywords uc_functions uc_types no_comments no_grouping placeholder multiline separator comma comma_break format colorize format_type wrap_limit wrap_after wrap_comment numbering redshift no_extra_line keep_newline no_space_function)) {
        $self->{ $key } = $options{ $key } if defined $options{ $key };
    }

    $self->_refresh_functions_re();

    # Make sure "break" is sensible
    $self->{ 'break' } = ' ' if $self->{ 'spaces' } == 0;

    # Initialize internal stuff.
    $self->{ '_level' } = 0;

    # Array to store placeholders values
    @{ $self->{ 'placeholder_values' } } = ();

    # Hash to store dynamic code
    %{ $self->{ 'dynamic_code' } } = ();

    # Hash to store and preserve constants
    %{ $self->{ 'keyword_constant' } } = ();

    # Hash to store and preserve aliases between double quote
    %{ $self->{ 'alias_constant' } } = ();

    # Check comma value, when invalid set to default: end
    if (lc($self->{ 'comma' }) ne 'start') {
        $self->{ 'comma' } = 'end';
    } else {
        $self->{ 'comma' } = lc($self->{ 'comma' });
    }

    $self->{ 'format' }        //= 'text';
    $self->{ 'colorize' }      //= 1;
    $self->{ 'format_type' }   //= 0;
    $self->{ 'wrap_limit' }    //= 0;
    $self->{ 'wrap_after' }    //= 0;
    $self->{ 'wrap_comment' }  //= 0;
    $self->{ 'no_extra_line' } //= 0;

    return $self;
}

=head2 query

Accessor to query string. Both reads:

    $object->query()

, and writes

    $object->query( $something )

=cut

sub query
{
    my $self      = shift;
    my $new_value = shift;

    $self->{ 'query' } = $new_value if defined $new_value;

    $self->{idx_code} = 0;

    # Replace any COMMENT constant between single quote 
    while ($self->{ 'query' } =~ s/IS\s+([EU]*'(?:[^;]*)')\s*;/IS TEXTVALUE$self->{idx_code};/is)
    {
        $self->{dynamic_code}{$self->{idx_code}} = $1;
	$self->{dynamic_code}{$self->{idx_code}} =~ s/([\n\r])\s+([EU]*'(?:[^']*)')/$1 . ($self->{ 'space' } x $self->{ 'spaces' }) . $2/gsei;
        $self->{idx_code}++;
    }

    # Replace any \\ by BSLHPGF
    $self->{ 'query' } =~ s/\\\\/BSLHPGF/sg;
    # Replace any \' by PGFBSLHQ
    $self->{ 'query' } =~ s/\\'/PGFBSLHQ/sg;
    # Replace any '' by PGFESCQ1
    while ($self->{ 'query' } =~ s/([^'])''([^'])/$1PGFESCQ1$2/s) {};
    # Replace any '''' by PGFESCQ1PGFESCQ1
    while ($self->{ 'query' } =~ s/([^'])''''([^'])/$1PGFESCQ1PGFESCQ1$2/s) {};
    # Replace any '...''' by '.*PGFESCQ1'
    while ($self->{ 'query' } =~ s/([^']'[^']+)''('[^'])/$1PGFESCQ1$2/s) {};
    # Replace any '''...' by 'PGFESCQ1.*'
    while ($self->{ 'query' } =~ s/([^']')''([^']+'[^'])/$1PGFESCQ1$2/s) {};
    # Replace any multiline '''...''' by 'PGFESCQ1...PGFESCQ1'
    $self->{ 'query' } =~ s/([^']')''([^']*)''('[^']|$)/$1PGFESCQ1$2PGFESCQ1$3/sg;
    # Replace any "" by PGFESCQ2
    while ($self->{ 'query' } =~ s/([^"])""([^"])/$1PGFESCQ2$2/s) {};

    # Replace aliases using double quote
    my $j = 0;
    while ($self->{ 'query' } =~ s/(\s+AS\s*)("+[^"]+"+)/$1PGFALIAS$j/is)
    {
	    $self->{ 'alias_constant' }{$j} = $2;
	    $j++;
    }

    # replace all constant between quote
    $j = 0;
    while ($self->{ 'query' } =~ s/('[^'\n\r]+')/AAKEYWCONST${j}AA/s)
    {
	    $self->{ 'keyword_constant' }{$j} = $1;
	    $j++;
    }

    # Fix false positive generated by code above.
    while ($self->{ 'query' } =~ s/(\s+AS\s+)AAKEYWCONST(\d+)AA/$1$self->{ 'keyword_constant' }{$2}/is) {
	    delete $self->{ 'keyword_constant' }{$2};
    };

    # Hide content of format() function when the code separator is not a single quote */
    my $i = 0;
    while ($self->{ 'query' } =~ s/\bformat\((\$(?:.*)?\$\s*)([,\)])/format\(CODEPARTB${i}CODEPARTB$2/i) {
        push(@{ $self->{ 'placeholder_values' } }, $1);
        $i++;
    }
    my %temp_placeholder = ();
    my @temp_content = split(/(CREATE(?:\s+OR\s+REPLACE)?\s+(?:FUNCTION|PROCEDURE)\s+)/i, $self->{ 'query' });
    if ($#temp_content > 0)
    {
        for (my $j = 0; $j <= $#temp_content; $j++)
	{
            next if ($temp_content[$j] =~ /^CREATE/i or $temp_content[$j] eq '');
	    # Replace single quote code delimiter into $PGFDLM$
	    if ($temp_content[$j] !~ s/(\s+AS\s+)'(\s+.*?;\s*)'/$1\$PGFDLM\$$2\$PGFDLM\$/is)
	    {
		    $temp_content[$j] =~ s/(\s+AS\s+)'(\s+.*?END[;]*\s*)'/$1\$PGFDLM\$$2\$PGFDLM\$/is;
	    }
	    # Remove any call too CREATE/DROP LANGUAGE to not break search of function code separator
	    $temp_content[$j] =~ s/(CREATE|DROP)\s+LANGUAGE\s+[^;]+;.*//is;
	    # Fix case where code separator with $ is associated to begin/end keywords
	    $temp_content[$j] =~ s/([^\s]+\$)(BEGIN\s)/$1 $2/igs;
	    $temp_content[$j] =~ s/(\sEND)(\$[^\s]+)/$1 $2/igs;
	    $temp_content[$j] =~ s/(CREATE|DROP)\s+LANGUAGE\s+[^;]+;.*//is;
            my $fctname = '';
            if ($temp_content[$j] =~ /^([^\s\(]+)/) {
                $fctname = lc($1);
            }
            next if (!$fctname);
            my $language = 'sql';
            if ($temp_content[$j] =~ /\s+LANGUAGE\s+[']*([^'\s;]+)[']*/is)
	    {
                $language = lc($1);
	        if ($language =~ /AAKEYWCONST(\d+)AA/i)
		{
		    $language = lc($self->{ 'keyword_constant' }{$1});
		    $language =~ s/'//g;
	        }
            }

            if ($language =~ /^internal$/i)
	    {
		    if ($temp_content[$j] =~ s/AS ('[^\']+')/AS CODEPARTB${i}CODEPARTB/is)
		    {
                            push(@{ $self->{ 'placeholder_values' } }, $1);
			    $i++;
		    }
	    }
	    # C function language with AS obj_file, link_symbol
	    elsif ($language =~ /^c$/i)
	    {
		    if ($temp_content[$j] =~ s/AS ('[^\']+')\s*,\s*('[^\']+')/AS CODEPARTB${i}CODEPARTB/is)
		    {
			    push(@{ $self->{ 'placeholder_values' } }, "$1, $2");
			    $i++;
		    }
	    }
            # if the function language is not SQL or PLPGSQL
	    elsif ($language !~ /^(?:plpg)?sql$/)
	    {
                # Try to find the code separator
	        my $tmp_str = $temp_content[$j];
                while ($tmp_str =~ s/\s+AS\s+([^\s]+)\s+//is)
		{
                    my $code_sep = quotemeta($1);
		    foreach my $k (@{ $self->{ 'keywords' } }) {
			    last if ($code_sep =~ s/\b$k$//i); 
		    }
		    next if (!$code_sep);
                    if ($tmp_str =~ /\s+$code_sep[\s;]+/)
		    {
                        while ( $temp_content[$j] =~ s/($code_sep(?:.+?)$code_sep)/CODEPART${i}CODEPART/s)
			{
                            push(@{ $self->{ 'placeholder_values' } }, $1);
                            $i++;
                        }
		        last;
                    }
                }
            }
        }
    }
    $self->{ 'query' } = join('', @temp_content);

    # Store values of code that must not be changed following the given placeholder
    if ($self->{ 'placeholder' })
    {
	if (!$self->{ 'multiline' }) 
	{
		while ( $self->{ 'query' } =~ s/($self->{ 'placeholder' })/PLACEHOLDER${i}PLACEHOLDER/)
		{
		    push(@{ $self->{ 'placeholder_values' } }, $1);
		    $i++;
	       }
       }
       else
       {
		while ( $self->{ 'query' } =~ s/($self->{ 'placeholder' })/PLACEHOLDER${i}PLACEHOLDER/s)
		{
		    push(@{ $self->{ 'placeholder_values' } }, $1);
		    $i++;
	       }
       }
    }

    # Replace dynamic code with placeholder
    $self->_remove_dynamic_code( \$self->{ 'query' }, $self->{ 'separator' } );

    # Replace operator with placeholder
    $self->_quote_operator( \$self->{ 'query' } );

    # Replace comment with not quote delimiter with placeholder
    $self->_quote_comment_stmt( \$self->{ 'query' } );

    return $self->{ 'query' };
}

=head2 content

Accessor to content of results. Must be called after $object->beautify().

This can be either plain text or html following the format asked by the
client with the $object->format() method.

=cut

sub content
{
    my $self      = shift;
    my $new_value = shift;

    $self->{ 'content' } = $new_value if defined $new_value;
    $self->{ 'content' } =~ s/\(\s+\(/\(\(/gs;

    # Replace placeholders with their original dynamic code
    $self->_restore_dynamic_code( \$self->{ 'content' } );

    # Replace placeholders with their original operator
    $self->_restore_operator( \$self->{ 'content' } );

    # Replace placeholders with their original string
    $self->_restore_comment_stmt( \$self->{ 'content' } );

    # Replace placeholders by their original values
    if ($#{ $self->{ 'placeholder_values' } } >= 0)
    {
        $self->{ 'content' } =~ s/PLACEHOLDER(\d+)PLACEHOLDER/$self->{ 'placeholder_values' }[$1]/igs;
        $self->{ 'content' } =~ s/CODEPART[B]*(\d+)CODEPART[B]*/$self->{ 'placeholder_values' }[$1]/igs;
    }

    $self->{ 'content' } =~ s/PGFALIAS(\d+)/$self->{ 'alias_constant' }{$1}/gs;

    while ( $self->{ 'content' } =~ s/AAKEYWCONST(\d+)AA/$self->{ 'keyword_constant' }{$1}/s ) {
	    delete $self->{ 'keyword_constant' }{$1};
    };

    # Replace any BSLHPGF by \\
    $self->{ 'content' } =~ s/BSLHPGF/\\\\/g;
    # Replace any PGFBSLHQ by \'
    $self->{ 'content' } =~ s/PGFBSLHQ/\\'/g;
    # Replace any $PGFDLM$ by code delimiter ' 
    $self->{ 'content' } =~ s/\$PGFDLM\$/'/g;

    # Replace any PGFESCQ1 by ''
    $self->{ 'content' } =~ s/PGFESCQ1/''/g;
    # Replace any PGFESCQ2 by ""
    $self->{ 'content' } =~ s/PGFESCQ2/""/g;

    return $self->{ 'content' };
}

=head2 highlight_code

Makes result html with styles set for highlighting.

=cut

sub highlight_code
{
    my ($self, $token, $last_token, $next_token) = @_;

    # Do not use uninitialized variable
    $last_token //= '';
    $next_token //= '';

    # Colorize operators
    while ( my ( $k, $v ) = each %{ $self->{ 'dict' }->{ 'symbols' } } ) {
        if ($token eq $k) {
            $token = '<span class="sy0">' . $v . '</span>';
            return $token;
        }
    }

    # lowercase/uppercase keywords taking care of function with same name
    if ( $self->_is_keyword( $token, $next_token, $last_token ) && (!$self->_is_function( $token, $last_token, $next_token ) || $next_token ne '(') ) {
        if ( $self->{ 'uc_keywords' } == 1 ) {
            $token = '<span class="kw1_l">' . $token . '</span>';
        } elsif ( $self->{ 'uc_keywords' } == 2 ) {
            $token = '<span class="kw1_u">' . $token . '</span>';
        } elsif ( $self->{ 'uc_keywords' } == 3 ) {
            $token = '<span class="kw1_c">' . $token . '</span>';
        } else {
            $token = '<span class="kw1">' . $token . '</span>';
        }
        return $token;
    }

    # lowercase/uppercase known functions or words followed by an open parenthesis
    # if the token is not a keyword, an open parenthesis or a comment
    if (($self->_is_function( $token, $last_token, $next_token ) && $next_token eq '(')
	    || (!$self->_is_keyword( $token, $next_token, $last_token ) && !$next_token eq '('
		    && $token ne '(' && !$self->_is_comment( $token )) ) {
        if ($self->{ 'uc_functions' } == 1) {
            $token = '<span class="kw2_l">' . $token . '</span>';
        } elsif ($self->{ 'uc_functions' } == 2) {
            $token = '<span class="kw2_u">' . $token . '</span>';
        } elsif ($self->{ 'uc_functions' } == 3) {
            $token = '<span class="kw2_c">' . $token . '</span>';
        } else {
            $token = '<span class="kw2">' . $token . '</span>';
        }
        return $token;
    }

    # Colorize STDIN/STDOUT in COPY statement
    if ( grep(/^\Q$token\E$/i, @{ $self->{ 'dict' }->{ 'copy_keywords' } }) ) {
        if ($self->{ 'uc_keywords' } == 1) {
            $token = '<span class="kw3_!">' . $token . '</span>';
        } elsif ($self->{ 'uc_keywords' } == 2) {
            $token = '<span class="kw3_u">' . $token . '</span>';
        } elsif ($self->{ 'uc_keywords' } == 3) {
            $token = '<span class="kw3_c">' . $token . '</span>';
        } else {
            $token = '<span class="kw3">' . $token . '</span>';
        }
        return $token;
    }

    # Colorize parenthesis
    if ( grep(/^\Q$token\E$/i, @{ $self->{ 'dict' }->{ 'brackets' } }) ) {
        $token = '<span class="br0">' . $token . '</span>';
        return $token;
    }

    # Colorize comment
    if ( $self->_is_comment( $token ) ) {
        $token = '<span class="br1">' . $token . '</span>';
        return $token;
    }

    # Colorize numbers
    $token =~ s/\b(\d+)\b/<span class="nu0">$1<\/span>/igs;

    # Colorize string
    $token =~ s/('.*?(?<!\\)')/<span class="st0">$1<\/span>/gs;
    $token =~ s/(`[^`]*`)/<span class="st0">$1<\/span>/gs;

    return $token;
}

=head2 tokenize_sql

Splits input SQL into tokens

Code lifted from SQL::Beautify

=cut

sub tokenize_sql
{
    my $self  = shift;
    my $query = shift;
    
    $query ||= $self->{ 'query' };

    # just in case it has not been called in the main script
    $query = $self->query() if (!$query);

    my $re = qr{
        (
		(?:\\(?:copyright|errverbose|gx|gexec|gset|gdesc|q|crosstabview|watch|\?|copy|qecho|echo|if|elif|else|endif|edit|ir|include_relative|include|warn|write|html|print|out|ef|ev|h|H|i|p|r|s|w|o|e|g|q|d(?:[aAbcCdDeEfFgilLmnoOpPrRstTuvwxy+]{0,3})?|l\+?|sf\+?|sv\+?|z|a|C|f|H|t|T|x|c|pset|connect|encoding|password|conninfo|cd|setenv|timing|prompt|reset|set|unset|lo_export|lo_import|lo_list|lo_unlink|\!))(?:$|[\n]|[\ \t](?:(?!\\(?:\\|pset|reset|connect|encoding|password|conninfo|cd|setenv|timing|prompt|set|unset|lo_export|lo_import|lo_list|lo_unlink|\!|copy|qecho|echo|edit|html|include_relative|include|print|out|warn|watch|write|q))[\ \t\S])*)        # psql meta-command
		|
		AAKEYWCONST\d+AA(?:\s+AAKEYWCONST\d+AA)+             # preserved multiple constants with newline
		|
		AAKEYWCONST\d+AA             # preserved constants
		|
		\/\/			# mysql delimiter ( $$ is handled later with PG code delimiters )
		|
		(?:COPY\s+[^\s]+\s+\((?:.*?)\\\.)		# COPY and its content
		|
		[^\s\(,]+\%(?:ROWTYPE|TYPE)      # single line comments
		|
		(?:\s*--)[\ \t\S]*      # single line comments
		|
		(?:\-\|\-) # range operator "is adjacent to"
		|
		(?:<\%|\%>|<<\->|<\->>|<\->)  # pg_trgm and some geometry operators
		|
		(?:\->>|\->|<\#>|\#>>|\#>|\?\&|\?\||\?|\@\?)  # Vector and Json Operators
		|
		(?:\#<=|\#>=|\#<>|\#<|\#=) # compares tinterval and reltime
		|
		(?:>>=|<<=) # inet operators
		|
		(?:!!|\@\@\@) # deprecated factorial and full text search  operators
		|
		(?:\|\|\/|\|\/) # square root and cube root
		|
		(?:\@\-\@|\@\@|\#\#|<<\||\|>>|\&<\||\&<|\|\&>|\&>|<\^|>\^|\?\#|\#|\?<\||\?\-\||\?\-|\?\|\||\?\||\@>|<\@|\~=)
                                 # Geometric Operators
		|
		(?:~<=~|~>=~|~>~|~<~) # string comparison for pattern matching operator families
		|
		(?:!~~|!~~\*|~~\*|~~) # LIKE operators
		|
		(?:!~\*|!~|~\*) # regular expression operators
		|
		(?:\*=|\*<>|\*<=|\*>=|\*<|\*>) # composite type comparison operators
		|
		(?:\d+e[\+\-]\d+) # signed exponents
		|
		(?:<>|<=>|>=|<=|=>|==|!=|:=|=|!|<<|>>|<|>|\|\||\||&&|&|\-|\+|\*(?!/)|/(?!\*)|\%|~|\^|\?) # operators and tests
		|
		[\[\]\(\),;.]            # punctuation (parenthesis, comma)
		|
		\"\"(?!\"")             # empty double quoted string
		|
		"[^\"\s]+"\.[^\"\s\(\)=<>!~\*&:\|\-\+\%\^\?\@\#\[\]\{\}\.,;']+ # fqdn identifier form "schema".table or "table".column
		|
		[^\"\s=<>!~\*&\(\):\|\-\+\%\^\?\@\#\[\]\{\}\.,;']+\."[^\"\s]+" # fqdn identifier form schema."table" or table."column"
		|
		"[^\"\s]+"\."[^\"\s]+" # fqdn identifier form "schema"."table" or "table"."column"
		|
		"(?>(?:(?>[^"\\]+)|""|\\.)*)+" # anything inside double quotes, ungreedy
		|
		`(?>(?:(?>[^`\\]+)|``|\\.)*)+` # anything inside backticks quotes, ungreedy
		|
		[EB]*'[^']+' # anything inside single quotes, ungreedy.
		|
		/\*[\ \t\r\n\S]*?\*/      # C style comments
		|
		(?:[\w:\@]+[\$]*[\w:\@]*(?:\.(?:\w+|\*)?)*) # words, standard named placeholders, db.table.*, db.*
		|
		(?:\$\w+\$)
                |
                (?: \$_\$ | \$\d+ | \${1,2} | \$\w+\$) # dollar expressions - eg $_$ $3 $$ $BODY$
                |
                (?:\r\n){2,}                      # empty line Windows
                |
                \n{2,}                      # empty line Unix
                |
                \r{2,}                      # empty line Mac
                |
                [\t\ ]+                 # any kind of white spaces
		|
		[^\s\*\/\-\\;:,]+                 # anything else
        )
    }ismx;

    my @query = grep { /\S/ } $query =~ m{$re}simxg;
    if ($self->{ 'keep_newline' }) {
	    @query = grep { /(?:\S|^[\r\n]+$)/ } $query =~ m{$re}simxg;
    }

    # Revert position when a comment is before a comma
    if ($self->{ 'comma' } eq 'end')
    {
	    for (my $i = 0; $i < ($#query - 1); $i++)
	    {
		if ($query[$i+1] eq ',' and $self->_is_comment($query[$i]))
		{
			$query[$i+1] = $query[$i];
			$query[$i] = ',';
		}
	    }
    }

    # Fix token split of negative numbers
    if ($#query > 2)
    {
        for (my $i = 2; $i <= $#query; $i++)
        {
	    if ($query[$i] =~ /^[\d\.]+$/ && $query[$i-1] =~ /^[\+\-]$/
			    and ($query[$i-2] =~ /$math_operators/ or $query[$i-2] =~ /^(?:,|\(|\[)$/
					or $self->_is_keyword( $query[$i-2]))
	    )
	    {
		    $query[$i] = $query[$i-1] . $query[$i];
		    $query[$i-1] = '';
	    }
        }
    }
    @query = grep(!/^$/, @query);

    #print STDERR "DEBUG KWDLIST: ", join(' | ', @query), "\n";

    return  @query if (wantarray);

    $self->{ '_tokens' } = \@query;
}

sub _pop_level
{
    my ($self, $token, $last_token) = @_;

    if ($DEBUG)
    {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_POP: line: $line => last=", ($last_token||''), ", token=$token\n";
    }

    return 0 if ($#{ $self->{ '_level_stack' } } == -1);

    return pop( @{ $self->{ '_level_stack' } } ) || 0;

}

sub _reset_level
{
    my ($self, $token, $last_token) = @_;

    if ($DEBUG)
    {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_RESET: line: $line => last=", ($last_token||''), ", token=$token\n";
    }

    @{ $self->{ '_level_stack' } } = ();
    $self->{ '_level' } = 0;
    $self->{ 'break' } = ' ' unless ( $self->{ 'spaces' } != 0 );
}

sub _set_level
{
    my ($self, $position, $token, $last_token) = @_;

    return 0 if (not defined $position);

    if ($DEBUG)
    {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_SET: line: $line => position=$position, last=", ($last_token||''), ", token=$token\n";
    }

    $self->{ '_level' } = ($position >= 0) ? $position : 0;
}

sub _push_level
{
    my ($self, $position, $token, $last_token) = @_;

    if ($DEBUG)
    {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_PUSH: line: $line => position=$position, last=", ($last_token||''), ", token=$token\n";
    }

    push(@{ $self->{ '_level_stack' } }, (($position >= 0) ? $position : 0));
}



sub _set_last
{
    my ($self, $token, $last_token) = @_;

    if ($DEBUG)
    {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_LAST: line: $line => last=", ($last_token||''), ", token=$token\n";
    }

    return $token;
}


=head2 beautify

Beautify SQL.

After calling this function, $object->content() will contain nicely indented result.

Code lifted from SQL::Beautify

=cut

sub beautify
{
    my $self = shift;

    # Use to store the token position in the array
    my $pos = 0;

    # Main variables used to store differents state
    $self->content( '' );
    $self->{ '_level' } = 0;
    $self->{ '_level_stack' } = [];
    $self->{ '_level_parenthesis' } = [];
    $self->{ '_new_line' }    = 1;
    $self->{ '_current_sql_stmt' } = '';
    $self->{ '_is_meta_command' } = 0;
    $self->{ '_fct_code_delimiter' } = '';
    $self->{ '_language_sql' } = 0;
    $self->{ '_first_when_in_case' } = 0;
    $self->{ '_is_in_if' } = 0;
    $self->{ '_is_in_conversion' } = 0;
    $self->{ '_is_in_case' } = 0;
    $self->{ '_is_in_where' } = 0;
    $self->{ '_is_in_from' } = 0;
    $self->{ '_is_in_join' } = 0;
    $self->{ '_is_in_create' } = 0;
    $self->{ '_is_in_create_schema' } = 0;
    $self->{ '_is_in_rule' } = 0;
    $self->{ '_is_in_create_function' } = 0;
    $self->{ '_is_in_drop_function' } = 0;
    $self->{ '_is_in_alter' } = 0;
    $self->{ '_is_in_trigger' } = 0;
    $self->{ '_is_in_publication' } = 0;
    $self->{ '_is_in_call' } = 0;
    $self->{ '_is_in_type' } = 0;
    $self->{ '_is_in_domain' } = 0;
    $self->{ '_is_in_declare' } = 0;
    $self->{ '_is_in_block' } = -1;
    $self->{ '_is_in_work' } = 0;
    $self->{ '_is_in_function' } = 0;
    $self->{ '_current_function' } = '';
    $self->{ '_is_in_statistics' } = 0;
    $self->{ '_is_in_cast' } = 0;
    $self->{ '_is_in_procedure' } = 0;
    $self->{ '_is_in_index' } = 0;
    $self->{ '_is_in_with' }  = 0;
    $self->{ '_is_in_explain' }  = 0;
    $self->{ '_is_in_overlaps' } = 0;
    $self->{ '_parenthesis_level' } = 0;
    $self->{ '_parenthesis_function_level' } = 0;
    $self->{ '_has_order_by' }  = 0;
    $self->{ '_is_in_order_by' }  = 0;
    $self->{ '_has_over_in_join' } = 0;
    $self->{ '_insert_values' } = 0;
    $self->{ '_is_in_constraint' } = 0;
    $self->{ '_is_in_distinct' } = 0;
    $self->{ '_is_in_array' } = 0;
    $self->{ '_is_in_filter' } = 0;
    $self->{ '_parenthesis_filter_level' } = 0;
    $self->{ '_is_in_within' } = 0;
    $self->{ '_is_in_grouping' } = 0;
    $self->{ '_is_in_partition' } = 0;
    $self->{ '_is_in_over' } = 0;
    $self->{ '_is_in_policy' } = 0;
    $self->{ '_is_in_truncate' } = 0;
    $self->{ '_is_in_using' } = 0;
    $self->{ '_and_level' } = 0;
    $self->{ '_col_count' } = 0;
    $self->{ '_is_in_drop' } = 0;
    $self->{ '_is_in_operator' } = 0;
    $self->{ '_is_in_exception' } = 0;
    $self->{ '_is_in_sub_query' } = 0;
    $self->{ '_is_in_fetch' } = 0;
    $self->{ '_is_in_aggregate' } = 0;
    $self->{ '_is_in_value' } = 0;
    $self->{ '_parenthesis_level_value' } = 0;
    $self->{ '_parenthesis_with_level' } = 0;
    $self->{ '_is_in_returns_table' } = 0;
    $self->{ '_has_limit' }  = 0;
    $self->{ '_not_a_type' } = 0;
    $self->{ 'stmt_number' } = 1;
    $self->{ '_is_subquery' } = 0;
    $self->{ '_mysql_delimiter' } = '';
    $self->{ '_is_in_generated' } = 0;
    $self->{ '_is_in_between' } = 0;
    $self->{ '_is_in_materialized' } = 0;

    @{ $self->{ '_begin_level' } } = ();

    my $last = '';
    $self->tokenize_sql();

    $self->{ 'content' } .= "-- Statement # $self->{ 'stmt_number' }\n" if ($self->{ 'numbering' } and $#{ $self->{ '_tokens' } } > 0);
    while ( defined( my $token = $self->_token ) )
    {
        my $rule = $self->_get_rule( $token );

	if ($self->{ 'keep_newline' } and $self->{ '_is_in_block' } >= 0 and $token =~ /^[\r\n]+$/s
		and defined $last and $last eq ';'
	)
	{
	     $self->_add_token( $token, $last );
	     next;
	}
	# Replace concat operator found in some SGBD into || for normalization
	if (lc($token) eq 'concat' && defined $self->_next_token() && $self->_next_token ne '(') {
		$token = '||';
	}
	# Case where a keyword is used as a column name.
        if ( $self->{ '_is_in_create' } > 1 and $self->_is_keyword( $token, $self->_next_token(), $last )
			and defined $self->_next_token and $self->_is_type($self->_next_token))
	{
		$self->_add_token($token, $last);
		$last = $self->_set_last($token, $last);
		next;
	
	}
	# COPY block
        if ( $token =~ /^COPY\s+[^\s]+\s+\(/i )
	{
                $self->_new_line($token,$last);
		$self->_add_token($token, $last);
                $self->_new_line($token,$last);
		$self->{ 'content' } .= "\n";
		$last = $self->_set_last($token, $last);
		next;
	}

	if (uc($token) eq 'BETWEEN')
	{
		$self->{ '_is_in_between' } = 1;
		$self->_add_token($token, $last);
		$last = $self->_set_last($token, $last);
		next;
	}

	# mark when we are processing a materialized view to avoid formating issue with parameters
	if (uc($token) eq 'MATERIALIZED' and uc($self->_next_token) eq 'VIEW') {
		$self->{ '_is_in_materialized' } = 1;
	}

        ####
        # Find if the current keyword is a known function name
        ####
        if (defined $last && $last && defined $self->_next_token and $self->_next_token eq '(')
	{
            my $word = lc($token);
            $word =~ s/^[^\.]+\.//;
            $word =~ s/^:://;
            if (uc($last) eq 'FUNCTION' and $token =~ /^\d+$/) {
                $self->{ '_is_in_function' }++;
	    } elsif ($word && exists $self->{ 'dict' }->{ 'pg_functions' }{$word}) {
		$self->{ '_current_function' } = $word;
                $self->{ '_is_in_function' }++ if ($self->{ '_is_in_create' } != 1 or $token =~ /^CAST$/i);
            # Try to detect user defined functions
	    } elsif ($last ne '*' and !$self->_is_keyword($token, $self->_next_token(), $last)
			    and (exists $self->{ 'dict' }->{ 'symbols' }{ $last }
				    or $last =~ /^\d+$/)
	    )
	    {
                $self->{ '_is_in_function' }++;
	    } elsif (uc($token) eq 'IN' and $self->{ '_tokens' }[1] !~ /^(SELECT|WITH|VALUES)$/i) {
                $self->{ '_is_in_function' }++;
	    # try to detect if this is a user function
	    } elsif (!$self->{ '_is_in_function' } and !$self->{ '_is_in_create' }
			    and !$self->_is_comment($token) and length($token) > 2 # lazy exclusion of operators/comma 
			    and $last !~ /^(?:AS|RECURSIVE|WITH|OPERATOR|INTO|TYPE|VIEW)/i
			    and !$self->_is_keyword($token, $self->_next_token(), $last))
	    {
                $self->{ '_is_in_function' }++;
	    }
        }

        ####
        # Set open parenthesis position to know if we
        # are in subqueries or function parameters
        ####
        if ( $token eq ')')
        {
	    $self->{ '_parenthesis_filter_level' }-- if ($self->{ '_parenthesis_filter_level' });
	    $self->{ '_parenthesis_with_level' }-- if ($self->{ '_parenthesis_with_level' });
	    $self->{ '_is_in_filter' } = 0 if (!$self->{ '_parenthesis_filter_level' });

            if (!$self->{ '_is_in_function' }) {
                $self->{ '_parenthesis_level' }-- if ($self->{ '_parenthesis_level' } > 0);
            } else {
                $self->{ '_parenthesis_function_level' }-- if ($self->{ '_parenthesis_function_level' } > 0);
                if (!$self->{ '_parenthesis_function_level' }) {
	            $self->_set_level(pop(@{ $self->{ '_level_parenthesis_function' } }) || 0, $token, $last);
		    $self->_over($token,$last) if (!$self->{ '_is_in_create' } && !$self->{ '_is_in_operator' } && !$self->{ '_is_in_alter' } and uc($self->_next_token($token,$last)||'') ne 'LOOP');
	        }
            }
	    $self->{ '_is_in_function' } = 0 if (!$self->{ '_parenthesis_function_level' });
	    $self->{ '_is_in_cast' } = 0 if ((not defined $self->_next_token or $self->_next_token !~ /^(WITH|WITHOUT)$/i) and (!$self->{ '_parenthesis_level' } or !$self->{ '_parenthesis_function_level' }));

	    if (!$self->{ '_parenthesis_level' } and $self->{ '_is_in_sub_query' } and defined $self->_next_token and (!$self->{ '_is_in_order_by' } or $self->_next_token =~ /^(FROM|GROUP)$/i)) {
		$self->{ '_is_in_sub_query' }--;
		$self->_back($token, $last);
	    }
            if ($self->{ '_is_in_value' }) {
                $self->{ '_parenthesis_level_value' }-- if ($self->{ '_parenthesis_level_value' });
	    }
        }
        elsif ( $token eq '(')
        {
	    $self->{ '_parenthesis_filter_level' }++ if ($self->{ '_is_in_filter' });
	    $self->{ '_parenthesis_with_level' }++ if ($self->{ '_is_in_with' });
            if ($self->{ '_is_in_function' }) {
                $self->{ '_parenthesis_function_level' }++;
	        push(@{ $self->{ '_level_parenthesis_function' } } , $self->{ '_level' }) if ($self->{ '_parenthesis_function_level' } == 1);
            } else {
                if (!$self->{ '_parenthesis_level' } && $self->{ '_is_in_from' }) {
                    push(@{ $self->{ '_level_parenthesis' } } , $self->{ '_level' });
                }
                $self->{ '_parenthesis_level' }++;
                if ($self->{ '_is_in_value' }) {
                    $self->{ '_parenthesis_level_value' }++;
		}
            }

	    if (defined $self->_next_token and $self->_next_token =~ /^(SELECT|WITH)$/i) {
		$self->{ '_is_in_sub_query' }++ if (defined $last and uc($last) ne 'AS');
	    }
        }

        ####
        # Control case where we have to add a newline, go back and
        # reset indentation after the last ) in the WITH statement
        ####
	if ($token =~ /^WITH$/i and (!defined $last or ($last ne ')' and $self->_next_token !~ /^(TIME|FUNCTION)/i)))
	{
		if (!$self->{ '_is_in_partition' } and !$self->{ '_is_in_publication' } and !$self->{ '_is_in_policy' })
		{
			$self->{ '_is_in_with' } = 1 if (!$self->{ '_is_in_using' } and !$self->{ '_is_in_materialized' }
					and uc($self->_next_token) ne 'ORDINALITY' and uc($last) ne 'START');
			$self->{ 'no_break' } = 1 if (uc($self->_next_token) eq 'ORDINALITY');
		}
		$self->{ '_is_in_materialized' } = 0;
        }
        elsif ($token =~ /^WITH$/i && uc($self->_next_token) eq 'ORDINALITY')
	{
		$self->{ 'no_break' } = 1;
	}
        elsif ($token =~ /^(AS|IS)$/i && defined $self->_next_token && $self->_next_token =~ /^(NOT|\()$/)
	{
	    $self->{ '_is_in_materialized' } = 0;
            $self->{ '_is_in_with' }++ if ($self->{ '_is_in_with' } == 1);
        }
        elsif ($self->{ '_is_in_create' } && $token =~ /^AS$/i && defined $self->_next_token && uc($self->_next_token) eq 'SELECT')
	{
	    $self->{ '_is_in_materialized' } = 0;
            $self->{ '_is_in_create' } = 0;
        }
        elsif ( $token eq '[' )
	{
            $self->{ '_is_in_array' }++;
        }
        elsif ( $token eq ']' )
	{
            $self->{ '_is_in_array' }-- if ($self->{ '_is_in_array' });
	}
        elsif ( $token eq ')' )
	{
            $self->{ '_has_order_by' } = 0;
	    if ($self->{ '_is_in_distinct' }) {
                    $self->_add_token( $token );
                    $self->_new_line($token,$last);
		    $self->{ '_is_in_distinct' } = 0;
		    $last = $self->_set_last($token, $last);
		    next;
	    }
	    $self->{ '_is_in_generated' } = 0 if ($self->{ '_is_in_create' } and $self->{ '_parenthesis_level' } == 1);
	    $self->{ '_is_in_using' } = 0 if ($self->{ '_is_in_using' } and !$self->{ '_parenthesis_level' } and !$self->{ '_is_in_policy' });
	    if (defined $self->_next_token and $self->_next_token !~ /^(AS|WITH|,)$/i
			    and (!$self->_is_comment($self->_next_token) or ($#{$self->{ '_tokens' }} >= 1 and $self->{ '_tokens' }[1] ne ','))
			    and !$self->{ '_parenthesis_with_level' })
	    {
		$self->{ '_is_in_with' } = 0;
	    }

	    if ($self->{ '_is_in_create' } > 1 and defined $self->_next_token
			    and uc($self->_next_token) eq 'AS' and !$self->{ '_is_in_with'})
	    {
	        $self->{ '_is_in_materialized' } = 0;
                $self->_new_line($token,$last) if ($last ne '(' and !$self->{ '_is_in_create' });
	    	if ($self->{ '_is_in_returns_table' } and !$self->{ '_parenthesis_level' })
		{
	            $self->{ '_is_in_returns_table' } = 0;
                    $self->_new_line($token,$last);
                    $self->_back($token, $last);
                    $self->_add_token( $token, $last );
		    $last = $self->_set_last($token, $last);
                    next;
		} else {
			$self->_over($token, $last) if ($self->{ '_is_in_procedure' });
		}
	    }
            if (($self->{ '_is_in_with' } > 1 || $self->{ '_is_in_operator' })
		    && !$self->{ '_parenthesis_level' } && !$self->{ '_parenthesis_with_level' }
		    && !$self->{ '_is_in_alter' } && !$self->{ '_is_in_policy' })
	    {
                $self->_new_line($token,$last) if (!$self->{ '_is_in_operator' } ||
			(!$self->{ '_is_in_drop' } and $self->_next_token eq ';'));

		if (!$self->{ '_is_in_operator' })
		{
                    $self->_set_level($self->_pop_level($token, $last), $token, $last);
                    $self->_back($token, $last);
	        }
                $self->_add_token( $token );
		if (!$self->{ '_is_in_operator' }) {
                    $self->_reset_level($token, $last);
	        }
                if ($self->{ '_is_in_with' })
		{
                    if (defined $self->_next_token && $self->_next_token eq ',') {
                        $self->{ '_is_in_with' } = 1;
                    } else {
                        $self->{ '_is_in_with' } = 0;
                    }
                }
		$last = $self->_set_last($token, $last);
                next;
            }
	}
	elsif (defined $self->_next_token && $self->_next_token eq '(')
	{
            $self->{ '_is_in_filter' } = 1 if (uc($token) eq 'FILTER');
	    $self->{ '_is_in_grouping' } = 1 if ($token =~ /^(GROUPING|ROLLUP)$/i);
        } 
        elsif ( uc($token) eq 'PASSING' and defined $self->_next_token && uc($self->_next_token) eq 'BY')
	{
            $self->{ '_has_order_by' } = 1;
        }

	# Explain need indentation in option list
        if ( uc($token) eq 'EXPLAIN' )
	{
	    $self->{ '_is_in_explain' }  = 1;
        }
	elsif ( uc($token) eq 'OVERLAPS' )
	{
		$self->{ '_is_in_overlaps' } = 1;
        } 

        ####
        # Set the current kind of statement parsed
        ####
        if ($token =~ /^(FUNCTION|PROCEDURE|SEQUENCE|INSERT|DELETE|UPDATE|SELECT|RAISE|ALTER|GRANT|REVOKE|COMMENT|DROP|RULE|COMMENT|LOCK)$/i) {
            my $k_stmt = uc($1);
	    $self->{ '_is_in_explain' }  = 0;
	    $self->{ '_is_in_where' } = 0;
            # Set current statement with taking care to exclude of SELECT ... FOR UPDATE
	    # statement and ON CONFLICT DO UPDATE.
            if ($k_stmt ne 'UPDATE' or (defined $self->_next_token and $self->_next_token ne ';' and $self->_next_token ne ')' and (not defined $last or $last !~ /^(DO|SHARE)$/i)))
	    {
                if ($k_stmt !~ /^(UPDATE|DELETE)$/i || !$self->{ '_is_in_create' })
		{
                    if ($self->{ '_current_sql_stmt' } !~ /^(GRANT|REVOKE)$/i and !$self->{ '_is_in_trigger' } and !$self->{ '_is_in_operator' } and !$self->{ '_is_in_alter' })
		    {
			if ($k_stmt ne 'COMMENT' or $self->_next_token =~ /^(ON|IS)$/i)
			{
                            $self->{ '_current_sql_stmt' } = $k_stmt if (not defined $last or uc($last) ne 'WITH');
		        }
		    }
                }
            }
        }

        ####
        # Mark that we are in CREATE statement that need newline
        # after a comma in the parameter, declare or column lists.
        ####
        if ($token =~ /^(FUNCTION|PROCEDURE)$/i and $self->{ '_is_in_create' } and !$self->{'_is_in_trigger'}) {
		$self->{ '_is_in_create_function' } = 1;
	} elsif ($token =~ /^(FUNCTION|PROCEDURE)$/i and defined $last and uc($last) eq 'DROP') {
		$self->{ '_is_in_drop_function' } = 1;
	} elsif ($token =~ /^(FUNCTION|PROCEDURE)$/i and $self->{'_is_in_trigger'}) {
		$self->{ '_is_in_index' } = 1;
	}
        if ($token =~ /^CREATE$/i and defined $self->_next_token && $self->_next_token !~ /^(EVENT|UNIQUE|INDEX|EXTENSION|TYPE|PUBLICATION|OPERATOR|RULE|CONVERSION|DOMAIN)$/i)
	{
            if ($self->_next_token =~ /^SCHEMA$/i) {
	        $self->{ '_is_in_create_schema' } = 1;
	    }
	    elsif ($self->{ '_is_in_create_schema' })
	    {
		# we are certainly in a create schema statement
		$self->_new_line($token,$last);
		$self->{ '_level' } = 1;
		$self->{ '_is_in_create_schema' }++;
	    }
	    $self->{ '_is_in_create' } = 1;
        } elsif ($token =~ /^CREATE$/i and defined $self->_next_token && $self->_next_token =~ /^RULE$/i) {
	    $self->{ '_is_in_rule' } = 1;
        } elsif ($token =~ /^CREATE$/i and defined $self->_next_token && $self->_next_token =~ /^EVENT$/i) {
	    $self->{ '_is_in_trigger' } = 1;
        } elsif ($token =~ /^CREATE$/i and defined $self->_next_token && $self->_next_token =~ /^TYPE$/i) {
            $self->{ '_is_in_type' } = 1;
        } elsif ($token =~ /^CREATE$/i and defined $self->_next_token && $self->_next_token =~ /^DOMAIN$/i) {
            $self->{ '_is_in_domain' } = 1;
        } elsif ($token =~ /^CREATE$/i and defined $self->_next_token && $self->_next_token =~ /^PUBLICATION$/i) {
            $self->{ '_is_in_publication' } = 1;
        } elsif ($token =~ /^CREATE$/i and defined $self->_next_token && $self->_next_token =~ /^CONVERSION$/i) {
	    $self->{ '_is_in_conversion' } = 1;
        } elsif ($token =~ /^(CREATE|DROP)$/i and defined $self->_next_token && $self->_next_token =~ /^OPERATOR$/i) {
	    $self->{ '_is_in_operator' } = 1;
            $self->{ '_is_in_drop' } = 1 if ($token =~ /^DROP$/i);
        } elsif ($token =~ /^ALTER$/i) {
            $self->{ '_is_in_alter' }++;
        } elsif ($token =~ /^DROP$/i){
            $self->{ '_is_in_drop' } = 1;
        } elsif ($token =~ /^VIEW$/i and $self->{ '_is_in_create' }) {
            $self->{ '_is_in_index' } = 1;
	    $self->{ '_is_in_create' } = 0;
        } elsif ($token =~ /^STATISTICS$/i and $self->{ '_is_in_create' }) {
            $self->{ '_is_in_statistics' } = 1;
            $self->{ '_is_in_create' } = 0;
        } elsif ($token =~ /^CAST$/i and defined $self->_next_token and $self->_next_token eq '(') {
            $self->{ '_is_in_cast' } = 1;
        } elsif ($token =~ /^AGGREGATE$/i and $self->{ '_is_in_create' }) {
            $self->{ '_is_in_aggregate' } = 1;
            $self->{ '_has_order_by' } = 1;
        } elsif ($token =~ /^EVENT$/i and defined $self->_next_token && $self->_next_token =~ /^TRIGGER$/i) {
	    $self->_over($token, $last);
            $self->{ '_is_in_index' } = 1;
        } elsif ($token =~ /^CREATE$/i and defined $self->_next_token && $self->_next_token =~ /^INDEX|UNIQUE/i)
	{
	    if ($self->{ '_is_in_create_schema' })
	    {
		    $self->_new_line($token,$last);
		    $self->{ '_level' } = 1;
		    $self->{ '_is_in_create_schema' }++;
	    }
        }

	if ($self->{ '_is_in_using' } and defined $self->_next_token and $self->_next_token =~ /^(OPERATOR|AS)$/i) {
		$self->{ '_is_in_using' } = 0;
	}

        if ($token =~ /^ALTER$/i and $self->{ '_is_in_alter' } > 1) {
	    $self->_new_line($token,$last);
	    $self->_over($token, $last) if ($last ne ',');
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
            next;
        }

	# Special case for MySQL delimiter
        if ( uc($token) eq 'DELIMITER' && defined $self->_next_token &&
		($self->_next_token eq '//' or $self->_next_token eq '$$'))
        {
		$self->{ '_mysql_delimiter' } = $self->_next_token;
	}
	elsif (uc($token) eq 'DELIMITER' && defined $self->_next_token &&
		$self->_next_token eq ';')
	{
		$self->{ '_mysql_delimiter' } = '';
	}
	# case of the delimiter alone
	if ($self->{ '_mysql_delimiter' } && $token eq $self->{ '_mysql_delimiter' })
	{
	    $self->{ 'content' } =~ s/\n\n$/\n/s;
            $self->_add_token( $token );
	    $self->_new_line($token,$last);
            $last = $self->_set_last(';', $last);
	    next
	}

	####
	# Mark that we are in a CALL statement to remove any new line
	####
	if ($token =~ /^CALL$/i) {
	    $self->{ '_is_in_call' } = 1;
	}

	# Increment operator tag to add newline in alter operator statement
        if (($self->{ '_is_in_alter' } or uc($last) eq 'AS') and uc($token) eq 'OPERATOR') {
	    $self->_new_line($token,$last) if (uc($last) eq 'AS' and uc($token) eq 'OPERATOR');
	    $self->{ '_is_in_operator' }++;
        }

        ####
        # Mark that we are in index/constraint creation statement to
        # avoid inserting a newline after comma and AND/OR keywords.
        # This also used in SET statement taking care that we are not
        # in update statement. CREATE statement are not subject to this rule
        ####
        if (! $self->{ '_is_in_create' } and $token =~ /^(INDEX|PRIMARY|CONSTRAINT)$/i) {
            $self->{ '_is_in_index' } = 1 if ($last =~ /^(ALTER|CREATE|UNIQUE|USING|ADD)$/i);
        } elsif (! $self->{ '_is_in_create' } and uc($token) eq 'SET') {
            $self->{ '_is_in_index' } = 1 if ($self->{ '_current_sql_stmt' } ne 'UPDATE');
        } elsif ($self->{ '_is_in_create' } and (uc($token) eq 'UNIQUE' or ($token =~ /^(PRIMARY|FOREIGN)$/i and uc($self->_next_token) eq 'KEY'))) {
		$self->{ '_is_in_constraint' } = 1;
	}

        # Same as above but for ALTER FUNCTION/PROCEDURE/SEQUENCE or when
        # we are in a CREATE FUNCTION/PROCEDURE statement
        elsif ($token =~ /^(FUNCTION|PROCEDURE|SEQUENCE)$/i and !$self->{'_is_in_trigger'}) {
            $self->{ '_is_in_index' } = 1 if (uc($last) eq 'ALTER' and !$self->{ '_is_in_operator' } and !$self->{ '_is_in_alter' });
            if ($token =~ /^FUNCTION$/i && ($self->{ '_is_in_create' } || $self->{ '_current_sql_stmt' } eq 'COMMENT')) {
                $self->{ '_is_in_index' } = 1 if (!$self->{ '_is_in_operator' });
	    } elsif ($token =~ /^PROCEDURE$/i && $self->{ '_is_in_create' }) {
                $self->{ '_is_in_index' } = 1;
		$self->{ '_is_in_procedure' } = 1;
            }
        }
        # Desactivate index like formatting when RETURN(S) keyword is found
        elsif ($token =~ /^(RETURN|RETURNS)$/i)
	{
            $self->{ '_is_in_index' } = 0;
	    if (uc($token) eq 'RETURNS' and uc ($self->_next_token()) eq 'TABLE') {
		    $self->{ '_is_in_returns_table' } = 1;
	    }
        }
	elsif ($token =~ /^AS$/i)
	{
	    $self->{ '_is_in_materialized' } = 0;
            if ( !$self->{ '_is_in_index' } and $self->{ '_is_in_from' } and $last eq ')' and uc($token) eq 'AS' and $self->_next_token() eq '(') {
                $self->{ '_is_in_index' } = 1;
            } else {
                $self->{ '_is_in_index' } = 0;
            }
	    $self->{ '_is_in_block' } = 1 if ($self->{ '_is_in_procedure' });
	    $self->{ '_is_in_over' } = 0;
        }

	if ($token =~ /^(BEGIN|DECLARE)$/i)
	{
            $self->{ '_is_in_create' }-- if ($self->{ '_is_in_create' });
	    if (uc($token) eq 'BEGIN')
	    {
	        push( @{ $self->{ '_begin_level' } }, ($#{ $self->{ '_begin_level' } } < 0) ? 0 : $self->{ '_level' } );
	    }
#	    $self->_add_token( $token );
#	    $self->_new_line($token,$last);
#	    $self->_over($token,$last);
#	    $last = $self->_set_last($token, $last);
#	    next;
	}
    
        ####
        # Mark statements that use string_agg() or group_concat() function
        # as statement that can have an ORDER BY clause inside the call to
        # prevent applying order by formatting.
        ####
        if ($token =~ /^(string_agg|group_concat|array_agg|percentile_cont)$/i) {
            $self->{ '_has_order_by' } = 1;
        } elsif ( $token =~ /^(?:GENERATED)$/i and $self->_next_token =~ /^(ALWAYS|BY)$/i ) {
	    $self->{ '_is_in_generated' } = 1;
        } elsif ( $token =~ /^(?:TRUNCATE)$/i ) {
            $self->{ 'no_break' } = 1;
        } elsif ( uc($token) eq 'IDENTITY' ) {
            $self->{ '_has_order_by' } = 0;
            $self->{ 'no_break' } = 0;
	    $self->{ '_is_in_generated' } = 0;
        } elsif ( $self->{ '_has_order_by' } and uc($token) eq 'ORDER' and $self->_next_token =~ /^BY$/i) {
	    $self->_add_token( $token, $last );
            $last = $self->_set_last($token, $last);
            next;
        } elsif ($self->{ '_has_order_by' } and uc($token) eq 'BY') {
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
            next;
        }
        elsif ($token =~ /^OVER$/i)
	{
            $self->_add_token( $token );
	    $self->{ '_is_in_over' } = 1;
	    $self->{ '_has_order_by' } = 1;
            $last = $self->_set_last($token, $last);
            next;
	}

	# Fix case where we don't knwon if we are outside a SQL function
	if (defined $last and uc($last) eq 'AS' and defined $self->_next_token and $self->_next_token eq ';'
			and $self->{ '_is_in_create_function' }) {
		$self->{ '_is_in_create_function' } = 0;
	}

        ####
        # Set function code delimiter, it can be any string found after
        # the AS keyword in function or procedure creation code
        ####
        # Toogle _fct_code_delimiter to force next token to be stored as the function code delimiter
        if (uc($token) eq 'AS' and (!$self->{ '_fct_code_delimiter' } || $self->_next_token =~ /CODEPART/)
                               and $self->{ '_current_sql_stmt' } =~ /^(FUNCTION|PROCEDURE)$/i)
        {
	    if ($self->{ '_is_in_create' } and !$self->{ '_is_in_with' } and !$self->{ '_is_in_cast' }
			    and $self->_next_token !~ /^(IMPLICIT|ASSIGNMENT)$/i)
	    {
                $self->_new_line($token,$last);
                $self->_add_token( $token );
		$self->_reset_level($token, $last) if ($self->_next_token !~ /CODEPARTB/);
	    } else {
                $self->_add_token( $token );
            }
	    if ($self->_next_token !~ /(CODEPART|IMPLICIT|ASSIGNMENT)/ || $self->_next_token =~ /^'/)
	    {
		if (!$self->{ '_is_in_cast' } and $self->{ '_is_in_create' })
		{
		    # extract potential code joined with the code separator
		    if ($self->{ '_tokens' }->[0] =~ s/^'(.)/$1/)
		    {
			$self->{ '_tokens' }->[0] =~ s/[;\s]*'$//;
			my @tmp_arr = $self->tokenize_sql($self->{ '_tokens' }->[0]);
			push(@tmp_arr, ";", "'");
			shift(@{ $self->{ '_tokens' } });
			unshift(@{ $self->{ '_tokens' } }, "'", @tmp_arr);
	            }
                    $self->{ '_fct_code_delimiter' } = '1';
	        }
	    }
            $self->{ '_is_in_create' } = 0;
            $last = $self->_set_last($token, $last);
            next;
        }
        elsif ($token =~ /^(INSTEAD|ALSO)$/i and defined $last and uc($last) eq 'DO')
	{
                $self->_add_token( $token );
                $self->_new_line($token,$last);
                $last = $self->_set_last($token, $last);
                next;
        }
        elsif ($token =~ /^DO$/i and defined $self->_next_token and $self->_next_token =~ /^(INSTEAD|ALSO|UPDATE|NOTHING)$/i)
	{
                $self->_new_line($token,$last);
		$self->_over($token,$last);
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
                next;
        }
        elsif ($token =~ /^DO$/i and !$self->{ '_fct_code_delimiter' } and $self->_next_token =~ /^\$[^\s]*/)
	{
		@{ $self->{ '_begin_level' } } = ();
                $self->{ '_fct_code_delimiter' } = '1';
		$self->{ '_is_in_create_function' } = 1;
                $self->_new_line($token,$last) if ($self->{ 'content' } !~ /\n$/s);
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
                next;
	}

        # Store function code delimiter
        if ($self->{ '_fct_code_delimiter' } eq '1')
	{
	    if ($self->_next_token =~ /CODEPART/) {
                $self->{ '_fct_code_delimiter' } = '0';
	    } elsif ($token =~ /^'.*'$/) {
	        $self->{ '_fct_code_delimiter' } = "'";
	    } else {
	        $self->{ '_fct_code_delimiter' } = $token;
	    }
            $self->_add_token( $token );
	    if (!$self->{ '_is_in_create_function' } or $self->_next_token ne ','
			    or $self->{ '_tokens' }[1] !~ /KEYWCONST/) {
		    $self->_new_line($token,$last);
	    }
	    if (defined $self->_next_token
			    and $self->_next_token !~ /^(DECLARE|BEGIN)$/i) {
		$self->_over($token,$last);
		$self->{ '_language_sql' } = 1;
	    }

	    if ($self->{ '_fct_code_delimiter' } eq "'")
	    {
                $self->{ '_is_in_block' } = -1;
                $self->{ '_is_in_exception' } = 0;
                $self->_reset_level($token, $last) if ($self->_next_token eq ';');
                $self->{ '_fct_code_delimiter' } = '';
                $self->{ '_current_sql_stmt' } = '';
		$self->{ '_is_in_procedure' } = 0;
		$self->{ '_is_in_function' } = 0;
		$self->{ '_is_in_create_function' } = 0;
		$self->{ '_language_sql' } = 0;
            }
            $last = $self->_set_last($token, $last);
            next;
        }

	# With SQL language the code delimiter can be include with the keyword, try to detect and fix it
	if ($self->{ '_fct_code_delimiter' } and $token =~ s/(.)\Q$self->{ '_fct_code_delimiter' }\E$/$1/)
	{
		unshift(@{ $self->{ '_tokens' } }, $self->{ '_fct_code_delimiter' });
	}

        # Desactivate the block mode when code delimiter is found for the second time
        if ($self->{ '_fct_code_delimiter' } && $token eq $self->{ '_fct_code_delimiter' })
	{
            $self->{ '_is_in_block' } = -1;
            $self->{ '_is_in_exception' } = 0;
	    $self->{ '_is_in_create_function' } = 0;
            $self->_reset_level($token, $last);
            $self->{ '_fct_code_delimiter' } = '';
            $self->{ '_current_sql_stmt' } = '';
	    $self->{ '_language_sql' } = 0;
            $self->_new_line($token,$last);
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
            next;
        }

        ####
        # Mark when we are parsing a DECLARE or a BLOCK section. When
        # entering a BLOCK section store the current indentation level
        ####
        if (uc($token) eq 'DECLARE' and $self->{ '_is_in_create_function' })
	{
	    $self->{ '_is_in_block' } = -1;
            $self->{ '_is_in_exception' } = 0;
            $self->{ '_is_in_declare' } = 1;
            $self->_reset_level($token, $last);
            $self->_new_line($token,$last);
            $self->_add_token( $token );
            $self->_new_line($token,$last);
            $self->_over($token,$last);
            $last = $self->_set_last($token, $last);
	    $self->{ '_is_in_create_function' } = 0;
            next;
        }
        elsif ( uc($token) eq 'BEGIN' )
	{
            $self->{ '_is_in_declare' } = 0;
            if ($self->{ '_is_in_block' } == -1) {
                $self->_reset_level($token, $last);
            }
            $self->_new_line($token,$last);
            $self->_add_token( $token );
	    if (defined $self->_next_token && $self->_next_token !~ /^(WORK|TRANSACTION|ISOLATION|;)$/i) {
		$self->_new_line($token,$last);
		$self->_over($token,$last);
                $self->{ '_is_in_block' }++;
                # Store current indent position to print END at the right level
		$self->_push_level($self->{ '_level' }, $token, $last);
            }
	    $self->{ '_is_in_work' }++ if (!$self->{ 'no_grouping' } and defined $self->_next_token && $self->_next_token =~ /^(WORK|TRANSACTION|ISOLATION|;)$/i);
            $last = $self->_set_last($token, $last);
            next;
        }
        elsif ( $token =~ /^(COMMIT|ROLLBACK)$/i and (not defined $last or uc($last) ne 'ON') and !$self->{ '_is_in_procedure' } )
	{
	    $self->{ '_is_in_work' } = 0;
	    $self->{ '_is_in_declare' } = 0;
	    $self->{ '_is_in_create_function' } = 0;
	    $self->_new_line($token,$last);
	    $self->_set_level($self->_pop_level($token, $last), $token, $last);
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    @{ $self->{ '_begin_level' } } = ();
            next;
        }
        elsif ( $token =~ /^(COMMIT|ROLLBACK)$/i and defined $self->_next_token and $self->_next_token eq ';' and $self->{ '_is_in_procedure' } )
	{
	    $self->_new_line($token,$last);
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    @{ $self->{ '_begin_level' } } = ();
	    next;
        }
        elsif ( $token =~ /^FETCH$/i and defined $last and $last eq ';')
	{
	    $self->_new_line($token,$last);
	    $self->_back($token, $last) if ($self->{ '_is_in_block' } == -1);
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    $self->{ '_is_in_fetch' } = 1;
            next;
        }

        ####
        # Special case where we want to add a newline into ) AS (
        ####
        if (uc($token) eq 'AS' and $last eq ')' and $self->_next_token eq '(')
	{
            $self->_new_line($token,$last);
        }
        # and before RETURNS with increasing indent level
	elsif (uc($token) eq 'RETURNS')
	{
            $self->_new_line($token,$last);
            $self->_over($token,$last) if (uc($self->_next_token) ne 'NULL');
        }
        # and before WINDOW
	elsif (uc($token) eq 'WINDOW')
	{
            $self->_new_line($token,$last);
	    $self->_set_level($self->_pop_level($token, $last), $token, $last);
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    $self->{ '_has_order_by' } = 1;
	    next;
        }

	# Treated DISTINCT as a modifier of the whole select clause, not only the first column only
	if (uc($token) eq 'ON' && defined $last && uc($last) eq 'DISTINCT')
	{
            $self->{ '_is_in_distinct' } = 1;
            $self->_over($token,$last);
        }
        elsif (uc($token) eq 'DISTINCT' && defined $last && uc($last) eq 'SELECT' && defined $self->_next_token && $self->_next_token !~ /^ON$/i)
        {
            $self->_add_token( $token );
            $self->_new_line($token,$last) if (!$self->{'wrap_after'});
            $self->_over($token,$last);
            $last = $self->_set_last($token, $last);
	    next;
        }

        if ( $rule )
	{
            $self->_process_rule( $rule, $token );
        }

        elsif ($token =~ /^(LANGUAGE|SECURITY|COST)$/i && !$self->{ '_is_in_alter' } && !$self->{ '_is_in_drop' } )
	{
	    @{ $self->{ '_begin_level' } } = ();
            $self->_new_line($token,$last) if (uc($token) ne 'SECURITY' or (defined $last and uc($last) ne 'LEVEL'));
            $self->_add_token( $token );
        }
        elsif ($token =~ /^PARTITION$/i && !$self->{ '_is_in_over' } && defined $last && $last ne '(')
	{
	    $self->{ '_is_in_partition' } = 1;
            if ($self->{ '_is_in_create' } && defined $last and $last eq ')')
	    {
                $self->_new_line($token,$last);
	        $self->_set_level($self->_pop_level($token, $last), $token, $last) if ($self->{ '_level' });
                $self->_add_token( $token );
	    }
	    else
	    {
                $self->_add_token( $token );
            }
        }
        elsif ($token =~ /^POLICY$/i)
	{
            $self->{ '_is_in_policy' } = 1;
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    next;
        }
        elsif ($token =~ /^TRUNCATE$/i && $self->_next_token !~ /^(TABLE|ONLY|,)$/i)
	{
            $self->{ '_is_in_truncate' } = 1;
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    my $str_tmp = join(' ', @{ $self->{ '_tokens' } });
	    $str_tmp =~ s/;.*//s;
	    if ($str_tmp =~ / , /s)
	    {
                $self->_new_line($token,$last);
                $self->_over($token,$last);
                $self->{ '_is_in_truncate' } = 2;
	    }
	    next;
        }
        elsif ($token =~ /^(TABLE|ONLY)$/i && uc($last) eq 'TRUNCATE')
	{
            $self->{ '_is_in_truncate' } = 1;
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    my $str_tmp = join(' ', @{ $self->{ '_tokens' } });
	    $str_tmp =~ s/;.*//s;
	    if ($str_tmp =~ / , /s)
	    {
                $self->_new_line($token,$last);
                $self->_over($token,$last);
                $self->{ '_is_in_truncate' } = 2;
	    }
	    next;
        }
        elsif ($token =~ /^(RESTART|CASCADE)$/i && $self->{ '_is_in_truncate' } == 2)
	{
            $self->_new_line($token,$last);
            $self->_back($token,$last);
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    next;
        }
        elsif ($token =~ /^TRIGGER$/i and defined $last and $last =~ /^(CREATE|CONSTRAINT|REPLACE)$/i)
	{
            $self->{ '_is_in_trigger' } = 1;
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    next;
        }
        elsif ($token =~ /^(BEFORE|AFTER|INSTEAD)$/i and $self->{ '_is_in_trigger' })
	{
            $self->_new_line($token,$last);
            $self->_over($token,$last);
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    next;
        }
        elsif ($token =~ /^EXECUTE$/i and ($self->{ '_is_in_trigger' } or (defined $last and uc($last) eq 'AS')))
	{
            $self->_new_line($token,$last);
            $self->_add_token( $token );
            $last = $self->_set_last($token, $last);
	    next;
        }
        elsif ( $token eq '(' )
	{
	    if ($self->{ '_is_in_aggregate' } && defined $self->_next_token and ($self->_is_keyword($self->_next_token) or $self->_is_sql_keyword($self->_next_token)) and uc($self->_next_token) ne 'VARIADIC') {
		$self->{ '_is_in_aggregate' } = 0;
                $self->{ '_has_order_by' } = 0;
	    }
            $self->{ '_is_in_create' }++ if ($self->{ '_is_in_create' });
            $self->{ '_is_in_constraint' }++ if ($self->{ '_is_in_constraint' });
            $self->_add_token( $token, $last );
	    if (defined $self->_next_token and uc($self->_next_token) eq 'SELECT')
	    {
	        $self->{ '_is_in_cast' } = 0;
	        $self->{ '_is_subquery' }++;
	    }
	    if (defined $self->_next_token and $self->_next_token eq ')' and !$self->{ '_is_in_create' }) {
		$last = $self->_set_last($token, $last);
		next;
	    }
            if ( !$self->{ '_is_in_index' } && !$self->{ '_is_in_publication' }
		    && !$self->{ '_is_in_distinct' } && !$self->{ '_is_in_filter' }
		    && !$self->{ '_is_in_grouping' } && !$self->{ '_is_in_partition' }
		    && !$self->{ '_is_in_over' } && !$self->{ '_is_in_trigger' }
		    && !$self->{ '_is_in_policy' } && !$self->{ '_is_in_aggregate' }
		    && !$self->{ 'no_break' } && !$self->{ '_is_in_generated' }
	    ) {
                if (uc($last) eq 'AS' || $self->{ '_is_in_create' } == 2 || uc($self->_next_token) eq 'CASE')
		{
                    $self->_new_line($token,$last) if ((!$self->{'_is_in_function'} or $self->_next_token =~ /^CASE$/i) and $self->_next_token ne ')' and $self->_next_token !~ /^(PARTITION|ORDER)$/i);
                }
                if ($self->{ '_is_in_with' } == 1 or $self->{ '_is_in_explain' }) {
                    $self->_over($token,$last);
                    $self->_new_line($token,$last) if (!$self->{ 'wrap_after' });
		    $last = $self->_set_last($token, $last) if (!$self->{ '_is_in_explain' } || $self->{ 'wrap_after' });
                    next;
                }
		if (!$self->{ '_is_in_if' } and !$self->{ '_is_in_alter' } and (!$self->{ '_is_in_function' } or $last ne '('))
		{
		    $self->_over($token,$last) if ($self->{ '_is_in_operator' } <= 2 && $self->{ '_is_in_create' } <= 2);
		    if (!$self->{ '_is_in_function' } and !$self->_is_type($self->_next_token))
		    {
		        if ($self->{ '_is_in_operator' } == 1) {
			    $self->_new_line($token,$last);
		            $self->{ '_is_in_operator' }++;
		        } elsif ($self->{ '_is_in_type' }) {
                            $self->_new_line($token,$last);
		        }
		    }
                    $last = $self->_set_last($token, $last);
		}
                if ($self->{ '_is_in_type' } == 1) {
                    $last = $self->_set_last($token, $last);
                    next;
                }
            }

	    if ($self->{ 'format_type' } && $self->{ '_current_sql_stmt' } =~ /(FUNCTION|PROCEDURE)/i
		    && $self->{ '_is_in_create' } == 2
		    && (not defined $self->_next_token or $self->_next_token ne ')')
	    ) {
                $self->_over($token,$last) if ($self->{ '_is_in_block' } < 0);
                $self->_new_line($token,$last);
                next;
	    }
        }

        elsif ( $token eq ')' )
	{
            if (defined $self->_next_token)
	    {
		my $next = quotemeta($self->_next_token) || 'SELECT';
		if (!$self->{ '_parenthesis_level' } and defined $self->_next_token
			    and $self->_is_keyword($self->_next_token) or (
				!grep(/^$next$/, %{$self->{ 'dict' }->{ 'symbols' }})
			)
		)
		{
		    $self->{ '_is_in_where' } = 0;
		}
	    }
	    if ($self->{ '_is_in_constraint' } and defined $self->_next_token
			    and ($self->_next_token eq ',' or $self->_next_token eq ')')) {
		$self->{ '_is_in_constraint' } = 0;
            } elsif ($self->{ '_is_in_constraint' }) {
		$self->{ '_is_in_constraint' }--;
	    }
	    # Case of CTE and explain
            if ($self->{ '_is_in_with' } == 1 || $self->{ '_is_in_explain' })
	    {
                $self->_back($token, $last);
	        $self->_new_line($token,$last) if (!$self->{ 'wrap_after' } && !$self->{ '_is_in_overlaps' });
                $self->_add_token( $token );
		$last = $self->_set_last($token, $last) if ($token ne ')' or uc($self->_next_token) ne 'AS');
		$self->{ '_is_in_explain' } = 0;
                next;
            }
	    if ( ($self->{ 'format_type' } && $self->{ '_current_sql_stmt' } =~ /(FUNCTION|PROCEDURE)/i
		    && $self->{ '_is_in_create' } == 2) || (defined $self->_next_token and uc($self->_next_token) eq 'INHERITS')
	    )
	    {
                $self->_back($token, $last) if ($self->{ '_is_in_block' } < 0);
                $self->_new_line($token,$last) if (defined $last && $last ne '(');
	    }
            if ($self->{ '_is_in_index' } || $self->{ '_is_in_alter' }
		    || $self->{ '_is_in_partition' } || $self->{ '_is_in_policy' }
		    || (defined $self->_next_token and $self->_next_token =~ /^OVER$/i)
	    ) {
                $self->_add_token( '' );
                $self->_add_token( $token );
		$self->{ '_is_in_over' } = 0 if (!$self->{ '_parenthesis_level' });
                $last = $self->_set_last($token, $last);
                $self->{ '_is_in_create' }-- if ($self->{ '_is_in_create' });
                next;
            }
	    if (defined $self->_next_token && $self->_next_token !~ /FILTER/i)
	    {
                my $add_nl = 0;
                $add_nl = 1 if ($self->{ '_is_in_create' } > 1
		    and defined $last and $last ne '('
		    and !$self->{ '_is_in_cast' }
                    and (not defined $self->_next_token or $self->_next_token =~ /^(TABLESPACE|PARTITION|AS|;)$/i or ($self->_next_token =~ /^ON$/i and !$self->{ '_parenthesis_level' }))
                );
                $add_nl = 1 if ($self->{ '_is_in_type' } == 1
		    and $self->_next_token !~ /^AS$/i
                    and (not defined $self->_next_token or $self->_next_token eq ';')
                );
                $add_nl = 1 if ($self->{ '_current_sql_stmt' } ne 'INSERT'
			    and !$self->{ '_is_in_function' }
			    and (defined $self->_next_token 
				    and $self->_next_token =~ /^(SELECT|WITH)$/i)
		    		    and $self->{ '_tokens' }[1] !~ /^(ORDINALITY|FUNCTION)$/i
			    and ($self->{ '_is_in_create' } or $last ne ')' and $last ne ']')
			    and (uc($self->_next_token) ne 'WITH' or uc($self->{ '_tokens' }->[ 1 ]) !~ /TIME|INOUT/i)
	        );
		$self->_new_line($token,$last) if ($add_nl);

                if (!$self->{ '_is_in_grouping' } and !$self->{ '_is_in_trigger' }
				and !$self->{ 'no_break' }
				and !$self->{ '_is_in_generated' }
				and $self->{ '_is_in_create' } <= 2
				and $self->_next_token !~ /^LOOP$/i
			)
		{
		    $self->_back($token, $last);
		}
                $self->{ '_is_in_create' }-- if ($self->{ '_is_in_create' });
		if ($self->{ '_is_in_type' })
		{
		    $self->_reset_level($token, $last) if ($self->{ '_is_in_block' } == -1 && !$self->{ '_parenthesis_level' });
                    $self->{ '_is_in_type' }--;
		}
	    }
	    if (!$self->{ '_parenthesis_level' })
	    {
                $self->{ '_is_in_filter' } = 0;
                $self->{ '_is_in_within' } = 0;
                $self->{ '_is_in_grouping' } = 0;
                $self->{ '_is_in_over' } = 0;
                $self->{ '_has_order_by' } = 0;
		$self->{ '_is_in_policy' } = 0;
                $self->{ '_is_in_aggregate' } = 0;
            } 
            $self->_add_token( $token );
            # Do not go further if this is the last token
            if (not defined $self->_next_token) {
                $last = $self->_set_last($token, $last);
                next;
            }

            # When closing CTE statement go back again
            if ( ($self->_next_token =~ /^(?:SELECT|INSERT|UPDATE|DELETE)$/i and !$self->{ '_is_in_policy' })
			    or ($self->{ '_is_in_with' } and $self->{ '_is_subquery' }
				    and $self->{ '_is_subquery' } % 2 == 0) )  {
                $self->_back($token, $last) if ($self->{ '_current_sql_stmt' } ne 'INSERT'
				and (!$self->{ '_parenthesis_level' } or !defined $self->_next_token
					or uc($self->_next_token) eq 'AS'
					or ($#{$self->{ '_tokens' }} >= 1 and $self->{ '_tokens' }->[ 1 ] eq ',')));
            }
	    $self->{ '_is_subquery' }-- if ($self->{ '_is_subquery' }
			    and defined $self->_next_token and $#{$self->{ '_tokens' }} >= 1
			    and (uc($self->_next_token) eq 'AS' or $self->{ '_tokens' }->[ 1 ] eq ','));
            if ($self->{ '_is_in_create' } <= 1)
	    {
                my $next_tok = quotemeta($self->_next_token);
                $self->_new_line($token,$last)
                    if (defined $self->_next_token
                    and $self->_next_token !~ /^(?:AS|IS|THEN|INTO|BETWEEN|ON|IN|FILTER|WITHIN|DESC|ASC|WITHOUT|CASCADE)$/i
                    and ($self->_next_token !~ /^(AND|OR)$/i or !$self->{ '_is_in_if' })
                    and $self->_next_token ne ')'
                    and $self->_next_token !~ /^:/
                    and $self->_next_token ne ';'
                    and $self->_next_token ne ','
                    and $self->_next_token ne '||'
                    and uc($self->_next_token) ne 'CONCAT'
                    and ($self->_is_keyword($self->_next_token) or $self->_is_function($self->_next_token))
		    and $self->{ '_current_sql_stmt' } !~ /^(GRANT|REVOKE)$/
                    and !exists  $self->{ 'dict' }->{ 'symbols' }{ $next_tok }
	    	    and !$self->{ '_is_in_over' }
	            and !$self->{ '_is_in_cast' }
	            and !$self->{ '_is_in_domain' }
                );
            }
        }

        elsif ( $token eq ',' )
	{
            my $add_newline = 0;
	    # Format INSERT with multiple values
	    if ($self->{ '_current_sql_stmt' } eq 'INSERT' and $last eq ')' and $self->_next_token eq '(') {
		    $self->_new_line($token,$last) if ($self->{ 'comma' } eq 'start');
		    $self->_add_token( $token );
		    $self->_new_line($token,$last) if ($self->{ 'comma' } eq 'end');
		    next;
	    }
	    $self->{ '_is_in_constraint' } = 0 if ($self->{ '_is_in_constraint' } == 1);
	    $self->{ '_col_count' }++ if (!$self->{ '_is_in_function' });
            if (($self->{ '_is_in_over' } or $self->{ '_has_order_by' }) and !$self->{ '_parenthesis_level' } and !$self->{ '_parenthesis_function_level' })
	    {
		    $self->{ '_is_in_over' } = 0;
		    $self->{ '_has_order_by' } = 0;
		    $self->_back($token, $last);
	    }
            $add_newline = 1 if ( !$self->{ 'no_break' }
		               && !$self->{ '_is_in_generated' }
                               && !$self->{ '_is_in_function' }
			       && !$self->{ '_is_in_distinct' }
			       && !$self->{ '_is_in_array' }
                               && ($self->{ 'comma_break' } || $self->{ '_current_sql_stmt' } ne 'INSERT')
                               && ($self->{ '_current_sql_stmt' } ne 'RAISE')
                               && ($self->{ '_current_sql_stmt' } !~ /^(FUNCTION|PROCEDURE)$/
				       || $self->{ '_fct_code_delimiter' } ne '')
                               && !$self->{ '_is_in_where' }
                               && !$self->{ '_is_in_drop' }
                               && !$self->{ '_is_in_index' }
                               && !$self->{ '_is_in_aggregate' }
			       && !$self->{ '_is_in_alter' }
			       && !$self->{ '_is_in_publication' }
			       && !$self->{ '_is_in_call' }
			       && !$self->{ '_is_in_policy' }
			       && !$self->{ '_is_in_grouping' }
			       && !$self->{ '_is_in_partition' }
			       && ($self->{ '_is_in_constraint' } <= 1)
			       && ($self->{ '_is_in_create' } <= 2)
			       && $self->{ '_is_in_operator' } != 1
			       && !$self->{ '_has_order_by' }
                               && $self->{ '_current_sql_stmt' } !~ /^(GRANT|REVOKE)$/
			       && ($self->_next_token !~ /^('$|\s*\-\-)/is or ($self->_next_token !~ /^'$/is and $self->{ 'no_comments' }))
                               && !$self->{ '_parenthesis_function_level' }
			       && (!$self->{ '_col_count' } or $self->{ '_col_count' } > ($self->{ 'wrap_after' } - 1))
                               || ($self->{ '_is_in_with' } and !$self->{ 'wrap_after' })
                    );
            $self->{ '_col_count' } = 0 if ($self->{ '_col_count' } > ($self->{ 'wrap_after' } - 1));
	    $add_newline = 0 if ($self->{ '_is_in_using' } and $self->{ '_parenthesis_level' });
	    $add_newline = 0 if ($self->{ 'no_break' });

            if ($self->{ '_is_in_with' } >= 1 && !$self->{ '_parenthesis_level' }) {
                $add_newline = 1 if (!$self->{ 'wrap_after' });
            }
	    if ($self->{ 'format_type' } && $self->{ '_current_sql_stmt' } =~ /(FUNCTION|PROCEDURE)/i && $self->{ '_is_in_create' } == 2) {
                $add_newline = 1;
	    }
            if ($self->{ '_is_in_alter' } && $self->{ '_is_in_operator' } >= 2) {
		$add_newline = 1 if (defined $self->_next_token and $self->_next_token =~ /^(OPERATOR|FUNCTION)$/i);
	    }
	    $add_newline = 1 if ($self->{ '_is_in_returns_table' });
	    $self->_new_line($token,$last) if ($add_newline and $self->{ 'comma' } eq 'start');
            $self->_add_token( $token );
	    $add_newline = 0 if ($self->{ '_is_in_value' } and $self->{ '_parenthesis_level_value' });
	    $add_newline = 0 if ($self->{ '_is_in_function' } or $self->{ '_is_in_statistics' });
	    $add_newline = 0 if (defined $self->_next_token and !$self->{ 'no_comments' } and $self->_is_comment($self->_next_token));
	    $add_newline = 0 if (defined $self->_next_token and $self->_next_token =~ /KEYWCONST/ and $#{ $self->{ '_tokens' } } >= 1 and $self->{ '_tokens' }[1] =~ /^(LANGUAGE|STRICT)$/i);
	    $add_newline = 1 if ($self->{ '_is_in_truncate' });
	    $self->_new_line($token,$last) if ($add_newline and $self->{ 'comma' } eq 'end' and ($self->{ 'comma_break' } || $self->{ '_current_sql_stmt' } ne 'INSERT'));
        }

        elsif ( $token eq ';' or $token =~ /^\\(?:g|crosstabview|watch)/ )
	{
	    # statement separator or executing psql meta command (prefix 'g' includes all its variants)

            $self->_add_token($token);

	    next if ($token eq ';' and $self->{ '_is_in_case' } and uc($last) ne 'CASE');

            if ($self->{ '_is_in_rule' }) {
		$self->_back($token, $last);
	    }
	    elsif ($self->{ '_is_in_create' } && $self->{ '_is_in_block' } > -1)
	    {
	        $self->_pop_level($token, $last);
	    }

            # Initialize most of statement related variables
            $self->{ 'no_break' } = 0;
	    $self->{ '_is_in_generated' } = 0;
            $self->{ '_is_in_where' } = 0;
	    $self->{ '_is_in_between' } = 0;
            $self->{ '_is_in_from' } = 0;
            $self->{ '_is_in_join' } = 0;
            $self->{ '_is_in_create' } = 0;
	    $self->{ '_is_in_create_schema' } = 0;
            $self->{ '_is_in_alter' } = 0;
	    $self->{ '_is_in_rule' } = 0;
            $self->{ '_is_in_publication' } = 0;
            $self->{ '_is_in_call' } = 0;
            $self->{ '_is_in_type' } = 0;
            $self->{ '_is_in_domain' } = 0;
            $self->{ '_is_in_function' } = 0;
            $self->{ '_current_function' } = '';
            $self->{ '_is_in_prodedure' } = 0;
            $self->{ '_is_in_index' } = 0;
	    $self->{ '_is_in_statistics' } = 0;
	    $self->{ '_is_in_cast' } = 0;
            $self->{ '_is_in_if' } = 0;
            $self->{ '_is_in_with' } = 0;
            $self->{ '_is_in_overlaps' } = 0;
            $self->{ '_has_order_by' } = 0;
            $self->{ '_has_over_in_join' } = 0;
            $self->{ '_parenthesis_level' } = 0;
            $self->{ '_parenthesis_function_level' } = 0;
	    $self->{ '_is_in_constraint' } = 0;
	    $self->{ '_is_in_distinct' } = 0;
	    $self->{ '_is_in_array' } = 0;
            $self->{ '_is_in_filter' } = 0;
	    $self->{ '_parenthesis_filter_level' } = 0;
            $self->{ '_is_in_partition' } = 0;
            $self->{ '_is_in_over' } = 0;
	    $self->{ '_is_in_policy' } = 0;
	    $self->{ '_is_in_truncate' } = 0;
	    $self->{ '_is_in_trigger' } = 0;
	    $self->{ '_is_in_using' } = 0;
	    $self->{ '_and_level' } = 0;
	    $self->{ '_col_count' } = 0;
	    $self->{ '_is_in_drop' } = 0;
	    $self->{ '_is_in_conversion' } = 0;
	    $self->{ '_is_in_operator' } = 0;
	    $self->{ '_is_in_explain' }  = 0;
            $self->{ '_is_in_sub_query' } = 0;
	    $self->{ '_is_in_fetch' } = 0;
            $self->{ '_is_in_aggregate' } = 0;
            $self->{ '_is_in_value' } = 0;
            $self->{ '_parenthesis_level_value' } = 0;
	    $self->{ '_parenthesis_with_level' } = 0;
            $self->{ '_is_in_returns_table' } = 0;
	    $self->{ '_has_limit' } = 0;
	    $self->{ '_not_a_type' } = 0;
            $self->{ '_is_subquery' } = 0;
	    $self->{ '_is_in_order_by' } = 0;
	    $self->{ '_is_in_materialized' } = 0;
	    $self->{ '_is_in_drop_function' } = 0;

	    if ( $self->{ '_insert_values' } )
	    {
		if ($self->{ '_is_in_block' } == -1 and !$self->{ '_is_in_declare' } and !$self->{ '_fct_code_delimiter' }) {
                    $self->_reset_level($token, $last);
		}
		elsif ($self->{ '_is_in_block' } == -1 and $self->{ '_current_sql_stmt' } eq 'INSERT' and !$self->{ '_is_in_create' } and !$self->{ '_is_in_create_function' })
		{
		    $self->_back($token, $last);
		    $self->_pop_level($token, $last);
	        }
		else
		{
		    $self->_set_level($self->_pop_level($token, $last), $token, $last);
	        }
		$self->{ '_insert_values' } = 0;
	    }
            $self->{ '_current_sql_stmt' } = '';
            $self->{ 'break' } = "\n" unless ( $self->{ 'spaces' } != 0 );
	    #$self->_new_line($token,$last) if ($last !~ /^(VALUES|IMPLICIT|ASSIGNMENT)$/i);
            $self->_new_line($token,$last) if ($last !~ /^VALUES$/i);
            # Add an additional newline after ; when we are not in a function
            if ($self->{ '_is_in_block' } == -1 and !$self->{ '_is_in_work' } and !$self->{ '_language_sql' }
			    and !$self->{ '_is_in_declare' } and uc($last) ne 'VALUES')
	    {
		$self->{ '_new_line' } = 0;
                $self->_new_line($token,$last);
		$self->{ 'stmt_number' }++;
		$self->{ 'content' } .= "-- Statement # $self->{ 'stmt_number' }\n" if ($self->{ 'numbering' } and $#{ $self->{ '_tokens' } } > 0);
            }
            # End of statement; remove all indentation when we are not in a BEGIN/END block
            if (!$self->{ '_is_in_declare' } and $self->{ '_is_in_block' } == -1 and !$self->{ '_fct_code_delimiter' })
	    {
		    $self->_reset_level($token, $last);
            }
	    #elsif ((not defined $self->_next_token or $self->_next_token !~ /^INSERT$/) and !$self->{ '_fct_code_delimiter' })
	    elsif (!$self->{ '_language_sql' } and (not defined $self->_next_token or $self->_next_token !~ /^INSERT$/))
	    {
                if ($#{ $self->{ '_level_stack' } } == -1) {
                        $self->_set_level(($self->{ '_is_in_declare' }) ? 1 : ($self->{ '_is_in_block' }+1), $token, $last);
                } else {
			$self->_set_level($self->{ '_level_stack' }[-1], $token, $last);
                }
            }
	    $last = $self->_set_last($token, $last);
        }

        elsif ($token =~ /^FOR$/i)
	{
	    if ($self->{ '_is_in_policy' })
	    {
		$self->_over($token,$last);
		$self->_new_line($token,$last);
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
                next;
	    }

            if ($self->_next_token =~ /^(UPDATE|KEY|NO|VALUES)$/i)
	    {
		$self->_back($token, $last) if (!$self->{ '_has_limit' } and ($#{$self->{ '_level_stack' }} == -1
					or  $self->{ '_level' } > $self->{ '_level_stack' }[-1]));
                $self->_new_line($token,$last);
		$self->{ '_has_limit' } = 0;
            }
	    elsif ($self->_next_token =~ /^EACH$/ and $self->{ '_is_in_trigger' })
	    {
                $self->_new_line($token,$last);
	    }
            $self->_add_token( $token );
 	    # cover FOR in cursor
            $self->_over($token,$last) if (uc($self->_next_token) eq 'SELECT');
            $last = $self->_set_last($token, $last);
        }

        elsif ( $token =~ /^(?:FROM|WHERE|SET|RETURNING|HAVING|VALUES)$/i )
	{
            if (uc($token) eq 'FROM' and $self->{ '_has_order_by' } and !$self->{ '_parenthesis_level' })
	    {
                $self->_back($token, $last) if ($self->{ '_has_order_by' });
	    }

	    $self->{ 'no_break' } = 0;
            $self->{ '_col_count' } = 0;
	    # special cases for create partition statement
            if ($token =~ /^VALUES$/i && defined $last and $last =~ /^(FOR|IN)$/i)
	    {
		$self->_add_token( $token );
		$self->{ 'no_break' } = 1;
		$last = $self->_set_last($token, $last);
		next;
	    }
	    elsif ($token =~ /^FROM$/i && defined $last and uc($last) eq 'VALUES')
	    {
		$self->_add_token( $token );
		$last = $self->_set_last($token, $last);
		next;
	    }

	    # Case of DISTINCT FROM clause
            if ($token =~ /^FROM$/i)
	    {
		if (uc($last) eq 'DISTINCT' || $self->{ '_is_in_fetch' } || $self->{ '_is_in_alter' } || $self->{ '_is_in_conversion' })
		{
			$self->_add_token( $token );
			$last = $self->_set_last($token, $last);
			next;
		}
                $self->{ '_is_in_from' }++ if (!$self->{ '_is_in_function' } && !$self->{ '_is_in_partition' });
            }

            if ($token =~ /^WHERE$/i && !$self->{ '_is_in_filter' })
	    {
                $self->_back($token, $last) if ($self->{ '_has_over_in_join' });
                $self->{ '_is_in_where' }++;
                $self->{ '_is_in_from' }-- if ($self->{ '_is_in_from' });
                $self->{ '_is_in_join' } = 0;
                $self->{ '_has_over_in_join' } = 0;
            }
	    elsif (!$self->{ '_is_in_function' })
	    {
                $self->{ '_is_in_where' }-- if ($self->{ '_is_in_where' });
            }

            if ($token =~ /^SET$/i and $self->{ '_is_in_create' })
	    {
                # Add newline before SET statement in function header
                $self->_new_line($token,$last) if (not defined $last or $last !~ /^(DELETE|UPDATE)$/i);
            }
	    elsif ($token =~ /^WHERE$/i and $self->{ '_current_sql_stmt' } eq 'DELETE')
	    {
                $self->_new_line($token,$last);
                $self->_add_token( $token );
                $self->_over($token,$last);
                $last = $self->_set_last($token, $last);
                $self->{ '_is_in_join' } = 0;
                $last = $self->_set_last($token, $last);
                next;
            }
	    elsif ($token =~ /^SET$/i and defined $last and uc($last) eq 'UPDATE' and !$self->_is_keyword($self->_next_token()))
	    {
		$self->{ '_is_in_index' } = 0;
		$self->{ '_is_in_from' } = 0;
                $self->_add_token( $token );
                $self->_new_line($token,$last);
                $self->_over($token,$last);
                $last = $self->_set_last($token, $last);
		next;
            }
	    elsif ($token !~ /^FROM$/i or (!$self->{ '_is_in_function' } and !$self->{ '_is_in_statistics' }
				    and $self->{ '_current_sql_stmt' } !~ /(DELETE|REVOKE)/))
	    {
                if (!$self->{ '_is_in_filter' } and ($token !~ /^SET$/i or !$self->{ '_is_in_index' }))
		{
			$self->_back($token, $last) if ((uc($token) ne 'VALUES' or $self->{ '_current_sql_stmt' } ne 'INSERT' and $last ne "'")and (uc($token) !~ /^WHERE$/i or $self->{'_is_in_with' } < 2 or $self->{ '_level' } > 1));
		    if (uc($token) eq 'WHERE' and $self->{'_is_in_function' }
				    and $self->{ '_is_subquery' } <= 2
		    )
		    {
			    $self->_over($token, $last);
		    }
		    $self->_new_line($token,$last) if (!$self->{ '_is_in_rule' } and ($last !~ /^DEFAULT$/i or $self->_next_token() ne ';'));
                }
            }
	    else
	    {
		if (uc($token) eq 'FROM' and $self->{ '_is_in_sub_query' }
				and !grep(/^\Q$last\E$/i, @extract_keywords)
				and ($self->{ '_insert_values' } or $self->{ '_is_in_function' })
				and (!$self->{ '_is_in_function' } or
					!grep(/^$self->{ '_current_function' }$/, @have_from_clause))
		)
		{
                    $self->_new_line($token,$last);
		    $self->_back($token, $last);
		}
		if (uc($token) eq 'FROM') {
			$self->{ '_current_function' } = '';
		}
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
                next;
            }

            if ($token =~ /^VALUES$/i and !$self->{ '_is_in_rule' } and !$self->{ 'comma_break' } and ($self->{ '_current_sql_stmt' } eq 'INSERT' or $last eq '('))
	    {
		$self->_over($token,$last);
		if ($self->{ '_current_sql_stmt' } eq 'INSERT' or $last eq '(')
		{
		    $self->{ '_insert_values' } = 1;
		    $self->_push_level($self->{ '_level' }, $token, $last);
	        }
	    }

	    if ($token =~ /^VALUES$/i and $last eq '(')
            {
                $self->{ '_is_in_value' } = 1;
            }

	    if (uc($token) eq 'WHERE')
	    {
		$self->_add_token( $token, $last );
                $self->{ '_is_in_value' } = 0;
                $self->{ '_parenthesis_level_value' } = 0;
            }
	    else
	    {
		$self->_add_token( $token );
            }

            if ($token =~ /^VALUES$/i and $last eq '(')
	    {
                $self->_over($token,$last);
            }
            elsif ( $token =~ /^SET$/i && $self->{ '_current_sql_stmt' } eq 'UPDATE' )
	    {
                    $self->_new_line($token,$last) if (!$self->{ 'wrap_after' });
                    $self->_over($token,$last);
            }
            elsif ( !$self->{ '_is_in_over' } and !$self->{ '_is_in_filter' } and ($token !~ /^SET$/i or $self->{ '_current_sql_stmt' } eq 'UPDATE') )
	    {
                if (defined $self->_next_token and $self->_next_token !~ /\(|;/
				and ($self->_next_token !~ /^(UPDATE|KEY|NO)$/i || uc($token) eq 'WHERE'))
		{
                    $self->_new_line($token,$last) if (!$self->{ 'wrap_after' });
                    $self->_over($token,$last);
                }
            }
        }

        # Add newline before INSERT and DELETE if last token was AS (prepared statement)
        elsif (defined $last and $token =~ /^(?:INSERT|DELETE|UPDATE)$/i and uc($last) eq 'AS')
	{
                $self->_new_line($token,$last);
                $self->_add_token( $token );
        }

        elsif ( $self->{ '_current_sql_stmt' } !~ /^(GRANT|REVOKE)$/
			and $token =~ /^(?:SELECT|PERFORM|UPDATE|DELETE)$/i
			and (!$self->{ '_is_in_policy' } || $self->{ 'format_type' })
       	)
	{
            $self->{ 'no_break' } = 0;

	    if ($token =~ /^(SELECT|UPDATE|DELETE|INSERT)$/i && $self->{ '_is_in_policy' })
	    {
		$self->_over($token,$last);
	    }

            # case of ON DELETE/UPDATE clause in create table statements
	    if ($token =~ /^(UPDATE|DELETE)$/i && $self->{ '_is_in_create' }) {
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
		next;
            }
            if ($token =~ /^UPDATE$/i and $last =~ /^(FOR|KEY|DO)$/i)
	    {
                $self->_add_token( $token );
            }
	    elsif (!$self->{ '_is_in_policy' } && $token !~ /^(DELETE|UPDATE)$/i && (!defined $self->_next_token || $self->_next_token !~ /^DISTINCT$/i))
	    {
                $self->_new_line($token,$last) if (!defined $last or $last ne "\\\\");
                $self->_add_token( $token );
                $self->_new_line($token,$last) if (!$self->{ 'wrap_after' } and (!defined $last or $last ne "\\\\"));
                $self->_over($token,$last);
            }
	    else
	    {
		if ($self->{ '_is_in_policy' } > 1) {
			$self->_new_line($token,$last);
		}
                $self->_add_token( $token );
		if ($self->{ '_is_in_policy' } > 1) {
		    $self->_new_line($token,$last);
                    $self->_over($token,$last);
		}
	        $self->{ '_is_in_policy' }++ if ($self->{ '_is_in_policy' });
            }
        }

        elsif ( $self->{ '_current_sql_stmt' } !~ /^(GRANT|REVOKE)$/
			and uc($token) eq 'INSERT' 
			and $self->{ '_is_in_policy' } && $self->{ 'format_type' })
	{
                $self->_add_token( $token );
                $self->_new_line($token,$last);
		$self->_over($token,$last);
	}
        elsif ( $token =~ /^(?:WITHIN)$/i )
	{
		$self->{ '_is_in_within' } = 1;
                $self->{ '_has_order_by' } = 1;
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
		next;
	}

        elsif ( $token =~ /^(?:GROUP|ORDER|LIMIT|EXCEPTION)$/i or (uc($token) eq 'ON' and uc($self->_next_token()) eq 'CONFLICT'))
	{
	    if ($self->{ 'format_type' } and uc($token) eq 'GROUP' and uc($self->_next_token()) eq 'BY') {
                $self->{ 'no_break' } = 1;
            }
	    if (uc($token) eq 'ORDER' and uc($self->_next_token()) eq 'BY') {
		    $self->{ '_is_in_order_by' } = 1;
	    } else {
		    $self->{ '_is_in_order_by' } = 0;
	    }
            $self->{ '_is_in_value' } = 0;
            $self->{ '_parenthesis_level_value' } = 0;
            if (uc($token) eq 'GROUP' and !defined $last or uc($last) eq 'EXCLUDE') {
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
		next;
	    }
	    if (($self->{ '_is_in_within' } && uc($token) eq 'GROUP') || ($self->{ '_is_in_over' } && uc($token) eq 'ORDER')) {
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
		next;
	    }
            if ($self->{ '_has_over_in_join' } and uc($token) eq 'GROUP')
	    {
                $self->_back($token, $last);
		$self->{ '_has_over_in_join' } = 0;
            }
            $self->{ '_is_in_join' } = 0;
	    $self->{ '_has_limit' } = 1 if (uc($token) eq 'LIMIT');
            if ($token !~ /^EXCEPTION/i) {
                $self->_back($token, $last);
            } else {
                $self->_set_level($self->_pop_level($token, $last), $token, $last);
            }
	    if (uc($token) ne 'EXCEPTION' or not defined $last or uc($last) ne 'RAISE')
	    {
		# Excluding CREATE/DROP GROUP
	        if (uc($token) ne 'LIMIT' or !$self->{ '_is_in_create' })
		{
                    $self->_new_line($token,$last) if (!$self->{ '_is_in_function' } and (not defined $last or $last !~ /^(CREATE|DROP)$/));
		}
            }
            # Store current indent position to print END at the right level
            if (uc($last) ne 'RAISE' and $token =~ /^EXCEPTION$/i)
	    {
	        $self->{ '_is_in_exception' } = 1;
		if ($#{ $self->{ '_begin_level' } } >= 0) {
		    $self->_set_level($self->{ '_begin_level' }[-1], $token, $last);
	        }
	    } elsif (uc($last) eq 'RAISE' and $token =~ /^EXCEPTION$/i) {
	        $self->_push_level($self->{ '_level' }, $token, $last);
                $self->_over($token,$last);
            }
            $self->{ '_is_in_where' }-- if ($self->{ '_is_in_where' });
            $self->_add_token( $token );
	    if ($token =~ /^EXCEPTION$/i && $self->{ '_level' } == 0) {
                    $self->_over($token,$last);
	    }
        }

        elsif ( $token =~ /^(?:BY)$/i and $last !~ /^(?:INCREMENT|OWNED|PARTITION|GENERATED)$/i)
	{
            $self->_add_token( $token );
	    $self->{ '_col_count' } = 0 if (defined $last && $last =~ /^(?:GROUP|ORDER)/i);
	    if (!$self->{ '_has_order_by' } and !$self->{ '_is_in_over' }) {
                $self->_new_line($token,$last) if (!$self->{ 'wrap_after' } and !$self->{ '_is_in_function' });
                $self->_over($token,$last);
	    }
        }

        elsif ( $token =~ /^(?:CASE)$/i and uc($last) ne 'END')
	{
	    if  ($self->{ '_is_in_policy' })
	    {
		 $self->_new_line($token,$last);
                 $self->_over($token,$last);
                 $self->_add_token( $token );
 		 $self->{ '_is_in_policy' }++;
	    } else {
                $self->_add_token( $token );
            }
            # Store current indent position to print END at the right level
	    $self->_push_level($self->{ '_level' }, $token, $last);
            # Mark next WHEN statement as first element of a case
            # to force indentation only after this element
            $self->{ '_first_when_in_case' } = 1;
            $self->{ '_is_in_case' }++;
        }

        elsif ( $token =~ /^(?:WHEN)$/i)
	{
            if (!$self->{ '_first_when_in_case' } and !$self->{'_is_in_trigger'}
			    and defined $last and uc($last) ne 'CASE'
	    )
	    {
		if (!$self->{ '_is_in_exception' }) {
		    $self->_set_level($self->{ '_level_stack' }[-1], $token, $last) if ($#{ $self->{ '_level_stack' } } >= 0);
	        } elsif ($#{ $self->{ '_begin_level' }} >= 0) {
		    $self->_set_level($self->{ '_begin_level' }[-1]+1, $token, $last);
	        }
	    }
            $self->_new_line($token,$last) if (not defined $last or $last !~ /^(CASE|,|\()$/i );
            $self->_add_token( $token );
            if (!$self->{ '_is_in_case' } && !$self->{ '_is_in_trigger' }) {
                $self->_over($token,$last);
	    }
            $self->{ '_first_when_in_case' } = 0;
        }

        elsif ( $token =~ /^(?:IF|LOOP)$/i && $self->{ '_current_sql_stmt' } ne 'GRANT')
	{
	    if ($self->{ '_is_in_join' }) {
	        $self->{ '_is_in_join' } = 0;
		$self->_back($token,$last);
                $self->_add_token( $token );
	    } else {
                $self->_add_token( $token );
	    }
	    $self->{ 'no_break' } = 0;
            if (defined $self->_next_token and $self->_next_token !~ /^(EXISTS|;)$/i)
	    {
		if (uc($self->_next_token) ne 'NOT' || uc($self->{ '_tokens' }->[ 1 ]) ne 'EXISTS')
		{
                    $self->_new_line($token,$last) if ($token =~ /^LOOP$/i);
		    $self->_over($token,$last);
	            $self->_push_level($self->{ '_level' }, $token, $last);
                    if ($token =~ /^IF$/i) {
                        $self->{ '_is_in_if' } = 1;
                    }
	        }
            }
        }

        elsif ($token =~ /^THEN$/i)
	{
            $self->_add_token( $token );
            $self->_new_line($token,$last);
	    $self->_set_level($self->{ '_level_stack' }[-1], $token, $last) if ($self->{ '_is_in_if' } and $#{ $self->{ '_level_stack' } } >= 0);
	    if ($self->{ '_is_in_case' } && defined $self->_next_token() and $self->_next_token() !~ /^(\(|RAISE)$/i) {
		$self->_set_level($self->{ '_level_stack' }[-1], $token, $last) if ($#{ $self->{ '_level_stack' } } >= 0);
	        $self->_over($token,$last);
	    }
	    if ($self->{ '_is_in_case' } && defined $self->_next_token() and
		    $self->_next_token() eq '(' and $self->{ '_tokens' }[1] !~ /^(SELECT|CASE)$/i
	    )
	    {
		$self->_set_level($self->{ '_level_stack' }[-1], $token, $last) if ($#{ $self->{ '_level_stack' } } >= 0);
	        $self->_over($token,$last);
	    }
            $self->{ '_is_in_if' } = 0;
        }

        elsif ( $token =~ /^(?:ELSE|ELSIF)$/i )
	{
	    $self->_back($token, $last);
            $self->_new_line($token,$last);
            $self->_add_token( $token );
            $self->_new_line($token,$last) if ($token !~ /^ELSIF$/i);
            $self->_over($token,$last);
        }

        elsif ( $token =~ /^(?:END)$/i )
	{
            $self->{ '_first_when_in_case' } = 0;
            if ($self->{ '_is_in_case' })
	    {
                $self->{ '_is_in_case' }--;
		$self->_back($token, $last);
	        $self->_set_level($self->_pop_level($token, $last), $token, $last);
		if (!$self->{ '_is_in_create_function' } or $self->_next_token eq ';')
		{
                    $self->_new_line($token,$last);
                    $self->_add_token( $token );
		    next;
	        }
            }
            # When we are not in a function code block (0 is the main begin/end block of a function)
            elsif ($self->{ '_is_in_block' } == -1 && $last ne ',')
	    {
                # END is closing a create function statement so reset position to begining
                if ($self->_next_token !~ /^(IF|LOOP|CASE|INTO|FROM|END|ELSE|AND|OR|WHEN|AS|,)$/i) {
			$self->_reset_level($token, $last);
                } else
		{
                    # otherwise back to last level stored at CASE keyword
                    $self->_set_level($self->_pop_level($token, $last), $token, $last);
                }
	    }
            # We reach the last end of the code
            elsif ($self->{ '_is_in_block' } > -1 and $self->_next_token =~/^(;|\$.*\$)$/ and !$self->{ '_is_in_exception' })
	    {
                if ($self->{ '_is_in_block' } == 0)
	        {
                    $self->_reset_level($token, $last);
		} else {
		    $self->_set_level($self->_pop_level($token, $last) - 1, $token, $last);
		    $self->{ '_is_in_block' }--;
		}
            }
            # We are in code block
	    elsif ($last ne ',')
	    {
                # decrease the block level if this is a END closing a BEGIN block
                if ($self->_next_token !~ /^(IF|LOOP|CASE|INTO|FROM|END|ELSE|AND|OR|WHEN|AS|,)$/i)
		{
                    $self->{ '_is_in_block' }--;
                }
                # Go back to level stored with IF/LOOP/BEGIN/EXCEPTION block
		if ($self->{ '_is_in_block' } > -1)
		{
		    $self->_set_level($self->_pop_level($token, $last), $token, $last);
		} else {
                    $self->_reset_level($token, $last);
		}
            }
            if ($self->_next_token eq ';') {
		$self->_set_level(pop( @{ $self->{ '_begin_level' } } ), $token, $last);
	    } elsif (!$self->{ '_is_in_exception' } and $self->_next_token !~ /^(AS|CASE|FROM|,)$/i) {
		$self->_back($token, $last) if ($self->_next_token =~ /^(IF|LOOP|CASE|INTO|FROM|END|ELSE|AND|OR|WHEN|AS|,)$/i);
            }
            $self->_new_line($token,$last);
            $self->_add_token( $token );
        }

        elsif ( $token =~ /^(?:END::[^\s]+)$/i and $self->{ '_is_in_case' } )
	{
            $self->{ '_first_when_in_case' } = 0;
            if ($self->{ '_is_in_case' })
	    {
                $self->{ '_is_in_case' }--;
                $self->_back($token, $last);
		$self->_set_level($self->_pop_level($token, $last), $token, $last);
            }
            $self->_new_line($token,$last);
            $self->_add_token( $token );
        }

        elsif ( $token =~ /^(?:UNION|INTERSECT|EXCEPT)$/i )
	{
            $self->{ 'no_break' } = 0;
            if ($self->{ '_is_in_join' })
	    {
                $self->_back($token, $last);
                $self->{ '_is_in_join' } = 0;
            }
            $self->_back($token, $last) unless defined $last and $last eq '(';
            $self->_new_line($token,$last);
            $self->_add_token( $token );
            $self->_new_line($token,$last) if ( defined $self->_next_token
			    and $self->_next_token ne '('
			    and $self->_next_token !~ /^ALL$/i
	    );
            $self->{ '_is_in_where' }-- if ($self->{ '_is_in_where' });
            $self->{ '_is_in_from' } = 0;
        }

        elsif ( $token =~ /^(?:LEFT|RIGHT|FULL|INNER|OUTER|CROSS|NATURAL)$/i and (not defined $last or uc($last) ne 'MATCH') )
	{
            $self->{ 'no_break' } = 0;
            if (!$self->{ '_is_in_join' } and ($last and $last ne ')') )
	    {
                $self->_back($token, $last);
            }
            if ($self->{ '_has_over_in_join' })
	    {
                $self->{ '_has_over_in_join' } = 0;
                $self->_back($token, $last);
            }

            if ( $token =~ /(?:LEFT|RIGHT|FULL|CROSS|NATURAL)$/i )
	    {
                $self->_new_line($token,$last);
                $self->_over($token,$last) if ( $self->{ '_level' } == 0 || ($self->{ '_is_in_with' } > 1 and $self->{ '_level' } == 1));
            }
            if ( ($token =~ /(?:INNER|OUTER)$/i) && ($last !~ /(?:LEFT|RIGHT|CROSS|NATURAL|FULL)$/i) )
	    {
                $self->_new_line($token,$last);
                $self->_over($token,$last) if (!$self->{ '_is_in_join' });
            } 
            $self->_add_token( $token );
        }

        elsif ( $token =~ /^(?:JOIN)$/i and !$self->{ '_is_in_operator' })
	{
            $self->{ 'no_break' } = 0;
            if ( not defined $last or $last !~ /^(?:LEFT|RIGHT|FULL|INNER|OUTER|CROSS|NATURAL)$/i )
	    {
                $self->_new_line($token,$last);
                $self->_back($token, $last) if ($self->{ '_has_over_in_join' });
                $self->{ '_has_over_in_join' } = 0;
            }
            $self->_add_token( $token );
	    $self->{ '_is_in_join' } = 1;
        }

        elsif ( $token =~ /^(?:AND|OR)$/i )
	{
            $self->{ '_is_in_where' } = 0;
            # Try to detect AND in BETWEEN clause to prevent newline insert
            if (uc($token) eq 'AND' and ($self->{ '_is_in_between' }
			    || (defined $last && $last =~ /^(PRECEDING|FOLLOWING|ROW)$/i)))
	    {
                $self->_add_token( $token );
                $last = $self->_set_last($token, $last);
	        $self->{ '_is_in_between' } = 0;
                next;
            }
            $self->{ 'no_break' } = 0;
            if ($self->{ '_is_in_join' })
	    {
                $self->_over($token,$last);
                $self->{ '_has_over_in_join' } = 1;
            }
            $self->{ '_is_in_join' } = 0;
            if ( !$self->{ '_is_in_if' } and !$self->{ '_is_in_index' }
			    and (!$last or $last !~ /^(?:CREATE)$/i)
			    and ($self->{ '_is_in_create' } <= 2)
                            and !$self->{ '_is_in_trigger' }
	    )
	    {
                $self->_new_line($token,$last);
                if (!$self->{'_and_level'} and (!$self->{ '_level' } || $self->{ '_is_in_alter' })) {
                        $self->_over($token,$last);
                } elsif ($self->{'_and_level'} and !$self->{ '_level' } and uc($token) eq 'OR') {
                        $self->_over($token,$last);
                } elsif ($#{$self->{ '_level_stack' }} >= 0 and $self->{ '_level' } == $self->{ '_level_stack' }[-1]) {
                        $self->_over($token,$last);
                }
            }
            $self->_add_token( $token );
	    $self->{'_and_level'}++;
        }

        elsif ( $token =~ /^\/\*.*\*\/$/s )
	{
            if ( !$self->{ 'no_comments' } )
	    {
                $token =~ s/\n[\s\t]+\*/\n\*/gs;
		if (!$self->{ '_is_in_over' } and !$self->{ '_is_in_function' })
		{
		    $self->_new_line($token,$last), $self->_add_token('') if (defined $last and $last eq ';');
		    $self->_new_line($token,$last);
		}
                $self->_add_token( $token );
                $self->{ 'break' } = "\n" unless ( $self->{ 'spaces' } != 0 );
                if (!$self->{ '_is_in_function' } and !$self->{ '_is_in_over' }
				and (!$self->_is_comment($token) or !defined $self->_next_token
					or $self->_next_token ne ')')
		)
		{
		    $self->_new_line($token,$last);
	        }
                $self->{ 'break' } = " " unless ( $self->{ 'spaces' } != 0 );
            }
        }

        elsif (($token =~ /^USING$/i and !$self->{ '_is_in_order_by' } and !$self->{ '_is_in_exception' }
				and ($self->{ '_current_sql_stmt' } ne 'DELETE' or uc($self->_next_token) !~ /^(\(|LATERAL)$/i))
			or (uc($token) eq 'WITH' and uc($self->_next_token()) eq 'CHECK' and $self->{ '_is_in_policy' })
	)
	{
            if (!$self->{ '_is_in_from' })
	    {
		$self->_over($token,$last) if ($self->{ '_is_in_operator' } || ($self->{ '_is_in_policy' } && !$self->{ 'format_type' } && !$self->{ '_is_in_using' }));
	        $self->_push_level($self->{ '_level' }, $token, $last) if ($token =~ /^USING$/i);
		$self->_set_level($self->_pop_level($token, $last), $token, $last) if (uc($token) eq 'WITH' and $self->{ '_is_in_policy' } > 1 && !$self->{ 'format_type' } && $self->{ '_is_in_using' });
                $self->_new_line($token,$last) if (uc($last) ne 'EXCLUDE' and !$self->{ '_is_in_index' } and !$self->{ '_is_in_function' });
            }
	    else
	    {
                # USING from join clause disable line break like in function
                $self->{ '_is_in_function' }++;
		# Restore FROM position
		$self->_set_level($self->_pop_level($token, $last), $token, $last) if (!$self->{ '_is_in_join' });
            }
            $self->_add_token($token);
	    $self->{ '_is_in_using' } = 1;
	    $self->{ '_is_in_policy' }++ if (!$self->{ '_is_in_from' } && !$self->{ '_is_in_join' }
		    				&& uc($last) ne 'EXCLUDE' && !$self->{ '_is_in_function' }
						&& !$self->{ '_is_in_operator' } && !$self->{ '_is_in_create' }
						&& !$self->{ '_is_in_index' });
        }

	elsif ($token =~ /^EXCLUDE$/i)
	{
	    if ($last !~ /^(FOLLOWING|ADD)$/i or $self->_next_token !~ /^USING$/i) {
                $self->_new_line($token,$last) if ($last !~ /^(FOLLOWING|ADD)$/i);
	    }
            $self->_add_token( $token );
	    $self->{ '_is_in_using' } = 1;
        }

        elsif ($token =~ /^\\\S/)
	{
	    # treat everything starting with a \ and at least one character as psql meta command. 
            $self->_add_token( $token );
            $self->_new_line($token,$last) if ($token ne "\\\\" and defined $self->_next_token and $self->_next_token ne "\\\\");
        }

        elsif ($token =~ /^(ADD|DROP)$/i && ($self->{ '_current_sql_stmt' } eq 'SEQUENCE'
			|| $self->{ '_current_sql_stmt' } eq 'ALTER'))
	{
	    if ($self->_next_token !~ /^(NOT|NULL|DEFAULT)$/i and (not defined $last or !$self->{ '_is_in_alter' } or $last ne '(')) {
                $self->_new_line($token,$last);
                if ($self->{ '_is_in_alter' } < 2) {
                    $self->_over($token,$last);
	        }
	    }
            $self->_add_token($token, $last);
	    $self->{ '_is_in_alter' }++ if ($self->{ '_is_in_alter' } == 1);
        }

        elsif ($token =~ /^INCREMENT$/i && $self->{ '_current_sql_stmt' } eq 'SEQUENCE')
	{
            $self->_new_line($token,$last);
            $self->_add_token($token);
        }

        elsif ($token =~ /^NO$/i and $self->_next_token =~ /^(MINVALUE|MAXVALUE)$/i)
	{
            $self->_new_line($token,$last);
            $self->_add_token($token);
        }

        elsif ($last !~ /^(\(|NO)$/i and $token =~ /^(MINVALUE|MAXVALUE)$/i)
	{
            $self->_new_line($token,$last);
            $self->_add_token($token);
        }

        elsif ($token =~ /^CACHE$/i)
	{
            $self->_new_line($token,$last);
            $self->_add_token($token);
        }
        else
	{
	     next if ($self->{'keep_newline'} and $token =~ /^\s+$/);

	     if ($self->{ '_fct_code_delimiter' } and $self->{ '_fct_code_delimiter' } =~ /^'.*'$/) {
	 	$self->{ '_fct_code_delimiter' } = "";
		$self->{ '_language_sql' } = 0;
	     }
	     if ($self->{ '_is_in_block' } != -1 and !$self->{ '_fct_code_delimiter' })
	     {
	         $self->{ '_is_in_block' } = -1;
	         $self->{ '_is_in_procedure' } = 0;
	         $self->{ '_is_in_function' } = 0;
	     }
	     # special case with comment
	     if ($token =~ /(?:\s*--)[\ \t\S]*/s)
	     {
                 if ( !$self->{ 'no_comments' } )
	         {
                     $token =~ s/^(\s*)(--.*)/$2/s;
                     my $start = $1 || '';
                     if ($start =~ /\n/s) {
                         $self->_new_line($token,$last), $self->_add_token('') if (defined $last and $last eq ';' and $self->{ 'content' } !~ /\n$/s);
                         $self->_new_line($token,$last);
                     }
                     $token =~ s/\s+$//s;
                     $token =~ s/^\s+//s;
                     $self->_add_token( $token );
		     $self->_new_line($token,$last) if ($start || ($self->{ 'content' } !~ /\n$/s && defined $self->_next_token && uc($self->_next_token) ne 'AS'));
                     # Add extra newline after the last comment if we are not in a block or a statement
                     if (defined $self->_next_token and $self->_next_token !~ /^\s*--/)
		     {
                         $self->{ 'content' } .= "\n" if ($self->{ '_is_in_block' } == -1
						 and !$self->{ '_is_in_declare' }
						 and !$self->{ '_fct_code_delimiter' }
						 and !$self->{ '_current_sql_stmt' }
						 and defined $last and $self->_is_comment($last)
						 and $self->{ 'content' } !~ /\n$/s
                                         );
                     }
		     $last = $self->_set_last($token, $last);
                 }
                 next;
	     }

             if ($last =~ /^(?:SEQUENCE)$/i and $self->_next_token !~ /^(OWNED|;)$/i)
	     {
                 $self->_add_token( $token );
                 $self->_new_line($token,$last);
                 $self->_over($token,$last);
             }
             else
	     {
                if (defined $last && $last eq ')' && (!defined $self->_next_token || $self->_next_token ne ';'))
		{
                      if (!$self->{ '_parenthesis_level' } && $self->{ '_is_in_from' })
		      {
                          $self->_set_level(pop(@{ $self->{ '_level_parenthesis' } }) || 1, $token, $last);
                      }
                }
                if (defined $last and uc($last) eq 'UPDATE' and $self->{ '_current_sql_stmt' } eq 'UPDATE')
		{
			$self->_new_line($token,$last);
			  $self->_over($token,$last);
		}

                if (defined $last and uc($last) eq 'AS' and uc($token) eq 'WITH') {
			$self->_new_line($token,$last);
		}

  		if (uc($token) eq 'INSERT' and defined $last and $last eq ';')
  		{
		      if ($#{ $self->{ '_level_stack' } } >= 0) {
		          $self->_set_level($self->{ '_level_stack' }[-1], $token, $last);
		      } else {
			  $self->_back($token,$last);
		      }
		}

		if  (($self->{ '_is_in_policy' } > 1 || ($self->{ '_is_in_policy' } && $self->{ '_is_in_sub_query' })) && $token =~ /^(ALL|SELECT|UPDATE|DELETE|INSERT)$/i)
		{
		     $self->_new_line($token,$last);
                     $self->_over($token,$last);
                     $self->_add_token( $token );
		     $self->_new_line($token,$last);
                     $self->_over($token,$last);
		     $last = $self->_set_last($token, $last);
		     next;
		}
 		$self->{ '_is_in_policy' }++ if ($token =~ /^SELECT$/i and $self->{ '_is_in_policy' });
		if ($self->{ 'comma_break' } and $self->{ '_current_sql_stmt' } eq 'INSERT' && $last eq '(')
	 	{
                    $self->_new_line($token,$last);
		}

		# Remove extra newline at end of code of SQL functions
		if ($token eq "'" and $last eq ';' and $self->_next_token =~ /^(;|LANGUAGE|STRICT|SET|IMMUTABLE|STABLE|VOLATILE)$/i) {
			$self->{ 'content' } =~ s/\s+$/\n/s;
		}

		# Finally add the token without further condition
                $self->_add_token( $token, $last );
		if ($last eq "'" and $token =~ /^(BEGIN|DECLARE)$/i)
		{
		    $last = $self->_set_last($token, $last);
                    $self->_new_line($token,$last);
                    $self->_over($token,$last);
		}

		# Reset CREATE statement flag when using CTE
		if ($self->{ '_is_in_create' } && $self->{ '_is_in_with' }
			&& uc($token) eq 'WITH' && uc($last) eq 'AS')
		{
		    $self->{ '_is_in_create' } = 0;
		}
                if (defined $last && uc($last) eq 'LANGUAGE' && (!defined $self->_next_token || $self->_next_token ne ';'))
                {
                    $self->_new_line($token,$last);
                }
            }
        }

        $last = $self->_set_last($token, $last);
        $pos++;
    }

    if ($self->{ 'no_extra_line' })
    {
        $self->_new_line() if ($self->{ 'content' } !~ /;$/s);
        $self->{ 'content' } =~ s/\s+$/\n/s;
    }
    else
    {
        $self->_new_line();
    }

    # Attempt to eliminate redundant parenthesis in DML queries
    while ($self->{ 'content' } =~ s/(\s+(?:WHERE|SELECT|FROM)\s+[^;]+)[\(]{2}([^\(\)]+)[\)]{2}([^;]+)/$1($2)$3/igs) {};

    return;
}

sub _lower
{
    my ( $self, $token ) = @_;

    if ($DEBUG) {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_ADD: line: $line => token=$token\n";
    }

    return lc($token);
}

=head2 _add_token

Add a token to the beautified string.

Code lifted from SQL::Beautify

=cut

sub _add_token
{
    my ( $self, $token, $last_token ) = @_;

    if ($DEBUG)
    {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_ADD: line: $line => last=", ($last_token||''), ", token=$token\n";
    }

    if ( $self->{ 'wrap' } )
    {
        my $wrap;
        if ( $self->_is_keyword( $token, $self->_next_token(), $last_token ) ) {
            $wrap = $self->{ 'wrap' }->{ 'keywords' };
        }
        elsif ( $self->_is_constant( $token ) ) {
            $wrap = $self->{ 'wrap' }->{ 'constants' };
        }

        if ( $wrap ) {
            $token = $wrap->[ 0 ] . $token . $wrap->[ 1 ];
        }
    }

    if ($self->{keep_newline} and $self->{ '_is_in_block' } >= 0 and $token =~ /^[\r\n]+$/s
	    and defined $last_token and $last_token eq ';'
    )
    {
	$token =~ s/^[\r\n]+$/\n/s;
        $self->{ 'content' } =~ s/\s+$/\n/s;
        $self->{ 'content' } .= $token if ($self->{ 'content' } !~ /[\n]{2,}$/s);
	return;
    }

    my $last_is_dot = defined( $last_token ) && $last_token eq '.';

    my $sp = $self->_indent;
    if ( !$self->_is_punctuation( $token ) and !$last_is_dot)
    {
        if ( (!defined($last_token) || $last_token ne '(') && $token ne ')' && $token !~ /^::/ )
	{
	    if ($token ne ')'
                                            && defined($last_token)
                                            && $last_token !~ '::$'
                                            && $last_token ne '[' 
					    && ($token ne '(' || !$self->_is_function( $last_token ) || $self->{ '_is_in_type' })
                )
            {
                print STDERR "DEBUG_SPC: 1) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
		if ( ($token !~ /PGFESCQ[12]/ or $last_token !~ /'$/)
				and ($last_token !~ /PGFESCQ[12]/ or $token !~ /^'/)
		)
	        {
		    if ($token !~ /^['"].*['"]$/ or $last_token ne ':')
		    {
			if ($token =~ /AAKEYWCONST\d+AA\s+AAKEYWCONST\d+AA/) {
				$token =~ s/(AAKEYWCONST\d+AA)/$sp$1/gs;
			} else {
				$self->{ 'content' } .= $sp if (!$self->{ 'no_space_function' } or $token ne '('
						or (!$self->{ '_is_in_drop_function' }
							and !$self->{ '_is_in_create_function' }
							and !$self->{ '_is_in_trigger' }));
				if ($self->{ 'no_space_function' } and $token eq '(' and !$self->_is_keyword( $last_token, $token, undef ))
				{
					$self->{ 'content' } =~ s/$sp$//s;
				}
			}
		    }
	        }
	    }
	    elsif (!defined($last_token) && $token)
	    {
                print STDERR "DEBUG_SPC: 2) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
	        $self->{ 'content' } .= $sp;
	    }
            elsif ($token eq '(' and $self->{ '_is_in_create' } == 2 and $self->{ 'content' } !~ /$sp$/)
	    {
                print STDERR "DEBUG_SPC: 2b) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
	        $self->{ 'content' } .= $sp;
	    }
	    elsif (defined $last_token && $self->_is_comment($last_token))
	    {
                print STDERR "DEBUG_SPC: 2c) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
	        $self->{ 'content' } .= $sp;
	    }
        }
	elsif ( defined $last_token && $last_token eq '(' && $token ne ')'
		&& $token !~ /^::/ && !$self->{'wrap_after'} && $self->{ '_is_in_with' } == 1)
	{
                print STDERR "DEBUG_SPC: 3) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
		$self->{ 'content' } .= $sp;
        }
	elsif ( $self->{ '_is_in_create' } == 2 && defined($last_token))
	{
             if ($last_token ne '::' and !$self->{ '_is_in_partition' }
		     				and !$self->{ '_is_in_policy' }
					        and !$self->{ '_is_in_trigger' }
						and !$self->{ '_is_in_aggregate' }
						and ($last_token ne '(' || !$self->{ '_is_in_index' }))
		{
                    print STDERR "DEBUG_SPC: 4) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
                    $self->{ 'content' } .= $sp if ($last_token ne '(' or !$self->{ '_is_in_function' });
		}
        }
	elsif (defined $last_token and (!$self->{ '_is_in_operator' } or !$self->{ '_is_in_alter' }))
	{
	    if ($last_token eq '(' and ($self->{ '_is_in_type' } or ($self->{ '_is_in_operator' }
					    and !$self->_is_type($token, $last_token, $self->_next_token))))
	    {
                print STDERR "DEBUG_SPC: 5a) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
                $self->{ 'content' } .= $sp;
	    }
	    elsif ($self->{ 'comma_break' } and $self->{ '_current_sql_stmt' } eq 'INSERT')
	    {
                print STDERR "DEBUG_SPC: 5b) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
                $self->{ 'content' } .= $sp;
	    }
        }
	elsif ($token eq ')' and $self->{ '_is_in_block' } >= 0 && $self->{ '_is_in_create' })
	{
            print STDERR "DEBUG_SPC: 6) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
            $self->{ 'content' } .= $sp;
	}
	else
	{
            print STDERR "DEBUG_SPC: 7) last=", ($last_token||''), ", token=$token\n" if ($DEBUG_SP);
        }

        if ($self->_is_comment($token))
	{
            my @lines = split(/\n/, $token);
            for (my $i = 1; $i <= $#lines; $i++) {
                if ($lines[$i] =~ /^\s*\*/) {
                    $lines[$i] =~ s/^\s*\*/$sp */;
                } elsif ($lines[$i] =~ /^\s+[^\*]/) {
                    $lines[$i] =~ s/^\s+/$sp /;
                }
            }
            $token = join("\n", @lines);
        }
	else
	{
	    $token =~ s/\n/\n$sp/gs if ($self->{ '_is_in_function' } and $self->{ '_fct_code_delimiter' } eq "'");
        }
    }

    my $next_token = $self->_next_token || '';
    my @cast = ();
    my @next_cast = ();

    # Be sure that we not going to modify a constant
    if ($self->{ '_is_in_create' } < 2 and $token !~ /^[E]*'.*'$/)
    {
	    @cast = split(/::/, $token, -1);
	    $token = shift(@cast) if ($#cast >= 0);
	    @next_cast = split(/::/, $next_token);
	    $next_token = shift(@next_cast) if ($#next_cast >= 0);
    }
    # lowercase/uppercase keywords taking care of function with same name
    if ($self->_is_keyword( $token, $next_token, $last_token ) and
	    (!$self->_is_type($next_token) or $self->{ '_is_in_create' } < 2 or $self->{ '_is_in_cast' }
			    or ($self->{ '_is_in_create' } == 2 and $token =~ /^(WITH|WITHOUT)$/i)
		   or $self->{ '_is_in_create_function' } or uc($token) eq 'AS')
		   and ($next_token ne '(' or (defined $last_token and $last_token =~ /^(CREATE|ALTER)$/i)
				   or !$self->_is_function( $token ))
    )
    {
	# Be sure that we are not formating with time zone
	if (uc($token) ne 'WITH' or not defined $next_token
			or $next_token !~ /^(time|timestamp)$/i)
	{
            $token = lc( $token )            if ( $self->{ 'uc_keywords' } == 1 );
            $token = uc( $token )            if ( $self->{ 'uc_keywords' } == 2 );
            $token = ucfirst( lc( $token ) ) if ( $self->{ 'uc_keywords' } == 3 );
        }
    }
    else
    {
        # lowercase/uppercase known functions or words followed by an open parenthesis
        # if the token is not a keyword, an open parenthesis or a comment
        my $fct = $self->_is_function( $token, $last_token, $next_token ) || '';
        if (($fct and $next_token eq '(' and defined $last_token and uc($last_token) ne 'CREATE')
		or (!$self->_is_keyword( $token, $next_token, $last_token ) and !$next_token eq '('
				    and $token ne '(' and !$self->_is_comment( $token )) )
	{
            $token =~ s/$fct/\L$fct\E/i if ( $self->{ 'uc_functions' } == 1 );
            $token =~ s/$fct/\U$fct\E/i if ( $self->{ 'uc_functions' } == 2 );
            $fct = ucfirst( lc( $fct ) );
            $token =~ s/$fct/$fct/i if ( $self->{ 'uc_functions' } == 3 );
        }
	# case of (NEW|OLD).colname keyword that need to formatted too
	if (($self->{ '_is_in_create_function' } or $self->{ '_fct_code_delimiter' } or $self->{ '_is_in_rule' })
			and $token =~ /^(NEW|OLD)\./i)
	{
            $token =~ s/^(OLD|NEW)\./\L$1\E\./i if ( $self->{ 'uc_keywords' } == 1 );
            $token =~ s/^(OLD|NEW)\./\U$1\E\./i if ( $self->{ 'uc_keywords' } == 2 );
            $token =~ s/^OLD\./\UOld\E\./i if ( $self->{ 'uc_keywords' } == 3 );
            $token =~ s/^NEW\./\UNew\E\./i if ( $self->{ 'uc_keywords' } == 3 );
	}
    }

    my $tk_is_type = $self->_is_type($token, $last_token, $next_token);

    if ($token =~ /^(AT|SET)$/i)
    {
        $self->{ '_not_a_type' } = 1;
    }
    elsif (!$tk_is_type)
    {
        $self->{ '_not_a_type' } = 0;
    }

    # Type are always lowercase
    if (!$self->{ '_not_a_type' } and ($self->{ '_is_in_create' } or $self->{ '_is_in_declare' }
			    or $self->{ '_is_in_cast' } or $self->{ '_is_in_type' } or $self->{ '_is_in_alter' } ))
    {
	    if ($tk_is_type and defined $last_token
			or ($token =~ /^(WITH|WITHOUT)$/i and $next_token =~ /^(time|timestamp)$/i)
	    )
	    {
		if ($last_token =~ /^(AS|RETURNS|INOUT|IN|OUT)$/i or !$self->_is_keyword($last_token)
			or $self->_is_type($last_token) or $self->_is_type($next_token))
		{
		    $token = lc( $token )            if ( $self->{ 'uc_types' } == 1 );
		    $token = uc( $token )            if ( $self->{ 'uc_types' } == 2 );
		    $token = ucfirst( lc( $token ) ) if ( $self->{ 'uc_types' } == 3 );
		}
	    }
    }

    # Add formatting for HTML output
    if ( $self->{ 'colorize' } && $self->{ 'format' } eq 'html' ) {
        $token = $self->highlight_code($token, $last_token, $next_token);
    }

    foreach my $c (@cast)
    {
	my @words = split(/(\s+)/, $c);
	$c = '';
	foreach my $w (@words)
	{
		if (!$self->_is_type($token))
		{
			$c .= $w;
		}
		else
		{
			$c .= lc($w) if ( $self->{ 'uc_types' } == 1 );
			$c .= uc($w) if ( $self->{ 'uc_types' } == 2 );
			$c .= ucfirst( lc( $w ) ) if ( $self->{ 'uc_types' } == 3 );
		}
        }
        $token .= '::' . $c;
    }

    # Format cast in function code
    my $reg = join('|', @{$self->{ 'types' }});
    $reg = '(?:TIMESTAMP(\s*\(\s*\d+\s*\))? WITH TIME ZONE|TIMESTAMP(\s*\(\s*\d+\s*\))? WITHOUT TIME ZONE|CHARACTER VARYING|' . $reg . ')';
    if ($token =~ /::/)
    {
        $token =~ s/::($reg)/'::' . lc($1)/igse if ( $self->{ 'uc_types' } == 1 );
        $token =~ s/::($reg)/'::' . uc($1)/igse if ( $self->{ 'uc_types' } == 2 );
        $token =~ s/::($reg)/'::' . ucfirst(lc($1))/igse if ( $self->{ 'uc_types' } == 3 );
    }

    # special case for MySQL
    if ($token =~ /^(;|\$\$|\/\/)$/ and $self->{ 'content' } =~ /DELIMITER\s*$/)
    {
        $self->{ 'content' } .=  ' ' if ($self->{ 'content' } !~ /DELIMITER\s$/);
    }
    $self->{ 'content' } .= $token;

    # This can't be the beginning of a new line anymore.
    $self->{ '_new_line' } = 0;
}

=head2 _over

Increase the indentation level.

Code lifted from SQL::Beautify

=cut

sub _over
{
    my ( $self, $token, $last ) = @_;

    if ($DEBUG) {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_OVER: line: $line => last=$last, token=$token\n";
    }

    ++$self->{ '_level' };
}

=head2 _back

Decrease the indentation level.

Code lifted from SQL::Beautify

=cut

sub _back
{
    my ( $self, $token, $last ) = @_;

    if ($DEBUG) {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_BACK: line: $line => last=$last, token=$token\n";
    }
    --$self->{ '_level' } if ( $self->{ '_level' } > 0 );
}

=head2 _indent

Return a string of spaces according to the current indentation level and the
spaces setting for indenting.

Code lifted from SQL::Beautify

=cut

sub _indent
{
    my ( $self ) = @_;

    if ( $self->{ '_new_line' } )
    {
        return $self->{ 'space' } x ( $self->{ 'spaces' } * ( $self->{ '_level' } // 0 ) );
    }
    # When this is not for identation force using space
    else
    {
        return ' ';
    }
}

=head2 _new_line

Add a line break, but make sure there are no empty lines.

Code lifted from SQL::Beautify

=cut

sub _new_line
{
    my ( $self, $token, $last ) = @_;

    if ($DEBUG and defined $token) {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_NL: line: $line => last=", ($last||''), ", token=$token\n";
    }

    $self->{ 'content' } .= $self->{ 'break' } unless ( $self->{ '_new_line' } );
    $self->{ '_new_line' } = 1;
}

=head2 _next_token

Have a look at the token that's coming up next.

Code lifted from SQL::Beautify

=cut

sub _next_token
{
    my ( $self ) = @_;

    return @{ $self->{ '_tokens' } } ? $self->{ '_tokens' }->[ 0 ] : undef;
}

=head2 _token

Get the next token, removing it from the list of remaining tokens.

Code lifted from SQL::Beautify

=cut

sub _token
{
    my ( $self ) = @_;

    return shift @{ $self->{ '_tokens' } };
}

=head2 _is_keyword

Check if a token is a known SQL keyword.

Code lifted from SQL::Beautify

=cut

sub _is_keyword
{
    my ( $self, $token, $next_token, $last_token ) = @_;

    return 0 if (!$token);

    # Remove cast if any
    $token =~ s/::[^:]+$//;

    # Fix some false positive
    if (defined $next_token)
    {
        return 0 if (uc($token) eq 'LEVEL' and uc($next_token) ne 'SECURITY');
        return 0 if (uc($token) eq 'EVENT' and uc($next_token) ne 'TRIGGER');
    }
    return 0 if ($token =~ /^(LOGIN|RULE)$/i and !$self->{ '_is_in_create' } and !$self->{ '_is_in_alter' } and !$self->{ '_is_in_drop' } and !$self->{ '_is_in_rule' });
    return 0 if (uc($token) eq 'COMMENT' and (not defined $next_token or $next_token) !~ /^ON|IS$/i);

    if (defined $last_token)
    {
	return 0 if (uc($token) eq 'KEY' and $last_token !~ /^(PRIMARY|FOREIGN|PARTITION|NO)$/i);
        return 0 if ($token =~ /^(BTREE|HASH|GIST|SPGIST|GIN|BRIN)$/i and $last_token !~ /^(USING|BY)$/i);
	return 0 if (uc($token) eq 'NOTICE' and uc($last_token) ne 'RAISE');
        return 0 if ( ($self->{ '_is_in_type' } or $self->{ '_is_in_create' }) and $last_token =~ /^(OF|FROM)$/i);
        return 0 if (uc($last_token) eq 'AS' and $token !~ /^(IDENTITY|SELECT|ENUM|TRANSACTION|UPDATE|DELETE|INSERT|MATERIALIZED|ON|VALUES|RESTRICTIVE|PERMISSIVE|UGLY|EXECUTE|STORAGE|OPERATOR|RANGE|NOT)$/i);
	return 0 if ($token =~ /^(TYPE|SCHEMA)$/i and $last_token =~ /^(COLUMN|\(|,|\||\))/i);
	return 0 if ($token =~ /^TYPE$/i and $last_token !~ /^(CREATE|DROP|ALTER|FOR)$/i
			and !$self->{ '_is_in_alter' }
			and !grep({ uc($_) eq uc( $next_token ) } @{ $self->{ 'types' } })
	);
    }

    if ($DEBUG and defined $token and grep { $_ eq uc( $token ) } @{ $self->{ 'keywords' } }) {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_KEYWORD: line: $line => last=", ($last_token||''), ", token=$token, next=", ($next_token||''), "\n";
    }

    return ~~ grep { $_ eq uc( $token ) } @{ $self->{ 'keywords' } };
}

=head2 _is_type

Check if a token is a known SQL type

=cut

sub _is_type
{
    my ( $self, $token, $last_token, $next_token ) = @_;

    return if (!defined $token);
    return if (defined $next_token and $next_token =~ /^(SEARCH)$/i);

    if ($DEBUG and defined $token)
    {
        my ($package, $filename, $line) = caller;
        print STDERR "DEBUG_TYPE: line: $line => token=[$token], last=", ($last_token||''), ", next=", ($next_token||''), ", type=", (grep { uc($_) eq uc( $token ) } @{ $self->{ 'types' } }), "\n";
    }

    return 0 if ($token =~ /^(int4|int8|num|tstz|ts|date)range$/i
		    and (not defined $next_token or $next_token eq '('));

    my @composite_types = (
        'VARYING', 'PRECISION',
       	'WITH', 'WITHOUT', 'ZONE'
	);

    # Typically case of a data type used as an object name
    if (defined $next_token)
    {
	    if (grep { $_ eq uc( $token ) } @{ $self->{ 'types' } }
			    and grep { $_ eq uc( $next_token ) } @{ $self->{ 'types' } }
			    and !grep { $_ eq uc( $next_token ) } @composite_types)
	    {
		    return 0;
	    }
    }

    $token =~ s/\s*\(.*//; # remove any parameter to the type
    return ~~ grep { $_ eq uc( $token ) } @{ $self->{ 'types' } };
}


sub _is_sql_keyword
{
    my ( $self, $token ) = @_;

    return ~~ grep { $_ eq uc( $token ) } @{ $self->{ 'sql_keywords' } };
}


=head2 _is_comment

Check if a token is a SQL or C style comment

=cut


sub _is_comment
{
    my ( $self, $token ) = @_;

    return 1 if ( $token =~ m#^\s*((?:--)[\ \t\S]*|/\*[\ \t\r\n\S]*?\*/)$#s );

    return 0;
}

=head2 _is_function

Check if a token is a known SQL function.

Code lifted from SQL::Beautify and rewritten to check one long regexp instead of a lot of small ones.

=cut

sub _is_function
{
    my ( $self, $token, $last_token, $next_token ) = @_;

    return undef if (!$token);

    if ( $token =~ $self->{ 'functions_re' } )
    {
	# Check the context of the function
        if (defined $last_token and defined $next_token)
        {
		return undef if ($next_token ne '(');
		return undef if ($self->{ '_is_in_create' } == 1);
        }
        return $1;
    }
    else
    {
        return undef;
    }
}

=head2 add_keywords

Add new keywords to highlight.

Code lifted from SQL::Beautify

=cut

sub add_keywords
{
    my $self = shift;

    for my $keyword ( @_ ) {
        push @{ $self->{ 'keywords' } }, ref( $keyword ) ? @{ $keyword } : $keyword;
    }
}

=head2 _re_from_list

Create compiled regexp from prefix, suffix and and a list of values to match.

=cut

sub _re_from_list
{
    my $prefix = shift;
    my $suffix = shift;
    my (@joined_list, $ret_re);

    for my $list_item ( @_ ) {
        push @joined_list, ref( $list_item ) ? @{ $list_item } : $list_item;
    }

    $ret_re = "$prefix(" . join('|', @joined_list) . ")$suffix";

    return qr/$ret_re/i;
}

=head2 _refresh_functions_re

Refresh compiled regexp for functions.

=cut

sub _refresh_functions_re
{
    my $self = shift;
    $self->{ 'functions_re' } = _re_from_list( '\b[\.]*', '$', @{ $self->{ 'functions' } });
}

=head2 add_functions

Add new functions to highlight.

Code lifted from SQL::Beautify

=cut

sub add_functions
{
    my $self = shift;

    for my $function ( @_ ) {
        push @{ $self->{ 'functions' } }, ref( $function ) ? @{ $function } : $function;
    }

    $self->_refresh_functions_re();
}

=head2 add_rule

Add new rules.

Code lifted from SQL::Beautify

=cut

sub add_rule
{
    my ( $self, $format, $token ) = @_;

    my $rules = $self->{ 'rules' }  ||= {};
    my $group = $rules->{ $format } ||= [];

    push @{ $group }, ref( $token ) ? @{ $token } : $token;
}

=head2 _get_rule

Find custom rule for a token.

Code lifted from SQL::Beautify

=cut

sub _get_rule
{
    my ( $self, $token ) = @_;

    values %{ $self->{ 'rules' } };    # Reset iterator.

    while ( my ( $rule, $list ) = each %{ $self->{ 'rules' } } ) {
        return $rule if ( grep { uc( $token ) eq uc( $_ ) } @$list );
    }

    return;
}

=head2 _process_rule

Applies defined rule.

Code lifted from SQL::Beautify

=cut

sub _process_rule
{
    my ( $self, $rule, $token ) = @_;

    my $format = {
        break => sub { $self->_new_line() },
        over  => sub { $self->_over() },
        back  => sub { $self->_back() },
        token => sub { $self->_add_token( $token ) },
        push  => sub { push @{ $self->{ '_level_stack' } }, $self->{ '_level' } },
        pop   => sub { $self->{ '_level' } = $self->_pop_level($token, '') },
        reset => sub { $self->{ '_level' } = 0; @{ $self->{ '_level_stack' } } = (); },
    };

    for ( split /-/, lc $rule ) {
        &{ $format->{ $_ } } if ( $format->{ $_ } );
    }
}

=head2 _is_constant

Check if a token is a constant.

Code lifted from SQL::Beautify

=cut

sub _is_constant
{
    my ( $self, $token ) = @_;

    return ( $token =~ /^\d+$/ or $token =~ /^(['"`]).*\1$/ );
}

=head2 _is_punctuation

Check if a token is punctuation.

Code lifted from SQL::Beautify

=cut

sub _is_punctuation
{
    my ( $self, $token ) = @_;
    if  ($self->{ 'comma' } eq 'start' and $token eq ',') {
    return 0;
    }
    return ( $token =~ /^[,;.\[\]]$/ );
}

=head2 _generate_anonymized_string

Simply generate a random string, thanks to Perlmonks.

Returns original in certain cases which don't require anonymization, like
timestamps, or intervals.

=cut

sub _generate_anonymized_string
{
    my $self = shift;
    my ( $before, $original, $after ) = @_;

    # Prevent dates from being anonymized
    return $original if $original =~ m{\A\d\d\d\d[/:-]\d\d[/:-]\d\d\z};
    return $original if $original =~ m{\A\d\d[/:-]\d\d[/:-]\d\d\d\d\z};

    # Prevent dates format like DD/MM/YYYY HH24:MI:SS from being anonymized
    return $original if $original =~ m{
        \A
        (?:FM|FX|TM)?
        (?:
            HH | HH12 | HH24
            | MI
            | SS
            | MS
            | US
            | SSSS
            | AM | A\.M\. | am | a\.m\.
            | PM | P\.M\. | pm | p\.m\.
            | Y,YYY | YYYY | YYY | YY | Y
            | IYYY | IYY | IY | I
            | BC | B\.C\. | bc | b\.c\.
            | AD | A\.D\. | ad | a\.d\.
            | MONTH | Month | month | MON | Mon | mon | MM
            | DAY | Day | day | DY | Dy | dy | DDD | DD | D
            | W | WW | IW
            | CC
            | J
            | Q
            | RM | rm
            | TZ | tz
            | [\s/:-]
        )+
        (?:TH|th|SP)?
        \z
    };

    # Prevent interval from being anonymized

    return $original if ($before && ($before =~ /interval/i));
    return $original if ($after && ($after =~ /^\)*::interval/i));

    # Shortcut
    my $cache = $self->{ '_anonymization_cache' };

    # Range of characters to use in anonymized strings
    my @chars = ( 'A' .. 'Z', 0 .. 9, 'a' .. 'z', '-', '_', '.' );

    unless ( $cache->{ $original } ) {

        # Actual anonymized version generation
        $cache->{ $original } = join( '', map { $chars[ rand @chars ] } 1 .. 10 );
    }

    return $cache->{ $original };
}

=head2 anonymize

Anonymize litteral in SQL queries by replacing parameters with fake values

=cut

sub anonymize
{
    my $self  = shift;
    my $query = $self->{ 'query' };

    # just in case it has not been called in the main script
    $query = $self->query() if (!$query);

    return if ( !$query );

    # Variable to hold anonymized versions, so we can provide the same value
    # for the same input, within single query.
    $self->{ '_anonymization_cache' } = {};

    # Remove comments
    $query =~ s/\/\*(.*?)\*\///gs;

    # Clean query
    $query =~ s/\\'//gs;
    $query =~ s/('')+/\$EMPTYSTRING\$/gs;

    # Anonymize each values
    $query =~ s{
        ([^\s\']+[\s\(]*)       # before
        '([^']*)'               # original
        ([\)]*::\w+)?           # after
    }{$1 . "'" . $self->_generate_anonymized_string($1, $2, $3) . "'" . ($3||'')}xeg;

    $query =~ s/\$EMPTYSTRING\$/''/gs;

    foreach my $k (keys %{ $self->{ 'keyword_constant' } }) {
	    $self->{ 'keyword_constant' }{$k} = "'" . $self->_generate_anonymized_string('', $self->{ 'keyword_constant' }{$k}, '') . "'";
    }

    $self->query( $query );
}

=head2 set_defaults

Sets defaults for newly created objects.

Currently defined defaults:

=over

=item spaces => 4

=item space => ' '

=item break => "\n"

=item uc_keywords => 2

=item uc_functions => 0

=item uc_types => 1

=item no_comments => 0

=item no_grouping => 0

=item placeholder => ''

=item multiline => 0

=item separator => ''

=item comma => 'end'

=item format => 'text'

=item colorize => 1

=item format_type => 0

=item wrap_limit => 0

=item wrap_after => 0

=item wrap_comment => 0

=item no_extra_line => 0

=item keep_newline => 0

=item no_space_function => 0

=back

=cut

sub set_defaults
{
    my $self = shift;
    $self->set_dicts();

    # Set some defaults.
    $self->{ 'query' }        = '';
    $self->{ 'spaces' }       = 4;
    $self->{ 'space' }        = ' ';
    $self->{ 'break' }        = "\n";
    $self->{ 'wrap' }         = {};
    $self->{ 'rules' }        = {};
    $self->{ 'uc_keywords' }  = 2;
    $self->{ 'uc_functions' } = 0;
    $self->{ 'uc_types' }     = 1;
    $self->{ 'no_comments' }  = 0;
    $self->{ 'no_grouping' }  = 0;
    $self->{ 'placeholder' }  = '';
    $self->{ 'multiline' }    = 0;
    $self->{ 'keywords' }     = $self->{ 'dict' }->{ 'pg_keywords' };
    $self->{ 'types' }        = $self->{ 'dict' }->{ 'pg_types' };
    $self->{ 'functions' }    = ();
    push(@{ $self->{ 'functions' } }, keys %{ $self->{ 'dict' }->{ 'pg_functions' } });
    $self->_refresh_functions_re();
    $self->{ 'separator' }     = '';
    $self->{ 'comma' }         = 'end';
    $self->{ 'format' }        = 'text';
    $self->{ 'colorize' }      = 1;
    $self->{ 'format_type' }   = 0;
    $self->{ 'wrap_limit' }    = 0;
    $self->{ 'wrap_after' }    = 0;
    $self->{ 'wrap_comment' }  = 0;
    $self->{ 'no_extra_line' } = 0;
    $self->{ 'keep_newline' }  = 0;
    $self->{ 'no_space_function' } = 0;

    return;
}

=head2 format

Set output format - possible values: 'text' and 'html'

Default is text output. Returns 0 in case or wrong format and use default.

=cut

sub format
{
    my $self  = shift;
    my $format  = shift;

    if ( grep(/^$format$/i, 'text', 'html') ) {
        $self->{ 'format' } = lc($format);
        return 1;
    }
    return 0;
}

=head2 set_dicts

Sets various dictionaries (lists of keywords, functions, symbols, and the like)

This was moved to separate function, so it can be put at the very end of module
so it will be easier to read the rest of the code.

=cut

sub set_dicts
{
    my $self = shift;

    # First load it all as "my" variables, to make it simpler to modify/map/grep/add
    # Afterwards, when everything is ready, put it in $self->{'dict'}->{...}

    my @pg_keywords = map { uc } qw( 
        ADD AFTER AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC ASYMMETRIC AUTHORIZATION ATTACH AUTO_INCREMENT
        BACKWARD BEFORE BEGIN BERNOULLI BETWEEN BINARY BOTH BY CACHE CASCADE CASE CAST CHECK CHECKPOINT CLOSE CLUSTER
	COLLATE COLLATION COLUMN COMMENT COMMIT COMMITTED CONCURRENTLY CONFLICT CONSTRAINT CONSTRAINT CONTINUE COPY
	COST COSTS CREATE CROSS CUBE CURRENT CURRENT_DATE CURRENT_ROLE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR
	CYCLE DATABASE DEALLOCATE DECLARE DEFAULT DEFERRABLE DEFERRED DEFINER DELETE DELIMITER DESC DETACH DISABLE DISTINCT
	DO DOMAIN DROP EACH ELSE ELSIF ENABLE ENCODING END EVENT EXCEPTION EXCEPT EXCLUDE EXCLUDING EXECUTE EXISTS EXPLAIN EXTENSION FALSE FETCH FILTER
	FIRST FOLLOWING FOR FOREIGN FORWARD FREEZE FROM FULL FUNCTION GENERATED GRANT GROUP GROUPING HAVING HASHES HASH
	IDENTITY IF ILIKE IMMUTABLE IN INCLUDING INCREMENT INDEX INHERITS INITIALLY INNER INOUT INSERT INSTEAD
	INTERSECT INTO INVOKER IS ISNULL ISOLATION JOIN KEY LANGUAGE LAST LATERAL LC_COLLATE LC_CTYPE LEADING
	LEAKPROOF LEFT LEFTARG LEVEL LIKE LIMIT LIST LISTEN LOAD LOCALTIME LOCALTIMESTAMP LOCK LOCKED LOGGED LOGIN
	LOOP MAPPING MATCH MAXVALUE MERGES MINVALUE MODULUS MOVE NATURAL NEXT NOTHING NOTICE ORDINALITY
        NO NOCREATEDB NOCREATEROLE NOSUPERUSER NOT NOTIFY NOTNULL NOWAIT NULL OFF OF OIDS ON ONLY OPEN OPERATOR OR ORDER
        OUTER OVER OVERLAPS OWNER PARTITION PASSWORD PERFORM PLACING POLICY PRECEDING PREPARE PRIMARY PROCEDURE RANGE
        REASSIGN RECURSIVE REFERENCES REINDEX REMAINDER RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURN RETURNING
        RETURNS REVOKE RIGHT RIGHTARG ROLE ROLLBACK ROLLUP ROWS ROW RULE SAVEPOINT SCHEMA SCROLL SECURITY SELECT SEQUENCE
        SEQUENCE SERIALIZABLE SERVER SESSION_USER SET SETOF SETS SHOW SIMILAR SKIP SNAPSHOT SOME STABLE START STRICT
        SYMMETRIC SYSTEM TABLE TABLESAMPLE TABLESPACE TEMPLATE TEMPORARY THEN TO TRAILING TRANSACTION TRIGGER TRUE
        TRUNCATE TYPE UNBOUNDED UNCOMMITTED UNION UNIQUE UNLISTEN UNLOCK UNLOGGED UPDATE USER USING VACUUM VALUES
        VARIADIC VERBOSE VIEW VOLATILE WHEN WHERE WINDOW WITH WITHIN WORK XOR ZEROFILL
	CALL GROUPS INCLUDE OTHERS PROCEDURES ROUTINE ROUTINES TIES READ_ONLY SHAREABLE READ_WRITE
        BASETYPE SFUNC STYPE SFUNC1 STYPE1 SSPACE FINALFUNC FINALFUNC_EXTRA FINALFUNC_MODIFY COMBINEFUNC SERIALFUNC DESERIALFUNC
       	INITCOND MSFUNC MINVFUNC MSTYPE MSSPACE MFINALFUNC MFINALFUNC_EXTRA MFINALFUNC_MODIFY MINITCOND SORTOP
	STORED REFRESH MATERIALIZED RAISE WITHOUT
        );

    my @pg_types = qw(
        BIGINT BIGSERIAL BIT BOOLEAN BOOL BOX BYTEA CHARACTER CHAR CIDR CIRCLE DATE DOUBLE INET INTEGER INTERVAL
        JSONB JSON LINE LSEG MACADDR8 MACADDR MONEY NUMERIC OID PG_LSN POINT POLYGON PRECISION REAL SMALLINT SMALLSERIAL
       	SERIAL TEXT TIMESTAMPTZ TIMESTAMP TSQUERY TSVECTOR TXID_SNAPSHOT UUID XML VARYING VARCHAR ZONE FLOAT4
	FLOAT8 FLOAT NAME TID INT4RANGE INT8RANGE NUMRANGE TSRANGE TSTZRANGE DATERANGE INT2 INT4 INT8 INT TIME
	REGCLASS REGCONFIG REGDICTIONARY REGNAMESPACE REGOPER REGOPERATOR REGPROC REGPROCEDURE REGROLE REGTYPE
	);

    my @sql_keywords = map { uc } qw(
        ABORT ABSOLUTE ACCESS ACTION ADMIN ALSO ALWAYS ASSERTION ASSIGNMENT AT ATTRIBUTE BIGINT BOOLEAN
        CALLED CASCADED CATALOG CHAIN CHANGE CHARACTER CHARACTERISTICS COLUMNS COMMENTS CONFIGURATION
        CONNECTION CONSTRAINTS CONTENT CONVERSION CSV CURRENT DATA DATABASES DAY DEC DECIMAL DEFAULTS DELAYED
        DELIMITERS DESCRIBE DICTIONARY DISABLE DISCARD DOCUMENT DOUBLE ENABLE ENCLOSED ENCRYPTED ENUM ESCAPE ESCAPED
        EXCLUSIVE EXTERNAL FIELD FIELDS FLOAT FLUSH FOLLOWING FORCE FUNCTIONS GLOBAL GRANTED GREATEST HANDLER
        HEADER HOLD HOUR IDENTIFIED IGNORE IMMEDIATE IMPLICIT INDEXES INFILE INHERIT INLINE INPUT INSENSITIVE
        INT INTEGER KEYS KILL LABEL LARGE LEAST LEVEL LINES LOCAL LOW_PRIORITY MATCH MINUTE MODE MODIFY MONTH NAMES
        NATIONAL NCHAR NONE NOTHING NULLIF NULLS OBJECT OFF OPERATOR OPTIMIZE OPTION OPTIONALLY OPTIONS OUT OUTFILE
        OWNED PARSER PARTIAL PASSING PLANS PRECISION PREPARED PRESERVE PRIOR PRIVILEGES PROCEDURAL QUOTE READ
        REAL RECHECK REF REGEXP RELATIVE RELEASE RLIKE ROW SEARCH SECOND SEQUENCES SESSION SHARE SIMPLE
        SMALLINT SONAME STANDALONE STATEMENT STATISTICS STATUS STORAGE STRAIGHT_JOIN SYSID TABLES TEMP TERMINATED
        TREAT TRUSTED TYPES UNENCRYPTED UNKNOWN UNSIGNED UNTIL USE VALID VALIDATE VALIDATOR VALUE VARIABLES VARYING
        WHITESPACE WORK WRAPPER WRITE XMLATTRIBUTES YEAR YES ZONE
        );

    my @redshift_keywords =  map { uc } qw(
	AES128 AES256 ALLOWOVERWRITE BACKUP BLANKSASNULL BYTEDICT BZIP2 CREDENTIALS CURRENT_USER_ID DEFLATE DEFRAG
	DELTA DELTA32K DISABLE DISTKEY EMPTYASNULL ENABLE ENCODE ENCRYPT ENCRYPTION ESCAPE EXPLICIT GLOBALDICT256
	GLOBALDICT64K GZIP INTERLEAVED LUN LUNS LZO LZOP MINUS MOSTLY13 MOSTLY32 MOSTLY8 NEW OFFLINE OFFSET OLD OID
	PARALLEL PERCENT PERMISSIONS RAW READRATIO RECOVER REJECTLOG RESORT RESPECT RESTORE SORTKEY SYSDATE TAG TDES
	TEXT255 TEXT32K TIMESTAMP TOP TRUNCATECOLUMNS UNLOAD WALLET ADDQUOTES
        );


    for my $k ( @pg_keywords ) {
        next if grep { $k eq $_ } @sql_keywords;
        push @sql_keywords, $k;
    }

    my @pg_functions = map { lc } qw(
        ascii age bit_length btrim cardinality cast char_length character_length coalesce
	brin_summarize_range brin_summarize_new_values
	convert chr current_date current_time current_timestamp count decode date_part date_trunc
	encode extract get_byte get_bit initcap isfinite interval justify_hours justify_days
        lower length lpad ltrim localtime localtimestamp md5 now octet_length overlay position pg_client_encoding
        quote_ident quote_literal repeat replace rpad rtrim substring split_part strpos substr set_byte set_bit
        trim to_ascii to_hex translate to_char to_date to_timestamp to_number timeofday upper
        abbrev abs abstime abstimeeq abstimege abstimegt abstimein abstimele
        abstimelt abstimene abstimeout abstimerecv abstimesend aclcontains acldefault
        aclexplode aclinsert aclitemeq aclitemin aclitemout aclremove acos
        any_in any_out anyarray_in anyarray_out anyarray_recv anyarray_send anyelement_in
        anyelement_out anyenum_in anyenum_out anynonarray_in anynonarray_out anyrange_in anyrange_out
        anytextcat area areajoinsel areasel armor array_agg array_agg_finalfn
        array_agg_transfn array_append array_cat array_dims array_eq array_fill array_ge array_positions
        array_gt array_in array_larger array_le array_length array_lower array_lt array_position
        array_ndims array_ne array_out array_prepend array_recv array_remove array_replace array_send array_smaller
        array_to_json array_to_string array_typanalyze array_upper arraycontained arraycontains arraycontjoinsel
        arraycontsel arrayoverlap ascii_to_mic ascii_to_utf8 asin atan atan2
        avg big5_to_euc_tw big5_to_mic big5_to_utf8 bit bit_and bit_in
        bit_or bit_out bit_recv bit_send bitand bitcat bitcmp
        biteq bitge bitgt bitle bitlt bitne bitnot
        bitor bitshiftleft bitshiftright bittypmodin bittypmodout bitxor bool
        bool_and bool_or booland_statefunc boolean booleq boolge boolgt boolin
        boolle boollt boolne boolor_statefunc boolout boolrecv boolsend
        box box_above box_above_eq box_add box_below box_below_eq box_center
        box_contain box_contain_pt box_contained box_distance box_div box_eq box_ge
        box_gt box_in box_intersect box_le box_left box_lt box_mul
        box_out box_overabove box_overbelow box_overlap box_overleft box_overright box_recv
        box_right box_same box_send box_sub bpchar bpchar_larger bpchar_pattern_ge
        bpchar_pattern_gt bpchar_pattern_le bpchar_pattern_lt bpchar_smaller bpcharcmp bpchareq bpcharge
        bpchargt bpchariclike bpcharicnlike bpcharicregexeq bpcharicregexne bpcharin bpcharle
        bpcharlike bpcharlt bpcharne bpcharnlike bpcharout bpcharrecv bpcharregexeq
        bpcharregexne bpcharsend bpchartypmodin bpchartypmodout broadcast btabstimecmp btarraycmp
        btbeginscan btboolcmp btbpchar_pattern_cmp btbuild btbuildempty btbulkdelete btcanreturn
        btcharcmp btcostestimate btendscan btfloat48cmp btfloat4cmp btfloat4sortsupport btfloat84cmp
        btfloat8cmp btfloat8sortsupport btgetbitmap btgettuple btinsert btint24cmp btint28cmp
        btint2cmp btint2sortsupport btint42cmp btint48cmp btint4cmp btint4sortsupport btint82cmp
        btint84cmp btint8cmp btint8sortsupport btmarkpos btnamecmp btnamesortsupport btoidcmp
        btoidsortsupport btoidvectorcmp btoptions btrecordcmp btreltimecmp btrescan btrestrpos
        bttext_pattern_cmp bttextcmp bttidcmp bttintervalcmp btvacuumcleanup bytea_string_agg_finalfn
	bytea_string_agg_transfn byteacat byteacmp byteaeq byteage byteagt byteain byteale
        bytealike bytealt byteane byteanlike byteaout bytearecv byteasend
        cash_cmp cash_div_cash cash_div_flt4 cash_div_flt8 cash_div_int2 cash_div_int4 cash_eq
        cash_ge cash_gt cash_in cash_le cash_lt cash_mi cash_mul_flt4
        cash_mul_flt8 cash_mul_int2 cash_mul_int4 cash_ne cash_out cash_pl cash_recv
        cash_send cash_words cashlarger cashsmaller cbrt ceil ceiling
        center char chareq charge chargt charin charle
        charlt charne charout charrecv charsend cideq cidin
        cidout cidr cidr_in cidr_out cidr_recv cidr_send cidrecv
        cidsend circle circle_above circle_add_pt circle_below circle_center circle_contain
        circle_contain_pt circle_contained circle_distance circle_div_pt circle_eq circle_ge circle_gt
        circle_in circle_le circle_left circle_lt circle_mul_pt circle_ne circle_out
        circle_overabove circle_overbelow circle_overlap circle_overleft circle_overright circle_recv circle_right
        circle_same circle_send circle_sub_pt clock_timestamp close_lb close_ls close_lseg
        close_pb close_pl close_ps close_sb close_sl col_description concat
        concat_ws contjoinsel contsel convert_from convert_to corr cos
        cot covar_pop covar_samp crypt cstring_in cstring_out cstring_recv
        cstring_send cume_dist current_database current_query current_schema current_schemas current_setting
        current_user currtid currtid2 currval date date_cmp date_cmp_timestamp date_cmp_timestamptz date_eq
        date_eq_timestamp date_eq_timestamptz date_ge date_ge_timestamp date_ge_timestamptz date_gt date_gt_timestamp
        date_gt_timestamptz date_in date_larger date_le date_le_timestamp date_le_timestamptz date_lt
        date_lt_timestamp date_lt_timestamptz date_mi date_mi_interval date_mii date_ne date_ne_timestamp
        date_ne_timestamptz date_out date_pl_interval date_pli date_recv date_send date_smaller
        date_sortsupport daterange daterange_canonical daterange_subdiff datetime_pl datetimetz_pl
        dblink_connect_u dblink_connect dblink_disconnect dblink_exec dblink_open dblink_fetch dblink_close
        dblink_get_connections dblink_error_message dblink_send_query dblink_is_busy dblink_get_notify
	dblink_get_result dblink_cancel_query dblink_get_pkey dblink_build_sql_insert dblink_build_sql_delete
	dblink_build_sql_update dblink dcbrt dearmor decrypt decrypt_iv degrees dense_rank dexp diagonal
        decimal diameter digest dispell_init dispell_lexize dist_cpoly dist_lb dist_pb
        dist_pc dist_pl dist_ppath dist_ps dist_sb dist_sl div
        dlog1 dlog10 domain_in domain_recv dpow dround dsimple_init
        dsimple_lexize dsnowball_init dsnowball_lexize dsqrt dsynonym_init dsynonym_lexize dtrunc
        elem_contained_by_range encrypt encrypt_iv enum_cmp enum_eq enum_first enum_ge
        enum_gt enum_in enum_larger enum_last enum_le enum_lt enum_ne
        enum_out enum_range enum_recv enum_send enum_smaller eqjoinsel eqsel
        euc_cn_to_mic euc_cn_to_utf8 euc_jis_2004_to_shift_jis_2004 euc_jis_2004_to_utf8
	euc_jp_to_mic euc_jp_to_sjis euc_jp_to_utf8
        euc_kr_to_mic euc_kr_to_utf8 euc_tw_to_big5 euc_tw_to_mic euc_tw_to_utf8 every exp
        factorial family fdw_handler_in fdw_handler_out first_value float4 float48div
        float48eq float48ge float48gt float48le float48lt float48mi float48mul
        float48ne float48pl float4_accum float4abs float4div float4eq float4ge
        float4gt float4in float4larger float4le float4lt float4mi float4mul
        float4ne float4out float4pl float4recv float4send float4smaller float4um
        float4up float8 float84div float84eq float84ge float84gt float84le
        float84lt float84mi float84mul float84ne float84pl float8_accum float8_avg
	float8_combine float8_regr_combine float8_corr float8_covar_pop float8_covar_samp
	float8_regr_accum float8_regr_avgx float8_regr_avgy float8_regr_intercept
        float8_regr_r2 float8_regr_slope float8_regr_sxx float8_regr_sxy float8_regr_syy
	float8_stddev_pop float8_stddev_samp
        float8_var_pop float8_var_samp float8abs float8div float8eq float8ge float8gt
        float8in float8larger float8le float8lt float8mi float8mul float8ne
        float8out float8pl float8recv float8send float8smaller float8um float8up
        floor flt4_mul_cash flt8_mul_cash fmgr_c_validator fmgr_internal_validator fmgr_sql_validator format
        format_type gb18030_to_utf8 gbk_to_utf8 gen_random_bytes gen_salt generate_series generate_subscripts
	geometry get_current_ts_config getdatabaseencoding getpgusername gin_cmp_prefix gin_cmp_tslexeme
	gin_extract_tsquery gin_extract_tsvector gin_tsquery_consistent ginarrayconsistent ginarrayextract
	ginbeginscan ginbuild ginbuildempty ginbulkdelete gincostestimate ginendscan gingetbitmap gininsert
	ginmarkpos ginoptions ginqueryarrayextract ginrescan ginrestrpos ginvacuumcleanup gist_box_compress
	gist_box_consistent gist_box_decompress gist_box_penalty gist_box_picksplit gist_box_same gist_box_union
	gist_circle_compress gist_circle_consistent gist_point_compress gist_point_consistent gist_point_distance
	gist_poly_compress gist_poly_consistent gistbeginscan gistbuild gistbuildempty gistbulkdelete
        gistcostestimate gistendscan gistgetbitmap gistgettuple gistinsert gistmarkpos gistoptions gistrescan
	gistrestrpos gistvacuumcleanup gtsquery_compress gtsquery_consistent gtsquery_decompress gtsquery_penalty
        gtsquery_picksplit gtsquery_same gtsquery_union gtsvector_compress gtsvector_consistent gtsvector_decompress
	gtsvector_penalty gtsvector_picksplit gtsvector_same gtsvector_union gtsvectorin gtsvectorout
	has_any_column_privilege has_column_privilege has_database_privilege has_foreign_data_wrapper_privilege
	has_function_privilege has_language_privilege has_schema_privilege has_sequence_privilege has_server_privilege
	has_table_privilege has_tablespace_privilege has_type_privilege hash_aclitem hash_array hash_numeric hash_range
	hashbeginscan hashbpchar hashbuild hashbuildempty hashbulkdelete hashchar hashcostestimate hash_aclitem_extended 
        hashendscan hashenum hashfloat4 hashfloat8 hashgetbitmap hashgettuple hashinet hashinsert hashint2
	hashint2extended hashint2vector hashint4 hashint4extended hashint8 hashint8extended hashmacaddr
	hashfloat4extended hashfloat8extended hashcharextended hashoidextended hashnameextended hashmarkpos
	hashoidvectorextended hashmacaddrextended hashinetextended hashname hashoid hashoidvector hashoptions
       	hash_numeric_extended hashmacaddr8extended hash_array_extended hashrescan hashrestrpos hashtext
        hashbpcharextended time_hash_extended timetz_hash_extended interval_hash_extended timestamp_hash_extended
	uuid_hash_extended pg_lsn_hash_extended hashenumextended jsonb_hash_extended hash_range_extended
	hashtextextended hashvacuumcleanup hashvarlena height hmac host hostmask iclikejoinsel
        iclikesel icnlikejoinsel icnlikesel icregexeqjoinsel icregexeqsel icregexnejoinsel icregexnesel
        inet_client_addr inet_client_port inet_in inet_out inet_recv inet_send inet_server_addr
        inet_server_port inetand inetmi inetmi_int8 inetnot inetor inetpl
        int int2 int24div int24eq int24ge int24gt int24le int24lt integer
        int24mi int24mul int24ne int24pl int28div int28eq int28ge
        int28gt int28le int28lt int28mi int28mul int28ne int28pl
        int2_accum int2_avg_accum int2_mul_cash int2_sum int2abs int2and int2div
        int2eq int2ge int2gt int2in int2larger int2le int2lt
        int2mi int2mod int2mul int2ne int2not int2or int2out
        int2pl int2recv int2send int2shl int2shr int2smaller int2um
        int2up int2vectoreq int2vectorin int2vectorout int2vectorrecv int2vectorsend int2xor
        int4 int42div int42eq int42ge int42gt int42le int42lt
        int42mi int42mul int42ne int42pl int48div int48eq int48ge
        int48gt int48le int48lt int48mi int48mul int48ne int48pl
        int4_accum int4_avg_accum int4_mul_cash int4_sum int4abs int4and int4div
        int4eq int4ge int4gt int4in int4inc int4larger int4le
        int4lt int4mi int4mod int4mul int4ne int4not int4or
        int4out int4pl int4range int4range_canonical int4range_subdiff int4recv int4send
        int4shl int4shr int4smaller int4um int4up int4xor int8
        int82div int82eq int82ge int82gt int82le int82lt int82mi
        int82mul int82ne int82pl int84div int84eq int84ge int84gt
        int84le int84lt int84mi int84mul int84ne int84pl int8_accum
        int8_avg int8_avg_accum int8_sum int8abs int8and int8div int8eq
        int8ge int8gt int8in int8inc int8inc_any int8inc_float8_float8 int8larger
        int8le int8lt int8mi int8mod int8mul int8ne int8not
        int8or int8out int8pl int8pl_inet int8range int8range_canonical int8range_subdiff
        int8recv int8send int8shl int8shr int8smaller int8um int8up
        int8xor integer_pl_date inter_lb inter_sb inter_sl internal_in internal_out
        interval_accum interval_avg interval_cmp interval_div interval_eq interval_ge interval_gt
        interval_hash interval_in interval_larger interval_le interval_lt interval_mi interval_mul
        interval_ne interval_out interval_pl interval_pl_date interval_pl_time interval_pl_timestamp interval_pl_timestamptz
        interval_pl_timetz interval_recv interval_send interval_smaller interval_transform interval_um intervaltypmodin
        intervaltypmodout intinterval isclosed isempty ishorizontal iso8859_1_to_utf8 iso8859_to_utf8
        iso_to_koi8r iso_to_mic iso_to_win1251 iso_to_win866 isopen isparallel isperp
        isvertical johab_to_utf8 json_agg jsonb_agg json_array_elements jsonb_array_elements
	json_array_elements_text jsonb_array_elements_text json_to_tsvector jsonb_insert 
        json_array_length jsonb_array_length json_build_array json_build_object json_each jsonb_each json_each_text
        jsonb_each_text json_extract_path jsonb_extract_path json_extract_path_text jsonb_extract_path_text json_in
	json_object json_object_agg jsonb_object_agg json_object_keys jsonb_object_keys json_out json_populate_record
	jsonb_populate_record json_populate_recordset jsonb_pretty jsonb_populate_recordset json_recv json_send
	jsonb_set json_typeof jsonb_typeof json_to_record jsonb_to_record json_to_recordset jsonb_to_recordset
	justify_interval koi8r_to_iso koi8r_to_mic koi8r_to_utf8 koi8r_to_win1251 koi8r_to_win866 koi8u_to_utf8
	jsonb_path_query jsonb_build_object jsonb_object jsonb_build_array jsonb_path_match jsonb_path_exists
        lag language_handler_in language_handler_out last_value lastval latin1_to_mic latin2_to_mic latin2_to_win1250
        latin3_to_mic latin4_to_mic lead like_escape likejoinsel jsonb_path_query_first jsonb_path_query_array
        likesel line line_distance line_eq line_horizontal line_in line_interpt
        line_intersect line_out line_parallel line_perp line_recv line_send line_vertical
        ln lo_close lo_creat lo_create lo_export lo_import lo_lseek lo_compat lo_from_bytea lo_get lo_import_with_oid
        lo_open lo_tell lo_truncate lo_unlink log lo_read lower_inc lo_seek64 lo_put lo_tell64 lo_truncate64 lo_write
        lower_inf lowrite lseg lseg_center lseg_distance lseg_eq lseg_ge
        lseg_gt lseg_horizontal lseg_in lseg_interpt lseg_intersect lseg_le lseg_length
        lseg_lt lseg_ne lseg_out lseg_parallel lseg_perp lseg_recv lseg_send
        lseg_vertical macaddr_and macaddr_cmp macaddr_eq macaddr_ge macaddr_gt macaddr_in
        macaddr_le macaddr_lt macaddr_ne macaddr_not macaddr_or macaddr_out macaddr_recv
        macaddr_send makeaclitem make_interval make_tsrange masklen max mic_to_ascii mic_to_big5 mic_to_euc_cn
        mic_to_euc_jp mic_to_euc_kr mic_to_euc_tw mic_to_iso mic_to_koi8r mic_to_latin1 mic_to_latin2
        mic_to_latin3 mic_to_latin4 mic_to_sjis mic_to_win1250 mic_to_win1251 mic_to_win866 min
        mktinterval mode mod money mul_d_interval name nameeq namege make_timestamptz make_timestamp
        namegt nameiclike nameicnlike nameicregexeq nameicregexne namein namele make_time make_date
        namelike namelt namene namenlike nameout namerecv nameregexeq make_interval
        nameregexne namesend neqjoinsel neqsel netmask network network_cmp
        network_eq network_ge network_gt network_le network_lt network_ne network_sub
        network_subeq network_sup network_supeq nextval nlikejoinsel nlikesel notlike
        npoints nth_value ntile numeric numeric_abs numeric_accum numeric_add
        numeric_avg numeric_avg_accum numeric_cmp numeric_div numeric_div_trunc numeric_eq numeric_exp
        numeric_fac numeric_ge numeric_gt numeric_in numeric_inc numeric_larger numeric_le
        numeric_ln numeric_log numeric_lt numeric_mod numeric_mul numeric_ne numeric_out
        numeric_power numeric_recv numeric_send numeric_smaller numeric_sqrt numeric_stddev_pop numeric_stddev_samp
        numeric_sub numeric_transform numeric_uminus numeric_uplus numeric_var_pop numeric_var_samp numerictypmodin
        numerictypmodout numnode numrange numrange_subdiff obj_description oid oideq
        oidge oidgt oidin oidlarger oidle oidlt oidne
        oidout oidrecv oidsend oidsmaller oidvectoreq oidvectorge oidvectorgt
        oidvectorin oidvectorle oidvectorlt oidvectorne oidvectorout oidvectorrecv oidvectorsend
        oidvectortypes on_pb on_pl on_ppath on_ps on_sb on_sl
        opaque_in opaque_out overlaps path path_add path_add_pt path_center
        path_contain_pt path_distance path_div_pt path_in path_inter path_length path_mul_pt
        path_n_eq path_n_ge path_n_gt path_n_le path_n_lt path_npoints path_out parse_ident
        path_recv path_send path_sub_pt pclose percent_rank percentile_cont percentile_disc
	pg_advisory_lock pg_advisory_lock_shared pg_advisory_unlock pg_advisory_unlock_all pg_advisory_unlock_shared
	pg_advisory_xact_lock pg_advisory_xact_lock_shared pg_available_extension_versions pg_available_extensions
	pg_backend_pid pg_cancel_backend pg_char_to_encoding pg_collation_for pg_collation_is_visible pg_column_size
	pg_conf_load_time pg_conversion_is_visible pg_create_restore_point pg_current_xlog_insert_location
        pg_current_xlog_location pg_cursor pg_database_size pg_describe_object pg_encoding_max_length
	pg_encoding_to_char pg_export_snapshot pg_extension_config_dump pg_extension_update_paths pg_function_is_visible
	pg_get_constraintdef pg_get_expr pg_get_function_arguments pg_filenode_relation pg_indexam_has_property
        pg_get_function_identity_arguments pg_get_function_result pg_get_functiondef pg_get_indexdef pg_get_keywords
        pg_get_ruledef pg_get_serial_sequence pg_get_triggerdef pg_get_userbyid pg_get_viewdef pg_has_role
	pg_indexes_size pg_is_in_recovery pg_is_other_temp_schema pg_is_xlog_replay_paused pg_last_xact_replay_timestamp
	pg_last_xlog_receive_location pg_last_xlog_replay_location pg_listening_channels pg_lock_status pg_ls_dir
	pg_my_temp_schema pg_node_tree_in pg_node_tree_out pg_node_tree_recv pg_node_tree_send pg_notify
	pg_opclass_is_visible pg_operator_is_visible pg_opfamily_is_visible pg_options_to_table pg_index_has_property
        pg_postmaster_start_time pg_prepared_statement pg_prepared_xact pg_read_binary_file pg_read_file
	pg_relation_filenode pg_relation_filepath pg_relation_size pg_reload_conf pg_rotate_logfile
	pg_sequence_parameters pg_show_all_settings pg_size_pretty pg_sleep pg_start_backup pg_index_column_has_property
        pg_stat_clear_snapshot pg_stat_file pg_stat_get_activity pg_stat_get_analyze_count pg_stat_get_autoanalyze_count
	pg_stat_get_autovacuum_count pg_get_object_address pg_identify_object_as_address pg_stat_get_backend_activity
	pg_stat_get_backend_activity_start pg_stat_get_backend_client_addr pg_stat_get_backend_client_port
        pg_stat_get_backend_dbid pg_stat_get_backend_idset pg_stat_get_backend_pid pg_stat_get_backend_start
	pg_stat_get_backend_userid pg_stat_get_backend_waiting pg_stat_get_backend_xact_start
	pg_stat_get_bgwriter_buf_written_checkpoints pg_stat_get_bgwriter_buf_written_clean
        pg_stat_get_bgwriter_maxwritten_clean pg_stat_get_bgwriter_requested_checkpoints
	pg_stat_get_bgwriter_stat_reset_time pg_stat_get_bgwriter_timed_checkpoints pg_stat_get_blocks_fetched
	pg_stat_get_blocks_hit pg_stat_get_buf_alloc pg_stat_get_buf_fsync_backend pg_stat_get_buf_written_backend
	pg_stat_get_checkpoint_sync_time pg_stat_get_checkpoint_write_time pg_stat_get_db_blk_read_time
	pg_stat_get_db_blk_write_time pg_stat_get_db_blocks_fetched pg_stat_get_db_blocks_hit
	pg_stat_get_db_conflict_all pg_stat_get_db_conflict_bufferpin pg_stat_get_db_conflict_lock
	pg_stat_get_db_conflict_snapshot pg_stat_get_db_conflict_startup_deadlock pg_stat_get_db_conflict_tablespace
        pg_stat_get_db_deadlocks pg_stat_get_db_numbackends pg_stat_get_db_stat_reset_time pg_stat_get_db_temp_bytes
	pg_stat_get_db_temp_files pg_stat_get_db_tuples_deleted pg_stat_get_db_tuples_fetched
	pg_stat_get_db_tuples_inserted pg_stat_get_db_tuples_returned pg_stat_get_db_tuples_updated
        pg_stat_get_db_xact_commit pg_stat_get_db_xact_rollback pg_stat_get_dead_tuples pg_stat_get_function_calls
	pg_stat_get_function_self_time pg_stat_get_function_total_time pg_stat_get_last_analyze_time
	pg_stat_get_last_autoanalyze_time pg_stat_get_last_autovacuum_time pg_stat_get_last_vacuum_time
	pg_stat_get_live_tuples pg_stat_get_numscans pg_stat_get_tuples_deleted pg_stat_get_tuples_fetched
        pg_stat_get_tuples_hot_updated pg_stat_get_tuples_inserted pg_stat_get_tuples_returned
	pg_stat_get_tuples_updated pg_stat_get_vacuum_count pg_stat_get_wal_senders pg_stat_get_xact_blocks_fetched
	pg_stat_get_xact_blocks_hit pg_stat_get_xact_function_calls pg_stat_get_xact_function_self_time
        pg_stat_get_xact_function_total_time pg_stat_get_xact_numscans pg_stat_get_xact_tuples_deleted
	pg_stat_get_xact_tuples_fetched pg_stat_get_xact_tuples_hot_updated pg_stat_get_xact_tuples_inserted
	pg_stat_get_xact_tuples_returned pg_stat_get_xact_tuples_updated pg_stat_reset pg_stat_reset_shared
	pg_stat_reset_single_function_counters pg_stat_reset_single_table_counters pg_stop_backup pg_switch_xlog
	pg_table_is_visible pg_table_size pg_tablespace_databases pg_tablespace_location pg_tablespace_size
	pg_terminate_backend pg_timezone_abbrevs pg_timezone_names pg_total_relation_size pg_trigger_depth
	pg_try_advisory_lock pg_try_advisory_lock_shared pg_try_advisory_xact_lock pg_try_advisory_xact_lock_shared
        pg_ts_config_is_visible pg_ts_dict_is_visible pg_ts_parser_is_visible pg_ts_template_is_visible
        pg_type_is_visible pg_typeof pg_xact_commit_timestamp pg_last_committed_xact pg_xlog_location_diff
	pg_xlog_replay_pause pg_xlog_replay_resume pg_xlogfile_name pg_xlogfile_name_offset pgp_key_id pgp_pub_decrypt
	pgp_pub_decrypt_bytea pgp_pub_encrypt pgp_pub_encrypt_bytea pgp_sym_decrypt pgp_sym_decrypt_bytea
        pgp_sym_encrypt pgp_sym_encrypt_bytea pi plainto_tsquery plpgsql_call_handler plpgsql_inline_handler
	plpgsql_validator point point_above point_add point_below point_distance point_div point_eq
        point_horiz point_in point_left point_mul point_ne point_out point_recv
        point_right point_send point_sub point_vert poly_above poly_below poly_center
        poly_contain poly_contain_pt poly_contained poly_distance poly_in poly_left poly_npoints
        poly_out poly_overabove poly_overbelow poly_overlap poly_overleft poly_overright poly_recv
        poly_right poly_same poly_send polygon popen positionjoinsel positionsel
        postgresql_fdw_validator pow power prsd_end prsd_headline prsd_lextype prsd_nexttoken
        prsd_start pt_contained_circle pt_contained_poly querytree
        quote_nullable radians radius random range_adjacent range_after range_before
        range_cmp range_contained_by range_contains range_contains_elem range_eq range_ge range_gist_compress
        range_gist_consistent range_gist_decompress range_gist_penalty range_gist_picksplit range_gist_same
	range_gist_union range_gt range_merge
        range_in range_intersect range_le range_lt range_minus range_ne range_out
        range_overlaps range_overleft range_overright range_recv range_send range_typanalyze range_union
        rank record_eq record_ge record_gt record_in record_le record_lt regexp_match
        record_ne record_out record_recv record_send regclass regclassin regclassout
        regclassrecv regclasssend regconfigin regconfigout regconfigrecv regconfigsend regdictionaryin
        regdictionaryout regdictionaryrecv regdictionarysend regexeqjoinsel regexeqsel regexnejoinsel regexnesel
        regexp_matches regexp_replace regexp_split_to_array regexp_split_to_table regoperatorin regoperatorout regoperatorrecv
        regoperatorsend regoperin regoperout regoperrecv regopersend regprocedurein regprocedureout
        regprocedurerecv regproceduresend regprocin regprocout regprocrecv regprocsend regr_avgx
        regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy
        regr_syy regtypein regtypeout regtyperecv regtypesend reltime reltimeeq
        reltimege reltimegt reltimein reltimele reltimelt reltimene reltimeout
        reltimerecv reltimesend reverse round row_number row_to_json
        scalargtjoinsel scalargtsel scalarltjoinsel scalarltsel
        session_user set_config set_masklen setseed setval setweight shell_in
        shell_out shift_jis_2004_to_euc_jis_2004 shift_jis_2004_to_utf8 shobj_description sign similar_escape sin
        sjis_to_euc_jp sjis_to_mic sjis_to_utf8 slope smgreq smgrin smgrne
        smgrout spg_kd_choose spg_kd_config spg_kd_inner_consistent spg_kd_picksplit spg_quad_choose spg_quad_config
        spg_quad_inner_consistent spg_quad_leaf_consistent spg_quad_picksplit spg_text_choose spg_text_config spg_text_inner_consistent spg_text_leaf_consistent
        spg_text_picksplit spgbeginscan spgbuild spgbuildempty spgbulkdelete spgcanreturn spgcostestimate
        spgendscan spggetbitmap spggettuple spginsert spgmarkpos spgoptions spgrescan
        spgrestrpos spgvacuumcleanup sqrt statement_timestamp stddev stddev_pop stddev_samp
        string_agg string_agg_finalfn string_agg_transfn string_to_array strip sum
        tan text text_ge text_gt text_larger
        text_le text_lt text_pattern_ge text_pattern_gt text_pattern_le text_pattern_lt text_smaller
        textanycat textcat texteq texticlike texticnlike texticregexeq texticregexne
        textin textlen textlike textne textnlike textout textrecv
        textregexeq textregexne textsend thesaurus_init thesaurus_lexize tideq tidge
        tidgt tidin tidlarger tidle tidlt tidne tidout
        tidrecv tidsend tidsmaller time time_cmp time_eq time_ge
        time_gt time_hash time_in time_larger time_le time_lt time_mi_interval
        time_mi_time time_ne time_out time_pl_interval time_recv time_send time_smaller
        time_transform timedate_pl timemi timenow timepl timestamp timestamp_cmp
        timestamp_cmp_date timestamp_cmp_timestamptz timestamp_eq timestamp_eq_date timestamp_eq_timestamptz timestamp_ge timestamp_ge_date
        timestamp_ge_timestamptz timestamp_gt timestamp_gt_date timestamp_gt_timestamptz timestamp_hash timestamp_in timestamp_larger
        timestamp_le timestamp_le_date timestamp_le_timestamptz timestamp_lt timestamp_lt_date timestamp_lt_timestamptz timestamp_mi
        timestamp_mi_interval timestamp_ne timestamp_ne_date timestamp_ne_timestamptz timestamp_out timestamp_pl_interval timestamp_recv
        timestamp_send timestamp_smaller timestamp_sortsupport timestamp_transform timestamptypmodin timestamptypmodout timestamptz
        timestamptz_cmp timestamptz_cmp_date timestamptz_cmp_timestamp timestamptz_eq timestamptz_eq_date timestamptz_eq_timestamp timestamptz_ge
        timestamptz_ge_date timestamptz_ge_timestamp timestamptz_gt timestamptz_gt_date timestamptz_gt_timestamp timestamptz_in timestamptz_larger
        timestamptz_le timestamptz_le_date timestamptz_le_timestamp timestamptz_lt timestamptz_lt_date timestamptz_lt_timestamp timestamptz_mi
        timestamptz_mi_interval timestamptz_ne timestamptz_ne_date timestamptz_ne_timestamp timestamptz_out timestamptz_pl_interval timestamptz_recv
        timestamptz_send timestamptz_smaller timestamptztypmodin timestamptztypmodout timetypmodin timetypmodout timetz
        timetz_cmp timetz_eq timetz_ge timetz_gt timetz_hash timetz_in timetz_larger
        timetz_le timetz_lt timetz_mi_interval timetz_ne timetz_out timetz_pl_interval timetz_recv
        timetz_send timetz_smaller timetzdate_pl timetztypmodin timetztypmodout timezone tinterval
        tintervalct tintervalend tintervaleq tintervalge tintervalgt tintervalin tintervalle
        tintervalleneq tintervallenge tintervallengt tintervallenle tintervallenlt tintervallenne tintervallt
        tintervalne tintervalout tintervalov tintervalrecv tintervalrel tintervalsame tintervalsend
        tintervalstart to_json to_tsquery to_tsvector transaction_timestamp trigger_out trunc ts_debug
        ts_headline ts_lexize ts_match_qv ts_match_tq ts_match_tt ts_match_vq ts_parse ts_delete ts_filter
        ts_rank ts_rank_cd ts_rewrite ts_stat ts_token_type ts_typanalyze tsmatchjoinsel tsquery_phrase
        tsmatchsel tsq_mcontained tsq_mcontains tsquery_and tsquery_cmp tsquery_eq tsquery_ge
        tsquery_gt tsquery_le tsquery_lt tsquery_ne tsquery_not tsquery_or tsqueryin websearch_to_tsquery
        tsqueryout tsqueryrecv tsquerysend tsrange tsrange_subdiff tstzrange tstzrange_subdiff phraseto_tsquery
        tsvector_cmp tsvector_concat tsvector_eq tsvector_ge tsvector_gt tsvector_le tsvector_lt
        tsvector_ne tsvectorin tsvectorout tsvectorrecv tsvectorsend txid_current txid_current_snapshot
        txid_snapshot_in txid_snapshot_out txid_snapshot_recv txid_snapshot_send txid_snapshot_xip
	txid_snapshot_xmax txid_snapshot_xmin
        txid_visible_in_snapshot uhc_to_utf8 unknownin unknownout unknownrecv unknownsend unnest
        upper_inc upper_inf utf8_to_ascii utf8_to_big5 utf8_to_euc_cn utf8_to_euc_jis_2004 utf8_to_euc_jp
        utf8_to_euc_kr utf8_to_euc_tw utf8_to_gb18030 utf8_to_gbk utf8_to_iso8859 utf8_to_iso8859_1 utf8_to_johab
        utf8_to_koi8r utf8_to_koi8u utf8_to_shift_jis_2004 utf8_to_sjis utf8_to_uhc utf8_to_win uuid_cmp
        uuid_eq uuid_ge uuid_gt uuid_hash uuid_in uuid_le uuid_lt
        uuid_ne uuid_out uuid_recv uuid_send var_pop var_samp varbit
        varbit_in varbit_out varbit_recv varbit_send varbit_transform varbitcmp varbiteq
        varbitge varbitgt varbitle varbitlt varbitne varbittypmodin varbittypmodout
        varchar varying varchar_transform varcharin varcharout varcharrecv varcharsend varchartypmodin
        varchartypmodout variance version void_in void_out void_recv void_send
        width width_bucket win1250_to_latin2 win1250_to_mic win1251_to_iso win1251_to_koi8r win1251_to_mic
        win1251_to_win866 win866_to_iso win866_to_koi8r win866_to_mic win866_to_win1251 win_to_utf8 xideq
        xideqint4 xidin xidout xidrecv xidsend xml xml_in xmlcomment xpath xpath_exists table_to_xmlschema
        query_to_xmlschema cursor_to_xmlschema table_to_xml_and_xmlschema query_to_xml_and_xmlschema
        schema_to_xml schema_to_xmlschema schema_to_xml_and_xmlschema database_to_xml database_to_xmlschema xmlroot
        database_to_xml_and_xmlschema table_to_xml query_to_xmlcursor_to_xml xmlcomment xmlconcat xmlelement xmlforest
        xml_is_well_formed_content xml_is_well_formed_document xml_is_well_formed xml_out xml_recv xml_send xmlagg
	xmlpi query_to_xml cursor_to_xml xmlserialize xmltable
    );

    my @copy_keywords = ( 'STDIN', 'STDOUT' );

    my %symbols = (
        '='  => '=', '<'  => '&lt;', '>' => '&gt;', '|' => '|', ',' => ',', '.' => '.', '+' => '+', '-' => '-',
        '*' => '*', '/' => '/', '!=' => '!=', '%' => '%', '<=' => '&lt;=', '>=' => '&gt;=', '<>' => '&lt;&gt;'
    );

    my @brackets = ( '(', ')' );

    # All setting and modification of dicts is done, can set them now to $self->{'dict'}->{...}
    $self->{ 'dict' }->{ 'pg_keywords' }   = \@pg_keywords;
    $self->{ 'dict' }->{ 'pg_types' }      = \@pg_types;
    $self->{ 'dict' }->{ 'sql_keywords' }  = \@sql_keywords;
    $self->{ 'dict' }->{ 'redshift_keywords' } = \@redshift_keywords;
    $self->{ 'dict' }->{ 'pg_functions' }  = ();
    map { $self->{ 'dict' }->{ 'pg_functions' }{$_} = ''; } @pg_functions;
    $self->{ 'dict' }->{ 'copy_keywords' } = \@copy_keywords;
    $self->{ 'dict' }->{ 'symbols' }       = \%symbols;
    $self->{ 'dict' }->{ 'brackets' }      = \@brackets;

    return;
}

=head2 _remove_dynamic_code

Internal function used to hide dynamic code in plpgsql to the parser.
The original values are restored with function _restore_dynamic_code().

=cut

sub _remove_dynamic_code
{
    my ($self, $str, $code_sep) = @_;

    my @dynsep = ();
    push(@dynsep, $code_sep) if ($code_sep && $code_sep ne "'");

    # Try to auto detect the string separator if none are provided.
    # Note that default single quote separtor is natively supported.
    if ($#dynsep == -1)
    {
        # if a dollar sign is found after EXECUTE then the following string
        # until an other dollar is found will be understand as a text delimiter
        @dynsep = $$str =~ /EXECUTE\s+(\$[^\$\s]*\$)/igs;
    }

    foreach my $sep (@dynsep)
    {
        while ($$str =~ s/(\Q$sep\E.*?\Q$sep\E)/TEXTVALUE$self->{idx_code}/s)
	{
            $self->{dynamic_code}{$self->{idx_code}} = $1;
            $self->{idx_code}++;
        }
    }

    # Replace any COMMENT constant between single quote 
    while ($$str =~ s/IS\s+('(?:.*?)')\s*;/IS TEXTVALUE$self->{idx_code};/s)
    {
        $self->{dynamic_code}{$self->{idx_code}} = $1;
        $self->{idx_code}++;
    }

    # keep untouched parts between double single quotes
    while ($$str =~ s/(PGFESCQ1(?:[^\r\n\|;]*?)PGFESCQ1)/TEXTVALUE$self->{idx_code}/s)
    {
        $self->{dynamic_code}{$self->{idx_code}} = $1;
        $self->{idx_code}++;
    }
}

=head2 _restore_dynamic_code

Internal function used to restore plpgsql dynamic code in plpgsql
that was removed by the _remove_dynamic_code() method.

=cut

sub _restore_dynamic_code
{
        my ($self, $str) = @_;

        $$str =~ s/TEXTVALUE(\d+)/$self->{dynamic_code}{$1}/gs;

}

=head2 _quote_operator

Internal function used to quote operator with multiple character
to be tokenized as a single word.
The original values are restored with function _restore_operator().

=cut

sub _quote_operator
{
    my ($self, $str) = @_;

    my @lines = split(/[\n]/, $$str);
    for (my $i = 0; $i <= $#lines; $i++)
    {
    	if ($lines[$i] =~ s/((?:CREATE|DROP|ALTER)\s+OPERATOR\s+(?:IF\s+EXISTS)?)\s*((:?[a-z0-9]+\.)?[\+\-\*\/<>=\~\!\@\#\%\^\&\|\`\?]+)\s*/$1 "$2" /i) {
		push(@{ $self->{operator} }, $2) if (!grep(/^\Q$2\E$/, @{ $self->{operator} }));
	}
    }
    $$str = join("\n", @lines);

    my $idx = 0;
    while ($$str =~ s/(NEGATOR|COMMUTATOR)\s*=\s*([^,\)\s]+)/\U$1\E$idx/is) {
	    $self->{uc($1)}{$idx} = "$1 = $2";
	    $idx++;
    }
}

=head2 _restore_operator

Internal function used to restore operator that was removed
by the _quote_operator() method.

=cut

sub _restore_operator
{
        my ($self, $str) = @_;

	foreach my $op (@{ $self->{operator} })
	{
		$$str =~ s/"$op"/$op/gs;
	}
	if (exists $self->{COMMUTATOR}) {
		$$str =~ s/COMMUTATOR(\d+)/$self->{COMMUTATOR}{$1}/igs;
	}
	if (exists $self->{NEGATOR}) {
		$$str =~ s/NEGATOR(\d+)/$self->{NEGATOR}{$1}/igs;
	}
}

=head2 _quote_comment_stmt

Internal function used to replace constant in a COMMENT statement
to be tokenized as a single word.
The original values are restored with function _restore_comment_stmt().

=cut

sub _quote_comment_stmt
{
    my ($self, $str) = @_;

    my $idx = 0;
    while ($$str =~ s/(COMMENT\s+ON\s+(?:.*?)\s+IS)\s+(\$[^;]+?\$)\s*;/$1 PGF_CMTSTR$idx;/is) {
        $self->{comment_str}{$idx} = $2;
	$idx++;
    }
}

=head2 _restore_comment_stmt

Internal function used to restore comment string that was removed
by the _quote_comment_stmt() method.

=cut

sub _restore_comment_stmt
{
        my ($self, $str) = @_;

	if (exists $self->{comment_str}) {
		$$str =~ s/PGF_CMTSTR(\d+)/$self->{comment_str}{$1}/igs;
	}
}

=head2 _remove_comments

Internal function used to remove comments in SQL code
to simplify the work of the wrap_lines. Comments must be
restored with the _restore_comments() method.

=cut

sub _remove_comments
{
    my $self = shift;

    my $idx = 0;

    while ($self->{ 'content' } =~ s/(\/\*(.*?)\*\/)/PGF_COMMENT${idx}A/s) {
        $self->{'comments'}{"PGF_COMMENT${idx}A"} = $1;
        $idx++;
    }
    my @lines = split(/\n/, $self->{ 'content' });
    for (my $j = 0; $j <= $#lines; $j++)
    {
        $lines[$j] //= '';
        # Extract multiline comments as a single placeholder
        my $old_j = $j;
        my $cmt = '';
        while ($j <= $#lines && $lines[$j] =~ /^(\s*\-\-.*)$/)
	{
            $cmt .= "$1\n";
            $j++;
        }
        if ( $j > $old_j )
	{
            chomp($cmt);
            $lines[$old_j] =~ s/^(\s*\-\-.*)$/PGF_COMMENT${idx}A/;
            $self->{'comments'}{"PGF_COMMENT${idx}A"} = $cmt;
            $idx++;
            $j--;
            while ($j > $old_j)
	    {
                delete $lines[$j];
                $j--;
            }
        }
        if ($lines[$j] =~ s/(\s*\-\-.*)$/PGF_COMMENT${idx}A/)
	{
            $self->{'comments'}{"PGF_COMMENT${idx}A"} = $1;
            $idx++;
        }

        # Mysql supports differents kinds of comment's starter
        if ( ($lines[$j] =~ s/(\s*COMMENT\s+'.*)$/PGF_COMMENT${idx}A/) ||
        	($lines[$j] =~ s/(\s*\# .*)$/PGF_COMMENT${idx}A/) )
	{
            $self->{'comments'}{"PGF_COMMENT${idx}A"} = $1;
            # Normalize start of comment
            $self->{'comments'}{"PGF_COMMENT${idx}A"} =~ s/^(\s*)COMMENT/$1\-\- /;
            $self->{'comments'}{"PGF_COMMENT${idx}A"} =~ s/^(\s*)\#/$1\-\- /;
            $idx++;
        }
    }
    $self->{ 'content' } = join("\n", @lines);

    # Remove extra newline after comment
    while ($self->{ 'content' } =~ s/(PGF_COMMENT\d+A[\n])[\n]+/$1/s) {};

    # Replace subsequent comment by a single one
    while ($self->{ 'content' } =~ s/(PGF_COMMENT\d+A\s*PGF_COMMENT\d+A)/PGF_COMMENT${idx}A/s)
    {
        $self->{'comments'}{"PGF_COMMENT${idx}A"} = $1;
        $idx++;
    }
}

=head2 _restore_comments

Internal function used to restore comments in SQL code
that was removed by the _remove_comments() method.

=cut

sub _restore_comments
{
    my ($self, $wrap_comment) = @_;

    if ($self->{'wrap_limit'} && $wrap_comment)
    {
	foreach my $k (keys %{$self->{'comments'}})
	{
	    if ($self->{'comments'}{$k} =~ /^(\s*)--[\r\n]/s)
	    {
		    next;
	    }
	    elsif ($self->{'comments'}{$k} =~ /^(\s*)--/)
	    {
		my $indent = $1 || '';
		if (length($self->{'comments'}{$k}) > $self->{'wrap_limit'} + ($self->{'wrap_limit'}*10/100))
	        {
		    my @data = split(/\n/, $self->{'comments'}{$k});
		    map { s/^\s*--//; } @data;
		    $self->{'comments'}{$k} = join("\n", @data);
		    $Text::Wrap::columns = $self->{'wrap_limit'};
		    my $t = wrap('', ' ', $self->{'comments'}{$k});
		    @data = split(/\n/, $t);
		    map { s/^/$indent--/; } @data;
		    $self->{'comments'}{$k} = join("\n", @data);
	        } else {
			$self->{'comments'}{$k} =~ s/^\s*--//s;
			$self->{'comments'}{$k} = $indent . "--$self->{'comments'}{$k}";
	        }
		# remove extra spaces after comment characters
		$self->{'comments'}{$k} =~ s/--[ ]+/-- /gs;
	    }
	}
    }

    while ($self->{ 'content' } =~ s/(PGF_COMMENT\d+A)/$self->{'comments'}{$1}/s) { delete $self->{'comments'}{$1}; };
}

=head2 wrap_lines

Internal function used to wrap line at a certain length.

=cut

sub wrap_lines
{
    my ($self, $wrap_comment) = @_;

    return if (!$self->{'wrap_limit'} || !$self->{ 'content' });

    $self->_remove_comments();

    my @lines = split(/\n/, $self->{ 'content' });
    $self->{ 'content' } = '';

    foreach my $l (@lines)
    {
	# Remove and store the indentation of the line
	my $indent = '';
	if ($l =~ s/^(\s+)//) {
		$indent = $1;
	}
	if (length($l) > $self->{'wrap_limit'} + ($self->{'wrap_limit'}*10/100))
	{
		$Text::Wrap::columns = $self->{'wrap_limit'};
		my $t = wrap($indent, " "x$self->{ 'spaces' } . $indent, $l);
		$self->{ 'content' } .= "$t\n";
	} else {
		$self->{ 'content' } .= $indent . "$l\n";
	}
    }

    $self->_restore_comments($wrap_comment || $self->{ 'wrap_comment' }) if ($self->{ 'content' });

    return;
}

sub _dump_var
{
	my $self = shift;
	foreach my $v (sort keys %{$self})
	{
		next if ($v !~ /^_/);
 		if ($self->{$v} =~ /ARRAY/) {
			print STDERR "$v => (", join(',', @{$self->{$v}}), ")\n";
		} else {
			print STDERR "$v => $self->{$v}\n";
		}
	}
}

=head1 AUTHOR

pgFormatter is an original work from Gilles Darold

=head1 BUGS

Please report any bugs or feature requests to: https://github.com/darold/pgFormatter/issues

=head1 COPYRIGHT

Copyright 2012-2023 Gilles Darold. All rights reserved.

=head1 LICENSE

pgFormatter is free software distributed under the PostgreSQL Licence.

A modified version of the SQL::Beautify Perl Module is embedded in pgFormatter
with copyright (C) 2009 by Jonas Kramer and is published under the terms of
the Artistic License 2.0.

=cut

1;
}

__DATA__

WRFILE: jquery.jqplot.min.css

.jqplot-target{position:relative;color:#666;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:1em}.jqplot-axis{font-size:.75em}.jqplot-xaxis{margin-top:10px}.jqplot-x2axis{margin-bottom:10px}.jqplot-yaxis{margin-right:10px}.jqplot-y2axis,.jqplot-y3axis,.jqplot-y4axis,.jqplot-y5axis,.jqplot-y6axis,.jqplot-y7axis,.jqplot-y8axis,.jqplot-y9axis,.jqplot-yMidAxis{margin-left:10px;margin-right:10px}.jqplot-axis-tick,.jqplot-xaxis-tick,.jqplot-yaxis-tick,.jqplot-x2axis-tick,.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick,.jqplot-yMidAxis-tick{position:absolute;white-space:pre}.jqplot-xaxis-tick{top:0;left:15px;vertical-align:top}.jqplot-x2axis-tick{bottom:0;left:15px;vertical-align:bottom}.jqplot-yaxis-tick{right:0;top:15px;text-align:right}.jqplot-yaxis-tick.jqplot-breakTick{right:-20px;margin-right:0;padding:1px 5px 1px 5px;z-index:2;font-size:1.5em}.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{left:0;top:15px;text-align:left}.jqplot-yMidAxis-tick{text-align:center;white-space:nowrap}.jqplot-xaxis-label{margin-top:10px;font-size:11pt;position:absolute}.jqplot-x2axis-label{margin-bottom:10px;font-size:11pt;position:absolute}.jqplot-yaxis-label{margin-right:10px;font-size:11pt;position:absolute}.jqplot-yMidAxis-label{font-size:11pt;position:absolute}.jqplot-y2axis-label,.jqplot-y3axis-label,.jqplot-y4axis-label,.jqplot-y5axis-label,.jqplot-y6axis-label,.jqplot-y7axis-label,.jqplot-y8axis-label,.jqplot-y9axis-label{font-size:11pt;margin-left:10px;position:absolute}.jqplot-meterGauge-tick{font-size:.75em;color:#999}.jqplot-meterGauge-label{font-size:1em;color:#999}table.jqplot-table-legend{margin-top:12px;margin-bottom:12px;margin-left:12px;margin-right:12px}table.jqplot-table-legend,table.jqplot-cursor-legend{background-color:rgba(255,255,255,0.6);border:1px solid #ccc;position:absolute;font-size:.75em}td.jqplot-table-legend{vertical-align:middle}td.jqplot-seriesToggle:hover,td.jqplot-seriesToggle:active{cursor:pointer}.jqplot-table-legend .jqplot-series-hidden{text-decoration:line-through}div.jqplot-table-legend-swatch-outline{border:1px solid #ccc;padding:1px}div.jqplot-table-legend-swatch{width:0;height:0;border-top-width:5px;border-bottom-width:5px;border-left-width:6px;border-right-width:6px;border-top-style:solid;border-bottom-style:solid;border-left-style:solid;border-right-style:solid}.jqplot-title{top:0;left:0;padding-bottom:.5em;font-size:1.2em}table.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em}.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px}.jqplot-highlighter-tooltip,.jqplot-canvasOverlay-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px}.jqplot-point-label{font-size:.75em;z-index:2}td.jqplot-cursor-legend-swatch{vertical-align:middle;text-align:center}div.jqplot-cursor-legend-swatch{width:1.2em;height:.7em}.jqplot-error{text-align:center}.jqplot-error-message{position:relative;top:46%;display:inline-block}div.jqplot-bubble-label{font-size:.8em;padding-left:2px;padding-right:2px;color:rgb(20%,20%,20%)}div.jqplot-bubble-label.jqplot-bubble-label-highlight{background:rgba(90%,90%,90%,0.7)}div.jqplot-noData-container{text-align:center;background-color:rgba(96%,96%,96%,0.3)}
WRFILE: jquery.min.js

/*!
 * jQuery JavaScript Library v1.9.1
 * http://jquery.com/
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 *
 * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2013-2-4
 */
(function(a2,aG){var ai,w,aC=typeof aG,l=a2.document,aL=a2.location,bi=a2.jQuery,H=a2.$,aa={},a6=[],s="1.9.1",aI=a6.concat,ao=a6.push,a4=a6.slice,aM=a6.indexOf,z=aa.toString,V=aa.hasOwnProperty,aQ=s.trim,bJ=function(e,b3){return new bJ.fn.init(e,b3,w)},bA=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ac=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,br=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,a=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,bh=/^[\],:{}\s]*$/,bk=/(?:^|:|,)(?:\s*\[)+/g,bG=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,aZ=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,bS=/^-ms-/,aV=/-([\da-z])/gi,M=function(e,b3){return b3.toUpperCase()},bW=function(e){if(l.addEventListener||e.type==="load"||l.readyState==="complete"){bl();bJ.ready()}},bl=function(){if(l.addEventListener){l.removeEventListener("DOMContentLoaded",bW,false);a2.removeEventListener("load",bW,false)}else{l.detachEvent("onreadystatechange",bW);a2.detachEvent("onload",bW)}};bJ.fn=bJ.prototype={jquery:s,constructor:bJ,init:function(e,b5,b4){var b3,b6;if(!e){return this}if(typeof e==="string"){if(e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3){b3=[null,e,null]}else{b3=br.exec(e)}if(b3&&(b3[1]||!b5)){if(b3[1]){b5=b5 instanceof bJ?b5[0]:b5;bJ.merge(this,bJ.parseHTML(b3[1],b5&&b5.nodeType?b5.ownerDocument||b5:l,true));if(a.test(b3[1])&&bJ.isPlainObject(b5)){for(b3 in b5){if(bJ.isFunction(this[b3])){this[b3](b5[b3])}else{this.attr(b3,b5[b3])}}}return this}else{b6=l.getElementById(b3[2]);if(b6&&b6.parentNode){if(b6.id!==b3[2]){return b4.find(e)}this.length=1;this[0]=b6}this.context=l;this.selector=e;return this}}else{if(!b5||b5.jquery){return(b5||b4).find(e)}else{return this.constructor(b5).find(e)}}}else{if(e.nodeType){this.context=this[0]=e;this.length=1;return this}else{if(bJ.isFunction(e)){return b4.ready(e)}}}if(e.selector!==aG){this.selector=e.selector;this.context=e.context}return bJ.makeArray(e,this)},selector:"",length:0,size:function(){return this.length},toArray:function(){return a4.call(this)},get:function(e){return e==null?this.toArray():(e<0?this[this.length+e]:this[e])},pushStack:function(e){var b3=bJ.merge(this.constructor(),e);b3.prevObject=this;b3.context=this.context;return b3},each:function(b3,e){return bJ.each(this,b3,e)},ready:function(e){bJ.ready.promise().done(e);return this},slice:function(){return this.pushStack(a4.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(b4){var e=this.length,b3=+b4+(b4<0?e:0);return this.pushStack(b3>=0&&b3<e?[this[b3]]:[])},map:function(e){return this.pushStack(bJ.map(this,function(b4,b3){return e.call(b4,b3,b4)}))},end:function(){return this.prevObject||this.constructor(null)},push:ao,sort:[].sort,splice:[].splice};bJ.fn.init.prototype=bJ.fn;bJ.extend=bJ.fn.extend=function(){var e,b8,b3,b4,cb,b9,b7=arguments[0]||{},b6=1,b5=arguments.length,ca=false;if(typeof b7==="boolean"){ca=b7;b7=arguments[1]||{};b6=2}if(typeof b7!=="object"&&!bJ.isFunction(b7)){b7={}}if(b5===b6){b7=this;--b6}for(;b6<b5;b6++){if((cb=arguments[b6])!=null){for(b4 in cb){e=b7[b4];b3=cb[b4];if(b7===b3){continue}if(ca&&b3&&(bJ.isPlainObject(b3)||(b8=bJ.isArray(b3)))){if(b8){b8=false;b9=e&&bJ.isArray(e)?e:[]}else{b9=e&&bJ.isPlainObject(e)?e:{}}b7[b4]=bJ.extend(ca,b9,b3)}else{if(b3!==aG){b7[b4]=b3}}}}}return b7};bJ.extend({noConflict:function(e){if(a2.$===bJ){a2.$=H}if(e&&a2.jQuery===bJ){a2.jQuery=bi}return bJ},isReady:false,readyWait:1,holdReady:function(e){if(e){bJ.readyWait++}else{bJ.ready(true)}},ready:function(e){if(e===true?--bJ.readyWait:bJ.isReady){return}if(!l.body){return setTimeout(bJ.ready)}bJ.isReady=true;if(e!==true&&--bJ.readyWait>0){return}ai.resolveWith(l,[bJ]);if(bJ.fn.trigger){bJ(l).trigger("ready").off("ready")}},isFunction:function(e){return bJ.type(e)==="function"},isArray:Array.isArray||function(e){return bJ.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return !isNaN(parseFloat(e))&&isFinite(e)},type:function(e){if(e==null){return String(e)}return typeof e==="object"||typeof e==="function"?aa[z.call(e)]||"object":typeof e},isPlainObject:function(b5){if(!b5||bJ.type(b5)!=="object"||b5.nodeType||bJ.isWindow(b5)){return false}try{if(b5.constructor&&!V.call(b5,"constructor")&&!V.call(b5.constructor.prototype,"isPrototypeOf")){return false}}catch(b4){return false}var b3;for(b3 in b5){}return b3===aG||V.call(b5,b3)},isEmptyObject:function(b3){var e;for(e in b3){return false}return true},error:function(e){throw new Error(e)},parseHTML:function(b6,b4,b5){if(!b6||typeof b6!=="string"){return null}if(typeof b4==="boolean"){b5=b4;b4=false}b4=b4||l;var b3=a.exec(b6),e=!b5&&[];if(b3){return[b4.createElement(b3[1])]}b3=bJ.buildFragment([b6],b4,e);if(e){bJ(e).remove()}return bJ.merge([],b3.childNodes)},parseJSON:function(e){if(a2.JSON&&a2.JSON.parse){return a2.JSON.parse(e)}if(e===null){return e}if(typeof e==="string"){e=bJ.trim(e);if(e){if(bh.test(e.replace(bG,"@").replace(aZ,"]").replace(bk,""))){return(new Function("return "+e))()}}}bJ.error("Invalid JSON: "+e)},parseXML:function(b5){var b3,b4;if(!b5||typeof b5!=="string"){return null}try{if(a2.DOMParser){b4=new DOMParser();b3=b4.parseFromString(b5,"text/xml")}else{b3=new ActiveXObject("Microsoft.XMLDOM");b3.async="false";b3.loadXML(b5)}}catch(b6){b3=aG}if(!b3||!b3.documentElement||b3.getElementsByTagName("parsererror").length){bJ.error("Invalid XML: "+b5)}return b3},noop:function(){},globalEval:function(e){if(e&&bJ.trim(e)){(a2.execScript||function(b3){a2["eval"].call(a2,b3)})(e)}},camelCase:function(e){return e.replace(bS,"ms-").replace(aV,M)},nodeName:function(b3,e){return b3.nodeName&&b3.nodeName.toLowerCase()===e.toLowerCase()},each:function(b7,b8,b3){var b6,b4=0,b5=b7.length,e=ab(b7);if(b3){if(e){for(;b4<b5;b4++){b6=b8.apply(b7[b4],b3);if(b6===false){break}}}else{for(b4 in b7){b6=b8.apply(b7[b4],b3);if(b6===false){break}}}}else{if(e){for(;b4<b5;b4++){b6=b8.call(b7[b4],b4,b7[b4]);if(b6===false){break}}}else{for(b4 in b7){b6=b8.call(b7[b4],b4,b7[b4]);if(b6===false){break}}}}return b7},trim:aQ&&!aQ.call("\uFEFF\xA0")?function(e){return e==null?"":aQ.call(e)}:function(e){return e==null?"":(e+"").replace(C,"")},makeArray:function(e,b4){var b3=b4||[];if(e!=null){if(ab(Object(e))){bJ.merge(b3,typeof e==="string"?[e]:e)}else{ao.call(b3,e)}}return b3},inArray:function(b5,b3,b4){var e;if(b3){if(aM){return aM.call(b3,b5,b4)}e=b3.length;b4=b4?b4<0?Math.max(0,e+b4):b4:0;for(;b4<e;b4++){if(b4 in b3&&b3[b4]===b5){return b4}}}return -1},merge:function(b6,b4){var e=b4.length,b5=b6.length,b3=0;if(typeof e==="number"){for(;b3<e;b3++){b6[b5++]=b4[b3]}}else{while(b4[b3]!==aG){b6[b5++]=b4[b3++]}}b6.length=b5;return b6},grep:function(b3,b8,e){var b7,b4=[],b5=0,b6=b3.length;e=!!e;for(;b5<b6;b5++){b7=!!b8(b3[b5],b5);if(e!==b7){b4.push(b3[b5])}}return b4},map:function(b4,b9,e){var b8,b6=0,b7=b4.length,b3=ab(b4),b5=[];if(b3){for(;b6<b7;b6++){b8=b9(b4[b6],b6,e);if(b8!=null){b5[b5.length]=b8}}}else{for(b6 in b4){b8=b9(b4[b6],b6,e);if(b8!=null){b5[b5.length]=b8}}}return aI.apply([],b5)},guid:1,proxy:function(b6,b5){var e,b4,b3;if(typeof b5==="string"){b3=b6[b5];b5=b6;b6=b3}if(!bJ.isFunction(b6)){return aG}e=a4.call(arguments,2);b4=function(){return b6.apply(b5||this,e.concat(a4.call(arguments)))};b4.guid=b6.guid=b6.guid||bJ.guid++;return b4},access:function(e,b7,b9,b8,b5,cb,ca){var b4=0,b3=e.length,b6=b9==null;if(bJ.type(b9)==="object"){b5=true;for(b4 in b9){bJ.access(e,b7,b4,b9[b4],true,cb,ca)}}else{if(b8!==aG){b5=true;if(!bJ.isFunction(b8)){ca=true}if(b6){if(ca){b7.call(e,b8);b7=null}else{b6=b7;b7=function(cd,cc,ce){return b6.call(bJ(cd),ce)}}}if(b7){for(;b4<b3;b4++){b7(e[b4],b9,ca?b8:b8.call(e[b4],b4,b7(e[b4],b9)))}}}}return b5?e:b6?b7.call(e):b3?b7(e[0],b9):cb},now:function(){return(new Date()).getTime()}});bJ.ready.promise=function(b6){if(!ai){ai=bJ.Deferred();if(l.readyState==="complete"){setTimeout(bJ.ready)}else{if(l.addEventListener){l.addEventListener("DOMContentLoaded",bW,false);a2.addEventListener("load",bW,false)}else{l.attachEvent("onreadystatechange",bW);a2.attachEvent("onload",bW);var b5=false;try{b5=a2.frameElement==null&&l.documentElement}catch(b4){}if(b5&&b5.doScroll){(function b3(){if(!bJ.isReady){try{b5.doScroll("left")}catch(b7){return setTimeout(b3,50)}bl();bJ.ready()}})()}}}}return ai.promise(b6)};bJ.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(b3,e){aa["[object "+e+"]"]=e.toLowerCase()});function ab(b4){var b3=b4.length,e=bJ.type(b4);if(bJ.isWindow(b4)){return false}if(b4.nodeType===1&&b3){return true}return e==="array"||e!=="function"&&(b3===0||typeof b3==="number"&&b3>0&&(b3-1) in b4)}w=bJ(l);var bY={};function ae(b3){var e=bY[b3]={};bJ.each(b3.match(ac)||[],function(b5,b4){e[b4]=true});return e}bJ.Callbacks=function(cc){cc=typeof cc==="string"?(bY[cc]||ae(cc)):bJ.extend({},cc);var b6,b5,e,b7,b8,b4,b9=[],ca=!cc.once&&[],b3=function(cd){b5=cc.memory&&cd;e=true;b8=b4||0;b4=0;b7=b9.length;b6=true;for(;b9&&b8<b7;b8++){if(b9[b8].apply(cd[0],cd[1])===false&&cc.stopOnFalse){b5=false;break}}b6=false;if(b9){if(ca){if(ca.length){b3(ca.shift())}}else{if(b5){b9=[]}else{cb.disable()}}}},cb={add:function(){if(b9){var ce=b9.length;(function cd(cf){bJ.each(cf,function(ch,cg){var ci=bJ.type(cg);if(ci==="function"){if(!cc.unique||!cb.has(cg)){b9.push(cg)}}else{if(cg&&cg.length&&ci!=="string"){cd(cg)}}})})(arguments);if(b6){b7=b9.length}else{if(b5){b4=ce;b3(b5)}}}return this},remove:function(){if(b9){bJ.each(arguments,function(cf,cd){var ce;while((ce=bJ.inArray(cd,b9,ce))>-1){b9.splice(ce,1);if(b6){if(ce<=b7){b7--}if(ce<=b8){b8--}}}})}return this},has:function(cd){return cd?bJ.inArray(cd,b9)>-1:!!(b9&&b9.length)},empty:function(){b9=[];return this},disable:function(){b9=ca=b5=aG;return this},disabled:function(){return !b9},lock:function(){ca=aG;if(!b5){cb.disable()}return this},locked:function(){return !ca},fireWith:function(ce,cd){cd=cd||[];cd=[ce,cd.slice?cd.slice():cd];if(b9&&(!e||ca)){if(b6){ca.push(cd)}else{b3(cd)}}return this},fire:function(){cb.fireWith(this,arguments);return this},fired:function(){return !!e}};return cb};bJ.extend({Deferred:function(b4){var b3=[["resolve","done",bJ.Callbacks("once memory"),"resolved"],["reject","fail",bJ.Callbacks("once memory"),"rejected"],["notify","progress",bJ.Callbacks("memory")]],b5="pending",b6={state:function(){return b5},always:function(){e.done(arguments).fail(arguments);return this},then:function(){var b7=arguments;return bJ.Deferred(function(b8){bJ.each(b3,function(ca,b9){var cc=b9[0],cb=bJ.isFunction(b7[ca])&&b7[ca];e[b9[1]](function(){var cd=cb&&cb.apply(this,arguments);if(cd&&bJ.isFunction(cd.promise)){cd.promise().done(b8.resolve).fail(b8.reject).progress(b8.notify)}else{b8[cc+"With"](this===b6?b8.promise():this,cb?[cd]:arguments)}})});b7=null}).promise()},promise:function(b7){return b7!=null?bJ.extend(b7,b6):b6}},e={};b6.pipe=b6.then;bJ.each(b3,function(b8,b7){var ca=b7[2],b9=b7[3];b6[b7[1]]=ca.add;if(b9){ca.add(function(){b5=b9},b3[b8^1][2].disable,b3[2][2].lock)}e[b7[0]]=function(){e[b7[0]+"With"](this===e?b6:this,arguments);return this};e[b7[0]+"With"]=ca.fireWith});b6.promise(e);if(b4){b4.call(e,e)}return e},when:function(b6){var b4=0,b8=a4.call(arguments),e=b8.length,b3=e!==1||(b6&&bJ.isFunction(b6.promise))?e:0,cb=b3===1?b6:bJ.Deferred(),b5=function(cd,ce,cc){return function(cf){ce[cd]=this;cc[cd]=arguments.length>1?a4.call(arguments):cf;if(cc===ca){cb.notifyWith(ce,cc)}else{if(!(--b3)){cb.resolveWith(ce,cc)}}}},ca,b7,b9;if(e>1){ca=new Array(e);b7=new Array(e);b9=new Array(e);for(;b4<e;b4++){if(b8[b4]&&bJ.isFunction(b8[b4].promise)){b8[b4].promise().done(b5(b4,b9,b8)).fail(cb.reject).progress(b5(b4,b7,ca))}else{--b3}}}if(!b3){cb.resolveWith(b9,b8)}return cb.promise()}});bJ.support=(function(){var ce,cd,cb,ca,cc,b9,b5,b7,b4,b6,b3=l.createElement("div");b3.setAttribute("className","t");b3.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";cd=b3.getElementsByTagName("*");cb=b3.getElementsByTagName("a")[0];if(!cd||!cb||!cd.length){return{}}cc=l.createElement("select");b5=cc.appendChild(l.createElement("option"));ca=b3.getElementsByTagName("input")[0];cb.style.cssText="top:1px;float:left;opacity:.5";ce={getSetAttribute:b3.className!=="t",leadingWhitespace:b3.firstChild.nodeType===3,tbody:!b3.getElementsByTagName("tbody").length,htmlSerialize:!!b3.getElementsByTagName("link").length,style:/top/.test(cb.getAttribute("style")),hrefNormalized:cb.getAttribute("href")==="/a",opacity:/^0.5/.test(cb.style.opacity),cssFloat:!!cb.style.cssFloat,checkOn:!!ca.value,optSelected:b5.selected,enctype:!!l.createElement("form").enctype,html5Clone:l.createElement("nav").cloneNode(true).outerHTML!=="<:nav></:nav>",boxModel:l.compatMode==="CSS1Compat",deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true,boxSizingReliable:true,pixelPosition:false};ca.checked=true;ce.noCloneChecked=ca.cloneNode(true).checked;cc.disabled=true;ce.optDisabled=!b5.disabled;try{delete b3.test}catch(b8){ce.deleteExpando=false}ca=l.createElement("input");ca.setAttribute("value","");ce.input=ca.getAttribute("value")==="";ca.value="t";ca.setAttribute("type","radio");ce.radioValue=ca.value==="t";ca.setAttribute("checked","t");ca.setAttribute("name","t");b9=l.createDocumentFragment();b9.appendChild(ca);ce.appendChecked=ca.checked;ce.checkClone=b9.cloneNode(true).cloneNode(true).lastChild.checked;if(b3.attachEvent){b3.attachEvent("onclick",function(){ce.noCloneEvent=false});b3.cloneNode(true).click()}for(b6 in {submit:true,change:true,focusin:true}){b3.setAttribute(b7="on"+b6,"t");ce[b6+"Bubbles"]=b7 in a2||b3.attributes[b7].expando===false}b3.style.backgroundClip="content-box";b3.cloneNode(true).style.backgroundClip="";ce.clearCloneStyle=b3.style.backgroundClip==="content-box";bJ(function(){var cf,ci,ch,cg="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",e=l.getElementsByTagName("body")[0];if(!e){return}cf=l.createElement("div");cf.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";e.appendChild(cf).appendChild(b3);b3.innerHTML="<table><tr><td></td><td>t</td></tr></table>";ch=b3.getElementsByTagName("td");ch[0].style.cssText="padding:0;margin:0;border:0;display:none";b4=(ch[0].offsetHeight===0);ch[0].style.display="";ch[1].style.display="none";ce.reliableHiddenOffsets=b4&&(ch[0].offsetHeight===0);b3.innerHTML="";b3.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";ce.boxSizing=(b3.offsetWidth===4);ce.doesNotIncludeMarginInBodyOffset=(e.offsetTop!==1);if(a2.getComputedStyle){ce.pixelPosition=(a2.getComputedStyle(b3,null)||{}).top!=="1%";ce.boxSizingReliable=(a2.getComputedStyle(b3,null)||{width:"4px"}).width==="4px";ci=b3.appendChild(l.createElement("div"));ci.style.cssText=b3.style.cssText=cg;ci.style.marginRight=ci.style.width="0";b3.style.width="1px";ce.reliableMarginRight=!parseFloat((a2.getComputedStyle(ci,null)||{}).marginRight)}if(typeof b3.style.zoom!==aC){b3.innerHTML="";b3.style.cssText=cg+"width:1px;padding:1px;display:inline;zoom:1";ce.inlineBlockNeedsLayout=(b3.offsetWidth===3);b3.style.display="block";b3.innerHTML="<div></div>";b3.firstChild.style.width="5px";ce.shrinkWrapBlocks=(b3.offsetWidth!==3);if(ce.inlineBlockNeedsLayout){e.style.zoom=1}}e.removeChild(cf);cf=b3=ch=ci=null});cd=cc=b9=b5=cb=ca=null;return ce})();var bw=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,aN=/([A-Z])/g;function ba(b5,b3,b7,b6){if(!bJ.acceptData(b5)){return}var b8,ca,cb=bJ.expando,b9=typeof b3==="string",cc=b5.nodeType,e=cc?bJ.cache:b5,b4=cc?b5[cb]:b5[cb]&&cb;if((!b4||!e[b4]||(!b6&&!e[b4].data))&&b9&&b7===aG){return}if(!b4){if(cc){b5[cb]=b4=a6.pop()||bJ.guid++}else{b4=cb}}if(!e[b4]){e[b4]={};if(!cc){e[b4].toJSON=bJ.noop}}if(typeof b3==="object"||typeof b3==="function"){if(b6){e[b4]=bJ.extend(e[b4],b3)}else{e[b4].data=bJ.extend(e[b4].data,b3)}}b8=e[b4];if(!b6){if(!b8.data){b8.data={}}b8=b8.data}if(b7!==aG){b8[bJ.camelCase(b3)]=b7}if(b9){ca=b8[b3];if(ca==null){ca=b8[bJ.camelCase(b3)]}}else{ca=b8}return ca}function Z(b5,b3,b6){if(!bJ.acceptData(b5)){return}var b8,b7,b9,ca=b5.nodeType,e=ca?bJ.cache:b5,b4=ca?b5[bJ.expando]:bJ.expando;if(!e[b4]){return}if(b3){b9=b6?e[b4]:e[b4].data;if(b9){if(!bJ.isArray(b3)){if(b3 in b9){b3=[b3]}else{b3=bJ.camelCase(b3);if(b3 in b9){b3=[b3]}else{b3=b3.split(" ")}}}else{b3=b3.concat(bJ.map(b3,bJ.camelCase))}for(b8=0,b7=b3.length;b8<b7;b8++){delete b9[b3[b8]]}if(!(b6?N:bJ.isEmptyObject)(b9)){return}}}if(!b6){delete e[b4].data;if(!N(e[b4])){return}}if(ca){bJ.cleanData([b5],true)}else{if(bJ.support.deleteExpando||e!=e.window){delete e[b4]}else{e[b4]=null}}}bJ.extend({cache:{},expando:"jQuery"+(s+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?bJ.cache[e[bJ.expando]]:e[bJ.expando];return !!e&&!N(e)},data:function(b3,e,b4){return ba(b3,e,b4)},removeData:function(b3,e){return Z(b3,e)},_data:function(b3,e,b4){return ba(b3,e,b4,true)},_removeData:function(b3,e){return Z(b3,e,true)},acceptData:function(b3){if(b3.nodeType&&b3.nodeType!==1&&b3.nodeType!==9){return false}var e=b3.nodeName&&bJ.noData[b3.nodeName.toLowerCase()];return !e||e!==true&&b3.getAttribute("classid")===e}});bJ.fn.extend({data:function(b5,b8){var b3,e,b6=this[0],b4=0,b7=null;if(b5===aG){if(this.length){b7=bJ.data(b6);if(b6.nodeType===1&&!bJ._data(b6,"parsedAttrs")){b3=b6.attributes;for(;b4<b3.length;b4++){e=b3[b4].name;if(!e.indexOf("data-")){e=bJ.camelCase(e.slice(5));by(b6,e,b7[e])}}bJ._data(b6,"parsedAttrs",true)}}return b7}if(typeof b5==="object"){return this.each(function(){bJ.data(this,b5)})}return bJ.access(this,function(b9){if(b9===aG){return b6?by(b6,b5,bJ.data(b6,b5)):null}this.each(function(){bJ.data(this,b5,b9)})},null,b8,arguments.length>1,null,true)},removeData:function(e){return this.each(function(){bJ.removeData(this,e)})}});function by(b5,b4,b6){if(b6===aG&&b5.nodeType===1){var b3="data-"+b4.replace(aN,"-$1").toLowerCase();b6=b5.getAttribute(b3);if(typeof b6==="string"){try{b6=b6==="true"?true:b6==="false"?false:b6==="null"?null:+b6+""===b6?+b6:bw.test(b6)?bJ.parseJSON(b6):b6}catch(b7){}bJ.data(b5,b4,b6)}else{b6=aG}}return b6}function N(b3){var e;for(e in b3){if(e==="data"&&bJ.isEmptyObject(b3[e])){continue}if(e!=="toJSON"){return false}}return true}bJ.extend({queue:function(b4,b3,b5){var e;if(b4){b3=(b3||"fx")+"queue";e=bJ._data(b4,b3);if(b5){if(!e||bJ.isArray(b5)){e=bJ._data(b4,b3,bJ.makeArray(b5))}else{e.push(b5)}}return e||[]}},dequeue:function(b7,b6){b6=b6||"fx";var b3=bJ.queue(b7,b6),b8=b3.length,b5=b3.shift(),e=bJ._queueHooks(b7,b6),b4=function(){bJ.dequeue(b7,b6)};if(b5==="inprogress"){b5=b3.shift();b8--}e.cur=b5;if(b5){if(b6==="fx"){b3.unshift("inprogress")}delete e.stop;b5.call(b7,b4,e)}if(!b8&&e){e.empty.fire()}},_queueHooks:function(b4,b3){var e=b3+"queueHooks";return bJ._data(b4,e)||bJ._data(b4,e,{empty:bJ.Callbacks("once memory").add(function(){bJ._removeData(b4,b3+"queue");bJ._removeData(b4,e)})})}});bJ.fn.extend({queue:function(e,b3){var b4=2;if(typeof e!=="string"){b3=e;e="fx";b4--}if(arguments.length<b4){return bJ.queue(this[0],e)}return b3===aG?this:this.each(function(){var b5=bJ.queue(this,e,b3);bJ._queueHooks(this,e);if(e==="fx"&&b5[0]!=="inprogress"){bJ.dequeue(this,e)}})},dequeue:function(e){return this.each(function(){bJ.dequeue(this,e)})},delay:function(b3,e){b3=bJ.fx?bJ.fx.speeds[b3]||b3:b3;e=e||"fx";return this.queue(e,function(b5,b4){var b6=setTimeout(b5,b3);b4.stop=function(){clearTimeout(b6)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(b4,b8){var b3,b5=1,b9=bJ.Deferred(),b7=this,e=this.length,b6=function(){if(!(--b5)){b9.resolveWith(b7,[b7])}};if(typeof b4!=="string"){b8=b4;b4=aG}b4=b4||"fx";while(e--){b3=bJ._data(b7[e],b4+"queueHooks");if(b3&&b3.empty){b5++;b3.empty.add(b6)}}b6();return b9.promise(b8)}});var a8,bZ,bM=/[\t\r\n]/g,ak=/\r/g,aF=/^(?:input|select|textarea|button|object)$/i,D=/^(?:a|area)$/i,L=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,aq=/^(?:checked|selected)$/i,bP=bJ.support.getSetAttribute,bF=bJ.support.input;bJ.fn.extend({attr:function(e,b3){return bJ.access(this,bJ.attr,e,b3,arguments.length>1)},removeAttr:function(e){return this.each(function(){bJ.removeAttr(this,e)})},prop:function(e,b3){return bJ.access(this,bJ.prop,e,b3,arguments.length>1)},removeProp:function(e){e=bJ.propFix[e]||e;return this.each(function(){try{this[e]=aG;delete this[e]}catch(b3){}})},addClass:function(b9){var b3,e,ca,b6,b4,b5=0,b7=this.length,b8=typeof b9==="string"&&b9;if(bJ.isFunction(b9)){return this.each(function(cb){bJ(this).addClass(b9.call(this,cb,this.className))})}if(b8){b3=(b9||"").match(ac)||[];for(;b5<b7;b5++){e=this[b5];ca=e.nodeType===1&&(e.className?(" "+e.className+" ").replace(bM," "):" ");if(ca){b4=0;while((b6=b3[b4++])){if(ca.indexOf(" "+b6+" ")<0){ca+=b6+" "}}e.className=bJ.trim(ca)}}}return this},removeClass:function(b9){var b3,e,ca,b6,b4,b5=0,b7=this.length,b8=arguments.length===0||typeof b9==="string"&&b9;if(bJ.isFunction(b9)){return this.each(function(cb){bJ(this).removeClass(b9.call(this,cb,this.className))})}if(b8){b3=(b9||"").match(ac)||[];for(;b5<b7;b5++){e=this[b5];ca=e.nodeType===1&&(e.className?(" "+e.className+" ").replace(bM," "):"");if(ca){b4=0;while((b6=b3[b4++])){while(ca.indexOf(" "+b6+" ")>=0){ca=ca.replace(" "+b6+" "," ")}}e.className=b9?bJ.trim(ca):""}}}return this},toggleClass:function(b5,b3){var b4=typeof b5,e=typeof b3==="boolean";if(bJ.isFunction(b5)){return this.each(function(b6){bJ(this).toggleClass(b5.call(this,b6,this.className,b3),b3)})}return this.each(function(){if(b4==="string"){var b8,b7=0,b6=bJ(this),b9=b3,ca=b5.match(ac)||[];while((b8=ca[b7++])){b9=e?b9:!b6.hasClass(b8);b6[b9?"addClass":"removeClass"](b8)}}else{if(b4===aC||b4==="boolean"){if(this.className){bJ._data(this,"__className__",this.className)}this.className=this.className||b5===false?"":bJ._data(this,"__className__")||""}}})},hasClass:function(e){var b5=" "+e+" ",b4=0,b3=this.length;for(;b4<b3;b4++){if(this[b4].nodeType===1&&(" "+this[b4].className+" ").replace(bM," ").indexOf(b5)>=0){return true}}return false},val:function(b5){var b3,e,b6,b4=this[0];if(!arguments.length){if(b4){e=bJ.valHooks[b4.type]||bJ.valHooks[b4.nodeName.toLowerCase()];if(e&&"get" in e&&(b3=e.get(b4,"value"))!==aG){return b3}b3=b4.value;return typeof b3==="string"?b3.replace(ak,""):b3==null?"":b3}return}b6=bJ.isFunction(b5);return this.each(function(b8){var b9,b7=bJ(this);if(this.nodeType!==1){return}if(b6){b9=b5.call(this,b8,b7.val())}else{b9=b5}if(b9==null){b9=""}else{if(typeof b9==="number"){b9+=""}else{if(bJ.isArray(b9)){b9=bJ.map(b9,function(ca){return ca==null?"":ca+""})}}}e=bJ.valHooks[this.type]||bJ.valHooks[this.nodeName.toLowerCase()];if(!e||!("set" in e)||e.set(this,b9,"value")===aG){this.value=b9}})}});bJ.extend({valHooks:{option:{get:function(e){var b3=e.attributes.value;return !b3||b3.specified?e.value:e.text}},select:{get:function(e){var b8,b4,ca=e.options,b6=e.selectedIndex,b5=e.type==="select-one"||b6<0,b9=b5?null:[],b7=b5?b6+1:ca.length,b3=b6<0?b7:b5?b6:0;for(;b3<b7;b3++){b4=ca[b3];if((b4.selected||b3===b6)&&(bJ.support.optDisabled?!b4.disabled:b4.getAttribute("disabled")===null)&&(!b4.parentNode.disabled||!bJ.nodeName(b4.parentNode,"optgroup"))){b8=bJ(b4).val();if(b5){return b8}b9.push(b8)}}return b9},set:function(b3,b4){var e=bJ.makeArray(b4);bJ(b3).find("option").each(function(){this.selected=bJ.inArray(bJ(this).val(),e)>=0});if(!e.length){b3.selectedIndex=-1}return e}}},attr:function(b7,b5,b8){var e,b6,b4,b3=b7.nodeType;if(!b7||b3===3||b3===8||b3===2){return}if(typeof b7.getAttribute===aC){return bJ.prop(b7,b5,b8)}b6=b3!==1||!bJ.isXMLDoc(b7);if(b6){b5=b5.toLowerCase();e=bJ.attrHooks[b5]||(L.test(b5)?bZ:a8)}if(b8!==aG){if(b8===null){bJ.removeAttr(b7,b5)}else{if(e&&b6&&"set" in e&&(b4=e.set(b7,b8,b5))!==aG){return b4}else{b7.setAttribute(b5,b8+"");return b8}}}else{if(e&&b6&&"get" in e&&(b4=e.get(b7,b5))!==null){return b4}else{if(typeof b7.getAttribute!==aC){b4=b7.getAttribute(b5)}return b4==null?aG:b4}}},removeAttr:function(b4,b6){var e,b5,b3=0,b7=b6&&b6.match(ac);if(b7&&b4.nodeType===1){while((e=b7[b3++])){b5=bJ.propFix[e]||e;if(L.test(e)){if(!bP&&aq.test(e)){b4[bJ.camelCase("default-"+e)]=b4[b5]=false}else{b4[b5]=false}}else{bJ.attr(b4,e,"")}b4.removeAttribute(bP?e:b5)}}},attrHooks:{type:{set:function(e,b3){if(!bJ.support.radioValue&&b3==="radio"&&bJ.nodeName(e,"input")){var b4=e.value;e.setAttribute("type",b3);if(b4){e.value=b4}return b3}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(b7,b5,b8){var b4,e,b6,b3=b7.nodeType;if(!b7||b3===3||b3===8||b3===2){return}b6=b3!==1||!bJ.isXMLDoc(b7);if(b6){b5=bJ.propFix[b5]||b5;e=bJ.propHooks[b5]}if(b8!==aG){if(e&&"set" in e&&(b4=e.set(b7,b8,b5))!==aG){return b4}else{return(b7[b5]=b8)}}else{if(e&&"get" in e&&(b4=e.get(b7,b5))!==null){return b4}else{return b7[b5]}}},propHooks:{tabIndex:{get:function(b3){var e=b3.getAttributeNode("tabindex");return e&&e.specified?parseInt(e.value,10):aF.test(b3.nodeName)||D.test(b3.nodeName)&&b3.href?0:aG}}}});bZ={get:function(b5,b3){var b6=bJ.prop(b5,b3),e=typeof b6==="boolean"&&b5.getAttribute(b3),b4=typeof b6==="boolean"?bF&&bP?e!=null:aq.test(b3)?b5[bJ.camelCase("default-"+b3)]:!!e:b5.getAttributeNode(b3);return b4&&b4.value!==false?b3.toLowerCase():aG},set:function(b3,b4,e){if(b4===false){bJ.removeAttr(b3,e)}else{if(bF&&bP||!aq.test(e)){b3.setAttribute(!bP&&bJ.propFix[e]||e,e)}else{b3[bJ.camelCase("default-"+e)]=b3[e]=true}}return e}};if(!bF||!bP){bJ.attrHooks.value={get:function(b4,b3){var e=b4.getAttributeNode(b3);return bJ.nodeName(b4,"input")?b4.defaultValue:e&&e.specified?e.value:aG},set:function(b3,b4,e){if(bJ.nodeName(b3,"input")){b3.defaultValue=b4}else{return a8&&a8.set(b3,b4,e)}}}}if(!bP){a8=bJ.valHooks.button={get:function(b4,b3){var e=b4.getAttributeNode(b3);return e&&(b3==="id"||b3==="name"||b3==="coords"?e.value!=="":e.specified)?e.value:aG},set:function(b4,b5,b3){var e=b4.getAttributeNode(b3);if(!e){b4.setAttributeNode((e=b4.ownerDocument.createAttribute(b3)))}e.value=b5+="";return b3==="value"||b5===b4.getAttribute(b3)?b5:aG}};bJ.attrHooks.contenteditable={get:a8.get,set:function(b3,b4,e){a8.set(b3,b4===""?false:b4,e)}};bJ.each(["width","height"],function(b3,e){bJ.attrHooks[e]=bJ.extend(bJ.attrHooks[e],{set:function(b4,b5){if(b5===""){b4.setAttribute(e,"auto");return b5}}})})}if(!bJ.support.hrefNormalized){bJ.each(["href","src","width","height"],function(b3,e){bJ.attrHooks[e]=bJ.extend(bJ.attrHooks[e],{get:function(b5){var b4=b5.getAttribute(e,2);return b4==null?aG:b4}})});bJ.each(["href","src"],function(b3,e){bJ.propHooks[e]={get:function(b4){return b4.getAttribute(e,4)}}})}if(!bJ.support.style){bJ.attrHooks.style={get:function(e){return e.style.cssText||aG},set:function(e,b3){return(e.style.cssText=b3+"")}}}if(!bJ.support.optSelected){bJ.propHooks.selected=bJ.extend(bJ.propHooks.selected,{get:function(b3){var e=b3.parentNode;if(e){e.selectedIndex;if(e.parentNode){e.parentNode.selectedIndex}}return null}})}if(!bJ.support.enctype){bJ.propFix.enctype="encoding"}if(!bJ.support.checkOn){bJ.each(["radio","checkbox"],function(){bJ.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}})}bJ.each(["radio","checkbox"],function(){bJ.valHooks[this]=bJ.extend(bJ.valHooks[this],{set:function(e,b3){if(bJ.isArray(b3)){return(e.checked=bJ.inArray(bJ(e).val(),b3)>=0)}}})});var bH=/^(?:input|select|textarea)$/i,a3=/^key/,bN=/^(?:mouse|contextmenu)|click/,bB=/^(?:focusinfocus|focusoutblur)$/,bu=/^([^.]*)(?:\.(.+)|)$/;function R(){return true}function X(){return false}bJ.event={global:{},add:function(b6,cb,cg,b8,b7){var b9,ch,ci,b4,cd,ca,cf,b5,ce,e,b3,cc=bJ._data(b6);if(!cc){return}if(cg.handler){b4=cg;cg=b4.handler;b7=b4.selector}if(!cg.guid){cg.guid=bJ.guid++}if(!(ch=cc.events)){ch=cc.events={}}if(!(ca=cc.handle)){ca=cc.handle=function(cj){return typeof bJ!==aC&&(!cj||bJ.event.triggered!==cj.type)?bJ.event.dispatch.apply(ca.elem,arguments):aG};ca.elem=b6}cb=(cb||"").match(ac)||[""];ci=cb.length;while(ci--){b9=bu.exec(cb[ci])||[];ce=b3=b9[1];e=(b9[2]||"").split(".").sort();cd=bJ.event.special[ce]||{};ce=(b7?cd.delegateType:cd.bindType)||ce;cd=bJ.event.special[ce]||{};cf=bJ.extend({type:ce,origType:b3,data:b8,handler:cg,guid:cg.guid,selector:b7,needsContext:b7&&bJ.expr.match.needsContext.test(b7),namespace:e.join(".")},b4);if(!(b5=ch[ce])){b5=ch[ce]=[];b5.delegateCount=0;if(!cd.setup||cd.setup.call(b6,b8,e,ca)===false){if(b6.addEventListener){b6.addEventListener(ce,ca,false)}else{if(b6.attachEvent){b6.attachEvent("on"+ce,ca)}}}}if(cd.add){cd.add.call(b6,cf);if(!cf.handler.guid){cf.handler.guid=cg.guid}}if(b7){b5.splice(b5.delegateCount++,0,cf)}else{b5.push(cf)}bJ.event.global[ce]=true}b6=null},remove:function(b5,cb,ci,b6,ca){var b8,cf,b9,b7,ch,cg,cd,b4,ce,e,b3,cc=bJ.hasData(b5)&&bJ._data(b5);if(!cc||!(cg=cc.events)){return}cb=(cb||"").match(ac)||[""];ch=cb.length;while(ch--){b9=bu.exec(cb[ch])||[];ce=b3=b9[1];e=(b9[2]||"").split(".").sort();if(!ce){for(ce in cg){bJ.event.remove(b5,ce+cb[ch],ci,b6,true)}continue}cd=bJ.event.special[ce]||{};ce=(b6?cd.delegateType:cd.bindType)||ce;b4=cg[ce]||[];b9=b9[2]&&new RegExp("(^|\\.)"+e.join("\\.(?:.*\\.|)")+"(\\.|$)");b7=b8=b4.length;while(b8--){cf=b4[b8];if((ca||b3===cf.origType)&&(!ci||ci.guid===cf.guid)&&(!b9||b9.test(cf.namespace))&&(!b6||b6===cf.selector||b6==="**"&&cf.selector)){b4.splice(b8,1);if(cf.selector){b4.delegateCount--}if(cd.remove){cd.remove.call(b5,cf)}}}if(b7&&!b4.length){if(!cd.teardown||cd.teardown.call(b5,e,cc.handle)===false){bJ.removeEvent(b5,ce,cc.handle)}delete cg[ce]}}if(bJ.isEmptyObject(cg)){delete cc.handle;bJ._removeData(b5,"events")}},trigger:function(b3,ca,b6,ch){var cb,b5,cf,cg,cd,b9,b8,b7=[b6||l],ce=V.call(b3,"type")?b3.type:b3,b4=V.call(b3,"namespace")?b3.namespace.split("."):[];cf=b9=b6=b6||l;if(b6.nodeType===3||b6.nodeType===8){return}if(bB.test(ce+bJ.event.triggered)){return}if(ce.indexOf(".")>=0){b4=ce.split(".");ce=b4.shift();b4.sort()}b5=ce.indexOf(":")<0&&"on"+ce;b3=b3[bJ.expando]?b3:new bJ.Event(ce,typeof b3==="object"&&b3);b3.isTrigger=true;b3.namespace=b4.join(".");b3.namespace_re=b3.namespace?new RegExp("(^|\\.)"+b4.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;b3.result=aG;if(!b3.target){b3.target=b6}ca=ca==null?[b3]:bJ.makeArray(ca,[b3]);cd=bJ.event.special[ce]||{};if(!ch&&cd.trigger&&cd.trigger.apply(b6,ca)===false){return}if(!ch&&!cd.noBubble&&!bJ.isWindow(b6)){cg=cd.delegateType||ce;if(!bB.test(cg+ce)){cf=cf.parentNode}for(;cf;cf=cf.parentNode){b7.push(cf);b9=cf}if(b9===(b6.ownerDocument||l)){b7.push(b9.defaultView||b9.parentWindow||a2)}}b8=0;while((cf=b7[b8++])&&!b3.isPropagationStopped()){b3.type=b8>1?cg:cd.bindType||ce;cb=(bJ._data(cf,"events")||{})[b3.type]&&bJ._data(cf,"handle");if(cb){cb.apply(cf,ca)}cb=b5&&cf[b5];if(cb&&bJ.acceptData(cf)&&cb.apply&&cb.apply(cf,ca)===false){b3.preventDefault()}}b3.type=ce;if(!ch&&!b3.isDefaultPrevented()){if((!cd._default||cd._default.apply(b6.ownerDocument,ca)===false)&&!(ce==="click"&&bJ.nodeName(b6,"a"))&&bJ.acceptData(b6)){if(b5&&b6[ce]&&!bJ.isWindow(b6)){b9=b6[b5];if(b9){b6[b5]=null}bJ.event.triggered=ce;try{b6[ce]()}catch(cc){}bJ.event.triggered=aG;if(b9){b6[b5]=b9}}}}return b3.result},dispatch:function(e){e=bJ.event.fix(e);var b6,b7,cb,b3,b5,ca=[],b9=a4.call(arguments),b4=(bJ._data(this,"events")||{})[e.type]||[],b8=bJ.event.special[e.type]||{};b9[0]=e;e.delegateTarget=this;if(b8.preDispatch&&b8.preDispatch.call(this,e)===false){return}ca=bJ.event.handlers.call(this,e,b4);b6=0;while((b3=ca[b6++])&&!e.isPropagationStopped()){e.currentTarget=b3.elem;b5=0;while((cb=b3.handlers[b5++])&&!e.isImmediatePropagationStopped()){if(!e.namespace_re||e.namespace_re.test(cb.namespace)){e.handleObj=cb;e.data=cb.data;b7=((bJ.event.special[cb.origType]||{}).handle||cb.handler).apply(b3.elem,b9);if(b7!==aG){if((e.result=b7)===false){e.preventDefault();e.stopPropagation()}}}}}if(b8.postDispatch){b8.postDispatch.call(this,e)}return e.result},handlers:function(e,b4){var b3,b9,b7,b6,b8=[],b5=b4.delegateCount,ca=e.target;if(b5&&ca.nodeType&&(!e.button||e.type!=="click")){for(;ca!=this;ca=ca.parentNode||this){if(ca.nodeType===1&&(ca.disabled!==true||e.type!=="click")){b7=[];for(b6=0;b6<b5;b6++){b9=b4[b6];b3=b9.selector+" ";if(b7[b3]===aG){b7[b3]=b9.needsContext?bJ(b3,this).index(ca)>=0:bJ.find(b3,this,null,[ca]).length}if(b7[b3]){b7.push(b9)}}if(b7.length){b8.push({elem:ca,handlers:b7})}}}}if(b5<b4.length){b8.push({elem:this,handlers:b4.slice(b5)})}return b8},fix:function(b5){if(b5[bJ.expando]){return b5}var b3,b8,b7,b4=b5.type,e=b5,b6=this.fixHooks[b4];if(!b6){this.fixHooks[b4]=b6=bN.test(b4)?this.mouseHooks:a3.test(b4)?this.keyHooks:{}}b7=b6.props?this.props.concat(b6.props):this.props;b5=new bJ.Event(e);b3=b7.length;while(b3--){b8=b7[b3];b5[b8]=e[b8]}if(!b5.target){b5.target=e.srcElement||l}if(b5.target.nodeType===3){b5.target=b5.target.parentNode}b5.metaKey=!!b5.metaKey;return b6.filter?b6.filter(b5,e):b5},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(b3,e){if(b3.which==null){b3.which=e.charCode!=null?e.charCode:e.keyCode}return b3}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(b5,b4){var e,b6,b7,b3=b4.button,b8=b4.fromElement;if(b5.pageX==null&&b4.clientX!=null){b6=b5.target.ownerDocument||l;b7=b6.documentElement;e=b6.body;b5.pageX=b4.clientX+(b7&&b7.scrollLeft||e&&e.scrollLeft||0)-(b7&&b7.clientLeft||e&&e.clientLeft||0);b5.pageY=b4.clientY+(b7&&b7.scrollTop||e&&e.scrollTop||0)-(b7&&b7.clientTop||e&&e.clientTop||0)}if(!b5.relatedTarget&&b8){b5.relatedTarget=b8===b5.target?b4.toElement:b8}if(!b5.which&&b3!==aG){b5.which=(b3&1?1:(b3&2?3:(b3&4?2:0)))}return b5}},special:{load:{noBubble:true},click:{trigger:function(){if(bJ.nodeName(this,"input")&&this.type==="checkbox"&&this.click){this.click();return false}}},focus:{trigger:function(){if(this!==l.activeElement&&this.focus){try{this.focus();return false}catch(b3){}}},delegateType:"focusin"},blur:{trigger:function(){if(this===l.activeElement&&this.blur){this.blur();return false}},delegateType:"focusout"},beforeunload:{postDispatch:function(e){if(e.result!==aG){e.originalEvent.returnValue=e.result}}}},simulate:function(b4,b6,b5,b3){var b7=bJ.extend(new bJ.Event(),b5,{type:b4,isSimulated:true,originalEvent:{}});if(b3){bJ.event.trigger(b7,null,b6)}else{bJ.event.dispatch.call(b6,b7)}if(b7.isDefaultPrevented()){b5.preventDefault()}}};bJ.removeEvent=l.removeEventListener?function(b3,e,b4){if(b3.removeEventListener){b3.removeEventListener(e,b4,false)}}:function(b4,b3,b5){var e="on"+b3;if(b4.detachEvent){if(typeof b4[e]===aC){b4[e]=null}b4.detachEvent(e,b5)}};bJ.Event=function(b3,e){if(!(this instanceof bJ.Event)){return new bJ.Event(b3,e)}if(b3&&b3.type){this.originalEvent=b3;this.type=b3.type;this.isDefaultPrevented=(b3.defaultPrevented||b3.returnValue===false||b3.getPreventDefault&&b3.getPreventDefault())?R:X}else{this.type=b3}if(e){bJ.extend(this,e)}this.timeStamp=b3&&b3.timeStamp||bJ.now();this[bJ.expando]=true};bJ.Event.prototype={isDefaultPrevented:X,isPropagationStopped:X,isImmediatePropagationStopped:X,preventDefault:function(){var b3=this.originalEvent;this.isDefaultPrevented=R;if(!b3){return}if(b3.preventDefault){b3.preventDefault()}else{b3.returnValue=false}},stopPropagation:function(){var b3=this.originalEvent;this.isPropagationStopped=R;if(!b3){return}if(b3.stopPropagation){b3.stopPropagation()}b3.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=R;this.stopPropagation()}};bJ.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(b3,e){bJ.event.special[b3]={delegateType:e,bindType:e,handle:function(b6){var b4,b8=this,b7=b6.relatedTarget,b5=b6.handleObj;if(!b7||(b7!==b8&&!bJ.contains(b8,b7))){b6.type=b5.origType;b4=b5.handler.apply(this,arguments);b6.type=e}return b4}}});if(!bJ.support.submitBubbles){bJ.event.special.submit={setup:function(){if(bJ.nodeName(this,"form")){return false}bJ.event.add(this,"click._submit keypress._submit",function(b5){var b4=b5.target,b3=bJ.nodeName(b4,"input")||bJ.nodeName(b4,"button")?b4.form:aG;if(b3&&!bJ._data(b3,"submitBubbles")){bJ.event.add(b3,"submit._submit",function(e){e._submit_bubble=true});bJ._data(b3,"submitBubbles",true)}})},postDispatch:function(e){if(e._submit_bubble){delete e._submit_bubble;if(this.parentNode&&!e.isTrigger){bJ.event.simulate("submit",this.parentNode,e,true)}}},teardown:function(){if(bJ.nodeName(this,"form")){return false}bJ.event.remove(this,"._submit")}}}if(!bJ.support.changeBubbles){bJ.event.special.change={setup:function(){if(bH.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio"){bJ.event.add(this,"propertychange._change",function(e){if(e.originalEvent.propertyName==="checked"){this._just_changed=true}});bJ.event.add(this,"click._change",function(e){if(this._just_changed&&!e.isTrigger){this._just_changed=false}bJ.event.simulate("change",this,e,true)})}return false}bJ.event.add(this,"beforeactivate._change",function(b4){var b3=b4.target;if(bH.test(b3.nodeName)&&!bJ._data(b3,"changeBubbles")){bJ.event.add(b3,"change._change",function(e){if(this.parentNode&&!e.isSimulated&&!e.isTrigger){bJ.event.simulate("change",this.parentNode,e,true)}});bJ._data(b3,"changeBubbles",true)}})},handle:function(b3){var e=b3.target;if(this!==e||b3.isSimulated||b3.isTrigger||(e.type!=="radio"&&e.type!=="checkbox")){return b3.handleObj.handler.apply(this,arguments)}},teardown:function(){bJ.event.remove(this,"._change");return !bH.test(this.nodeName)}}}if(!bJ.support.focusinBubbles){bJ.each({focus:"focusin",blur:"focusout"},function(b5,e){var b3=0,b4=function(b6){bJ.event.simulate(e,b6.target,bJ.event.fix(b6),true)};bJ.event.special[e]={setup:function(){if(b3++===0){l.addEventListener(b5,b4,true)}},teardown:function(){if(--b3===0){l.removeEventListener(b5,b4,true)}}}})}bJ.fn.extend({on:function(b4,e,b7,b6,b3){var b5,b8;if(typeof b4==="object"){if(typeof e!=="string"){b7=b7||e;e=aG}for(b5 in b4){this.on(b5,e,b7,b4[b5],b3)}return this}if(b7==null&&b6==null){b6=e;b7=e=aG}else{if(b6==null){if(typeof e==="string"){b6=b7;b7=aG}else{b6=b7;b7=e;e=aG}}}if(b6===false){b6=X}else{if(!b6){return this}}if(b3===1){b8=b6;b6=function(b9){bJ().off(b9);return b8.apply(this,arguments)};b6.guid=b8.guid||(b8.guid=bJ.guid++)}return this.each(function(){bJ.event.add(this,b4,b6,b7,e)})},one:function(b3,e,b5,b4){return this.on(b3,e,b5,b4,1)},off:function(b4,e,b6){var b3,b5;if(b4&&b4.preventDefault&&b4.handleObj){b3=b4.handleObj;bJ(b4.delegateTarget).off(b3.namespace?b3.origType+"."+b3.namespace:b3.origType,b3.selector,b3.handler);return this}if(typeof b4==="object"){for(b5 in b4){this.off(b5,e,b4[b5])}return this}if(e===false||typeof e==="function"){b6=e;e=aG}if(b6===false){b6=X}return this.each(function(){bJ.event.remove(this,b4,b6,e)})},bind:function(e,b4,b3){return this.on(e,null,b4,b3)},unbind:function(e,b3){return this.off(e,null,b3)},delegate:function(e,b3,b5,b4){return this.on(b3,e,b5,b4)},undelegate:function(e,b3,b4){return arguments.length===1?this.off(e,"**"):this.off(b3,e||"**",b4)},trigger:function(e,b3){return this.each(function(){bJ.event.trigger(e,b3,this)})},triggerHandler:function(e,b4){var b3=this[0];if(b3){return bJ.event.trigger(e,b4,b3,true)}}});
/*!
 * Sizzle CSS Selector Engine
 * Copyright 2012 jQuery Foundation and other contributors
 * Released under the MIT license
 * http://sizzlejs.com/
 */
(function(da,ch){var cx,cb,cn,cH,cJ,cS,cT,dg,cV,cB,co,cd,cZ,db,ca,cF,cD,c5="sizzle"+-(new Date()),cI=da.document,dd={},de=0,c0=0,b5=cz(),c4=cz(),cG=cz(),c9=typeof ch,cN=1<<31,c7=[],c8=c7.pop,b4=c7.push,cm=c7.slice,b9=c7.indexOf||function(di){var dh=0,e=this.length;for(;dh<e;dh++){if(this[dh]===di){return dh}}return -1},cp="[\\x20\\t\\r\\n\\f]",b3="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",cK=b3.replace("w","w#"),ci="([*^$|!~]?=)",c2="\\["+cp+"*("+b3+")"+cp+"*(?:"+ci+cp+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+cK+")|)|)"+cp+"*\\]",ck=":("+b3+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+c2.replace(3,8)+")*)|.*)\\)|)",cr=new RegExp("^"+cp+"+|((?:^|[^\\\\])(?:\\\\.)*)"+cp+"+$","g"),cu=new RegExp("^"+cp+"*,"+cp+"*"),cA=new RegExp("^"+cp+"*([\\x20\\t\\r\\n\\f>+~])"+cp+"*"),cP=new RegExp(ck),cQ=new RegExp("^"+cK+"$"),cY={ID:new RegExp("^#("+b3+")"),CLASS:new RegExp("^\\.("+b3+")"),NAME:new RegExp("^\\[name=['\"]?("+b3+")['\"]?\\]"),TAG:new RegExp("^("+b3.replace("w","w*")+")"),ATTR:new RegExp("^"+c2),PSEUDO:new RegExp("^"+ck),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+cp+"*(even|odd|(([+-]|)(\\d*)n|)"+cp+"*(?:([+-]|)"+cp+"*(\\d+)|))"+cp+"*\\)|)","i"),needsContext:new RegExp("^"+cp+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+cp+"*((?:-\\d)?\\d*)"+cp+"*\\)|)(?=[^-]|$)","i")},cW=/[\x20\t\r\n\f]*[+~]/,cM=/^[^{]+\{\s*\[native code/,cO=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,b8=/^(?:input|select|textarea|button)$/i,cl=/^h\d$/i,cL=/'|\\/g,ct=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,cs=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,c1=function(e,di){var dh="0x"+di-65536;return dh!==dh?di:dh<0?String.fromCharCode(dh+65536):String.fromCharCode(dh>>10|55296,dh&1023|56320)};try{cm.call(cI.documentElement.childNodes,0)[0].nodeType}catch(cC){cm=function(dh){var di,e=[];while((di=this[dh++])){e.push(di)}return e}}function cE(e){return cM.test(e+"")}function cz(){var e,dh=[];return(e=function(di,dj){if(dh.push(di+=" ")>cn.cacheLength){delete e[dh.shift()]}return(e[di]=dj)})}function cj(e){e[c5]=true;return e}function cc(dh){var dj=cB.createElement("div");try{return dh(dj)}catch(di){return false}finally{dj=null}}function cv(dp,dh,dt,dv){var du,dl,dm,dr,ds,dk,dj,e,di,dq;if((dh?dh.ownerDocument||dh:cI)!==cB){cV(dh)}dh=dh||cB;dt=dt||[];if(!dp||typeof dp!=="string"){return dt}if((dr=dh.nodeType)!==1&&dr!==9){return[]}if(!cd&&!dv){if((du=cO.exec(dp))){if((dm=du[1])){if(dr===9){dl=dh.getElementById(dm);if(dl&&dl.parentNode){if(dl.id===dm){dt.push(dl);return dt}}else{return dt}}else{if(dh.ownerDocument&&(dl=dh.ownerDocument.getElementById(dm))&&cF(dh,dl)&&dl.id===dm){dt.push(dl);return dt}}}else{if(du[2]){b4.apply(dt,cm.call(dh.getElementsByTagName(dp),0));return dt}else{if((dm=du[3])&&dd.getByClassName&&dh.getElementsByClassName){b4.apply(dt,cm.call(dh.getElementsByClassName(dm),0));return dt}}}}if(dd.qsa&&!cZ.test(dp)){dj=true;e=c5;di=dh;dq=dr===9&&dp;if(dr===1&&dh.nodeName.toLowerCase()!=="object"){dk=cf(dp);if((dj=dh.getAttribute("id"))){e=dj.replace(cL,"\\$&")}else{dh.setAttribute("id",e)}e="[id='"+e+"'] ";ds=dk.length;while(ds--){dk[ds]=e+cg(dk[ds])}di=cW.test(dp)&&dh.parentNode||dh;dq=dk.join(",")}if(dq){try{b4.apply(dt,cm.call(di.querySelectorAll(dq),0));return dt}catch(dn){}finally{if(!dj){dh.removeAttribute("id")}}}}}return dc(dp.replace(cr,"$1"),dh,dt,dv)}cJ=cv.isXML=function(e){var dh=e&&(e.ownerDocument||e).documentElement;return dh?dh.nodeName!=="HTML":false};cV=cv.setDocument=function(e){var dh=e?e.ownerDocument||e:cI;if(dh===cB||dh.nodeType!==9||!dh.documentElement){return cB}cB=dh;co=dh.documentElement;cd=cJ(dh);dd.tagNameNoComments=cc(function(di){di.appendChild(dh.createComment(""));return !di.getElementsByTagName("*").length});dd.attributes=cc(function(dj){dj.innerHTML="<select></select>";var di=typeof dj.lastChild.getAttribute("multiple");return di!=="boolean"&&di!=="string"});dd.getByClassName=cc(function(di){di.innerHTML="<div class='hidden e'></div><div class='hidden'></div>";if(!di.getElementsByClassName||!di.getElementsByClassName("e").length){return false}di.lastChild.className="e";return di.getElementsByClassName("e").length===2});dd.getByName=cc(function(dj){dj.id=c5+0;dj.innerHTML="<a name='"+c5+"'></a><div name='"+c5+"'></div>";co.insertBefore(dj,co.firstChild);var di=dh.getElementsByName&&dh.getElementsByName(c5).length===2+dh.getElementsByName(c5+0).length;dd.getIdNotName=!dh.getElementById(c5);co.removeChild(dj);return di});cn.attrHandle=cc(function(di){di.innerHTML="<a href='#'></a>";return di.firstChild&&typeof di.firstChild.getAttribute!==c9&&di.firstChild.getAttribute("href")==="#"})?{}:{href:function(di){return di.getAttribute("href",2)},type:function(di){return di.getAttribute("type")}};if(dd.getIdNotName){cn.find.ID=function(dk,dj){if(typeof dj.getElementById!==c9&&!cd){var di=dj.getElementById(dk);return di&&di.parentNode?[di]:[]}};cn.filter.ID=function(dj){var di=dj.replace(cs,c1);return function(dk){return dk.getAttribute("id")===di}}}else{cn.find.ID=function(dk,dj){if(typeof dj.getElementById!==c9&&!cd){var di=dj.getElementById(dk);return di?di.id===dk||typeof di.getAttributeNode!==c9&&di.getAttributeNode("id").value===dk?[di]:ch:[]}};cn.filter.ID=function(dj){var di=dj.replace(cs,c1);return function(dl){var dk=typeof dl.getAttributeNode!==c9&&dl.getAttributeNode("id");return dk&&dk.value===di}}}cn.find.TAG=dd.tagNameNoComments?function(di,dj){if(typeof dj.getElementsByTagName!==c9){return dj.getElementsByTagName(di)}}:function(di,dm){var dn,dl=[],dk=0,dj=dm.getElementsByTagName(di);if(di==="*"){while((dn=dj[dk++])){if(dn.nodeType===1){dl.push(dn)}}return dl}return dj};cn.find.NAME=dd.getByName&&function(di,dj){if(typeof dj.getElementsByName!==c9){return dj.getElementsByName(name)}};cn.find.CLASS=dd.getByClassName&&function(dj,di){if(typeof di.getElementsByClassName!==c9&&!cd){return di.getElementsByClassName(dj)}};db=[];cZ=[":focus"];if((dd.qsa=cE(dh.querySelectorAll))){cc(function(di){di.innerHTML="<select><option selected=''></option></select>";if(!di.querySelectorAll("[selected]").length){cZ.push("\\["+cp+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)")}if(!di.querySelectorAll(":checked").length){cZ.push(":checked")}});cc(function(di){di.innerHTML="<input type='hidden' i=''/>";if(di.querySelectorAll("[i^='']").length){cZ.push("[*^$]="+cp+"*(?:\"\"|'')")}if(!di.querySelectorAll(":enabled").length){cZ.push(":enabled",":disabled")}di.querySelectorAll("*,:x");cZ.push(",.*:")})}if((dd.matchesSelector=cE((ca=co.matchesSelector||co.mozMatchesSelector||co.webkitMatchesSelector||co.oMatchesSelector||co.msMatchesSelector)))){cc(function(di){dd.disconnectedMatch=ca.call(di,"div");ca.call(di,"[s!='']:x");db.push("!=",ck)})}cZ=new RegExp(cZ.join("|"));db=new RegExp(db.join("|"));cF=cE(co.contains)||co.compareDocumentPosition?function(dj,di){var dl=dj.nodeType===9?dj.documentElement:dj,dk=di&&di.parentNode;return dj===dk||!!(dk&&dk.nodeType===1&&(dl.contains?dl.contains(dk):dj.compareDocumentPosition&&dj.compareDocumentPosition(dk)&16))}:function(dj,di){if(di){while((di=di.parentNode)){if(di===dj){return true}}}return false};cD=co.compareDocumentPosition?function(dj,di){var dk;if(dj===di){cT=true;return 0}if((dk=di.compareDocumentPosition&&dj.compareDocumentPosition&&dj.compareDocumentPosition(di))){if(dk&1||dj.parentNode&&dj.parentNode.nodeType===11){if(dj===dh||cF(cI,dj)){return -1}if(di===dh||cF(cI,di)){return 1}return 0}return dk&4?-1:1}return dj.compareDocumentPosition?-1:1}:function(dj,di){var dq,dm=0,dp=dj.parentNode,dl=di.parentNode,dk=[dj],dn=[di];if(dj===di){cT=true;return 0}else{if(!dp||!dl){return dj===dh?-1:di===dh?1:dp?-1:dl?1:0}else{if(dp===dl){return b6(dj,di)}}}dq=dj;while((dq=dq.parentNode)){dk.unshift(dq)}dq=di;while((dq=dq.parentNode)){dn.unshift(dq)}while(dk[dm]===dn[dm]){dm++}return dm?b6(dk[dm],dn[dm]):dk[dm]===cI?-1:dn[dm]===cI?1:0};cT=false;[0,0].sort(cD);dd.detectDuplicates=cT;return cB};cv.matches=function(dh,e){return cv(dh,null,null,e)};cv.matchesSelector=function(di,dk){if((di.ownerDocument||di)!==cB){cV(di)}dk=dk.replace(ct,"='$1']");if(dd.matchesSelector&&!cd&&(!db||!db.test(dk))&&!cZ.test(dk)){try{var dh=ca.call(di,dk);if(dh||dd.disconnectedMatch||di.document&&di.document.nodeType!==11){return dh}}catch(dj){}}return cv(dk,cB,null,[di]).length>0};cv.contains=function(e,dh){if((e.ownerDocument||e)!==cB){cV(e)}return cF(e,dh)};cv.attr=function(dh,e){var di;if((dh.ownerDocument||dh)!==cB){cV(dh)}if(!cd){e=e.toLowerCase()}if((di=cn.attrHandle[e])){return di(dh)}if(cd||dd.attributes){return dh.getAttribute(e)}return((di=dh.getAttributeNode(e))||dh.getAttribute(e))&&dh[e]===true?e:di&&di.specified?di.value:null};cv.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)};cv.uniqueSort=function(di){var dj,dk=[],dh=1,e=0;cT=!dd.detectDuplicates;di.sort(cD);if(cT){for(;(dj=di[dh]);dh++){if(dj===di[dh-1]){e=dk.push(dh)}}while(e--){di.splice(dk[e],1)}}return di};function b6(dh,e){var dj=e&&dh,di=dj&&(~e.sourceIndex||cN)-(~dh.sourceIndex||cN);if(di){return di}if(dj){while((dj=dj.nextSibling)){if(dj===e){return -1}}}return dh?1:-1}function cw(e){return function(di){var dh=di.nodeName.toLowerCase();return dh==="input"&&di.type===e}}function b7(e){return function(di){var dh=di.nodeName.toLowerCase();return(dh==="input"||dh==="button")&&di.type===e}}function c3(e){return cj(function(dh){dh=+dh;return cj(function(di,dm){var dk,dj=e([],di.length,dh),dl=dj.length;while(dl--){if(di[(dk=dj[dl])]){di[dk]=!(dm[dk]=di[dk])}}})})}cH=cv.getText=function(dk){var dj,dh="",di=0,e=dk.nodeType;if(!e){for(;(dj=dk[di]);di++){dh+=cH(dj)}}else{if(e===1||e===9||e===11){if(typeof dk.textContent==="string"){return dk.textContent}else{for(dk=dk.firstChild;dk;dk=dk.nextSibling){dh+=cH(dk)}}}else{if(e===3||e===4){return dk.nodeValue}}}return dh};cn=cv.selectors={cacheLength:50,createPseudo:cj,match:cY,find:{},relative:{">":{dir:"parentNode",first:true}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:true},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){e[1]=e[1].replace(cs,c1);e[3]=(e[4]||e[5]||"").replace(cs,c1);if(e[2]==="~="){e[3]=" "+e[3]+" "}return e.slice(0,4)},CHILD:function(e){e[1]=e[1].toLowerCase();if(e[1].slice(0,3)==="nth"){if(!e[3]){cv.error(e[0])}e[4]=+(e[4]?e[5]+(e[6]||1):2*(e[3]==="even"||e[3]==="odd"));e[5]=+((e[7]+e[8])||e[3]==="odd")}else{if(e[3]){cv.error(e[0])}}return e},PSEUDO:function(dh){var e,di=!dh[5]&&dh[2];if(cY.CHILD.test(dh[0])){return null}if(dh[4]){dh[2]=dh[4]}else{if(di&&cP.test(di)&&(e=cf(di,true))&&(e=di.indexOf(")",di.length-e)-di.length)){dh[0]=dh[0].slice(0,e);dh[2]=di.slice(0,e)}}return dh.slice(0,3)}},filter:{TAG:function(e){if(e==="*"){return function(){return true}}e=e.replace(cs,c1).toLowerCase();return function(dh){return dh.nodeName&&dh.nodeName.toLowerCase()===e}},CLASS:function(e){var dh=b5[e+" "];return dh||(dh=new RegExp("(^|"+cp+")"+e+"("+cp+"|$)"))&&b5(e,function(di){return dh.test(di.className||(typeof di.getAttribute!==c9&&di.getAttribute("class"))||"")})},ATTR:function(di,dh,e){return function(dk){var dj=cv.attr(dk,di);if(dj==null){return dh==="!="}if(!dh){return true}dj+="";return dh==="="?dj===e:dh==="!="?dj!==e:dh==="^="?e&&dj.indexOf(e)===0:dh==="*="?e&&dj.indexOf(e)>-1:dh==="$="?e&&dj.slice(-e.length)===e:dh==="~="?(" "+dj+" ").indexOf(e)>-1:dh==="|="?dj===e||dj.slice(0,e.length+1)===e+"-":false}},CHILD:function(dh,dk,dj,dl,di){var dn=dh.slice(0,3)!=="nth",e=dh.slice(-4)!=="last",dm=dk==="of-type";return dl===1&&di===0?function(dp){return !!dp.parentNode}:function(dv,dt,dy){var dp,dB,dw,dA,dx,ds,du=dn!==e?"nextSibling":"previousSibling",dz=dv.parentNode,dr=dm&&dv.nodeName.toLowerCase(),dq=!dy&&!dm;if(dz){if(dn){while(du){dw=dv;while((dw=dw[du])){if(dm?dw.nodeName.toLowerCase()===dr:dw.nodeType===1){return false}}ds=du=dh==="only"&&!ds&&"nextSibling"}return true}ds=[e?dz.firstChild:dz.lastChild];if(e&&dq){dB=dz[c5]||(dz[c5]={});dp=dB[dh]||[];dx=dp[0]===de&&dp[1];dA=dp[0]===de&&dp[2];dw=dx&&dz.childNodes[dx];while((dw=++dx&&dw&&dw[du]||(dA=dx=0)||ds.pop())){if(dw.nodeType===1&&++dA&&dw===dv){dB[dh]=[de,dx,dA];break}}}else{if(dq&&(dp=(dv[c5]||(dv[c5]={}))[dh])&&dp[0]===de){dA=dp[1]}else{while((dw=++dx&&dw&&dw[du]||(dA=dx=0)||ds.pop())){if((dm?dw.nodeName.toLowerCase()===dr:dw.nodeType===1)&&++dA){if(dq){(dw[c5]||(dw[c5]={}))[dh]=[de,dA]}if(dw===dv){break}}}}}dA-=di;return dA===dl||(dA%dl===0&&dA/dl>=0)}}},PSEUDO:function(dj,di){var e,dh=cn.pseudos[dj]||cn.setFilters[dj.toLowerCase()]||cv.error("unsupported pseudo: "+dj);if(dh[c5]){return dh(di)}if(dh.length>1){e=[dj,dj,"",di];return cn.setFilters.hasOwnProperty(dj.toLowerCase())?cj(function(dm,dp){var dl,dk=dh(dm,di),dn=dk.length;while(dn--){dl=b9.call(dm,dk[dn]);dm[dl]=!(dp[dl]=dk[dn])}}):function(dk){return dh(dk,0,e)}}return dh}},pseudos:{not:cj(function(e){var dh=[],di=[],dj=cS(e.replace(cr,"$1"));return dj[c5]?cj(function(dl,dr,dp,dm){var dq,dk=dj(dl,null,dm,[]),dn=dl.length;while(dn--){if((dq=dk[dn])){dl[dn]=!(dr[dn]=dq)}}}):function(dm,dl,dk){dh[0]=dm;dj(dh,null,dk,di);return !di.pop()}}),has:cj(function(e){return function(dh){return cv(e,dh).length>0}}),contains:cj(function(e){return function(dh){return(dh.textContent||dh.innerText||cH(dh)).indexOf(e)>-1}}),lang:cj(function(e){if(!cQ.test(e||"")){cv.error("unsupported lang: "+e)}e=e.replace(cs,c1).toLowerCase();return function(di){var dh;do{if((dh=cd?di.getAttribute("xml:lang")||di.getAttribute("lang"):di.lang)){dh=dh.toLowerCase();return dh===e||dh.indexOf(e+"-")===0}}while((di=di.parentNode)&&di.nodeType===1);return false}}),target:function(e){var dh=da.location&&da.location.hash;return dh&&dh.slice(1)===e.id},root:function(e){return e===co},focus:function(e){return e===cB.activeElement&&(!cB.hasFocus||cB.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===false},disabled:function(e){return e.disabled===true},checked:function(e){var dh=e.nodeName.toLowerCase();return(dh==="input"&&!!e.checked)||(dh==="option"&&!!e.selected)},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling){if(e.nodeName>"@"||e.nodeType===3||e.nodeType===4){return false}}return true},parent:function(e){return !cn.pseudos.empty(e)},header:function(e){return cl.test(e.nodeName)},input:function(e){return b8.test(e.nodeName)},button:function(dh){var e=dh.nodeName.toLowerCase();return e==="input"&&dh.type==="button"||e==="button"},text:function(dh){var e;return dh.nodeName.toLowerCase()==="input"&&dh.type==="text"&&((e=dh.getAttribute("type"))==null||e.toLowerCase()===dh.type)},first:c3(function(){return[0]}),last:c3(function(e,dh){return[dh-1]}),eq:c3(function(e,di,dh){return[dh<0?dh+di:dh]}),even:c3(function(e,di){var dh=0;for(;dh<di;dh+=2){e.push(dh)}return e}),odd:c3(function(e,di){var dh=1;for(;dh<di;dh+=2){e.push(dh)}return e}),lt:c3(function(e,dj,di){var dh=di<0?di+dj:di;for(;--dh>=0;){e.push(dh)}return e}),gt:c3(function(e,dj,di){var dh=di<0?di+dj:di;for(;++dh<dj;){e.push(dh)}return e})}};for(cx in {radio:true,checkbox:true,file:true,password:true,image:true}){cn.pseudos[cx]=cw(cx)}for(cx in {submit:true,reset:true}){cn.pseudos[cx]=b7(cx)}function cf(dk,dq){var dh,dl,dn,dp,dm,di,e,dj=c4[dk+" "];if(dj){return dq?0:dj.slice(0)}dm=dk;di=[];e=cn.preFilter;while(dm){if(!dh||(dl=cu.exec(dm))){if(dl){dm=dm.slice(dl[0].length)||dm}di.push(dn=[])}dh=false;if((dl=cA.exec(dm))){dh=dl.shift();dn.push({value:dh,type:dl[0].replace(cr," ")});dm=dm.slice(dh.length)}for(dp in cn.filter){if((dl=cY[dp].exec(dm))&&(!e[dp]||(dl=e[dp](dl)))){dh=dl.shift();dn.push({value:dh,type:dp,matches:dl});dm=dm.slice(dh.length)}}if(!dh){break}}return dq?dm.length:dm?cv.error(dk):c4(dk,di).slice(0)}function cg(dj){var di=0,dh=dj.length,e="";for(;di<dh;di++){e+=dj[di].value}return e}function cq(dk,di,dj){var e=di.dir,dl=dj&&e==="parentNode",dh=c0++;return di.first?function(dp,dn,dm){while((dp=dp[e])){if(dp.nodeType===1||dl){return dk(dp,dn,dm)}}}:function(dr,dp,dn){var dt,dm,dq,ds=de+" "+dh;if(dn){while((dr=dr[e])){if(dr.nodeType===1||dl){if(dk(dr,dp,dn)){return true}}}}else{while((dr=dr[e])){if(dr.nodeType===1||dl){dq=dr[c5]||(dr[c5]={});if((dm=dq[e])&&dm[0]===ds){if((dt=dm[1])===true||dt===cb){return dt===true}}else{dm=dq[e]=[ds];dm[1]=dk(dr,dp,dn)||cb;if(dm[1]===true){return true}}}}}}}function df(e){return e.length>1?function(dk,dj,dh){var di=e.length;while(di--){if(!e[di](dk,dj,dh)){return false}}return true}:e[0]}function cX(e,dh,di,dj,dm){var dk,dq=[],dl=0,dn=e.length,dp=dh!=null;for(;dl<dn;dl++){if((dk=e[dl])){if(!di||di(dk,dj,dm)){dq.push(dk);if(dp){dh.push(dl)}}}}return dq}function ce(di,dh,dk,dj,dl,e){if(dj&&!dj[c5]){dj=ce(dj)}if(dl&&!dl[c5]){dl=ce(dl,e)}return cj(function(dx,du,dp,dw){var dz,dv,dr,dq=[],dy=[],dn=du.length,dm=dx||cy(dh||"*",dp.nodeType?[dp]:dp,[]),ds=di&&(dx||!dh)?cX(dm,dq,di,dp,dw):dm,dt=dk?dl||(dx?di:dn||dj)?[]:du:ds;if(dk){dk(ds,dt,dp,dw)}if(dj){dz=cX(dt,dy);dj(dz,[],dp,dw);dv=dz.length;while(dv--){if((dr=dz[dv])){dt[dy[dv]]=!(ds[dy[dv]]=dr)}}}if(dx){if(dl||di){if(dl){dz=[];dv=dt.length;while(dv--){if((dr=dt[dv])){dz.push((ds[dv]=dr))}}dl(null,(dt=[]),dz,dw)}dv=dt.length;while(dv--){if((dr=dt[dv])&&(dz=dl?b9.call(dx,dr):dq[dv])>-1){dx[dz]=!(du[dz]=dr)}}}}else{dt=cX(dt===du?dt.splice(dn,dt.length):dt);if(dl){dl(null,du,dt,dw)}else{b4.apply(du,dt)}}})}function c6(dm){var dh,dk,di,dl=dm.length,dq=cn.relative[dm[0].type],dr=dq||cn.relative[" "],dj=dq?1:0,dn=cq(function(ds){return ds===dh},dr,true),dp=cq(function(ds){return b9.call(dh,ds)>-1},dr,true),e=[function(du,dt,ds){return(!dq&&(ds||dt!==dg))||((dh=dt).nodeType?dn(du,dt,ds):dp(du,dt,ds))}];for(;dj<dl;dj++){if((dk=cn.relative[dm[dj].type])){e=[cq(df(e),dk)]}else{dk=cn.filter[dm[dj].type].apply(null,dm[dj].matches);if(dk[c5]){di=++dj;for(;di<dl;di++){if(cn.relative[dm[di].type]){break}}return ce(dj>1&&df(e),dj>1&&cg(dm.slice(0,dj-1)).replace(cr,"$1"),dk,dj<di&&c6(dm.slice(dj,di)),di<dl&&c6((dm=dm.slice(di))),di<dl&&cg(dm))}e.push(dk)}}return df(e)}function cU(dj,di){var dl=0,e=di.length>0,dk=dj.length>0,dh=function(dw,dq,dv,du,dC){var dr,ds,dx,dB=[],dA=0,dt="0",dm=dw&&[],dy=dC!=null,dz=dg,dp=dw||dk&&cn.find.TAG("*",dC&&dq.parentNode||dq),dn=(de+=dz==null?1:Math.random()||0.1);if(dy){dg=dq!==cB&&dq;cb=dl}for(;(dr=dp[dt])!=null;dt++){if(dk&&dr){ds=0;while((dx=dj[ds++])){if(dx(dr,dq,dv)){du.push(dr);break}}if(dy){de=dn;cb=++dl}}if(e){if((dr=!dx&&dr)){dA--}if(dw){dm.push(dr)}}}dA+=dt;if(e&&dt!==dA){ds=0;while((dx=di[ds++])){dx(dm,dB,dq,dv)}if(dw){if(dA>0){while(dt--){if(!(dm[dt]||dB[dt])){dB[dt]=c8.call(du)}}}dB=cX(dB)}b4.apply(du,dB);if(dy&&!dw&&dB.length>0&&(dA+di.length)>1){cv.uniqueSort(du)}}if(dy){de=dn;dg=dz}return dm};return e?cj(dh):dh}cS=cv.compile=function(e,dl){var di,dh=[],dk=[],dj=cG[e+" "];if(!dj){if(!dl){dl=cf(e)}di=dl.length;while(di--){dj=c6(dl[di]);if(dj[c5]){dh.push(dj)}else{dk.push(dj)}}dj=cG(e,cU(dk,dh))}return dj};function cy(dh,dk,dj){var di=0,e=dk.length;for(;di<e;di++){cv(dh,dk[di],dj)}return dj}function dc(di,e,dj,dm){var dk,dp,dh,dq,dn,dl=cf(di);if(!dm){if(dl.length===1){dp=dl[0]=dl[0].slice(0);if(dp.length>2&&(dh=dp[0]).type==="ID"&&e.nodeType===9&&!cd&&cn.relative[dp[1].type]){e=cn.find.ID(dh.matches[0].replace(cs,c1),e)[0];if(!e){return dj}di=di.slice(dp.shift().value.length)}dk=cY.needsContext.test(di)?0:dp.length;while(dk--){dh=dp[dk];if(cn.relative[(dq=dh.type)]){break}if((dn=cn.find[dq])){if((dm=dn(dh.matches[0].replace(cs,c1),cW.test(dp[0].type)&&e.parentNode||e))){dp.splice(dk,1);di=dm.length&&cg(dp);if(!di){b4.apply(dj,cm.call(dm,0));return dj}break}}}}}cS(di,dl)(dm,e,cd,dj,cW.test(di));return dj}cn.pseudos.nth=cn.pseudos.eq;function cR(){}cn.filters=cR.prototype=cn.pseudos;cn.setFilters=new cR();cV();cv.attr=bJ.attr;bJ.find=cv;bJ.expr=cv.selectors;bJ.expr[":"]=bJ.expr.pseudos;bJ.unique=cv.uniqueSort;bJ.text=cv.getText;bJ.isXMLDoc=cv.isXML;bJ.contains=cv.contains})(a2);var aj=/Until$/,bt=/^(?:parents|prev(?:Until|All))/,an=/^.[^:#\[\.,]*$/,y=bJ.expr.match.needsContext,bx={children:true,contents:true,next:true,prev:true};bJ.fn.extend({find:function(b3){var b6,b5,b4,e=this.length;if(typeof b3!=="string"){b4=this;return this.pushStack(bJ(b3).filter(function(){for(b6=0;b6<e;b6++){if(bJ.contains(b4[b6],this)){return true}}}))}b5=[];for(b6=0;b6<e;b6++){bJ.find(b3,this[b6],b5)}b5=this.pushStack(e>1?bJ.unique(b5):b5);b5.selector=(this.selector?this.selector+" ":"")+b3;return b5},has:function(b5){var b4,b3=bJ(b5,this),e=b3.length;return this.filter(function(){for(b4=0;b4<e;b4++){if(bJ.contains(this,b3[b4])){return true}}})},not:function(e){return this.pushStack(aO(this,e,false))},filter:function(e){return this.pushStack(aO(this,e,true))},is:function(e){return !!e&&(typeof e==="string"?y.test(e)?bJ(e,this.context).index(this[0])>=0:bJ.filter(e,this).length>0:this.filter(e).length>0)},closest:function(b6,b5){var b7,b4=0,e=this.length,b3=[],b8=y.test(b6)||typeof b6!=="string"?bJ(b6,b5||this.context):0;for(;b4<e;b4++){b7=this[b4];while(b7&&b7.ownerDocument&&b7!==b5&&b7.nodeType!==11){if(b8?b8.index(b7)>-1:bJ.find.matchesSelector(b7,b6)){b3.push(b7);break}b7=b7.parentNode}}return this.pushStack(b3.length>1?bJ.unique(b3):b3)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.first().prevAll().length:-1}if(typeof e==="string"){return bJ.inArray(this[0],bJ(e))}return bJ.inArray(e.jquery?e[0]:e,this)},add:function(e,b3){var b5=typeof e==="string"?bJ(e,b3):bJ.makeArray(e&&e.nodeType?[e]:e),b4=bJ.merge(this.get(),b5);return this.pushStack(bJ.unique(b4))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}});bJ.fn.andSelf=bJ.fn.addBack;function aX(b3,e){do{b3=b3[e]}while(b3&&b3.nodeType!==1);return b3}bJ.each({parent:function(b3){var e=b3.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return bJ.dir(e,"parentNode")},parentsUntil:function(b3,e,b4){return bJ.dir(b3,"parentNode",b4)},next:function(e){return aX(e,"nextSibling")},prev:function(e){return aX(e,"previousSibling")},nextAll:function(e){return bJ.dir(e,"nextSibling")},prevAll:function(e){return bJ.dir(e,"previousSibling")},nextUntil:function(b3,e,b4){return bJ.dir(b3,"nextSibling",b4)},prevUntil:function(b3,e,b4){return bJ.dir(b3,"previousSibling",b4)},siblings:function(e){return bJ.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return bJ.sibling(e.firstChild)},contents:function(e){return bJ.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:bJ.merge([],e.childNodes)}},function(e,b3){bJ.fn[e]=function(b6,b4){var b5=bJ.map(this,b3,b6);if(!aj.test(e)){b4=b6}if(b4&&typeof b4==="string"){b5=bJ.filter(b4,b5)}b5=this.length>1&&!bx[e]?bJ.unique(b5):b5;if(this.length>1&&bt.test(e)){b5=b5.reverse()}return this.pushStack(b5)}});bJ.extend({filter:function(b4,e,b3){if(b3){b4=":not("+b4+")"}return e.length===1?bJ.find.matchesSelector(e[0],b4)?[e[0]]:[]:bJ.find.matches(b4,e)},dir:function(b4,b3,b6){var e=[],b5=b4[b3];while(b5&&b5.nodeType!==9&&(b6===aG||b5.nodeType!==1||!bJ(b5).is(b6))){if(b5.nodeType===1){e.push(b5)}b5=b5[b3]}return e},sibling:function(b4,b3){var e=[];for(;b4;b4=b4.nextSibling){if(b4.nodeType===1&&b4!==b3){e.push(b4)}}return e}});function aO(b5,b4,e){b4=b4||0;if(bJ.isFunction(b4)){return bJ.grep(b5,function(b7,b6){var b8=!!b4.call(b7,b6,b7);return b8===e})}else{if(b4.nodeType){return bJ.grep(b5,function(b6){return(b6===b4)===e})}else{if(typeof b4==="string"){var b3=bJ.grep(b5,function(b6){return b6.nodeType===1});if(an.test(b4)){return bJ.filter(b4,b3,!e)}else{b4=bJ.filter(b4,b3)}}}}return bJ.grep(b5,function(b6){return(bJ.inArray(b6,b4)>=0)===e})}function A(e){var b4=d.split("|"),b3=e.createDocumentFragment();if(b3.createElement){while(b4.length){b3.createElement(b4.pop())}}return b3}var d="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",aA=/ jQuery\d+="(?:null|\d+)"/g,J=new RegExp("<(?:"+d+")[\\s/>]","i"),b2=/^\s+/,aD=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,m=/<([\w:]+)/,bX=/<tbody/i,I=/<|&#?\w+;/,al=/<(?:script|style|link)/i,q=/^(?:checkbox|radio)$/i,bU=/checked\s*(?:[^=]|=\s*.checked.)/i,bz=/^$|\/(?:java|ecma)script/i,ar=/^true\/(.*)/,aK=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,T={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:bJ.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},aS=A(l),j=aS.appendChild(l.createElement("div"));T.optgroup=T.option;T.tbody=T.tfoot=T.colgroup=T.caption=T.thead;T.th=T.td;bJ.fn.extend({text:function(e){return bJ.access(this,function(b3){return b3===aG?bJ.text(this):this.empty().append((this[0]&&this[0].ownerDocument||l).createTextNode(b3))},null,e,arguments.length)},wrapAll:function(e){if(bJ.isFunction(e)){return this.each(function(b4){bJ(this).wrapAll(e.call(this,b4))})}if(this[0]){var b3=bJ(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){b3.insertBefore(this[0])}b3.map(function(){var b4=this;while(b4.firstChild&&b4.firstChild.nodeType===1){b4=b4.firstChild}return b4}).append(this)}return this},wrapInner:function(e){if(bJ.isFunction(e)){return this.each(function(b3){bJ(this).wrapInner(e.call(this,b3))})}return this.each(function(){var b3=bJ(this),b4=b3.contents();if(b4.length){b4.wrapAll(e)}else{b3.append(e)}})},wrap:function(e){var b3=bJ.isFunction(e);return this.each(function(b4){bJ(this).wrapAll(b3?e.call(this,b4):e)})},unwrap:function(){return this.parent().each(function(){if(!bJ.nodeName(this,"body")){bJ(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){this.insertBefore(e,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(e){if(this.parentNode){this.parentNode.insertBefore(e,this)}})},after:function(){return this.domManip(arguments,false,function(e){if(this.parentNode){this.parentNode.insertBefore(e,this.nextSibling)}})},remove:function(e,b5){var b4,b3=0;for(;(b4=this[b3])!=null;b3++){if(!e||bJ.filter(e,[b4]).length>0){if(!b5&&b4.nodeType===1){bJ.cleanData(k(b4))}if(b4.parentNode){if(b5&&bJ.contains(b4.ownerDocument,b4)){bs(k(b4,"script"))}b4.parentNode.removeChild(b4)}}}return this},empty:function(){var b3,e=0;for(;(b3=this[e])!=null;e++){if(b3.nodeType===1){bJ.cleanData(k(b3,false))}while(b3.firstChild){b3.removeChild(b3.firstChild)}if(b3.options&&bJ.nodeName(b3,"select")){b3.options.length=0}}return this},clone:function(b3,e){b3=b3==null?false:b3;e=e==null?b3:e;return this.map(function(){return bJ.clone(this,b3,e)})},html:function(e){return bJ.access(this,function(b6){var b5=this[0]||{},b4=0,b3=this.length;if(b6===aG){return b5.nodeType===1?b5.innerHTML.replace(aA,""):aG}if(typeof b6==="string"&&!al.test(b6)&&(bJ.support.htmlSerialize||!J.test(b6))&&(bJ.support.leadingWhitespace||!b2.test(b6))&&!T[(m.exec(b6)||["",""])[1].toLowerCase()]){b6=b6.replace(aD,"<$1></$2>");try{for(;b4<b3;b4++){b5=this[b4]||{};if(b5.nodeType===1){bJ.cleanData(k(b5,false));b5.innerHTML=b6}}b5=0}catch(b7){}}if(b5){this.empty().append(b6)}},null,e,arguments.length)},replaceWith:function(b3){var e=bJ.isFunction(b3);if(!e&&typeof b3!=="string"){b3=bJ(b3).not(this).detach()}return this.domManip([b3],true,function(b6){var b5=this.nextSibling,b4=this.parentNode;if(b4){bJ(this).remove();b4.insertBefore(b6,b5)}})},detach:function(e){return this.remove(e,true)},domManip:function(ca,cg,cf){ca=aI.apply([],ca);var b8,b4,e,b6,cd,b9,b7=0,b5=this.length,cc=this,ce=b5-1,cb=ca[0],b3=bJ.isFunction(cb);if(b3||!(b5<=1||typeof cb!=="string"||bJ.support.checkClone||!bU.test(cb))){return this.each(function(ci){var ch=cc.eq(ci);if(b3){ca[0]=cb.call(this,ci,cg?ch.html():aG)}ch.domManip(ca,cg,cf)})}if(b5){b9=bJ.buildFragment(ca,this[0].ownerDocument,false,this);b8=b9.firstChild;if(b9.childNodes.length===1){b9=b8}if(b8){cg=cg&&bJ.nodeName(b8,"tr");b6=bJ.map(k(b9,"script"),t);e=b6.length;for(;b7<b5;b7++){b4=b9;if(b7!==ce){b4=bJ.clone(b4,true,true);if(e){bJ.merge(b6,k(b4,"script"))}}cf.call(cg&&bJ.nodeName(this[b7],"table")?x(this[b7],"tbody"):this[b7],b4,b7)}if(e){cd=b6[b6.length-1].ownerDocument;bJ.map(b6,bc);for(b7=0;b7<e;b7++){b4=b6[b7];if(bz.test(b4.type||"")&&!bJ._data(b4,"globalEval")&&bJ.contains(cd,b4)){if(b4.src){bJ.ajax({url:b4.src,type:"GET",dataType:"script",async:false,global:false,"throws":true})}else{bJ.globalEval((b4.text||b4.textContent||b4.innerHTML||"").replace(aK,""))}}}}b9=b8=null}}return this}});function x(b3,e){return b3.getElementsByTagName(e)[0]||b3.appendChild(b3.ownerDocument.createElement(e))}function t(b3){var e=b3.getAttributeNode("type");b3.type=(e&&e.specified)+"/"+b3.type;return b3}function bc(b3){var e=ar.exec(b3.type);if(e){b3.type=e[1]}else{b3.removeAttribute("type")}return b3}function bs(e,b4){var b5,b3=0;for(;(b5=e[b3])!=null;b3++){bJ._data(b5,"globalEval",!b4||bJ._data(b4[b3],"globalEval"))}}function at(b9,b3){if(b3.nodeType!==1||!bJ.hasData(b9)){return}var b6,b5,e,b8=bJ._data(b9),b7=bJ._data(b3,b8),b4=b8.events;if(b4){delete b7.handle;b7.events={};for(b6 in b4){for(b5=0,e=b4[b6].length;b5<e;b5++){bJ.event.add(b3,b6,b4[b6][b5])}}}if(b7.data){b7.data=bJ.extend({},b7.data)}}function Q(b6,b3){var b7,b5,b4;if(b3.nodeType!==1){return}b7=b3.nodeName.toLowerCase();if(!bJ.support.noCloneEvent&&b3[bJ.expando]){b4=bJ._data(b3);for(b5 in b4.events){bJ.removeEvent(b3,b5,b4.handle)}b3.removeAttribute(bJ.expando)}if(b7==="script"&&b3.text!==b6.text){t(b3).text=b6.text;bc(b3)}else{if(b7==="object"){if(b3.parentNode){b3.outerHTML=b6.outerHTML}if(bJ.support.html5Clone&&(b6.innerHTML&&!bJ.trim(b3.innerHTML))){b3.innerHTML=b6.innerHTML}}else{if(b7==="input"&&q.test(b6.type)){b3.defaultChecked=b3.checked=b6.checked;if(b3.value!==b6.value){b3.value=b6.value}}else{if(b7==="option"){b3.defaultSelected=b3.selected=b6.defaultSelected}else{if(b7==="input"||b7==="textarea"){b3.defaultValue=b6.defaultValue}}}}}}bJ.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,b3){bJ.fn[e]=function(b4){var b5,b7=0,b6=[],b9=bJ(b4),b8=b9.length-1;for(;b7<=b8;b7++){b5=b7===b8?this:this.clone(true);bJ(b9[b7])[b3](b5);ao.apply(b6,b5.get())}return this.pushStack(b6)}});function k(b5,e){var b3,b6,b4=0,b7=typeof b5.getElementsByTagName!==aC?b5.getElementsByTagName(e||"*"):typeof b5.querySelectorAll!==aC?b5.querySelectorAll(e||"*"):aG;if(!b7){for(b7=[],b3=b5.childNodes||b5;(b6=b3[b4])!=null;b4++){if(!e||bJ.nodeName(b6,e)){b7.push(b6)}else{bJ.merge(b7,k(b6,e))}}}return e===aG||e&&bJ.nodeName(b5,e)?bJ.merge([b5],b7):b7}function bV(e){if(q.test(e.type)){e.defaultChecked=e.checked}}bJ.extend({clone:function(b3,b5,e){var b7,b4,ca,b6,b8,b9=bJ.contains(b3.ownerDocument,b3);if(bJ.support.html5Clone||bJ.isXMLDoc(b3)||!J.test("<"+b3.nodeName+">")){ca=b3.cloneNode(true)}else{j.innerHTML=b3.outerHTML;j.removeChild(ca=j.firstChild)}if((!bJ.support.noCloneEvent||!bJ.support.noCloneChecked)&&(b3.nodeType===1||b3.nodeType===11)&&!bJ.isXMLDoc(b3)){b7=k(ca);b8=k(b3);for(b6=0;(b4=b8[b6])!=null;++b6){if(b7[b6]){Q(b4,b7[b6])}}}if(b5){if(e){b8=b8||k(b3);b7=b7||k(ca);for(b6=0;(b4=b8[b6])!=null;b6++){at(b4,b7[b6])}}else{at(b3,ca)}}b7=k(ca,"script");if(b7.length>0){bs(b7,!b9&&k(b3,"script"))}b7=b8=b4=null;return ca},buildFragment:function(b3,b5,ca,cf){var cb,b7,b9,ce,cg,cd,b4,b8=b3.length,b6=A(b5),e=[],cc=0;for(;cc<b8;cc++){b7=b3[cc];if(b7||b7===0){if(bJ.type(b7)==="object"){bJ.merge(e,b7.nodeType?[b7]:b7)}else{if(!I.test(b7)){e.push(b5.createTextNode(b7))}else{ce=ce||b6.appendChild(b5.createElement("div"));cg=(m.exec(b7)||["",""])[1].toLowerCase();b4=T[cg]||T._default;ce.innerHTML=b4[1]+b7.replace(aD,"<$1></$2>")+b4[2];cb=b4[0];while(cb--){ce=ce.lastChild}if(!bJ.support.leadingWhitespace&&b2.test(b7)){e.push(b5.createTextNode(b2.exec(b7)[0]))}if(!bJ.support.tbody){b7=cg==="table"&&!bX.test(b7)?ce.firstChild:b4[1]==="<table>"&&!bX.test(b7)?ce:0;cb=b7&&b7.childNodes.length;while(cb--){if(bJ.nodeName((cd=b7.childNodes[cb]),"tbody")&&!cd.childNodes.length){b7.removeChild(cd)}}}bJ.merge(e,ce.childNodes);ce.textContent="";while(ce.firstChild){ce.removeChild(ce.firstChild)}ce=b6.lastChild}}}}if(ce){b6.removeChild(ce)}if(!bJ.support.appendChecked){bJ.grep(k(e,"input"),bV)}cc=0;while((b7=e[cc++])){if(cf&&bJ.inArray(b7,cf)!==-1){continue}b9=bJ.contains(b7.ownerDocument,b7);ce=k(b6.appendChild(b7),"script");if(b9){bs(ce)}if(ca){cb=0;while((b7=ce[cb++])){if(bz.test(b7.type||"")){ca.push(b7)}}}}ce=null;return b6},cleanData:function(b3,cb){var b5,ca,b4,b6,b7=0,cc=bJ.expando,e=bJ.cache,b8=bJ.support.deleteExpando,b9=bJ.event.special;for(;(b5=b3[b7])!=null;b7++){if(cb||bJ.acceptData(b5)){b4=b5[cc];b6=b4&&e[b4];if(b6){if(b6.events){for(ca in b6.events){if(b9[ca]){bJ.event.remove(b5,ca)}else{bJ.removeEvent(b5,ca,b6.handle)}}}if(e[b4]){delete e[b4];if(b8){delete b5[cc]}else{if(typeof b5.removeAttribute!==aC){b5.removeAttribute(cc)}else{b5[cc]=null}}a6.push(b4)}}}}}});var aE,bo,E,bg=/alpha\([^)]*\)/i,aT=/opacity\s*=\s*([^)]*)/,bn=/^(top|right|bottom|left)$/,F=/^(none|table(?!-c[ea]).+)/,aY=/^margin/,a9=new RegExp("^("+bA+")(.*)$","i"),W=new RegExp("^("+bA+")(?!px)[a-z%]+$","i"),S=new RegExp("^([+-])=("+bA+")","i"),bj={BODY:"block"},bb={position:"absolute",visibility:"hidden",display:"block"},bC={letterSpacing:0,fontWeight:400},bT=["Top","Right","Bottom","Left"],av=["Webkit","O","Moz","ms"];function b(b5,b3){if(b3 in b5){return b3}var b6=b3.charAt(0).toUpperCase()+b3.slice(1),e=b3,b4=av.length;while(b4--){b3=av[b4]+b6;if(b3 in b5){return b3}}return e}function P(b3,e){b3=e||b3;return bJ.css(b3,"display")==="none"||!bJ.contains(b3.ownerDocument,b3)}function p(b8,e){var b9,b6,b7,b3=[],b4=0,b5=b8.length;for(;b4<b5;b4++){b6=b8[b4];if(!b6.style){continue}b3[b4]=bJ._data(b6,"olddisplay");b9=b6.style.display;if(e){if(!b3[b4]&&b9==="none"){b6.style.display=""}if(b6.style.display===""&&P(b6)){b3[b4]=bJ._data(b6,"olddisplay",bE(b6.nodeName))}}else{if(!b3[b4]){b7=P(b6);if(b9&&b9!=="none"||!b7){bJ._data(b6,"olddisplay",b7?b9:bJ.css(b6,"display"))}}}}for(b4=0;b4<b5;b4++){b6=b8[b4];if(!b6.style){continue}if(!e||b6.style.display==="none"||b6.style.display===""){b6.style.display=e?b3[b4]||"":"none"}}return b8}bJ.fn.extend({css:function(e,b3){return bJ.access(this,function(b8,b5,b9){var b4,b7,ca={},b6=0;if(bJ.isArray(b5)){b7=bo(b8);b4=b5.length;for(;b6<b4;b6++){ca[b5[b6]]=bJ.css(b8,b5[b6],false,b7)}return ca}return b9!==aG?bJ.style(b8,b5,b9):bJ.css(b8,b5)},e,b3,arguments.length>1)},show:function(){return p(this,true)},hide:function(){return p(this)},toggle:function(b3){var e=typeof b3==="boolean";return this.each(function(){if(e?b3:P(this)){bJ(this).show()}else{bJ(this).hide()}})}});bJ.extend({cssHooks:{opacity:{get:function(b4,b3){if(b3){var e=E(b4,"opacity");return e===""?"1":e}}}},cssNumber:{columnCount:true,fillOpacity:true,fontWeight:true,lineHeight:true,opacity:true,orphans:true,widows:true,zIndex:true,zoom:true},cssProps:{"float":bJ.support.cssFloat?"cssFloat":"styleFloat"},style:function(b5,b4,cb,b6){if(!b5||b5.nodeType===3||b5.nodeType===8||!b5.style){return}var b9,ca,cc,b7=bJ.camelCase(b4),b3=b5.style;b4=bJ.cssProps[b7]||(bJ.cssProps[b7]=b(b3,b7));cc=bJ.cssHooks[b4]||bJ.cssHooks[b7];if(cb!==aG){ca=typeof cb;if(ca==="string"&&(b9=S.exec(cb))){cb=(b9[1]+1)*b9[2]+parseFloat(bJ.css(b5,b4));ca="number"}if(cb==null||ca==="number"&&isNaN(cb)){return}if(ca==="number"&&!bJ.cssNumber[b7]){cb+="px"}if(!bJ.support.clearCloneStyle&&cb===""&&b4.indexOf("background")===0){b3[b4]="inherit"}if(!cc||!("set" in cc)||(cb=cc.set(b5,cb,b6))!==aG){try{b3[b4]=cb}catch(b8){}}}else{if(cc&&"get" in cc&&(b9=cc.get(b5,false,b6))!==aG){return b9}return b3[b4]}},css:function(b8,b6,b3,b7){var b5,b9,e,b4=bJ.camelCase(b6);b6=bJ.cssProps[b4]||(bJ.cssProps[b4]=b(b8.style,b4));e=bJ.cssHooks[b6]||bJ.cssHooks[b4];if(e&&"get" in e){b9=e.get(b8,true,b3)}if(b9===aG){b9=E(b8,b6,b7)}if(b9==="normal"&&b6 in bC){b9=bC[b6]}if(b3===""||b3){b5=parseFloat(b9);return b3===true||bJ.isNumeric(b5)?b5||0:b9}return b9},swap:function(b7,b6,b8,b5){var b4,b3,e={};for(b3 in b6){e[b3]=b7.style[b3];b7.style[b3]=b6[b3]}b4=b8.apply(b7,b5||[]);for(b3 in b6){b7.style[b3]=e[b3]}return b4}});if(a2.getComputedStyle){bo=function(e){return a2.getComputedStyle(e,null)};E=function(b6,b4,b8){var b5,b3,ca,b7=b8||bo(b6),b9=b7?b7.getPropertyValue(b4)||b7[b4]:aG,e=b6.style;if(b7){if(b9===""&&!bJ.contains(b6.ownerDocument,b6)){b9=bJ.style(b6,b4)}if(W.test(b9)&&aY.test(b4)){b5=e.width;b3=e.minWidth;ca=e.maxWidth;e.minWidth=e.maxWidth=e.width=b9;b9=b7.width;e.width=b5;e.minWidth=b3;e.maxWidth=ca}}return b9}}else{if(l.documentElement.currentStyle){bo=function(e){return e.currentStyle};E=function(b5,b3,b8){var b4,b7,b9,b6=b8||bo(b5),ca=b6?b6[b3]:aG,e=b5.style;if(ca==null&&e&&e[b3]){ca=e[b3]}if(W.test(ca)&&!bn.test(b3)){b4=e.left;b7=b5.runtimeStyle;b9=b7&&b7.left;if(b9){b7.left=b5.currentStyle.left}e.left=b3==="fontSize"?"1em":ca;ca=e.pixelLeft+"px";e.left=b4;if(b9){b7.left=b9}}return ca===""?"auto":ca}}}function aJ(e,b4,b5){var b3=a9.exec(b4);return b3?Math.max(0,b3[1]-(b5||0))+(b3[2]||"px"):b4}function aw(b6,b3,e,b8,b5){var b4=e===(b8?"border":"content")?4:b3==="width"?1:0,b7=0;for(;b4<4;b4+=2){if(e==="margin"){b7+=bJ.css(b6,e+bT[b4],true,b5)}if(b8){if(e==="content"){b7-=bJ.css(b6,"padding"+bT[b4],true,b5)}if(e!=="margin"){b7-=bJ.css(b6,"border"+bT[b4]+"Width",true,b5)}}else{b7+=bJ.css(b6,"padding"+bT[b4],true,b5);if(e!=="padding"){b7+=bJ.css(b6,"border"+bT[b4]+"Width",true,b5)}}}return b7}function u(b6,b3,e){var b5=true,b7=b3==="width"?b6.offsetWidth:b6.offsetHeight,b4=bo(b6),b8=bJ.support.boxSizing&&bJ.css(b6,"boxSizing",false,b4)==="border-box";if(b7<=0||b7==null){b7=E(b6,b3,b4);if(b7<0||b7==null){b7=b6.style[b3]}if(W.test(b7)){return b7}b5=b8&&(bJ.support.boxSizingReliable||b7===b6.style[b3]);b7=parseFloat(b7)||0}return(b7+aw(b6,b3,e||(b8?"border":"content"),b5,b4))+"px"}function bE(b4){var b3=l,e=bj[b4];if(!e){e=a1(b4,b3);if(e==="none"||!e){aE=(aE||bJ("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(b3.documentElement);b3=(aE[0].contentWindow||aE[0].contentDocument).document;b3.write("<!doctype html><html><body>");b3.close();e=a1(b4,b3);aE.detach()}bj[b4]=e}return e}function a1(e,b5){var b3=bJ(b5.createElement(e)).appendTo(b5.body),b4=bJ.css(b3[0],"display");b3.remove();return b4}bJ.each(["height","width"],function(b3,e){bJ.cssHooks[e]={get:function(b6,b5,b4){if(b5){return b6.offsetWidth===0&&F.test(bJ.css(b6,"display"))?bJ.swap(b6,bb,function(){return u(b6,e,b4)}):u(b6,e,b4)}},set:function(b6,b7,b4){var b5=b4&&bo(b6);return aJ(b6,b7,b4?aw(b6,e,b4,bJ.support.boxSizing&&bJ.css(b6,"boxSizing",false,b5)==="border-box",b5):0)}}});if(!bJ.support.opacity){bJ.cssHooks.opacity={get:function(b3,e){return aT.test((e&&b3.currentStyle?b3.currentStyle.filter:b3.style.filter)||"")?(0.01*parseFloat(RegExp.$1))+"":e?"1":""},set:function(b6,b7){var b5=b6.style,b3=b6.currentStyle,e=bJ.isNumeric(b7)?"alpha(opacity="+b7*100+")":"",b4=b3&&b3.filter||b5.filter||"";b5.zoom=1;if((b7>=1||b7==="")&&bJ.trim(b4.replace(bg,""))===""&&b5.removeAttribute){b5.removeAttribute("filter");if(b7===""||b3&&!b3.filter){return}}b5.filter=bg.test(b4)?b4.replace(bg,e):b4+" "+e}}}bJ(function(){if(!bJ.support.reliableMarginRight){bJ.cssHooks.marginRight={get:function(b3,e){if(e){return bJ.swap(b3,{display:"inline-block"},E,[b3,"marginRight"])}}}}if(!bJ.support.pixelPosition&&bJ.fn.position){bJ.each(["top","left"],function(e,b3){bJ.cssHooks[b3]={get:function(b5,b4){if(b4){b4=E(b5,b3);return W.test(b4)?bJ(b5).position()[b3]+"px":b4}}}})}});if(bJ.expr&&bJ.expr.filters){bJ.expr.filters.hidden=function(e){return e.offsetWidth<=0&&e.offsetHeight<=0||(!bJ.support.reliableHiddenOffsets&&((e.style&&e.style.display)||bJ.css(e,"display"))==="none")};bJ.expr.filters.visible=function(e){return !bJ.expr.filters.hidden(e)}}bJ.each({margin:"",padding:"",border:"Width"},function(e,b3){bJ.cssHooks[e+b3]={expand:function(b6){var b5=0,b4={},b7=typeof b6==="string"?b6.split(" "):[b6];for(;b5<4;b5++){b4[e+bT[b5]+b3]=b7[b5]||b7[b5-2]||b7[0]}return b4}};if(!aY.test(e)){bJ.cssHooks[e+b3].set=aJ}});var bv=/%20/g,aR=/\[\]$/,U=/\r?\n/g,c=/^(?:submit|button|image|reset|file)$/i,au=/^(?:input|select|textarea|keygen)/i;bJ.fn.extend({serialize:function(){return bJ.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=bJ.prop(this,"elements");return e?bJ.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!bJ(this).is(":disabled")&&au.test(this.nodeName)&&!c.test(e)&&(this.checked||!q.test(e))}).map(function(e,b3){var b4=bJ(this).val();return b4==null?null:bJ.isArray(b4)?bJ.map(b4,function(b5){return{name:b3.name,value:b5.replace(U,"\r\n")}}):{name:b3.name,value:b4.replace(U,"\r\n")}}).get()}});bJ.param=function(e,b4){var b5,b3=[],b6=function(b7,b8){b8=bJ.isFunction(b8)?b8():(b8==null?"":b8);b3[b3.length]=encodeURIComponent(b7)+"="+encodeURIComponent(b8)};if(b4===aG){b4=bJ.ajaxSettings&&bJ.ajaxSettings.traditional}if(bJ.isArray(e)||(e.jquery&&!bJ.isPlainObject(e))){bJ.each(e,function(){b6(this.name,this.value)})}else{for(b5 in e){i(b5,e[b5],b4,b6)}}return b3.join("&").replace(bv,"+")};function i(b4,b6,b3,b5){var e;if(bJ.isArray(b6)){bJ.each(b6,function(b8,b7){if(b3||aR.test(b4)){b5(b4,b7)}else{i(b4+"["+(typeof b7==="object"?b8:"")+"]",b7,b3,b5)}})}else{if(!b3&&bJ.type(b6)==="object"){for(e in b6){i(b4+"["+e+"]",b6[e],b3,b5)}}else{b5(b4,b6)}}}bJ.each(("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu").split(" "),function(b3,e){bJ.fn[e]=function(b5,b4){return arguments.length>0?this.on(e,null,b5,b4):this.trigger(e)}});bJ.fn.hover=function(e,b3){return this.mouseenter(e).mouseleave(b3||e)};var b1,Y,bO=bJ.now(),az=/\?/,ap=/#.*$/,O=/([?&])_=[^&]*/,ag=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,B=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,o=/^(?:GET|HEAD)$/,aH=/^\/\//,aU=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,b0=bJ.fn.load,v={},a7={},aW="*/".concat("*");try{Y=aL.href}catch(bf){Y=l.createElement("a");Y.href="";Y=Y.href}b1=aU.exec(Y.toLowerCase())||[];function bL(e){return function(b6,b7){if(typeof b6!=="string"){b7=b6;b6="*"}var b3,b4=0,b5=b6.toLowerCase().match(ac)||[];if(bJ.isFunction(b7)){while((b3=b5[b4++])){if(b3[0]==="+"){b3=b3.slice(1)||"*";(e[b3]=e[b3]||[]).unshift(b7)}else{(e[b3]=e[b3]||[]).push(b7)}}}}}function n(e,b4,b8,b5){var b3={},b6=(e===a7);function b7(b9){var ca;b3[b9]=true;bJ.each(e[b9]||[],function(cc,cb){var cd=cb(b4,b8,b5);if(typeof cd==="string"&&!b6&&!b3[cd]){b4.dataTypes.unshift(cd);b7(cd);return false}else{if(b6){return !(ca=cd)}}});return ca}return b7(b4.dataTypes[0])||!b3["*"]&&b7("*")}function r(b4,b5){var e,b3,b6=bJ.ajaxSettings.flatOptions||{};for(b3 in b5){if(b5[b3]!==aG){(b6[b3]?b4:(e||(e={})))[b3]=b5[b3]}}if(e){bJ.extend(true,b4,e)}return b4}bJ.fn.load=function(b5,b8,b9){if(typeof b5!=="string"&&b0){return b0.apply(this,arguments)}var e,b4,b6,b3=this,b7=b5.indexOf(" ");if(b7>=0){e=b5.slice(b7,b5.length);b5=b5.slice(0,b7)}if(bJ.isFunction(b8)){b9=b8;b8=aG}else{if(b8&&typeof b8==="object"){b6="POST"}}if(b3.length>0){bJ.ajax({url:b5,type:b6,dataType:"html",data:b8}).done(function(ca){b4=arguments;b3.html(e?bJ("<div>").append(bJ.parseHTML(ca)).find(e):ca)}).complete(b9&&function(cb,ca){b3.each(b9,b4||[cb.responseText,ca,cb])})}return this};bJ.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,b3){bJ.fn[b3]=function(b4){return this.on(b3,b4)}});bJ.each(["get","post"],function(e,b3){bJ[b3]=function(b4,b6,b7,b5){if(bJ.isFunction(b6)){b5=b5||b7;b7=b6;b6=aG}return bJ.ajax({url:b4,type:b3,dataType:b5,data:b6,success:b7})}});bJ.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Y,type:"GET",isLocal:B.test(b1[1]),global:true,processData:true,async:true,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":aW,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a2.String,"text html":true,"text json":bJ.parseJSON,"text xml":bJ.parseXML},flatOptions:{url:true,context:true}},ajaxSetup:function(b3,e){return e?r(r(b3,bJ.ajaxSettings),e):r(bJ.ajaxSettings,b3)},ajaxPrefilter:bL(v),ajaxTransport:bL(a7),ajax:function(b7,b4){if(typeof b7==="object"){b4=b7;b7=aG}b4=b4||{};var cg,ci,b8,cn,cc,b3,cj,b5,cb=bJ.ajaxSetup({},b4),cp=cb.context||cb,ce=cb.context&&(cp.nodeType||cp.jquery)?bJ(cp):bJ.event,co=bJ.Deferred(),cl=bJ.Callbacks("once memory"),b9=cb.statusCode||{},cf={},cm={},b6=0,ca="canceled",ch={readyState:0,getResponseHeader:function(cq){var e;if(b6===2){if(!b5){b5={};while((e=ag.exec(cn))){b5[e[1].toLowerCase()]=e[2]}}e=b5[cq.toLowerCase()]}return e==null?null:e},getAllResponseHeaders:function(){return b6===2?cn:null},setRequestHeader:function(cq,cr){var e=cq.toLowerCase();if(!b6){cq=cm[e]=cm[e]||cq;cf[cq]=cr}return this},overrideMimeType:function(e){if(!b6){cb.mimeType=e}return this},statusCode:function(cq){var e;if(cq){if(b6<2){for(e in cq){b9[e]=[b9[e],cq[e]]}}else{ch.always(cq[ch.status])}}return this},abort:function(cq){var e=cq||ca;if(cj){cj.abort(e)}cd(0,e);return this}};co.promise(ch).complete=cl.add;ch.success=ch.done;ch.error=ch.fail;cb.url=((b7||cb.url||Y)+"").replace(ap,"").replace(aH,b1[1]+"//");cb.type=b4.method||b4.type||cb.method||cb.type;cb.dataTypes=bJ.trim(cb.dataType||"*").toLowerCase().match(ac)||[""];if(cb.crossDomain==null){cg=aU.exec(cb.url.toLowerCase());cb.crossDomain=!!(cg&&(cg[1]!==b1[1]||cg[2]!==b1[2]||(cg[3]||(cg[1]==="http:"?80:443))!=(b1[3]||(b1[1]==="http:"?80:443))))}if(cb.data&&cb.processData&&typeof cb.data!=="string"){cb.data=bJ.param(cb.data,cb.traditional)}n(v,cb,b4,ch);if(b6===2){return ch}b3=cb.global;if(b3&&bJ.active++===0){bJ.event.trigger("ajaxStart")}cb.type=cb.type.toUpperCase();cb.hasContent=!o.test(cb.type);b8=cb.url;if(!cb.hasContent){if(cb.data){b8=(cb.url+=(az.test(b8)?"&":"?")+cb.data);delete cb.data}if(cb.cache===false){cb.url=O.test(b8)?b8.replace(O,"$1_="+bO++):b8+(az.test(b8)?"&":"?")+"_="+bO++}}if(cb.ifModified){if(bJ.lastModified[b8]){ch.setRequestHeader("If-Modified-Since",bJ.lastModified[b8])}if(bJ.etag[b8]){ch.setRequestHeader("If-None-Match",bJ.etag[b8])}}if(cb.data&&cb.hasContent&&cb.contentType!==false||b4.contentType){ch.setRequestHeader("Content-Type",cb.contentType)}ch.setRequestHeader("Accept",cb.dataTypes[0]&&cb.accepts[cb.dataTypes[0]]?cb.accepts[cb.dataTypes[0]]+(cb.dataTypes[0]!=="*"?", "+aW+"; q=0.01":""):cb.accepts["*"]);for(ci in cb.headers){ch.setRequestHeader(ci,cb.headers[ci])}if(cb.beforeSend&&(cb.beforeSend.call(cp,ch,cb)===false||b6===2)){return ch.abort()}ca="abort";for(ci in {success:1,error:1,complete:1}){ch[ci](cb[ci])}cj=n(a7,cb,b4,ch);if(!cj){cd(-1,"No Transport")}else{ch.readyState=1;if(b3){ce.trigger("ajaxSend",[ch,cb])}if(cb.async&&cb.timeout>0){cc=setTimeout(function(){ch.abort("timeout")},cb.timeout)}try{b6=1;cj.send(cf,cd)}catch(ck){if(b6<2){cd(-1,ck)}else{throw ck}}}function cd(cu,cq,cv,cs){var e,cy,cw,ct,cx,cr=cq;if(b6===2){return}b6=2;if(cc){clearTimeout(cc)}cj=aG;cn=cs||"";ch.readyState=cu>0?4:0;if(cv){ct=g(cb,ch,cv)}if(cu>=200&&cu<300||cu===304){if(cb.ifModified){cx=ch.getResponseHeader("Last-Modified");if(cx){bJ.lastModified[b8]=cx}cx=ch.getResponseHeader("etag");if(cx){bJ.etag[b8]=cx}}if(cu===204){e=true;cr="nocontent"}else{if(cu===304){e=true;cr="notmodified"}else{e=af(cb,ct);cr=e.state;cy=e.data;cw=e.error;e=!cw}}}else{cw=cr;if(cu||!cr){cr="error";if(cu<0){cu=0}}}ch.status=cu;ch.statusText=(cq||cr)+"";if(e){co.resolveWith(cp,[cy,cr,ch])}else{co.rejectWith(cp,[ch,cr,cw])}ch.statusCode(b9);b9=aG;if(b3){ce.trigger(e?"ajaxSuccess":"ajaxError",[ch,cb,e?cy:cw])}cl.fireWith(cp,[ch,cr]);if(b3){ce.trigger("ajaxComplete",[ch,cb]);if(!(--bJ.active)){bJ.event.trigger("ajaxStop")}}}return ch},getScript:function(e,b3){return bJ.get(e,aG,b3,"script")},getJSON:function(e,b3,b4){return bJ.get(e,b3,b4,"json")}});function g(cb,ca,b7){var e,b6,b5,b8,b3=cb.contents,b9=cb.dataTypes,b4=cb.responseFields;for(b8 in b4){if(b8 in b7){ca[b4[b8]]=b7[b8]}}while(b9[0]==="*"){b9.shift();if(b6===aG){b6=cb.mimeType||ca.getResponseHeader("Content-Type")}}if(b6){for(b8 in b3){if(b3[b8]&&b3[b8].test(b6)){b9.unshift(b8);break}}}if(b9[0] in b7){b5=b9[0]}else{for(b8 in b7){if(!b9[0]||cb.converters[b8+" "+b9[0]]){b5=b8;break}if(!e){e=b8}}b5=b5||e}if(b5){if(b5!==b9[0]){b9.unshift(b5)}return b7[b5]}}function af(cd,b5){var b3,b9,cb,b6,cc={},b7=0,ca=cd.dataTypes.slice(),b4=ca[0];if(cd.dataFilter){b5=cd.dataFilter(b5,cd.dataType)}if(ca[1]){for(cb in cd.converters){cc[cb.toLowerCase()]=cd.converters[cb]}}for(;(b9=ca[++b7]);){if(b9!=="*"){if(b4!=="*"&&b4!==b9){cb=cc[b4+" "+b9]||cc["* "+b9];if(!cb){for(b3 in cc){b6=b3.split(" ");if(b6[1]===b9){cb=cc[b4+" "+b6[0]]||cc["* "+b6[0]];if(cb){if(cb===true){cb=cc[b3]}else{if(cc[b3]!==true){b9=b6[0];ca.splice(b7--,0,b9)}}break}}}}if(cb!==true){if(cb&&cd["throws"]){b5=cb(b5)}else{try{b5=cb(b5)}catch(b8){return{state:"parsererror",error:cb?b8:"No conversion from "+b4+" to "+b9}}}}}b4=b9}}return{state:"success",data:b5}}bJ.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){bJ.globalEval(e);return e}}});bJ.ajaxPrefilter("script",function(e){if(e.cache===aG){e.cache=false}if(e.crossDomain){e.type="GET";e.global=false}});bJ.ajaxTransport("script",function(b4){if(b4.crossDomain){var e,b3=l.head||bJ("head")[0]||l.documentElement;return{send:function(b5,b6){e=l.createElement("script");e.async=true;if(b4.scriptCharset){e.charset=b4.scriptCharset}e.src=b4.url;e.onload=e.onreadystatechange=function(b8,b7){if(b7||!e.readyState||/loaded|complete/.test(e.readyState)){e.onload=e.onreadystatechange=null;if(e.parentNode){e.parentNode.removeChild(e)}e=null;if(!b7){b6(200,"success")}}};b3.insertBefore(e,b3.firstChild)},abort:function(){if(e){e.onload(aG,true)}}}}});var bq=[],a5=/(=)\?(?=&|$)|\?\?/;bJ.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=bq.pop()||(bJ.expando+"_"+(bO++));this[e]=true;return e}});bJ.ajaxPrefilter("json jsonp",function(b5,e,b6){var b8,b3,b4,b7=b5.jsonp!==false&&(a5.test(b5.url)?"url":typeof b5.data==="string"&&!(b5.contentType||"").indexOf("application/x-www-form-urlencoded")&&a5.test(b5.data)&&"data");if(b7||b5.dataTypes[0]==="jsonp"){b8=b5.jsonpCallback=bJ.isFunction(b5.jsonpCallback)?b5.jsonpCallback():b5.jsonpCallback;if(b7){b5[b7]=b5[b7].replace(a5,"$1"+b8)}else{if(b5.jsonp!==false){b5.url+=(az.test(b5.url)?"&":"?")+b5.jsonp+"="+b8}}b5.converters["script json"]=function(){if(!b4){bJ.error(b8+" was not called")}return b4[0]};b5.dataTypes[0]="json";b3=a2[b8];a2[b8]=function(){b4=arguments};b6.always(function(){a2[b8]=b3;if(b5[b8]){b5.jsonpCallback=e.jsonpCallback;bq.push(b8)}if(b4&&bJ.isFunction(b3)){b3(b4[0])}b4=b3=aG});return"script"}});var ah,ax,ay=0,aP=a2.ActiveXObject&&function(){var e;for(e in ah){ah[e](aG,true)}};function bD(){try{return new a2.XMLHttpRequest()}catch(b3){}}function bd(){try{return new a2.ActiveXObject("Microsoft.XMLHTTP")}catch(b3){}}bJ.ajaxSettings.xhr=a2.ActiveXObject?function(){return !this.isLocal&&bD()||bd()}:bD;ax=bJ.ajaxSettings.xhr();bJ.support.cors=!!ax&&("withCredentials" in ax);ax=bJ.support.ajax=!!ax;if(ax){bJ.ajaxTransport(function(e){if(!e.crossDomain||bJ.support.cors){var b3;return{send:function(b9,b4){var b7,b5,b8=e.xhr();if(e.username){b8.open(e.type,e.url,e.async,e.username,e.password)}else{b8.open(e.type,e.url,e.async)}if(e.xhrFields){for(b5 in e.xhrFields){b8[b5]=e.xhrFields[b5]}}if(e.mimeType&&b8.overrideMimeType){b8.overrideMimeType(e.mimeType)}if(!e.crossDomain&&!b9["X-Requested-With"]){b9["X-Requested-With"]="XMLHttpRequest"}try{for(b5 in b9){b8.setRequestHeader(b5,b9[b5])}}catch(b6){}b8.send((e.hasContent&&e.data)||null);b3=function(cc,cb){var ca,cd,cg,ce;try{if(b3&&(cb||b8.readyState===4)){b3=aG;if(b7){b8.onreadystatechange=bJ.noop;if(aP){delete ah[b7]}}if(cb){if(b8.readyState!==4){b8.abort()}}else{ce={};ca=b8.status;cd=b8.getAllResponseHeaders();if(typeof b8.responseText==="string"){ce.text=b8.responseText}try{cg=b8.statusText}catch(cf){cg=""}if(!ca&&e.isLocal&&!e.crossDomain){ca=ce.text?200:404}else{if(ca===1223){ca=204}}}}}catch(ch){if(!cb){b4(-1,ch)}}if(ce){b4(ca,cg,ce,cd)}};if(!e.async){b3()}else{if(b8.readyState===4){setTimeout(b3)}else{b7=++ay;if(aP){if(!ah){ah={};bJ(a2).unload(aP)}ah[b7]=b3}b8.onreadystatechange=b3}}},abort:function(){if(b3){b3(aG,true)}}}}})}var K,ad,bR=/^(?:toggle|show|hide)$/,bK=new RegExp("^(?:([+-])=|)("+bA+")([a-z%]*)$","i"),bQ=/queueHooks$/,aB=[h],a0={"*":[function(e,b9){var b5,ca,cb=this.createTween(e,b9),b6=bK.exec(b9),b7=cb.cur(),b3=+b7||0,b4=1,b8=20;if(b6){b5=+b6[2];ca=b6[3]||(bJ.cssNumber[e]?"":"px");if(ca!=="px"&&b3){b3=bJ.css(cb.elem,e,true)||b5||1;do{b4=b4||".5";b3=b3/b4;bJ.style(cb.elem,e,b3+ca)}while(b4!==(b4=cb.cur()/b7)&&b4!==1&&--b8)}cb.unit=ca;cb.start=b3;cb.end=b6[1]?b3+(b6[1]+1)*b5:b5}return cb}]};function bm(){setTimeout(function(){K=aG});return(K=bJ.now())}function be(b3,e){bJ.each(e,function(b8,b6){var b7=(a0[b8]||[]).concat(a0["*"]),b4=0,b5=b7.length;for(;b4<b5;b4++){if(b7[b4].call(b3,b8,b6)){return}}})}function f(b4,b8,cb){var cc,e,b7=0,b3=aB.length,ca=bJ.Deferred().always(function(){delete b6.elem}),b6=function(){if(e){return false}var ci=K||bm(),cf=Math.max(0,b5.startTime+b5.duration-ci),cd=cf/b5.duration||0,ch=1-cd,ce=0,cg=b5.tweens.length;for(;ce<cg;ce++){b5.tweens[ce].run(ch)}ca.notifyWith(b4,[b5,ch,cf]);if(ch<1&&cg){return cf}else{ca.resolveWith(b4,[b5]);return false}},b5=ca.promise({elem:b4,props:bJ.extend({},b8),opts:bJ.extend(true,{specialEasing:{}},cb),originalProperties:b8,originalOptions:cb,startTime:K||bm(),duration:cb.duration,tweens:[],createTween:function(cf,cd){var ce=bJ.Tween(b4,b5.opts,cf,cd,b5.opts.specialEasing[cf]||b5.opts.easing);b5.tweens.push(ce);return ce},stop:function(ce){var cd=0,cf=ce?b5.tweens.length:0;if(e){return this}e=true;for(;cd<cf;cd++){b5.tweens[cd].run(1)}if(ce){ca.resolveWith(b4,[b5,ce])}else{ca.rejectWith(b4,[b5,ce])}return this}}),b9=b5.props;am(b9,b5.opts.specialEasing);for(;b7<b3;b7++){cc=aB[b7].call(b5,b4,b9,b5.opts);if(cc){return cc}}be(b5,b9);if(bJ.isFunction(b5.opts.start)){b5.opts.start.call(b4,b5)}bJ.fx.timer(bJ.extend(b6,{elem:b4,anim:b5,queue:b5.opts.queue}));return b5.progress(b5.opts.progress).done(b5.opts.done,b5.opts.complete).fail(b5.opts.fail).always(b5.opts.always)}function am(b5,b7){var b6,b4,b3,b8,e;for(b3 in b5){b4=bJ.camelCase(b3);b8=b7[b4];b6=b5[b3];if(bJ.isArray(b6)){b8=b6[1];b6=b5[b3]=b6[0]}if(b3!==b4){b5[b4]=b6;delete b5[b3]}e=bJ.cssHooks[b4];if(e&&"expand" in e){b6=e.expand(b6);delete b5[b4];for(b3 in b6){if(!(b3 in b5)){b5[b3]=b6[b3];b7[b3]=b8}}}else{b7[b4]=b8}}}bJ.Animation=bJ.extend(f,{tweener:function(b3,b6){if(bJ.isFunction(b3)){b6=b3;b3=["*"]}else{b3=b3.split(" ")}var b5,e=0,b4=b3.length;for(;e<b4;e++){b5=b3[e];a0[b5]=a0[b5]||[];a0[b5].unshift(b6)}},prefilter:function(b3,e){if(e){aB.unshift(b3)}else{aB.push(b3)}}});function h(b6,cc,e){var b4,cb,b5,ce,ci,b8,ch,cg,cf,b7=this,b3=b6.style,cd={},ca=[],b9=b6.nodeType&&P(b6);if(!e.queue){cg=bJ._queueHooks(b6,"fx");if(cg.unqueued==null){cg.unqueued=0;cf=cg.empty.fire;cg.empty.fire=function(){if(!cg.unqueued){cf()}}}cg.unqueued++;b7.always(function(){b7.always(function(){cg.unqueued--;if(!bJ.queue(b6,"fx").length){cg.empty.fire()}})})}if(b6.nodeType===1&&("height" in cc||"width" in cc)){e.overflow=[b3.overflow,b3.overflowX,b3.overflowY];if(bJ.css(b6,"display")==="inline"&&bJ.css(b6,"float")==="none"){if(!bJ.support.inlineBlockNeedsLayout||bE(b6.nodeName)==="inline"){b3.display="inline-block"}else{b3.zoom=1}}}if(e.overflow){b3.overflow="hidden";if(!bJ.support.shrinkWrapBlocks){b7.always(function(){b3.overflow=e.overflow[0];b3.overflowX=e.overflow[1];b3.overflowY=e.overflow[2]})}}for(cb in cc){ce=cc[cb];if(bR.exec(ce)){delete cc[cb];b8=b8||ce==="toggle";if(ce===(b9?"hide":"show")){continue}ca.push(cb)}}b5=ca.length;if(b5){ci=bJ._data(b6,"fxshow")||bJ._data(b6,"fxshow",{});if("hidden" in ci){b9=ci.hidden}if(b8){ci.hidden=!b9}if(b9){bJ(b6).show()}else{b7.done(function(){bJ(b6).hide()})}b7.done(function(){var cj;bJ._removeData(b6,"fxshow");for(cj in cd){bJ.style(b6,cj,cd[cj])}});for(cb=0;cb<b5;cb++){b4=ca[cb];ch=b7.createTween(b4,b9?ci[b4]:0);cd[b4]=ci[b4]||bJ.style(b6,b4);if(!(b4 in ci)){ci[b4]=ch.start;if(b9){ch.end=ch.start;ch.start=b4==="width"||b4==="height"?1:0}}}}}function G(b4,b3,b6,e,b5){return new G.prototype.init(b4,b3,b6,e,b5)}bJ.Tween=G;G.prototype={constructor:G,init:function(b5,b3,b7,e,b6,b4){this.elem=b5;this.prop=b7;this.easing=b6||"swing";this.options=b3;this.start=this.now=this.cur();this.end=e;this.unit=b4||(bJ.cssNumber[b7]?"":"px")},cur:function(){var e=G.propHooks[this.prop];return e&&e.get?e.get(this):G.propHooks._default.get(this)},run:function(b4){var b3,e=G.propHooks[this.prop];if(this.options.duration){this.pos=b3=bJ.easing[this.easing](b4,this.options.duration*b4,0,1,this.options.duration)}else{this.pos=b3=b4}this.now=(this.end-this.start)*b3+this.start;if(this.options.step){this.options.step.call(this.elem,this.now,this)}if(e&&e.set){e.set(this)}else{G.propHooks._default.set(this)}return this}};G.prototype.init.prototype=G.prototype;G.propHooks={_default:{get:function(b3){var e;if(b3.elem[b3.prop]!=null&&(!b3.elem.style||b3.elem.style[b3.prop]==null)){return b3.elem[b3.prop]}e=bJ.css(b3.elem,b3.prop,"");return !e||e==="auto"?0:e},set:function(e){if(bJ.fx.step[e.prop]){bJ.fx.step[e.prop](e)}else{if(e.elem.style&&(e.elem.style[bJ.cssProps[e.prop]]!=null||bJ.cssHooks[e.prop])){bJ.style(e.elem,e.prop,e.now+e.unit)}else{e.elem[e.prop]=e.now}}}}};G.propHooks.scrollTop=G.propHooks.scrollLeft={set:function(e){if(e.elem.nodeType&&e.elem.parentNode){e.elem[e.prop]=e.now}}};bJ.each(["toggle","show","hide"],function(b3,e){var b4=bJ.fn[e];bJ.fn[e]=function(b5,b7,b6){return b5==null||typeof b5==="boolean"?b4.apply(this,arguments):this.animate(bI(e,true),b5,b7,b6)}});bJ.fn.extend({fadeTo:function(e,b5,b4,b3){return this.filter(P).css("opacity",0).show().end().animate({opacity:b5},e,b4,b3)},animate:function(b8,b5,b7,b6){var b4=bJ.isEmptyObject(b8),e=bJ.speed(b5,b7,b6),b3=function(){var b9=f(this,bJ.extend({},b8),e);b3.finish=function(){b9.stop(true)};if(b4||bJ._data(this,"finish")){b9.stop(true)}};b3.finish=b3;return b4||e.queue===false?this.each(b3):this.queue(e.queue,b3)},stop:function(b4,b3,e){var b5=function(b6){var b7=b6.stop;delete b6.stop;b7(e)};if(typeof b4!=="string"){e=b3;b3=b4;b4=aG}if(b3&&b4!==false){this.queue(b4||"fx",[])}return this.each(function(){var b9=true,b6=b4!=null&&b4+"queueHooks",b8=bJ.timers,b7=bJ._data(this);if(b6){if(b7[b6]&&b7[b6].stop){b5(b7[b6])}}else{for(b6 in b7){if(b7[b6]&&b7[b6].stop&&bQ.test(b6)){b5(b7[b6])}}}for(b6=b8.length;b6--;){if(b8[b6].elem===this&&(b4==null||b8[b6].queue===b4)){b8[b6].anim.stop(e);b9=false;b8.splice(b6,1)}}if(b9||!e){bJ.dequeue(this,b4)}})},finish:function(e){if(e!==false){e=e||"fx"}return this.each(function(){var b5,b8=bJ._data(this),b4=b8[e+"queue"],b3=b8[e+"queueHooks"],b7=bJ.timers,b6=b4?b4.length:0;b8.finish=true;bJ.queue(this,e,[]);if(b3&&b3.cur&&b3.cur.finish){b3.cur.finish.call(this)}for(b5=b7.length;b5--;){if(b7[b5].elem===this&&b7[b5].queue===e){b7[b5].anim.stop(true);b7.splice(b5,1)}}for(b5=0;b5<b6;b5++){if(b4[b5]&&b4[b5].finish){b4[b5].finish.call(this)}}delete b8.finish})}});function bI(b4,b6){var b5,e={height:b4},b3=0;b6=b6?1:0;for(;b3<4;b3+=2-b6){b5=bT[b3];e["margin"+b5]=e["padding"+b5]=b4}if(b6){e.opacity=e.width=b4}return e}bJ.each({slideDown:bI("show"),slideUp:bI("hide"),slideToggle:bI("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,b3){bJ.fn[e]=function(b4,b6,b5){return this.animate(b3,b4,b6,b5)}});bJ.speed=function(b4,b5,b3){var e=b4&&typeof b4==="object"?bJ.extend({},b4):{complete:b3||!b3&&b5||bJ.isFunction(b4)&&b4,duration:b4,easing:b3&&b5||b5&&!bJ.isFunction(b5)&&b5};e.duration=bJ.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in bJ.fx.speeds?bJ.fx.speeds[e.duration]:bJ.fx.speeds._default;if(e.queue==null||e.queue===true){e.queue="fx"}e.old=e.complete;e.complete=function(){if(bJ.isFunction(e.old)){e.old.call(this)}if(e.queue){bJ.dequeue(this,e.queue)}};return e};bJ.easing={linear:function(e){return e},swing:function(e){return 0.5-Math.cos(e*Math.PI)/2}};bJ.timers=[];bJ.fx=G.prototype.init;bJ.fx.tick=function(){var b4,b3=bJ.timers,e=0;K=bJ.now();for(;e<b3.length;e++){b4=b3[e];if(!b4()&&b3[e]===b4){b3.splice(e--,1)}}if(!b3.length){bJ.fx.stop()}K=aG};bJ.fx.timer=function(e){if(e()&&bJ.timers.push(e)){bJ.fx.start()}};bJ.fx.interval=13;bJ.fx.start=function(){if(!ad){ad=setInterval(bJ.fx.tick,bJ.fx.interval)}};bJ.fx.stop=function(){clearInterval(ad);ad=null};bJ.fx.speeds={slow:600,fast:200,_default:400};bJ.fx.step={};if(bJ.expr&&bJ.expr.filters){bJ.expr.filters.animated=function(e){return bJ.grep(bJ.timers,function(b3){return e===b3.elem}).length}}bJ.fn.offset=function(b3){if(arguments.length){return b3===aG?this:this.each(function(b8){bJ.offset.setOffset(this,b3,b8)})}var e,b7,b5={top:0,left:0},b4=this[0],b6=b4&&b4.ownerDocument;if(!b6){return}e=b6.documentElement;if(!bJ.contains(e,b4)){return b5}if(typeof b4.getBoundingClientRect!==aC){b5=b4.getBoundingClientRect()}b7=bp(b6);return{top:b5.top+(b7.pageYOffset||e.scrollTop)-(e.clientTop||0),left:b5.left+(b7.pageXOffset||e.scrollLeft)-(e.clientLeft||0)}};bJ.offset={setOffset:function(b5,ce,b8){var b9=bJ.css(b5,"position");if(b9==="static"){b5.style.position="relative"}var b7=bJ(b5),b3=b7.offset(),e=bJ.css(b5,"top"),cc=bJ.css(b5,"left"),cd=(b9==="absolute"||b9==="fixed")&&bJ.inArray("auto",[e,cc])>-1,cb={},ca={},b4,b6;if(cd){ca=b7.position();b4=ca.top;b6=ca.left}else{b4=parseFloat(e)||0;b6=parseFloat(cc)||0}if(bJ.isFunction(ce)){ce=ce.call(b5,b8,b3)}if(ce.top!=null){cb.top=(ce.top-b3.top)+b4}if(ce.left!=null){cb.left=(ce.left-b3.left)+b6}if("using" in ce){ce.using.call(b5,cb)}else{b7.css(cb)}}};bJ.fn.extend({position:function(){if(!this[0]){return}var b4,b5,e={top:0,left:0},b3=this[0];if(bJ.css(b3,"position")==="fixed"){b5=b3.getBoundingClientRect()}else{b4=this.offsetParent();b5=this.offset();if(!bJ.nodeName(b4[0],"html")){e=b4.offset()}e.top+=bJ.css(b4[0],"borderTopWidth",true);e.left+=bJ.css(b4[0],"borderLeftWidth",true)}return{top:b5.top-e.top-bJ.css(b3,"marginTop",true),left:b5.left-e.left-bJ.css(b3,"marginLeft",true)}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||l.documentElement;while(e&&(!bJ.nodeName(e,"html")&&bJ.css(e,"position")==="static")){e=e.offsetParent}return e||l.documentElement})}});bJ.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b4,b3){var e=/Y/.test(b3);bJ.fn[b4]=function(b5){return bJ.access(this,function(b6,b9,b8){var b7=bp(b6);if(b8===aG){return b7?(b3 in b7)?b7[b3]:b7.document.documentElement[b9]:b6[b9]}if(b7){b7.scrollTo(!e?b8:bJ(b7).scrollLeft(),e?b8:bJ(b7).scrollTop())}else{b6[b9]=b8}},b4,b5,arguments.length,null)}});function bp(e){return bJ.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}bJ.each({Height:"height",Width:"width"},function(e,b3){bJ.each({padding:"inner"+e,content:b3,"":"outer"+e},function(b4,b5){bJ.fn[b5]=function(b9,b8){var b7=arguments.length&&(b4||typeof b9!=="boolean"),b6=b4||(b9===true||b8===true?"margin":"border");return bJ.access(this,function(cb,ca,cc){var cd;if(bJ.isWindow(cb)){return cb.document.documentElement["client"+e]}if(cb.nodeType===9){cd=cb.documentElement;return Math.max(cb.body["scroll"+e],cd["scroll"+e],cb.body["offset"+e],cd["offset"+e],cd["client"+e])}return cc===aG?bJ.css(cb,ca,b6):bJ.style(cb,ca,cc,b6)},b3,b7?b9:aG,b7,null)}})});a2.jQuery=a2.$=bJ;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return bJ})}})(window);
WRFILE: jquery.jqplot.min.js

(function(L){var u;L.fn.emptyForce=function(){for(var ah=0,ai;(ai=L(this)[ah])!=null;ah++){if(ai.nodeType===1){L.cleanData(ai.getElementsByTagName("*"))}if(L.jqplot.use_excanvas){ai.outerHTML=""}else{while(ai.firstChild){ai.removeChild(ai.firstChild)}}ai=null}return L(this)};L.fn.removeChildForce=function(ah){while(ah.firstChild){this.removeChildForce(ah.firstChild);ah.removeChild(ah.firstChild)}};L.fn.jqplot=function(){var ah=[];var aj=[];for(var ak=0,ai=arguments.length;ak<ai;ak++){if(L.isArray(arguments[ak])){ah.push(arguments[ak])}else{if(L.isPlainObject(arguments[ak])){aj.push(arguments[ak])}}}return this.each(function(an){var at,ar,aq=L(this),am=ah.length,al=aj.length,ap,ao;if(an<am){ap=ah[an]}else{ap=am?ah[am-1]:null}if(an<al){ao=aj[an]}else{ao=al?aj[al-1]:null}at=aq.attr("id");if(at===u){at="jqplot_target_"+L.jqplot.targetCounter++;aq.attr("id",at)}ar=L.jqplot(at,ap,ao);aq.data("jqplot",ar)})};L.jqplot=function(an,ak,ai){var aj=null,ah=null;if(arguments.length===3){aj=ak;ah=ai}else{if(arguments.length===2){if(L.isArray(ak)){aj=ak}else{if(L.isPlainObject(ak)){ah=ak}}}}if(aj===null&&ah!==null&&ah.data){aj=ah.data}var am=new R();L("#"+an).removeClass("jqplot-error");if(L.jqplot.config.catchErrors){try{am.init(an,aj,ah);am.draw();am.themeEngine.init.call(am);return am}catch(al){var ao=L.jqplot.config.errorMessage||al.message;L("#"+an).append('<div class="jqplot-error-message">'+ao+"</div>");L("#"+an).addClass("jqplot-error");document.getElementById(an).style.background=L.jqplot.config.errorBackground;document.getElementById(an).style.border=L.jqplot.config.errorBorder;document.getElementById(an).style.fontFamily=L.jqplot.config.errorFontFamily;document.getElementById(an).style.fontSize=L.jqplot.config.errorFontSize;document.getElementById(an).style.fontStyle=L.jqplot.config.errorFontStyle;document.getElementById(an).style.fontWeight=L.jqplot.config.errorFontWeight}}else{am.init(an,aj,ah);am.draw();am.themeEngine.init.call(am);return am}};L.jqplot.version="1.0.8";L.jqplot.revision="1250";L.jqplot.targetCounter=1;L.jqplot.CanvasManager=function(){if(typeof L.jqplot.CanvasManager.canvases=="undefined"){L.jqplot.CanvasManager.canvases=[];L.jqplot.CanvasManager.free=[]}var ah=[];this.getCanvas=function(){var ak;var aj=true;if(!L.jqplot.use_excanvas){for(var al=0,ai=L.jqplot.CanvasManager.canvases.length;al<ai;al++){if(L.jqplot.CanvasManager.free[al]===true){aj=false;ak=L.jqplot.CanvasManager.canvases[al];L.jqplot.CanvasManager.free[al]=false;ah.push(al);break}}}if(aj){ak=document.createElement("canvas");ah.push(L.jqplot.CanvasManager.canvases.length);L.jqplot.CanvasManager.canvases.push(ak);L.jqplot.CanvasManager.free.push(false)}return ak};this.initCanvas=function(ai){if(L.jqplot.use_excanvas){return window.G_vmlCanvasManager.initElement(ai)}return ai};this.freeAllCanvases=function(){for(var aj=0,ai=ah.length;aj<ai;aj++){this.freeCanvas(ah[aj])}ah=[]};this.freeCanvas=function(ai){if(L.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==u){window.G_vmlCanvasManager.uninitElement(L.jqplot.CanvasManager.canvases[ai]);L.jqplot.CanvasManager.canvases[ai]=null}else{var aj=L.jqplot.CanvasManager.canvases[ai];aj.getContext("2d").clearRect(0,0,aj.width,aj.height);L(aj).unbind().removeAttr("class").removeAttr("style");L(aj).css({left:"",top:"",position:""});aj.width=0;aj.height=0;L.jqplot.CanvasManager.free[ai]=true}}};L.jqplot.log=function(){if(window.console){window.console.log.apply(window.console,arguments)}};L.jqplot.config={addDomReference:false,enablePlugins:false,defaultHeight:300,defaultWidth:400,UTCAdjust:false,timezoneOffset:new Date(new Date().getTimezoneOffset()*60000),errorMessage:"",errorBackground:"",errorBorder:"",errorFontFamily:"",errorFontSize:"",errorFontStyle:"",errorFontWeight:"",catchErrors:false,defaultTickFormatString:"%.1f",defaultColors:["#4bb2c5","#EAA228","#c5b47f","#579575","#839557","#958c12","#953579","#4b5de4","#d8b83f","#ff5800","#0085cc","#c747a3","#cddf54","#FBD178","#26B4E3","#bd70c7"],defaultNegativeColors:["#498991","#C08840","#9F9274","#546D61","#646C4A","#6F6621","#6E3F5F","#4F64B0","#A89050","#C45923","#187399","#945381","#959E5C","#C7AF7B","#478396","#907294"],dashLength:4,gapLength:4,dotGapLength:2.5,srcLocation:"jqplot/src/",pluginLocation:"jqplot/src/plugins/"};L.jqplot.arrayMax=function(ah){return Math.max.apply(Math,ah)};L.jqplot.arrayMin=function(ah){return Math.min.apply(Math,ah)};L.jqplot.enablePlugins=L.jqplot.config.enablePlugins;L.jqplot.support_canvas=function(){if(typeof L.jqplot.support_canvas.result=="undefined"){L.jqplot.support_canvas.result=!!document.createElement("canvas").getContext}return L.jqplot.support_canvas.result};L.jqplot.support_canvas_text=function(){if(typeof L.jqplot.support_canvas_text.result=="undefined"){if(window.G_vmlCanvasManager!==u&&window.G_vmlCanvasManager._version>887){L.jqplot.support_canvas_text.result=true}else{L.jqplot.support_canvas_text.result=!!(document.createElement("canvas").getContext&&typeof document.createElement("canvas").getContext("2d").fillText=="function")}}return L.jqplot.support_canvas_text.result};L.jqplot.use_excanvas=((!L.support.boxModel||!L.support.objectAll||!$support.leadingWhitespace)&&!L.jqplot.support_canvas())?true:false;L.jqplot.preInitHooks=[];L.jqplot.postInitHooks=[];L.jqplot.preParseOptionsHooks=[];L.jqplot.postParseOptionsHooks=[];L.jqplot.preDrawHooks=[];L.jqplot.postDrawHooks=[];L.jqplot.preDrawSeriesHooks=[];L.jqplot.postDrawSeriesHooks=[];L.jqplot.preDrawLegendHooks=[];L.jqplot.addLegendRowHooks=[];L.jqplot.preSeriesInitHooks=[];L.jqplot.postSeriesInitHooks=[];L.jqplot.preParseSeriesOptionsHooks=[];L.jqplot.postParseSeriesOptionsHooks=[];L.jqplot.eventListenerHooks=[];L.jqplot.preDrawSeriesShadowHooks=[];L.jqplot.postDrawSeriesShadowHooks=[];L.jqplot.ElemContainer=function(){this._elem;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null}};L.jqplot.ElemContainer.prototype.createElement=function(ak,am,ai,aj,an){this._offsets=am;var ah=ai||"jqplot";var al=document.createElement(ak);this._elem=L(al);this._elem.addClass(ah);this._elem.css(aj);this._elem.attr(an);al=null;return this._elem};L.jqplot.ElemContainer.prototype.getWidth=function(){if(this._elem){return this._elem.outerWidth(true)}else{return null}};L.jqplot.ElemContainer.prototype.getHeight=function(){if(this._elem){return this._elem.outerHeight(true)}else{return null}};L.jqplot.ElemContainer.prototype.getPosition=function(){if(this._elem){return this._elem.position()}else{return{top:null,left:null,bottom:null,right:null}}};L.jqplot.ElemContainer.prototype.getTop=function(){return this.getPosition().top};L.jqplot.ElemContainer.prototype.getLeft=function(){return this.getPosition().left};L.jqplot.ElemContainer.prototype.getBottom=function(){return this._elem.css("bottom")};L.jqplot.ElemContainer.prototype.getRight=function(){return this._elem.css("right")};function w(ah){L.jqplot.ElemContainer.call(this);this.name=ah;this._series=[];this.show=false;this.tickRenderer=L.jqplot.AxisTickRenderer;this.tickOptions={};this.labelRenderer=L.jqplot.AxisLabelRenderer;this.labelOptions={};this.label=null;this.showLabel=true;this.min=null;this.max=null;this.autoscale=false;this.pad=1.2;this.padMax=null;this.padMin=null;this.ticks=[];this.numberTicks;this.tickInterval;this.renderer=L.jqplot.LinearAxisRenderer;this.rendererOptions={};this.showTicks=true;this.showTickMarks=true;this.showMinorTicks=true;this.drawMajorGridlines=true;this.drawMinorGridlines=false;this.drawMajorTickMarks=true;this.drawMinorTickMarks=true;this.useSeriesColor=false;this.borderWidth=null;this.borderColor=null;this.scaleToHiddenSeries=false;this._dataBounds={min:null,max:null};this._intervalStats=[];this._offsets={min:null,max:null};this._ticks=[];this._label=null;this.syncTicks=null;this.tickSpacing=75;this._min=null;this._max=null;this._tickInterval=null;this._numberTicks=null;this.__ticks=null;this._options={}}w.prototype=new L.jqplot.ElemContainer();w.prototype.constructor=w;w.prototype.init=function(){if(L.isFunction(this.renderer)){this.renderer=new this.renderer()}this.tickOptions.axis=this.name;if(this.tickOptions.showMark==null){this.tickOptions.showMark=this.showTicks}if(this.tickOptions.showMark==null){this.tickOptions.showMark=this.showTickMarks}if(this.tickOptions.showLabel==null){this.tickOptions.showLabel=this.showTicks}if(this.label==null||this.label==""){this.showLabel=false}else{this.labelOptions.label=this.label}if(this.showLabel==false){this.labelOptions.show=false}if(this.pad==0){this.pad=1}if(this.padMax==0){this.padMax=1}if(this.padMin==0){this.padMin=1}if(this.padMax==null){this.padMax=(this.pad-1)/2+1}if(this.padMin==null){this.padMin=(this.pad-1)/2+1}this.pad=this.padMax+this.padMin-1;if(this.min!=null||this.max!=null){this.autoscale=false}if(this.syncTicks==null&&this.name.indexOf("y")>-1){this.syncTicks=true}else{if(this.syncTicks==null){this.syncTicks=false}}this.renderer.init.call(this,this.rendererOptions)};w.prototype.draw=function(ah,ai){if(this.__ticks){this.__ticks=null}return this.renderer.draw.call(this,ah,ai)};w.prototype.set=function(){this.renderer.set.call(this)};w.prototype.pack=function(ai,ah){if(this.show){this.renderer.pack.call(this,ai,ah)}if(this._min==null){this._min=this.min;this._max=this.max;this._tickInterval=this.tickInterval;this._numberTicks=this.numberTicks;this.__ticks=this._ticks}};w.prototype.reset=function(){this.renderer.reset.call(this)};w.prototype.resetScale=function(ah){L.extend(true,this,{min:null,max:null,numberTicks:null,tickInterval:null,_ticks:[],ticks:[]},ah);this.resetDataBounds()};w.prototype.resetDataBounds=function(){var ao=this._dataBounds;ao.min=null;ao.max=null;var ai,ap,am;var aj=(this.show)?true:false;for(var al=0;al<this._series.length;al++){ap=this._series[al];if(ap.show||this.scaleToHiddenSeries){am=ap._plotData;if(ap._type==="line"&&ap.renderer.bands.show&&this.name.charAt(0)!=="x"){am=[[0,ap.renderer.bands._min],[1,ap.renderer.bands._max]]}var ah=1,an=1;if(ap._type!=null&&ap._type=="ohlc"){ah=3;an=2}for(var ak=0,ai=am.length;ak<ai;ak++){if(this.name=="xaxis"||this.name=="x2axis"){if((am[ak][0]!=null&&am[ak][0]<ao.min)||ao.min==null){ao.min=am[ak][0]}if((am[ak][0]!=null&&am[ak][0]>ao.max)||ao.max==null){ao.max=am[ak][0]}}else{if((am[ak][ah]!=null&&am[ak][ah]<ao.min)||ao.min==null){ao.min=am[ak][ah]}if((am[ak][an]!=null&&am[ak][an]>ao.max)||ao.max==null){ao.max=am[ak][an]}}}if(aj&&ap.renderer.constructor!==L.jqplot.BarRenderer){aj=false}else{if(aj&&this._options.hasOwnProperty("forceTickAt0")&&this._options.forceTickAt0==false){aj=false}else{if(aj&&ap.renderer.constructor===L.jqplot.BarRenderer){if(ap.barDirection=="vertical"&&this.name!="xaxis"&&this.name!="x2axis"){if(this._options.pad!=null||this._options.padMin!=null){aj=false}}else{if(ap.barDirection=="horizontal"&&(this.name=="xaxis"||this.name=="x2axis")){if(this._options.pad!=null||this._options.padMin!=null){aj=false}}}}}}}}if(aj&&this.renderer.constructor===L.jqplot.LinearAxisRenderer&&ao.min>=0){this.padMin=1;this.forceTickAt0=true}};function q(ah){L.jqplot.ElemContainer.call(this);this.show=false;this.location="ne";this.labels=[];this.showLabels=true;this.showSwatches=true;this.placement="insideGrid";this.xoffset=0;this.yoffset=0;this.border;this.background;this.textColor;this.fontFamily;this.fontSize;this.rowSpacing="0.5em";this.renderer=L.jqplot.TableLegendRenderer;this.rendererOptions={};this.preDraw=false;this.marginTop=null;this.marginRight=null;this.marginBottom=null;this.marginLeft=null;this.escapeHtml=false;this._series=[];L.extend(true,this,ah)}q.prototype=new L.jqplot.ElemContainer();q.prototype.constructor=q;q.prototype.setOptions=function(ah){L.extend(true,this,ah);if(this.placement=="inside"){this.placement="insideGrid"}if(this.xoffset>0){if(this.placement=="insideGrid"){switch(this.location){case"nw":case"w":case"sw":if(this.marginLeft==null){this.marginLeft=this.xoffset+"px"}this.marginRight="0px";break;case"ne":case"e":case"se":default:if(this.marginRight==null){this.marginRight=this.xoffset+"px"}this.marginLeft="0px";break}}else{if(this.placement=="outside"){switch(this.location){case"nw":case"w":case"sw":if(this.marginRight==null){this.marginRight=this.xoffset+"px"}this.marginLeft="0px";break;case"ne":case"e":case"se":default:if(this.marginLeft==null){this.marginLeft=this.xoffset+"px"}this.marginRight="0px";break}}}this.xoffset=0}if(this.yoffset>0){if(this.placement=="outside"){switch(this.location){case"sw":case"s":case"se":if(this.marginTop==null){this.marginTop=this.yoffset+"px"}this.marginBottom="0px";break;case"ne":case"n":case"nw":default:if(this.marginBottom==null){this.marginBottom=this.yoffset+"px"}this.marginTop="0px";break}}else{if(this.placement=="insideGrid"){switch(this.location){case"sw":case"s":case"se":if(this.marginBottom==null){this.marginBottom=this.yoffset+"px"}this.marginTop="0px";break;case"ne":case"n":case"nw":default:if(this.marginTop==null){this.marginTop=this.yoffset+"px"}this.marginBottom="0px";break}}}this.yoffset=0}};q.prototype.init=function(){if(L.isFunction(this.renderer)){this.renderer=new this.renderer()}this.renderer.init.call(this,this.rendererOptions)};q.prototype.draw=function(ai,aj){for(var ah=0;ah<L.jqplot.preDrawLegendHooks.length;ah++){L.jqplot.preDrawLegendHooks[ah].call(this,ai)}return this.renderer.draw.call(this,ai,aj)};q.prototype.pack=function(ah){this.renderer.pack.call(this,ah)};function y(ah){L.jqplot.ElemContainer.call(this);this.text=ah;this.show=true;this.fontFamily;this.fontSize;this.textAlign;this.textColor;this.renderer=L.jqplot.DivTitleRenderer;this.rendererOptions={};this.escapeHtml=false}y.prototype=new L.jqplot.ElemContainer();y.prototype.constructor=y;y.prototype.init=function(){if(L.isFunction(this.renderer)){this.renderer=new this.renderer()}this.renderer.init.call(this,this.rendererOptions)};y.prototype.draw=function(ah){return this.renderer.draw.call(this,ah)};y.prototype.pack=function(){this.renderer.pack.call(this)};function S(ah){ah=ah||{};L.jqplot.ElemContainer.call(this);this.show=true;this.xaxis="xaxis";this._xaxis;this.yaxis="yaxis";this._yaxis;this.gridBorderWidth=2;this.renderer=L.jqplot.LineRenderer;this.rendererOptions={};this.data=[];this.gridData=[];this.label="";this.showLabel=true;this.color;this.negativeColor;this.lineWidth=2.5;this.lineJoin="round";this.lineCap="round";this.linePattern="solid";this.shadow=true;this.shadowAngle=45;this.shadowOffset=1.25;this.shadowDepth=3;this.shadowAlpha="0.1";this.breakOnNull=false;this.markerRenderer=L.jqplot.MarkerRenderer;this.markerOptions={};this.showLine=true;this.showMarker=true;this.index;this.fill=false;this.fillColor;this.fillAlpha;this.fillAndStroke=false;this.disableStack=false;this._stack=false;this.neighborThreshold=4;this.fillToZero=false;this.fillToValue=0;this.fillAxis="y";this.useNegativeColors=true;this._stackData=[];this._plotData=[];this._plotValues={x:[],y:[]};this._intervals={x:{},y:{}};this._prevPlotData=[];this._prevGridData=[];this._stackAxis="y";this._primaryAxis="_xaxis";this.canvas=new L.jqplot.GenericCanvas();this.shadowCanvas=new L.jqplot.GenericCanvas();this.plugins={};this._sumy=0;this._sumx=0;this._type=""}S.prototype=new L.jqplot.ElemContainer();S.prototype.constructor=S;S.prototype.init=function(ak,ao,am){this.index=ak;this.gridBorderWidth=ao;var an=this.data;var aj=[],al,ah;for(al=0,ah=an.length;al<ah;al++){if(!this.breakOnNull){if(an[al]==null||an[al][0]==null||an[al][1]==null){continue}else{aj.push(an[al])}}else{aj.push(an[al])}}this.data=aj;if(!this.color){this.color=am.colorGenerator.get(this.index)}if(!this.negativeColor){this.negativeColor=am.negativeColorGenerator.get(this.index)}if(!this.fillColor){this.fillColor=this.color}if(this.fillAlpha){var ai=L.jqplot.normalize2rgb(this.fillColor);var ai=L.jqplot.getColorComponents(ai);this.fillColor="rgba("+ai[0]+","+ai[1]+","+ai[2]+","+this.fillAlpha+")"}if(L.isFunction(this.renderer)){this.renderer=new this.renderer()}this.renderer.init.call(this,this.rendererOptions,am);this.markerRenderer=new this.markerRenderer();if(!this.markerOptions.color){this.markerOptions.color=this.color}if(this.markerOptions.show==null){this.markerOptions.show=this.showMarker}this.showMarker=this.markerOptions.show;this.markerRenderer.init(this.markerOptions)};S.prototype.draw=function(an,ak,am){var ai=(ak==u)?{}:ak;an=(an==u)?this.canvas._ctx:an;var ah,al,aj;for(ah=0;ah<L.jqplot.preDrawSeriesHooks.length;ah++){L.jqplot.preDrawSeriesHooks[ah].call(this,an,ai)}if(this.show){this.renderer.setGridData.call(this,am);if(!ai.preventJqPlotSeriesDrawTrigger){L(an.canvas).trigger("jqplotSeriesDraw",[this.data,this.gridData])}al=[];if(ai.data){al=ai.data}else{if(!this._stack){al=this.data}else{al=this._plotData}}aj=ai.gridData||this.renderer.makeGridData.call(this,al,am);if(this._type==="line"&&this.renderer.smooth&&this.renderer._smoothedData.length){aj=this.renderer._smoothedData}this.renderer.draw.call(this,an,aj,ai,am)}for(ah=0;ah<L.jqplot.postDrawSeriesHooks.length;ah++){L.jqplot.postDrawSeriesHooks[ah].call(this,an,ai,am)}an=ak=am=ah=al=aj=null};S.prototype.drawShadow=function(an,ak,am){var ai=(ak==u)?{}:ak;an=(an==u)?this.shadowCanvas._ctx:an;var ah,al,aj;for(ah=0;ah<L.jqplot.preDrawSeriesShadowHooks.length;ah++){L.jqplot.preDrawSeriesShadowHooks[ah].call(this,an,ai)}if(this.shadow){this.renderer.setGridData.call(this,am);al=[];if(ai.data){al=ai.data}else{if(!this._stack){al=this.data}else{al=this._plotData}}aj=ai.gridData||this.renderer.makeGridData.call(this,al,am);this.renderer.drawShadow.call(this,an,aj,ai,am)}for(ah=0;ah<L.jqplot.postDrawSeriesShadowHooks.length;ah++){L.jqplot.postDrawSeriesShadowHooks[ah].call(this,an,ai)}an=ak=am=ah=al=aj=null};S.prototype.toggleDisplay=function(ai,ak){var ah,aj;if(ai.data.series){ah=ai.data.series}else{ah=this}if(ai.data.speed){aj=ai.data.speed}if(aj){if(ah.canvas._elem.is(":hidden")||!ah.show){ah.show=true;ah.canvas._elem.removeClass("jqplot-series-hidden");if(ah.shadowCanvas._elem){ah.shadowCanvas._elem.fadeIn(aj)}ah.canvas._elem.fadeIn(aj,ak);ah.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+ah.index).fadeIn(aj)}else{ah.show=false;ah.canvas._elem.addClass("jqplot-series-hidden");if(ah.shadowCanvas._elem){ah.shadowCanvas._elem.fadeOut(aj)}ah.canvas._elem.fadeOut(aj,ak);ah.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+ah.index).fadeOut(aj)}}else{if(ah.canvas._elem.is(":hidden")||!ah.show){ah.show=true;ah.canvas._elem.removeClass("jqplot-series-hidden");if(ah.shadowCanvas._elem){ah.shadowCanvas._elem.show()}ah.canvas._elem.show(0,ak);ah.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+ah.index).show()}else{ah.show=false;ah.canvas._elem.addClass("jqplot-series-hidden");if(ah.shadowCanvas._elem){ah.shadowCanvas._elem.hide()}ah.canvas._elem.hide(0,ak);ah.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+ah.index).hide()}}};function M(){L.jqplot.ElemContainer.call(this);this.drawGridlines=true;this.gridLineColor="#cccccc";this.gridLineWidth=1;this.background="#fffdf6";this.borderColor="#999999";this.borderWidth=2;this.drawBorder=true;this.shadow=true;this.shadowAngle=45;this.shadowOffset=1.5;this.shadowWidth=3;this.shadowDepth=3;this.shadowColor=null;this.shadowAlpha="0.07";this._left;this._top;this._right;this._bottom;this._width;this._height;this._axes=[];this.renderer=L.jqplot.CanvasGridRenderer;this.rendererOptions={};this._offsets={top:null,bottom:null,left:null,right:null}}M.prototype=new L.jqplot.ElemContainer();M.prototype.constructor=M;M.prototype.init=function(){if(L.isFunction(this.renderer)){this.renderer=new this.renderer()}this.renderer.init.call(this,this.rendererOptions)};M.prototype.createElement=function(ah,ai){this._offsets=ah;return this.renderer.createElement.call(this,ai)};M.prototype.draw=function(){this.renderer.draw.call(this)};L.jqplot.GenericCanvas=function(){L.jqplot.ElemContainer.call(this);this._ctx};L.jqplot.GenericCanvas.prototype=new L.jqplot.ElemContainer();L.jqplot.GenericCanvas.prototype.constructor=L.jqplot.GenericCanvas;L.jqplot.GenericCanvas.prototype.createElement=function(al,aj,ai,am){this._offsets=al;var ah="jqplot";if(aj!=u){ah=aj}var ak;ak=am.canvasManager.getCanvas();if(ai!=null){this._plotDimensions=ai}ak.width=this._plotDimensions.width-this._offsets.left-this._offsets.right;ak.height=this._plotDimensions.height-this._offsets.top-this._offsets.bottom;this._elem=L(ak);this._elem.css({position:"absolute",left:this._offsets.left,top:this._offsets.top});this._elem.addClass(ah);ak=am.canvasManager.initCanvas(ak);ak=null;return this._elem};L.jqplot.GenericCanvas.prototype.setContext=function(){this._ctx=this._elem.get(0).getContext("2d");return this._ctx};L.jqplot.GenericCanvas.prototype.resetCanvas=function(){if(this._elem){if(L.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==u){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce()}this._ctx=null};L.jqplot.HooksManager=function(){this.hooks=[];this.args=[]};L.jqplot.HooksManager.prototype.addOnce=function(ak,ai){ai=ai||[];var al=false;for(var aj=0,ah=this.hooks.length;aj<ah;aj++){if(this.hooks[aj]==ak){al=true}}if(!al){this.hooks.push(ak);this.args.push(ai)}};L.jqplot.HooksManager.prototype.add=function(ai,ah){ah=ah||[];this.hooks.push(ai);this.args.push(ah)};L.jqplot.EventListenerManager=function(){this.hooks=[]};L.jqplot.EventListenerManager.prototype.addOnce=function(al,ak){var am=false,aj,ai;for(var ai=0,ah=this.hooks.length;ai<ah;ai++){aj=this.hooks[ai];if(aj[0]==al&&aj[1]==ak){am=true}}if(!am){this.hooks.push([al,ak])}};L.jqplot.EventListenerManager.prototype.add=function(ai,ah){this.hooks.push([ai,ah])};var U=["yMidAxis","xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis"];function R(){this.animate=false;this.animateReplot=false;this.axes={xaxis:new w("xaxis"),yaxis:new w("yaxis"),x2axis:new w("x2axis"),y2axis:new w("y2axis"),y3axis:new w("y3axis"),y4axis:new w("y4axis"),y5axis:new w("y5axis"),y6axis:new w("y6axis"),y7axis:new w("y7axis"),y8axis:new w("y8axis"),y9axis:new w("y9axis"),yMidAxis:new w("yMidAxis")};this.baseCanvas=new L.jqplot.GenericCanvas();this.captureRightClick=false;this.data=[];this.dataRenderer;this.dataRendererOptions;this.defaults={axesDefaults:{},axes:{xaxis:{},yaxis:{},x2axis:{},y2axis:{},y3axis:{},y4axis:{},y5axis:{},y6axis:{},y7axis:{},y8axis:{},y9axis:{},yMidAxis:{}},seriesDefaults:{},series:[]};this.defaultAxisStart=1;this.drawIfHidden=false;this.eventCanvas=new L.jqplot.GenericCanvas();this.fillBetween={series1:null,series2:null,color:null,baseSeries:0,fill:true};this.fontFamily;this.fontSize;this.grid=new M();this.legend=new q();this.noDataIndicator={show:false,indicator:"Loading Data...",axes:{xaxis:{min:0,max:10,tickInterval:2,show:true},yaxis:{min:0,max:12,tickInterval:3,show:true}}};this.negativeSeriesColors=L.jqplot.config.defaultNegativeColors;this.options={};this.previousSeriesStack=[];this.plugins={};this.series=[];this.seriesStack=[];this.seriesColors=L.jqplot.config.defaultColors;this.sortData=true;this.stackSeries=false;this.syncXTicks=true;this.syncYTicks=true;this.target=null;this.targetId=null;this.textColor;this.title=new y();this._drawCount=0;this._sumy=0;this._sumx=0;this._stackData=[];this._plotData=[];this._width=null;this._height=null;this._plotDimensions={height:null,width:null};this._gridPadding={top:null,right:null,bottom:null,left:null};this._defaultGridPadding={top:10,right:10,bottom:23,left:10};this._addDomReference=L.jqplot.config.addDomReference;this.preInitHooks=new L.jqplot.HooksManager();this.postInitHooks=new L.jqplot.HooksManager();this.preParseOptionsHooks=new L.jqplot.HooksManager();this.postParseOptionsHooks=new L.jqplot.HooksManager();this.preDrawHooks=new L.jqplot.HooksManager();this.postDrawHooks=new L.jqplot.HooksManager();this.preDrawSeriesHooks=new L.jqplot.HooksManager();this.postDrawSeriesHooks=new L.jqplot.HooksManager();this.preDrawLegendHooks=new L.jqplot.HooksManager();this.addLegendRowHooks=new L.jqplot.HooksManager();this.preSeriesInitHooks=new L.jqplot.HooksManager();this.postSeriesInitHooks=new L.jqplot.HooksManager();this.preParseSeriesOptionsHooks=new L.jqplot.HooksManager();this.postParseSeriesOptionsHooks=new L.jqplot.HooksManager();this.eventListenerHooks=new L.jqplot.EventListenerManager();this.preDrawSeriesShadowHooks=new L.jqplot.HooksManager();this.postDrawSeriesShadowHooks=new L.jqplot.HooksManager();this.colorGenerator=new L.jqplot.ColorGenerator();this.negativeColorGenerator=new L.jqplot.ColorGenerator();this.canvasManager=new L.jqplot.CanvasManager();this.themeEngine=new L.jqplot.ThemeEngine();var aj=0;this.init=function(av,ar,ay){ay=ay||{};for(var at=0;at<L.jqplot.preInitHooks.length;at++){L.jqplot.preInitHooks[at].call(this,av,ar,ay)}for(var at=0;at<this.preInitHooks.hooks.length;at++){this.preInitHooks.hooks[at].call(this,av,ar,ay)}this.targetId="#"+av;this.target=L("#"+av);if(this._addDomReference){this.target.data("jqplot",this)}this.target.removeClass("jqplot-error");if(!this.target.get(0)){throw new Error("No plot target specified")}if(this.target.css("position")=="static"){this.target.css("position","relative")}if(!this.target.hasClass("jqplot-target")){this.target.addClass("jqplot-target")}if(!this.target.height()){var au;if(ay&&ay.height){au=parseInt(ay.height,10)}else{if(this.target.attr("data-height")){au=parseInt(this.target.attr("data-height"),10)}else{au=parseInt(L.jqplot.config.defaultHeight,10)}}this._height=au;this.target.css("height",au+"px")}else{this._height=au=this.target.height()}if(!this.target.width()){var aw;if(ay&&ay.width){aw=parseInt(ay.width,10)}else{if(this.target.attr("data-width")){aw=parseInt(this.target.attr("data-width"),10)}else{aw=parseInt(L.jqplot.config.defaultWidth,10)}}this._width=aw;this.target.css("width",aw+"px")}else{this._width=aw=this.target.width()}for(var at=0,ap=U.length;at<ap;at++){this.axes[U[at]]=new w(U[at])}this._plotDimensions.height=this._height;this._plotDimensions.width=this._width;this.grid._plotDimensions=this._plotDimensions;this.title._plotDimensions=this._plotDimensions;this.baseCanvas._plotDimensions=this._plotDimensions;this.eventCanvas._plotDimensions=this._plotDimensions;this.legend._plotDimensions=this._plotDimensions;if(this._height<=0||this._width<=0||!this._height||!this._width){throw new Error("Canvas dimension not set")}if(ay.dataRenderer&&L.isFunction(ay.dataRenderer)){if(ay.dataRendererOptions){this.dataRendererOptions=ay.dataRendererOptions}this.dataRenderer=ay.dataRenderer;ar=this.dataRenderer(ar,this,this.dataRendererOptions)}if(ay.noDataIndicator&&L.isPlainObject(ay.noDataIndicator)){L.extend(true,this.noDataIndicator,ay.noDataIndicator)}if(ar==null||L.isArray(ar)==false||ar.length==0||L.isArray(ar[0])==false||ar[0].length==0){if(this.noDataIndicator.show==false){throw new Error("No data specified")}else{for(var al in this.noDataIndicator.axes){for(var an in this.noDataIndicator.axes[al]){this.axes[al][an]=this.noDataIndicator.axes[al][an]}}this.postDrawHooks.add(function(){var aD=this.eventCanvas.getHeight();var aA=this.eventCanvas.getWidth();var az=L('<div class="jqplot-noData-container" style="position:absolute;"></div>');this.target.append(az);az.height(aD);az.width(aA);az.css("top",this.eventCanvas._offsets.top);az.css("left",this.eventCanvas._offsets.left);var aC=L('<div class="jqplot-noData-contents" style="text-align:center; position:relative; margin-left:auto; margin-right:auto;"></div>');az.append(aC);aC.html(this.noDataIndicator.indicator);var aB=aC.height();var ax=aC.width();aC.height(aB);aC.width(ax);aC.css("top",(aD-aB)/2+"px")})}}this.data=L.extend(true,[],ar);this.parseOptions(ay);if(this.textColor){this.target.css("color",this.textColor)}if(this.fontFamily){this.target.css("font-family",this.fontFamily)}if(this.fontSize){this.target.css("font-size",this.fontSize)}this.title.init();this.legend.init();this._sumy=0;this._sumx=0;this.computePlotData();for(var at=0;at<this.series.length;at++){this.seriesStack.push(at);this.previousSeriesStack.push(at);this.series[at].shadowCanvas._plotDimensions=this._plotDimensions;this.series[at].canvas._plotDimensions=this._plotDimensions;for(var aq=0;aq<L.jqplot.preSeriesInitHooks.length;aq++){L.jqplot.preSeriesInitHooks[aq].call(this.series[at],av,this.data,this.options.seriesDefaults,this.options.series[at],this)}for(var aq=0;aq<this.preSeriesInitHooks.hooks.length;aq++){this.preSeriesInitHooks.hooks[aq].call(this.series[at],av,this.data,this.options.seriesDefaults,this.options.series[at],this)}this.series[at]._plotDimensions=this._plotDimensions;this.series[at].init(at,this.grid.borderWidth,this);for(var aq=0;aq<L.jqplot.postSeriesInitHooks.length;aq++){L.jqplot.postSeriesInitHooks[aq].call(this.series[at],av,this.data,this.options.seriesDefaults,this.options.series[at],this)}for(var aq=0;aq<this.postSeriesInitHooks.hooks.length;aq++){this.postSeriesInitHooks.hooks[aq].call(this.series[at],av,this.data,this.options.seriesDefaults,this.options.series[at],this)}this._sumy+=this.series[at]._sumy;this._sumx+=this.series[at]._sumx}var am,ao;for(var at=0,ap=U.length;at<ap;at++){am=U[at];ao=this.axes[am];ao._plotDimensions=this._plotDimensions;ao.init();if(this.axes[am].borderColor==null){if(am.charAt(0)!=="x"&&ao.useSeriesColor===true&&ao.show){ao.borderColor=ao._series[0].color}else{ao.borderColor=this.grid.borderColor}}}if(this.sortData){ah(this.series)}this.grid.init();this.grid._axes=this.axes;this.legend._series=this.series;for(var at=0;at<L.jqplot.postInitHooks.length;at++){L.jqplot.postInitHooks[at].call(this,av,this.data,ay)}for(var at=0;at<this.postInitHooks.hooks.length;at++){this.postInitHooks.hooks[at].call(this,av,this.data,ay)}};this.resetAxesScale=function(aq,am){var ao=am||{};var ap=aq||this.axes;if(ap===true){ap=this.axes}if(L.isArray(ap)){for(var an=0;an<ap.length;an++){this.axes[ap[an]].resetScale(ao[ap[an]])}}else{if(typeof(ap)==="object"){for(var al in ap){this.axes[al].resetScale(ao[al])}}}};this.reInitialize=function(au,al){var ay=L.extend(true,{},this.options,al);var aw=this.targetId.substr(1);var ar=(au==null)?this.data:au;for(var av=0;av<L.jqplot.preInitHooks.length;av++){L.jqplot.preInitHooks[av].call(this,aw,ar,ay)}for(var av=0;av<this.preInitHooks.hooks.length;av++){this.preInitHooks.hooks[av].call(this,aw,ar,ay)}this._height=this.target.height();this._width=this.target.width();if(this._height<=0||this._width<=0||!this._height||!this._width){throw new Error("Target dimension not set")}this._plotDimensions.height=this._height;this._plotDimensions.width=this._width;this.grid._plotDimensions=this._plotDimensions;this.title._plotDimensions=this._plotDimensions;this.baseCanvas._plotDimensions=this._plotDimensions;this.eventCanvas._plotDimensions=this._plotDimensions;this.legend._plotDimensions=this._plotDimensions;var am,ax,at,ao;for(var av=0,aq=U.length;av<aq;av++){am=U[av];ao=this.axes[am];ax=ao._ticks;for(var at=0,ap=ax.length;at<ap;at++){var an=ax[at]._elem;if(an){if(L.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==u){window.G_vmlCanvasManager.uninitElement(an.get(0))}an.emptyForce();an=null;ax._elem=null}}ax=null;delete ao.ticks;delete ao._ticks;this.axes[am]=new w(am);this.axes[am]._plotWidth=this._width;this.axes[am]._plotHeight=this._height}if(au){if(ay.dataRenderer&&L.isFunction(ay.dataRenderer)){if(ay.dataRendererOptions){this.dataRendererOptions=ay.dataRendererOptions}this.dataRenderer=ay.dataRenderer;au=this.dataRenderer(au,this,this.dataRendererOptions)}this.data=L.extend(true,[],au)}if(al){this.parseOptions(ay)}this.title._plotWidth=this._width;if(this.textColor){this.target.css("color",this.textColor)}if(this.fontFamily){this.target.css("font-family",this.fontFamily)}if(this.fontSize){this.target.css("font-size",this.fontSize)}this.title.init();this.legend.init();this._sumy=0;this._sumx=0;this.seriesStack=[];this.previousSeriesStack=[];this.computePlotData();for(var av=0,aq=this.series.length;av<aq;av++){this.seriesStack.push(av);this.previousSeriesStack.push(av);this.series[av].shadowCanvas._plotDimensions=this._plotDimensions;this.series[av].canvas._plotDimensions=this._plotDimensions;for(var at=0;at<L.jqplot.preSeriesInitHooks.length;at++){L.jqplot.preSeriesInitHooks[at].call(this.series[av],aw,this.data,this.options.seriesDefaults,this.options.series[av],this)}for(var at=0;at<this.preSeriesInitHooks.hooks.length;at++){this.preSeriesInitHooks.hooks[at].call(this.series[av],aw,this.data,this.options.seriesDefaults,this.options.series[av],this)}this.series[av]._plotDimensions=this._plotDimensions;this.series[av].init(av,this.grid.borderWidth,this);for(var at=0;at<L.jqplot.postSeriesInitHooks.length;at++){L.jqplot.postSeriesInitHooks[at].call(this.series[av],aw,this.data,this.options.seriesDefaults,this.options.series[av],this)}for(var at=0;at<this.postSeriesInitHooks.hooks.length;at++){this.postSeriesInitHooks.hooks[at].call(this.series[av],aw,this.data,this.options.seriesDefaults,this.options.series[av],this)}this._sumy+=this.series[av]._sumy;this._sumx+=this.series[av]._sumx}for(var av=0,aq=U.length;av<aq;av++){am=U[av];ao=this.axes[am];ao._plotDimensions=this._plotDimensions;ao.init();if(ao.borderColor==null){if(am.charAt(0)!=="x"&&ao.useSeriesColor===true&&ao.show){ao.borderColor=ao._series[0].color}else{ao.borderColor=this.grid.borderColor}}}if(this.sortData){ah(this.series)}this.grid.init();this.grid._axes=this.axes;this.legend._series=this.series;for(var av=0,aq=L.jqplot.postInitHooks.length;av<aq;av++){L.jqplot.postInitHooks[av].call(this,aw,this.data,ay)}for(var av=0,aq=this.postInitHooks.hooks.length;av<aq;av++){this.postInitHooks.hooks[av].call(this,aw,this.data,ay)}};this.quickInit=function(){this._height=this.target.height();this._width=this.target.width();if(this._height<=0||this._width<=0||!this._height||!this._width){throw new Error("Target dimension not set")}this._plotDimensions.height=this._height;this._plotDimensions.width=this._width;this.grid._plotDimensions=this._plotDimensions;this.title._plotDimensions=this._plotDimensions;this.baseCanvas._plotDimensions=this._plotDimensions;this.eventCanvas._plotDimensions=this._plotDimensions;this.legend._plotDimensions=this._plotDimensions;for(var aq in this.axes){this.axes[aq]._plotWidth=this._width;this.axes[aq]._plotHeight=this._height}this.title._plotWidth=this._width;if(this.textColor){this.target.css("color",this.textColor)}if(this.fontFamily){this.target.css("font-family",this.fontFamily)}if(this.fontSize){this.target.css("font-size",this.fontSize)}this._sumy=0;this._sumx=0;this.computePlotData();for(var ao=0;ao<this.series.length;ao++){if(this.series[ao]._type==="line"&&this.series[ao].renderer.bands.show){this.series[ao].renderer.initBands.call(this.series[ao],this.series[ao].renderer.options,this)}this.series[ao]._plotDimensions=this._plotDimensions;this.series[ao].canvas._plotDimensions=this._plotDimensions;this._sumy+=this.series[ao]._sumy;this._sumx+=this.series[ao]._sumx}var am;for(var al=0;al<12;al++){am=U[al];var an=this.axes[am]._ticks;for(var ao=0;ao<an.length;ao++){var ap=an[ao]._elem;if(ap){if(L.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==u){window.G_vmlCanvasManager.uninitElement(ap.get(0))}ap.emptyForce();ap=null;an._elem=null}}an=null;this.axes[am]._plotDimensions=this._plotDimensions;this.axes[am]._ticks=[]}if(this.sortData){ah(this.series)}this.grid._axes=this.axes;this.legend._series=this.series};function ah(ap){var au,av,aw,al,at;for(var aq=0;aq<ap.length;aq++){var am;var ar=[ap[aq].data,ap[aq]._stackData,ap[aq]._plotData,ap[aq]._prevPlotData];for(var an=0;an<4;an++){am=true;au=ar[an];if(ap[aq]._stackAxis=="x"){for(var ao=0;ao<au.length;ao++){if(typeof(au[ao][1])!="number"){am=false;break}}if(am){au.sort(function(ay,ax){return ay[1]-ax[1]})}}else{for(var ao=0;ao<au.length;ao++){if(typeof(au[ao][0])!="number"){am=false;break}}if(am){au.sort(function(ay,ax){return ay[0]-ax[0]})}}}}}this.computePlotData=function(){this._plotData=[];this._stackData=[];var at,au,ao;for(au=0,ao=this.series.length;au<ao;au++){at=this.series[au];this._plotData.push([]);this._stackData.push([]);var am=at.data;this._plotData[au]=L.extend(true,[],am);this._stackData[au]=L.extend(true,[],am);at._plotData=this._plotData[au];at._stackData=this._stackData[au];var ax={x:[],y:[]};if(this.stackSeries&&!at.disableStack){at._stack=true;var av=(at._stackAxis==="x")?0:1;for(var ap=0,al=am.length;ap<al;ap++){var aw=am[ap][av];if(aw==null){aw=0}this._plotData[au][ap][av]=aw;this._stackData[au][ap][av]=aw;if(au>0){for(var aq=au;aq--;){var an=this._plotData[aq][ap][av];if(aw*an>=0){this._plotData[au][ap][av]+=an;this._stackData[au][ap][av]+=an;break}}}}}else{for(var ar=0;ar<at.data.length;ar++){ax.x.push(at.data[ar][0]);ax.y.push(at.data[ar][1])}this._stackData.push(at.data);this.series[au]._stackData=at.data;this._plotData.push(at.data);at._plotData=at.data;at._plotValues=ax}if(au>0){at._prevPlotData=this.series[au-1]._plotData}at._sumy=0;at._sumx=0;for(ar=at.data.length-1;ar>-1;ar--){at._sumy+=at.data[ar][1];at._sumx+=at.data[ar][0]}}};this.populatePlotData=function(au,av){this._plotData=[];this._stackData=[];au._stackData=[];au._plotData=[];var ay={x:[],y:[]};if(this.stackSeries&&!au.disableStack){au._stack=true;var ax=(au._stackAxis==="x")?0:1;var az=L.extend(true,[],au.data);var aA=L.extend(true,[],au.data);var an,am,ao,aw,al;for(var ar=0;ar<av;ar++){var ap=this.series[ar].data;for(var aq=0;aq<ap.length;aq++){ao=ap[aq];an=(ao[0]!=null)?ao[0]:0;am=(ao[1]!=null)?ao[1]:0;az[aq][0]+=an;az[aq][1]+=am;aw=(ax)?am:an;if(au.data[aq][ax]*aw>=0){aA[aq][ax]+=aw}}}for(var at=0;at<aA.length;at++){ay.x.push(aA[at][0]);ay.y.push(aA[at][1])}this._plotData.push(aA);this._stackData.push(az);au._stackData=az;au._plotData=aA;au._plotValues=ay}else{for(var at=0;at<au.data.length;at++){ay.x.push(au.data[at][0]);ay.y.push(au.data[at][1])}this._stackData.push(au.data);this.series[av]._stackData=au.data;this._plotData.push(au.data);au._plotData=au.data;au._plotValues=ay}if(av>0){au._prevPlotData=this.series[av-1]._plotData}au._sumy=0;au._sumx=0;for(at=au.data.length-1;at>-1;at--){au._sumy+=au.data[at][1];au._sumx+=au.data[at][0]}};this.getNextSeriesColor=(function(am){var al=0;var an=am.seriesColors;return function(){if(al<an.length){return an[al++]}else{al=0;return an[al++]}}})(this);this.parseOptions=function(ay){for(var at=0;at<this.preParseOptionsHooks.hooks.length;at++){this.preParseOptionsHooks.hooks[at].call(this,ay)}for(var at=0;at<L.jqplot.preParseOptionsHooks.length;at++){L.jqplot.preParseOptionsHooks[at].call(this,ay)}this.options=L.extend(true,{},this.defaults,ay);var am=this.options;this.animate=am.animate;this.animateReplot=am.animateReplot;this.stackSeries=am.stackSeries;if(L.isPlainObject(am.fillBetween)){var ax=["series1","series2","color","baseSeries","fill"],au;for(var at=0,aq=ax.length;at<aq;at++){au=ax[at];if(am.fillBetween[au]!=null){this.fillBetween[au]=am.fillBetween[au]}}}if(am.seriesColors){this.seriesColors=am.seriesColors}if(am.negativeSeriesColors){this.negativeSeriesColors=am.negativeSeriesColors}if(am.captureRightClick){this.captureRightClick=am.captureRightClick}this.defaultAxisStart=(ay&&ay.defaultAxisStart!=null)?ay.defaultAxisStart:this.defaultAxisStart;this.colorGenerator.setColors(this.seriesColors);this.negativeColorGenerator.setColors(this.negativeSeriesColors);L.extend(true,this._gridPadding,am.gridPadding);this.sortData=(am.sortData!=null)?am.sortData:this.sortData;for(var at=0;at<12;at++){var an=U[at];var ap=this.axes[an];ap._options=L.extend(true,{},am.axesDefaults,am.axes[an]);L.extend(true,ap,am.axesDefaults,am.axes[an]);ap._plotWidth=this._width;ap._plotHeight=this._height}var aw=function(aD,aB,aE){var aA=[];var aC,az;aB=aB||"vertical";if(!L.isArray(aD[0])){for(aC=0,az=aD.length;aC<az;aC++){if(aB=="vertical"){aA.push([aE+aC,aD[aC]])}else{aA.push([aD[aC],aE+aC])}}}else{L.extend(true,aA,aD)}return aA};var av=0;this.series=[];for(var at=0;at<this.data.length;at++){var al=L.extend(true,{index:at},{seriesColors:this.seriesColors,negativeSeriesColors:this.negativeSeriesColors},this.options.seriesDefaults,this.options.series[at],{rendererOptions:{animation:{show:this.animate}}});var ax=new S(al);for(var ar=0;ar<L.jqplot.preParseSeriesOptionsHooks.length;ar++){L.jqplot.preParseSeriesOptionsHooks[ar].call(ax,this.options.seriesDefaults,this.options.series[at])}for(var ar=0;ar<this.preParseSeriesOptionsHooks.hooks.length;ar++){this.preParseSeriesOptionsHooks.hooks[ar].call(ax,this.options.seriesDefaults,this.options.series[at])}L.extend(true,ax,al);var ao="vertical";if(ax.renderer===L.jqplot.BarRenderer&&ax.rendererOptions&&ax.rendererOptions.barDirection=="horizontal"){ao="horizontal";ax._stackAxis="x";ax._primaryAxis="_yaxis"}ax.data=aw(this.data[at],ao,this.defaultAxisStart);switch(ax.xaxis){case"xaxis":ax._xaxis=this.axes.xaxis;break;case"x2axis":ax._xaxis=this.axes.x2axis;break;default:break}ax._yaxis=this.axes[ax.yaxis];ax._xaxis._series.push(ax);ax._yaxis._series.push(ax);if(ax.show){ax._xaxis.show=true;ax._yaxis.show=true}else{if(ax._xaxis.scaleToHiddenSeries){ax._xaxis.show=true}if(ax._yaxis.scaleToHiddenSeries){ax._yaxis.show=true}}if(!ax.label){ax.label="Series "+(at+1).toString()}this.series.push(ax);for(var ar=0;ar<L.jqplot.postParseSeriesOptionsHooks.length;ar++){L.jqplot.postParseSeriesOptionsHooks[ar].call(this.series[at],this.options.seriesDefaults,this.options.series[at])}for(var ar=0;ar<this.postParseSeriesOptionsHooks.hooks.length;ar++){this.postParseSeriesOptionsHooks.hooks[ar].call(this.series[at],this.options.seriesDefaults,this.options.series[at])}}L.extend(true,this.grid,this.options.grid);for(var at=0,aq=U.length;at<aq;at++){var an=U[at];var ap=this.axes[an];if(ap.borderWidth==null){ap.borderWidth=this.grid.borderWidth}}if(typeof this.options.title=="string"){this.title.text=this.options.title}else{if(typeof this.options.title=="object"){L.extend(true,this.title,this.options.title)}}this.title._plotWidth=this._width;this.legend.setOptions(this.options.legend);for(var at=0;at<L.jqplot.postParseOptionsHooks.length;at++){L.jqplot.postParseOptionsHooks[at].call(this,ay)}for(var at=0;at<this.postParseOptionsHooks.hooks.length;at++){this.postParseOptionsHooks.hooks[at].call(this,ay)}};this.destroy=function(){this.canvasManager.freeAllCanvases();if(this.eventCanvas&&this.eventCanvas._elem){this.eventCanvas._elem.unbind()}this.target.empty();this.target[0].innerHTML=""};this.replot=function(am){var an=am||{};var ap=an.data||null;var al=(an.clear===false)?false:true;var ao=an.resetAxes||false;delete an.data;delete an.clear;delete an.resetAxes;this.target.trigger("jqplotPreReplot");if(al){this.destroy()}if(ap||!L.isEmptyObject(an)){this.reInitialize(ap,an)}else{this.quickInit()}if(ao){this.resetAxesScale(ao,an.axes)}this.draw();this.target.trigger("jqplotPostReplot")};this.redraw=function(al){al=(al!=null)?al:true;this.target.trigger("jqplotPreRedraw");if(al){this.canvasManager.freeAllCanvases();this.eventCanvas._elem.unbind();this.target.empty()}for(var an in this.axes){this.axes[an]._ticks=[]}this.computePlotData();this._sumy=0;this._sumx=0;for(var am=0,ao=this.series.length;am<ao;am++){this._sumy+=this.series[am]._sumy;this._sumx+=this.series[am]._sumx}this.draw();this.target.trigger("jqplotPostRedraw")};this.draw=function(){if(this.drawIfHidden||this.target.is(":visible")){this.target.trigger("jqplotPreDraw");var aH,aF,aE,ao;for(aH=0,aE=L.jqplot.preDrawHooks.length;aH<aE;aH++){L.jqplot.preDrawHooks[aH].call(this)}for(aH=0,aE=this.preDrawHooks.hooks.length;aH<aE;aH++){this.preDrawHooks.hooks[aH].apply(this,this.preDrawSeriesHooks.args[aH])}this.target.append(this.baseCanvas.createElement({left:0,right:0,top:0,bottom:0},"jqplot-base-canvas",null,this));this.baseCanvas.setContext();this.target.append(this.title.draw());this.title.pack({top:0,left:0});var aL=this.legend.draw({},this);var al={top:0,left:0,bottom:0,right:0};if(this.legend.placement=="outsideGrid"){this.target.append(aL);switch(this.legend.location){case"n":al.top+=this.legend.getHeight();break;case"s":al.bottom+=this.legend.getHeight();break;case"ne":case"e":case"se":al.right+=this.legend.getWidth();break;case"nw":case"w":case"sw":al.left+=this.legend.getWidth();break;default:al.right+=this.legend.getWidth();break}aL=aL.detach()}var ar=this.axes;var aM;for(aH=0;aH<12;aH++){aM=U[aH];this.target.append(ar[aM].draw(this.baseCanvas._ctx,this));ar[aM].set()}if(ar.yaxis.show){al.left+=ar.yaxis.getWidth()}var aG=["y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis"];var az=[0,0,0,0,0,0,0,0];var aC=0;var aB;for(aB=0;aB<8;aB++){if(ar[aG[aB]].show){aC+=ar[aG[aB]].getWidth();az[aB]=aC}}al.right+=aC;if(ar.x2axis.show){al.top+=ar.x2axis.getHeight()}if(this.title.show){al.top+=this.title.getHeight()}if(ar.xaxis.show){al.bottom+=ar.xaxis.getHeight()}if(this.options.gridDimensions&&L.isPlainObject(this.options.gridDimensions)){var at=parseInt(this.options.gridDimensions.width,10)||0;var aI=parseInt(this.options.gridDimensions.height,10)||0;var an=(this._width-al.left-al.right-at)/2;var aK=(this._height-al.top-al.bottom-aI)/2;if(aK>=0&&an>=0){al.top+=aK;al.bottom+=aK;al.left+=an;al.right+=an}}var am=["top","bottom","left","right"];for(var aB in am){if(this._gridPadding[am[aB]]==null&&al[am[aB]]>0){this._gridPadding[am[aB]]=al[am[aB]]}else{if(this._gridPadding[am[aB]]==null){this._gridPadding[am[aB]]=this._defaultGridPadding[am[aB]]}}}var aA=this._gridPadding;if(this.legend.placement==="outsideGrid"){aA={top:this.title.getHeight(),left:0,right:0,bottom:0};if(this.legend.location==="s"){aA.left=this._gridPadding.left;aA.right=this._gridPadding.right}}ar.xaxis.pack({position:"absolute",bottom:this._gridPadding.bottom-ar.xaxis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right});ar.yaxis.pack({position:"absolute",top:0,left:this._gridPadding.left-ar.yaxis.getWidth(),height:this._height},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top});ar.x2axis.pack({position:"absolute",top:this._gridPadding.top-ar.x2axis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right});for(aH=8;aH>0;aH--){ar[aG[aH-1]].pack({position:"absolute",top:0,right:this._gridPadding.right-az[aH-1]},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top})}var au=(this._width-this._gridPadding.left-this._gridPadding.right)/2+this._gridPadding.left-ar.yMidAxis.getWidth()/2;ar.yMidAxis.pack({position:"absolute",top:0,left:au,zIndex:9,textAlign:"center"},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top});this.target.append(this.grid.createElement(this._gridPadding,this));this.grid.draw();var aq=this.series;var aJ=aq.length;for(aH=0,aE=aJ;aH<aE;aH++){aF=this.seriesStack[aH];this.target.append(aq[aF].shadowCanvas.createElement(this._gridPadding,"jqplot-series-shadowCanvas",null,this));aq[aF].shadowCanvas.setContext();aq[aF].shadowCanvas._elem.data("seriesIndex",aF)}for(aH=0,aE=aJ;aH<aE;aH++){aF=this.seriesStack[aH];this.target.append(aq[aF].canvas.createElement(this._gridPadding,"jqplot-series-canvas",null,this));aq[aF].canvas.setContext();aq[aF].canvas._elem.data("seriesIndex",aF)}this.target.append(this.eventCanvas.createElement(this._gridPadding,"jqplot-event-canvas",null,this));this.eventCanvas.setContext();this.eventCanvas._ctx.fillStyle="rgba(0,0,0,0)";this.eventCanvas._ctx.fillRect(0,0,this.eventCanvas._ctx.canvas.width,this.eventCanvas._ctx.canvas.height);this.bindCustomEvents();if(this.legend.preDraw){this.eventCanvas._elem.before(aL);this.legend.pack(aA);if(this.legend._elem){this.drawSeries({legendInfo:{location:this.legend.location,placement:this.legend.placement,width:this.legend.getWidth(),height:this.legend.getHeight(),xoffset:this.legend.xoffset,yoffset:this.legend.yoffset}})}else{this.drawSeries()}}else{this.drawSeries();if(aJ){L(aq[aJ-1].canvas._elem).after(aL)}this.legend.pack(aA)}for(var aH=0,aE=L.jqplot.eventListenerHooks.length;aH<aE;aH++){this.eventCanvas._elem.bind(L.jqplot.eventListenerHooks[aH][0],{plot:this},L.jqplot.eventListenerHooks[aH][1])}for(var aH=0,aE=this.eventListenerHooks.hooks.length;aH<aE;aH++){this.eventCanvas._elem.bind(this.eventListenerHooks.hooks[aH][0],{plot:this},this.eventListenerHooks.hooks[aH][1])}var ay=this.fillBetween;if(ay.fill&&ay.series1!==ay.series2&&ay.series1<aJ&&ay.series2<aJ&&aq[ay.series1]._type==="line"&&aq[ay.series2]._type==="line"){this.doFillBetweenLines()}for(var aH=0,aE=L.jqplot.postDrawHooks.length;aH<aE;aH++){L.jqplot.postDrawHooks[aH].call(this)}for(var aH=0,aE=this.postDrawHooks.hooks.length;aH<aE;aH++){this.postDrawHooks.hooks[aH].apply(this,this.postDrawHooks.args[aH])}if(this.target.is(":visible")){this._drawCount+=1}var av,aw,aD,ap;for(aH=0,aE=aJ;aH<aE;aH++){av=aq[aH];aw=av.renderer;aD=".jqplot-point-label.jqplot-series-"+aH;if(aw.animation&&aw.animation._supported&&aw.animation.show&&(this._drawCount<2||this.animateReplot)){ap=this.target.find(aD);ap.stop(true,true).hide();av.canvas._elem.stop(true,true).hide();av.shadowCanvas._elem.stop(true,true).hide();av.canvas._elem.jqplotEffect("blind",{mode:"show",direction:aw.animation.direction},aw.animation.speed);av.shadowCanvas._elem.jqplotEffect("blind",{mode:"show",direction:aw.animation.direction},aw.animation.speed);ap.fadeIn(aw.animation.speed*0.8)}}ap=null;this.target.trigger("jqplotPostDraw",[this])}};R.prototype.doFillBetweenLines=function(){var an=this.fillBetween;var ax=an.series1;var av=an.series2;var aw=(ax<av)?ax:av;var au=(av>ax)?av:ax;var ar=this.series[aw];var aq=this.series[au];if(aq.renderer.smooth){var ap=aq.renderer._smoothedData.slice(0).reverse()}else{var ap=aq.gridData.slice(0).reverse()}if(ar.renderer.smooth){var at=ar.renderer._smoothedData.concat(ap)}else{var at=ar.gridData.concat(ap)}var ao=(an.color!==null)?an.color:this.series[ax].fillColor;var ay=(an.baseSeries!==null)?an.baseSeries:aw;var am=this.series[ay].renderer.shapeRenderer;var al={fillStyle:ao,fill:true,closePath:true};am.draw(ar.shadowCanvas._ctx,at,al)};this.bindCustomEvents=function(){this.eventCanvas._elem.bind("click",{plot:this},this.onClick);this.eventCanvas._elem.bind("dblclick",{plot:this},this.onDblClick);this.eventCanvas._elem.bind("mousedown",{plot:this},this.onMouseDown);this.eventCanvas._elem.bind("mousemove",{plot:this},this.onMouseMove);this.eventCanvas._elem.bind("mouseenter",{plot:this},this.onMouseEnter);this.eventCanvas._elem.bind("mouseleave",{plot:this},this.onMouseLeave);if(this.captureRightClick){this.eventCanvas._elem.bind("mouseup",{plot:this},this.onRightClick);this.eventCanvas._elem.get(0).oncontextmenu=function(){return false}}else{this.eventCanvas._elem.bind("mouseup",{plot:this},this.onMouseUp)}};function ai(av){var au=av.data.plot;var ap=au.eventCanvas._elem.offset();var at={x:av.pageX-ap.left,y:av.pageY-ap.top};var aq={xaxis:null,yaxis:null,x2axis:null,y2axis:null,y3axis:null,y4axis:null,y5axis:null,y6axis:null,y7axis:null,y8axis:null,y9axis:null,yMidAxis:null};var ar=["xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"];var al=au.axes;var am,ao;for(am=11;am>0;am--){ao=ar[am-1];if(al[ao].show){aq[ao]=al[ao].series_p2u(at[ao.charAt(0)])}}return{offsets:ap,gridPos:at,dataPos:aq}}function ak(al,am){var aq=am.series;var aW,aU,aT,aO,aP,aJ,aI,aw,au,az,aA,aK;var aS,aX,aQ,ar,aH,aM,aV;var an,aN;for(aT=am.seriesStack.length-1;aT>=0;aT--){aW=am.seriesStack[aT];aO=aq[aW];aV=aO._highlightThreshold;switch(aO.renderer.constructor){case L.jqplot.BarRenderer:aJ=al.x;aI=al.y;for(aU=0;aU<aO._barPoints.length;aU++){aH=aO._barPoints[aU];aQ=aO.gridData[aU];if(aJ>aH[0][0]&&aJ<aH[2][0]&&aI>aH[2][1]&&aI<aH[0][1]){return{seriesIndex:aO.index,pointIndex:aU,gridData:aQ,data:aO.data[aU],points:aO._barPoints[aU]}}}break;case L.jqplot.PyramidRenderer:aJ=al.x;aI=al.y;for(aU=0;aU<aO._barPoints.length;aU++){aH=aO._barPoints[aU];aQ=aO.gridData[aU];if(aJ>aH[0][0]+aV[0][0]&&aJ<aH[2][0]+aV[2][0]&&aI>aH[2][1]&&aI<aH[0][1]){return{seriesIndex:aO.index,pointIndex:aU,gridData:aQ,data:aO.data[aU],points:aO._barPoints[aU]}}}break;case L.jqplot.DonutRenderer:az=aO.startAngle/180*Math.PI;aJ=al.x-aO._center[0];aI=al.y-aO._center[1];aP=Math.sqrt(Math.pow(aJ,2)+Math.pow(aI,2));if(aJ>0&&-aI>=0){aw=2*Math.PI-Math.atan(-aI/aJ)}else{if(aJ>0&&-aI<0){aw=-Math.atan(-aI/aJ)}else{if(aJ<0){aw=Math.PI-Math.atan(-aI/aJ)}else{if(aJ==0&&-aI>0){aw=3*Math.PI/2}else{if(aJ==0&&-aI<0){aw=Math.PI/2}else{if(aJ==0&&aI==0){aw=0}}}}}}if(az){aw-=az;if(aw<0){aw+=2*Math.PI}else{if(aw>2*Math.PI){aw-=2*Math.PI}}}au=aO.sliceMargin/180*Math.PI;if(aP<aO._radius&&aP>aO._innerRadius){for(aU=0;aU<aO.gridData.length;aU++){aA=(aU>0)?aO.gridData[aU-1][1]+au:au;aK=aO.gridData[aU][1];if(aw>aA&&aw<aK){return{seriesIndex:aO.index,pointIndex:aU,gridData:[al.x,al.y],data:aO.data[aU]}}}}break;case L.jqplot.PieRenderer:az=aO.startAngle/180*Math.PI;aJ=al.x-aO._center[0];aI=al.y-aO._center[1];aP=Math.sqrt(Math.pow(aJ,2)+Math.pow(aI,2));if(aJ>0&&-aI>=0){aw=2*Math.PI-Math.atan(-aI/aJ)}else{if(aJ>0&&-aI<0){aw=-Math.atan(-aI/aJ)}else{if(aJ<0){aw=Math.PI-Math.atan(-aI/aJ)}else{if(aJ==0&&-aI>0){aw=3*Math.PI/2}else{if(aJ==0&&-aI<0){aw=Math.PI/2}else{if(aJ==0&&aI==0){aw=0}}}}}}if(az){aw-=az;if(aw<0){aw+=2*Math.PI}else{if(aw>2*Math.PI){aw-=2*Math.PI}}}au=aO.sliceMargin/180*Math.PI;if(aP<aO._radius){for(aU=0;aU<aO.gridData.length;aU++){aA=(aU>0)?aO.gridData[aU-1][1]+au:au;aK=aO.gridData[aU][1];if(aw>aA&&aw<aK){return{seriesIndex:aO.index,pointIndex:aU,gridData:[al.x,al.y],data:aO.data[aU]}}}}break;case L.jqplot.BubbleRenderer:aJ=al.x;aI=al.y;var aF=null;if(aO.show){for(var aU=0;aU<aO.gridData.length;aU++){aQ=aO.gridData[aU];aX=Math.sqrt((aJ-aQ[0])*(aJ-aQ[0])+(aI-aQ[1])*(aI-aQ[1]));if(aX<=aQ[2]&&(aX<=aS||aS==null)){aS=aX;aF={seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}if(aF!=null){return aF}}break;case L.jqplot.FunnelRenderer:aJ=al.x;aI=al.y;var aL=aO._vertices,ap=aL[0],ao=aL[aL.length-1],at,aE,ay;function aR(a0,a2,a1){var aZ=(a2[1]-a1[1])/(a2[0]-a1[0]);var aY=a2[1]-aZ*a2[0];var a3=a0+a2[1];return[(a3-aY)/aZ,a3]}at=aR(aI,ap[0],ao[3]);aE=aR(aI,ap[1],ao[2]);for(aU=0;aU<aL.length;aU++){ay=aL[aU];if(aI>=ay[0][1]&&aI<=ay[3][1]&&aJ>=at[0]&&aJ<=aE[0]){return{seriesIndex:aO.index,pointIndex:aU,gridData:null,data:aO.data[aU]}}}break;case L.jqplot.LineRenderer:aJ=al.x;aI=al.y;aP=aO.renderer;if(aO.show){if((aO.fill||(aO.renderer.bands.show&&aO.renderer.bands.fill))&&(!am.plugins.highlighter||!am.plugins.highlighter.show)){var ax=false;if(aJ>aO._boundingBox[0][0]&&aJ<aO._boundingBox[1][0]&&aI>aO._boundingBox[1][1]&&aI<aO._boundingBox[0][1]){var aD=aO._areaPoints.length;var aG;var aU=aD-1;for(var aG=0;aG<aD;aG++){var aC=[aO._areaPoints[aG][0],aO._areaPoints[aG][1]];var aB=[aO._areaPoints[aU][0],aO._areaPoints[aU][1]];if(aC[1]<aI&&aB[1]>=aI||aB[1]<aI&&aC[1]>=aI){if(aC[0]+(aI-aC[1])/(aB[1]-aC[1])*(aB[0]-aC[0])<aJ){ax=!ax}}aU=aG}}if(ax){return{seriesIndex:aW,pointIndex:null,gridData:aO.gridData,data:aO.data,points:aO._areaPoints}}break}else{aN=aO.markerRenderer.size/2+aO.neighborThreshold;an=(aN>0)?aN:0;for(var aU=0;aU<aO.gridData.length;aU++){aQ=aO.gridData[aU];if(aP.constructor==L.jqplot.OHLCRenderer){if(aP.candleStick){var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._bodyWidth/2&&aJ<=aQ[0]+aP._bodyWidth/2&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{if(!aP.hlc){var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][1])&&aI<=av(aO.data[aU][2])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}else{if(aQ[0]!=null&&aQ[1]!=null){aX=Math.sqrt((aJ-aQ[0])*(aJ-aQ[0])+(aI-aQ[1])*(aI-aQ[1]));if(aX<=an&&(aX<=aS||aS==null)){aS=aX;return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}}}break;default:aJ=al.x;aI=al.y;aP=aO.renderer;if(aO.show){aN=aO.markerRenderer.size/2+aO.neighborThreshold;an=(aN>0)?aN:0;for(var aU=0;aU<aO.gridData.length;aU++){aQ=aO.gridData[aU];if(aP.constructor==L.jqplot.OHLCRenderer){if(aP.candleStick){var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._bodyWidth/2&&aJ<=aQ[0]+aP._bodyWidth/2&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{if(!aP.hlc){var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][1])&&aI<=av(aO.data[aU][2])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}else{aX=Math.sqrt((aJ-aQ[0])*(aJ-aQ[0])+(aI-aQ[1])*(aI-aQ[1]));if(aX<=an&&(aX<=aS||aS==null)){aS=aX;return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}break}}return null}this.onClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onDblClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotDblClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseDown=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotMouseDown");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseUp=function(an){var am=ai(an);var al=L.Event("jqplotMouseUp");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,null,an.data.plot])};this.onRightClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);if(ap.captureRightClick){if(an.which==3){var al=L.Event("jqplotRightClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])}else{var al=L.Event("jqplotMouseUp");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])}}};this.onMouseMove=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotMouseMove");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseEnter=function(an){var am=ai(an);var ao=an.data.plot;var al=L.Event("jqplotMouseEnter");al.pageX=an.pageX;al.pageY=an.pageY;al.relatedTarget=an.relatedTarget;L(this).trigger(al,[am.gridPos,am.dataPos,null,ao])};this.onMouseLeave=function(an){var am=ai(an);var ao=an.data.plot;var al=L.Event("jqplotMouseLeave");al.pageX=an.pageX;al.pageY=an.pageY;al.relatedTarget=an.relatedTarget;L(this).trigger(al,[am.gridPos,am.dataPos,null,ao])};this.drawSeries=function(an,al){var ap,ao,am;al=(typeof(an)==="number"&&al==null)?an:al;an=(typeof(an)==="object")?an:{};if(al!=u){ao=this.series[al];am=ao.shadowCanvas._ctx;am.clearRect(0,0,am.canvas.width,am.canvas.height);ao.drawShadow(am,an,this);am=ao.canvas._ctx;am.clearRect(0,0,am.canvas.width,am.canvas.height);ao.draw(am,an,this);if(ao.renderer.constructor==L.jqplot.BezierCurveRenderer){if(al<this.series.length-1){this.drawSeries(al+1)}}}else{for(ap=0;ap<this.series.length;ap++){ao=this.series[ap];am=ao.shadowCanvas._ctx;am.clearRect(0,0,am.canvas.width,am.canvas.height);ao.drawShadow(am,an,this);am=ao.canvas._ctx;am.clearRect(0,0,am.canvas.width,am.canvas.height);ao.draw(am,an,this)}}an=al=ap=ao=am=null};this.moveSeriesToFront=function(am){am=parseInt(am,10);var ap=L.inArray(am,this.seriesStack);if(ap==-1){return}if(ap==this.seriesStack.length-1){this.previousSeriesStack=this.seriesStack.slice(0);return}var al=this.seriesStack[this.seriesStack.length-1];var ao=this.series[am].canvas._elem.detach();var an=this.series[am].shadowCanvas._elem.detach();this.series[al].shadowCanvas._elem.after(an);this.series[al].canvas._elem.after(ao);this.previousSeriesStack=this.seriesStack.slice(0);this.seriesStack.splice(ap,1);this.seriesStack.push(am)};this.moveSeriesToBack=function(am){am=parseInt(am,10);var ap=L.inArray(am,this.seriesStack);if(ap==0||ap==-1){return}var al=this.seriesStack[0];var ao=this.series[am].canvas._elem.detach();var an=this.series[am].shadowCanvas._elem.detach();this.series[al].shadowCanvas._elem.before(an);this.series[al].canvas._elem.before(ao);this.previousSeriesStack=this.seriesStack.slice(0);this.seriesStack.splice(ap,1);this.seriesStack.unshift(am)};this.restorePreviousSeriesOrder=function(){var ar,aq,ap,ao,an,al,am;if(this.seriesStack==this.previousSeriesStack){return}for(ar=1;ar<this.previousSeriesStack.length;ar++){al=this.previousSeriesStack[ar];am=this.previousSeriesStack[ar-1];ap=this.series[al].canvas._elem.detach();ao=this.series[al].shadowCanvas._elem.detach();this.series[am].shadowCanvas._elem.after(ao);this.series[am].canvas._elem.after(ap)}an=this.seriesStack.slice(0);this.seriesStack=this.previousSeriesStack.slice(0);this.previousSeriesStack=an};this.restoreOriginalSeriesOrder=function(){var ap,ao,al=[],an,am;for(ap=0;ap<this.series.length;ap++){al.push(ap)}if(this.seriesStack==al){return}this.previousSeriesStack=this.seriesStack.slice(0);this.seriesStack=al;for(ap=1;ap<this.seriesStack.length;ap++){an=this.series[ap].canvas._elem.detach();am=this.series[ap].shadowCanvas._elem.detach();this.series[ap-1].shadowCanvas._elem.after(am);this.series[ap-1].canvas._elem.after(an)}};this.activateTheme=function(al){this.themeEngine.activate(this,al)}}L.jqplot.computeHighlightColors=function(ai){var ak;if(L.isArray(ai)){ak=[];for(var am=0;am<ai.length;am++){var al=L.jqplot.getColorComponents(ai[am]);var ah=[al[0],al[1],al[2]];var an=ah[0]+ah[1]+ah[2];for(var aj=0;aj<3;aj++){ah[aj]=(an>660)?ah[aj]*0.85:0.73*ah[aj]+90;ah[aj]=parseInt(ah[aj],10);(ah[aj]>255)?255:ah[aj]}ah[3]=0.3+0.35*al[3];ak.push("rgba("+ah[0]+","+ah[1]+","+ah[2]+","+ah[3]+")")}}else{var al=L.jqplot.getColorComponents(ai);var ah=[al[0],al[1],al[2]];var an=ah[0]+ah[1]+ah[2];for(var aj=0;aj<3;aj++){ah[aj]=(an>660)?ah[aj]*0.85:0.73*ah[aj]+90;ah[aj]=parseInt(ah[aj],10);(ah[aj]>255)?255:ah[aj]}ah[3]=0.3+0.35*al[3];ak="rgba("+ah[0]+","+ah[1]+","+ah[2]+","+ah[3]+")"}return ak};L.jqplot.ColorGenerator=function(ai){ai=ai||L.jqplot.config.defaultColors;var ah=0;this.next=function(){if(ah<ai.length){return ai[ah++]}else{ah=0;return ai[ah++]}};this.previous=function(){if(ah>0){return ai[ah--]}else{ah=ai.length-1;return ai[ah]}};this.get=function(ak){var aj=ak-ai.length*Math.floor(ak/ai.length);return ai[aj]};this.setColors=function(aj){ai=aj};this.reset=function(){ah=0};this.getIndex=function(){return ah};this.setIndex=function(aj){ah=aj}};L.jqplot.hex2rgb=function(aj,ah){aj=aj.replace("#","");if(aj.length==3){aj=aj.charAt(0)+aj.charAt(0)+aj.charAt(1)+aj.charAt(1)+aj.charAt(2)+aj.charAt(2)}var ai;ai="rgba("+parseInt(aj.slice(0,2),16)+", "+parseInt(aj.slice(2,4),16)+", "+parseInt(aj.slice(4,6),16);if(ah){ai+=", "+ah}ai+=")";return ai};L.jqplot.rgb2hex=function(am){var aj=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/;var ah=am.match(aj);var al="#";for(var ak=1;ak<4;ak++){var ai;if(ah[ak].search(/%/)!=-1){ai=parseInt(255*ah[ak]/100,10).toString(16);if(ai.length==1){ai="0"+ai}}else{ai=parseInt(ah[ak],10).toString(16);if(ai.length==1){ai="0"+ai}}al+=ai}return al};L.jqplot.normalize2rgb=function(ai,ah){if(ai.search(/^ *rgba?\(/)!=-1){return ai}else{if(ai.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/)!=-1){return L.jqplot.hex2rgb(ai,ah)}else{throw new Error("Invalid color spec")}}};L.jqplot.getColorComponents=function(am){am=L.jqplot.colorKeywordMap[am]||am;var ak=L.jqplot.normalize2rgb(am);var aj=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/;var ah=ak.match(aj);var ai=[];for(var al=1;al<4;al++){if(ah[al].search(/%/)!=-1){ai[al-1]=parseInt(255*ah[al]/100,10)}else{ai[al-1]=parseInt(ah[al],10)}}ai[3]=parseFloat(ah[4])?parseFloat(ah[4]):1;return ai};L.jqplot.colorKeywordMap={aliceblue:"rgb(240, 248, 255)",antiquewhite:"rgb(250, 235, 215)",aqua:"rgb( 0, 255, 255)",aquamarine:"rgb(127, 255, 212)",azure:"rgb(240, 255, 255)",beige:"rgb(245, 245, 220)",bisque:"rgb(255, 228, 196)",black:"rgb( 0, 0, 0)",blanchedalmond:"rgb(255, 235, 205)",blue:"rgb( 0, 0, 255)",blueviolet:"rgb(138, 43, 226)",brown:"rgb(165, 42, 42)",burlywood:"rgb(222, 184, 135)",cadetblue:"rgb( 95, 158, 160)",chartreuse:"rgb(127, 255, 0)",chocolate:"rgb(210, 105, 30)",coral:"rgb(255, 127, 80)",cornflowerblue:"rgb(100, 149, 237)",cornsilk:"rgb(255, 248, 220)",crimson:"rgb(220, 20, 60)",cyan:"rgb( 0, 255, 255)",darkblue:"rgb( 0, 0, 139)",darkcyan:"rgb( 0, 139, 139)",darkgoldenrod:"rgb(184, 134, 11)",darkgray:"rgb(169, 169, 169)",darkgreen:"rgb( 0, 100, 0)",darkgrey:"rgb(169, 169, 169)",darkkhaki:"rgb(189, 183, 107)",darkmagenta:"rgb(139, 0, 139)",darkolivegreen:"rgb( 85, 107, 47)",darkorange:"rgb(255, 140, 0)",darkorchid:"rgb(153, 50, 204)",darkred:"rgb(139, 0, 0)",darksalmon:"rgb(233, 150, 122)",darkseagreen:"rgb(143, 188, 143)",darkslateblue:"rgb( 72, 61, 139)",darkslategray:"rgb( 47, 79, 79)",darkslategrey:"rgb( 47, 79, 79)",darkturquoise:"rgb( 0, 206, 209)",darkviolet:"rgb(148, 0, 211)",deeppink:"rgb(255, 20, 147)",deepskyblue:"rgb( 0, 191, 255)",dimgray:"rgb(105, 105, 105)",dimgrey:"rgb(105, 105, 105)",dodgerblue:"rgb( 30, 144, 255)",firebrick:"rgb(178, 34, 34)",floralwhite:"rgb(255, 250, 240)",forestgreen:"rgb( 34, 139, 34)",fuchsia:"rgb(255, 0, 255)",gainsboro:"rgb(220, 220, 220)",ghostwhite:"rgb(248, 248, 255)",gold:"rgb(255, 215, 0)",goldenrod:"rgb(218, 165, 32)",gray:"rgb(128, 128, 128)",grey:"rgb(128, 128, 128)",green:"rgb( 0, 128, 0)",greenyellow:"rgb(173, 255, 47)",honeydew:"rgb(240, 255, 240)",hotpink:"rgb(255, 105, 180)",indianred:"rgb(205, 92, 92)",indigo:"rgb( 75, 0, 130)",ivory:"rgb(255, 255, 240)",khaki:"rgb(240, 230, 140)",lavender:"rgb(230, 230, 250)",lavenderblush:"rgb(255, 240, 245)",lawngreen:"rgb(124, 252, 0)",lemonchiffon:"rgb(255, 250, 205)",lightblue:"rgb(173, 216, 230)",lightcoral:"rgb(240, 128, 128)",lightcyan:"rgb(224, 255, 255)",lightgoldenrodyellow:"rgb(250, 250, 210)",lightgray:"rgb(211, 211, 211)",lightgreen:"rgb(144, 238, 144)",lightgrey:"rgb(211, 211, 211)",lightpink:"rgb(255, 182, 193)",lightsalmon:"rgb(255, 160, 122)",lightseagreen:"rgb( 32, 178, 170)",lightskyblue:"rgb(135, 206, 250)",lightslategray:"rgb(119, 136, 153)",lightslategrey:"rgb(119, 136, 153)",lightsteelblue:"rgb(176, 196, 222)",lightyellow:"rgb(255, 255, 224)",lime:"rgb( 0, 255, 0)",limegreen:"rgb( 50, 205, 50)",linen:"rgb(250, 240, 230)",magenta:"rgb(255, 0, 255)",maroon:"rgb(128, 0, 0)",mediumaquamarine:"rgb(102, 205, 170)",mediumblue:"rgb( 0, 0, 205)",mediumorchid:"rgb(186, 85, 211)",mediumpurple:"rgb(147, 112, 219)",mediumseagreen:"rgb( 60, 179, 113)",mediumslateblue:"rgb(123, 104, 238)",mediumspringgreen:"rgb( 0, 250, 154)",mediumturquoise:"rgb( 72, 209, 204)",mediumvioletred:"rgb(199, 21, 133)",midnightblue:"rgb( 25, 25, 112)",mintcream:"rgb(245, 255, 250)",mistyrose:"rgb(255, 228, 225)",moccasin:"rgb(255, 228, 181)",navajowhite:"rgb(255, 222, 173)",navy:"rgb( 0, 0, 128)",oldlace:"rgb(253, 245, 230)",olive:"rgb(128, 128, 0)",olivedrab:"rgb(107, 142, 35)",orange:"rgb(255, 165, 0)",orangered:"rgb(255, 69, 0)",orchid:"rgb(218, 112, 214)",palegoldenrod:"rgb(238, 232, 170)",palegreen:"rgb(152, 251, 152)",paleturquoise:"rgb(175, 238, 238)",palevioletred:"rgb(219, 112, 147)",papayawhip:"rgb(255, 239, 213)",peachpuff:"rgb(255, 218, 185)",peru:"rgb(205, 133, 63)",pink:"rgb(255, 192, 203)",plum:"rgb(221, 160, 221)",powderblue:"rgb(176, 224, 230)",purple:"rgb(128, 0, 128)",red:"rgb(255, 0, 0)",rosybrown:"rgb(188, 143, 143)",royalblue:"rgb( 65, 105, 225)",saddlebrown:"rgb(139, 69, 19)",salmon:"rgb(250, 128, 114)",sandybrown:"rgb(244, 164, 96)",seagreen:"rgb( 46, 139, 87)",seashell:"rgb(255, 245, 238)",sienna:"rgb(160, 82, 45)",silver:"rgb(192, 192, 192)",skyblue:"rgb(135, 206, 235)",slateblue:"rgb(106, 90, 205)",slategray:"rgb(112, 128, 144)",slategrey:"rgb(112, 128, 144)",snow:"rgb(255, 250, 250)",springgreen:"rgb( 0, 255, 127)",steelblue:"rgb( 70, 130, 180)",tan:"rgb(210, 180, 140)",teal:"rgb( 0, 128, 128)",thistle:"rgb(216, 191, 216)",tomato:"rgb(255, 99, 71)",turquoise:"rgb( 64, 224, 208)",violet:"rgb(238, 130, 238)",wheat:"rgb(245, 222, 179)",white:"rgb(255, 255, 255)",whitesmoke:"rgb(245, 245, 245)",yellow:"rgb(255, 255, 0)",yellowgreen:"rgb(154, 205, 50)"};L.jqplot.AxisLabelRenderer=function(ah){L.jqplot.ElemContainer.call(this);this.axis;this.show=true;this.label="";this.fontFamily=null;this.fontSize=null;this.textColor=null;this._elem;this.escapeHTML=false;L.extend(true,this,ah)};L.jqplot.AxisLabelRenderer.prototype=new L.jqplot.ElemContainer();L.jqplot.AxisLabelRenderer.prototype.constructor=L.jqplot.AxisLabelRenderer;L.jqplot.AxisLabelRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.AxisLabelRenderer.prototype.draw=function(ah,ai){if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=L('<div style="position:absolute;" class="jqplot-'+this.axis+'-label"></div>');if(Number(this.label)){this._elem.css("white-space","nowrap")}if(!this.escapeHTML){this._elem.html(this.label)}else{this._elem.text(this.label)}if(this.fontFamily){this._elem.css("font-family",this.fontFamily)}if(this.fontSize){this._elem.css("font-size",this.fontSize)}if(this.textColor){this._elem.css("color",this.textColor)}return this._elem};L.jqplot.AxisLabelRenderer.prototype.pack=function(){};L.jqplot.AxisTickRenderer=function(ah){L.jqplot.ElemContainer.call(this);this.mark="outside";this.axis;this.showMark=true;this.showGridline=true;this.isMinorTick=false;this.size=4;this.markSize=6;this.show=true;this.showLabel=true;this.label=null;this.value=null;this._styles={};this.formatter=L.jqplot.DefaultTickFormatter;this.prefix="";this.suffix="";this.formatString="";this.fontFamily;this.fontSize;this.textColor;this.escapeHTML=false;this._elem;this._breakTick=false;L.extend(true,this,ah)};L.jqplot.AxisTickRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.AxisTickRenderer.prototype=new L.jqplot.ElemContainer();L.jqplot.AxisTickRenderer.prototype.constructor=L.jqplot.AxisTickRenderer;L.jqplot.AxisTickRenderer.prototype.setTick=function(ah,aj,ai){this.value=ah;this.axis=aj;if(ai){this.isMinorTick=true}return this};L.jqplot.AxisTickRenderer.prototype.draw=function(){if(this.label===null){this.label=this.prefix+this.formatter(this.formatString,this.value)+this.suffix}var ai={position:"absolute"};if(Number(this.label)){ai.whitSpace="nowrap"}if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=L(document.createElement("div"));this._elem.addClass("jqplot-"+this.axis+"-tick");if(!this.escapeHTML){this._elem.html(this.label)}else{this._elem.text(this.label)}this._elem.css(ai);for(var ah in this._styles){this._elem.css(ah,this._styles[ah])}if(this.fontFamily){this._elem.css("font-family",this.fontFamily)}if(this.fontSize){this._elem.css("font-size",this.fontSize)}if(this.textColor){this._elem.css("color",this.textColor)}if(this._breakTick){this._elem.addClass("jqplot-breakTick")}return this._elem};L.jqplot.DefaultTickFormatter=function(ah,ai){if(typeof ai=="number"){if(!ah){ah=L.jqplot.config.defaultTickFormatString}return L.jqplot.sprintf(ah,ai)}else{return String(ai)}};L.jqplot.PercentTickFormatter=function(ah,ai){if(typeof ai=="number"){ai=100*ai;if(!ah){ah=L.jqplot.config.defaultTickFormatString}return L.jqplot.sprintf(ah,ai)}else{return String(ai)}};L.jqplot.AxisTickRenderer.prototype.pack=function(){};L.jqplot.CanvasGridRenderer=function(){this.shadowRenderer=new L.jqplot.ShadowRenderer()};L.jqplot.CanvasGridRenderer.prototype.init=function(ai){this._ctx;L.extend(true,this,ai);var ah={lineJoin:"miter",lineCap:"round",fill:false,isarc:false,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.shadowWidth,closePath:false,strokeStyle:this.shadowColor};this.renderer.shadowRenderer.init(ah)};L.jqplot.CanvasGridRenderer.prototype.createElement=function(ak){var aj;if(this._elem){if(L.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==u){aj=this._elem.get(0);window.G_vmlCanvasManager.uninitElement(aj);aj=null}this._elem.emptyForce();this._elem=null}aj=ak.canvasManager.getCanvas();var ah=this._plotDimensions.width;var ai=this._plotDimensions.height;aj.width=ah;aj.height=ai;this._elem=L(aj);this._elem.addClass("jqplot-grid-canvas");this._elem.css({position:"absolute",left:0,top:0});aj=ak.canvasManager.initCanvas(aj);this._top=this._offsets.top;this._bottom=ai-this._offsets.bottom;this._left=this._offsets.left;this._right=ah-this._offsets.right;this._width=this._right-this._left;this._height=this._bottom-this._top;aj=null;return this._elem};L.jqplot.CanvasGridRenderer.prototype.draw=function(){this._ctx=this._elem.get(0).getContext("2d");var at=this._ctx;var aw=this._axes;at.save();at.clearRect(0,0,this._plotDimensions.width,this._plotDimensions.height);at.fillStyle=this.backgroundColor||this.background;at.fillRect(this._left,this._top,this._width,this._height);at.save();at.lineJoin="miter";at.lineCap="butt";at.lineWidth=this.gridLineWidth;at.strokeStyle=this.gridLineColor;var aA,az,ap,aq;var am=["xaxis","yaxis","x2axis","y2axis"];for(var ay=4;ay>0;ay--){var aD=am[ay-1];var ah=aw[aD];var aB=ah._ticks;var ar=aB.length;if(ah.show){if(ah.drawBaseline){var aC={};if(ah.baselineWidth!==null){aC.lineWidth=ah.baselineWidth}if(ah.baselineColor!==null){aC.strokeStyle=ah.baselineColor}switch(aD){case"xaxis":ao(this._left,this._bottom,this._right,this._bottom,aC);break;case"yaxis":ao(this._left,this._bottom,this._left,this._top,aC);break;case"x2axis":ao(this._left,this._bottom,this._right,this._bottom,aC);break;case"y2axis":ao(this._right,this._bottom,this._right,this._top,aC);break}}for(var au=ar;au>0;au--){var an=aB[au-1];if(an.show){var ak=Math.round(ah.u2p(an.value))+0.5;switch(aD){case"xaxis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(ak,this._top,ak,this._bottom)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._bottom;az=this._bottom+ap;break;case"inside":aA=this._bottom-ap;az=this._bottom;break;case"cross":aA=this._bottom-ap;az=this._bottom+ap;break;default:aA=this._bottom;az=this._bottom+ap;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[ak,aA],[ak,az]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}ao(ak,aA,ak,az)}break;case"yaxis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(this._right,ak,this._left,ak)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._left-ap;az=this._left;break;case"inside":aA=this._left;az=this._left+ap;break;case"cross":aA=this._left-ap;az=this._left+ap;break;default:aA=this._left-ap;az=this._left;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[aA,ak],[az,ak]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}break;case"x2axis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(ak,this._bottom,ak,this._top)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._top-ap;az=this._top;break;case"inside":aA=this._top;az=this._top+ap;break;case"cross":aA=this._top-ap;az=this._top+ap;break;default:aA=this._top-ap;az=this._top;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[ak,aA],[ak,az]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}ao(ak,aA,ak,az)}break;case"y2axis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(this._left,ak,this._right,ak)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._right;az=this._right+ap;break;case"inside":aA=this._right-ap;az=this._right;break;case"cross":aA=this._right-ap;az=this._right+ap;break;default:aA=this._right;az=this._right+ap;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[aA,ak],[az,ak]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}break;default:break}}}an=null}ah=null;aB=null}am=["y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"];for(var ay=7;ay>0;ay--){var ah=aw[am[ay-1]];var aB=ah._ticks;if(ah.show){var ai=aB[ah.numberTicks-1];var al=aB[0];var aj=ah.getLeft();var av=[[aj,ai.getTop()+ai.getHeight()/2],[aj,al.getTop()+al.getHeight()/2+1]];if(this.shadow){this.renderer.shadowRenderer.draw(at,av,{lineCap:"butt",fill:false,closePath:false})}ao(av[0][0],av[0][1],av[1][0],av[1][1],{lineCap:"butt",strokeStyle:ah.borderColor,lineWidth:ah.borderWidth});for(var au=aB.length;au>0;au--){var an=aB[au-1];ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;if(an.showMark&&an.mark){switch(aq){case"outside":aA=aj;az=aj+ap;break;case"inside":aA=aj-ap;az=aj;break;case"cross":aA=aj-ap;az=aj+ap;break;default:aA=aj;az=aj+ap;break}av=[[aA,ak],[az,ak]];if(this.shadow){this.renderer.shadowRenderer.draw(at,av,{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}an=null}al=null}ah=null;aB=null}at.restore();function ao(aH,aG,aE,ax,aF){at.save();aF=aF||{};if(aF.lineWidth==null||aF.lineWidth!=0){L.extend(true,at,aF);at.beginPath();at.moveTo(aH,aG);at.lineTo(aE,ax);at.stroke();at.restore()}}if(this.shadow){var av=[[this._left,this._bottom],[this._right,this._bottom],[this._right,this._top]];this.renderer.shadowRenderer.draw(at,av)}if(this.borderWidth!=0&&this.drawBorder){ao(this._left,this._top,this._right,this._top,{lineCap:"round",strokeStyle:aw.x2axis.borderColor,lineWidth:aw.x2axis.borderWidth});ao(this._right,this._top,this._right,this._bottom,{lineCap:"round",strokeStyle:aw.y2axis.borderColor,lineWidth:aw.y2axis.borderWidth});ao(this._right,this._bottom,this._left,this._bottom,{lineCap:"round",strokeStyle:aw.xaxis.borderColor,lineWidth:aw.xaxis.borderWidth});ao(this._left,this._bottom,this._left,this._top,{lineCap:"round",strokeStyle:aw.yaxis.borderColor,lineWidth:aw.yaxis.borderWidth})}at.restore();at=null;aw=null};L.jqplot.DivTitleRenderer=function(){};L.jqplot.DivTitleRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.DivTitleRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}var ak=this.renderer;var aj=document.createElement("div");this._elem=L(aj);this._elem.addClass("jqplot-title");if(!this.text){this.show=false;this._elem.height(0);this._elem.width(0)}else{if(this.text){var ah;if(this.color){ah=this.color}else{if(this.textColor){ah=this.textColor}}var ai={position:"absolute",top:"0px",left:"0px"};if(this._plotWidth){ai.width=this._plotWidth+"px"}if(this.fontSize){ai.fontSize=this.fontSize}if(typeof this.textAlign==="string"){ai.textAlign=this.textAlign}else{ai.textAlign="center"}if(ah){ai.color=ah}if(this.paddingBottom){ai.paddingBottom=this.paddingBottom}if(this.fontFamily){ai.fontFamily=this.fontFamily}this._elem.css(ai);if(this.escapeHtml){this._elem.text(this.text)}else{this._elem.html(this.text)}}}aj=null;return this._elem};L.jqplot.DivTitleRenderer.prototype.pack=function(){};var r=0.1;L.jqplot.LinePattern=function(aw,aq){var ap={dotted:[r,L.jqplot.config.dotGapLength],dashed:[L.jqplot.config.dashLength,L.jqplot.config.gapLength],solid:null};if(typeof aq==="string"){if(aq[0]==="."||aq[0]==="-"){var ax=aq;aq=[];for(var ao=0,al=ax.length;ao<al;ao++){if(ax[ao]==="."){aq.push(r)}else{if(ax[ao]==="-"){aq.push(L.jqplot.config.dashLength)}else{continue}}aq.push(L.jqplot.config.gapLength)}}else{aq=ap[aq]}}if(!(aq&&aq.length)){return aw}var ak=0;var ar=aq[0];var au=0;var at=0;var an=0;var ah=0;var av=function(ay,az){aw.moveTo(ay,az);au=ay;at=az;an=ay;ah=az};var aj=function(ay,aE){var aC=aw.lineWidth;var aA=ay-au;var az=aE-at;var aB=Math.sqrt(aA*aA+az*az);if((aB>0)&&(aC>0)){aA/=aB;az/=aB;while(true){var aD=aC*ar;if(aD<aB){au+=aD*aA;at+=aD*az;if((ak&1)==0){aw.lineTo(au,at)}else{aw.moveTo(au,at)}aB-=aD;ak++;if(ak>=aq.length){ak=0}ar=aq[ak]}else{au=ay;at=aE;if((ak&1)==0){aw.lineTo(au,at)}else{aw.moveTo(au,at)}ar-=aB/aC;break}}}};var ai=function(){aw.beginPath()};var am=function(){aj(an,ah)};return{moveTo:av,lineTo:aj,beginPath:ai,closePath:am}};L.jqplot.LineRenderer=function(){this.shapeRenderer=new L.jqplot.ShapeRenderer();this.shadowRenderer=new L.jqplot.ShadowRenderer()};L.jqplot.LineRenderer.prototype.init=function(ai,an){ai=ai||{};this._type="line";this.renderer.animation={show:false,direction:"left",speed:2500,_supported:true};this.renderer.smooth=false;this.renderer.tension=null;this.renderer.constrainSmoothing=true;this.renderer._smoothedData=[];this.renderer._smoothedPlotData=[];this.renderer._hiBandGridData=[];this.renderer._lowBandGridData=[];this.renderer._hiBandSmoothedData=[];this.renderer._lowBandSmoothedData=[];this.renderer.bandData=[];this.renderer.bands={show:false,hiData:[],lowData:[],color:this.color,showLines:false,fill:true,fillColor:null,_min:null,_max:null,interval:"3%"};var al={highlightMouseOver:ai.highlightMouseOver,highlightMouseDown:ai.highlightMouseDown,highlightColor:ai.highlightColor};delete (ai.highlightMouseOver);delete (ai.highlightMouseDown);delete (ai.highlightColor);L.extend(true,this.renderer,ai);this.renderer.options=ai;if(this.renderer.bandData.length>1&&(!ai.bands||ai.bands.show==null)){this.renderer.bands.show=true}else{if(ai.bands&&ai.bands.show==null&&ai.bands.interval!=null){this.renderer.bands.show=true}}if(this.fill){this.renderer.bands.show=false}if(this.renderer.bands.show){this.renderer.initBands.call(this,this.renderer.options,an)}if(this._stack){this.renderer.smooth=false}var am={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:false,strokeStyle:this.color,fillStyle:this.fillColor,lineWidth:this.lineWidth,linePattern:this.linePattern,closePath:this.fill};this.renderer.shapeRenderer.init(am);var aj=ai.shadowOffset;if(aj==null){if(this.lineWidth>2.5){aj=1.25*(1+(Math.atan((this.lineWidth/2.5))/0.785398163-1)*0.6)}else{aj=1.25*Math.atan((this.lineWidth/2.5))/0.785398163}}var ah={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:false,angle:this.shadowAngle,offset:aj,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.lineWidth,linePattern:this.linePattern,closePath:this.fill};this.renderer.shadowRenderer.init(ah);this._areaPoints=[];this._boundingBox=[[],[]];if(!this.isTrendline&&this.fill||this.renderer.bands.show){this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColor=null;if(al.highlightMouseDown&&al.highlightMouseOver==null){al.highlightMouseOver=false}L.extend(true,this,{highlightMouseOver:al.highlightMouseOver,highlightMouseDown:al.highlightMouseDown,highlightColor:al.highlightColor});if(!this.highlightColor){var ak=(this.renderer.bands.show)?this.renderer.bands.fillColor:this.fillColor;this.highlightColor=L.jqplot.computeHighlightColors(ak)}if(this.highlighter){this.highlighter.show=false}}if(!this.isTrendline&&an){an.plugins.lineRenderer={};an.postInitHooks.addOnce(z);an.postDrawHooks.addOnce(af);an.eventListenerHooks.addOnce("jqplotMouseMove",h);an.eventListenerHooks.addOnce("jqplotMouseDown",e);an.eventListenerHooks.addOnce("jqplotMouseUp",ad);an.eventListenerHooks.addOnce("jqplotClick",g);an.eventListenerHooks.addOnce("jqplotRightClick",s)}};L.jqplot.LineRenderer.prototype.initBands=function(ak,av){var al=ak.bandData||[];var an=this.renderer.bands;an.hiData=[];an.lowData=[];var aB=this.data;an._max=null;an._min=null;if(al.length==2){if(L.isArray(al[0][0])){var ao;var ah=0,ar=0;for(var aw=0,at=al[0].length;aw<at;aw++){ao=al[0][aw];if((ao[1]!=null&&ao[1]>an._max)||an._max==null){an._max=ao[1]}if((ao[1]!=null&&ao[1]<an._min)||an._min==null){an._min=ao[1]}}for(var aw=0,at=al[1].length;aw<at;aw++){ao=al[1][aw];if((ao[1]!=null&&ao[1]>an._max)||an._max==null){an._max=ao[1];ar=1}if((ao[1]!=null&&ao[1]<an._min)||an._min==null){an._min=ao[1];ah=1}}if(ar===ah){an.show=false}an.hiData=al[ar];an.lowData=al[ah]}else{if(al[0].length===aB.length&&al[1].length===aB.length){var aj=(al[0][0]>al[1][0])?0:1;var aC=(aj)?0:1;for(var aw=0,at=aB.length;aw<at;aw++){an.hiData.push([aB[aw][0],al[aj][aw]]);an.lowData.push([aB[aw][0],al[aC][aw]])}}else{an.show=false}}}else{if(al.length>2&&!L.isArray(al[0][0])){var aj=(al[0][0]>al[0][1])?0:1;var aC=(aj)?0:1;for(var aw=0,at=al.length;aw<at;aw++){an.hiData.push([aB[aw][0],al[aw][aj]]);an.lowData.push([aB[aw][0],al[aw][aC]])}}else{var aq=an.interval;var aA=null;var az=null;var ai=null;var au=null;if(L.isArray(aq)){aA=aq[0];az=aq[1]}else{aA=aq}if(isNaN(aA)){if(aA.charAt(aA.length-1)==="%"){ai="multiply";aA=parseFloat(aA)/100+1}}else{aA=parseFloat(aA);ai="add"}if(az!==null&&isNaN(az)){if(az.charAt(az.length-1)==="%"){au="multiply";az=parseFloat(az)/100+1}}else{if(az!==null){az=parseFloat(az);au="add"}}if(aA!==null){if(az===null){az=-aA;au=ai;if(au==="multiply"){az+=2}}if(aA<az){var ax=aA;aA=az;az=ax;ax=ai;ai=au;au=ax}for(var aw=0,at=aB.length;aw<at;aw++){switch(ai){case"add":an.hiData.push([aB[aw][0],aB[aw][1]+aA]);break;case"multiply":an.hiData.push([aB[aw][0],aB[aw][1]*aA]);break}switch(au){case"add":an.lowData.push([aB[aw][0],aB[aw][1]+az]);break;case"multiply":an.lowData.push([aB[aw][0],aB[aw][1]*az]);break}}}else{an.show=false}}}var am=an.hiData;var ap=an.lowData;for(var aw=0,at=am.length;aw<at;aw++){if((am[aw][1]!=null&&am[aw][1]>an._max)||an._max==null){an._max=am[aw][1]}}for(var aw=0,at=ap.length;aw<at;aw++){if((ap[aw][1]!=null&&ap[aw][1]<an._min)||an._min==null){an._min=ap[aw][1]}}if(an.fillColor===null){var ay=L.jqplot.getColorComponents(an.color);ay[3]=ay[3]*0.5;an.fillColor="rgba("+ay[0]+", "+ay[1]+", "+ay[2]+", "+ay[3]+")"}};function K(ai,ah){return(3.4182054+ah)*Math.pow(ai,-0.3534992)}function n(aj,ai){var ah=Math.sqrt(Math.pow((ai[0]-aj[0]),2)+Math.pow((ai[1]-aj[1]),2));return 5.7648*Math.log(ah)+7.4456}function A(ah){var ai=(Math.exp(2*ah)-1)/(Math.exp(2*ah)+1);return ai}function J(aJ){var at=this.renderer.smooth;var aD=this.canvas.getWidth();var an=this._xaxis.series_p2u;var aG=this._yaxis.series_p2u;var aF=null;var am=null;var az=aJ.length/aD;var aj=[];var ay=[];if(!isNaN(parseFloat(at))){aF=parseFloat(at)}else{aF=K(az,0.5)}var aw=[];var ak=[];for(var aE=0,aA=aJ.length;aE<aA;aE++){aw.push(aJ[aE][1]);ak.push(aJ[aE][0])}function av(aK,aL){if(aK-aL==0){return Math.pow(10,10)}else{return aK-aL}}var ax,ar,aq,ap;var ah=aJ.length-1;for(var al=1,aB=aJ.length;al<aB;al++){var ai=[];var au=[];for(var aC=0;aC<2;aC++){var aE=al-1+aC;if(aE==0||aE==ah){ai[aC]=Math.pow(10,10)}else{if(aw[aE+1]-aw[aE]==0||aw[aE]-aw[aE-1]==0){ai[aC]=0}else{if(((ak[aE+1]-ak[aE])/(aw[aE+1]-aw[aE])+(ak[aE]-ak[aE-1])/(aw[aE]-aw[aE-1]))==0){ai[aC]=0}else{if((aw[aE+1]-aw[aE])*(aw[aE]-aw[aE-1])<0){ai[aC]=0}else{ai[aC]=2/(av(ak[aE+1],ak[aE])/(aw[aE+1]-aw[aE])+av(ak[aE],ak[aE-1])/(aw[aE]-aw[aE-1]))}}}}}if(al==1){ai[0]=3/2*(aw[1]-aw[0])/av(ak[1],ak[0])-ai[1]/2}else{if(al==ah){ai[1]=3/2*(aw[ah]-aw[ah-1])/av(ak[ah],ak[ah-1])-ai[0]/2}}au[0]=-2*(ai[1]+2*ai[0])/av(ak[al],ak[al-1])+6*(aw[al]-aw[al-1])/Math.pow(av(ak[al],ak[al-1]),2);au[1]=2*(2*ai[1]+ai[0])/av(ak[al],ak[al-1])-6*(aw[al]-aw[al-1])/Math.pow(av(ak[al],ak[al-1]),2);ap=1/6*(au[1]-au[0])/av(ak[al],ak[al-1]);aq=1/2*(ak[al]*au[0]-ak[al-1]*au[1])/av(ak[al],ak[al-1]);ar=(aw[al]-aw[al-1]-aq*(Math.pow(ak[al],2)-Math.pow(ak[al-1],2))-ap*(Math.pow(ak[al],3)-Math.pow(ak[al-1],3)))/av(ak[al],ak[al-1]);ax=aw[al-1]-ar*ak[al-1]-aq*Math.pow(ak[al-1],2)-ap*Math.pow(ak[al-1],3);var aI=(ak[al]-ak[al-1])/aF;var aH,ao;for(var aC=0,aA=aF;aC<aA;aC++){aH=[];ao=ak[al-1]+aC*aI;aH.push(ao);aH.push(ax+ar*ao+aq*Math.pow(ao,2)+ap*Math.pow(ao,3));aj.push(aH);ay.push([an(aH[0]),aG(aH[1])])}}aj.push(aJ[aE]);ay.push([an(aJ[aE][0]),aG(aJ[aE][1])]);return[aj,ay]}function F(ap){var ao=this.renderer.smooth;var aU=this.renderer.tension;var ah=this.canvas.getWidth();var aH=this._xaxis.series_p2u;var aq=this._yaxis.series_p2u;var aI=null;var aJ=null;var aT=null;var aO=null;var aM=null;var at=null;var aR=null;var am=null;var aK,aL,aD,aC,aA,ay;var ak,ai,av,au;var aB,az,aN;var aw=[];var aj=[];var al=ap.length/ah;var aS,ax,aF,aG,aE;var ar=[];var an=[];if(!isNaN(parseFloat(ao))){aI=parseFloat(ao)}else{aI=K(al,0.5)}if(!isNaN(parseFloat(aU))){aU=parseFloat(aU)}for(var aQ=0,aP=ap.length-1;aQ<aP;aQ++){if(aU===null){at=Math.abs((ap[aQ+1][1]-ap[aQ][1])/(ap[aQ+1][0]-ap[aQ][0]));aS=0.3;ax=0.6;aF=(ax-aS)/2;aG=2.5;aE=-1.4;am=at/aG+aE;aO=aF*A(am)-aF*A(aE)+aS;if(aQ>0){aR=Math.abs((ap[aQ][1]-ap[aQ-1][1])/(ap[aQ][0]-ap[aQ-1][0]))}am=aR/aG+aE;aM=aF*A(am)-aF*A(aE)+aS;aT=(aO+aM)/2}else{aT=aU}for(aK=0;aK<aI;aK++){aL=aK/aI;aD=(1+2*aL)*Math.pow((1-aL),2);aC=aL*Math.pow((1-aL),2);aA=Math.pow(aL,2)*(3-2*aL);ay=Math.pow(aL,2)*(aL-1);if(ap[aQ-1]){ak=aT*(ap[aQ+1][0]-ap[aQ-1][0]);ai=aT*(ap[aQ+1][1]-ap[aQ-1][1])}else{ak=aT*(ap[aQ+1][0]-ap[aQ][0]);ai=aT*(ap[aQ+1][1]-ap[aQ][1])}if(ap[aQ+2]){av=aT*(ap[aQ+2][0]-ap[aQ][0]);au=aT*(ap[aQ+2][1]-ap[aQ][1])}else{av=aT*(ap[aQ+1][0]-ap[aQ][0]);au=aT*(ap[aQ+1][1]-ap[aQ][1])}aB=aD*ap[aQ][0]+aA*ap[aQ+1][0]+aC*ak+ay*av;az=aD*ap[aQ][1]+aA*ap[aQ+1][1]+aC*ai+ay*au;aN=[aB,az];ar.push(aN);an.push([aH(aB),aq(az)])}}ar.push(ap[aP]);an.push([aH(ap[aP][0]),aq(ap[aP][1])]);return[ar,an]}L.jqplot.LineRenderer.prototype.setGridData=function(ap){var al=this._xaxis.series_u2p;var ah=this._yaxis.series_u2p;var am=this._plotData;var aq=this._prevPlotData;this.gridData=[];this._prevGridData=[];this.renderer._smoothedData=[];this.renderer._smoothedPlotData=[];this.renderer._hiBandGridData=[];this.renderer._lowBandGridData=[];this.renderer._hiBandSmoothedData=[];this.renderer._lowBandSmoothedData=[];var ak=this.renderer.bands;var ai=false;for(var an=0,aj=am.length;an<aj;an++){if(am[an][0]!=null&&am[an][1]!=null){this.gridData.push([al.call(this._xaxis,am[an][0]),ah.call(this._yaxis,am[an][1])])}else{if(am[an][0]==null){ai=true;this.gridData.push([null,ah.call(this._yaxis,am[an][1])])}else{if(am[an][1]==null){ai=true;this.gridData.push([al.call(this._xaxis,am[an][0]),null])}}}if(aq[an]!=null&&aq[an][0]!=null&&aq[an][1]!=null){this._prevGridData.push([al.call(this._xaxis,aq[an][0]),ah.call(this._yaxis,aq[an][1])])}else{if(aq[an]!=null&&aq[an][0]==null){this._prevGridData.push([null,ah.call(this._yaxis,aq[an][1])])}else{if(aq[an]!=null&&aq[an][0]!=null&&aq[an][1]==null){this._prevGridData.push([al.call(this._xaxis,aq[an][0]),null])}}}}if(ai){this.renderer.smooth=false;if(this._type==="line"){ak.show=false}}if(this._type==="line"&&ak.show){for(var an=0,aj=ak.hiData.length;an<aj;an++){this.renderer._hiBandGridData.push([al.call(this._xaxis,ak.hiData[an][0]),ah.call(this._yaxis,ak.hiData[an][1])])}for(var an=0,aj=ak.lowData.length;an<aj;an++){this.renderer._lowBandGridData.push([al.call(this._xaxis,ak.lowData[an][0]),ah.call(this._yaxis,ak.lowData[an][1])])}}if(this._type==="line"&&this.renderer.smooth&&this.gridData.length>2){var ao;if(this.renderer.constrainSmoothing){ao=J.call(this,this.gridData);this.renderer._smoothedData=ao[0];this.renderer._smoothedPlotData=ao[1];if(ak.show){ao=J.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ao[0];ao=J.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ao[0]}ao=null}else{ao=F.call(this,this.gridData);this.renderer._smoothedData=ao[0];this.renderer._smoothedPlotData=ao[1];if(ak.show){ao=F.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ao[0];ao=F.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ao[0]}ao=null}}};L.jqplot.LineRenderer.prototype.makeGridData=function(ao,aq){var am=this._xaxis.series_u2p;var ah=this._yaxis.series_u2p;var ar=[];var aj=[];this.renderer._smoothedData=[];this.renderer._smoothedPlotData=[];this.renderer._hiBandGridData=[];this.renderer._lowBandGridData=[];this.renderer._hiBandSmoothedData=[];this.renderer._lowBandSmoothedData=[];var al=this.renderer.bands;var ai=false;for(var an=0;an<ao.length;an++){if(ao[an][0]!=null&&ao[an][1]!=null){ar.push([am.call(this._xaxis,ao[an][0]),ah.call(this._yaxis,ao[an][1])])}else{if(ao[an][0]==null){ai=true;ar.push([null,ah.call(this._yaxis,ao[an][1])])}else{if(ao[an][1]==null){ai=true;ar.push([am.call(this._xaxis,ao[an][0]),null])}}}}if(ai){this.renderer.smooth=false;if(this._type==="line"){al.show=false}}if(this._type==="line"&&al.show){for(var an=0,ak=al.hiData.length;an<ak;an++){this.renderer._hiBandGridData.push([am.call(this._xaxis,al.hiData[an][0]),ah.call(this._yaxis,al.hiData[an][1])])}for(var an=0,ak=al.lowData.length;an<ak;an++){this.renderer._lowBandGridData.push([am.call(this._xaxis,al.lowData[an][0]),ah.call(this._yaxis,al.lowData[an][1])])}}if(this._type==="line"&&this.renderer.smooth&&ar.length>2){var ap;if(this.renderer.constrainSmoothing){ap=J.call(this,ar);this.renderer._smoothedData=ap[0];this.renderer._smoothedPlotData=ap[1];if(al.show){ap=J.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ap[0];ap=J.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ap[0]}ap=null}else{ap=F.call(this,ar);this.renderer._smoothedData=ap[0];this.renderer._smoothedPlotData=ap[1];if(al.show){ap=F.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ap[0];ap=F.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ap[0]}ap=null}}return ar};L.jqplot.LineRenderer.prototype.draw=function(ax,aI,ai,aB){var aC;var aq=L.extend(true,{},ai);var ak=(aq.shadow!=u)?aq.shadow:this.shadow;var aJ=(aq.showLine!=u)?aq.showLine:this.showLine;var aA=(aq.fill!=u)?aq.fill:this.fill;var ah=(aq.fillAndStroke!=u)?aq.fillAndStroke:this.fillAndStroke;var ar,ay,av,aE;ax.save();if(aI.length){if(aJ){if(aA){if(this.fillToZero){var aF=this.negativeColor;if(!this.useNegativeColors){aF=aq.fillStyle}var ao=false;var ap=aq.fillStyle;if(ah){var aH=aI.slice(0)}if(this.index==0||!this._stack){var aw=[];var aL=(this.renderer.smooth)?this.renderer._smoothedPlotData:this._plotData;this._areaPoints=[];var aG=this._yaxis.series_u2p(this.fillToValue);var aj=this._xaxis.series_u2p(this.fillToValue);aq.closePath=true;if(this.fillAxis=="y"){aw.push([aI[0][0],aG]);this._areaPoints.push([aI[0][0],aG]);for(var aC=0;aC<aI.length-1;aC++){aw.push(aI[aC]);this._areaPoints.push(aI[aC]);if(aL[aC][1]*aL[aC+1][1]<=0){if(aL[aC][1]<0){ao=true;aq.fillStyle=aF}else{ao=false;aq.fillStyle=ap}var an=aI[aC][0]+(aI[aC+1][0]-aI[aC][0])*(aG-aI[aC][1])/(aI[aC+1][1]-aI[aC][1]);aw.push([an,aG]);this._areaPoints.push([an,aG]);if(ak){this.renderer.shadowRenderer.draw(ax,aw,aq)}this.renderer.shapeRenderer.draw(ax,aw,aq);aw=[[an,aG]]}}if(aL[aI.length-1][1]<0){ao=true;aq.fillStyle=aF}else{ao=false;aq.fillStyle=ap}aw.push(aI[aI.length-1]);this._areaPoints.push(aI[aI.length-1]);aw.push([aI[aI.length-1][0],aG]);this._areaPoints.push([aI[aI.length-1][0],aG])}if(ak){this.renderer.shadowRenderer.draw(ax,aw,aq)}this.renderer.shapeRenderer.draw(ax,aw,aq)}else{var au=this._prevGridData;for(var aC=au.length;aC>0;aC--){aI.push(au[aC-1])}if(ak){this.renderer.shadowRenderer.draw(ax,aI,aq)}this._areaPoints=aI;this.renderer.shapeRenderer.draw(ax,aI,aq)}}else{if(ah){var aH=aI.slice(0)}if(this.index==0||!this._stack){var al=ax.canvas.height;aI.unshift([aI[0][0],al]);var aD=aI.length;aI.push([aI[aD-1][0],al])}else{var au=this._prevGridData;for(var aC=au.length;aC>0;aC--){aI.push(au[aC-1])}}this._areaPoints=aI;if(ak){this.renderer.shadowRenderer.draw(ax,aI,aq)}this.renderer.shapeRenderer.draw(ax,aI,aq)}if(ah){var az=L.extend(true,{},aq,{fill:false,closePath:false});this.renderer.shapeRenderer.draw(ax,aH,az);if(this.markerRenderer.show){if(this.renderer.smooth){aH=this.gridData}for(aC=0;aC<aH.length;aC++){this.markerRenderer.draw(aH[aC][0],aH[aC][1],ax,aq.markerOptions)}}}}else{if(this.renderer.bands.show){var am;var aK=L.extend(true,{},aq);if(this.renderer.bands.showLines){am=(this.renderer.smooth)?this.renderer._hiBandSmoothedData:this.renderer._hiBandGridData;this.renderer.shapeRenderer.draw(ax,am,aq);am=(this.renderer.smooth)?this.renderer._lowBandSmoothedData:this.renderer._lowBandGridData;this.renderer.shapeRenderer.draw(ax,am,aK)}if(this.renderer.bands.fill){if(this.renderer.smooth){am=this.renderer._hiBandSmoothedData.concat(this.renderer._lowBandSmoothedData.reverse())}else{am=this.renderer._hiBandGridData.concat(this.renderer._lowBandGridData.reverse())}this._areaPoints=am;aK.closePath=true;aK.fill=true;aK.fillStyle=this.renderer.bands.fillColor;this.renderer.shapeRenderer.draw(ax,am,aK)}}if(ak){this.renderer.shadowRenderer.draw(ax,aI,aq)}this.renderer.shapeRenderer.draw(ax,aI,aq)}}var ar=av=ay=aE=null;for(aC=0;aC<this._areaPoints.length;aC++){var at=this._areaPoints[aC];if(ar>at[0]||ar==null){ar=at[0]}if(aE<at[1]||aE==null){aE=at[1]}if(av<at[0]||av==null){av=at[0]}if(ay>at[1]||ay==null){ay=at[1]}}if(this.type==="line"&&this.renderer.bands.show){aE=this._yaxis.series_u2p(this.renderer.bands._min);ay=this._yaxis.series_u2p(this.renderer.bands._max)}this._boundingBox=[[ar,aE],[av,ay]];if(this.markerRenderer.show&&!aA){if(this.renderer.smooth){aI=this.gridData}for(aC=0;aC<aI.length;aC++){if(aI[aC][0]!=null&&aI[aC][1]!=null){this.markerRenderer.draw(aI[aC][0],aI[aC][1],ax,aq.markerOptions)}}}}ax.restore()};L.jqplot.LineRenderer.prototype.drawShadow=function(ah,aj,ai){};function z(ak,aj,ah){for(var ai=0;ai<this.series.length;ai++){if(this.series[ai].renderer.constructor==L.jqplot.LineRenderer){if(this.series[ai].highlightMouseOver){this.series[ai].highlightMouseDown=false}}}}function af(){if(this.plugins.lineRenderer&&this.plugins.lineRenderer.highlightCanvas){this.plugins.lineRenderer.highlightCanvas.resetCanvas();this.plugins.lineRenderer.highlightCanvas=null}this.plugins.lineRenderer.highlightedSeriesIndex=null;this.plugins.lineRenderer.highlightCanvas=new L.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.lineRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-lineRenderer-highlight-canvas",this._plotDimensions,this));this.plugins.lineRenderer.highlightCanvas.setContext();this.eventCanvas._elem.bind("mouseleave",{plot:this},function(ah){aa(ah.data.plot)})}function ac(an,am,ak,aj){var ai=an.series[am];var ah=an.plugins.lineRenderer.highlightCanvas;ah._ctx.clearRect(0,0,ah._ctx.canvas.width,ah._ctx.canvas.height);ai._highlightedPoint=ak;an.plugins.lineRenderer.highlightedSeriesIndex=am;var al={fillStyle:ai.highlightColor};if(ai.type==="line"&&ai.renderer.bands.show){al.fill=true;al.closePath=true}ai.renderer.shapeRenderer.draw(ah._ctx,aj,al);ah=null}function aa(aj){var ah=aj.plugins.lineRenderer.highlightCanvas;ah._ctx.clearRect(0,0,ah._ctx.canvas.width,ah._ctx.canvas.height);for(var ai=0;ai<aj.series.length;ai++){aj.series[ai]._highlightedPoint=null}aj.plugins.lineRenderer.highlightedSeriesIndex=null;aj.target.trigger("jqplotDataUnhighlight");ah=null}function h(al,ak,ao,an,am){if(an){var aj=[an.seriesIndex,an.pointIndex,an.data];var ai=jQuery.Event("jqplotDataMouseOver");ai.pageX=al.pageX;ai.pageY=al.pageY;am.target.trigger(ai,aj);if(am.series[aj[0]].highlightMouseOver&&!(aj[0]==am.plugins.lineRenderer.highlightedSeriesIndex)){var ah=jQuery.Event("jqplotDataHighlight");ah.which=al.which;ah.pageX=al.pageX;ah.pageY=al.pageY;am.target.trigger(ah,aj);ac(am,an.seriesIndex,an.pointIndex,an.points)}}else{if(an==null){aa(am)}}}function e(ak,aj,an,am,al){if(am){var ai=[am.seriesIndex,am.pointIndex,am.data];if(al.series[ai[0]].highlightMouseDown&&!(ai[0]==al.plugins.lineRenderer.highlightedSeriesIndex)){var ah=jQuery.Event("jqplotDataHighlight");ah.which=ak.which;ah.pageX=ak.pageX;ah.pageY=ak.pageY;al.target.trigger(ah,ai);ac(al,am.seriesIndex,am.pointIndex,am.points)}}else{if(am==null){aa(al)}}}function ad(aj,ai,am,al,ak){var ah=ak.plugins.lineRenderer.highlightedSeriesIndex;if(ah!=null&&ak.series[ah].highlightMouseDown){aa(ak)}}function g(ak,aj,an,am,al){if(am){var ai=[am.seriesIndex,am.pointIndex,am.data];var ah=jQuery.Event("jqplotDataClick");ah.which=ak.which;ah.pageX=ak.pageX;ah.pageY=ak.pageY;al.target.trigger(ah,ai)}}function s(al,ak,ao,an,am){if(an){var aj=[an.seriesIndex,an.pointIndex,an.data];var ah=am.plugins.lineRenderer.highlightedSeriesIndex;if(ah!=null&&am.series[ah].highlightMouseDown){aa(am)}var ai=jQuery.Event("jqplotDataRightClick");ai.which=al.which;ai.pageX=al.pageX;ai.pageY=al.pageY;am.target.trigger(ai,aj)}}L.jqplot.LinearAxisRenderer=function(){};L.jqplot.LinearAxisRenderer.prototype.init=function(ah){this.breakPoints=null;this.breakTickLabel="&asymp;";this.drawBaseline=true;this.baselineWidth=null;this.baselineColor=null;this.forceTickAt0=false;this.forceTickAt100=false;this.tickInset=0;this.minorTicks=0;this.alignTicks=false;this._autoFormatString="";this._overrideFormatString=false;this._scalefact=1;L.extend(true,this,ah);if(this.breakPoints){if(!L.isArray(this.breakPoints)){this.breakPoints=null}else{if(this.breakPoints.length<2||this.breakPoints[1]<=this.breakPoints[0]){this.breakPoints=null}}}if(this.numberTicks!=null&&this.numberTicks<2){this.numberTicks=2}this.resetDataBounds()};L.jqplot.LinearAxisRenderer.prototype.draw=function(ah,ao){if(this.show){this.renderer.createTicks.call(this,ao);var an=0;var ai;if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=L(document.createElement("div"));this._elem.addClass("jqplot-axis jqplot-"+this.name);this._elem.css("position","absolute");if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){var am=this._label.draw(ah,ao);am.appendTo(this._elem);am=null}var al=this._ticks;var ak;for(var aj=0;aj<al.length;aj++){ak=al[aj];if(ak.show&&ak.showLabel&&(!ak.isMinorTick||this.showMinorTicks)){this._elem.append(ak.draw(ah,ao))}}ak=null;al=null}return this._elem};L.jqplot.LinearAxisRenderer.prototype.reset=function(){this.min=this._options.min;this.max=this._options.max;this.tickInterval=this._options.tickInterval;this.numberTicks=this._options.numberTicks;this._autoFormatString="";if(this._overrideFormatString&&this.tickOptions&&this.tickOptions.formatString){this.tickOptions.formatString=""}};L.jqplot.LinearAxisRenderer.prototype.set=function(){var ao=0;var aj;var ai=0;var an=0;var ah=(this._label==null)?false:this._label.show;if(this.show){var am=this._ticks;var al;for(var ak=0;ak<am.length;ak++){al=am[ak];if(!al._breakTick&&al.show&&al.showLabel&&(!al.isMinorTick||this.showMinorTicks)){if(this.name=="xaxis"||this.name=="x2axis"){aj=al._elem.outerHeight(true)}else{aj=al._elem.outerWidth(true)}if(aj>ao){ao=aj}}}al=null;am=null;if(ah){ai=this._label._elem.outerWidth(true);an=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){ao=ao+an;this._elem.css({height:ao+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){ao=ao+an;this._elem.css({height:ao+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){ao=ao+ai;this._elem.css({width:ao+"px",left:"0px",top:"0px"});if(ah&&this._label.constructor==L.jqplot.AxisLabelRenderer){this._label._elem.css("width",ai+"px")}}else{ao=ao+ai;this._elem.css({width:ao+"px",right:"0px",top:"0px"});if(ah&&this._label.constructor==L.jqplot.AxisLabelRenderer){this._label._elem.css("width",ai+"px")}}}}}};L.jqplot.LinearAxisRenderer.prototype.createTicks=function(aj){var aT=this._ticks;var aK=this.ticks;var az=this.name;var aB=this._dataBounds;var ah=(this.name.charAt(0)==="x")?this._plotDimensions.width:this._plotDimensions.height;var an;var a6,aI;var ap,ao;var a4,a0;var aH=this.min;var a5=this.max;var aW=this.numberTicks;var ba=this.tickInterval;var am=30;this._scalefact=(Math.max(ah,am+1)-am)/300;if(aK.length){for(a0=0;a0<aK.length;a0++){var aO=aK[a0];var aU=new this.tickRenderer(this.tickOptions);if(L.isArray(aO)){aU.value=aO[0];if(this.breakPoints){if(aO[0]==this.breakPoints[0]){aU.label=this.breakTickLabel;aU._breakTick=true;aU.showGridline=false;aU.showMark=false}else{if(aO[0]>this.breakPoints[0]&&aO[0]<=this.breakPoints[1]){aU.show=false;aU.showGridline=false;aU.label=aO[1]}else{aU.label=aO[1]}}}else{aU.label=aO[1]}aU.setTick(aO[0],this.name);this._ticks.push(aU)}else{if(L.isPlainObject(aO)){L.extend(true,aU,aO);aU.axis=this.name;this._ticks.push(aU)}else{aU.value=aO;if(this.breakPoints){if(aO==this.breakPoints[0]){aU.label=this.breakTickLabel;aU._breakTick=true;aU.showGridline=false;aU.showMark=false}else{if(aO>this.breakPoints[0]&&aO<=this.breakPoints[1]){aU.show=false;aU.showGridline=false}}}aU.setTick(aO,this.name);this._ticks.push(aU)}}}this.numberTicks=aK.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value;this.tickInterval=(this.max-this.min)/(this.numberTicks-1)}else{if(az=="xaxis"||az=="x2axis"){ah=this._plotDimensions.width}else{ah=this._plotDimensions.height}var ax=this.numberTicks;if(this.alignTicks){if(this.name==="x2axis"&&aj.axes.xaxis.show){ax=aj.axes.xaxis.numberTicks}else{if(this.name.charAt(0)==="y"&&this.name!=="yaxis"&&this.name!=="yMidAxis"&&aj.axes.yaxis.show){ax=aj.axes.yaxis.numberTicks}}}a6=((this.min!=null)?this.min:aB.min);aI=((this.max!=null)?this.max:aB.max);var av=aI-a6;var aS,ay;var at;if(this.tickOptions==null||!this.tickOptions.formatString){this._overrideFormatString=true}if(this.min==null||this.max==null&&this.tickInterval==null&&!this.autoscale){if(this.forceTickAt0){if(a6>0){a6=0}if(aI<0){aI=0}}if(this.forceTickAt100){if(a6>100){a6=100}if(aI<100){aI=100}}var aE=false,a1=false;if(this.min!=null){aE=true}else{if(this.max!=null){a1=true}}var aP=L.jqplot.LinearTickGenerator(a6,aI,this._scalefact,ax,aE,a1);var aw=(this.min!=null)?a6:a6+av*(this.padMin-1);var aQ=(this.max!=null)?aI:aI-av*(this.padMax-1);if(a6<aw||aI>aQ){aw=(this.min!=null)?a6:a6-av*(this.padMin-1);aQ=(this.max!=null)?aI:aI+av*(this.padMax-1);aP=L.jqplot.LinearTickGenerator(aw,aQ,this._scalefact,ax,aE,a1)}this.min=aP[0];this.max=aP[1];this.numberTicks=aP[2];this._autoFormatString=aP[3];this.tickInterval=aP[4]}else{if(a6==aI){var ai=0.05;if(a6>0){ai=Math.max(Math.log(a6)/Math.LN10,0.05)}a6-=ai;aI+=ai}if(this.autoscale&&this.min==null&&this.max==null){var ak,al,ar;var aC=false;var aN=false;var aA={min:null,max:null,average:null,stddev:null};for(var a0=0;a0<this._series.length;a0++){var aV=this._series[a0];var aD=(aV.fillAxis=="x")?aV._xaxis.name:aV._yaxis.name;if(this.name==aD){var aR=aV._plotValues[aV.fillAxis];var aG=aR[0];var a2=aR[0];for(var aZ=1;aZ<aR.length;aZ++){if(aR[aZ]<aG){aG=aR[aZ]}else{if(aR[aZ]>a2){a2=aR[aZ]}}}var au=(a2-aG)/a2;if(aV.renderer.constructor==L.jqplot.BarRenderer){if(aG>=0&&(aV.fillToZero||au>0.1)){aC=true}else{aC=false;if(aV.fill&&aV.fillToZero&&aG<0&&a2>0){aN=true}else{aN=false}}}else{if(aV.fill){if(aG>=0&&(aV.fillToZero||au>0.1)){aC=true}else{if(aG<0&&a2>0&&aV.fillToZero){aC=false;aN=true}else{aC=false;aN=false}}}else{if(aG<0){aC=false}}}}}if(aC){this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing);this.min=0;aH=0;al=aI/(this.numberTicks-1);at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)));if(al/at==parseInt(al/at,10)){al+=at}this.tickInterval=Math.ceil(al/at)*at;this.max=this.tickInterval*(this.numberTicks-1)}else{if(aN){this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing);var aJ=Math.ceil(Math.abs(a6)/av*(this.numberTicks-1));var a9=this.numberTicks-1-aJ;al=Math.max(Math.abs(a6/aJ),Math.abs(aI/a9));at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)));this.tickInterval=Math.ceil(al/at)*at;this.max=this.tickInterval*a9;this.min=-this.tickInterval*aJ}else{if(this.numberTicks==null){if(this.tickInterval){this.numberTicks=3+Math.ceil(av/this.tickInterval)}else{this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing)}}if(this.tickInterval==null){al=av/(this.numberTicks-1);if(al<1){at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)))}else{at=1}this.tickInterval=Math.ceil(al*at*this.pad)/at}else{at=1/this.tickInterval}ak=this.tickInterval*(this.numberTicks-1);ar=(ak-av)/2;if(this.min==null){this.min=Math.floor(at*(a6-ar))/at}if(this.max==null){this.max=this.min+ak}}}var aF=L.jqplot.getSignificantFigures(this.tickInterval);var aM;if(aF.digitsLeft>=aF.significantDigits){aM="%d"}else{var at=Math.max(0,5-aF.digitsLeft);at=Math.min(at,aF.digitsRight);aM="%."+at+"f"}this._autoFormatString=aM}else{aS=(this.min!=null)?this.min:a6-av*(this.padMin-1);ay=(this.max!=null)?this.max:aI+av*(this.padMax-1);av=ay-aS;if(this.numberTicks==null){if(this.tickInterval!=null){this.numberTicks=Math.ceil((ay-aS)/this.tickInterval)+1}else{if(ah>100){this.numberTicks=parseInt(3+(ah-100)/75,10)}else{this.numberTicks=2}}}if(this.tickInterval==null){this.tickInterval=av/(this.numberTicks-1)}if(this.max==null){ay=aS+this.tickInterval*(this.numberTicks-1)}if(this.min==null){aS=ay-this.tickInterval*(this.numberTicks-1)}var aF=L.jqplot.getSignificantFigures(this.tickInterval);var aM;if(aF.digitsLeft>=aF.significantDigits){aM="%d"}else{var at=Math.max(0,5-aF.digitsLeft);at=Math.min(at,aF.digitsRight);aM="%."+at+"f"}this._autoFormatString=aM;this.min=aS;this.max=ay}if(this.renderer.constructor==L.jqplot.LinearAxisRenderer&&this._autoFormatString==""){av=this.max-this.min;var a7=new this.tickRenderer(this.tickOptions);var aL=a7.formatString||L.jqplot.config.defaultTickFormatString;var aL=aL.match(L.jqplot.sprintf.regex)[0];var a3=0;if(aL){if(aL.search(/[fFeEgGpP]/)>-1){var aY=aL.match(/\%\.(\d{0,})?[eEfFgGpP]/);if(aY){a3=parseInt(aY[1],10)}else{a3=6}}else{if(aL.search(/[di]/)>-1){a3=0}}var aq=Math.pow(10,-a3);if(this.tickInterval<aq){if(aW==null&&ba==null){this.tickInterval=aq;if(a5==null&&aH==null){this.min=Math.floor(this._dataBounds.min/aq)*aq;if(this.min==this._dataBounds.min){this.min=this._dataBounds.min-this.tickInterval}this.max=Math.ceil(this._dataBounds.max/aq)*aq;if(this.max==this._dataBounds.max){this.max=this._dataBounds.max+this.tickInterval}var aX=(this.max-this.min)/this.tickInterval;aX=aX.toFixed(11);aX=Math.ceil(aX);this.numberTicks=aX+1}else{if(a5==null){var aX=(this._dataBounds.max-this.min)/this.tickInterval;aX=aX.toFixed(11);this.numberTicks=Math.ceil(aX)+2;this.max=this.min+this.tickInterval*(this.numberTicks-1)}else{if(aH==null){var aX=(this.max-this._dataBounds.min)/this.tickInterval;aX=aX.toFixed(11);this.numberTicks=Math.ceil(aX)+2;this.min=this.max-this.tickInterval*(this.numberTicks-1)}else{this.numberTicks=Math.ceil((a5-aH)/this.tickInterval)+1;this.min=Math.floor(aH*Math.pow(10,a3))/Math.pow(10,a3);this.max=Math.ceil(a5*Math.pow(10,a3))/Math.pow(10,a3);this.numberTicks=Math.ceil((this.max-this.min)/this.tickInterval)+1}}}}}}}}if(this._overrideFormatString&&this._autoFormatString!=""){this.tickOptions=this.tickOptions||{};this.tickOptions.formatString=this._autoFormatString}var aU,a8;for(var a0=0;a0<this.numberTicks;a0++){a4=this.min+a0*this.tickInterval;aU=new this.tickRenderer(this.tickOptions);aU.setTick(a4,this.name);this._ticks.push(aU);if(a0<this.numberTicks-1){for(var aZ=0;aZ<this.minorTicks;aZ++){a4+=this.tickInterval/(this.minorTicks+1);a8=L.extend(true,{},this.tickOptions,{name:this.name,value:a4,label:"",isMinorTick:true});aU=new this.tickRenderer(a8);this._ticks.push(aU)}}aU=null}}if(this.tickInset){this.min=this.min-this.tickInset*this.tickInterval;this.max=this.max+this.tickInset*this.tickInterval}aT=null};L.jqplot.LinearAxisRenderer.prototype.resetTickValues=function(aj){if(L.isArray(aj)&&aj.length==this._ticks.length){var ai;for(var ah=0;ah<aj.length;ah++){ai=this._ticks[ah];ai.value=aj[ah];ai.label=ai.formatter(ai.formatString,aj[ah]);ai.label=ai.prefix+ai.label;ai._elem.html(ai.label)}ai=null;this.min=L.jqplot.arrayMin(aj);this.max=L.jqplot.arrayMax(aj);this.pack()}};L.jqplot.LinearAxisRenderer.prototype.pack=function(aj,ai){aj=aj||{};ai=ai||this._offsets;var ay=this._ticks;var au=this.max;var at=this.min;var ao=ai.max;var am=ai.min;var aq=(this._label==null)?false:this._label.show;for(var ar in aj){this._elem.css(ar,aj[ar])}this._offsets=ai;var ak=ao-am;var al=au-at;if(this.breakPoints){al=al-this.breakPoints[1]+this.breakPoints[0];this.p2u=function(aA){return(aA-am)*al/ak+at};this.u2p=function(aA){if(aA>this.breakPoints[0]&&aA<this.breakPoints[1]){aA=this.breakPoints[0]}if(aA<=this.breakPoints[0]){return(aA-at)*ak/al+am}else{return(aA-this.breakPoints[1]+this.breakPoints[0]-at)*ak/al+am}};if(this.name.charAt(0)=="x"){this.series_u2p=function(aA){if(aA>this.breakPoints[0]&&aA<this.breakPoints[1]){aA=this.breakPoints[0]}if(aA<=this.breakPoints[0]){return(aA-at)*ak/al}else{return(aA-this.breakPoints[1]+this.breakPoints[0]-at)*ak/al}};this.series_p2u=function(aA){return aA*al/ak+at}}else{this.series_u2p=function(aA){if(aA>this.breakPoints[0]&&aA<this.breakPoints[1]){aA=this.breakPoints[0]}if(aA>=this.breakPoints[1]){return(aA-au)*ak/al}else{return(aA+this.breakPoints[1]-this.breakPoints[0]-au)*ak/al}};this.series_p2u=function(aA){return aA*al/ak+au}}}else{this.p2u=function(aA){return(aA-am)*al/ak+at};this.u2p=function(aA){return(aA-at)*ak/al+am};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(aA){return(aA-at)*ak/al};this.series_p2u=function(aA){return aA*al/ak+at}}else{this.series_u2p=function(aA){return(aA-au)*ak/al};this.series_p2u=function(aA){return aA*al/ak+au}}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(var av=0;av<ay.length;av++){var ap=ay[av];if(ap.show&&ap.showLabel){var ah;if(ap.constructor==L.jqplot.CanvasAxisTickRenderer&&ap.angle){var ax=(this.name=="xaxis")?1:-1;switch(ap.labelPosition){case"auto":if(ax*ap.angle<0){ah=-ap.getWidth()+ap._textRenderer.height*Math.sin(-ap._textRenderer.angle)/2}else{ah=-ap._textRenderer.height*Math.sin(ap._textRenderer.angle)/2}break;case"end":ah=-ap.getWidth()+ap._textRenderer.height*Math.sin(-ap._textRenderer.angle)/2;break;case"start":ah=-ap._textRenderer.height*Math.sin(ap._textRenderer.angle)/2;break;case"middle":ah=-ap.getWidth()/2+ap._textRenderer.height*Math.sin(-ap._textRenderer.angle)/2;break;default:ah=-ap.getWidth()/2+ap._textRenderer.height*Math.sin(-ap._textRenderer.angle)/2;break}}else{ah=-ap.getWidth()/2}var az=this.u2p(ap.value)+ah+"px";ap._elem.css("left",az);ap.pack()}}if(aq){var an=this._label._elem.outerWidth(true);this._label._elem.css("left",am+ak/2-an/2+"px");if(this.name=="xaxis"){this._label._elem.css("bottom","0px")}else{this._label._elem.css("top","0px")}this._label.pack()}}else{for(var av=0;av<ay.length;av++){var ap=ay[av];if(ap.show&&ap.showLabel){var ah;if(ap.constructor==L.jqplot.CanvasAxisTickRenderer&&ap.angle){var ax=(this.name=="yaxis")?1:-1;switch(ap.labelPosition){case"auto":case"end":if(ax*ap.angle<0){ah=-ap._textRenderer.height*Math.cos(-ap._textRenderer.angle)/2}else{ah=-ap.getHeight()+ap._textRenderer.height*Math.cos(ap._textRenderer.angle)/2}break;case"start":if(ap.angle>0){ah=-ap._textRenderer.height*Math.cos(-ap._textRenderer.angle)/2}else{ah=-ap.getHeight()+ap._textRenderer.height*Math.cos(ap._textRenderer.angle)/2}break;case"middle":ah=-ap.getHeight()/2;break;default:ah=-ap.getHeight()/2;break}}else{ah=-ap.getHeight()/2}var az=this.u2p(ap.value)+ah+"px";ap._elem.css("top",az);ap.pack()}}if(aq){var aw=this._label._elem.outerHeight(true);this._label._elem.css("top",ao-ak/2-aw/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{this._label._elem.css("right","0px")}this._label.pack()}}}ay=null};function i(ai){var ah;ai=Math.abs(ai);if(ai>=10){ah="%d"}else{if(ai>1){if(ai===parseInt(ai,10)){ah="%d"}else{ah="%.1f"}}else{var aj=-Math.floor(Math.log(ai)/Math.LN10);ah="%."+aj+"f"}}return ah}var b=[0.1,0.2,0.3,0.4,0.5,0.8,1,2,3,4,5];var c=function(ai){var ah=b.indexOf(ai);if(ah>0){return b[ah-1]}else{return b[b.length-1]/100}};var k=function(ai){var ah=b.indexOf(ai);if(ah<b.length-1){return b[ah+1]}else{return b[0]*100}};function d(al,au,at){var aq=Math.floor(at/2);var ai=Math.ceil(at*1.5);var ak=Number.MAX_VALUE;var ah=(au-al);var ax;var ap;var ar;var ay=L.jqplot.getSignificantFigures;var aw;var an;var ao;var av;for(var am=0,aj=ai-aq+1;am<aj;am++){ao=aq+am;ax=ah/(ao-1);ap=ay(ax);ax=Math.abs(at-ao)+ap.digitsRight;if(ax<ak){ak=ax;ar=ao;av=ap.digitsRight}else{if(ax===ak){if(ap.digitsRight<av){ar=ao;av=ap.digitsRight}}}}aw=Math.max(av,Math.max(ay(al).digitsRight,ay(au).digitsRight));if(aw===0){an="%d"}else{an="%."+aw+"f"}ax=ah/(ar-1);return[al,au,ar,an,ax]}function W(ai,al){al=al||7;var ak=ai/(al-1);var aj=Math.pow(10,Math.floor(Math.log(ak)/Math.LN10));var am=ak/aj;var ah;if(aj<1){if(am>5){ah=10*aj}else{if(am>2){ah=5*aj}else{if(am>1){ah=2*aj}else{ah=aj}}}}else{if(am>5){ah=10*aj}else{if(am>4){ah=5*aj}else{if(am>3){ah=4*aj}else{if(am>2){ah=3*aj}else{if(am>1){ah=2*aj}else{ah=aj}}}}}}return ah}function Q(ai,ah){ah=ah||1;var ak=Math.floor(Math.log(ai)/Math.LN10);var am=Math.pow(10,ak);var al=ai/am;var aj;al=al/ah;if(al<=0.38){aj=0.1}else{if(al<=1.6){aj=0.2}else{if(al<=4){aj=0.5}else{if(al<=8){aj=1}else{if(al<=16){aj=2}else{aj=5}}}}}return aj*am}function x(aj,ai){var al=Math.floor(Math.log(aj)/Math.LN10);var an=Math.pow(10,al);var am=aj/an;var ah;var ak;am=am/ai;if(am<=0.38){ak=0.1}else{if(am<=1.6){ak=0.2}else{if(am<=4){ak=0.5}else{if(am<=8){ak=1}else{if(am<=16){ak=2}else{ak=5}}}}}ah=ak*an;return[ah,ak,an]}L.jqplot.LinearTickGenerator=function(an,aq,aj,ak,ao,ar){ao=(ao===null)?false:ao;ar=(ar===null||ao)?false:ar;if(an===aq){aq=(aq)?0:1}aj=aj||1;if(aq<an){var at=aq;aq=an;an=at}var ai=[];var aw=Q(aq-an,aj);var av=L.jqplot.getSignificantFigures;if(ak==null){if(!ao&&!ar){ai[0]=Math.floor(an/aw)*aw;ai[1]=Math.ceil(aq/aw)*aw;ai[2]=Math.round((ai[1]-ai[0])/aw+1);ai[3]=i(aw);ai[4]=aw}else{if(ao){ai[0]=an;ai[2]=Math.ceil((aq-an)/aw+1);ai[1]=an+(ai[2]-1)*aw;var au=av(an).digitsRight;var ap=av(aw).digitsRight;if(au<ap){ai[3]=i(aw)}else{ai[3]="%."+au+"f"}ai[4]=aw}else{if(ar){ai[1]=aq;ai[2]=Math.ceil((aq-an)/aw+1);ai[0]=aq-(ai[2]-1)*aw;var al=av(aq).digitsRight;var ap=av(aw).digitsRight;if(al<ap){ai[3]=i(aw)}else{ai[3]="%."+al+"f"}ai[4]=aw}}}}else{var am=[];am[0]=Math.floor(an/aw)*aw;am[1]=Math.ceil(aq/aw)*aw;am[2]=Math.round((am[1]-am[0])/aw+1);am[3]=i(aw);am[4]=aw;if(am[2]===ak){ai=am}else{var ah=W(am[1]-am[0],ak);ai[0]=am[0];ai[2]=ak;ai[4]=ah;ai[3]=i(ah);ai[1]=ai[0]+(ai[2]-1)*ai[4]}}return ai};L.jqplot.LinearTickGenerator.bestLinearInterval=Q;L.jqplot.LinearTickGenerator.bestInterval=W;L.jqplot.LinearTickGenerator.bestLinearComponents=x;L.jqplot.LinearTickGenerator.bestConstrainedInterval=d;L.jqplot.MarkerRenderer=function(ah){this.show=true;this.style="filledCircle";this.lineWidth=2;this.size=9;this.color="#666666";this.shadow=true;this.shadowAngle=45;this.shadowOffset=1;this.shadowDepth=3;this.shadowAlpha="0.07";this.shadowRenderer=new L.jqplot.ShadowRenderer();this.shapeRenderer=new L.jqplot.ShapeRenderer();L.extend(true,this,ah)};L.jqplot.MarkerRenderer.prototype.init=function(ah){L.extend(true,this,ah);var aj={angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,lineWidth:this.lineWidth,depth:this.shadowDepth,closePath:true};if(this.style.indexOf("filled")!=-1){aj.fill=true}if(this.style.indexOf("ircle")!=-1){aj.isarc=true;aj.closePath=false}this.shadowRenderer.init(aj);var ai={fill:false,isarc:false,strokeStyle:this.color,fillStyle:this.color,lineWidth:this.lineWidth,closePath:true};if(this.style.indexOf("filled")!=-1){ai.fill=true}if(this.style.indexOf("ircle")!=-1){ai.isarc=true;ai.closePath=false}this.shapeRenderer.init(ai)};L.jqplot.MarkerRenderer.prototype.drawDiamond=function(aj,ai,am,al,ao){var ah=1.2;var ap=this.size/2/ah;var an=this.size/2*ah;var ak=[[aj-ap,ai],[aj,ai+an],[aj+ap,ai],[aj,ai-an]];if(this.shadow){this.shadowRenderer.draw(am,ak)}this.shapeRenderer.draw(am,ak,ao)};L.jqplot.MarkerRenderer.prototype.drawPlus=function(ak,aj,an,am,aq){var ai=1;var ar=this.size/2*ai;var ao=this.size/2*ai;var ap=[[ak,aj-ao],[ak,aj+ao]];var al=[[ak+ar,aj],[ak-ar,aj]];var ah=L.extend(true,{},this.options,{closePath:false});if(this.shadow){this.shadowRenderer.draw(an,ap,{closePath:false});this.shadowRenderer.draw(an,al,{closePath:false})}this.shapeRenderer.draw(an,ap,ah);this.shapeRenderer.draw(an,al,ah)};L.jqplot.MarkerRenderer.prototype.drawX=function(ak,aj,an,am,aq){var ai=1;var ar=this.size/2*ai;var ao=this.size/2*ai;var ah=L.extend(true,{},this.options,{closePath:false});var ap=[[ak-ar,aj-ao],[ak+ar,aj+ao]];var al=[[ak-ar,aj+ao],[ak+ar,aj-ao]];if(this.shadow){this.shadowRenderer.draw(an,ap,{closePath:false});this.shadowRenderer.draw(an,al,{closePath:false})}this.shapeRenderer.draw(an,ap,ah);this.shapeRenderer.draw(an,al,ah)};L.jqplot.MarkerRenderer.prototype.drawDash=function(aj,ai,am,al,ao){var ah=1;var ap=this.size/2*ah;var an=this.size/2*ah;var ak=[[aj-ap,ai],[aj+ap,ai]];if(this.shadow){this.shadowRenderer.draw(am,ak)}this.shapeRenderer.draw(am,ak,ao)};L.jqplot.MarkerRenderer.prototype.drawLine=function(am,al,ah,ak,ai){var aj=[am,al];if(this.shadow){this.shadowRenderer.draw(ah,aj)}this.shapeRenderer.draw(ah,aj,ai)};L.jqplot.MarkerRenderer.prototype.drawSquare=function(aj,ai,am,al,ao){var ah=1;var ap=this.size/2/ah;var an=this.size/2*ah;var ak=[[aj-ap,ai-an],[aj-ap,ai+an],[aj+ap,ai+an],[aj+ap,ai-an]];if(this.shadow){this.shadowRenderer.draw(am,ak)}this.shapeRenderer.draw(am,ak,ao)};L.jqplot.MarkerRenderer.prototype.drawCircle=function(ai,ao,ak,an,al){var ah=this.size/2;var aj=2*Math.PI;var am=[ai,ao,ah,0,aj,true];if(this.shadow){this.shadowRenderer.draw(ak,am)}this.shapeRenderer.draw(ak,am,al)};L.jqplot.MarkerRenderer.prototype.draw=function(ah,ak,ai,aj){aj=aj||{};if(aj.show==null||aj.show!=false){if(aj.color&&!aj.fillStyle){aj.fillStyle=aj.color}if(aj.color&&!aj.strokeStyle){aj.strokeStyle=aj.color}switch(this.style){case"diamond":this.drawDiamond(ah,ak,ai,false,aj);break;case"filledDiamond":this.drawDiamond(ah,ak,ai,true,aj);break;case"circle":this.drawCircle(ah,ak,ai,false,aj);break;case"filledCircle":this.drawCircle(ah,ak,ai,true,aj);break;case"square":this.drawSquare(ah,ak,ai,false,aj);break;case"filledSquare":this.drawSquare(ah,ak,ai,true,aj);break;case"x":this.drawX(ah,ak,ai,true,aj);break;case"plus":this.drawPlus(ah,ak,ai,true,aj);break;case"dash":this.drawDash(ah,ak,ai,true,aj);break;case"line":this.drawLine(ah,ak,ai,false,aj);break;default:this.drawDiamond(ah,ak,ai,false,aj);break}}};L.jqplot.ShadowRenderer=function(ah){this.angle=45;this.offset=1;this.alpha=0.07;this.lineWidth=1.5;this.lineJoin="miter";this.lineCap="round";this.closePath=false;this.fill=false;this.depth=3;this.strokeStyle="rgba(0,0,0,0.1)";this.isarc=false;L.extend(true,this,ah)};L.jqplot.ShadowRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.ShadowRenderer.prototype.draw=function(av,at,ax){av.save();var ah=(ax!=null)?ax:{};var au=(ah.fill!=null)?ah.fill:this.fill;var ap=(ah.fillRect!=null)?ah.fillRect:this.fillRect;var ao=(ah.closePath!=null)?ah.closePath:this.closePath;var al=(ah.offset!=null)?ah.offset:this.offset;var aj=(ah.alpha!=null)?ah.alpha:this.alpha;var an=(ah.depth!=null)?ah.depth:this.depth;var aw=(ah.isarc!=null)?ah.isarc:this.isarc;var aq=(ah.linePattern!=null)?ah.linePattern:this.linePattern;av.lineWidth=(ah.lineWidth!=null)?ah.lineWidth:this.lineWidth;av.lineJoin=(ah.lineJoin!=null)?ah.lineJoin:this.lineJoin;av.lineCap=(ah.lineCap!=null)?ah.lineCap:this.lineCap;av.strokeStyle=ah.strokeStyle||this.strokeStyle||"rgba(0,0,0,"+aj+")";av.fillStyle=ah.fillStyle||this.fillStyle||"rgba(0,0,0,"+aj+")";for(var ak=0;ak<an;ak++){var ar=L.jqplot.LinePattern(av,aq);av.translate(Math.cos(this.angle*Math.PI/180)*al,Math.sin(this.angle*Math.PI/180)*al);ar.beginPath();if(aw){av.arc(at[0],at[1],at[2],at[3],at[4],true)}else{if(ap){if(ap){av.fillRect(at[0],at[1],at[2],at[3])}}else{if(at&&at.length){var ai=true;for(var am=0;am<at.length;am++){if(at[am][0]!=null&&at[am][1]!=null){if(ai){ar.moveTo(at[am][0],at[am][1]);ai=false}else{ar.lineTo(at[am][0],at[am][1])}}else{ai=true}}}}}if(ao){ar.closePath()}if(au){av.fill()}else{av.stroke()}}av.restore()};L.jqplot.ShapeRenderer=function(ah){this.lineWidth=1.5;this.linePattern="solid";this.lineJoin="miter";this.lineCap="round";this.closePath=false;this.fill=false;this.isarc=false;this.fillRect=false;this.strokeRect=false;this.clearRect=false;this.strokeStyle="#999999";this.fillStyle="#999999";L.extend(true,this,ah)};L.jqplot.ShapeRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.ShapeRenderer.prototype.draw=function(at,aq,av){at.save();var ah=(av!=null)?av:{};var ar=(ah.fill!=null)?ah.fill:this.fill;var am=(ah.closePath!=null)?ah.closePath:this.closePath;var an=(ah.fillRect!=null)?ah.fillRect:this.fillRect;var ak=(ah.strokeRect!=null)?ah.strokeRect:this.strokeRect;var ai=(ah.clearRect!=null)?ah.clearRect:this.clearRect;var au=(ah.isarc!=null)?ah.isarc:this.isarc;var ao=(ah.linePattern!=null)?ah.linePattern:this.linePattern;var ap=L.jqplot.LinePattern(at,ao);at.lineWidth=ah.lineWidth||this.lineWidth;at.lineJoin=ah.lineJoin||this.lineJoin;at.lineCap=ah.lineCap||this.lineCap;at.strokeStyle=(ah.strokeStyle||ah.color)||this.strokeStyle;at.fillStyle=ah.fillStyle||this.fillStyle;at.beginPath();if(au){at.arc(aq[0],aq[1],aq[2],aq[3],aq[4],true);if(am){at.closePath()}if(ar){at.fill()}else{at.stroke()}at.restore();return}else{if(ai){at.clearRect(aq[0],aq[1],aq[2],aq[3]);at.restore();return}else{if(an||ak){if(an){at.fillRect(aq[0],aq[1],aq[2],aq[3])}if(ak){at.strokeRect(aq[0],aq[1],aq[2],aq[3]);at.restore();return}}else{if(aq&&aq.length){var aj=true;for(var al=0;al<aq.length;al++){if(aq[al][0]!=null&&aq[al][1]!=null){if(aj){ap.moveTo(aq[al][0],aq[al][1]);aj=false}else{ap.lineTo(aq[al][0],aq[al][1])}}else{aj=true}}if(am){ap.closePath()}if(ar){at.fill()}else{at.stroke()}}}}}at.restore()};L.jqplot.TableLegendRenderer=function(){};L.jqplot.TableLegendRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.TableLegendRenderer.prototype.addrow=function(aq,ak,ah,ao){var al=(ah)?this.rowSpacing+"px":"0px";var ap;var aj;var ai;var an;var am;ai=document.createElement("tr");ap=L(ai);ap.addClass("jqplot-table-legend");ai=null;if(ao){ap.prependTo(this._elem)}else{ap.appendTo(this._elem)}if(this.showSwatches){aj=L(document.createElement("td"));aj.addClass("jqplot-table-legend jqplot-table-legend-swatch");aj.css({textAlign:"center",paddingTop:al});an=L(document.createElement("div"));an.addClass("jqplot-table-legend-swatch-outline");am=L(document.createElement("div"));am.addClass("jqplot-table-legend-swatch");am.css({backgroundColor:ak,borderColor:ak});ap.append(aj.append(an.append(am)))}if(this.showLabels){aj=L(document.createElement("td"));aj.addClass("jqplot-table-legend jqplot-table-legend-label");aj.css("paddingTop",al);ap.append(aj);if(this.escapeHtml){aj.text(aq)}else{aj.html(aq)}}aj=null;an=null;am=null;ap=null;ai=null};L.jqplot.TableLegendRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}if(this.show){var am=this._series;var ai=document.createElement("table");this._elem=L(ai);this._elem.addClass("jqplot-table-legend");var ar={position:"absolute"};if(this.background){ar.background=this.background}if(this.border){ar.border=this.border}if(this.fontSize){ar.fontSize=this.fontSize}if(this.fontFamily){ar.fontFamily=this.fontFamily}if(this.textColor){ar.textColor=this.textColor}if(this.marginTop!=null){ar.marginTop=this.marginTop}if(this.marginBottom!=null){ar.marginBottom=this.marginBottom}if(this.marginLeft!=null){ar.marginLeft=this.marginLeft}if(this.marginRight!=null){ar.marginRight=this.marginRight}var ah=false,ao=false,aq;for(var an=0;an<am.length;an++){aq=am[an];if(aq._stack||aq.renderer.constructor==L.jqplot.BezierCurveRenderer){ao=true}if(aq.show&&aq.showLabel){var al=this.labels[an]||aq.label.toString();if(al){var aj=aq.color;if(ao&&an<am.length-1){ah=true}else{if(ao&&an==am.length-1){ah=false}}this.renderer.addrow.call(this,al,aj,ah,ao);ah=true}for(var ak=0;ak<L.jqplot.addLegendRowHooks.length;ak++){var ap=L.jqplot.addLegendRowHooks[ak].call(this,aq);if(ap){this.renderer.addrow.call(this,ap.label,ap.color,ah);ah=true}}al=null}}}return this._elem};L.jqplot.TableLegendRenderer.prototype.pack=function(aj){if(this.show){if(this.placement=="insideGrid"){switch(this.location){case"nw":var ai=aj.left;var ah=aj.top;this._elem.css("left",ai);this._elem.css("top",ah);break;case"n":var ai=(aj.left+(this._plotDimensions.width-aj.right))/2-this.getWidth()/2;var ah=aj.top;this._elem.css("left",ai);this._elem.css("top",ah);break;case"ne":var ai=aj.right;var ah=aj.top;this._elem.css({right:ai,top:ah});break;case"e":var ai=aj.right;var ah=(aj.top+(this._plotDimensions.height-aj.bottom))/2-this.getHeight()/2;this._elem.css({right:ai,top:ah});break;case"se":var ai=aj.right;var ah=aj.bottom;this._elem.css({right:ai,bottom:ah});break;case"s":var ai=(aj.left+(this._plotDimensions.width-aj.right))/2-this.getWidth()/2;var ah=aj.bottom;this._elem.css({left:ai,bottom:ah});break;case"sw":var ai=aj.left;var ah=aj.bottom;this._elem.css({left:ai,bottom:ah});break;case"w":var ai=aj.left;var ah=(aj.top+(this._plotDimensions.height-aj.bottom))/2-this.getHeight()/2;this._elem.css({left:ai,top:ah});break;default:var ai=aj.right;var ah=aj.bottom;this._elem.css({right:ai,bottom:ah});break}}else{if(this.placement=="outside"){switch(this.location){case"nw":var ai=this._plotDimensions.width-aj.left;var ah=aj.top;this._elem.css("right",ai);this._elem.css("top",ah);break;case"n":var ai=(aj.left+(this._plotDimensions.width-aj.right))/2-this.getWidth()/2;var ah=this._plotDimensions.height-aj.top;this._elem.css("left",ai);this._elem.css("bottom",ah);break;case"ne":var ai=this._plotDimensions.width-aj.right;var ah=aj.top;this._elem.css({left:ai,top:ah});break;case"e":var ai=this._plotDimensions.width-aj.right;var ah=(aj.top+(this._plotDimensions.height-aj.bottom))/2-this.getHeight()/2;this._elem.css({left:ai,top:ah});break;case"se":var ai=this._plotDimensions.width-aj.right;var ah=aj.bottom;this._elem.css({left:ai,bottom:ah});break;case"s":var ai=(aj.left+(this._plotDimensions.width-aj.right))/2-this.getWidth()/2;var ah=this._plotDimensions.height-aj.bottom;this._elem.css({left:ai,top:ah});break;case"sw":var ai=this._plotDimensions.width-aj.left;var ah=aj.bottom;this._elem.css({right:ai,bottom:ah});break;case"w":var ai=this._plotDimensions.width-aj.left;var ah=(aj.top+(this._plotDimensions.height-aj.bottom))/2-this.getHeight()/2;this._elem.css({right:ai,top:ah});break;default:var ai=aj.right;var ah=aj.bottom;this._elem.css({right:ai,bottom:ah});break}}else{switch(this.location){case"nw":this._elem.css({left:0,top:aj.top});break;case"n":var ai=(aj.left+(this._plotDimensions.width-aj.right))/2-this.getWidth()/2;this._elem.css({left:ai,top:aj.top});break;case"ne":this._elem.css({right:0,top:aj.top});break;case"e":var ah=(aj.top+(this._plotDimensions.height-aj.bottom))/2-this.getHeight()/2;this._elem.css({right:aj.right,top:ah});break;case"se":this._elem.css({right:aj.right,bottom:aj.bottom});break;case"s":var ai=(aj.left+(this._plotDimensions.width-aj.right))/2-this.getWidth()/2;this._elem.css({left:ai,bottom:aj.bottom});break;case"sw":this._elem.css({left:aj.left,bottom:aj.bottom});break;case"w":var ah=(aj.top+(this._plotDimensions.height-aj.bottom))/2-this.getHeight()/2;this._elem.css({left:aj.left,top:ah});break;default:this._elem.css({right:aj.right,bottom:aj.bottom});break}}}}};L.jqplot.ThemeEngine=function(){this.themes={};this.activeTheme=null};L.jqplot.ThemeEngine.prototype.init=function(){var ak=new L.jqplot.Theme({_name:"Default"});var an,ai,am;for(an in ak.target){if(an=="textColor"){ak.target[an]=this.target.css("color")}else{ak.target[an]=this.target.css(an)}}if(this.title.show&&this.title._elem){for(an in ak.title){if(an=="textColor"){ak.title[an]=this.title._elem.css("color")}else{ak.title[an]=this.title._elem.css(an)}}}for(an in ak.grid){ak.grid[an]=this.grid[an]}if(ak.grid.backgroundColor==null&&this.grid.background!=null){ak.grid.backgroundColor=this.grid.background}if(this.legend.show&&this.legend._elem){for(an in ak.legend){if(an=="textColor"){ak.legend[an]=this.legend._elem.css("color")}else{ak.legend[an]=this.legend._elem.css(an)}}}var aj;for(ai=0;ai<this.series.length;ai++){aj=this.series[ai];if(aj.renderer.constructor==L.jqplot.LineRenderer){ak.series.push(new p())}else{if(aj.renderer.constructor==L.jqplot.BarRenderer){ak.series.push(new T())}else{if(aj.renderer.constructor==L.jqplot.PieRenderer){ak.series.push(new f())}else{if(aj.renderer.constructor==L.jqplot.DonutRenderer){ak.series.push(new G())}else{if(aj.renderer.constructor==L.jqplot.FunnelRenderer){ak.series.push(new Z())}else{if(aj.renderer.constructor==L.jqplot.MeterGaugeRenderer){ak.series.push(new D())}else{ak.series.push({})}}}}}}for(an in ak.series[ai]){ak.series[ai][an]=aj[an]}}var ah,al;for(an in this.axes){al=this.axes[an];ah=ak.axes[an]=new P();ah.borderColor=al.borderColor;ah.borderWidth=al.borderWidth;if(al._ticks&&al._ticks[0]){for(am in ah.ticks){if(al._ticks[0].hasOwnProperty(am)){ah.ticks[am]=al._ticks[0][am]}else{if(al._ticks[0]._elem){ah.ticks[am]=al._ticks[0]._elem.css(am)}}}}if(al._label&&al._label.show){for(am in ah.label){if(al._label[am]){ah.label[am]=al._label[am]}else{if(al._label._elem){if(am=="textColor"){ah.label[am]=al._label._elem.css("color")}else{ah.label[am]=al._label._elem.css(am)}}}}}}this.themeEngine._add(ak);this.themeEngine.activeTheme=this.themeEngine.themes[ak._name]};L.jqplot.ThemeEngine.prototype.get=function(ah){if(!ah){return this.activeTheme}else{return this.themes[ah]}};function O(ai,ah){return ai-ah}L.jqplot.ThemeEngine.prototype.getThemeNames=function(){var ah=[];for(var ai in this.themes){ah.push(ai)}return ah.sort(O)};L.jqplot.ThemeEngine.prototype.getThemes=function(){var ai=[];var ah=[];for(var ak in this.themes){ai.push(ak)}ai.sort(O);for(var aj=0;aj<ai.length;aj++){ah.push(this.themes[ai[aj]])}return ah};L.jqplot.ThemeEngine.prototype.activate=function(av,aB){var ah=false;if(!aB&&this.activeTheme&&this.activeTheme._name){aB=this.activeTheme._name}if(!this.themes.hasOwnProperty(aB)){throw new Error("No theme of that name")}else{var am=this.themes[aB];this.activeTheme=am;var aA,at=false,ar=false;var ai=["xaxis","x2axis","yaxis","y2axis"];for(aw=0;aw<ai.length;aw++){var an=ai[aw];if(am.axesStyles.borderColor!=null){av.axes[an].borderColor=am.axesStyles.borderColor}if(am.axesStyles.borderWidth!=null){av.axes[an].borderWidth=am.axesStyles.borderWidth}}for(var az in av.axes){var ak=av.axes[az];if(ak.show){var aq=am.axes[az]||{};var ao=am.axesStyles;var al=L.jqplot.extend(true,{},aq,ao);aA=(am.axesStyles.borderColor!=null)?am.axesStyles.borderColor:al.borderColor;if(al.borderColor!=null){ak.borderColor=al.borderColor;ah=true}aA=(am.axesStyles.borderWidth!=null)?am.axesStyles.borderWidth:al.borderWidth;if(al.borderWidth!=null){ak.borderWidth=al.borderWidth;ah=true}if(ak._ticks&&ak._ticks[0]){for(var aj in al.ticks){aA=al.ticks[aj];if(aA!=null){ak.tickOptions[aj]=aA;ak._ticks=[];ah=true}}}if(ak._label&&ak._label.show){for(var aj in al.label){aA=al.label[aj];if(aA!=null){ak.labelOptions[aj]=aA;ah=true}}}}}for(var au in am.grid){if(am.grid[au]!=null){av.grid[au]=am.grid[au]}}if(!ah){av.grid.draw()}if(av.legend.show){for(au in am.legend){if(am.legend[au]!=null){av.legend[au]=am.legend[au]}}}if(av.title.show){for(au in am.title){if(am.title[au]!=null){av.title[au]=am.title[au]}}}var aw;for(aw=0;aw<am.series.length;aw++){var ap={};var ay=false;for(au in am.series[aw]){aA=(am.seriesStyles[au]!=null)?am.seriesStyles[au]:am.series[aw][au];if(aA!=null){ap[au]=aA;if(au=="color"){av.series[aw].renderer.shapeRenderer.fillStyle=aA;av.series[aw].renderer.shapeRenderer.strokeStyle=aA;av.series[aw][au]=aA}else{if((au=="lineWidth")||(au=="linePattern")){av.series[aw].renderer.shapeRenderer[au]=aA;av.series[aw][au]=aA}else{if(au=="markerOptions"){V(av.series[aw].markerOptions,aA);V(av.series[aw].markerRenderer,aA)}else{av.series[aw][au]=aA}}}ah=true}}}if(ah){av.target.empty();av.draw()}for(au in am.target){if(am.target[au]!=null){av.target.css(au,am.target[au])}}}};L.jqplot.ThemeEngine.prototype._add=function(ai,ah){if(ah){ai._name=ah}if(!ai._name){ai._name=Date.parse(new Date())}if(!this.themes.hasOwnProperty(ai._name)){this.themes[ai._name]=ai}else{throw new Error("jqplot.ThemeEngine Error: Theme already in use")}};L.jqplot.ThemeEngine.prototype.remove=function(ah){if(ah=="Default"){return false}return delete this.themes[ah]};L.jqplot.ThemeEngine.prototype.newTheme=function(ah,aj){if(typeof(ah)=="object"){aj=aj||ah;ah=null}if(aj&&aj._name){ah=aj._name}else{ah=ah||Date.parse(new Date())}var ai=this.copy(this.themes.Default._name,ah);L.jqplot.extend(ai,aj);return ai};function B(aj){if(aj==null||typeof(aj)!="object"){return aj}var ah=new aj.constructor();for(var ai in aj){ah[ai]=B(aj[ai])}return ah}L.jqplot.clone=B;function V(aj,ai){if(ai==null||typeof(ai)!="object"){return}for(var ah in ai){if(ah=="highlightColors"){aj[ah]=B(ai[ah])}if(ai[ah]!=null&&typeof(ai[ah])=="object"){if(!aj.hasOwnProperty(ah)){aj[ah]={}}V(aj[ah],ai[ah])}else{aj[ah]=ai[ah]}}}L.jqplot.merge=V;L.jqplot.extend=function(){var am=arguments[0]||{},ak=1,al=arguments.length,ah=false,aj;if(typeof am==="boolean"){ah=am;am=arguments[1]||{};ak=2}if(typeof am!=="object"&&!toString.call(am)==="[object Function]"){am={}}for(;ak<al;ak++){if((aj=arguments[ak])!=null){for(var ai in aj){var an=am[ai],ao=aj[ai];if(am===ao){continue}if(ah&&ao&&typeof ao==="object"&&!ao.nodeType){am[ai]=L.jqplot.extend(ah,an||(ao.length!=null?[]:{}),ao)}else{if(ao!==u){am[ai]=ao}}}}}return am};L.jqplot.ThemeEngine.prototype.rename=function(ai,ah){if(ai=="Default"||ah=="Default"){throw new Error("jqplot.ThemeEngine Error: Cannot rename from/to Default")}if(this.themes.hasOwnProperty(ah)){throw new Error("jqplot.ThemeEngine Error: New name already in use.")}else{if(this.themes.hasOwnProperty(ai)){var aj=this.copy(ai,ah);this.remove(ai);return aj}}throw new Error("jqplot.ThemeEngine Error: Old name or new name invalid")};L.jqplot.ThemeEngine.prototype.copy=function(ah,aj,al){if(aj=="Default"){throw new Error("jqplot.ThemeEngine Error: Cannot copy over Default theme")}if(!this.themes.hasOwnProperty(ah)){var ai="jqplot.ThemeEngine Error: Source name invalid";throw new Error(ai)}if(this.themes.hasOwnProperty(aj)){var ai="jqplot.ThemeEngine Error: Target name invalid";throw new Error(ai)}else{var ak=B(this.themes[ah]);ak._name=aj;L.jqplot.extend(true,ak,al);this._add(ak);return ak}};L.jqplot.Theme=function(ah,ai){if(typeof(ah)=="object"){ai=ai||ah;ah=null}ah=ah||Date.parse(new Date());this._name=ah;this.target={backgroundColor:null};this.legend={textColor:null,fontFamily:null,fontSize:null,border:null,background:null};this.title={textColor:null,fontFamily:null,fontSize:null,textAlign:null};this.seriesStyles={};this.series=[];this.grid={drawGridlines:null,gridLineColor:null,gridLineWidth:null,backgroundColor:null,borderColor:null,borderWidth:null,shadow:null};this.axesStyles={label:{},ticks:{}};this.axes={};if(typeof(ai)=="string"){this._name=ai}else{if(typeof(ai)=="object"){L.jqplot.extend(true,this,ai)}}};var P=function(){this.borderColor=null;this.borderWidth=null;this.ticks=new o();this.label=new t()};var o=function(){this.show=null;this.showGridline=null;this.showLabel=null;this.showMark=null;this.size=null;this.textColor=null;this.whiteSpace=null;this.fontSize=null;this.fontFamily=null};var t=function(){this.textColor=null;this.whiteSpace=null;this.fontSize=null;this.fontFamily=null;this.fontWeight=null};var p=function(){this.color=null;this.lineWidth=null;this.linePattern=null;this.shadow=null;this.fillColor=null;this.showMarker=null;this.markerOptions=new I()};var I=function(){this.show=null;this.style=null;this.lineWidth=null;this.size=null;this.color=null;this.shadow=null};var T=function(){this.color=null;this.seriesColors=null;this.lineWidth=null;this.shadow=null;this.barPadding=null;this.barMargin=null;this.barWidth=null;this.highlightColors=null};var f=function(){this.seriesColors=null;this.padding=null;this.sliceMargin=null;this.fill=null;this.shadow=null;this.startAngle=null;this.lineWidth=null;this.highlightColors=null};var G=function(){this.seriesColors=null;this.padding=null;this.sliceMargin=null;this.fill=null;this.shadow=null;this.startAngle=null;this.lineWidth=null;this.innerDiameter=null;this.thickness=null;this.ringMargin=null;this.highlightColors=null};var Z=function(){this.color=null;this.lineWidth=null;this.shadow=null;this.padding=null;this.sectionMargin=null;this.seriesColors=null;this.highlightColors=null};var D=function(){this.padding=null;this.backgroundColor=null;this.ringColor=null;this.tickColor=null;this.ringWidth=null;this.intervalColors=null;this.intervalInnerRadius=null;this.intervalOuterRadius=null;this.hubRadius=null;this.needleThickness=null;this.needlePad=null};L.fn.jqplotChildText=function(){return L(this).contents().filter(function(){return this.nodeType==3}).text()};L.fn.jqplotGetComputedFontStyle=function(){var ak=window.getComputedStyle?window.getComputedStyle(this[0],""):this[0].currentStyle;var ai=ak["font-style"]?["font-style","font-weight","font-size","font-family"]:["fontStyle","fontWeight","fontSize","fontFamily"];var al=[];for(var aj=0;aj<ai.length;++aj){var ah=String(ak[ai[aj]]);if(ah&&ah!="normal"){al.push(ah)}}return al.join(" ")};L.fn.jqplotToImageCanvas=function(aj){aj=aj||{};var av=(aj.x_offset==null)?0:aj.x_offset;var ax=(aj.y_offset==null)?0:aj.y_offset;var al=(aj.backgroundColor==null)?"rgb(255,255,255)":aj.backgroundColor;if(L(this).width()==0||L(this).height()==0){return null}if(L.jqplot.use_excanvas){return null}var an=document.createElement("canvas");var aA=L(this).outerHeight(true);var at=L(this).outerWidth(true);var am=L(this).offset();var ao=am.left;var aq=am.top;var au=0,ar=0;var ay=["jqplot-table-legend","jqplot-xaxis-tick","jqplot-x2axis-tick","jqplot-yaxis-tick","jqplot-y2axis-tick","jqplot-y3axis-tick","jqplot-y4axis-tick","jqplot-y5axis-tick","jqplot-y6axis-tick","jqplot-y7axis-tick","jqplot-y8axis-tick","jqplot-y9axis-tick","jqplot-xaxis-label","jqplot-x2axis-label","jqplot-yaxis-label","jqplot-y2axis-label","jqplot-y3axis-label","jqplot-y4axis-label","jqplot-y5axis-label","jqplot-y6axis-label","jqplot-y7axis-label","jqplot-y8axis-label","jqplot-y9axis-label"];var ap,ah,ai,aB;for(var az=0;az<ay.length;az++){L(this).find("."+ay[az]).each(function(){ap=L(this).offset().top-aq;ah=L(this).offset().left-ao;aB=ah+L(this).outerWidth(true)+au;ai=ap+L(this).outerHeight(true)+ar;if(ah<-au){at=at-au-ah;au=-ah}if(ap<-ar){aA=aA-ar-ap;ar=-ap}if(aB>at){at=aB}if(ai>aA){aA=ai}})}an.width=at+Number(av);an.height=aA+Number(ax);var ak=an.getContext("2d");ak.save();ak.fillStyle=al;ak.fillRect(0,0,an.width,an.height);ak.restore();ak.translate(au,ar);ak.textAlign="left";ak.textBaseline="top";function aC(aE){var aF=parseInt(L(aE).css("line-height"),10);if(isNaN(aF)){aF=parseInt(L(aE).css("font-size"),10)*1.2}return aF}function aD(aF,aE,aS,aG,aO,aH){var aQ=aC(aF);var aK=L(aF).innerWidth();var aL=L(aF).innerHeight();var aN=aS.split(/\s+/);var aR=aN.length;var aP="";var aM=[];var aU=aO;var aT=aG;for(var aJ=0;aJ<aR;aJ++){aP+=aN[aJ];if(aE.measureText(aP).width>aK&&aP.length>aN[aJ].length){aM.push(aJ);aP="";aJ--}}if(aM.length===0){if(L(aF).css("textAlign")==="center"){aT=aG+(aH-aE.measureText(aP).width)/2-au}aE.fillText(aS,aT,aO)}else{aP=aN.slice(0,aM[0]).join(" ");if(L(aF).css("textAlign")==="center"){aT=aG+(aH-aE.measureText(aP).width)/2-au}aE.fillText(aP,aT,aU);aU+=aQ;for(var aJ=1,aI=aM.length;aJ<aI;aJ++){aP=aN.slice(aM[aJ-1],aM[aJ]).join(" ");if(L(aF).css("textAlign")==="center"){aT=aG+(aH-aE.measureText(aP).width)/2-au}aE.fillText(aP,aT,aU);aU+=aQ}aP=aN.slice(aM[aJ-1],aN.length).join(" ");if(L(aF).css("textAlign")==="center"){aT=aG+(aH-aE.measureText(aP).width)/2-au}aE.fillText(aP,aT,aU)}}function aw(aG,aJ,aE){var aN=aG.tagName.toLowerCase();var aF=L(aG).position();var aK=window.getComputedStyle?window.getComputedStyle(aG,""):aG.currentStyle;var aI=aJ+aF.left+parseInt(aK.marginLeft,10)+parseInt(aK.borderLeftWidth,10)+parseInt(aK.paddingLeft,10);var aL=aE+aF.top+parseInt(aK.marginTop,10)+parseInt(aK.borderTopWidth,10)+parseInt(aK.paddingTop,10);var aM=an.width;if((aN=="div"||aN=="span")&&!L(aG).hasClass("jqplot-highlighter-tooltip")){L(aG).children().each(function(){aw(this,aI,aL)});var aO=L(aG).jqplotChildText();if(aO){ak.font=L(aG).jqplotGetComputedFontStyle();ak.fillStyle=L(aG).css("color");aD(aG,ak,aO,aI,aL,aM)}}else{if(aN==="table"&&L(aG).hasClass("jqplot-table-legend")){ak.strokeStyle=L(aG).css("border-top-color");ak.fillStyle=L(aG).css("background-color");ak.fillRect(aI,aL,L(aG).innerWidth(),L(aG).innerHeight());if(parseInt(L(aG).css("border-top-width"),10)>0){ak.strokeRect(aI,aL,L(aG).innerWidth(),L(aG).innerHeight())}L(aG).find("div.jqplot-table-legend-swatch-outline").each(function(){var aU=L(this);ak.strokeStyle=aU.css("border-top-color");var aQ=aI+aU.position().left;var aR=aL+aU.position().top;ak.strokeRect(aQ,aR,aU.innerWidth(),aU.innerHeight());aQ+=parseInt(aU.css("padding-left"),10);aR+=parseInt(aU.css("padding-top"),10);var aT=aU.innerHeight()-2*parseInt(aU.css("padding-top"),10);var aP=aU.innerWidth()-2*parseInt(aU.css("padding-left"),10);var aS=aU.children("div.jqplot-table-legend-swatch");ak.fillStyle=aS.css("background-color");ak.fillRect(aQ,aR,aP,aT)});L(aG).find("td.jqplot-table-legend-label").each(function(){var aR=L(this);var aP=aI+aR.position().left;var aQ=aL+aR.position().top+parseInt(aR.css("padding-top"),10);ak.font=aR.jqplotGetComputedFontStyle();ak.fillStyle=aR.css("color");aD(aR,ak,aR.text(),aP,aQ,aM)});var aH=null}else{if(aN=="canvas"){ak.drawImage(aG,aI,aL)}}}}L(this).children().each(function(){aw(this,av,ax)});return an};L.fn.jqplotToImageStr=function(ai){var ah=L(this).jqplotToImageCanvas(ai);if(ah){return ah.toDataURL("image/png")}else{return null}};L.fn.jqplotToImageElem=function(ah){var ai=document.createElement("img");var aj=L(this).jqplotToImageStr(ah);ai.src=aj;return ai};L.fn.jqplotToImageElemStr=function(ah){var ai="<img src="+L(this).jqplotToImageStr(ah)+" />";return ai};L.fn.jqplotSaveImage=function(){var ah=L(this).jqplotToImageStr({});if(ah){window.location.href=ah.replace("image/png","image/octet-stream")}};L.fn.jqplotViewImage=function(){var ai=L(this).jqplotToImageElemStr({});var aj=L(this).jqplotToImageStr({});if(ai){var ah=window.open("");ah.document.open("image/png");ah.document.write(ai);ah.document.close();ah=null}};var ag=function(){this.syntax=ag.config.syntax;this._type="jsDate";this.proxy=new Date();this.options={};this.locale=ag.regional.getLocale();this.formatString="";this.defaultCentury=ag.config.defaultCentury;switch(arguments.length){case 0:break;case 1:if(l(arguments[0])=="[object Object]"&&arguments[0]._type!="jsDate"){var aj=this.options=arguments[0];this.syntax=aj.syntax||this.syntax;this.defaultCentury=aj.defaultCentury||this.defaultCentury;this.proxy=ag.createDate(aj.date)}else{this.proxy=ag.createDate(arguments[0])}break;default:var ah=[];for(var ai=0;ai<arguments.length;ai++){ah.push(arguments[ai])}this.proxy=new Date();this.proxy.setFullYear.apply(this.proxy,ah.slice(0,3));if(ah.slice(3).length){this.proxy.setHours.apply(this.proxy,ah.slice(3))}break}};ag.config={defaultLocale:"en",syntax:"perl",defaultCentury:1900};ag.prototype.add=function(aj,ai){var ah=E[ai]||E.day;if(typeof ah=="number"){this.proxy.setTime(this.proxy.getTime()+(ah*aj))}else{ah.add(this,aj)}return this};ag.prototype.clone=function(){return new ag(this.proxy.getTime())};ag.prototype.getUtcOffset=function(){return this.proxy.getTimezoneOffset()*60000};ag.prototype.diff=function(ai,al,ah){ai=new ag(ai);if(ai===null){return null}var aj=E[al]||E.day;if(typeof aj=="number"){var ak=(this.proxy.getTime()-ai.proxy.getTime())/aj}else{var ak=aj.diff(this.proxy,ai.proxy)}return(ah?ak:Math[ak>0?"floor":"ceil"](ak))};ag.prototype.getAbbrDayName=function(){return ag.regional[this.locale]["dayNamesShort"][this.proxy.getDay()]};ag.prototype.getAbbrMonthName=function(){return ag.regional[this.locale]["monthNamesShort"][this.proxy.getMonth()]};ag.prototype.getAMPM=function(){return this.proxy.getHours()>=12?"PM":"AM"};ag.prototype.getAmPm=function(){return this.proxy.getHours()>=12?"pm":"am"};ag.prototype.getCentury=function(){return parseInt(this.proxy.getFullYear()/100,10)};ag.prototype.getDate=function(){return this.proxy.getDate()};ag.prototype.getDay=function(){return this.proxy.getDay()};ag.prototype.getDayOfWeek=function(){var ah=this.proxy.getDay();return ah===0?7:ah};ag.prototype.getDayOfYear=function(){var ai=this.proxy;var ah=ai-new Date(""+ai.getFullYear()+"/1/1 GMT");ah+=ai.getTimezoneOffset()*60000;ai=null;return parseInt(ah/60000/60/24,10)+1};ag.prototype.getDayName=function(){return ag.regional[this.locale]["dayNames"][this.proxy.getDay()]};ag.prototype.getFullWeekOfYear=function(){var ak=this.proxy;var ah=this.getDayOfYear();var aj=6-ak.getDay();var ai=parseInt((ah+aj)/7,10);return ai};ag.prototype.getFullYear=function(){return this.proxy.getFullYear()};ag.prototype.getGmtOffset=function(){var ah=this.proxy.getTimezoneOffset()/60;var ai=ah<0?"+":"-";ah=Math.abs(ah);return ai+N(Math.floor(ah),2)+":"+N((ah%1)*60,2)};ag.prototype.getHours=function(){return this.proxy.getHours()};ag.prototype.getHours12=function(){var ah=this.proxy.getHours();return ah>12?ah-12:(ah==0?12:ah)};ag.prototype.getIsoWeek=function(){var ak=this.proxy;var aj=this.getWeekOfYear();var ah=(new Date(""+ak.getFullYear()+"/1/1")).getDay();var ai=aj+(ah>4||ah<=1?0:1);if(ai==53&&(new Date(""+ak.getFullYear()+"/12/31")).getDay()<4){ai=1}else{if(ai===0){ak=new ag(new Date(""+(ak.getFullYear()-1)+"/12/31"));ai=ak.getIsoWeek()}}ak=null;return ai};ag.prototype.getMilliseconds=function(){return this.proxy.getMilliseconds()};ag.prototype.getMinutes=function(){return this.proxy.getMinutes()};ag.prototype.getMonth=function(){return this.proxy.getMonth()};ag.prototype.getMonthName=function(){return ag.regional[this.locale]["monthNames"][this.proxy.getMonth()]};ag.prototype.getMonthNumber=function(){return this.proxy.getMonth()+1};ag.prototype.getSeconds=function(){return this.proxy.getSeconds()};ag.prototype.getShortYear=function(){return this.proxy.getYear()%100};ag.prototype.getTime=function(){return this.proxy.getTime()};ag.prototype.getTimezoneAbbr=function(){return this.proxy.toString().replace(/^.*\(([^)]+)\)$/,"$1")};ag.prototype.getTimezoneName=function(){var ah=/(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString());return ah[1]||ah[2]||"GMT"+this.getGmtOffset()};ag.prototype.getTimezoneOffset=function(){return this.proxy.getTimezoneOffset()};ag.prototype.getWeekOfYear=function(){var ah=this.getDayOfYear();var aj=7-this.getDayOfWeek();var ai=parseInt((ah+aj)/7,10);return ai};ag.prototype.getUnix=function(){return Math.round(this.proxy.getTime()/1000,0)};ag.prototype.getYear=function(){return this.proxy.getYear()};ag.prototype.next=function(ah){ah=ah||"day";return this.clone().add(1,ah)};ag.prototype.set=function(){switch(arguments.length){case 0:this.proxy=new Date();break;case 1:if(l(arguments[0])=="[object Object]"&&arguments[0]._type!="jsDate"){var aj=this.options=arguments[0];this.syntax=aj.syntax||this.syntax;this.defaultCentury=aj.defaultCentury||this.defaultCentury;this.proxy=ag.createDate(aj.date)}else{this.proxy=ag.createDate(arguments[0])}break;default:var ah=[];for(var ai=0;ai<arguments.length;ai++){ah.push(arguments[ai])}this.proxy=new Date();this.proxy.setFullYear.apply(this.proxy,ah.slice(0,3));if(ah.slice(3).length){this.proxy.setHours.apply(this.proxy,ah.slice(3))}break}return this};ag.prototype.setDate=function(ah){this.proxy.setDate(ah);return this};ag.prototype.setFullYear=function(){this.proxy.setFullYear.apply(this.proxy,arguments);return this};ag.prototype.setHours=function(){this.proxy.setHours.apply(this.proxy,arguments);return this};ag.prototype.setMilliseconds=function(ah){this.proxy.setMilliseconds(ah);return this};ag.prototype.setMinutes=function(){this.proxy.setMinutes.apply(this.proxy,arguments);return this};ag.prototype.setMonth=function(){this.proxy.setMonth.apply(this.proxy,arguments);return this};ag.prototype.setSeconds=function(){this.proxy.setSeconds.apply(this.proxy,arguments);return this};ag.prototype.setTime=function(ah){this.proxy.setTime(ah);return this};ag.prototype.setYear=function(){this.proxy.setYear.apply(this.proxy,arguments);return this};ag.prototype.strftime=function(ah){ah=ah||this.formatString||ag.regional[this.locale]["formatString"];return ag.strftime(this,ah,this.syntax)};ag.prototype.toString=function(){return this.proxy.toString()};ag.prototype.toYmdInt=function(){return(this.proxy.getFullYear()*10000)+(this.getMonthNumber()*100)+this.proxy.getDate()};ag.regional={en:{monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],formatString:"%Y-%m-%d %H:%M:%S"},fr:{monthNames:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthNamesShort:["Jan","Fév","Mar","Avr","Mai","Jun","Jul","Aoû","Sep","Oct","Nov","Déc"],dayNames:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],dayNamesShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],formatString:"%Y-%m-%d %H:%M:%S"},de:{monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],formatString:"%Y-%m-%d %H:%M:%S"},es:{monthNames:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthNamesShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],dayNames:["Domingo","Lunes","Martes","Mi&eacute;rcoles","Jueves","Viernes","S&aacute;bado"],dayNamesShort:["Dom","Lun","Mar","Mi&eacute;","Juv","Vie","S&aacute;b"],formatString:"%Y-%m-%d %H:%M:%S"},ru:{monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],dayNamesShort:["вск","пнд","втр","срд","чтв","птн","сбт"],formatString:"%Y-%m-%d %H:%M:%S"},ar:{monthNames:["كانون الثاني","شباط","آذار","نيسان","آذار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["السبت","الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة"],dayNamesShort:["سبت","أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة"],formatString:"%Y-%m-%d %H:%M:%S"},pt:{monthNames:["Janeiro","Fevereiro","Mar&ccedil;o","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Ter&ccedil;a-feira","Quarta-feira","Quinta-feira","Sexta-feira","S&aacute;bado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","S&aacute;b"],formatString:"%Y-%m-%d %H:%M:%S"},"pt-BR":{monthNames:["Janeiro","Fevereiro","Mar&ccedil;o","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Ter&ccedil;a-feira","Quarta-feira","Quinta-feira","Sexta-feira","S&aacute;bado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","S&aacute;b"],formatString:"%Y-%m-%d %H:%M:%S"},pl:{monthNames:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthNamesShort:["Sty","Lut","Mar","Kwi","Maj","Cze","Lip","Sie","Wrz","Paź","Lis","Gru"],dayNames:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],dayNamesShort:["Ni","Pn","Wt","Śr","Cz","Pt","Sb"],formatString:"%Y-%m-%d %H:%M:%S"},nl:{monthNames:["Januari","Februari","Maart","April","Mei","Juni","July","Augustus","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNames:","["Zondag","Maandag","Dinsdag","Woensdag","Donderdag","Vrijdag","Zaterdag"],dayNamesShort:["Zo","Ma","Di","Wo","Do","Vr","Za"],formatString:"%Y-%m-%d %H:%M:%S"},sv:{monthNames:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],monthNamesShort:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],dayNames:["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],dayNamesShort:["sön","mån","tis","ons","tor","fre","lör"],formatString:"%Y-%m-%d %H:%M:%S"}};ag.regional["en-US"]=ag.regional["en-GB"]=ag.regional.en;ag.regional.getLocale=function(){var ah=ag.config.defaultLocale;if(document&&document.getElementsByTagName("html")&&document.getElementsByTagName("html")[0].lang){ah=document.getElementsByTagName("html")[0].lang;if(!ag.regional.hasOwnProperty(ah)){ah=ag.config.defaultLocale}}return ah};var C=24*60*60*1000;var N=function(ah,ak){ah=String(ah);var ai=ak-ah.length;var aj=String(Math.pow(10,ai)).slice(1);return aj.concat(ah)};var E={millisecond:1,second:1000,minute:60*1000,hour:60*60*1000,day:C,week:7*C,month:{add:function(aj,ah){E.year.add(aj,Math[ah>0?"floor":"ceil"](ah/12));var ai=aj.getMonth()+(ah%12);if(ai==12){ai=0;aj.setYear(aj.getFullYear()+1)}else{if(ai==-1){ai=11;aj.setYear(aj.getFullYear()-1)}}aj.setMonth(ai)},diff:function(al,aj){var ah=al.getFullYear()-aj.getFullYear();var ai=al.getMonth()-aj.getMonth()+(ah*12);var ak=al.getDate()-aj.getDate();return ai+(ak/30)}},year:{add:function(ai,ah){ai.setYear(ai.getFullYear()+Math[ah>0?"floor":"ceil"](ah))},diff:function(ai,ah){return E.month.diff(ai,ah)/12}}};for(var Y in E){if(Y.substring(Y.length-1)!="s"){E[Y+"s"]=E[Y]}}var H=function(al,ak,ai){if(ag.formats[ai]["shortcuts"][ak]){return ag.strftime(al,ag.formats[ai]["shortcuts"][ak],ai)}else{var ah=(ag.formats[ai]["codes"][ak]||"").split(".");var aj=al["get"+ah[0]]?al["get"+ah[0]]():"";if(ah[1]){aj=N(aj,ah[1])}return aj}};ag.strftime=function(an,ak,aj,ao){var ai="perl";var am=ag.regional.getLocale();if(aj&&ag.formats.hasOwnProperty(aj)){ai=aj}else{if(aj&&ag.regional.hasOwnProperty(aj)){am=aj}}if(ao&&ag.formats.hasOwnProperty(ao)){ai=ao}else{if(ao&&ag.regional.hasOwnProperty(ao)){am=ao}}if(l(an)!="[object Object]"||an._type!="jsDate"){an=new ag(an);an.locale=am}if(!ak){ak=an.formatString||ag.regional[am]["formatString"]}var ah=ak||"%Y-%m-%d",ap="",al;while(ah.length>0){if(al=ah.match(ag.formats[ai].codes.matcher)){ap+=ah.slice(0,al.index);ap+=(al[1]||"")+H(an,al[2],ai);ah=ah.slice(al.index+al[0].length)}else{ap+=ah;ah=""}}return ap};ag.formats={ISO:"%Y-%m-%dT%H:%M:%S.%N%G",SQL:"%Y-%m-%d %H:%M:%S"};ag.formats.perl={codes:{matcher:/()%(#?(%|[a-z]))/i,Y:"FullYear",y:"ShortYear.2",m:"MonthNumber.2","#m":"MonthNumber",B:"MonthName",b:"AbbrMonthName",d:"Date.2","#d":"Date",e:"Date",A:"DayName",a:"AbbrDayName",w:"Day",H:"Hours.2","#H":"Hours",I:"Hours12.2","#I":"Hours12",p:"AMPM",M:"Minutes.2","#M":"Minutes",S:"Seconds.2","#S":"Seconds",s:"Unix",N:"Milliseconds.3","#N":"Milliseconds",O:"TimezoneOffset",Z:"TimezoneName",G:"GmtOffset"},shortcuts:{F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",D:"%m/%d/%y","#c":"%a %b %e %H:%M:%S %Y",v:"%e-%b-%Y",R:"%H:%M",r:"%I:%M:%S %p",t:"\t",n:"\n","%":"%"}};ag.formats.php={codes:{matcher:/()%((%|[a-z]))/i,a:"AbbrDayName",A:"DayName",d:"Date.2",e:"Date",j:"DayOfYear.3",u:"DayOfWeek",w:"Day",U:"FullWeekOfYear.2",V:"IsoWeek.2",W:"WeekOfYear.2",b:"AbbrMonthName",B:"MonthName",m:"MonthNumber.2",h:"AbbrMonthName",C:"Century.2",y:"ShortYear.2",Y:"FullYear",H:"Hours.2",I:"Hours12.2",l:"Hours12",p:"AMPM",P:"AmPm",M:"Minutes.2",S:"Seconds.2",s:"Unix",O:"TimezoneOffset",z:"GmtOffset",Z:"TimezoneAbbr"},shortcuts:{D:"%m/%d/%y",F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",R:"%H:%M",r:"%I:%M:%S %p",t:"\t",n:"\n","%":"%"}};ag.createDate=function(aj){if(aj==null){return new Date()}if(aj instanceof Date){return aj}if(typeof aj=="number"){return new Date(aj)}var ao=String(aj).replace(/^\s*(.+)\s*$/g,"$1");ao=ao.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/,"$1/$2/$3");ao=ao.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i,"$1 $2 $3");var an=ao.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i);if(an&&an.length>3){var at=parseFloat(an[3]);var am=ag.config.defaultCentury+at;am=String(am);ao=ao.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i,an[1]+" "+an[2]+" "+am)}an=ao.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/);function ar(ax,aw){var aC=parseFloat(aw[1]);var aB=parseFloat(aw[2]);var aA=parseFloat(aw[3]);var az=ag.config.defaultCentury;var av,au,aD,ay;if(aC>31){au=aA;aD=aB;av=az+aC}else{au=aB;aD=aC;av=az+aA}ay=aD+"/"+au+"/"+av;return ax.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/,ay)}if(an&&an.length>3){ao=ar(ao,an)}var an=ao.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/);if(an&&an.length>3){ao=ar(ao,an)}var al=0;var ai=ag.matchers.length;var aq,ah,ap=ao,ak;while(al<ai){ah=Date.parse(ap);if(!isNaN(ah)){return new Date(ah)}aq=ag.matchers[al];if(typeof aq=="function"){ak=aq.call(ag,ap);if(ak instanceof Date){return ak}}else{ap=ao.replace(aq[0],aq[1])}al++}return NaN};ag.daysInMonth=function(ah,ai){if(ai==2){return new Date(ah,1,29).getDate()==29?29:28}return[u,31,u,31,30,31,30,31,31,30,31,30,31][ai]};ag.matchers=[[/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/,"$2/$1/$3"],[/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/,"$2/$3/$1"],function(ak){var ai=ak.match(/^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i);if(ai){if(ai[1]){var aj=this.createDate(ai[1]);if(isNaN(aj)){return}}else{var aj=new Date();aj.setMilliseconds(0)}var ah=parseFloat(ai[2]);if(ai[6]){ah=ai[6].toLowerCase()=="am"?(ah==12?0:ah):(ah==12?12:ah+12)}aj.setHours(ah,parseInt(ai[3]||0,10),parseInt(ai[4]||0,10),((parseFloat(ai[5]||0))||0)*1000);return aj}else{return ak}},function(ak){var ai=ak.match(/^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i);if(ai){if(ai[1]){var aj=this.createDate(ai[1]);if(isNaN(aj)){return}}else{var aj=new Date();aj.setMilliseconds(0)}var ah=parseFloat(ai[2]);aj.setHours(ah,parseInt(ai[3],10),parseInt(ai[4],10),parseFloat(ai[5])*1000);return aj}else{return ak}},function(al){var aj=al.match(/^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/);if(aj){var ak=new Date();var am=ag.config.defaultCentury;var ao=parseFloat(aj[1]);var an=parseFloat(aj[3]);var ai,ah,ap;if(ao>31){ah=an;ai=am+ao}else{ah=ao;ai=am+an}var ap=ab(aj[2],ag.regional[ag.regional.getLocale()]["monthNamesShort"]);if(ap==-1){ap=ab(aj[2],ag.regional[ag.regional.getLocale()]["monthNames"])}ak.setFullYear(ai,ap,ah);ak.setHours(0,0,0,0);return ak}else{return al}}];function ab(aj,ak){if(ak.indexOf){return ak.indexOf(aj)}for(var ah=0,ai=ak.length;ah<ai;ah++){if(ak[ah]===aj){return ah}}return -1}function l(ah){if(ah===null){return"[object Null]"}return Object.prototype.toString.call(ah)}L.jsDate=ag;L.jqplot.sprintf=function(){function an(au,ap,aq,at){var ar=(au.length>=ap)?"":Array(1+ap-au.length>>>0).join(aq);return at?au+ar:ar+au}function ak(ar){var aq=new String(ar);for(var ap=10;ap>0;ap--){if(aq==(aq=aq.replace(/^(\d+)(\d{3})/,"$1"+L.jqplot.sprintf.thousandsSeparator+"$2"))){break}}return aq}function aj(av,au,ax,ar,at,aq){var aw=ar-av.length;if(aw>0){var ap=" ";if(aq){ap="&nbsp;"}if(ax||!at){av=an(av,ar,ap,ax)}else{av=av.slice(0,au.length)+an("",aw,"0",true)+av.slice(au.length)}}return av}function ao(ay,aq,aw,ar,ap,av,ax,au){var at=ay>>>0;aw=aw&&at&&{"2":"0b","8":"0","16":"0x"}[aq]||"";ay=aw+an(at.toString(aq),av||0,"0",false);return aj(ay,aw,ar,ap,ax,au)}function ah(au,av,ar,ap,at,aq){if(ap!=null){au=au.slice(0,ap)}return aj(au,"",av,ar,at,aq)}var ai=arguments,al=0,am=ai[al++];return am.replace(L.jqplot.sprintf.regex,function(aM,ax,ay,aB,aO,aJ,av){if(aM=="%%"){return"%"}var aD=false,az="",aA=false,aL=false,aw=false,au=false;for(var aI=0;ay&&aI<ay.length;aI++){switch(ay.charAt(aI)){case" ":az=" ";break;case"+":az="+";break;case"-":aD=true;break;case"0":aA=true;break;case"#":aL=true;break;case"&":aw=true;break;case"'":au=true;break}}if(!aB){aB=0}else{if(aB=="*"){aB=+ai[al++]}else{if(aB.charAt(0)=="*"){aB=+ai[aB.slice(1,-1)]}else{aB=+aB}}}if(aB<0){aB=-aB;aD=true}if(!isFinite(aB)){throw new Error("$.jqplot.sprintf: (minimum-)width must be finite")}if(!aJ){aJ="fFeE".indexOf(av)>-1?6:(av=="d")?0:void (0)}else{if(aJ=="*"){aJ=+ai[al++]}else{if(aJ.charAt(0)=="*"){aJ=+ai[aJ.slice(1,-1)]}else{aJ=+aJ}}}var aF=ax?ai[ax.slice(0,-1)]:ai[al++];switch(av){case"s":if(aF==null){return""}return ah(String(aF),aD,aB,aJ,aA,aw);case"c":return ah(String.fromCharCode(+aF),aD,aB,aJ,aA,aw);case"b":return ao(aF,2,aL,aD,aB,aJ,aA,aw);case"o":return ao(aF,8,aL,aD,aB,aJ,aA,aw);case"x":return ao(aF,16,aL,aD,aB,aJ,aA,aw);case"X":return ao(aF,16,aL,aD,aB,aJ,aA,aw).toUpperCase();case"u":return ao(aF,10,aL,aD,aB,aJ,aA,aw);case"i":var ar=parseInt(+aF,10);if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aK=au?ak(String(Math.abs(ar))):String(Math.abs(ar));aF=aH+an(aK,aJ,"0",false);return aj(aF,aH,aD,aB,aA,aw);case"d":var ar=Math.round(+aF);if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aK=au?ak(String(Math.abs(ar))):String(Math.abs(ar));aF=aH+an(aK,aJ,"0",false);return aj(aF,aH,aD,aB,aA,aw);case"e":case"E":case"f":case"F":case"g":case"G":var ar=+aF;if(isNaN(ar)){return""}var aH=ar<0?"-":az;var at=["toExponential","toFixed","toPrecision"]["efg".indexOf(av.toLowerCase())];var aN=["toString","toUpperCase"]["eEfFgG".indexOf(av)%2];var aK=Math.abs(ar)[at](aJ);var aE=aK.toString().split(".");aE[0]=au?ak(aE[0]):aE[0];aK=aE.join(L.jqplot.sprintf.decimalMark);aF=aH+aK;var aC=aj(aF,aH,aD,aB,aA,aw)[aN]();return aC;case"p":case"P":var ar=+aF;if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aE=String(Number(Math.abs(ar)).toExponential()).split(/e|E/);var aq=(aE[0].indexOf(".")!=-1)?aE[0].length-1:String(ar).length;var aG=(aE[1]<0)?-aE[1]-1:0;if(Math.abs(ar)<1){if(aq+aG<=aJ){aF=aH+Math.abs(ar).toPrecision(aq)}else{if(aq<=aJ-1){aF=aH+Math.abs(ar).toExponential(aq-1)}else{aF=aH+Math.abs(ar).toExponential(aJ-1)}}}else{var ap=(aq<=aJ)?aq:aJ;aF=aH+Math.abs(ar).toPrecision(ap)}var aN=["toString","toUpperCase"]["pP".indexOf(av)%2];return aj(aF,aH,aD,aB,aA,aw)[aN]();case"n":return"";default:return aM}})};L.jqplot.sprintf.thousandsSeparator=",";L.jqplot.sprintf.decimalMark=".";L.jqplot.sprintf.regex=/%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g;L.jqplot.getSignificantFigures=function(al){var an=String(Number(Math.abs(al)).toExponential()).split(/e|E/);var am=(an[0].indexOf(".")!=-1)?an[0].length-1:an[0].length;var ai=(an[1]<0)?-an[1]-1:0;var ah=parseInt(an[1],10);var aj=(ah+1>0)?ah+1:0;var ak=(am<=aj)?0:am-ah-1;return{significantDigits:am,digitsLeft:aj,digitsRight:ak,zeros:ai,exponent:ah}};L.jqplot.getPrecision=function(ah){return L.jqplot.getSignificantFigures(ah).digitsRight};var X=L.uiBackCompat!==false;L.jqplot.effects={effect:{}};var m="jqplot.storage.";L.extend(L.jqplot.effects,{version:"1.9pre",save:function(ai,aj){for(var ah=0;ah<aj.length;ah++){if(aj[ah]!==null){ai.data(m+aj[ah],ai[0].style[aj[ah]])}}},restore:function(ai,aj){for(var ah=0;ah<aj.length;ah++){if(aj[ah]!==null){ai.css(aj[ah],ai.data(m+aj[ah]))}}},setMode:function(ah,ai){if(ai==="toggle"){ai=ah.is(":hidden")?"show":"hide"}return ai},createWrapper:function(ai){if(ai.parent().is(".ui-effects-wrapper")){return ai.parent()}var aj={width:ai.outerWidth(true),height:ai.outerHeight(true),"float":ai.css("float")},al=L("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),ah={width:ai.width(),height:ai.height()},ak=document.activeElement;ai.wrap(al);if(ai[0]===ak||L.contains(ai[0],ak)){L(ak).focus()}al=ai.parent();if(ai.css("position")==="static"){al.css({position:"relative"});ai.css({position:"relative"})}else{L.extend(aj,{position:ai.css("position"),zIndex:ai.css("z-index")});L.each(["top","left","bottom","right"],function(am,an){aj[an]=ai.css(an);if(isNaN(parseInt(aj[an],10))){aj[an]="auto"}});ai.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}ai.css(ah);return al.css(aj).show()},removeWrapper:function(ah){var ai=document.activeElement;if(ah.parent().is(".ui-effects-wrapper")){ah.parent().replaceWith(ah);if(ah[0]===ai||L.contains(ah[0],ai)){L(ai).focus()}}return ah}});function j(ai,ah,aj,ak){if(L.isPlainObject(ai)){return ai}ai={effect:ai};if(ah===u){ah={}}if(L.isFunction(ah)){ak=ah;aj=null;ah={}}if(L.type(ah)==="number"||L.fx.speeds[ah]){ak=aj;aj=ah;ah={}}if(L.isFunction(aj)){ak=aj;aj=null}if(ah){L.extend(ai,ah)}aj=aj||ah.duration;ai.duration=L.fx.off?0:typeof aj==="number"?aj:aj in L.fx.speeds?L.fx.speeds[aj]:L.fx.speeds._default;ai.complete=ak||ah.complete;return ai}function ae(ah){if(!ah||typeof ah==="number"||L.fx.speeds[ah]){return true}if(typeof ah==="string"&&!L.jqplot.effects.effect[ah]){if(X&&L.jqplot.effects[ah]){return false}return true}return false}L.fn.extend({jqplotEffect:function(ap,aq,ai,ao){var an=j.apply(this,arguments),ak=an.mode,al=an.queue,am=L.jqplot.effects.effect[an.effect],ah=!am&&X&&L.jqplot.effects[an.effect];if(L.fx.off||!(am||ah)){if(ak){return this[ak](an.duration,an.complete)}else{return this.each(function(){if(an.complete){an.complete.call(this)}})}}function aj(au){var av=L(this),at=an.complete,aw=an.mode;function ar(){if(L.isFunction(at)){at.call(av[0])}if(L.isFunction(au)){au()}}if(av.is(":hidden")?aw==="hide":aw==="show"){ar()}else{am.call(av[0],an,ar)}}if(am){return al===false?this.each(aj):this.queue(al||"fx",aj)}else{return ah.call(this,{options:an,duration:an.duration,callback:an.complete,mode:an.mode})}}});var a=/up|down|vertical/,v=/up|left|vertical|horizontal/;L.jqplot.effects.effect.blind=function(aj,ao){var ak=L(this),ar=["position","top","bottom","left","right","height","width"],ap=L.jqplot.effects.setMode(ak,aj.mode||"hide"),au=aj.direction||"up",am=a.test(au),al=am?"height":"width",aq=am?"top":"left",aw=v.test(au),an={},av=ap==="show",ai,ah,at;if(ak.parent().is(".ui-effects-wrapper")){L.jqplot.effects.save(ak.parent(),ar)}else{L.jqplot.effects.save(ak,ar)}ak.show();at=parseInt(ak.css("top"),10);ai=L.jqplot.effects.createWrapper(ak).css({overflow:"hidden"});ah=am?ai[al]()+at:ai[al]();an[al]=av?String(ah):"0";if(!aw){ak.css(am?"bottom":"right",0).css(am?"top":"left","").css({position:"absolute"});an[aq]=av?"0":String(ah)}if(av){ai.css(al,0);if(!aw){ai.css(aq,ah)}}ai.animate(an,{duration:aj.duration,easing:aj.easing,queue:false,complete:function(){if(ap==="hide"){ak.hide()}L.jqplot.effects.restore(ak,ar);L.jqplot.effects.removeWrapper(ak);ao()}})}})(jQuery);
WRFILE: jqplot.pieRenderer.min.js

(function(e){e.jqplot.PieRenderer=function(){e.jqplot.LineRenderer.call(this)};e.jqplot.PieRenderer.prototype=new e.jqplot.LineRenderer();e.jqplot.PieRenderer.prototype.constructor=e.jqplot.PieRenderer;e.jqplot.PieRenderer.prototype.init=function(q,u){this.diameter=null;this.padding=20;this.sliceMargin=0;this.fill=true;this.shadowOffset=2;this.shadowAlpha=0.07;this.shadowDepth=5;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.dataLabels="percent";this.showDataLabels=false;this.dataLabelFormatString=null;this.dataLabelThreshold=3;this.dataLabelPositionFactor=0.52;this.dataLabelNudge=2;this.dataLabelCenterOn=true;this.startAngle=0;this.tickRenderer=e.jqplot.PieTickRenderer;this._drawData=true;this._type="pie";if(q.highlightMouseDown&&q.highlightMouseOver==null){q.highlightMouseOver=false}e.extend(true,this,q);if(this.sliceMargin<0){this.sliceMargin=0}this._diameter=null;this._radius=null;this._sliceAngles=[];this._highlightedPoint=null;if(this.highlightColors.length==0){for(var s=0;s<this.seriesColors.length;s++){var r=e.jqplot.getColorComponents(this.seriesColors[s]);var o=[r[0],r[1],r[2]];var t=o[0]+o[1]+o[2];for(var p=0;p<3;p++){o[p]=(t>570)?o[p]*0.8:o[p]+0.3*(255-o[p]);o[p]=parseInt(o[p],10)}this.highlightColors.push("rgb("+o[0]+","+o[1]+","+o[2]+")")}}this.highlightColorGenerator=new e.jqplot.ColorGenerator(this.highlightColors);u.postParseOptionsHooks.addOnce(m);u.postInitHooks.addOnce(g);u.eventListenerHooks.addOnce("jqplotMouseMove",b);u.eventListenerHooks.addOnce("jqplotMouseDown",a);u.eventListenerHooks.addOnce("jqplotMouseUp",l);u.eventListenerHooks.addOnce("jqplotClick",f);u.eventListenerHooks.addOnce("jqplotRightClick",n);u.postDrawHooks.addOnce(i)};e.jqplot.PieRenderer.prototype.setGridData=function(t){var p=[];var u=[];var o=this.startAngle/180*Math.PI;var s=0;this._drawData=false;for(var r=0;r<this.data.length;r++){if(this.data[r][1]!=0){this._drawData=true}p.push(this.data[r][1]);u.push([this.data[r][0]]);if(r>0){p[r]+=p[r-1]}s+=this.data[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r<p.length;r++){u[r][1]=p[r]*q;u[r][2]=this.data[r][1]/s}this.gridData=u};e.jqplot.PieRenderer.prototype.makeGridData=function(t,u){var p=[];var v=[];var s=0;var o=this.startAngle/180*Math.PI;this._drawData=false;for(var r=0;r<t.length;r++){if(this.data[r][1]!=0){this._drawData=true}p.push(t[r][1]);v.push([t[r][0]]);if(r>0){p[r]+=p[r-1]}s+=t[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r<p.length;r++){v[r][1]=p[r]*q;v[r][2]=t[r][1]/s}return v};function h(o){return Math.sin((o-(o-Math.PI)/8/Math.PI)/2)}function j(u,t,o,v,r){var w=0;var q=t-u;var s=Math.abs(q);var p=o;if(v==false){p+=r}if(p>0&&s>0.01&&s<6.282){w=parseFloat(p)/2/h(q)}return w}e.jqplot.PieRenderer.prototype.drawSlice=function(B,z,y,u,w){if(this._drawData){var p=this._radius;var A=this.fill;var x=this.lineWidth;var s=this.sliceMargin;if(this.fill==false){s+=this.lineWidth}B.save();B.translate(this._center[0],this._center[1]);var D=j(z,y,this.sliceMargin,this.fill,this.lineWidth);var o=D*Math.cos((z+y)/2);var C=D*Math.sin((z+y)/2);if((y-z)<=Math.PI){p-=D}else{p+=D}B.translate(o,C);if(w){for(var v=0,t=this.shadowDepth;v<t;v++){B.save();B.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI),this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));q(p)}for(var v=0,t=this.shadowDepth;v<t;v++){B.restore()}}else{q(p)}B.restore()}function q(r){if(y>6.282+this.startAngle){y=6.282+this.startAngle;if(z>y){z=6.281+this.startAngle}}if(z>=y){return}B.beginPath();B.fillStyle=u;B.strokeStyle=u;B.lineWidth=x;B.arc(0,0,r,z,y,false);B.lineTo(0,0);B.closePath();if(A){B.fill()}else{B.stroke()}}};e.jqplot.PieRenderer.prototype.draw=function(B,z,E,o){var W;var H=(E!=undefined)?E:{};var t=0;var s=0;var N=1;var L=new e.jqplot.ColorGenerator(this.seriesColors);if(E.legendInfo&&E.legendInfo.placement=="insideGrid"){var J=E.legendInfo;switch(J.location){case"nw":t=J.width+J.xoffset;break;case"w":t=J.width+J.xoffset;break;case"sw":t=J.width+J.xoffset;break;case"ne":t=J.width+J.xoffset;N=-1;break;case"e":t=J.width+J.xoffset;N=-1;break;case"se":t=J.width+J.xoffset;N=-1;break;case"n":s=J.height+J.yoffset;break;case"s":s=J.height+J.yoffset;N=-1;break;default:break}}var K=(H.shadow!=undefined)?H.shadow:this.shadow;var A=(H.fill!=undefined)?H.fill:this.fill;var C=B.canvas.width;var I=B.canvas.height;var Q=C-t-2*this.padding;var X=I-s-2*this.padding;var M=Math.min(Q,X);var Y=M;this._sliceAngles=[];var v=this.sliceMargin;if(this.fill==false){v+=this.lineWidth}var q;var G=0;var R,aa,Z,ab;var D=this.startAngle/180*Math.PI;for(var W=0,V=z.length;W<V;W++){aa=(W==0)?D:z[W-1][1]+D;Z=z[W][1]+D;this._sliceAngles.push([aa,Z]);q=j(aa,Z,this.sliceMargin,this.fill,this.lineWidth);if(Math.abs(Z-aa)>Math.PI){G=Math.max(q,G)}}if(this.diameter!=null&&this.diameter>0){this._diameter=this.diameter-2*G}else{this._diameter=Y-2*G}if(this._diameter<6){e.jqplot.log("Diameter of pie too small, not rendering.");return}var S=this._radius=this._diameter/2;this._center=[(C-N*t)/2+N*t+G*Math.cos(D),(I-N*s)/2+N*s+G*Math.sin(D)];if(this.shadow){for(var W=0,V=z.length;W<V;W++){ab="rgba(0,0,0,"+this.shadowAlpha+")";this.renderer.drawSlice.call(this,B,this._sliceAngles[W][0],this._sliceAngles[W][1],ab,true)}}for(var W=0;W<z.length;W++){this.renderer.drawSlice.call(this,B,this._sliceAngles[W][0],this._sliceAngles[W][1],L.next(),false);if(this.showDataLabels&&z[W][2]*100>=this.dataLabelThreshold){var F,U=(this._sliceAngles[W][0]+this._sliceAngles[W][1])/2,T;if(this.dataLabels=="label"){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,z[W][0])}else{if(this.dataLabels=="value"){F=this.dataLabelFormatString||"%d";T=e.jqplot.sprintf(F,this.data[W][1])}else{if(this.dataLabels=="percent"){F=this.dataLabelFormatString||"%d%%";T=e.jqplot.sprintf(F,z[W][2]*100)}else{if(this.dataLabels.constructor==Array){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,this.dataLabels[W])}}}}var p=(this._radius)*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var P=this._center[0]+Math.cos(U)*p+this.canvas._offsets.left;var O=this._center[1]+Math.sin(U)*p+this.canvas._offsets.top;var u=e('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">'+T+"</div>").insertBefore(o.eventCanvas._elem);if(this.dataLabelCenterOn){P-=u.width()/2;O-=u.height()/2}else{P-=u.width()*Math.sin(U/2);O-=u.height()/2}P=Math.round(P);O=Math.round(O);u.css({left:P,top:O})}}};e.jqplot.PieAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.PieAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.PieAxisRenderer.prototype.constructor=e.jqplot.PieAxisRenderer;e.jqplot.PieAxisRenderer.prototype.init=function(o){this.tickRenderer=e.jqplot.PieTickRenderer;e.extend(true,this,o);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.PieLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.PieLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.PieLegendRenderer.prototype.constructor=e.jqplot.PieLegendRenderer;e.jqplot.PieLegendRenderer.prototype.init=function(o){this.numberRows=null;this.numberColumns=null;e.extend(true,this,o)};e.jqplot.PieLegendRenderer.prototype.draw=function(){var r=this;if(this.show){var B=this._series;this._elem=e(document.createElement("table"));this._elem.addClass("jqplot-table-legend");var E={position:"absolute"};if(this.background){E.background=this.background}if(this.border){E.border=this.border}if(this.fontSize){E.fontSize=this.fontSize}if(this.fontFamily){E.fontFamily=this.fontFamily}if(this.textColor){E.textColor=this.textColor}if(this.marginTop!=null){E.marginTop=this.marginTop}if(this.marginBottom!=null){E.marginBottom=this.marginBottom}if(this.marginLeft!=null){E.marginLeft=this.marginLeft}if(this.marginRight!=null){E.marginRight=this.marginRight}this._elem.css(E);var I=false,A=false,o,y;var C=B[0];var p=new e.jqplot.ColorGenerator(C.seriesColors);if(C.show){var J=C.data;if(this.numberRows){o=this.numberRows;if(!this.numberColumns){y=Math.ceil(J.length/o)}else{y=this.numberColumns}}else{if(this.numberColumns){y=this.numberColumns;o=Math.ceil(J.length/this.numberColumns)}else{o=J.length;y=1}}var H,G;var q,w,v;var x,z,F;var D=0;var u,t;for(H=0;H<o;H++){q=e(document.createElement("tr"));q.addClass("jqplot-table-legend");if(A){q.prependTo(this._elem)}else{q.appendTo(this._elem)}for(G=0;G<y;G++){if(D<J.length){x=this.labels[D]||J[D][0].toString();F=p.next();if(!A){if(H>0){I=true}else{I=false}}else{if(H==o-1){I=false}else{I=true}}z=(I)?this.rowSpacing:"0";w=e(document.createElement("td"));w.addClass("jqplot-table-legend jqplot-table-legend-swatch");w.css({textAlign:"center",paddingTop:z});u=e(document.createElement("div"));u.addClass("jqplot-table-legend-swatch-outline");t=e(document.createElement("div"));t.addClass("jqplot-table-legend-swatch");t.css({backgroundColor:F,borderColor:F});w.append(u.append(t));v=e(document.createElement("td"));v.addClass("jqplot-table-legend jqplot-table-legend-label");v.css("paddingTop",z);if(this.escapeHtml){v.text(x)}else{v.html(x)}if(A){v.prependTo(q);w.prependTo(q)}else{w.appendTo(q);v.appendTo(q)}I=true}D++}}}}return this._elem};e.jqplot.PieRenderer.prototype.handleMove=function(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];r.target.trigger("jqplotDataMouseOver",o);if(r.series[o[0]].highlightMouseOver&&!(o[0]==r.plugins.pieRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){r.target.trigger("jqplotDataHighlight",o);d(r,o[0],o[1])}}else{if(s==null){k(r)}}};function c(s,r,p){p=p||{};p.axesDefaults=p.axesDefaults||{};p.legend=p.legend||{};p.seriesDefaults=p.seriesDefaults||{};var o=false;if(p.seriesDefaults.renderer==e.jqplot.PieRenderer){o=true}else{if(p.series){for(var q=0;q<p.series.length;q++){if(p.series[q].renderer==e.jqplot.PieRenderer){o=true}}}}if(o){p.axesDefaults.renderer=e.jqplot.PieAxisRenderer;p.legend.renderer=e.jqplot.PieLegendRenderer;p.legend.preDraw=true;p.seriesDefaults.pointLabels={show:false}}}function g(r,q,o){for(var p=0;p<this.series.length;p++){if(this.series[p].renderer.constructor==e.jqplot.PieRenderer){if(this.series[p].highlightMouseOver){this.series[p].highlightMouseDown=false}}}}function m(o){for(var p=0;p<this.series.length;p++){this.series[p].seriesColors=this.seriesColors;this.series[p].colorGenerator=e.jqplot.colorGenerator}}function d(t,r,q){var p=t.series[r];var o=t.plugins.pieRenderer.highlightCanvas;o._ctx.clearRect(0,0,o._ctx.canvas.width,o._ctx.canvas.height);p._highlightedPoint=q;t.plugins.pieRenderer.highlightedSeriesIndex=r;p.renderer.drawSlice.call(p,o._ctx,p._sliceAngles[q][0],p._sliceAngles[q][1],p.highlightColorGenerator.get(q),false)}function k(q){var o=q.plugins.pieRenderer.highlightCanvas;o._ctx.clearRect(0,0,o._ctx.canvas.width,o._ctx.canvas.height);for(var p=0;p<q.series.length;p++){q.series[p]._highlightedPoint=null}q.plugins.pieRenderer.highlightedSeriesIndex=null;q.target.trigger("jqplotDataUnhighlight")}function b(s,r,v,u,t){if(u){var q=[u.seriesIndex,u.pointIndex,u.data];var p=jQuery.Event("jqplotDataMouseOver");p.pageX=s.pageX;p.pageY=s.pageY;t.target.trigger(p,q);if(t.series[q[0]].highlightMouseOver&&!(q[0]==t.plugins.pieRenderer.highlightedSeriesIndex&&q[1]==t.series[q[0]]._highlightedPoint)){var o=jQuery.Event("jqplotDataHighlight");o.which=s.which;o.pageX=s.pageX;o.pageY=s.pageY;t.target.trigger(o,q);d(t,q[0],q[1])}}else{if(u==null){k(t)}}}function a(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];if(s.series[p[0]].highlightMouseDown&&!(p[0]==s.plugins.pieRenderer.highlightedSeriesIndex&&p[1]==s.series[p[0]]._highlightedPoint)){var o=jQuery.Event("jqplotDataHighlight");o.which=r.which;o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p);d(s,p[0],p[1])}}else{if(t==null){k(s)}}}function l(q,p,t,s,r){var o=r.plugins.pieRenderer.highlightedSeriesIndex;if(o!=null&&r.series[o].highlightMouseDown){k(r)}}function f(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];var o=jQuery.Event("jqplotDataClick");o.which=r.which;o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p)}}function n(s,r,v,u,t){if(u){var q=[u.seriesIndex,u.pointIndex,u.data];var o=t.plugins.pieRenderer.highlightedSeriesIndex;if(o!=null&&t.series[o].highlightMouseDown){k(t)}var p=jQuery.Event("jqplotDataRightClick");p.which=s.which;p.pageX=s.pageX;p.pageY=s.pageY;t.target.trigger(p,q)}}function i(){if(this.plugins.pieRenderer&&this.plugins.pieRenderer.highlightCanvas){this.plugins.pieRenderer.highlightCanvas.resetCanvas();this.plugins.pieRenderer.highlightCanvas=null}this.plugins.pieRenderer={highlightedSeriesIndex:null};this.plugins.pieRenderer.highlightCanvas=new e.jqplot.GenericCanvas();var p=e(this.targetId+" .jqplot-data-label");if(p.length){e(p[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-pieRenderer-highlight-canvas",this._plotDimensions,this))}else{this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-pieRenderer-highlight-canvas",this._plotDimensions,this))}var o=this.plugins.pieRenderer.highlightCanvas.setContext();this.eventCanvas._elem.bind("mouseleave",{plot:this},function(q){k(q.data.plot)})}e.jqplot.preInitHooks.push(c);e.jqplot.PieTickRenderer=function(){e.jqplot.AxisTickRenderer.call(this)};e.jqplot.PieTickRenderer.prototype=new e.jqplot.AxisTickRenderer();e.jqplot.PieTickRenderer.prototype.constructor=e.jqplot.PieTickRenderer})(jQuery);
WRFILE: jqplot.barRenderer.min.js

(function(d){d.jqplot.BarRenderer=function(){d.jqplot.LineRenderer.call(this)};d.jqplot.BarRenderer.prototype=new d.jqplot.LineRenderer();d.jqplot.BarRenderer.prototype.constructor=d.jqplot.BarRenderer;d.jqplot.BarRenderer.prototype.init=function(o,q){this.barPadding=8;this.barMargin=10;this.barDirection="vertical";this.barWidth=null;this.shadowOffset=2;this.shadowDepth=5;this.shadowAlpha=0.08;this.waterfall=false;this.groups=1;this.varyBarColor=false;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.transposedData=true;this.renderer.animation={show:false,direction:"down",speed:3000,_supported:true};this._type="bar";if(o.highlightMouseDown&&o.highlightMouseOver==null){o.highlightMouseOver=false}d.extend(true,this,o);d.extend(true,this.renderer,o);this.fill=true;if(this.barDirection==="horizontal"&&this.rendererOptions.animation&&this.rendererOptions.animation.direction==null){this.renderer.animation.direction="left"}if(this.waterfall){this.fillToZero=false;this.disableStack=true}if(this.barDirection=="vertical"){this._primaryAxis="_xaxis";this._stackAxis="y";this.fillAxis="y"}else{this._primaryAxis="_yaxis";this._stackAxis="x";this.fillAxis="x"}this._highlightedPoint=null;this._plotSeriesInfo=null;this._dataColors=[];this._barPoints=[];var p={lineJoin:"miter",lineCap:"round",fill:true,isarc:false,strokeStyle:this.color,fillStyle:this.color,closePath:this.fill};this.renderer.shapeRenderer.init(p);var n={lineJoin:"miter",lineCap:"round",fill:true,isarc:false,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,closePath:this.fill};this.renderer.shadowRenderer.init(n);q.postInitHooks.addOnce(h);q.postDrawHooks.addOnce(j);q.eventListenerHooks.addOnce("jqplotMouseMove",b);q.eventListenerHooks.addOnce("jqplotMouseDown",a);q.eventListenerHooks.addOnce("jqplotMouseUp",l);q.eventListenerHooks.addOnce("jqplotClick",e);q.eventListenerHooks.addOnce("jqplotRightClick",m)};function g(t,p,o,w){if(this.rendererOptions.barDirection=="horizontal"){this._stackAxis="x";this._primaryAxis="_yaxis"}if(this.rendererOptions.waterfall==true){this._data=d.extend(true,[],this.data);var s=0;var u=(!this.rendererOptions.barDirection||this.rendererOptions.barDirection==="vertical"||this.transposedData===false)?1:0;for(var q=0;q<this.data.length;q++){s+=this.data[q][u];if(q>0){this.data[q][u]+=this.data[q-1][u]}}this.data[this.data.length]=(u==1)?[this.data.length+1,s]:[s,this.data.length+1];this._data[this._data.length]=(u==1)?[this._data.length+1,s]:[s,this._data.length+1]}if(this.rendererOptions.groups>1){this.breakOnNull=true;var n=this.data.length;var v=parseInt(n/this.rendererOptions.groups,10);var r=0;for(var q=v;q<n;q+=v){this.data.splice(q+r,0,[null,null]);this._plotData.splice(q+r,0,[null,null]);this._stackData.splice(q+r,0,[null,null]);r++}for(q=0;q<this.data.length;q++){if(this._primaryAxis=="_xaxis"){this.data[q][0]=q+1;this._plotData[q][0]=q+1;this._stackData[q][0]=q+1}else{this.data[q][1]=q+1;this._plotData[q][1]=q+1;this._stackData[q][1]=q+1}}}}d.jqplot.preSeriesInitHooks.push(g);d.jqplot.BarRenderer.prototype.calcSeriesNumbers=function(){var r=0;var t=0;var q=this[this._primaryAxis];var p,o,u;for(var n=0;n<q._series.length;n++){o=q._series[n];if(o===this){u=n}if(o.renderer.constructor==d.jqplot.BarRenderer){r+=o.data.length;t+=1}}return[r,t,u]};d.jqplot.BarRenderer.prototype.setBarWidth=function(){var q;var n=0;var o=0;var t=this[this._primaryAxis];var x,r,v;var w=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);n=w[0];o=w[1];var u=t.numberTicks;var p=(u-1)/2;if(t.name=="xaxis"||t.name=="x2axis"){if(this._stack){this.barWidth=(t._offsets.max-t._offsets.min)/n*o-this.barMargin}else{this.barWidth=((t._offsets.max-t._offsets.min)/p-this.barPadding*(o-1)-this.barMargin*2)/o}}else{if(this._stack){this.barWidth=(t._offsets.min-t._offsets.max)/n*o-this.barMargin}else{this.barWidth=((t._offsets.min-t._offsets.max)/p-this.barPadding*(o-1)-this.barMargin*2)/o}}return[n,o]};function f(o){var q=[];for(var s=0;s<o.length;s++){var r=d.jqplot.getColorComponents(o[s]);var n=[r[0],r[1],r[2]];var t=n[0]+n[1]+n[2];for(var p=0;p<3;p++){n[p]=(t>570)?n[p]*0.8:n[p]+0.3*(255-n[p]);n[p]=parseInt(n[p],10)}q.push("rgb("+n[0]+","+n[1]+","+n[2]+")")}return q}function i(v,u,s,t,o){var q=v,w=v-1,n,p,r=(o==="x")?0:1;if(q>0){p=t.series[w]._plotData[u][r];if((s*p)<0){n=i(w,u,s,t,o)}else{n=t.series[w].gridData[u][r]}}else{n=(r===0)?t.series[q]._xaxis.series_u2p(0):t.series[q]._yaxis.series_u2p(0)}return n}d.jqplot.BarRenderer.prototype.draw=function(E,L,q,G){var I;var A=d.extend({},q);var w=(A.shadow!=undefined)?A.shadow:this.shadow;var O=(A.showLine!=undefined)?A.showLine:this.showLine;var F=(A.fill!=undefined)?A.fill:this.fill;var p=this.xaxis;var J=this.yaxis;var y=this._xaxis.series_u2p;var K=this._yaxis.series_u2p;var D,C;this._dataColors=[];this._barPoints=[];if(this.barWidth==null){this.renderer.setBarWidth.call(this)}var N=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);var x=N[0];var v=N[1];var s=N[2];var H=[];if(this._stack){this._barNudge=0}else{this._barNudge=(-Math.abs(v/2-0.5)+s)*(this.barWidth+this.barPadding)}if(O){var u=new d.jqplot.ColorGenerator(this.negativeSeriesColors);var B=new d.jqplot.ColorGenerator(this.seriesColors);var M=u.get(this.index);if(!this.useNegativeColors){M=A.fillStyle}var t=A.fillStyle;var r;var P;var o;if(this.barDirection=="vertical"){for(var I=0;I<L.length;I++){if(!this._stack&&this.data[I][1]==null){continue}H=[];r=L[I][0]+this._barNudge;if(this._stack&&this._prevGridData.length){o=i(this.index,I,this._plotData[I][1],G,"y")}else{if(this.fillToZero){o=this._yaxis.series_u2p(0)}else{if(this.waterfall&&I>0&&I<this.gridData.length-1){o=this.gridData[I-1][1]}else{if(this.waterfall&&I==0&&I<this.gridData.length-1){if(this._yaxis.min<=0&&this._yaxis.max>=0){o=this._yaxis.series_u2p(0)}else{if(this._yaxis.min>0){o=E.canvas.height}else{o=0}}}else{if(this.waterfall&&I==this.gridData.length-1){if(this._yaxis.min<=0&&this._yaxis.max>=0){o=this._yaxis.series_u2p(0)}else{if(this._yaxis.min>0){o=E.canvas.height}else{o=0}}}else{o=E.canvas.height}}}}}if((this.fillToZero&&this._plotData[I][1]<0)||(this.waterfall&&this._data[I][1]<0)){if(this.varyBarColor&&!this._stack){if(this.useNegativeColors){A.fillStyle=u.next()}else{A.fillStyle=B.next()}}else{A.fillStyle=M}}else{if(this.varyBarColor&&!this._stack){A.fillStyle=B.next()}else{A.fillStyle=t}}if(!this.fillToZero||this._plotData[I][1]>=0){H.push([r-this.barWidth/2,o]);H.push([r-this.barWidth/2,L[I][1]]);H.push([r+this.barWidth/2,L[I][1]]);H.push([r+this.barWidth/2,o])}else{H.push([r-this.barWidth/2,L[I][1]]);H.push([r-this.barWidth/2,o]);H.push([r+this.barWidth/2,o]);H.push([r+this.barWidth/2,L[I][1]])}this._barPoints.push(H);if(w&&!this._stack){var z=d.extend(true,{},A);delete z.fillStyle;this.renderer.shadowRenderer.draw(E,H,z)}var n=A.fillStyle||this.color;this._dataColors.push(n);this.renderer.shapeRenderer.draw(E,H,A)}}else{if(this.barDirection=="horizontal"){for(var I=0;I<L.length;I++){if(!this._stack&&this.data[I][0]==null){continue}H=[];r=L[I][1]-this._barNudge;P;if(this._stack&&this._prevGridData.length){P=i(this.index,I,this._plotData[I][0],G,"x")}else{if(this.fillToZero){P=this._xaxis.series_u2p(0)}else{if(this.waterfall&&I>0&&I<this.gridData.length-1){P=this.gridData[I-1][0]}else{if(this.waterfall&&I==0&&I<this.gridData.length-1){if(this._xaxis.min<=0&&this._xaxis.max>=0){P=this._xaxis.series_u2p(0)}else{if(this._xaxis.min>0){P=0}else{P=0}}}else{if(this.waterfall&&I==this.gridData.length-1){if(this._xaxis.min<=0&&this._xaxis.max>=0){P=this._xaxis.series_u2p(0)}else{if(this._xaxis.min>0){P=0}else{P=E.canvas.width}}}else{P=0}}}}}if((this.fillToZero&&this._plotData[I][0]<0)||(this.waterfall&&this._data[I][0]<0)){if(this.varyBarColor&&!this._stack){if(this.useNegativeColors){A.fillStyle=u.next()}else{A.fillStyle=B.next()}}else{A.fillStyle=M}}else{if(this.varyBarColor&&!this._stack){A.fillStyle=B.next()}else{A.fillStyle=t}}if(!this.fillToZero||this._plotData[I][0]>=0){H.push([P,r+this.barWidth/2]);H.push([P,r-this.barWidth/2]);H.push([L[I][0],r-this.barWidth/2]);H.push([L[I][0],r+this.barWidth/2])}else{H.push([L[I][0],r+this.barWidth/2]);H.push([L[I][0],r-this.barWidth/2]);H.push([P,r-this.barWidth/2]);H.push([P,r+this.barWidth/2])}this._barPoints.push(H);if(w&&!this._stack){var z=d.extend(true,{},A);delete z.fillStyle;this.renderer.shadowRenderer.draw(E,H,z)}var n=A.fillStyle||this.color;this._dataColors.push(n);this.renderer.shapeRenderer.draw(E,H,A)}}}}if(this.highlightColors.length==0){this.highlightColors=d.jqplot.computeHighlightColors(this._dataColors)}else{if(typeof(this.highlightColors)=="string"){var N=this.highlightColors;this.highlightColors=[];for(var I=0;I<this._dataColors.length;I++){this.highlightColors.push(N)}}}};d.jqplot.BarRenderer.prototype.drawShadow=function(z,G,p,B){var D;var w=(p!=undefined)?p:{};var t=(w.shadow!=undefined)?w.shadow:this.shadow;var I=(w.showLine!=undefined)?w.showLine:this.showLine;var A=(w.fill!=undefined)?w.fill:this.fill;var o=this.xaxis;var E=this.yaxis;var v=this._xaxis.series_u2p;var F=this._yaxis.series_u2p;var y,C,x,u,s,r;if(this._stack&&this.shadow){if(this.barWidth==null){this.renderer.setBarWidth.call(this)}var H=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);u=H[0];s=H[1];r=H[2];if(this._stack){this._barNudge=0}else{this._barNudge=(-Math.abs(s/2-0.5)+r)*(this.barWidth+this.barPadding)}if(I){if(this.barDirection=="vertical"){for(var D=0;D<G.length;D++){if(this.data[D][1]==null){continue}C=[];var q=G[D][0]+this._barNudge;var n;if(this._stack&&this._prevGridData.length){n=i(this.index,D,this._plotData[D][1],B,"y")}else{if(this.fillToZero){n=this._yaxis.series_u2p(0)}else{n=z.canvas.height}}C.push([q-this.barWidth/2,n]);C.push([q-this.barWidth/2,G[D][1]]);C.push([q+this.barWidth/2,G[D][1]]);C.push([q+this.barWidth/2,n]);this.renderer.shadowRenderer.draw(z,C,w)}}else{if(this.barDirection=="horizontal"){for(var D=0;D<G.length;D++){if(this.data[D][0]==null){continue}C=[];var q=G[D][1]-this._barNudge;var J;if(this._stack&&this._prevGridData.length){J=i(this.index,D,this._plotData[D][0],B,"x")}else{if(this.fillToZero){J=this._xaxis.series_u2p(0)}else{J=0}}C.push([J,q+this.barWidth/2]);C.push([G[D][0],q+this.barWidth/2]);C.push([G[D][0],q-this.barWidth/2]);C.push([J,q-this.barWidth/2]);this.renderer.shadowRenderer.draw(z,C,w)}}}}}};function h(q,p,n){for(var o=0;o<this.series.length;o++){if(this.series[o].renderer.constructor==d.jqplot.BarRenderer){if(this.series[o].highlightMouseOver){this.series[o].highlightMouseDown=false}}}}function j(){if(this.plugins.barRenderer&&this.plugins.barRenderer.highlightCanvas){this.plugins.barRenderer.highlightCanvas.resetCanvas();this.plugins.barRenderer.highlightCanvas=null}this.plugins.barRenderer={highlightedSeriesIndex:null};this.plugins.barRenderer.highlightCanvas=new d.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.barRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-barRenderer-highlight-canvas",this._plotDimensions,this));this.plugins.barRenderer.highlightCanvas.setContext();this.eventCanvas._elem.bind("mouseleave",{plot:this},function(n){k(n.data.plot)})}function c(u,t,q,p){var o=u.series[t];var n=u.plugins.barRenderer.highlightCanvas;n._ctx.clearRect(0,0,n._ctx.canvas.width,n._ctx.canvas.height);o._highlightedPoint=q;u.plugins.barRenderer.highlightedSeriesIndex=t;var r={fillStyle:o.highlightColors[q]};o.renderer.shapeRenderer.draw(n._ctx,p,r);n=null}function k(p){var n=p.plugins.barRenderer.highlightCanvas;n._ctx.clearRect(0,0,n._ctx.canvas.width,n._ctx.canvas.height);for(var o=0;o<p.series.length;o++){p.series[o]._highlightedPoint=null}p.plugins.barRenderer.highlightedSeriesIndex=null;p.target.trigger("jqplotDataUnhighlight");n=null}function b(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];var o=jQuery.Event("jqplotDataMouseOver");o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p);if(s.series[p[0]].show&&s.series[p[0]].highlightMouseOver&&!(p[0]==s.plugins.barRenderer.highlightedSeriesIndex&&p[1]==s.series[p[0]]._highlightedPoint)){var n=jQuery.Event("jqplotDataHighlight");n.which=r.which;n.pageX=r.pageX;n.pageY=r.pageY;s.target.trigger(n,p);c(s,t.seriesIndex,t.pointIndex,t.points)}}else{if(t==null){k(s)}}}function a(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];if(r.series[o[0]].highlightMouseDown&&!(o[0]==r.plugins.barRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){var n=jQuery.Event("jqplotDataHighlight");n.which=q.which;n.pageX=q.pageX;n.pageY=q.pageY;r.target.trigger(n,o);c(r,s.seriesIndex,s.pointIndex,s.points)}}else{if(s==null){k(r)}}}function l(p,o,s,r,q){var n=q.plugins.barRenderer.highlightedSeriesIndex;if(n!=null&&q.series[n].highlightMouseDown){k(q)}}function e(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];var n=jQuery.Event("jqplotDataClick");n.which=q.which;n.pageX=q.pageX;n.pageY=q.pageY;r.target.trigger(n,o)}}function m(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];var n=s.plugins.barRenderer.highlightedSeriesIndex;if(n!=null&&s.series[n].highlightMouseDown){k(s)}var o=jQuery.Event("jqplotDataRightClick");o.which=r.which;o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p)}}})(jQuery);
WRFILE: jqplot.dateAxisRenderer.min.js

(function(h){h.jqplot.DateAxisRenderer=function(){h.jqplot.LinearAxisRenderer.call(this);this.date=new h.jsDate()};var c=1000;var e=60*c;var f=60*e;var l=24*f;var b=7*l;var j=30.4368499*l;var k=365.242199*l;var g=[31,28,31,30,31,30,31,30,31,30,31,30];var i=["%M:%S.%#N","%M:%S.%#N","%M:%S.%#N","%M:%S","%M:%S","%M:%S","%M:%S","%H:%M:%S","%H:%M:%S","%H:%M","%H:%M","%H:%M","%H:%M","%H:%M","%H:%M","%a %H:%M","%a %H:%M","%b %e %H:%M","%b %e %H:%M","%b %e %H:%M","%b %e %H:%M","%v","%v","%v","%v","%v","%v","%v"];var m=[0.1*c,0.2*c,0.5*c,c,2*c,5*c,10*c,15*c,30*c,e,2*e,5*e,10*e,15*e,30*e,f,2*f,4*f,6*f,8*f,12*f,l,2*l,3*l,4*l,5*l,b,2*b];var d=[];function a(p,s,t){var o=Number.MAX_VALUE;var u,r,v;for(var q=0,n=m.length;q<n;q++){u=Math.abs(t-m[q]);if(u<o){o=u;r=m[q];v=i[q]}}return[r,v]}h.jqplot.DateAxisRenderer.prototype=new h.jqplot.LinearAxisRenderer();h.jqplot.DateAxisRenderer.prototype.constructor=h.jqplot.DateAxisRenderer;h.jqplot.DateTickFormatter=function(n,o){if(!n){n="%Y/%m/%d"}return h.jsDate.strftime(o,n)};h.jqplot.DateAxisRenderer.prototype.init=function(E){this.tickOptions.formatter=h.jqplot.DateTickFormatter;this.tickInset=0;this.drawBaseline=true;this.baselineWidth=null;this.baselineColor=null;this.daTickInterval=null;this._daTickInterval=null;h.extend(true,this,E);var C=this._dataBounds,u,x,D,y,A,z,o;for(var t=0;t<this._series.length;t++){u={intervals:[],frequencies:{},sortedIntervals:[],min:null,max:null,mean:null};x=0;D=this._series[t];y=D.data;A=D._plotData;z=D._stackData;o=0;for(var r=0;r<y.length;r++){if(this.name=="xaxis"||this.name=="x2axis"){y[r][0]=new h.jsDate(y[r][0]).getTime();A[r][0]=new h.jsDate(y[r][0]).getTime();z[r][0]=new h.jsDate(y[r][0]).getTime();if((y[r][0]!=null&&y[r][0]<C.min)||C.min==null){C.min=y[r][0]}if((y[r][0]!=null&&y[r][0]>C.max)||C.max==null){C.max=y[r][0]}if(r>0){o=Math.abs(y[r][0]-y[r-1][0]);u.intervals.push(o);if(u.frequencies.hasOwnProperty(o)){u.frequencies[o]+=1}else{u.frequencies[o]=1}}x+=o}else{y[r][1]=new h.jsDate(y[r][1]).getTime();A[r][1]=new h.jsDate(y[r][1]).getTime();z[r][1]=new h.jsDate(y[r][1]).getTime();if((y[r][1]!=null&&y[r][1]<C.min)||C.min==null){C.min=y[r][1]}if((y[r][1]!=null&&y[r][1]>C.max)||C.max==null){C.max=y[r][1]}if(r>0){o=Math.abs(y[r][1]-y[r-1][1]);u.intervals.push(o);if(u.frequencies.hasOwnProperty(o)){u.frequencies[o]+=1}else{u.frequencies[o]=1}}}x+=o}if(D.renderer.bands){if(D.renderer.bands.hiData.length){var w=D.renderer.bands.hiData;for(var r=0,q=w.length;r<q;r++){if(this.name==="xaxis"||this.name==="x2axis"){w[r][0]=new h.jsDate(w[r][0]).getTime();if((w[r][0]!=null&&w[r][0]>C.max)||C.max==null){C.max=w[r][0]}}else{w[r][1]=new h.jsDate(w[r][1]).getTime();if((w[r][1]!=null&&w[r][1]>C.max)||C.max==null){C.max=w[r][1]}}}}if(D.renderer.bands.lowData.length){var w=D.renderer.bands.lowData;for(var r=0,q=w.length;r<q;r++){if(this.name==="xaxis"||this.name==="x2axis"){w[r][0]=new h.jsDate(w[r][0]).getTime();if((w[r][0]!=null&&w[r][0]<C.min)||C.min==null){C.min=w[r][0]}}else{w[r][1]=new h.jsDate(w[r][1]).getTime();if((w[r][1]!=null&&w[r][1]<C.min)||C.min==null){C.min=w[r][1]}}}}}var B=0,v=0;for(var p in u.frequencies){u.sortedIntervals.push({interval:p,frequency:u.frequencies[p]})}u.sortedIntervals.sort(function(s,n){return n.frequency-s.frequency});u.min=h.jqplot.arrayMin(u.intervals);u.max=h.jqplot.arrayMax(u.intervals);u.mean=x/y.length;this._intervalStats.push(u);u=x=D=y=A=z=null}C=null};h.jqplot.DateAxisRenderer.prototype.reset=function(){this.min=this._options.min;this.max=this._options.max;this.tickInterval=this._options.tickInterval;this.numberTicks=this._options.numberTicks;this._autoFormatString="";if(this._overrideFormatString&&this.tickOptions&&this.tickOptions.formatString){this.tickOptions.formatString=""}this.daTickInterval=this._daTickInterval};h.jqplot.DateAxisRenderer.prototype.createTicks=function(p){var X=this._ticks;var L=this.ticks;var F=this.name;var H=this._dataBounds;var M=this._intervalStats;var n=(this.name.charAt(0)==="x")?this._plotDimensions.width:this._plotDimensions.height;var w;var ae,J;var y,x;var ad,aa;var s=30;var O=1;var U=null;if(this.tickInterval!=null){if(Number(this.tickInterval)){U=[Number(this.tickInterval),"seconds"]}else{if(typeof this.tickInterval=="string"){var ac=this.tickInterval.split(" ");if(ac.length==1){U=[1,ac[0]]}else{if(ac.length==2){U=[ac[0],ac[1]]}}}}}var v=this.tickInterval;ae=new h.jsDate((this.min!=null)?this.min:H.min).getTime();J=new h.jsDate((this.max!=null)?this.max:H.max).getTime();var A=p.plugins.cursor;if(A&&A._zoom&&A._zoom.zooming){this.min=null;this.max=null}var B=J-ae;if(this.tickOptions==null||!this.tickOptions.formatString){this._overrideFormatString=true}if(L.length){for(aa=0;aa<L.length;aa++){var P=L[aa];var Y=new this.tickRenderer(this.tickOptions);if(P.constructor==Array){Y.value=new h.jsDate(P[0]).getTime();Y.label=P[1];if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}Y.setTick(Y.value,this.name);this._ticks.push(Y)}else{Y.value=new h.jsDate(P).getTime();if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}Y.setTick(Y.value,this.name);this._ticks.push(Y)}}this.numberTicks=L.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value;this.daTickInterval=[(this.max-this.min)/(this.numberTicks-1)/1000,"seconds"]}else{if(this.min==null&&this.max==null&&H.min==H.max){var E=h.extend(true,{},this.tickOptions,{name:this.name,value:null});var T=300000;this.min=H.min-T;this.max=H.max+T;this.numberTicks=3;for(var aa=this.min;aa<=this.max;aa+=T){E.value=aa;var Y=new this.tickRenderer(E);if(this._overrideFormatString&&this._autoFormatString!=""){Y.formatString=this._autoFormatString}Y.showLabel=false;Y.showMark=false;this._ticks.push(Y)}if(this.showTicks){this._ticks[1].showLabel=true}if(this.showTickMarks){this._ticks[1].showTickMarks=true}}else{if(this.min==null&&this.max==null){var N=h.extend(true,{},this.tickOptions,{name:this.name,value:null});var ab,I;if(!this.tickInterval&&!this.numberTicks){var R=Math.max(n,s+1);var Z=115;if(this.tickRenderer===h.jqplot.CanvasAxisTickRenderer&&this.tickOptions.angle){Z=115-40*Math.abs(Math.sin(this.tickOptions.angle/180*Math.PI))}ab=Math.ceil((R-s)/Z+1);I=(J-ae)/(ab-1)}else{if(this.tickInterval){I=new h.jsDate(0).add(U[0],U[1]).getTime()}else{if(this.numberTicks){ab=this.numberTicks;I=(J-ae)/(ab-1)}}}if(I<=19*l){var Q=a(ae,J,I);var r=Q[0];this._autoFormatString=Q[1];ae=new h.jsDate(ae);ae=Math.floor((ae.getTime()-ae.getUtcOffset())/r)*r+ae.getUtcOffset();ab=Math.ceil((J-ae)/r)+1;this.min=ae;this.max=ae+(ab-1)*r;if(this.max<J){this.max+=r;ab+=1}this.tickInterval=r;this.numberTicks=ab;for(var aa=0;aa<ab;aa++){N.value=this.min+aa*r;Y=new this.tickRenderer(N);if(this._overrideFormatString&&this._autoFormatString!=""){Y.formatString=this._autoFormatString}if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}this._ticks.push(Y)}O=this.tickInterval}else{if(I<=9*j){this._autoFormatString="%v";var D=Math.round(I/j);if(D<1){D=1}else{if(D>6){D=6}}var V=new h.jsDate(ae).setDate(1).setHours(0,0,0,0);var q=new h.jsDate(J);var z=new h.jsDate(J).setDate(1).setHours(0,0,0,0);if(q.getTime()!==z.getTime()){z=z.add(1,"month")}var S=z.diff(V,"month");ab=Math.ceil(S/D)+1;this.min=V.getTime();this.max=V.clone().add((ab-1)*D,"month").getTime();this.numberTicks=ab;for(var aa=0;aa<ab;aa++){if(aa===0){N.value=V.getTime()}else{N.value=V.add(D,"month").getTime()}Y=new this.tickRenderer(N);if(this._overrideFormatString&&this._autoFormatString!=""){Y.formatString=this._autoFormatString}if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}this._ticks.push(Y)}O=D*j}else{this._autoFormatString="%v";var D=Math.round(I/k);if(D<1){D=1}var V=new h.jsDate(ae).setMonth(0,1).setHours(0,0,0,0);var z=new h.jsDate(J).add(1,"year").setMonth(0,1).setHours(0,0,0,0);var K=z.diff(V,"year");ab=Math.ceil(K/D)+1;this.min=V.getTime();this.max=V.clone().add((ab-1)*D,"year").getTime();this.numberTicks=ab;for(var aa=0;aa<ab;aa++){if(aa===0){N.value=V.getTime()}else{N.value=V.add(D,"year").getTime()}Y=new this.tickRenderer(N);if(this._overrideFormatString&&this._autoFormatString!=""){Y.formatString=this._autoFormatString}if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}this._ticks.push(Y)}O=D*k}}}else{if(F=="xaxis"||F=="x2axis"){n=this._plotDimensions.width}else{n=this._plotDimensions.height}if(this.min!=null&&this.max!=null&&this.numberTicks!=null){this.tickInterval=null}if(this.tickInterval!=null&&U!=null){this.daTickInterval=U}if(ae==J){var o=24*60*60*500;ae-=o;J+=o}B=J-ae;var G=2+parseInt(Math.max(0,n-100)/100,10);var W,C;W=(this.min!=null)?new h.jsDate(this.min).getTime():ae-B/2*(this.padMin-1);C=(this.max!=null)?new h.jsDate(this.max).getTime():J+B/2*(this.padMax-1);this.min=W;this.max=C;B=this.max-this.min;if(this.numberTicks==null){if(this.daTickInterval!=null){var u=new h.jsDate(this.max).diff(this.min,this.daTickInterval[1],true);this.numberTicks=Math.ceil(u/this.daTickInterval[0])+1;this.max=new h.jsDate(this.min).add((this.numberTicks-1)*this.daTickInterval[0],this.daTickInterval[1]).getTime()}else{if(n>200){this.numberTicks=parseInt(3+(n-200)/100,10)}else{this.numberTicks=2}}}O=B/(this.numberTicks-1)/1000;if(this.daTickInterval==null){this.daTickInterval=[O,"seconds"]}for(var aa=0;aa<this.numberTicks;aa++){var ae=new h.jsDate(this.min);ad=ae.add(aa*this.daTickInterval[0],this.daTickInterval[1]).getTime();var Y=new this.tickRenderer(this.tickOptions);if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}Y.setTick(ad,this.name);this._ticks.push(Y)}}}}if(this.tickInset){this.min=this.min-this.tickInset*O;this.max=this.max+this.tickInset*O}if(this._daTickInterval==null){this._daTickInterval=this.daTickInterval}X=null}})(jQuery);
WRFILE: jqplot.canvasTextRenderer.min.js

(function(a){a.jqplot.CanvasTextRenderer=function(b){this.fontStyle="normal";this.fontVariant="normal";this.fontWeight="normal";this.fontSize="10px";this.fontFamily="sans-serif";this.fontStretch=1;this.fillStyle="#666666";this.angle=0;this.textAlign="start";this.textBaseline="alphabetic";this.text;this.width;this.height;this.pt2px=1.28;a.extend(true,this,b);this.normalizedFontSize=this.normalizeFontSize(this.fontSize);this.setHeight()};a.jqplot.CanvasTextRenderer.prototype.init=function(b){a.extend(true,this,b);this.normalizedFontSize=this.normalizeFontSize(this.fontSize);this.setHeight()};a.jqplot.CanvasTextRenderer.prototype.normalizeFontSize=function(b){b=String(b);var c=parseFloat(b);if(b.indexOf("px")>-1){return c/this.pt2px}else{if(b.indexOf("pt")>-1){return c}else{if(b.indexOf("em")>-1){return c*12}else{if(b.indexOf("%")>-1){return c*12/100}else{return c/this.pt2px}}}}};a.jqplot.CanvasTextRenderer.prototype.fontWeight2Float=function(b){if(Number(b)){return b/400}else{switch(b){case"normal":return 1;break;case"bold":return 1.75;break;case"bolder":return 2.25;break;case"lighter":return 0.75;break;default:return 1;break}}};a.jqplot.CanvasTextRenderer.prototype.getText=function(){return this.text};a.jqplot.CanvasTextRenderer.prototype.setText=function(c,b){this.text=c;this.setWidth(b);return this};a.jqplot.CanvasTextRenderer.prototype.getWidth=function(b){return this.width};a.jqplot.CanvasTextRenderer.prototype.setWidth=function(c,b){if(!b){this.width=this.measure(c,this.text)}else{this.width=b}return this};a.jqplot.CanvasTextRenderer.prototype.getHeight=function(b){return this.height};a.jqplot.CanvasTextRenderer.prototype.setHeight=function(b){if(!b){this.height=this.normalizedFontSize*this.pt2px}else{this.height=b}return this};a.jqplot.CanvasTextRenderer.prototype.letter=function(b){return this.letters[b]};a.jqplot.CanvasTextRenderer.prototype.ascent=function(){return this.normalizedFontSize};a.jqplot.CanvasTextRenderer.prototype.descent=function(){return 7*this.normalizedFontSize/25};a.jqplot.CanvasTextRenderer.prototype.measure=function(d,g){var f=0;var b=g.length;for(var e=0;e<b;e++){var h=this.letter(g.charAt(e));if(h){f+=h.width*this.normalizedFontSize/25*this.fontStretch}}return f};a.jqplot.CanvasTextRenderer.prototype.draw=function(s,n){var r=0;var o=this.height*0.72;var p=0;var l=n.length;var k=this.normalizedFontSize/25;s.save();var h,f;if((-Math.PI/2<=this.angle&&this.angle<=0)||(Math.PI*3/2<=this.angle&&this.angle<=Math.PI*2)){h=0;f=-Math.sin(this.angle)*this.width}else{if((0<this.angle&&this.angle<=Math.PI/2)||(-Math.PI*2<=this.angle&&this.angle<=-Math.PI*3/2)){h=Math.sin(this.angle)*this.height;f=0}else{if((-Math.PI<this.angle&&this.angle<-Math.PI/2)||(Math.PI<=this.angle&&this.angle<=Math.PI*3/2)){h=-Math.cos(this.angle)*this.width;f=-Math.sin(this.angle)*this.width-Math.cos(this.angle)*this.height}else{if((-Math.PI*3/2<this.angle&&this.angle<Math.PI)||(Math.PI/2<this.angle&&this.angle<Math.PI)){h=Math.sin(this.angle)*this.height-Math.cos(this.angle)*this.width;f=-Math.cos(this.angle)*this.height}}}}s.strokeStyle=this.fillStyle;s.fillStyle=this.fillStyle;s.translate(h,f);s.rotate(this.angle);s.lineCap="round";var t=(this.normalizedFontSize>30)?2:2+(30-this.normalizedFontSize)/20;s.lineWidth=t*k*this.fontWeight2Float(this.fontWeight);for(var g=0;g<l;g++){var m=this.letter(n.charAt(g));if(!m){continue}s.beginPath();var e=1;var b=0;for(var d=0;d<m.points.length;d++){var q=m.points[d];if(q[0]==-1&&q[1]==-1){e=1;continue}if(e){s.moveTo(r+q[0]*k*this.fontStretch,o-q[1]*k);e=false}else{s.lineTo(r+q[0]*k*this.fontStretch,o-q[1]*k)}}s.stroke();r+=m.width*k*this.fontStretch}s.restore();return p};a.jqplot.CanvasTextRenderer.prototype.letters={" ":{width:16,points:[]},"!":{width:10,points:[[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]]},'"':{width:16,points:[[4,21],[4,14],[-1,-1],[12,21],[12,14]]},"#":{width:21,points:[[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]]},"$":{width:20,points:[[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},"%":{width:24,points:[[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]]},"&":{width:26,points:[[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]]},"'":{width:10,points:[[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]]},"(":{width:14,points:[[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]]},")":{width:14,points:[[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]]},"*":{width:16,points:[[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]]},"+":{width:26,points:[[13,18],[13,0],[-1,-1],[4,9],[22,9]]},",":{width:10,points:[[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]]},"-":{width:18,points:[[6,9],[12,9]]},".":{width:10,points:[[5,2],[4,1],[5,0],[6,1],[5,2]]},"/":{width:22,points:[[20,25],[2,-7]]},"0":{width:20,points:[[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]]},"1":{width:20,points:[[6,17],[8,18],[11,21],[11,0]]},"2":{width:20,points:[[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]]},"3":{width:20,points:[[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]]},"4":{width:20,points:[[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]]},"5":{width:20,points:[[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]]},"6":{width:20,points:[[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]]},"7":{width:20,points:[[17,21],[7,0],[-1,-1],[3,21],[17,21]]},"8":{width:20,points:[[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]]},"9":{width:20,points:[[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]]},":":{width:10,points:[[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]]},";":{width:10,points:[[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]]},"<":{width:24,points:[[20,18],[4,9],[20,0]]},"=":{width:26,points:[[4,12],[22,12],[-1,-1],[4,6],[22,6]]},">":{width:24,points:[[4,18],[20,9],[4,0]]},"?":{width:18,points:[[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]]},"@":{width:27,points:[[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]]},A:{width:18,points:[[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]]},B:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]]},C:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]]},D:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]]},E:{width:19,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]]},F:{width:18,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]]},G:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]]},H:{width:22,points:[[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]]},I:{width:8,points:[[4,21],[4,0]]},J:{width:16,points:[[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]]},K:{width:21,points:[[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]]},L:{width:17,points:[[4,21],[4,0],[-1,-1],[4,0],[16,0]]},M:{width:24,points:[[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]]},N:{width:22,points:[[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]]},O:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]]},P:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]]},Q:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]]},R:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]]},S:{width:20,points:[[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},T:{width:16,points:[[8,21],[8,0],[-1,-1],[1,21],[15,21]]},U:{width:22,points:[[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]]},V:{width:18,points:[[1,21],[9,0],[-1,-1],[17,21],[9,0]]},W:{width:24,points:[[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]]},X:{width:20,points:[[3,21],[17,0],[-1,-1],[17,21],[3,0]]},Y:{width:18,points:[[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]]},Z:{width:20,points:[[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]]},"[":{width:14,points:[[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]]},"\\":{width:14,points:[[0,21],[14,-3]]},"]":{width:14,points:[[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]]},"^":{width:16,points:[[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]]},_:{width:16,points:[[0,-2],[16,-2]]},"`":{width:10,points:[[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]]},a:{width:19,points:[[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},b:{width:19,points:[[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},c:{width:18,points:[[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},d:{width:19,points:[[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},e:{width:18,points:[[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},f:{width:12,points:[[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]]},g:{width:19,points:[[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},h:{width:19,points:[[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},i:{width:8,points:[[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]]},j:{width:10,points:[[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]]},k:{width:17,points:[[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]]},l:{width:8,points:[[4,21],[4,0]]},m:{width:30,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]]},n:{width:19,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},o:{width:19,points:[[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]]},p:{width:19,points:[[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},q:{width:19,points:[[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},r:{width:13,points:[[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]]},s:{width:17,points:[[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]]},t:{width:12,points:[[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]]},u:{width:19,points:[[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]]},v:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0]]},w:{width:22,points:[[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]]},x:{width:17,points:[[3,14],[14,0],[-1,-1],[14,14],[3,0]]},y:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]]},z:{width:17,points:[[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]]},"{":{width:14,points:[[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]]},"|":{width:8,points:[[4,25],[4,-7]]},"}":{width:14,points:[[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]]},"~":{width:24,points:[[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]]}};a.jqplot.CanvasFontRenderer=function(b){b=b||{};if(!b.pt2px){b.pt2px=1.5}a.jqplot.CanvasTextRenderer.call(this,b)};a.jqplot.CanvasFontRenderer.prototype=new a.jqplot.CanvasTextRenderer({});a.jqplot.CanvasFontRenderer.prototype.constructor=a.jqplot.CanvasFontRenderer;a.jqplot.CanvasFontRenderer.prototype.measure=function(c,e){var d=this.fontSize+" "+this.fontFamily;c.save();c.font=d;var b=c.measureText(e).width;c.restore();return b};a.jqplot.CanvasFontRenderer.prototype.draw=function(e,g){var c=0;var h=this.height*0.72;e.save();var d,b;if((-Math.PI/2<=this.angle&&this.angle<=0)||(Math.PI*3/2<=this.angle&&this.angle<=Math.PI*2)){d=0;b=-Math.sin(this.angle)*this.width}else{if((0<this.angle&&this.angle<=Math.PI/2)||(-Math.PI*2<=this.angle&&this.angle<=-Math.PI*3/2)){d=Math.sin(this.angle)*this.height;b=0}else{if((-Math.PI<this.angle&&this.angle<-Math.PI/2)||(Math.PI<=this.angle&&this.angle<=Math.PI*3/2)){d=-Math.cos(this.angle)*this.width;b=-Math.sin(this.angle)*this.width-Math.cos(this.angle)*this.height}else{if((-Math.PI*3/2<this.angle&&this.angle<Math.PI)||(Math.PI/2<this.angle&&this.angle<Math.PI)){d=Math.sin(this.angle)*this.height-Math.cos(this.angle)*this.width;b=-Math.cos(this.angle)*this.height}}}}e.strokeStyle=this.fillStyle;e.fillStyle=this.fillStyle;var f=this.fontSize+" "+this.fontFamily;e.font=f;e.translate(d,b);e.rotate(this.angle);e.fillText(g,c,h);e.restore()}})(jQuery);
WRFILE: jqplot.categoryAxisRenderer.min.js

(function(a){a.jqplot.CategoryAxisRenderer=function(b){a.jqplot.LinearAxisRenderer.call(this);this.sortMergedLabels=false};a.jqplot.CategoryAxisRenderer.prototype=new a.jqplot.LinearAxisRenderer();a.jqplot.CategoryAxisRenderer.prototype.constructor=a.jqplot.CategoryAxisRenderer;a.jqplot.CategoryAxisRenderer.prototype.init=function(e){this.groups=1;this.groupLabels=[];this._groupLabels=[];this._grouped=false;this._barsPerGroup=null;this.reverse=false;a.extend(true,this,{tickOptions:{formatString:"%d"}},e);var b=this._dataBounds;for(var f=0;f<this._series.length;f++){var g=this._series[f];if(g.groups){this.groups=g.groups}var h=g.data;for(var c=0;c<h.length;c++){if(this.name=="xaxis"||this.name=="x2axis"){if(h[c][0]<b.min||b.min==null){b.min=h[c][0]}if(h[c][0]>b.max||b.max==null){b.max=h[c][0]}}else{if(h[c][1]<b.min||b.min==null){b.min=h[c][1]}if(h[c][1]>b.max||b.max==null){b.max=h[c][1]}}}}if(this.groupLabels.length){this.groups=this.groupLabels.length}};a.jqplot.CategoryAxisRenderer.prototype.createTicks=function(){var D=this._ticks;var z=this.ticks;var F=this.name;var C=this._dataBounds;var v,A;var q,w;var d,c;var b,x;if(z.length){if(this.groups>1&&!this._grouped){var r=z.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x<r;x+=p){z.splice(x+e,0," ");e++}this._grouped=true}this.min=0.5;this.max=z.length+0.5;var m=this.max-this.min;this.numberTicks=2*z.length+1;for(x=0;x<z.length;x++){b=this.min+2*x*m/(this.numberTicks-1);var h=new this.tickRenderer(this.tickOptions);h.showLabel=false;h.setTick(b,this.name);this._ticks.push(h);var h=new this.tickRenderer(this.tickOptions);h.label=z[x];h.showMark=false;h.showGridline=false;h.setTick(b+0.5,this.name);this._ticks.push(h)}var h=new this.tickRenderer(this.tickOptions);h.showLabel=false;h.setTick(b+1,this.name);this._ticks.push(h)}else{if(F=="xaxis"||F=="x2axis"){v=this._plotDimensions.width}else{v=this._plotDimensions.height}if(this.min!=null&&this.max!=null&&this.numberTicks!=null){this.tickInterval=null}if(this.min!=null&&this.max!=null&&this.tickInterval!=null){if(parseInt((this.max-this.min)/this.tickInterval,10)!=(this.max-this.min)/this.tickInterval){this.tickInterval=null}}var y=[];var B=0;var q=0.5;var w,E;var f=false;for(var x=0;x<this._series.length;x++){var k=this._series[x];for(var u=0;u<k.data.length;u++){if(this.name=="xaxis"||this.name=="x2axis"){E=k.data[u][0]}else{E=k.data[u][1]}if(a.inArray(E,y)==-1){f=true;B+=1;y.push(E)}}}if(f&&this.sortMergedLabels){if(typeof y[0]=="string"){y.sort()}else{y.sort(function(j,i){return j-i})}}this.ticks=y;for(var x=0;x<this._series.length;x++){var k=this._series[x];for(var u=0;u<k.data.length;u++){if(this.name=="xaxis"||this.name=="x2axis"){E=k.data[u][0]}else{E=k.data[u][1]}var n=a.inArray(E,y)+1;if(this.name=="xaxis"||this.name=="x2axis"){k.data[u][0]=n}else{k.data[u][1]=n}}}if(this.groups>1&&!this._grouped){var r=y.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x<r;x+=p+1){y[x]=" "}this._grouped=true}w=B+0.5;if(this.numberTicks==null){this.numberTicks=2*B+1}var m=w-q;this.min=q;this.max=w;var o=0;var g=parseInt(3+v/10,10);var p=parseInt(B/g,10);if(this.tickInterval==null){this.tickInterval=m/(this.numberTicks-1)}for(var x=0;x<this.numberTicks;x++){b=this.min+x*this.tickInterval;var h=new this.tickRenderer(this.tickOptions);if(x/2==parseInt(x/2,10)){h.showLabel=false;h.showMark=true}else{if(p>0&&o<p){h.showLabel=false;o+=1}else{h.showLabel=true;o=0}h.label=h.formatter(h.formatString,y[(x-1)/2]);h.showMark=false;h.showGridline=false}h.setTick(b,this.name);this._ticks.push(h)}}};a.jqplot.CategoryAxisRenderer.prototype.draw=function(b,j){if(this.show){this.renderer.createTicks.call(this);var h=0;var c;if(this._elem){this._elem.emptyForce()}this._elem=this._elem||a('<div class="jqplot-axis jqplot-'+this.name+'" style="position:absolute;"></div>');if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){var g=this._label.draw(b,j);g.appendTo(this._elem)}var f=this._ticks;for(var e=0;e<f.length;e++){var d=f[e];if(d.showLabel&&(!d.isMinorTick||this.showMinorTicks)){var g=d.draw(b,j);g.appendTo(this._elem)}}this._groupLabels=[];for(var e=0;e<this.groupLabels.length;e++){var g=a('<div style="position:absolute;" class="jqplot-'+this.name+'-groupLabel"></div>');g.html(this.groupLabels[e]);this._groupLabels.push(g);g.appendTo(this._elem)}}return this._elem};a.jqplot.CategoryAxisRenderer.prototype.set=function(){var e=0;var m;var k=0;var f=0;var d=(this._label==null)?false:this._label.show;if(this.show){var n=this._ticks;for(var c=0;c<n.length;c++){var g=n[c];if(g.showLabel&&(!g.isMinorTick||this.showMinorTicks)){if(this.name=="xaxis"||this.name=="x2axis"){m=g._elem.outerHeight(true)}else{m=g._elem.outerWidth(true)}if(m>e){e=m}}}var j=0;for(var c=0;c<this._groupLabels.length;c++){var b=this._groupLabels[c];if(this.name=="xaxis"||this.name=="x2axis"){m=b.outerHeight(true)}else{m=b.outerWidth(true)}if(m>j){j=m}}if(d){k=this._label._elem.outerWidth(true);f=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){e+=j+k;this._elem.css({width:e+"px",left:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}else{e+=j+k;this._elem.css({width:e+"px",right:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}}}}};a.jqplot.CategoryAxisRenderer.prototype.pack=function(e,c){var C=this._ticks;var v=this.max;var s=this.min;var n=c.max;var l=c.min;var q=(this._label==null)?false:this._label.show;var x;for(var r in e){this._elem.css(r,e[r])}this._offsets=c;var g=n-l;var k=v-s;if(!this.reverse){this.u2p=function(h){return(h-s)*g/k+l};this.p2u=function(h){return(h-l)*k/g+s};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(h-s)*g/k};this.series_p2u=function(h){return h*k/g+s}}else{this.series_u2p=function(h){return(h-v)*g/k};this.series_p2u=function(h){return h*k/g+v}}}else{this.u2p=function(h){return l+(v-h)*g/k};this.p2u=function(h){return s+(h-l)*k/g};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(v-h)*g/k};this.series_p2u=function(h){return h*k/g+v}}else{this.series_u2p=function(h){return(s-h)*g/k};this.series_p2u=function(h){return h*k/g+s}}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(x=0;x<C.length;x++){var o=C[x];if(o.show&&o.showLabel){var b;if(o.constructor==a.jqplot.CanvasAxisTickRenderer&&o.angle){var A=(this.name=="xaxis")?1:-1;switch(o.labelPosition){case"auto":if(A*o.angle<0){b=-o.getWidth()+o._textRenderer.height*Math.sin(-o._textRenderer.angle)/2}else{b=-o._textRenderer.height*Math.sin(o._textRenderer.angle)/2}break;case"end":b=-o.getWidth()+o._textRenderer.height*Math.sin(-o._textRenderer.angle)/2;break;case"start":b=-o._textRenderer.height*Math.sin(o._textRenderer.angle)/2;break;case"middle":b=-o.getWidth()/2+o._textRenderer.height*Math.sin(-o._textRenderer.angle)/2;break;default:b=-o.getWidth()/2+o._textRenderer.height*Math.sin(-o._textRenderer.angle)/2;break}}else{b=-o.getWidth()/2}var D=this.u2p(o.value)+b+"px";o._elem.css("left",D);o.pack()}}var z=["bottom",0];if(q){var m=this._label._elem.outerWidth(true);this._label._elem.css("left",l+g/2-m/2+"px");if(this.name=="xaxis"){this._label._elem.css("bottom","0px");z=["bottom",this._label._elem.outerHeight(true)]}else{this._label._elem.css("top","0px");z=["top",this._label._elem.outerHeight(true)]}this._label.pack()}var d=parseInt(this._ticks.length/this.groups,10)+1;for(x=0;x<this._groupLabels.length;x++){var B=0;var f=0;for(var u=x*d;u<(x+1)*d;u++){if(u>=this._ticks.length-1){continue}if(this._ticks[u]._elem&&this._ticks[u].label!=" "){var o=this._ticks[u]._elem;var r=o.position();B+=r.left+o.outerWidth(true)/2;f++}}B=B/f;this._groupLabels[x].css({left:(B-this._groupLabels[x].outerWidth(true)/2)});this._groupLabels[x].css(z[0],z[1])}}else{for(x=0;x<C.length;x++){var o=C[x];if(o.show&&o.showLabel){var b;if(o.constructor==a.jqplot.CanvasAxisTickRenderer&&o.angle){var A=(this.name=="yaxis")?1:-1;switch(o.labelPosition){case"auto":case"end":if(A*o.angle<0){b=-o._textRenderer.height*Math.cos(-o._textRenderer.angle)/2}else{b=-o.getHeight()+o._textRenderer.height*Math.cos(o._textRenderer.angle)/2}break;case"start":if(o.angle>0){b=-o._textRenderer.height*Math.cos(-o._textRenderer.angle)/2}else{b=-o.getHeight()+o._textRenderer.height*Math.cos(o._textRenderer.angle)/2}break;case"middle":b=-o.getHeight()/2;break;default:b=-o.getHeight()/2;break}}else{b=-o.getHeight()/2}var D=this.u2p(o.value)+b+"px";o._elem.css("top",D);o.pack()}}var z=["left",0];if(q){var y=this._label._elem.outerHeight(true);this._label._elem.css("top",n-g/2-y/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px");z=["left",this._label._elem.outerWidth(true)]}else{this._label._elem.css("right","0px");z=["right",this._label._elem.outerWidth(true)]}this._label.pack()}var d=parseInt(this._ticks.length/this.groups,10)+1;for(x=0;x<this._groupLabels.length;x++){var B=0;var f=0;for(var u=x*d;u<(x+1)*d;u++){if(u>=this._ticks.length-1){continue}if(this._ticks[u]._elem&&this._ticks[u].label!=" "){var o=this._ticks[u]._elem;var r=o.position();B+=r.top+o.outerHeight()/2;f++}}B=B/f;this._groupLabels[x].css({top:B-this._groupLabels[x].outerHeight()/2});this._groupLabels[x].css(z[0],z[1])}}}}})(jQuery);
WRFILE: jqplot.canvasAxisTickRenderer.min.js

(function(a){a.jqplot.CanvasAxisTickRenderer=function(b){this.mark="outside";this.showMark=true;this.showGridline=true;this.isMinorTick=false;this.angle=0;this.markSize=4;this.show=true;this.showLabel=true;this.labelPosition="auto";this.label="";this.value=null;this._styles={};this.formatter=a.jqplot.DefaultTickFormatter;this.formatString="";this.prefix="";this.fontFamily='"Trebuchet MS", Arial, Helvetica, sans-serif';this.fontSize="10pt";this.fontWeight="normal";this.fontStretch=1;this.textColor="#666666";this.enableFontSupport=true;this.pt2px=null;this._elem;this._ctx;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null};a.extend(true,this,b);var c={fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily};if(this.pt2px){c.pt2px=this.pt2px}if(this.enableFontSupport){if(a.jqplot.support_canvas_text()){this._textRenderer=new a.jqplot.CanvasFontRenderer(c)}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}};a.jqplot.CanvasAxisTickRenderer.prototype.init=function(b){a.extend(true,this,b);this._textRenderer.init({fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily})};a.jqplot.CanvasAxisTickRenderer.prototype.getWidth=function(d){if(this._elem){return this._elem.outerWidth(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.sin(f.angle)*e)+Math.abs(Math.cos(f.angle)*c);return b}};a.jqplot.CanvasAxisTickRenderer.prototype.getHeight=function(d){if(this._elem){return this._elem.outerHeight(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.cos(f.angle)*e)+Math.abs(Math.sin(f.angle)*c);return b}};a.jqplot.CanvasAxisTickRenderer.prototype.getTop=function(b){if(this._elem){return this._elem.position().top}else{return null}};a.jqplot.CanvasAxisTickRenderer.prototype.getAngleRad=function(){var b=this.angle*Math.PI/180;return b};a.jqplot.CanvasAxisTickRenderer.prototype.setTick=function(b,d,c){this.value=b;if(c){this.isMinorTick=true}return this};a.jqplot.CanvasAxisTickRenderer.prototype.draw=function(c,f){if(!this.label){this.label=this.prefix+this.formatter(this.formatString,this.value)}if(this._elem){if(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==undefined){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce();this._elem=null}var e=f.canvasManager.getCanvas();this._textRenderer.setText(this.label,c);var b=this.getWidth(c);var d=this.getHeight(c);e.width=b;e.height=d;e.style.width=b;e.style.height=d;e.style.textAlign="left";e.style.position="absolute";e=f.canvasManager.initCanvas(e);this._elem=a(e);this._elem.css(this._styles);this._elem.addClass("jqplot-"+this.axis+"-tick");e=null;return this._elem};a.jqplot.CanvasAxisTickRenderer.prototype.pack=function(){this._textRenderer.draw(this._elem.get(0).getContext("2d"),this.label)}})(jQuery);
WRFILE: jqplot.highlighter.min.js

(function(d){d.jqplot.eventListenerHooks.push(["jqplotMouseMove",f]);d.jqplot.Highlighter=function(h){this.show=d.jqplot.config.enablePlugins;this.markerRenderer=new d.jqplot.MarkerRenderer({shadow:false});this.showMarker=true;this.lineWidthAdjust=2.5;this.sizeAdjust=5;this.showTooltip=true;this.tooltipLocation="nw";this.fadeTooltip=true;this.tooltipFadeSpeed="fast";this.tooltipOffset=2;this.tooltipAxes="both";this.tooltipSeparator=", ";this.tooltipContentEditor=null;this.useAxesFormatters=true;this.tooltipFormatString="%.5P";this.formatString=null;this.yvalues=1;this.bringSeriesToFront=false;this._tooltipElem;this.isHighlighting=false;this.currentNeighbor=null;d.extend(true,this,h)};var b=["nw","n","ne","e","se","s","sw","w"];var e={nw:0,n:1,ne:2,e:3,se:4,s:5,sw:6,w:7};var c=["se","s","sw","w","nw","n","ne","e"];d.jqplot.Highlighter.init=function(k,j,i){var h=i||{};this.plugins.highlighter=new d.jqplot.Highlighter(h.highlighter)};d.jqplot.Highlighter.parseOptions=function(i,h){this.showHighlight=true};d.jqplot.Highlighter.postPlotDraw=function(){if(this.plugins.highlighter&&this.plugins.highlighter.highlightCanvas){this.plugins.highlighter.highlightCanvas.resetCanvas();this.plugins.highlighter.highlightCanvas=null}if(this.plugins.highlighter&&this.plugins.highlighter._tooltipElem){this.plugins.highlighter._tooltipElem.emptyForce();this.plugins.highlighter._tooltipElem=null}this.plugins.highlighter.highlightCanvas=new d.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding,"jqplot-highlight-canvas",this._plotDimensions,this));this.plugins.highlighter.highlightCanvas.setContext();var h=document.createElement("div");this.plugins.highlighter._tooltipElem=d(h);h=null;this.plugins.highlighter._tooltipElem.addClass("jqplot-highlighter-tooltip");this.plugins.highlighter._tooltipElem.css({position:"absolute",display:"none"});this.eventCanvas._elem.before(this.plugins.highlighter._tooltipElem)};d.jqplot.preInitHooks.push(d.jqplot.Highlighter.init);d.jqplot.preParseSeriesOptionsHooks.push(d.jqplot.Highlighter.parseOptions);d.jqplot.postDrawHooks.push(d.jqplot.Highlighter.postPlotDraw);function a(m,o){var j=m.plugins.highlighter;var p=m.series[o.seriesIndex];var h=p.markerRenderer;var i=j.markerRenderer;i.style=h.style;i.lineWidth=h.lineWidth+j.lineWidthAdjust;i.size=h.size+j.sizeAdjust;var l=d.jqplot.getColorComponents(h.color);var n=[l[0],l[1],l[2]];var k=(l[3]>=0.6)?l[3]*0.6:l[3]*(2-l[3]);i.color="rgba("+n[0]+","+n[1]+","+n[2]+","+k+")";i.init();i.draw(p.gridData[o.pointIndex][0],p.gridData[o.pointIndex][1],j.highlightCanvas._ctx)}function g(A,q,m){var k=A.plugins.highlighter;var D=k._tooltipElem;var r=q.highlighter||{};var t=d.extend(true,{},k,r);if(t.useAxesFormatters){var w=q._xaxis._ticks[0].formatter;var h=q._yaxis._ticks[0].formatter;var E=q._xaxis._ticks[0].formatString;var s=q._yaxis._ticks[0].formatString;var z;var u=w(E,m.data[0]);var l=[];for(var B=1;B<t.yvalues+1;B++){l.push(h(s,m.data[B]))}if(typeof t.formatString==="string"){switch(t.tooltipAxes){case"both":case"xy":l.unshift(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;case"yx":l.push(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;case"x":z=d.jqplot.sprintf.apply(d.jqplot.sprintf,[t.formatString,u]);break;case"y":l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;default:l.unshift(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break}}else{switch(t.tooltipAxes){case"both":case"xy":z=u;for(var B=0;B<l.length;B++){z+=t.tooltipSeparator+l[B]}break;case"yx":z="";for(var B=0;B<l.length;B++){z+=l[B]+t.tooltipSeparator}z+=u;break;case"x":z=u;break;case"y":z=l.join(t.tooltipSeparator);break;default:z=u;for(var B=0;B<l.length;B++){z+=t.tooltipSeparator+l[B]}break}}}else{var z;if(typeof t.formatString==="string"){z=d.jqplot.sprintf.apply(d.jqplot.sprintf,[t.formatString].concat(m.data))}else{if(t.tooltipAxes=="both"||t.tooltipAxes=="xy"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[0])+t.tooltipSeparator+d.jqplot.sprintf(t.tooltipFormatString,m.data[1])}else{if(t.tooltipAxes=="yx"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[1])+t.tooltipSeparator+d.jqplot.sprintf(t.tooltipFormatString,m.data[0])}else{if(t.tooltipAxes=="x"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[0])}else{if(t.tooltipAxes=="y"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[1])}}}}}}if(d.isFunction(t.tooltipContentEditor)){z=t.tooltipContentEditor(z,m.seriesIndex,m.pointIndex,A)}D.html(z);var C={x:m.gridData[0],y:m.gridData[1]};var v=0;var j=0.707;if(q.markerRenderer.show==true){v=(q.markerRenderer.size+t.sizeAdjust)/2}var o=b;if(q.fillToZero&&q.fill&&m.data[1]<0){o=c}switch(o[e[t.tooltipLocation]]){case"nw":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break;case"n":var p=C.x+A._gridPadding.left-D.outerWidth(true)/2;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-v;break;case"ne":var p=C.x+A._gridPadding.left+t.tooltipOffset+j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break;case"e":var p=C.x+A._gridPadding.left+t.tooltipOffset+v;var n=C.y+A._gridPadding.top-D.outerHeight(true)/2;break;case"se":var p=C.x+A._gridPadding.left+t.tooltipOffset+j*v;var n=C.y+A._gridPadding.top+t.tooltipOffset+j*v;break;case"s":var p=C.x+A._gridPadding.left-D.outerWidth(true)/2;var n=C.y+A._gridPadding.top+t.tooltipOffset+v;break;case"sw":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top+t.tooltipOffset+j*v;break;case"w":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-v;var n=C.y+A._gridPadding.top-D.outerHeight(true)/2;break;default:var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break}D.css("left",p);D.css("top",n);if(t.fadeTooltip){D.stop(true,true).fadeIn(t.tooltipFadeSpeed)}else{D.show()}D=null}function f(n,j,i,p,l){var h=l.plugins.highlighter;var m=l.plugins.cursor;if(h.show){if(p==null&&h.isHighlighting){var o=jQuery.Event("jqplotHighlighterUnhighlight");l.target.trigger(o);var q=h.highlightCanvas._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);if(h.fadeTooltip){h._tooltipElem.fadeOut(h.tooltipFadeSpeed)}else{h._tooltipElem.hide()}if(h.bringSeriesToFront){l.restorePreviousSeriesOrder()}h.isHighlighting=false;h.currentNeighbor=null;q=null}else{if(p!=null&&l.series[p.seriesIndex].showHighlight&&!h.isHighlighting){var o=jQuery.Event("jqplotHighlighterHighlight");o.which=n.which;o.pageX=n.pageX;o.pageY=n.pageY;var k=[p.seriesIndex,p.pointIndex,p.data,l];l.target.trigger(o,k);h.isHighlighting=true;h.currentNeighbor=p;if(h.showMarker){a(l,p)}if(l.series[p.seriesIndex].show&&h.showTooltip&&(!m||!m._zoom.started)){g(l,l.series[p.seriesIndex],p)}if(h.bringSeriesToFront){l.moveSeriesToFront(p.seriesIndex)}}else{if(p!=null&&h.isHighlighting&&h.currentNeighbor!=p){if(l.series[p.seriesIndex].showHighlight){var q=h.highlightCanvas._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);h.isHighlighting=true;h.currentNeighbor=p;if(h.showMarker){a(l,p)}if(l.series[p.seriesIndex].show&&h.showTooltip&&(!m||!m._zoom.started)){g(l,l.series[p.seriesIndex],p)}if(h.bringSeriesToFront){l.moveSeriesToFront(p.seriesIndex)}}}}}}}})(jQuery);
WRFILE: jqplot.highlighter.min.js

(function(d){d.jqplot.eventListenerHooks.push(["jqplotMouseMove",f]);d.jqplot.Highlighter=function(h){this.show=d.jqplot.config.enablePlugins;this.markerRenderer=new d.jqplot.MarkerRenderer({shadow:false});this.showMarker=true;this.lineWidthAdjust=2.5;this.sizeAdjust=5;this.showTooltip=true;this.tooltipLocation="nw";this.fadeTooltip=true;this.tooltipFadeSpeed="fast";this.tooltipOffset=2;this.tooltipAxes="both";this.tooltipSeparator=", ";this.tooltipContentEditor=null;this.useAxesFormatters=true;this.tooltipFormatString="%.5P";this.formatString=null;this.yvalues=1;this.bringSeriesToFront=false;this._tooltipElem;this.isHighlighting=false;this.currentNeighbor=null;d.extend(true,this,h)};var b=["nw","n","ne","e","se","s","sw","w"];var e={nw:0,n:1,ne:2,e:3,se:4,s:5,sw:6,w:7};var c=["se","s","sw","w","nw","n","ne","e"];d.jqplot.Highlighter.init=function(k,j,i){var h=i||{};this.plugins.highlighter=new d.jqplot.Highlighter(h.highlighter)};d.jqplot.Highlighter.parseOptions=function(i,h){this.showHighlight=true};d.jqplot.Highlighter.postPlotDraw=function(){if(this.plugins.highlighter&&this.plugins.highlighter.highlightCanvas){this.plugins.highlighter.highlightCanvas.resetCanvas();this.plugins.highlighter.highlightCanvas=null}if(this.plugins.highlighter&&this.plugins.highlighter._tooltipElem){this.plugins.highlighter._tooltipElem.emptyForce();this.plugins.highlighter._tooltipElem=null}this.plugins.highlighter.highlightCanvas=new d.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding,"jqplot-highlight-canvas",this._plotDimensions,this));this.plugins.highlighter.highlightCanvas.setContext();var h=document.createElement("div");this.plugins.highlighter._tooltipElem=d(h);h=null;this.plugins.highlighter._tooltipElem.addClass("jqplot-highlighter-tooltip");this.plugins.highlighter._tooltipElem.css({position:"absolute",display:"none"});this.eventCanvas._elem.before(this.plugins.highlighter._tooltipElem)};d.jqplot.preInitHooks.push(d.jqplot.Highlighter.init);d.jqplot.preParseSeriesOptionsHooks.push(d.jqplot.Highlighter.parseOptions);d.jqplot.postDrawHooks.push(d.jqplot.Highlighter.postPlotDraw);function a(m,o){var j=m.plugins.highlighter;var p=m.series[o.seriesIndex];var h=p.markerRenderer;var i=j.markerRenderer;i.style=h.style;i.lineWidth=h.lineWidth+j.lineWidthAdjust;i.size=h.size+j.sizeAdjust;var l=d.jqplot.getColorComponents(h.color);var n=[l[0],l[1],l[2]];var k=(l[3]>=0.6)?l[3]*0.6:l[3]*(2-l[3]);i.color="rgba("+n[0]+","+n[1]+","+n[2]+","+k+")";i.init();i.draw(p.gridData[o.pointIndex][0],p.gridData[o.pointIndex][1],j.highlightCanvas._ctx)}function g(A,q,m){var k=A.plugins.highlighter;var D=k._tooltipElem;var r=q.highlighter||{};var t=d.extend(true,{},k,r);if(t.useAxesFormatters){var w=q._xaxis._ticks[0].formatter;var h=q._yaxis._ticks[0].formatter;var E=q._xaxis._ticks[0].formatString;var s=q._yaxis._ticks[0].formatString;var z;var u=w(E,m.data[0]);var l=[];for(var B=1;B<t.yvalues+1;B++){l.push(h(s,m.data[B]))}if(typeof t.formatString==="string"){switch(t.tooltipAxes){case"both":case"xy":l.unshift(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;case"yx":l.push(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;case"x":z=d.jqplot.sprintf.apply(d.jqplot.sprintf,[t.formatString,u]);break;case"y":l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;default:l.unshift(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break}}else{switch(t.tooltipAxes){case"both":case"xy":z=u;for(var B=0;B<l.length;B++){z+=t.tooltipSeparator+l[B]}break;case"yx":z="";for(var B=0;B<l.length;B++){z+=l[B]+t.tooltipSeparator}z+=u;break;case"x":z=u;break;case"y":z=l.join(t.tooltipSeparator);break;default:z=u;for(var B=0;B<l.length;B++){z+=t.tooltipSeparator+l[B]}break}}}else{var z;if(typeof t.formatString==="string"){z=d.jqplot.sprintf.apply(d.jqplot.sprintf,[t.formatString].concat(m.data))}else{if(t.tooltipAxes=="both"||t.tooltipAxes=="xy"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[0])+t.tooltipSeparator+d.jqplot.sprintf(t.tooltipFormatString,m.data[1])}else{if(t.tooltipAxes=="yx"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[1])+t.tooltipSeparator+d.jqplot.sprintf(t.tooltipFormatString,m.data[0])}else{if(t.tooltipAxes=="x"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[0])}else{if(t.tooltipAxes=="y"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[1])}}}}}}if(d.isFunction(t.tooltipContentEditor)){z=t.tooltipContentEditor(z,m.seriesIndex,m.pointIndex,A)}D.html(z);var C={x:m.gridData[0],y:m.gridData[1]};var v=0;var j=0.707;if(q.markerRenderer.show==true){v=(q.markerRenderer.size+t.sizeAdjust)/2}var o=b;if(q.fillToZero&&q.fill&&m.data[1]<0){o=c}switch(o[e[t.tooltipLocation]]){case"nw":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break;case"n":var p=C.x+A._gridPadding.left-D.outerWidth(true)/2;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-v;break;case"ne":var p=C.x+A._gridPadding.left+t.tooltipOffset+j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break;case"e":var p=C.x+A._gridPadding.left+t.tooltipOffset+v;var n=C.y+A._gridPadding.top-D.outerHeight(true)/2;break;case"se":var p=C.x+A._gridPadding.left+t.tooltipOffset+j*v;var n=C.y+A._gridPadding.top+t.tooltipOffset+j*v;break;case"s":var p=C.x+A._gridPadding.left-D.outerWidth(true)/2;var n=C.y+A._gridPadding.top+t.tooltipOffset+v;break;case"sw":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top+t.tooltipOffset+j*v;break;case"w":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-v;var n=C.y+A._gridPadding.top-D.outerHeight(true)/2;break;default:var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break}D.css("left",p);D.css("top",n);if(t.fadeTooltip){D.stop(true,true).fadeIn(t.tooltipFadeSpeed)}else{D.show()}D=null}function f(n,j,i,p,l){var h=l.plugins.highlighter;var m=l.plugins.cursor;if(h.show){if(p==null&&h.isHighlighting){var o=jQuery.Event("jqplotHighlighterUnhighlight");l.target.trigger(o);var q=h.highlightCanvas._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);if(h.fadeTooltip){h._tooltipElem.fadeOut(h.tooltipFadeSpeed)}else{h._tooltipElem.hide()}if(h.bringSeriesToFront){l.restorePreviousSeriesOrder()}h.isHighlighting=false;h.currentNeighbor=null;q=null}else{if(p!=null&&l.series[p.seriesIndex].showHighlight&&!h.isHighlighting){var o=jQuery.Event("jqplotHighlighterHighlight");o.which=n.which;o.pageX=n.pageX;o.pageY=n.pageY;var k=[p.seriesIndex,p.pointIndex,p.data,l];l.target.trigger(o,k);h.isHighlighting=true;h.currentNeighbor=p;if(h.showMarker){a(l,p)}if(l.series[p.seriesIndex].show&&h.showTooltip&&(!m||!m._zoom.started)){g(l,l.series[p.seriesIndex],p)}if(h.bringSeriesToFront){l.moveSeriesToFront(p.seriesIndex)}}else{if(p!=null&&h.isHighlighting&&h.currentNeighbor!=p){if(l.series[p.seriesIndex].showHighlight){var q=h.highlightCanvas._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);h.isHighlighting=true;h.currentNeighbor=p;if(h.showMarker){a(l,p)}if(l.series[p.seriesIndex].show&&h.showTooltip&&(!m||!m._zoom.started)){g(l,l.series[p.seriesIndex],p)}if(h.bringSeriesToFront){l.moveSeriesToFront(p.seriesIndex)}}}}}}}})(jQuery);
WRFILE: jqplot.cursor.min.js

(function(j){j.jqplot.Cursor=function(q){this.style="crosshair";this.previousCursor="auto";this.show=j.jqplot.config.enablePlugins;this.showTooltip=true;this.followMouse=false;this.tooltipLocation="se";this.tooltipOffset=6;this.showTooltipGridPosition=false;this.showTooltipUnitPosition=true;this.showTooltipDataPosition=false;this.tooltipFormatString="%.4P, %.4P";this.useAxesFormatters=true;this.tooltipAxisGroups=[];this.zoom=false;this.zoomProxy=false;this.zoomTarget=false;this.looseZoom=true;this.clickReset=false;this.dblClickReset=true;this.showVerticalLine=false;this.showHorizontalLine=false;this.constrainZoomTo="none";this.shapeRenderer=new j.jqplot.ShapeRenderer();this._zoom={start:[],end:[],started:false,zooming:false,isZoomed:false,axes:{start:{},end:{}},gridpos:{},datapos:{}};this._tooltipElem;this.zoomCanvas;this.cursorCanvas;this.intersectionThreshold=2;this.showCursorLegend=false;this.cursorLegendFormatString=j.jqplot.Cursor.cursorLegendFormatString;this._oldHandlers={onselectstart:null,ondrag:null,onmousedown:null};this.constrainOutsideZoom=true;this.showTooltipOutsideZoom=false;this.onGrid=false;j.extend(true,this,q)};j.jqplot.Cursor.cursorLegendFormatString="%s x:%s, y:%s";j.jqplot.Cursor.init=function(t,s,r){var q=r||{};this.plugins.cursor=new j.jqplot.Cursor(q.cursor);var u=this.plugins.cursor;if(u.show){j.jqplot.eventListenerHooks.push(["jqplotMouseEnter",b]);j.jqplot.eventListenerHooks.push(["jqplotMouseLeave",f]);j.jqplot.eventListenerHooks.push(["jqplotMouseMove",i]);if(u.showCursorLegend){r.legend=r.legend||{};r.legend.renderer=j.jqplot.CursorLegendRenderer;r.legend.formatString=this.plugins.cursor.cursorLegendFormatString;r.legend.show=true}if(u.zoom){j.jqplot.eventListenerHooks.push(["jqplotMouseDown",a]);if(u.clickReset){j.jqplot.eventListenerHooks.push(["jqplotClick",k])}if(u.dblClickReset){j.jqplot.eventListenerHooks.push(["jqplotDblClick",c])}}this.resetZoom=function(){var x=this.axes;if(!u.zoomProxy){for(var w in x){x[w].reset();x[w]._ticks=[];if(u._zoom.axes[w]!==undefined){x[w]._autoFormatString=u._zoom.axes[w].tickFormatString}}this.redraw()}else{var v=this.plugins.cursor.zoomCanvas._ctx;v.clearRect(0,0,v.canvas.width,v.canvas.height);v=null}this.plugins.cursor._zoom.isZoomed=false;this.target.trigger("jqplotResetZoom",[this,this.plugins.cursor])};if(u.showTooltipDataPosition){u.showTooltipUnitPosition=false;u.showTooltipGridPosition=false;if(q.cursor.tooltipFormatString==undefined){u.tooltipFormatString=j.jqplot.Cursor.cursorLegendFormatString}}}};j.jqplot.Cursor.postDraw=function(){var x=this.plugins.cursor;if(x.zoomCanvas){x.zoomCanvas.resetCanvas();x.zoomCanvas=null}if(x.cursorCanvas){x.cursorCanvas.resetCanvas();x.cursorCanvas=null}if(x._tooltipElem){x._tooltipElem.emptyForce();x._tooltipElem=null}if(x.zoom){x.zoomCanvas=new j.jqplot.GenericCanvas();this.eventCanvas._elem.before(x.zoomCanvas.createElement(this._gridPadding,"jqplot-zoom-canvas",this._plotDimensions,this));x.zoomCanvas.setContext()}var v=document.createElement("div");x._tooltipElem=j(v);v=null;x._tooltipElem.addClass("jqplot-cursor-tooltip");x._tooltipElem.css({position:"absolute",display:"none"});if(x.zoomCanvas){x.zoomCanvas._elem.before(x._tooltipElem)}else{this.eventCanvas._elem.before(x._tooltipElem)}if(x.showVerticalLine||x.showHorizontalLine){x.cursorCanvas=new j.jqplot.GenericCanvas();this.eventCanvas._elem.before(x.cursorCanvas.createElement(this._gridPadding,"jqplot-cursor-canvas",this._plotDimensions,this));x.cursorCanvas.setContext()}if(x.showTooltipUnitPosition){if(x.tooltipAxisGroups.length===0){var t=this.series;var u;var q=[];for(var r=0;r<t.length;r++){u=t[r];var w=u.xaxis+","+u.yaxis;if(j.inArray(w,q)==-1){q.push(w)}}for(var r=0;r<q.length;r++){x.tooltipAxisGroups.push(q[r].split(","))}}}};j.jqplot.Cursor.zoomProxy=function(v,r){var q=v.plugins.cursor;var u=r.plugins.cursor;q.zoomTarget=true;q.zoom=true;q.style="auto";q.dblClickReset=false;u.zoom=true;u.zoomProxy=true;r.target.bind("jqplotZoom",t);r.target.bind("jqplotResetZoom",s);function t(x,w,z,y,A){q.doZoom(w,z,v,A)}function s(w,x,y){v.resetZoom()}};j.jqplot.Cursor.prototype.resetZoom=function(u,v){var t=u.axes;var s=v._zoom.axes;if(!u.plugins.cursor.zoomProxy&&v._zoom.isZoomed){for(var r in t){t[r].reset();t[r]._ticks=[];t[r]._autoFormatString=s[r].tickFormatString}u.redraw();v._zoom.isZoomed=false}else{var q=v.zoomCanvas._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);q=null}u.target.trigger("jqplotResetZoom",[u,v])};j.jqplot.Cursor.resetZoom=function(q){q.resetZoom()};j.jqplot.Cursor.prototype.doZoom=function(G,t,C,u){var I=u;var F=C.axes;var r=I._zoom.axes;var w=r.start;var s=r.end;var B,E,z,D,v,x,q,H,J;var A=C.plugins.cursor.zoomCanvas._ctx;if((I.constrainZoomTo=="none"&&Math.abs(G.x-I._zoom.start[0])>6&&Math.abs(G.y-I._zoom.start[1])>6)||(I.constrainZoomTo=="x"&&Math.abs(G.x-I._zoom.start[0])>6)||(I.constrainZoomTo=="y"&&Math.abs(G.y-I._zoom.start[1])>6)){if(!C.plugins.cursor.zoomProxy){for(var y in t){if(I._zoom.axes[y]==undefined){I._zoom.axes[y]={};I._zoom.axes[y].numberTicks=F[y].numberTicks;I._zoom.axes[y].tickInterval=F[y].tickInterval;I._zoom.axes[y].daTickInterval=F[y].daTickInterval;I._zoom.axes[y].min=F[y].min;I._zoom.axes[y].max=F[y].max;I._zoom.axes[y].tickFormatString=(F[y].tickOptions!=null)?F[y].tickOptions.formatString:""}if((I.constrainZoomTo=="none")||(I.constrainZoomTo=="x"&&y.charAt(0)=="x")||(I.constrainZoomTo=="y"&&y.charAt(0)=="y")){z=t[y];if(z!=null){if(z>w[y]){v=w[y];x=z}else{D=w[y]-z;v=z;x=w[y]}q=F[y];H=null;if(q.alignTicks){if(q.name==="x2axis"&&C.axes.xaxis.show){H=C.axes.xaxis.numberTicks}else{if(q.name.charAt(0)==="y"&&q.name!=="yaxis"&&q.name!=="yMidAxis"&&C.axes.yaxis.show){H=C.axes.yaxis.numberTicks}}}if(this.looseZoom&&(F[y].renderer.constructor===j.jqplot.LinearAxisRenderer||F[y].renderer.constructor===j.jqplot.LogAxisRenderer)){J=j.jqplot.LinearTickGenerator(v,x,q._scalefact,H);if(F[y].tickInset&&J[0]<F[y].min+F[y].tickInset*F[y].tickInterval){J[0]+=J[4];J[2]-=1}if(F[y].tickInset&&J[1]>F[y].max-F[y].tickInset*F[y].tickInterval){J[1]-=J[4];J[2]-=1}if(F[y].renderer.constructor===j.jqplot.LogAxisRenderer&&J[0]<F[y].min){J[0]+=J[4];J[2]-=1}F[y].min=J[0];F[y].max=J[1];F[y]._autoFormatString=J[3];F[y].numberTicks=J[2];F[y].tickInterval=J[4];F[y].daTickInterval=[J[4]/1000,"seconds"]}else{F[y].min=v;F[y].max=x;F[y].tickInterval=null;F[y].numberTicks=null;F[y].daTickInterval=null}F[y]._ticks=[]}}}A.clearRect(0,0,A.canvas.width,A.canvas.height);C.redraw();I._zoom.isZoomed=true;A=null}C.target.trigger("jqplotZoom",[G,t,C,u])}};j.jqplot.preInitHooks.push(j.jqplot.Cursor.init);j.jqplot.postDrawHooks.push(j.jqplot.Cursor.postDraw);function e(G,r,C){var J=C.plugins.cursor;var w="";var N=false;if(J.showTooltipGridPosition){w=G.x+", "+G.y;N=true}if(J.showTooltipUnitPosition){var F;for(var E=0;E<J.tooltipAxisGroups.length;E++){F=J.tooltipAxisGroups[E];if(N){w+="<br />"}if(J.useAxesFormatters){for(var D=0;D<F.length;D++){if(D){w+=", "}var H=C.axes[F[D]]._ticks[0].formatter;var B=C.axes[F[D]]._ticks[0].formatString;w+=H(B,r[F[D]])}}else{w+=j.jqplot.sprintf(J.tooltipFormatString,r[F[0]],r[F[1]])}N=true}}if(J.showTooltipDataPosition){var u=C.series;var M=d(C,G.x,G.y);var N=false;for(var E=0;E<u.length;E++){if(u[E].show){var y=u[E].index;var t=u[E].label.toString();var I=j.inArray(y,M.indices);var z=undefined;var x=undefined;if(I!=-1){var L=M.data[I].data;if(J.useAxesFormatters){var A=u[E]._xaxis._ticks[0].formatter;var q=u[E]._yaxis._ticks[0].formatter;var K=u[E]._xaxis._ticks[0].formatString;var v=u[E]._yaxis._ticks[0].formatString;z=A(K,L[0]);x=q(v,L[1])}else{z=L[0];x=L[1]}if(N){w+="<br />"}w+=j.jqplot.sprintf(J.tooltipFormatString,t,z,x);N=true}}}}J._tooltipElem.html(w)}function g(C,A){var E=A.plugins.cursor;var z=E.cursorCanvas._ctx;z.clearRect(0,0,z.canvas.width,z.canvas.height);if(E.showVerticalLine){E.shapeRenderer.draw(z,[[C.x,0],[C.x,z.canvas.height]])}if(E.showHorizontalLine){E.shapeRenderer.draw(z,[[0,C.y],[z.canvas.width,C.y]])}var G=d(A,C.x,C.y);if(E.showCursorLegend){var r=j(A.targetId+" td.jqplot-cursor-legend-label");for(var B=0;B<r.length;B++){var v=j(r[B]).data("seriesIndex");var t=A.series[v];var s=t.label.toString();var D=j.inArray(v,G.indices);var x=undefined;var w=undefined;if(D!=-1){var H=G.data[D].data;if(E.useAxesFormatters){var y=t._xaxis._ticks[0].formatter;var q=t._yaxis._ticks[0].formatter;var F=t._xaxis._ticks[0].formatString;var u=t._yaxis._ticks[0].formatString;x=y(F,H[0]);w=q(u,H[1])}else{x=H[0];w=H[1]}}if(A.legend.escapeHtml){j(r[B]).text(j.jqplot.sprintf(E.cursorLegendFormatString,s,x,w))}else{j(r[B]).html(j.jqplot.sprintf(E.cursorLegendFormatString,s,x,w))}}}z=null}function d(A,F,E){var B={indices:[],data:[]};var G,w,u,C,v,q,t;var z;var D=A.plugins.cursor;for(var w=0;w<A.series.length;w++){G=A.series[w];q=G.renderer;if(G.show){z=D.intersectionThreshold;if(G.showMarker){z+=G.markerRenderer.size/2}for(var v=0;v<G.gridData.length;v++){t=G.gridData[v];if(D.showVerticalLine){if(Math.abs(F-t[0])<=z){B.indices.push(w);B.data.push({seriesIndex:w,pointIndex:v,gridData:t,data:G.data[v]})}}}}}return B}function n(r,t){var v=t.plugins.cursor;var s=v._tooltipElem;switch(v.tooltipLocation){case"nw":var q=r.x+t._gridPadding.left-s.outerWidth(true)-v.tooltipOffset;var u=r.y+t._gridPadding.top-v.tooltipOffset-s.outerHeight(true);break;case"n":var q=r.x+t._gridPadding.left-s.outerWidth(true)/2;var u=r.y+t._gridPadding.top-v.tooltipOffset-s.outerHeight(true);break;case"ne":var q=r.x+t._gridPadding.left+v.tooltipOffset;var u=r.y+t._gridPadding.top-v.tooltipOffset-s.outerHeight(true);break;case"e":var q=r.x+t._gridPadding.left+v.tooltipOffset;var u=r.y+t._gridPadding.top-s.outerHeight(true)/2;break;case"se":var q=r.x+t._gridPadding.left+v.tooltipOffset;var u=r.y+t._gridPadding.top+v.tooltipOffset;break;case"s":var q=r.x+t._gridPadding.left-s.outerWidth(true)/2;var u=r.y+t._gridPadding.top+v.tooltipOffset;break;case"sw":var q=r.x+t._gridPadding.left-s.outerWidth(true)-v.tooltipOffset;var u=r.y+t._gridPadding.top+v.tooltipOffset;break;case"w":var q=r.x+t._gridPadding.left-s.outerWidth(true)-v.tooltipOffset;var u=r.y+t._gridPadding.top-s.outerHeight(true)/2;break;default:var q=r.x+t._gridPadding.left+v.tooltipOffset;var u=r.y+t._gridPadding.top+v.tooltipOffset;break}s.css("left",q);s.css("top",u);s=null}function m(u){var s=u._gridPadding;var v=u.plugins.cursor;var t=v._tooltipElem;switch(v.tooltipLocation){case"nw":var r=s.left+v.tooltipOffset;var q=s.top+v.tooltipOffset;t.css("left",r);t.css("top",q);break;case"n":var r=(s.left+(u._plotDimensions.width-s.right))/2-t.outerWidth(true)/2;var q=s.top+v.tooltipOffset;t.css("left",r);t.css("top",q);break;case"ne":var r=s.right+v.tooltipOffset;var q=s.top+v.tooltipOffset;t.css({right:r,top:q});break;case"e":var r=s.right+v.tooltipOffset;var q=(s.top+(u._plotDimensions.height-s.bottom))/2-t.outerHeight(true)/2;t.css({right:r,top:q});break;case"se":var r=s.right+v.tooltipOffset;var q=s.bottom+v.tooltipOffset;t.css({right:r,bottom:q});break;case"s":var r=(s.left+(u._plotDimensions.width-s.right))/2-t.outerWidth(true)/2;var q=s.bottom+v.tooltipOffset;t.css({left:r,bottom:q});break;case"sw":var r=s.left+v.tooltipOffset;var q=s.bottom+v.tooltipOffset;t.css({left:r,bottom:q});break;case"w":var r=s.left+v.tooltipOffset;var q=(s.top+(u._plotDimensions.height-s.bottom))/2-t.outerHeight(true)/2;t.css({left:r,top:q});break;default:var r=s.right-v.tooltipOffset;var q=s.bottom+v.tooltipOffset;t.css({right:r,bottom:q});break}t=null}function k(r,q,v,u,t){r.preventDefault();r.stopImmediatePropagation();var w=t.plugins.cursor;if(w.clickReset){w.resetZoom(t,w)}var s=window.getSelection;if(document.selection&&document.selection.empty){document.selection.empty()}else{if(s&&!s().isCollapsed){s().collapse()}}return false}function c(r,q,v,u,t){r.preventDefault();r.stopImmediatePropagation();var w=t.plugins.cursor;if(w.dblClickReset){w.resetZoom(t,w)}var s=window.getSelection;if(document.selection&&document.selection.empty){document.selection.empty()}else{if(s&&!s().isCollapsed){s().collapse()}}return false}function f(w,t,q,z,u){var v=u.plugins.cursor;v.onGrid=false;if(v.show){j(w.target).css("cursor",v.previousCursor);if(v.showTooltip&&!(v._zoom.zooming&&v.showTooltipOutsideZoom&&!v.constrainOutsideZoom)){v._tooltipElem.empty();v._tooltipElem.hide()}if(v.zoom){v._zoom.gridpos=t;v._zoom.datapos=q}if(v.showVerticalLine||v.showHorizontalLine){var B=v.cursorCanvas._ctx;B.clearRect(0,0,B.canvas.width,B.canvas.height);B=null}if(v.showCursorLegend){var A=j(u.targetId+" td.jqplot-cursor-legend-label");for(var s=0;s<A.length;s++){var y=j(A[s]).data("seriesIndex");var r=u.series[y];var x=r.label.toString();if(u.legend.escapeHtml){j(A[s]).text(j.jqplot.sprintf(v.cursorLegendFormatString,x,undefined,undefined))}else{j(A[s]).html(j.jqplot.sprintf(v.cursorLegendFormatString,x,undefined,undefined))}}}}}function b(r,q,u,t,s){var v=s.plugins.cursor;v.onGrid=true;if(v.show){v.previousCursor=r.target.style.cursor;r.target.style.cursor=v.style;if(v.showTooltip){e(q,u,s);if(v.followMouse){n(q,s)}else{m(s)}v._tooltipElem.show()}if(v.showVerticalLine||v.showHorizontalLine){g(q,s)}}}function i(r,q,u,t,s){var v=s.plugins.cursor;if(v.show){if(v.showTooltip){e(q,u,s);if(v.followMouse){n(q,s)}}if(v.showVerticalLine||v.showHorizontalLine){g(q,s)}}}function o(y){var x=y.data.plot;var t=x.eventCanvas._elem.offset();var w={x:y.pageX-t.left,y:y.pageY-t.top};var u={xaxis:null,yaxis:null,x2axis:null,y2axis:null,y3axis:null,y4axis:null,y5axis:null,y6axis:null,y7axis:null,y8axis:null,y9axis:null,yMidAxis:null};var v=["xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"];var q=x.axes;var r,s;for(r=11;r>0;r--){s=v[r-1];if(q[s].show){u[s]=q[s].series_p2u(w[s.charAt(0)])}}return{offsets:t,gridPos:w,dataPos:u}}function h(z){var x=z.data.plot;var y=x.plugins.cursor;if(y.show&&y.zoom&&y._zoom.started&&!y.zoomTarget){z.preventDefault();var B=y.zoomCanvas._ctx;var v=o(z);var w=v.gridPos;var t=v.dataPos;y._zoom.gridpos=w;y._zoom.datapos=t;y._zoom.zooming=true;var u=w.x;var s=w.y;var A=B.canvas.height;var q=B.canvas.width;if(y.showTooltip&&!y.onGrid&&y.showTooltipOutsideZoom){e(w,t,x);if(y.followMouse){n(w,x)}}if(y.constrainZoomTo=="x"){y._zoom.end=[u,A]}else{if(y.constrainZoomTo=="y"){y._zoom.end=[q,s]}else{y._zoom.end=[u,s]}}var r=window.getSelection;if(document.selection&&document.selection.empty){document.selection.empty()}else{if(r&&!r().isCollapsed){r().collapse()}}l.call(y);B=null}}function a(w,s,r,x,t){var v=t.plugins.cursor;if(t.plugins.mobile){j(document).one("vmouseup.jqplot_cursor",{plot:t},p)}else{j(document).one("mouseup.jqplot_cursor",{plot:t},p)}var u=t.axes;if(document.onselectstart!=undefined){v._oldHandlers.onselectstart=document.onselectstart;document.onselectstart=function(){return false}}if(document.ondrag!=undefined){v._oldHandlers.ondrag=document.ondrag;document.ondrag=function(){return false}}if(document.onmousedown!=undefined){v._oldHandlers.onmousedown=document.onmousedown;document.onmousedown=function(){return false}}if(v.zoom){if(!v.zoomProxy){var y=v.zoomCanvas._ctx;y.clearRect(0,0,y.canvas.width,y.canvas.height);y=null}if(v.constrainZoomTo=="x"){v._zoom.start=[s.x,0]}else{if(v.constrainZoomTo=="y"){v._zoom.start=[0,s.y]}else{v._zoom.start=[s.x,s.y]}}v._zoom.started=true;for(var q in r){v._zoom.axes.start[q]=r[q]}if(t.plugins.mobile){j(document).bind("vmousemove.jqplotCursor",{plot:t},h)}else{j(document).bind("mousemove.jqplotCursor",{plot:t},h)}}}function p(y){var v=y.data.plot;var x=v.plugins.cursor;if(x.zoom&&x._zoom.zooming&&!x.zoomTarget){var u=x._zoom.gridpos.x;var r=x._zoom.gridpos.y;var t=x._zoom.datapos;var z=x.zoomCanvas._ctx.canvas.height;var q=x.zoomCanvas._ctx.canvas.width;var w=v.axes;if(x.constrainOutsideZoom&&!x.onGrid){if(u<0){u=0}else{if(u>q){u=q}}if(r<0){r=0}else{if(r>z){r=z}}for(var s in t){if(t[s]){if(s.charAt(0)=="x"){t[s]=w[s].series_p2u(u)}else{t[s]=w[s].series_p2u(r)}}}}if(x.constrainZoomTo=="x"){r=z}else{if(x.constrainZoomTo=="y"){u=q}}x._zoom.end=[u,r];x._zoom.gridpos={x:u,y:r};x.doZoom(x._zoom.gridpos,t,v,x)}x._zoom.started=false;x._zoom.zooming=false;j(document).unbind("mousemove.jqplotCursor",h);if(document.onselectstart!=undefined&&x._oldHandlers.onselectstart!=null){document.onselectstart=x._oldHandlers.onselectstart;x._oldHandlers.onselectstart=null}if(document.ondrag!=undefined&&x._oldHandlers.ondrag!=null){document.ondrag=x._oldHandlers.ondrag;x._oldHandlers.ondrag=null}if(document.onmousedown!=undefined&&x._oldHandlers.onmousedown!=null){document.onmousedown=x._oldHandlers.onmousedown;x._oldHandlers.onmousedown=null}}function l(){var y=this._zoom.start;var u=this._zoom.end;var s=this.zoomCanvas._ctx;var r,v,x,q;if(u[0]>y[0]){r=y[0];q=u[0]-y[0]}else{r=u[0];q=y[0]-u[0]}if(u[1]>y[1]){v=y[1];x=u[1]-y[1]}else{v=u[1];x=y[1]-u[1]}s.fillStyle="rgba(0,0,0,0.2)";s.strokeStyle="#999999";s.lineWidth=1;s.clearRect(0,0,s.canvas.width,s.canvas.height);s.fillRect(0,0,s.canvas.width,s.canvas.height);s.clearRect(r,v,q,x);s.strokeRect(r,v,q,x);s=null}j.jqplot.CursorLegendRenderer=function(q){j.jqplot.TableLegendRenderer.call(this,q);this.formatString="%s"};j.jqplot.CursorLegendRenderer.prototype=new j.jqplot.TableLegendRenderer();j.jqplot.CursorLegendRenderer.prototype.constructor=j.jqplot.CursorLegendRenderer;j.jqplot.CursorLegendRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}if(this.show){var w=this._series,A;var r=document.createElement("table");this._elem=j(r);r=null;this._elem.addClass("jqplot-legend jqplot-cursor-legend");this._elem.css("position","absolute");var q=false;for(var x=0;x<w.length;x++){A=w[x];if(A.show&&A.showLabel){var v=j.jqplot.sprintf(this.formatString,A.label.toString());if(v){var t=A.color;if(A._stack&&!A.fill){t=""}z.call(this,v,t,q,x);q=true}for(var u=0;u<j.jqplot.addLegendRowHooks.length;u++){var y=j.jqplot.addLegendRowHooks[u].call(this,A);if(y){z.call(this,y.label,y.color,q);q=true}}}}w=A=null;delete w;delete A}function z(D,C,F,s){var B=(F)?this.rowSpacing:"0";var E=j('<tr class="jqplot-legend jqplot-cursor-legend"></tr>').appendTo(this._elem);E.data("seriesIndex",s);j('<td class="jqplot-legend jqplot-cursor-legend-swatch" style="padding-top:'+B+';"><div style="border:1px solid #cccccc;padding:0.2em;"><div class="jqplot-cursor-legend-swatch" style="background-color:'+C+';"></div></div></td>').appendTo(E);var G=j('<td class="jqplot-legend jqplot-cursor-legend-label" style="vertical-align:middle;padding-top:'+B+';"></td>');G.appendTo(E);G.data("seriesIndex",s);if(this.escapeHtml){G.text(D)}else{G.html(D)}E=null;G=null}return this._elem}})(jQuery);
WRFILE: jqplot.pointLabels.min.js

(function(c){c.jqplot.PointLabels=function(e){this.show=c.jqplot.config.enablePlugins;this.location="n";this.labelsFromSeries=false;this.seriesLabelIndex=null;this.labels=[];this._labels=[];this.stackedValue=false;this.ypadding=6;this.xpadding=6;this.escapeHTML=true;this.edgeTolerance=-5;this.formatter=c.jqplot.DefaultTickFormatter;this.formatString="";this.hideZeros=false;this._elems=[];c.extend(true,this,e)};var a=["nw","n","ne","e","se","s","sw","w"];var d={nw:0,n:1,ne:2,e:3,se:4,s:5,sw:6,w:7};var b=["se","s","sw","w","nw","n","ne","e"];c.jqplot.PointLabels.init=function(j,h,f,g,i){var e=c.extend(true,{},f,g);e.pointLabels=e.pointLabels||{};if(this.renderer.constructor===c.jqplot.BarRenderer&&this.barDirection==="horizontal"&&!e.pointLabels.location){e.pointLabels.location="e"}this.plugins.pointLabels=new c.jqplot.PointLabels(e.pointLabels);this.plugins.pointLabels.setLabels.call(this)};c.jqplot.PointLabels.prototype.setLabels=function(){var f=this.plugins.pointLabels;var h;if(f.seriesLabelIndex!=null){h=f.seriesLabelIndex}else{if(this.renderer.constructor===c.jqplot.BarRenderer&&this.barDirection==="horizontal"){h=(this._plotData[0].length<3)?0:this._plotData[0].length-1}else{h=(this._plotData.length===0)?0:this._plotData[0].length-1}}f._labels=[];if(f.labels.length===0||f.labelsFromSeries){if(f.stackedValue){if(this._plotData.length&&this._plotData[0].length){for(var e=0;e<this._plotData.length;e++){f._labels.push(this._plotData[e][h])}}}else{var g=this.data;if(this.renderer.constructor===c.jqplot.BarRenderer&&this.waterfall){g=this._data}if(g.length&&g[0].length){for(var e=0;e<g.length;e++){f._labels.push(g[e][h])}}g=null}}else{if(f.labels.length){f._labels=f.labels}}};c.jqplot.PointLabels.prototype.xOffset=function(f,e,g){e=e||this.location;g=g||this.xpadding;var h;switch(e){case"nw":h=-f.outerWidth(true)-this.xpadding;break;case"n":h=-f.outerWidth(true)/2;break;case"ne":h=this.xpadding;break;case"e":h=this.xpadding;break;case"se":h=this.xpadding;break;case"s":h=-f.outerWidth(true)/2;break;case"sw":h=-f.outerWidth(true)-this.xpadding;break;case"w":h=-f.outerWidth(true)-this.xpadding;break;default:h=-f.outerWidth(true)-this.xpadding;break}return h};c.jqplot.PointLabels.prototype.yOffset=function(f,e,g){e=e||this.location;g=g||this.xpadding;var h;switch(e){case"nw":h=-f.outerHeight(true)-this.ypadding;break;case"n":h=-f.outerHeight(true)-this.ypadding;break;case"ne":h=-f.outerHeight(true)-this.ypadding;break;case"e":h=-f.outerHeight(true)/2;break;case"se":h=this.ypadding;break;case"s":h=this.ypadding;break;case"sw":h=this.ypadding;break;case"w":h=-f.outerHeight(true)/2;break;default:h=-f.outerHeight(true)-this.ypadding;break}return h};c.jqplot.PointLabels.draw=function(x,j,v){var t=this.plugins.pointLabels;t.setLabels.call(this);for(var w=0;w<t._elems.length;w++){t._elems[w].emptyForce()}t._elems.splice(0,t._elems.length);if(t.show){var r="_"+this._stackAxis+"axis";if(!t.formatString){t.formatString=this[r]._ticks[0].formatString;t.formatter=this[r]._ticks[0].formatter}var E=this._plotData;var D=this._prevPlotData;var A=this._xaxis;var q=this._yaxis;var z,f;for(var w=0,u=t._labels.length;w<u;w++){var o=t._labels[w];if(o==null||(t.hideZeros&&parseInt(o,10)==0)){continue}o=t.formatter(t.formatString,o);f=document.createElement("div");t._elems[w]=c(f);z=t._elems[w];z.addClass("jqplot-point-label jqplot-series-"+this.index+" jqplot-point-"+w);z.css("position","absolute");z.insertAfter(x.canvas);if(t.escapeHTML){z.text(o)}else{z.html(o)}var g=t.location;if((this.fillToZero&&E[w][1]<0)||(this.fillToZero&&this._type==="bar"&&this.barDirection==="horizontal"&&E[w][0]<0)||(this.waterfall&&parseInt(o,10))<0){g=b[d[g]]}var n=A.u2p(E[w][0])+t.xOffset(z,g);var h=q.u2p(E[w][1])+t.yOffset(z,g);if(this._stack&&!t.stackedValue){if(this.barDirection==="vertical"){h=(this._barPoints[w][0][1]+this._barPoints[w][1][1])/2+v._gridPadding.top-0.5*z.outerHeight(true)}else{n=(this._barPoints[w][2][0]+this._barPoints[w][0][0])/2+v._gridPadding.left-0.5*z.outerWidth(true)}}if(this.renderer.constructor==c.jqplot.BarRenderer){if(this.barDirection=="vertical"){n+=this._barNudge}else{h-=this._barNudge}}z.css("left",n);z.css("top",h);var k=n+z.width();var s=h+z.height();var C=t.edgeTolerance;var e=c(x.canvas).position().left;var y=c(x.canvas).position().top;var B=x.canvas.width+e;var m=x.canvas.height+y;if(n-C<e||h-C<y||k+C>B||s+C>m){z.remove()}z=null;f=null}}};c.jqplot.postSeriesInitHooks.push(c.jqplot.PointLabels.init);c.jqplot.postDrawSeriesHooks.push(c.jqplot.PointLabels.draw)})(jQuery);
WRFILE: bean.min.js

/*!
  * Bean - copyright (c) Jacob Thornton 2011-2012
  * https://github.com/fat/bean
  * MIT license
  */
(function(a,c,b){if(typeof module!="undefined"&&module.exports){module.exports=b()}else{if(typeof define=="function"&&define.amd){define(b)}else{c[a]=b()}}})("bean",this,function(l,O){l=l||"bean";O=O||this;var G=window,H=O[l],t=/[^\.]*(?=\..*)\.|.*/,C=/\..*/,j="addEventListener",a="removeEventListener",g=document||{},u=g.documentElement||{},q=u[j],v=q?j:"attachEvent",A={},n=Array.prototype.slice,I=function(P,Q){return P.split(Q||" ")},k=function(P){return typeof P=="string"},o=function(P){return typeof P=="function"},z="click dblclick mouseup mousedown contextmenu mousewheel mousemultiwheel DOMMouseScroll mouseover mouseout mousemove selectstart selectend keydown keypress keyup orientationchange focus blur change reset select submit load unload beforeunload resize move DOMContentLoaded readystatechange message error abort scroll ",c="show input invalid touchstart touchmove touchend touchcancel gesturestart gesturechange gestureend textinput readystatechange pageshow pagehide popstate hashchange offline online afterprint beforeprint dragstart dragenter dragover dragleave drag drop dragend loadstart progress suspend emptied stalled loadmetadata loadeddata canplay canplaythrough playing waiting seeking seeked ended durationchange timeupdate play pause ratechange volumechange cuechange checking noupdate downloading cached updateready obsolete ",M=(function(R,Q,P){for(P=0;P<Q.length;P++){Q[P]&&(R[Q[P]]=1)}return R}({},I(z+(q?c:"")))),y=(function(){var Q="compareDocumentPosition" in u?function(S,R){return R.compareDocumentPosition&&(R.compareDocumentPosition(S)&16)===16}:"contains" in u?function(S,R){R=R.nodeType===9||R===window?u:R;return R!==S&&R.contains(S)}:function(S,R){while(S=S.parentNode){if(S===R){return 1}}return 0},P=function(R){var S=R.relatedTarget;return !S?S==null:(S!==this&&S.prefix!=="xul"&&!/document/.test(this.toString())&&!Q(S,this))};return{mouseenter:{base:"mouseover",condition:P},mouseleave:{base:"mouseout",condition:P},mousewheel:{base:/Firefox/.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel"}}}()),E=(function(){var Y=I("altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which propertyName"),W=Y.concat(I("button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement")),Q=W.concat(I("wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ axis")),S=Y.concat(I("char charCode key keyCode keyIdentifier keyLocation location")),R=Y.concat(I("data")),X=Y.concat(I("touches targetTouches changedTouches scale rotation")),aa=Y.concat(I("data origin source")),T=Y.concat(I("state")),U=/over|out/,P=[{reg:/key/i,fix:function(ab,ac){ac.keyCode=ab.keyCode||ab.which;return S}},{reg:/click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i,fix:function(ac,ad,ab){ad.rightClick=ac.which===3||ac.button===2;ad.pos={x:0,y:0};if(ac.pageX||ac.pageY){ad.clientX=ac.pageX;ad.clientY=ac.pageY}else{if(ac.clientX||ac.clientY){ad.clientX=ac.clientX+g.body.scrollLeft+u.scrollLeft;ad.clientY=ac.clientY+g.body.scrollTop+u.scrollTop}}if(U.test(ab)){ad.relatedTarget=ac.relatedTarget||ac[(ab=="mouseover"?"from":"to")+"Element"]}return W}},{reg:/mouse.*(wheel|scroll)/i,fix:function(){return Q}},{reg:/^text/i,fix:function(){return R}},{reg:/^touch|^gesture/i,fix:function(){return X}},{reg:/^message$/i,fix:function(){return aa}},{reg:/^popstate$/i,fix:function(){return T}},{reg:/.*/,fix:function(){return Y}}],V={},Z=function(ac,af,ab){if(!arguments.length){return}ac=ac||((af.ownerDocument||af.document||af).parentWindow||G).event;this.originalEvent=ac;this.isNative=ab;this.isBean=true;if(!ac){return}var aj=ac.type,ah=ac.target||ac.srcElement,ag,ae,ad,ai,ak;this.target=ah&&ah.nodeType===3?ah.parentNode:ah;if(ab){ak=V[aj];if(!ak){for(ag=0,ae=P.length;ag<ae;ag++){if(P[ag].reg.test(aj)){V[aj]=ak=P[ag].fix;break}}}ai=ak(ac,this,aj);for(ag=ai.length;ag--;){if(!((ad=ai[ag]) in this)&&ad in ac){this[ad]=ac[ad]}}}};Z.prototype.preventDefault=function(){if(this.originalEvent.preventDefault){this.originalEvent.preventDefault()}else{this.originalEvent.returnValue=false}};Z.prototype.stopPropagation=function(){if(this.originalEvent.stopPropagation){this.originalEvent.stopPropagation()}else{this.originalEvent.cancelBubble=true}};Z.prototype.stop=function(){this.preventDefault();this.stopPropagation();this.stopped=true};Z.prototype.stopImmediatePropagation=function(){if(this.originalEvent.stopImmediatePropagation){this.originalEvent.stopImmediatePropagation()}this.isImmediatePropagationStopped=function(){return true}};Z.prototype.isImmediatePropagationStopped=function(){return this.originalEvent.isImmediatePropagationStopped&&this.originalEvent.isImmediatePropagationStopped()};Z.prototype.clone=function(ac){var ab=new Z(this,this.element,this.isNative);ab.currentTarget=ac;return ab};return Z}()),d=function(Q,P){return !q&&!P&&(Q===g||Q===G)?u:Q},i=(function(){var Q=function(S,V,X,R){var U=function(Z,Y){return V.apply(S,R?n.call(Y,Z?0:1).concat(R):Y)},W=function(Z,Y){return V.__beanDel?V.__beanDel.ft(Z.target,S):Y},T=X?function(Y){var Z=W(Y,this);if(X.apply(Z,arguments)){if(Y){Y.currentTarget=Z}return U(Y,arguments)}}:function(Y){if(V.__beanDel){Y=Y.clone(W(Y))}return U(Y,arguments)};T.__beanDel=V.__beanDel;return T},P=function(V,X,Z,T,S,W,Y){var U=y[X],R;if(X=="unload"){Z=s(b,V,X,Z,T)}if(U){if(U.condition){Z=Q(V,Z,U.condition,W)}X=U.base||X}this.isNative=R=M[X]&&!!V[v];this.customType=!q&&!R&&X;this.element=V;this.type=X;this.original=T;this.namespaces=S;this.eventType=q||R?X:"propertychange";this.target=d(V,R);this[v]=!!this.target[v];this.root=Y;this.handler=Q(V,Z,null,W)};P.prototype.inNamespaces=function(T){var S,R,U=0;if(!T){return true}if(!this.namespaces){return false}for(S=T.length;S--;){for(R=this.namespaces.length;R--;){if(T[S]==this.namespaces[R]){U++}}}return T.length===U};P.prototype.matches=function(S,R,T){return this.element===S&&(!R||this.original===R)&&(!T||this.handler===T)};return P}()),K=(function(){var U={},T=function(Z,ac,W,ag,ae,ad){var ab=ae?"r":"$";if(!ac||ac=="*"){for(var ah in U){if(ah.charAt(0)==ab){T(Z,ah.substr(1),W,ag,ae,ad)}}}else{var Y=0,X,aa=U[ab+ac],af=Z=="*";if(!aa){return}for(X=aa.length;Y<X;Y++){if((af||aa[Y].matches(Z,W,ag))&&!ad(aa[Y],aa,Y,ac)){return}}}},S=function(Z,aa,Y,W){var X,ab=U[(W?"r":"$")+aa];if(ab){for(X=ab.length;X--;){if(!ab[X].root&&ab[X].matches(Z,Y,null)){return true}}}return false},R=function(Z,aa,Y,X){var W=[];T(Z,aa,Y,null,X,function(ab){return W.push(ab)});return W},V=function(Y){var W=!Y.root&&!this.has(Y.element,Y.type,null,false),X=(Y.root?"r":"$")+Y.type;(U[X]||(U[X]=[])).push(Y);return W},Q=function(W){T(W.element,W.type,null,W.handler,W.root,function(Y,Z,X){Z.splice(X,1);Y.removed=true;if(Z.length===0){delete U[(Y.root?"r":"$")+Y.type]}return false})},P=function(){var X,W=[];for(X in U){if(X.charAt(0)=="$"){W=W.concat(U[X])}}return W};return{has:S,get:R,put:V,del:Q,entries:P}}()),w,N=function(P){if(!arguments.length){w=g.querySelectorAll?function(Q,R){return R.querySelectorAll(Q)}:function(){throw new Error("Bean: No selector engine installed")}}else{w=P}},D=function(T,S){if(!q&&S&&T&&T.propertyName!="_on"+S){return}var R=K.get(this,S||T.type,null,false),P=R.length,Q=0;T=new E(T,this,true);if(S){T.type=S}for(;Q<P&&!T.isImmediatePropagationStopped();Q++){if(!R[Q].removed){R[Q].handler.call(this,T)}}},J=q?function(P,Q,R){P[R?j:a](Q,D,false)}:function(P,Q,T,S){var R;if(T){K.put(R=new i(P,S||Q,function(U){D.call(P,U,S)},D,null,null,true));if(S&&P["_on"+S]==null){P["_on"+S]=0}R.target.attachEvent("on"+R.eventType,R.handler)}else{R=K.get(P,S||Q,D,true)[0];if(R){R.target.detachEvent("on"+R.eventType,R.handler);K.del(R)}}},s=function(T,P,R,Q,S){return function(){Q.apply(this,arguments);T(P,R,S)}},b=function(T,S,X,P){var W=S&&S.replace(C,""),Q=K.get(T,W,null,false),V={},U,R;for(U=0,R=Q.length;U<R;U++){if((!X||Q[U].original===X)&&Q[U].inNamespaces(P)){K.del(Q[U]);if(!V[Q[U].eventType]&&Q[U][v]){V[Q[U].eventType]={t:Q[U].eventType,c:Q[U].type}}}}for(U in V){if(!K.has(T,V[U].t,null,false)){J(T,V[U].t,false,V[U].c)}}},m=function(P,R){var S=function(V,T){var U,W=k(P)?w(P,T):P;for(;V&&V!==T;V=V.parentNode){for(U=W.length;U--;){if(W[U]===V){return V}}}},Q=function(U){var T=S(U.target,this);if(T){R.apply(T,arguments)}};Q.__beanDel={ft:S,selector:P};return Q},L=q?function(Q,S,R){var P=g.createEvent(Q?"HTMLEvents":"UIEvents");P[Q?"initEvent":"initUIEvent"](S,true,true,G,1);R.dispatchEvent(P)}:function(P,R,Q){Q=d(Q,P);P?Q.fireEvent("on"+R,g.createEventObject()):Q["_on"+R]++},F=function(T,P,V){var S=k(P),Q,U,W,R;if(S&&P.indexOf(" ")>0){P=I(P);for(R=P.length;R--;){F(T,P[R],V)}return T}U=S&&P.replace(C,"");if(U&&y[U]){U=y[U].base}if(!P||S){if(W=S&&P.replace(t,"")){W=I(W,".")}b(T,U,V,W)}else{if(o(P)){b(T,null,P)}else{for(Q in P){if(P.hasOwnProperty(Q)){F(T,Q,P[Q])}}}}return T},x=function(Q,Z,P,X){var W,V,T,R,U,Y,S;if(P===undefined&&typeof Z=="object"){for(V in Z){if(Z.hasOwnProperty(V)){x.call(this,Q,V,Z[V])}}return}if(!o(P)){W=X;U=n.call(arguments,4);X=m(P,W,w)}else{U=n.call(arguments,3);X=W=P}T=I(Z);if(this===A){X=s(F,Q,Z,X,W)}for(R=T.length;R--;){S=K.put(Y=new i(Q,T[R].replace(C,""),X,W,I(T[R].replace(t,""),"."),U,false));if(Y[v]&&S){J(Q,Y.eventType,true,Y.customType)}}return Q},f=function(R,Q,S,P){return x.apply(null,!k(S)?n.call(arguments):[R,S,Q,P].concat(arguments.length>3?n.call(arguments,5):[]))},h=function(){return x.apply(A,arguments)},r=function(S,X,V){var U=I(X),T,R,Q,W,P;for(T=U.length;T--;){X=U[T].replace(C,"");if(W=U[T].replace(t,"")){W=I(W,".")}if(!W&&!V&&S[v]){L(M[X],X,S)}else{P=K.get(S,X,null,false);V=[false].concat(V);for(R=0,Q=P.length;R<Q;R++){if(P[R].inNamespaces(W)){P[R].handler.apply(S,V)}}}}return S},p=function(T,W,U){var Q=K.get(W,U,null,false),P=Q.length,S=0,R,V;for(;S<P;S++){if(Q[S].original){R=[T,Q[S].type];if(V=Q[S].handler.__beanDel){R.push(V.selector)}R.push(Q[S].original);x.apply(null,R)}}return T},B={on:x,add:f,one:h,off:F,remove:F,clone:p,fire:r,Event:E,setSelectorEngine:N,noConflict:function(){O[l]=H;return this}};if(G.attachEvent){var e=function(){var Q,P=K.entries();for(Q in P){if(P[Q].type&&P[Q].type!=="unload"){F(P[Q].element,P[Q].type)}}G.detachEvent("onunload",e);G.CollectGarbage&&G.CollectGarbage()};G.attachEvent("onunload",e)}N();return B});
WRFILE: underscore.min.js

(function(b,a){typeof exports==="object"&&typeof module!=="undefined"?module.exports=a():typeof define==="function"&&define.amd?define("underscore",a):(b=typeof globalThis!=="undefined"?globalThis:b||self,(function(){var d=b._;var c=b._=a();c.noConflict=function(){b._=d;return c}}()))}(this,(function(){var cu="1.13.1";var cf=typeof self=="object"&&self.self===self&&self||typeof global=="object"&&global.global===global&&global||Function("return this")()||{};var bV=Array.prototype,bO=Object.prototype;var bv=typeof Symbol!=="undefined"?Symbol.prototype:null;var q=bV.push,V=bV.slice,t=bO.toString,ab=bO.hasOwnProperty;var e=typeof ArrayBuffer!=="undefined",F=typeof DataView!=="undefined";var aq=Array.isArray,bs=Object.keys,o=Object.create,S=e&&ArrayBuffer.isView;var a=isNaN,y=isFinite;var a4=!{toString:null}.propertyIsEnumerable("toString");var bB=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];var u=Math.pow(2,53)-1;function cm(cb,cF){cF=cF==null?cb.length-1:+cF;return function(){var cJ=Math.max(arguments.length-cF,0),cI=Array(cJ),cH=0;for(;cH<cJ;cH++){cI[cH]=arguments[cH+cF]}switch(cF){case 0:return cb.call(this,cI);case 1:return cb.call(this,arguments[0],cI);case 2:return cb.call(this,arguments[0],arguments[1],cI)}var cG=Array(cF+1);for(cH=0;cH<cF;cH++){cG[cH]=arguments[cH]}cG[cF]=cI;return cb.apply(this,cG)}}function cD(cF){var cb=typeof cF;return cb==="function"||cb==="object"&&!!cF}function cl(cb){return cb===null}function ba(cb){return cb===void 0}function aU(cb){return cb===true||cb===false||t.call(cb)==="[object Boolean]"}function be(cb){return !!(cb&&cb.nodeType===1)}function U(cF){var cb="[object "+cF+"]";return function(cG){return t.call(cG)===cb}}var bN=U("String");var aE=U("Number");var am=U("Date");var b3=U("RegExp");var R=U("Error");var bI=U("Symbol");var W=U("ArrayBuffer");var s=U("Function");var O=cf.document&&cf.document.childNodes;if(typeof/./!="function"&&typeof Int8Array!="object"&&typeof O!="function"){s=function(cb){return typeof cb=="function"||false}}var bW=s;var aH=U("Object");var G=(F&&aH(new DataView(new ArrayBuffer(8)))),Q=(typeof Map!=="undefined"&&aH(new Map));var aC=U("DataView");function ac(cb){return cb!=null&&bW(cb.getInt8)&&W(cb.buffer)}var aQ=(G?ac:aC);var aR=aq||U("Array");function k(cF,cb){return cF!=null&&ab.call(cF,cb)}var aj=U("Arguments");(function(){if(!aj(arguments)){aj=function(cb){return k(cb,"callee")}}}());var bK=aj;function cA(cb){return !bI(cb)&&y(cb)&&!isNaN(parseFloat(cb))}function a6(cb){return aE(cb)&&a(cb)}function bH(cb){return function(){return cb}}function cz(cb){return function(cG){var cF=cb(cG);return typeof cF=="number"&&cF>=0&&cF<=u}}function a7(cb){return function(cF){return cF==null?void 0:cF[cb]}}var b4=a7("byteLength");var bd=cz(b4);var ad=/\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/;function bq(cb){return S?(S(cb)&&!aQ(cb)):bd(cb)&&ad.test(t.call(cb))}var l=e?bq:bH(false);var B=a7("length");function aA(cG){var cH={};for(var cb=cG.length,cF=0;cF<cb;++cF){cH[cG[cF]]=true}return{contains:function(cI){return cH[cI]},push:function(cI){cH[cI]=true;return cG.push(cI)}}}function aM(cI,cH){cH=aA(cH);var cb=bB.length;var cF=cI.constructor;var cG=bW(cF)&&cF.prototype||bO;var cJ="constructor";if(k(cI,cJ)&&!cH.contains(cJ)){cH.push(cJ)}while(cb--){cJ=bB[cb];if(cJ in cI&&cI[cJ]!==cG[cJ]&&!cH.contains(cJ)){cH.push(cJ)}}}function bm(cG){if(!cD(cG)){return[]}if(bs){return bs(cG)}var cF=[];for(var cb in cG){if(k(cG,cb)){cF.push(cb)}}if(a4){aM(cG,cF)}return cF}function bC(cF){if(cF==null){return true}var cb=B(cF);if(typeof cb=="number"&&(aR(cF)||bN(cF)||bK(cF))){return cb===0}return B(bm(cF))===0}function Z(cF,cb){var cI=bm(cb),cJ=cI.length;if(cF==null){return !cJ}var cK=Object(cF);for(var cH=0;cH<cJ;cH++){var cG=cI[cH];if(cb[cG]!==cK[cG]||!(cG in cK)){return false}}return true}function a8(cb){if(cb instanceof a8){return cb}if(!(this instanceof a8)){return new a8(cb)}this._wrapped=cb}a8.VERSION=cu;a8.prototype.value=function(){return this._wrapped};a8.prototype.valueOf=a8.prototype.toJSON=a8.prototype.value;a8.prototype.toString=function(){return String(this._wrapped)};function af(cb){return new Uint8Array(cb.buffer||cb,cb.byteOffset||0,b4(cb))}var bf="[object DataView]";function aZ(cF,cb,cI,cH){if(cF===cb){return cF!==0||1/cF===1/cb}if(cF==null||cb==null){return false}if(cF!==cF){return cb!==cb}var cG=typeof cF;if(cG!=="function"&&cG!=="object"&&typeof cb!="object"){return false}return X(cF,cb,cI,cH)}function X(cN,cM,cF,cH){if(cN instanceof a8){cN=cN._wrapped}if(cM instanceof a8){cM=cM._wrapped}var cJ=t.call(cN);if(cJ!==t.call(cM)){return false}if(G&&cJ=="[object Object]"&&aQ(cN)){if(!aQ(cM)){return false}cJ=bf}switch(cJ){case"[object RegExp]":case"[object String]":return""+cN===""+cM;case"[object Number]":if(+cN!==+cN){return +cM!==+cM}return +cN===0?1/+cN===1/cM:+cN===+cM;case"[object Date]":case"[object Boolean]":return +cN===+cM;case"[object Symbol]":return bv.valueOf.call(cN)===bv.valueOf.call(cM);case"[object ArrayBuffer]":case bf:return X(af(cN),af(cM),cF,cH)}var cG=cJ==="[object Array]";if(!cG&&l(cN)){var cP=b4(cN);if(cP!==b4(cM)){return false}if(cN.buffer===cM.buffer&&cN.byteOffset===cM.byteOffset){return true}cG=true}if(!cG){if(typeof cN!="object"||typeof cM!="object"){return false}var cL=cN.constructor,cI=cM.constructor;if(cL!==cI&&!(bW(cL)&&cL instanceof cL&&bW(cI)&&cI instanceof cI)&&("constructor" in cN&&"constructor" in cM)){return false}}cF=cF||[];cH=cH||[];var cb=cF.length;while(cb--){if(cF[cb]===cN){return cH[cb]===cM}}cF.push(cN);cH.push(cM);if(cG){cb=cN.length;if(cb!==cM.length){return false}while(cb--){if(!aZ(cN[cb],cM[cb],cF,cH)){return false}}}else{var cK=bm(cN),cO;cb=cK.length;if(bm(cM).length!==cb){return false}while(cb--){cO=cK[cb];if(!(k(cM,cO)&&aZ(cN[cO],cM[cO],cF,cH))){return false}}}cF.pop();cH.pop();return true}function bg(cF,cb){return aZ(cF,cb)}function cj(cG){if(!cD(cG)){return[]}var cF=[];for(var cb in cG){cF.push(cb)}if(a4){aM(cG,cF)}return cF}function bU(cb){var cF=B(cb);return function(cI){if(cI==null){return false}var cH=cj(cI);if(B(cH)){return false}for(var cG=0;cG<cF;cG++){if(!bW(cI[cb[cG]])){return false}}return cb!==b5||!bW(cI[aa])}}var aa="forEach",bh="has",ch=["clear","delete"],cC=["get",bh,"set"];var ao=ch.concat(aa,cC),b5=ch.concat(cC),aP=["add"].concat(ch,aa,bh);var cy=Q?bU(ao):U("Map");var au=Q?bU(b5):U("WeakMap");var a5=Q?bU(aP):U("Set");var ct=U("WeakSet");function aK(cI){var cG=bm(cI);var cH=cG.length;var cb=Array(cH);for(var cF=0;cF<cH;cF++){cb[cF]=cI[cG[cF]]}return cb}function aO(cI){var cF=bm(cI);var cG=cF.length;var cH=Array(cG);for(var cb=0;cb<cG;cb++){cH[cb]=[cF[cb],cI[cF[cb]]]}return cH}function bk(cI){var cb={};var cG=bm(cI);for(var cF=0,cH=cG.length;cF<cH;cF++){cb[cI[cG[cF]]]=cG[cF]}return cb}function bX(cG){var cF=[];for(var cb in cG){if(bW(cG[cb])){cF.push(cb)}}return cF.sort()}function i(cb,cF){return function(cN){var cL=arguments.length;if(cF){cN=Object(cN)}if(cL<2||cN==null){return cN}for(var cH=1;cH<cL;cH++){var cM=arguments[cH],cK=cb(cM),cG=cK.length;for(var cJ=0;cJ<cG;cJ++){var cI=cK[cJ];if(!cF||cN[cI]===void 0){cN[cI]=cM[cI]}}}return cN}}var bA=i(cj);var cr=i(bm);var aF=i(cj,true);function m(){return function(){}}function bc(cG){if(!cD(cG)){return{}}if(o){return o(cG)}var cF=m();cF.prototype=cG;var cb=new cF;cF.prototype=null;return cb}function K(cF,cG){var cb=bc(cF);if(cG){cr(cb,cG)}return cb}function bR(cb){if(!cD(cb)){return cb}return aR(cb)?cb.slice():bA({},cb)}function bP(cF,cb){cb(cF);return cF}function bL(cb){return aR(cb)?cb:[cb]}a8.toPath=bL;function cd(cb){return a8.toPath(cb)}function cw(cH,cG){var cF=cG.length;for(var cb=0;cb<cF;cb++){if(cH==null){return void 0}cH=cH[cG[cb]]}return cF?cH:void 0}function h(cF,cH,cb){var cG=cw(cF,cd(cH));return ba(cG)?cb:cG}function ce(cI,cH){cH=cd(cH);var cG=cH.length;for(var cF=0;cF<cG;cF++){var cb=cH[cF];if(!k(cI,cb)){return false}cI=cI[cb]}return !!cG}function aw(cb){return cb}function bY(cb){cb=cr({},cb);return function(cF){return Z(cF,cb)}}function ag(cb){cb=cd(cb);return function(cF){return cw(cF,cb)}}function b0(cF,cb,cG){if(cb===void 0){return cF}switch(cG==null?3:cG){case 1:return function(cH){return cF.call(cb,cH)};case 3:return function(cI,cH,cJ){return cF.call(cb,cI,cH,cJ)};case 4:return function(cH,cJ,cI,cK){return cF.call(cb,cH,cJ,cI,cK)}}return function(){return cF.apply(cb,arguments)}}function aW(cF,cb,cG){if(cF==null){return aw}if(bW(cF)){return b0(cF,cb,cG)}if(cD(cF)&&!aR(cF)){return bY(cF)}return ag(cF)}function az(cF,cb){return aW(cF,cb,Infinity)}a8.iteratee=az;function bz(cF,cb,cG){if(a8.iteratee!==az){return a8.iteratee(cF,cb)}return aW(cF,cb,cG)}function p(cJ,cL,cH){cL=bz(cL,cH);var cG=bm(cJ),cI=cG.length,cF={};for(var cb=0;cb<cI;cb++){var cK=cG[cb];cF[cK]=cL(cJ[cK],cK,cJ)}return cF}function d(){}function b9(cb){if(cb==null){return d}return function(cF){return h(cb,cF)}}function g(cI,cH,cG){var cb=Array(Math.max(0,cI));cH=b0(cH,cG,1);for(var cF=0;cF<cI;cF++){cb[cF]=cH(cF)}return cb}function bo(cF,cb){if(cb==null){cb=cF;cF=0}return cF+Math.floor(Math.random()*(cb-cF+1))}var br=Date.now||function(){return new Date().getTime()};function bi(cI){var cF=function(cJ){return cI[cJ]};var cH="(?:"+bm(cI).join("|")+")";var cG=RegExp(cH);var cb=RegExp(cH,"g");return function(cJ){cJ=cJ==null?"":""+cJ;return cG.test(cJ)?cJ.replace(cb,cF):cJ}}var T={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"};var M=bi(T);var I=bk(T);var c=bi(I);var av=a8.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var v=/(.)^/;var cp={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"};var bt=/\\|'|\r|\n|\u2028|\u2029/g;function cg(cb){return"\\"+cp[cb]}var b8=/^\s*(\w|\$)+\s*$/;function aT(cN,cH,cL){if(!cH&&cL){cH=cL}cH=aF({},cH,a8.templateSettings);var cI=RegExp([(cH.escape||v).source,(cH.interpolate||v).source,(cH.evaluate||v).source].join("|")+"|$","g");var cJ=0;var cb="__p+='";cN.replace(cI,function(cP,cQ,cO,cS,cR){cb+=cN.slice(cJ,cR).replace(bt,cg);cJ=cR+cP.length;if(cQ){cb+="'+\n((__t=("+cQ+"))==null?'':_.escape(__t))+\n'"}else{if(cO){cb+="'+\n((__t=("+cO+"))==null?'':__t)+\n'"}else{if(cS){cb+="';\n"+cS+"\n__p+='"}}}return cP});cb+="';\n";var cF=cH.variable;if(cF){if(!b8.test(cF)){throw new Error("variable is not a bare identifier: "+cF)}}else{cb="with(obj||{}){\n"+cb+"}\n";cF="obj"}cb="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+cb+"return __p;\n";var cG;try{cG=new Function(cF,"_",cb)}catch(cK){cK.source=cb;throw cK}var cM=function(cO){return cG.call(this,cO,a8)};cM.source="function("+cF+"){\n"+cb+"}";return cM}function L(cH,cG,cJ){cG=cd(cG);var cF=cG.length;if(!cF){return bW(cJ)?cJ.call(cH):cJ}for(var cb=0;cb<cF;cb++){var cI=cH==null?void 0:cH[cG[cb]];if(cI===void 0){cI=cJ;cb=cF}cH=bW(cI)?cI.call(cH):cI}return cH}var bj=0;function bu(cb){var cF=++bj+"";return cb?cb+cF:cF}function aN(cF){var cb=a8(cF);cb._chain=true;return cb}function cv(cJ,cG,cI,cK,cH){if(!(cK instanceof cG)){return cJ.apply(cI,cH)}var cF=bc(cJ.prototype);var cb=cJ.apply(cF,cH);if(cD(cb)){return cb}return cF}var ca=cm(function(cF,cH){var cG=ca.placeholder;var cb=function(){var cI=0,cL=cH.length;var cJ=Array(cL);for(var cK=0;cK<cL;cK++){cJ[cK]=cH[cK]===cG?arguments[cI++]:cH[cK]}while(cI<arguments.length){cJ.push(arguments[cI++])}return cv(cF,cb,this,this,cJ)};return cb});ca.placeholder=a8;var bb=cm(function(cH,cF,cb){if(!bW(cH)){throw new TypeError("Bind must be called on a function")}var cG=cm(function(cI){return cv(cH,cG,cF,this,cb.concat(cI))});return cG});var aL=cz(B);function a2(cK,cH,cL,cF){cF=cF||[];if(!cH&&cH!==0){cH=Infinity}else{if(cH<=0){return cF.concat(cK)}}var cN=cF.length;for(var cI=0,cb=B(cK);cI<cb;cI++){var cM=cK[cI];if(aL(cM)&&(aR(cM)||bK(cM))){if(cH>1){a2(cM,cH-1,cL,cF);cN=cF.length}else{var cG=0,cJ=cM.length;while(cG<cJ){cF[cN++]=cM[cG++]}}}else{if(!cL){cF[cN++]=cM}}}return cF}var aJ=cm(function(cH,cG){cG=a2(cG,false,false);var cb=cG.length;if(cb<1){throw new Error("bindAll must be passed function names")}while(cb--){var cF=cG[cb];cH[cF]=bb(cH[cF],cH)}return cH});function ah(cF,cb){var cG=function(cJ){var cI=cG.cache;var cH=""+(cb?cb.apply(this,arguments):cJ);if(!k(cI,cH)){cI[cH]=cF.apply(this,arguments)}return cI[cH]};cG.cache={};return cG}var a0=cm(function(cF,cG,cb){return setTimeout(function(){return cF.apply(null,cb)},cG)});var ae=ca(a0,a8,1);function bw(cG,cI,cM){var cL,cF,cK,cN;var cJ=0;if(!cM){cM={}}var cH=function(){cJ=cM.leading===false?0:br();cL=null;cN=cG.apply(cF,cK);if(!cL){cF=cK=null}};var cb=function(){var cO=br();if(!cJ&&cM.leading===false){cJ=cO}var cP=cI-(cO-cJ);cF=this;cK=arguments;if(cP<=0||cP>cI){if(cL){clearTimeout(cL);cL=null}cJ=cO;cN=cG.apply(cF,cK);if(!cL){cF=cK=null}}else{if(!cL&&cM.trailing!==false){cL=setTimeout(cH,cP)}}return cN};cb.cancel=function(){clearTimeout(cL);cJ=0;cL=cF=cK=null};return cb}function bS(cG,cJ,cF){var cM,cK,cL,cN,cb;var cI=function(){var cO=br()-cK;if(cJ>cO){cM=setTimeout(cI,cJ-cO)}else{cM=null;if(!cF){cN=cG.apply(cb,cL)}if(!cM){cL=cb=null}}};var cH=cm(function(cO){cb=this;cL=cO;cK=br();if(!cM){cM=setTimeout(cI,cJ);if(cF){cN=cG.apply(cb,cL)}}return cN});cH.cancel=function(){clearTimeout(cM);cM=cL=cb=null};return cH}function a9(cb,cF){return ca(cF,cb)}function z(cb){return function(){return !cb.apply(this,arguments)}}function bT(){var cb=arguments;var cF=cb.length-1;return function(){var cH=cF;var cG=cb[cF].apply(this,arguments);while(cH--){cG=cb[cH].call(this,cG)}return cG}}function P(cF,cb){return function(){if(--cF<1){return cb.apply(this,arguments)}}}function b1(cG,cF){var cb;return function(){if(--cG>0){cb=cF.apply(this,arguments)}if(cG<=1){cF=null}return cb}}var bJ=ca(b1,2);function bD(cK,cb,cI){cb=bz(cb,cI);var cH=bm(cK),cG;for(var cF=0,cJ=cH.length;cF<cJ;cF++){cG=cH[cF];if(cb(cK[cG],cG,cK)){return cG}}}function bp(cb){return function(cJ,cF,cH){cF=bz(cF,cH);var cI=B(cJ);var cG=cb>0?0:cI-1;for(;cG>=0&&cG<cI;cG+=cb){if(cF(cJ[cG],cG,cJ)){return cG}}return -1}}var ck=bp(1);var E=bp(-1);function ap(cL,cJ,cK,cG){cK=bz(cK,cG,1);var cI=cK(cJ);var cb=0,cH=B(cL);while(cb<cH){var cF=Math.floor((cb+cH)/2);if(cK(cL[cF])<cI){cb=cF+1}else{cH=cF}}return cb}function aV(cb,cF,cG){return function(cL,cK,cH){var cI=0,cJ=B(cL);if(typeof cH=="number"){if(cb>0){cI=cH>=0?cH:Math.max(cH+cJ,cI)}else{cJ=cH>=0?Math.min(cH+1,cJ):cH+cJ+1}}else{if(cG&&cH&&cJ){cH=cG(cL,cK);return cL[cH]===cK?cH:-1}}if(cK!==cK){cH=cF(V.call(cL,cI,cJ),a6);return cH>=0?cH+cI:-1}for(cH=cb>0?cI:cJ-1;cH>=0&&cH<cJ;cH+=cb){if(cL[cH]===cK){return cH}}return -1}}var co=aV(1,ck,ap);var cE=aV(-1,E);function aS(cI,cb,cG){var cH=aL(cI)?ck:bD;var cF=cH(cI,cb,cG);if(cF!==void 0&&cF!==-1){return cI[cF]}}function D(cF,cb){return aS(cF,bY(cb))}function N(cI,cJ,cG){cJ=b0(cJ,cG);var cF,cH;if(aL(cI)){for(cF=0,cH=cI.length;cF<cH;cF++){cJ(cI[cF],cF,cI)}}else{var cb=bm(cI);for(cF=0,cH=cb.length;cF<cH;cF++){cJ(cI[cb[cF]],cb[cF],cI)}}return cI}function ax(cJ,cL,cH){cL=bz(cL,cH);var cG=!aL(cJ)&&bm(cJ),cI=(cG||cJ).length,cF=Array(cI);for(var cb=0;cb<cI;cb++){var cK=cG?cG[cb]:cb;cF[cb]=cL(cJ[cK],cK,cJ)}return cF}function bZ(cb){var cF=function(cL,cN,cG,cI){var cJ=!aL(cL)&&bm(cL),cK=(cJ||cL).length,cH=cb>0?0:cK-1;if(!cI){cG=cL[cJ?cJ[cH]:cH];cH+=cb}for(;cH>=0&&cH<cK;cH+=cb){var cM=cJ?cJ[cH]:cH;cG=cN(cG,cL[cM],cM,cL)}return cG};return function(cJ,cK,cG,cI){var cH=arguments.length>=3;return cF(cJ,b0(cK,cI,4),cG,cH)}}var by=bZ(1);var b7=bZ(-1);function a1(cH,cb,cG){var cF=[];cb=bz(cb,cG);N(cH,function(cK,cI,cJ){if(cb(cK,cI,cJ)){cF.push(cK)}});return cF}function w(cG,cb,cF){return a1(cG,z(bz(cb)),cF)}function r(cJ,cb,cH){cb=bz(cb,cH);var cG=!aL(cJ)&&bm(cJ),cI=(cG||cJ).length;for(var cF=0;cF<cI;cF++){var cK=cG?cG[cF]:cF;if(!cb(cJ[cK],cK,cJ)){return false}}return true}function ak(cJ,cb,cH){cb=bz(cb,cH);var cG=!aL(cJ)&&bm(cJ),cI=(cG||cJ).length;for(var cF=0;cF<cI;cF++){var cK=cG?cG[cF]:cF;if(cb(cJ[cK],cK,cJ)){return true}}return false}function ai(cH,cG,cb,cF){if(!aL(cH)){cH=aK(cH)}if(typeof cb!="number"||cF){cb=0}return co(cH,cG,cb)>=0}var C=cm(function(cI,cH,cF){var cb,cG;if(bW(cH)){cG=cH}else{cH=cd(cH);cb=cH.slice(0,-1);cH=cH[cH.length-1]}return ax(cI,function(cJ){var cK=cG;if(!cK){if(cb&&cb.length){cJ=cw(cJ,cb)}if(cJ==null){return void 0}cK=cJ[cH]}return cK==null?cK:cK.apply(cJ,cF)})});function cx(cF,cb){return ax(cF,ag(cb))}function f(cF,cb){return a1(cF,bY(cb))}function at(cH,cJ,cb){var cM=-Infinity,cK=-Infinity,cL,cG;if(cJ==null||typeof cJ=="number"&&typeof cH[0]!="object"&&cH!=null){cH=aL(cH)?cH:aK(cH);for(var cI=0,cF=cH.length;cI<cF;cI++){cL=cH[cI];if(cL!=null&&cL>cM){cM=cL}}}else{cJ=bz(cJ,cb);N(cH,function(cN,cO,cP){cG=cJ(cN,cO,cP);if(cG>cK||cG===-Infinity&&cM===-Infinity){cM=cN;cK=cG}})}return cM}function bx(cH,cJ,cb){var cM=Infinity,cK=Infinity,cL,cG;if(cJ==null||typeof cJ=="number"&&typeof cH[0]!="object"&&cH!=null){cH=aL(cH)?cH:aK(cH);for(var cI=0,cF=cH.length;cI<cF;cI++){cL=cH[cI];if(cL!=null&&cL<cM){cM=cL}}}else{cJ=bz(cJ,cb);N(cH,function(cN,cO,cP){cG=cJ(cN,cO,cP);if(cG<cK||cG===Infinity&&cM===Infinity){cM=cN;cK=cG}})}return cM}function b6(cG,cF,cI){if(cF==null||cI){if(!aL(cG)){cG=aK(cG)}return cG[bo(cG.length-1)]}var cK=aL(cG)?bR(cG):aK(cG);var cb=B(cK);cF=Math.max(Math.min(cF,cb),0);var cL=cb-1;for(var cH=0;cH<cF;cH++){var cJ=bo(cH,cL);var cM=cK[cH];cK[cH]=cK[cJ];cK[cJ]=cM}return cK.slice(0,cF)}function aI(cb){return b6(cb,Infinity)}function an(cG,cH,cF){var cb=0;cH=bz(cH,cF);return cx(ax(cG,function(cK,cI,cJ){return{value:cK,index:cb++,criteria:cH(cK,cI,cJ)}}).sort(function(cL,cK){var cJ=cL.criteria;var cI=cK.criteria;if(cJ!==cI){if(cJ>cI||cJ===void 0){return 1}if(cJ<cI||cI===void 0){return -1}}return cL.index-cK.index}),"value")}function aB(cF,cb){return function(cI,cJ,cH){var cG=cb?[[],[]]:{};cJ=bz(cJ,cH);N(cI,function(cM,cK){var cL=cJ(cM,cK,cI);cF(cG,cM,cL)});return cG}}var aD=aB(function(cb,cG,cF){if(k(cb,cF)){cb[cF].push(cG)}else{cb[cF]=[cG]}});var cq=aB(function(cb,cG,cF){cb[cF]=cG});var aX=aB(function(cb,cG,cF){if(k(cb,cF)){cb[cF]++}else{cb[cF]=1}});var bG=aB(function(cb,cG,cF){cb[cF?0:1].push(cG)},true);var cB=/[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;function A(cb){if(!cb){return[]}if(aR(cb)){return V.call(cb)}if(bN(cb)){return cb.match(cB)}if(aL(cb)){return ax(cb,aw)}return aK(cb)}function al(cb){if(cb==null){return 0}return aL(cb)?cb.length:bm(cb).length}function cc(cF,cb,cG){return cb in cG}var aY=cm(function(cK,cI){var cb={},cL=cI[0];if(cK==null){return cb}if(bW(cL)){if(cI.length>1){cL=b0(cL,cI[1])}cI=cj(cK)}else{cL=cc;cI=a2(cI,false,false);cK=Object(cK)}for(var cG=0,cH=cI.length;cG<cH;cG++){var cF=cI[cG];var cJ=cK[cF];if(cL(cJ,cF,cK)){cb[cF]=cJ}}return cb});var bF=cm(function(cG,cF){var cH=cF[0],cb;if(bW(cH)){cH=z(cH);if(cF.length>1){cb=cF[1]}}else{cF=ax(a2(cF,false,false),String);cH=function(cJ,cI){return !ai(cF,cI)}}return aY(cG,cH,cb)});function cs(cG,cF,cb){return V.call(cG,0,Math.max(0,cG.length-(cF==null||cb?1:cF)))}function ar(cG,cF,cb){if(cG==null||cG.length<1){return cF==null||cb?void 0:[]}if(cF==null||cb){return cG[0]}return cs(cG,cG.length-cF)}function bl(cG,cF,cb){return V.call(cG,cF==null||cb?1:cF)}function aG(cG,cF,cb){if(cG==null||cG.length<1){return cF==null||cb?void 0:[]}if(cF==null||cb){return cG[cG.length-1]}return bl(cG,Math.max(0,cG.length-cF))}function H(cb){return a1(cb,Boolean)}function bQ(cF,cb){return a2(cF,cb,false)}var b=cm(function(cF,cb){cb=a2(cb,true,true);return a1(cF,function(cG){return !ai(cb,cG)})});var ci=cm(function(cF,cb){return b(cF,cb)});function a3(cL,cH,cK,cF){if(!aU(cH)){cF=cK;cK=cH;cH=false}if(cK!=null){cK=bz(cK,cF)}var cN=[];var cb=[];for(var cJ=0,cG=B(cL);cJ<cG;cJ++){var cM=cL[cJ],cI=cK?cK(cM,cJ,cL):cM;if(cH&&!cK){if(!cJ||cb!==cI){cN.push(cM)}cb=cI}else{if(cK){if(!ai(cb,cI)){cb.push(cI);cN.push(cM)}}else{if(!ai(cN,cM)){cN.push(cM)}}}}return cN}var n=cm(function(cb){return a3(a2(cb,true,true))});function bM(cK){var cb=[];var cJ=arguments.length;for(var cG=0,cI=B(cK);cG<cI;cG++){var cH=cK[cG];if(ai(cb,cH)){continue}var cF;for(cF=1;cF<cJ;cF++){if(!ai(arguments[cF],cH)){break}}if(cF===cJ){cb.push(cH)}}return cb}function cn(cH){var cG=cH&&at(cH,B).length||0;var cb=Array(cG);for(var cF=0;cF<cG;cF++){cb[cF]=cx(cH,cF)}return cb}var j=cm(cn);function J(cI,cF){var cb={};for(var cG=0,cH=B(cI);cG<cH;cG++){if(cF){cb[cI[cG]]=cF[cG]}else{cb[cI[cG][0]]=cI[cG][1]}}return cb}function Y(cJ,cG,cI){if(cG==null){cG=cJ||0;cJ=0}if(!cI){cI=cG<cJ?-1:1}var cH=Math.max(Math.ceil((cG-cJ)/cI),0);var cF=Array(cH);for(var cb=0;cb<cH;cb++,cJ+=cI){cF[cb]=cJ}return cF}function b2(cI,cH){if(cH==null||cH<1){return[]}var cb=[];var cF=0,cG=cI.length;while(cF<cG){cb.push(V.call(cI,cF,cF+=cH))}return cb}function bn(cb,cF){return cb._chain?a8(cF).chain():cF}function x(cb){N(bX(cb),function(cF){var cG=a8[cF]=cb[cF];a8.prototype[cF]=function(){var cH=[this._wrapped];q.apply(cH,arguments);return bn(this,cG.apply(a8,cH))}});return a8}N(["pop","push","reverse","shift","sort","splice","unshift"],function(cb){var cF=bV[cb];a8.prototype[cb]=function(){var cG=this._wrapped;if(cG!=null){cF.apply(cG,arguments);if((cb==="shift"||cb==="splice")&&cG.length===0){delete cG[0]}}return bn(this,cG)}});N(["concat","join","slice"],function(cb){var cF=bV[cb];a8.prototype[cb]=function(){var cG=this._wrapped;if(cG!=null){cG=cF.apply(cG,arguments)}return bn(this,cG)}});var ay={__proto__:null,VERSION:cu,restArguments:cm,isObject:cD,isNull:cl,isUndefined:ba,isBoolean:aU,isElement:be,isString:bN,isNumber:aE,isDate:am,isRegExp:b3,isError:R,isSymbol:bI,isArrayBuffer:W,isDataView:aQ,isArray:aR,isFunction:bW,isArguments:bK,isFinite:cA,isNaN:a6,isTypedArray:l,isEmpty:bC,isMatch:Z,isEqual:bg,isMap:cy,isWeakMap:au,isSet:a5,isWeakSet:ct,keys:bm,allKeys:cj,values:aK,pairs:aO,invert:bk,functions:bX,methods:bX,extend:bA,extendOwn:cr,assign:cr,defaults:aF,create:K,clone:bR,tap:bP,get:h,has:ce,mapObject:p,identity:aw,constant:bH,noop:d,toPath:bL,property:ag,propertyOf:b9,matcher:bY,matches:bY,times:g,random:bo,now:br,escape:M,unescape:c,templateSettings:av,template:aT,result:L,uniqueId:bu,chain:aN,iteratee:az,partial:ca,bind:bb,bindAll:aJ,memoize:ah,delay:a0,defer:ae,throttle:bw,debounce:bS,wrap:a9,negate:z,compose:bT,after:P,before:b1,once:bJ,findKey:bD,findIndex:ck,findLastIndex:E,sortedIndex:ap,indexOf:co,lastIndexOf:cE,find:aS,detect:aS,findWhere:D,each:N,forEach:N,map:ax,collect:ax,reduce:by,foldl:by,inject:by,reduceRight:b7,foldr:b7,filter:a1,select:a1,reject:w,every:r,all:r,some:ak,any:ak,contains:ai,includes:ai,include:ai,invoke:C,pluck:cx,where:f,max:at,min:bx,shuffle:aI,sample:b6,sortBy:an,groupBy:aD,indexBy:cq,countBy:aX,partition:bG,toArray:A,size:al,pick:aY,omit:bF,first:ar,head:ar,take:ar,initial:cs,last:aG,rest:bl,tail:bl,drop:bl,compact:H,flatten:bQ,without:ci,uniq:a3,unique:a3,union:n,intersection:bM,difference:b,unzip:cn,transpose:cn,zip:j,object:J,range:Y,chunk:b2,mixin:x,"default":a8};var bE=x(ay);bE._=bE;return bE})));
WRFILE: bootstrap.min.css

/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{color:#000 !important;text-shadow:none !important;background:transparent !important;-webkit-box-shadow:none !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media(min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width:768px){.container{width:750px}}@media(min-width:992px){.container{width:970px}}@media(min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media(min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{position:static;display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label ~ .form-control-feedback{top:25px}.has-feedback label.sr-only ~ .form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media(min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media(min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:normal;color:#337ab7;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media(min-width:768px){.navbar{border-radius:4px}}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media(max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media(min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media(min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right ~ .navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-right:15px;padding-left:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:transparent;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media(min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media(min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:normal;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:normal;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media(max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media(max-width:767px){.visible-xs-block{display:block !important}}@media(max-width:767px){.visible-xs-inline{display:inline !important}}@media(max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media(min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media(min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media(min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media(min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media(min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media(min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media(min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media(min-width:1200px){.visible-lg-block{display:block !important}}@media(min-width:1200px){.visible-lg-inline{display:inline !important}}@media(min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media(max-width:767px){.hidden-xs{display:none !important}}@media(min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media(min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media(min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}
WRFILE: fontawesome.min.css

/*!
 *  Font Awesome 3.2.1
 *  the iconic font designed for Bootstrap
 *  ------------------------------------------------------------------------------
 *  The full suite of pictographic icons, examples, and documentation can be
 *  found at http://fontawesome.io.  Stay up to date on Twitter at
 *  http://twitter.com/fontawesome.
 *
 *  License
 *  ------------------------------------------------------------------------------
 *  - The Font Awesome font is licensed under SIL OFL 1.1 -
 *    http://scripts.sil.org/OFL
 *  - Font Awesome CSS, LESS, and SASS files are licensed under MIT License -
 *    http://opensource.org/licenses/mit-license.html
 *  - Font Awesome documentation licensed under CC BY 3.0 -
 *    http://creativecommons.org/licenses/by/3.0/
 *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
 *    "Font Awesome by Dave Gandy - http://fontawesome.io"
 *
 *  Author - Dave Gandy
 *  ------------------------------------------------------------------------------
 *  Email: dave@fontawesome.io
 *  Twitter: http://twitter.com/davegandy
 *  Work: Lead Product Designer @ Kyruus - http://kyruus.com
 */@font-face{font-family:'FontAwesome';src: url('data:font/opentype;charset=utf-8;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAsAAwAKAAIDgABwAcAAAAaAAHYFgAAABAAAXwcAAAAHAAAABwAAAAcAAAAHAAAABYAAAAcAAAAHAABdBgAAAAaAAAAHAAAABwAAAAaAAAAGgAAABYAAAAeAAAAGgAAABwAAAAcAAAAHAAB5BYAAbgaAAAAGgAAABgAAAAcAAAAGAAAABYAAAAaAABoFAAAABgAAAAeAADIGgAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABwAAAASAAAAHAABABoAAAAMAAAAEgAAABoAAAAWAAAAHAAAABgAAAAeAAAAGgP//BQAAAAaAAAAHgAAABoAAAAWAAAAEAAAABwAAAAYAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAeAAAAGAAAABAAAAAYAAAAEAAAABwAAAAaAAAAGgAAABwAAAAQAAAAHAAAABoAAegWAAAAGAAAABgAAAAaAAAAHAAAABAAAAAYC//8EgAA1BIAAdQYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAABABgAAAAaAADUGgAA1BwAAAAYAAAAGAAANBgAAAAYAAAAHAAAABYAAAAcAAAAHAAAABwAAAAWAAAAGgAAABwAAAAcAAAAGAAAABoAANQaAADUHgAAABoAAAAaAAAAHgAAAAwAAQAcAAAAHgAAABgAAAAYAAAAHAAAABwAAAAeAAAAHAAAABgAAAAYAAAADgAAABwAAAAaAAAAGAAAABIAAAAcAAAAGAAAABoAAAAYAAAAGgAAABgAAAAWAAAAFgAAABQAAAAYAAAAGgAAsAwAAAAYAAAAGgAAAB4AAAAWAAAAGAAAABwAAAAaAAAAGAP//BwAAAAcAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABoAAFQcAAAAFgAAABwAAAAYAAAAHAAAABwAAAAcAAAAHgAAABoAAEAeAAAAGgABmBwAAAAcAAAAFgAAEBgAAAAYAAAAGAAAABwAAAAcAAA8HAAAABgAAAAaAAAAGgAAbBwAAQAYAAAAGAAAABgAAAAaAAAAHgAAABAAAAAQAAAACgABAAoAAAAaAAAAEAAAABAAAAAQAAAAHAAAABgAAAAYAAAAHAAAoBwAAAAcAAAAHAAAAA4AAAAcAAAAGgAAABwAAAAQAAAAHAAAAB4AAAAeAAAAFgAAABYAAAAcAAAAGgAAAB4AAAAWAAAAFAAAABYAAAAWAAAAHgABABwAAAAeAAAAGgABABgAAAAYAAAAEAAAtBAAADQSAAE0EgABNAoAALQKAAA0EgABNBIAATQeAAAAHgAAABIAAAAMAAAAGAAAABoAAAAaAAAAGIAAABgAAAAcAAAAGgAAABoAAAAeAAAAEgAAABIAAAAYAAAAGAAAABgAAAAeAAAAHgAAABwAAQAcAAEAGgAANB4AALQcAAAAGgAAABYAAAAaAAAAEAAAABoAAAAKAAAACgABiBgAABQYAAAUHgAAABoAAAASAAAAFgAANBQAAAAaAAAAFgAAABoAAIAcAAAAGAAAABgAAAAYAAAAGAAAABYAAAAcAAAwHAAAABIAAAAYAAAAFgAAAAYAAAAYAAAAGAAAABwAANQYAAAAFgAAABAAAAAQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAQAAAAEAAAABAAALQOCAAAEAwAABoAAHAcAAAAFAAA4BQAAAAUAAAAGgAAfBoAAHwcAAB8HAAAfBgAAHwYAAB8GgAAABoAAAAYAAAAGAAAbBYAAAAYAAAAHAAAABwAAQAWAAAAGAAAABgAAAAYAAAAFgAAABgAAAAQAAE4GAAAAAwAAAAMAAAAHAABABwAAAAWAAAAGgAAABYAAAAYAAAYGAAAABgAAAAaA//8GAAAABQAAAAQAAAAGAAAABwAAKgYAAAAHAABABoAAIAeA//8HAAAAB4AAAAcAAAAAAAAAAAMAAAAAAAD/egBaAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQCAAEBAQxGb250QXdlc29tZQABAQFE+BAA+YUB+YYC+YYD+BkE+0cMA+UMBIr7lRwHgRwGAQUeoABVgDb/i4seoABVgDb/i4sMBxwghQ8cIKcRrh0AANUuEgFsAgABAAYACwARABkAHgAiACwAMAA0ADwAPgBFAEcATQBUAFwAXwBlAGgAbQBxAHkAfQCBAI0AlQCbAKAAqwCxALgAwADEAMgA0gDcAOcA8AD2AP0BAAEEAQgBEAEVARsBHwEjASkBNAE+AUgBVAFfAWwBcAF7AYcBlQGcAaIBrAGyAbYBugG/AcQByAHVAeIB6gHuAfMB9wH+AgoCFgIbAicCNAI9AkcCUgJZAmYCbwJ5AoYCjwKZAqMCrgK2AsACyQLUAuAC8AL0AvgC/AMEAw0DGQMeAyYDLAMzAzkDQwNPA1YDYwNvA3oDiQOaA6MDrwO8A8gDywPPA9cD5APzA/wEBwQOBBsEIgQvBDUEOwRGBFAEVQRaBGUEcwR9BIQEjASSBJgEowSmBKkEsQS1BMAEygTTBNoE4wT0BQYFFQUmBSsFMQU2BTwFRQVPBVcFXwVoBW0FcQV2BXwFfwWDBY0FkQWbBaIFpAWmBbMFvAXBBcYFywXUBeIF8gX9BgIGDAYUBh4GKQYwBjQGPQZEBlAGWAZcBmEGagZ1BoEGhQaMBpQGmQajBqsGuQbFBswG1wbfBucG7QbxBv4HBgcOBxcHHQcoBywHMgc2B0cHWQdoB3kHgweOB5YHoAenB60Hswe/B8sH1QfgB+cH7QfyB/wIDAgbCCUIMQg2CDsIPghFCE0IVQhjCGsIbwh4CIcIlQiZCKIIqAisCLcIwgjLCM8I2wjlCPMI+QkHCRgJHgkkCTUJRwlWCWcJbAlwCXYJgAmICZsJrAmwCbkJvwnNCdgJ4AnqCfQJ/QoBCgsKEgoaCiYKKgotCjAKMwo2CjkKPAo/CkIKRgpPCl8KYwp1CosKmAqpCq0KsQq9CsQKyArRCt0K5ArxCvoLAAsDCwcLFQsbCyYLNQtCC1ELYQtmC20LdAt5C4ALhQuPC5ULmwufC6ULqAusC7MLtgu4C70LwwvHC8sLzwvoC/NnbGFzc211c2ljc2VhcmNoZW52ZWxvcGVoZWFydHN0YXJzdGFyX2VtcHR5dXNlcmZpbG10aF9sYXJnZXRodGhfbGlzdG9rcmVtb3Zlem9vbV9pbnpvb21fb3V0b2Zmc2lnbmFsY29ndHJhc2hob21lZmlsZV9hbHR0aW1lcm9hZGRvd25sb2FkX2FsdGRvd25sb2FkdXBsb2FkaW5ib3hwbGF5X2NpcmNsZXJlcGVhdHJlZnJlc2hsaXN0X2FsdGxvY2tmbGFnaGVhZHBob25lc3ZvbHVtZV9vZmZ2b2x1bWVfZG93bnZvbHVtZV91cHFyY29kZWJhcmNvZGV0YWd0YWdzYm9va2Jvb2ttYXJrcHJpbnRjYW1lcmFmb250Ym9sZGl0YWxpY3RleHRfaGVpZ2h0dGV4dF93aWR0aGFsaWduX2xlZnRhbGlnbl9jZW50ZXJhbGlnbl9yaWdodGFsaWduX2p1c3RpZnlsaXN0aW5kZW50X2xlZnRpbmRlbnRfcmlnaHRmYWNldGltZV92aWRlb3BpY3R1cmVwZW5jaWxtYXBfbWFya2VyYWRqdXN0dGludGVkaXRzaGFyZWNoZWNrbW92ZXN0ZXBfYmFja3dhcmRmYXN0X2JhY2t3YXJkYmFja3dhcmRwbGF5cGF1c2VzdG9wZm9yd2FyZGZhc3RfZm9yd2FyZHN0ZXBfZm9yd2FyZGVqZWN0Y2hldnJvbl9sZWZ0Y2hldnJvbl9yaWdodHBsdXNfc2lnbm1pbnVzX3NpZ25yZW1vdmVfc2lnbm9rX3NpZ25xdWVzdGlvbl9zaWduaW5mb19zaWduc2NyZWVuc2hvdHJlbW92ZV9jaXJjbGVva19jaXJjbGViYW5fY2lyY2xlYXJyb3dfbGVmdGFycm93X3JpZ2h0YXJyb3dfdXBhcnJvd19kb3duc2hhcmVfYWx0cmVzaXplX2Z1bGxyZXNpemVfc21hbGxleGNsYW1hdGlvbl9zaWduZ2lmdGxlYWZmaXJlZXllX29wZW5leWVfY2xvc2V3YXJuaW5nX3NpZ25wbGFuZWNhbGVuZGFycmFuZG9tY29tbWVudG1hZ25ldGNoZXZyb25fdXBjaGV2cm9uX2Rvd25yZXR3ZWV0c2hvcHBpbmdfY2FydGZvbGRlcl9jbG9zZWZvbGRlcl9vcGVucmVzaXplX3ZlcnRpY2FscmVzaXplX2hvcml6b250YWxiYXJfY2hhcnR0d2l0dGVyX3NpZ25mYWNlYm9va19zaWduY2FtZXJhX3JldHJva2V5Y29nc2NvbW1lbnRzdGh1bWJzX3VwX2FsdHRodW1ic19kb3duX2FsdHN0YXJfaGFsZmhlYXJ0X2VtcHR5c2lnbm91dGxpbmtlZGluX3NpZ25wdXNocGluZXh0ZXJuYWxfbGlua3NpZ25pbnRyb3BoeWdpdGh1Yl9zaWdudXBsb2FkX2FsdGxlbW9ucGhvbmVjaGVja19lbXB0eWJvb2ttYXJrX2VtcHR5cGhvbmVfc2lnbnR3aXR0ZXJmYWNlYm9va2dpdGh1YnVubG9ja2NyZWRpdF9jYXJkcnNzaGRkYnVsbGhvcm5iZWxsY2VydGlmaWNhdGVoYW5kX3JpZ2h0aGFuZF9sZWZ0aGFuZF91cGhhbmRfZG93bmNpcmNsZV9hcnJvd19sZWZ0Y2lyY2xlX2Fycm93X3JpZ2h0Y2lyY2xlX2Fycm93X3VwY2lyY2xlX2Fycm93X2Rvd25nbG9iZXdyZW5jaHRhc2tzZmlsdGVyYnJpZWZjYXNlZnVsbHNjcmVlbm5vdGVxdWFsaW5maW5pdHlsZXNzZXF1YWxncm91cGxpbmtjbG91ZGJlYWtlcmN1dGNvcHlwYXBlcl9jbGlwc2F2ZXNpZ25fYmxhbmtyZW9yZGVydWxvbHN0cmlrZXRocm91Z2h1bmRlcmxpbmV0YWJsZW1hZ2ljdHJ1Y2twaW50ZXJlc3RwaW50ZXJlc3Rfc2lnbmdvb2dsZV9wbHVzX3NpZ25nb29nbGVfcGx1c21vbmV5Y2FyZXRfZG93bmNhcmV0X3VwY2FyZXRfbGVmdGNhcmV0X3JpZ2h0Y29sdW1uc3NvcnRzb3J0X2Rvd25zb3J0X3VwZW52ZWxvcGVfYWx0bGlua2VkaW51bmRvbGVnYWxkYXNoYm9hcmRjb21tZW50X2FsdGNvbW1lbnRzX2FsdGJvbHRzaXRlbWFwdW1icmVsbGFwYXN0ZWxpZ2h0X2J1bGJleGNoYW5nZWNsb3VkX2Rvd25sb2FkY2xvdWRfdXBsb2FkdXNlcl9tZHN0ZXRob3Njb3Blc3VpdGNhc2ViZWxsX2FsdGNvZmZlZWZvb2RmaWxlX3RleHRfYWx0YnVpbGRpbmdob3NwaXRhbGFtYnVsYW5jZW1lZGtpdGZpZ2h0ZXJfamV0YmVlcmhfc2lnbmYwZmVkb3VibGVfYW5nbGVfbGVmdGRvdWJsZV9hbmdsZV9yaWdodGRvdWJsZV9hbmdsZV91cGRvdWJsZV9hbmdsZV9kb3duYW5nbGVfbGVmdGFuZ2xlX3JpZ2h0YW5nbGVfdXBhbmdsZV9kb3duZGVza3RvcGxhcHRvcHRhYmxldG1vYmlsZV9waG9uZWNpcmNsZV9ibGFua3F1b3RlX2xlZnRxdW90ZV9yaWdodHNwaW5uZXJjaXJjbGVyZXBseWdpdGh1Yl9hbHRmb2xkZXJfY2xvc2VfYWx0Zm9sZGVyX29wZW5fYWx0ZXhwYW5kX2FsdGNvbGxhcHNlX2FsdHNtaWxlZnJvd25tZWhnYW1lcGFka2V5Ym9hcmRmbGFnX2FsdGZsYWdfY2hlY2tlcmVkdGVybWluYWxjb2RlcmVwbHlfYWxsc3Rhcl9oYWxmX2VtcHR5bG9jYXRpb25fYXJyb3djcm9wY29kZV9mb3JrdW5saW5rXzI3OWV4Y2xhbWF0aW9uc3VwZXJzY3JpcHRzdWJzY3JpcHRfMjgzcHV6emxlX3BpZWNlbWljcm9waG9uZW1pY3JvcGhvbmVfb2Zmc2hpZWxkY2FsZW5kYXJfZW1wdHlmaXJlX2V4dGluZ3Vpc2hlcnJvY2tldG1heGNkbmNoZXZyb25fc2lnbl9sZWZ0Y2hldnJvbl9zaWduX3JpZ2h0Y2hldnJvbl9zaWduX3VwY2hldnJvbl9zaWduX2Rvd25odG1sNWNzczNhbmNob3J1bmxvY2tfYWx0YnVsbHNleWVlbGxpcHNpc19ob3Jpem9udGFsZWxsaXBzaXNfdmVydGljYWxfMzAzcGxheV9zaWdudGlja2V0bWludXNfc2lnbl9hbHRjaGVja19taW51c2xldmVsX3VwbGV2ZWxfZG93bmNoZWNrX3NpZ25lZGl0X3NpZ25fMzEyc2hhcmVfc2lnbmNvbXBhc3Njb2xsYXBzZWNvbGxhcHNlX3RvcF8zMTdldXJnYnB1c2RpbnJqcHljbnlrcndidGNmaWxlZmlsZV90ZXh0c29ydF9ieV9hbHBoYWJldF8zMjlzb3J0X2J5X2F0dHJpYnV0ZXNzb3J0X2J5X2F0dHJpYnV0ZXNfYWx0c29ydF9ieV9vcmRlcnNvcnRfYnlfb3JkZXJfYWx0XzMzNF8zMzV5b3V0dWJlX3NpZ255b3V0dWJleGluZ3hpbmdfc2lnbnlvdXR1YmVfcGxheWRyb3Bib3hzdGFja2V4Y2hhbmdlaW5zdGFncmFtZmxpY2tyYWRuZjE3MWJpdGJ1Y2tldF9zaWdudHVtYmxydHVtYmxyX3NpZ25sb25nX2Fycm93X2Rvd25sb25nX2Fycm93X3VwbG9uZ19hcnJvd19sZWZ0bG9uZ19hcnJvd19yaWdodGFwcGxld2luZG93c2FuZHJvaWRsaW51eGRyaWJibGVza3lwZWZvdXJzcXVhcmV0cmVsbG9mZW1hbGVtYWxlZ2l0dGlwc3VuXzM2NmFyY2hpdmVidWd2a3dlaWJvcmVucmVuXzM3Ml8zNzNfMzc0U0lMIE9wZW4gRm9udCBMaWNlbnNlIDEuMUZvbnRBd2Vzb21lASMCAAEACQAWACcAOQA+AEsAVgBaAGIAdgB6AM4A1ADYANwA6gD3APwBEgEWATEBOgE/AUsBWQFnAWsBbwF0AXoCAQJKAk4CUQJVAmICZgJtAnICdwKBAoUCiQKSApoCqQMFAw8DVQNaA2ADZAO5A78D5QP5BAIECgQOBDYEOgReBG4EdATBBPIE9wT7BQAFRgVMBX0FoAWqBbkF7gYvBj8GRAZWBloGXgZiBmgGbQZ1Bn0Ggga3Bu4G8wb4Bv0HAwcHBxoHLQcxBzoHQQdKB04HUgdgB3sHhgeaB54HpQe9B8kH0gf+CCkIMQg2CDsIQAhFCEkIcQh1CIoIkQiUCJgIngijCKgIzgjUCN0I4gjnCPcI/QkGCQwJEgkjCS4JNQk8CUAJWwlfCWIJdwmACYsJmAmeCaMJqAm1Cb4JywnjCgIKIQopCkcKWApiCn0KmQqmCqsKtwrACsoK4wr1CvwLAwsICxULIwsxCzcLPAtAC1cLbguDC5kLrwu3C70LxAvKC9EL1gvbC/AMBQwXDCsMNww7DEMMSAxNDFsMbAx/DIgMmwyfDKgMrwy2DMgM0QzcDOEM5gzrDPwNDQ0SDRoNIg0yDTYNOg1CDUoNUQ1WDV0NZA1pDW4Ncg2BDZANmQ2hDaQNqQ2wDb4Nwg3KDdAN1Q3aDd8N6A3tDfMN9w39DgIOBw4UDiEOLA45Dj8ORg5KDk4OUg5WDlwOZg5uDnYOfg6EDokOjg6TDpgOng6mDrEOtw7CDskO0w7eDukO8g79DwEPBg8LDxD2CiId+lTECi4KSwZfCktEHctOCgv+VAb7M/sV+xX7Mx/+VCYdC6UduR1LHffA94i5HR73dBYgCmhubmgLlh2vHfdUWgr31HgKCwf7M/cV+xX3Mx4LBioKCwZfCvtURB0LaG5uaB77FPcTHfcAHW5oH/sUBwsuHR8LFYMd9xkd912tHfddrR33Jx0e+JT91BWtfax0oh776/frBdz3Cbb3IPciGvgZ+8/3z/wZ/Bn7z/vP/Bn8GffP+8/4Gfci9yC23PcJHvfr++r3Nh0LnX2ZeR4LNR0eCwYkHQsFhYWHgoMag4+CkYUeCzMdHPmAJgocBoAnHQsGOgofCysGgoSEgh8rB4KShJQe6waUkpKUHws7Ch4Llwr8HfdICvgdBZGFgo+DG4KDox34ZvxmZQoL9zP7FfcV+zMLeX19eQsFhZGUh5Mbk5S4CgskHWhuqK6uqKiuoB0eCwWRhYKPgxuDgoeFhR8LFSQKC0YdHwshCvuUC1ZgYFYfC5Sfte+dGo2KjoiNHpJ/IMqGG4WJaWltZG9kGYGMgYyBgYGKgQwkmoFA7n4bhiBLhX8fiImKiIkaerUmlHcef3uBeYN5CHeJ+xV9fBr7IAd89xV9n4kek3iVepd7CIJ3YSZ6GomMiI6JHoSX9kuQG5jW75qVH5WKlYqVlZWMlQwkfJXWJ5gbCxWcfJp6Hhz5QAZ6fHx6H/tUB3qafJweHAbABpyampwf+NQEnHyaeh7+1AZ6fHx6H/tUB3qafJwe+tSJHRz5QCgdHAbABjcKHw4VOB0LJx0OFSwdC1EKjwoDjwr3VBUwHQtTHR4LMAr7VC0KC8C2tsAL95RiHQv7IfcH+wdYCh4LFTMdC1IdiwulHYQd94j3wAsVdgqDCkgdC7Qdlgof/FT8VH0K+hRBHfc7+wL3KPs96B6aWpNYVxr7Ry/7Ofs7+w4e+wT7L/tfTftrG25tjY1uHzn3Efc6WfdJG8jGkZXDH95Q6WDwcaaEqIaph5uJmpiPnQjpCo+efpeAmGS3X7Jp3ggLG/xpi/xp/GkaC3cK+JT8NDIK+DT9lAb8FPoUFfgMB5yFnIKShPfN+80YkoSUepF6CPccaxXAbNVmsB77zPfMBbBmQapWG/0U9wYd+tQ2Cg4wCo0KC/sUVgoBCwdqCgsVbP5ui2wbfHyIhX0fX3pvYl4aHPr3B16nYrd6HoWZmoiaG6qol6CiH/hN+Dz4Tfw8BXaiqICqG5qajZGZH7ecp7S4GhwFCQe4b7RfnB6RfXyOfBsO9zkd9xQLjx1ZWQWFhYeCgxqDj4KRhR74Hfwd90gKwwr4ZvhmBZGRj5STGgvpHfyUBkVRUUUf/BQHqh34lIsKC1wdgYCLgU8dCwWRkY+UkxoLBl8dCxV6CvsG9wY5Hfvg++D7JPckfR38VCgK+FQG90Yd+yT3JPfg9+BZHQsWWwoLSR38VC4dnh0f9yT7JPvg++AvHfcG+wY3Hffg9+D3JPskfAoL9TXhIbgdIeE19fXh4fUeC52ZfXkfCxX3bfsU9xb7M/snIfsF+x77Fur7BvclxsagqacejQYjeE0n+wwbbnGRkncfgI6Aj4KPZPsFGJeGmYabhgiCpbCEuBv3gvcC92/3Xh8LH/u0B/gUyxXpHfsU6waFCkt7HSv8FOsHhQpLex0r+xQHRVFRRR8c+wAHqh1yHfcECvcUggoLNh0eCwagHR8L6PcNkJ4b9wzUiIa4H4W514fMG5SWi4yZH42YjJWRGpKJm4imHn2SepF4kGGXUZyGjHCQV6GBkIOlh5GMwIz3JxiI9/sFC2huqK4fC/c4HR77dAZWYLbAH6v3Mx0nHbcKHksG+677evt6+64f/VQHIeE19R74FAb14eH1HwsVnQr8tPi0fR37tPxUByQdH/wUKAr4VPu0BoId+LT4tHUdC8AKVgr81BW6HQsVgwr7IfsH9wf3IcEKHgsV/LQGVmC2wB/4tPy09y0KHPrAMgr61DYKiPo0FYK7ccFtqfvM98wYbalVpVuUCPyR+JEHDo+Hmh+ViJSEk4KQhZQsnlOeU51gnG6fjaGRpZUIjpmMnJ8ajMWK74r0jNqKvxmMfoKLhRthigWLc2prjR5pjQULxwr5OpoKHPqAmx35On8dC0RSUkQLqwbVCvvUBvsPJib7Dx/+VAcLBC4KCwaGCgscBYALeX2ZnR8L+xT3FAsFl5eSm5waC/do90D3KB0L0sTE0gtpOF9kZF+Afn5/j3gI6Qp6jpl/moyMi4wbqY+okKaS8KXptt7GCIHDxoXIG/gZ98/3efevC/e5+0f3Q/u/+0P7OPsePTwe2Tz7OPce+0Mb+7/7R/tD+7n7hPdw+12ThB/5BPzuBX+Xm4WbGwsGlAofCwaUHR8L90odHgtvCiQdHwscBIALB46Ej4WRhfla/VoYpHKflK4aCweIkoeRhZH9WvlaGHKkd4JoGgsVOQoLLwqcm5KXlx4L9xkd9ycdC/eI98D3wPeICweGHQs3Ch4LQB33lBY4HfcU93TgCgv3Lgr7dPt0Bqgd93T7dAdzHfdUWgr3dPd0BgtUCv7UKB361FQKC5OIowr70/fTBZGEg4+CGzAK+1QLFXwdCxWUhJKCHguSCvuU+5QFf3+Ee3oanh0e9xIKfAr3FAv3lPeUVR2THfcUAwt6Cvxm+GY5HQsV+zn5IvsPBvtU+03dNcnFmJiTlZCTGZKXBY17BoGKfn4a/ET7O/sG+GkHCxWXmIuff5h+l3eLfn/7lPuUGH9+i3eXfgiFkpOIkxuTk46Rkh/3lPeUBQv3LQr81MkKC/eU8R0LM0NDMwv3B/chC2Md+9QLbh1EC/oV9zsV+wEG+2D3vPdM958F9xH3PPuVBvsg+3hyYYaEh4SJhBmIBgscBMAL9xT3FPcU9xT3FPcU9xT3FPcU9xQLKAr3FCcdC3odDgcsHQt6knuXfwv4FPcUC66obmgLFfsS2ib3DGn3IWn7ISb7DPsSPAhg2ORz6hvp5KO22R/79PqJFQtCHYv7VAuHhYUfWVkvHQv3B/sHC/vA+4gL+5T3lPccCvuU+5R9CvcUCzEdy50dC3l9fdQKmZ0fC2YdaAoeC0XFUdEeC5z3Jh0e99T31AWRkY6UkxoL9xT3lPcU9xT3FAv3i/eL910LcqSLs6SkCwZzHQv7aPtA+0D7aPto+0D3KB12Hfdo90D7QPtoHgsVKR0LogoOFZ18mXoeHPtARwqgCnqZfJ33PQoLnQr8VPhUbwoLVmC2wEYdwLZgVgt/f3uFeht6e5GXfx8L9wAKmZ0LITU1IQv7iPvACy4KHPrAKB0cBUBOCgsyHfgU+zSMHQsuChz5QCgdHAbATgoLFVZgYFYe/VQGVmC2wB/5VAfAtrb3QQoLsaGltLoaHAXASxWhf6B4lx54lnSMd4GEh4CFfoQICxXU926Sn4yajpcZjp8FjwaFjIWMgx6XXNP7bgX9DAt/HRwFwOgKDgemT0mXSRv7AftnWPsh+yH3Z1j3AfcB92e+9yEfCxVt7W0pKW3tbakpqe3tqQULMx38FCod+xQHCxX3ECfv+xD7ECcn+xD7EO8n9xD3EO/v9xAeDhL3lPeU+Bf3s/tV9wz3mPe0+2b3DRP9QBwEpwt8HRz5wHEdmR33QgoL0B3mMAv5WvlakZGPkY6SGQsGTAoe+lQ2Cgv4PPfs9+z4PB8OMgefeZdxcBpWYGBWVmC2wKaXpZ+dHuQHC/cUEov3FPeU9xSL90QKi/cUC619rHSjHgt+fot3mH4Lnx34FAsFl5ebkfc8HYV/lx8LBXl5gXJyGnKVcp15Hgt0l3affx6GlZaIlhuWC/jUFVUKC88d9xQLat0KC/dN9xX3A/dRiR+yvaDLyxqZipqJmR4Lo8cb9wCgiIieH5GKj4mPiI6IjYWMhQuSi5GKkh81+Ij3//f2BZiYmJydGg5xdXVxcXWhpfc79x33Hfc7paF1cR4L97P1QAa69yQF94cGuvskBUAh97QGC1UdVgr3FAMLPQo7Ch8LpKSzi6RyCwGLch0DC3JyY4typAv3FJ8KC7kKnZkLBXmdgaOlGqSVo52dHvcn9yYFnJ0Lm5uRl5cf+QP47AWUlPdw9133hBoL9yUK+Eb3H9D3HcL3IAMcBUILiZKIkoWShJiEmoKZ+x/3eBj7qAv3FPcUi/cU95T3FAuL4B0LAYv6lAP6lAv3BR0eC34d9xQLBvsPJib7Dx/91PceCgsVRVFRRUVRxdGkCtHFUUUeC/sHiniIBWVgi1obPfsRjo2DHwv3KQp+HfcUAwtceGNpax6XdpFzcxpddFJhdB4LFdUKC/eU95T3lPeUC36Yd4t+fgsGwLZgVh8L+6/3eft596/3r/d593n3rx4LoB0f+xQH95QL9xQSi/cU9xT3FAv3SR2oCwH3MB0L9xRHHQvS9wn3X9b3JBv3D9tjWPAfC/wZ+8/7efuv+zbz+yX3Ni0L0VHFRQuEChz6wDIKC3MKHAXAeh0LUEDBH5d6lHmWegiAkpOFCxp2CgtDCh4L97T3tPu0BwsB2Pp6A/rHC/eU+BT3lAsH9yUdC6Ski7NypAt6hXt/fx4LB/ckHQt5HpgKCwapHQtmTfsWQPsKG2ptkZhxHwua+xWZd40eg52BnX+bCAsHPQoe+ZRkHQuLlRv3MVwdC3wKDvuL+10LBXSj9z0dC4UIhYWDh4Ib+xQGen0LBbYdCzoKHvdUWh0L+xT3Lh0LVR33FAv6lFUdC/vU4AoL/Dv37fvt+DsLdM4KagtExFLSHguUCh4Lk5SOkZEL+137iwv3QPdoC/cU9xT3FPcU9xQUcAulopujlR+VooaneJ0Li/eU+RT3lPclCgt+l5yFmxubnJGYlx8LVgr5FBUL95T6lPeUCxorCguLVgoLdwoVC5AKBgsH9wodywscBsD3JQoD+ZELBpybfXmMHwsFc6Ksfa0bCwWdnZWkpBoLFfU14SEL9xQBiwtqaRppC/mU9xQLnBucmwt1CqKiHwv6lPl0FS4KCwbOyE9HH/cUjBULBzsKVQoLBq6okpSUbpJoHwv7/6B23h0LHouLi/coCgwiC/sl+/J0+6Uafo0L+25x+yL7FPt1Ggs9CpyEm3+XHwv3DPct9wP3nPcMC/ciCg73FAauC3p8fHoLaRtpagsBAAEAAAsBACAAAH0AAIMAAIoAAJkAAKUBAKoAAYf/AodpAXYCAAEANQA5AMMA8wGRAZMBlQGXAZkBmwGtAa8B9gIrAkIC4wLzAyEDdQOyA/0EHARmBLEE9QVVBZYFvAZEBokHwQhZCOUI+gkrCdYKQgqGCtYLNwt1C+wMow0GDUUNzg5nDnQOtQ+fEF0RXRFgEaQSkBKjExQTjBSWFgcW7xevGGcYkBixGN0Y7xkZGVEZhhnUGiwaphrmGvobeBxAHQMdrR3+HhQeKx5YHogesh67HuAe9B8JH0Qfhx/YIBIgNSDTISghpyH0Ipsi9yM5I6kkCyR4JNklEiV9JYwlpCYFJsMncifRKIMpnConKuIrlyxALGgsuCz7LSot3C5cLngu3S8ULzQvlTAyMHoxCDHAM10zhzSiNfc2EDZlNqo3LjeiN+E4IzjJOeI6Szt0PBk8RzxzPPg9oT3jPis+Xj7JP35ADUCSQSNCJkMNRCNFN0ZmRr9HJkd7R8dMc0zvTS5Nak3OTm9OcU5zTnVPKFB/UNFRLVMIU7ZUj1UXVR9VOVWFVpVXvVkrWZJaJVqbW1pcHV0MXh1esF69Xspe8V8SX1VfZl9yX39gE2CaYRpiCmKZYw9jf2P2ZGJlGWWPZotm72c/Z5BoPmjqaTdpgmnXajxqemsoa8ZsbGzcbXpt4m4LbjBuZW58bpBupG7Fbv5vDW8cb2Fvz3AOcHJwgHCZcLNxX3FpcdtypXLyc6Jz8nQldHd0yXTldYV2hXcyeDl4WHjEeTZ5vHoNenp7JHw9fHd8vX0ifYN91n6+fxF/pn/7gEmBA4GZggWCPIJwgqeC2oM9g42Ea4SehOyFCoUlhaGF4oaJhqGG24c7h5uHzohPiKmJJIlYia2KAopWizWLwoyIjSSNwo5ij3+QeZCGkKaQ7ZEzkWWRppHJke2Sq5NylceYK5jSmYKaL5q4m0ycI5xXnIidqJ6/nziftqAAoFCgn6Duobuh+aL3p1+okKlgqkOqi6sZq2aroKynrTatea49rzqw4bGRsZOxlbGX/f+L9wQcBR/3BAH3BPcE+FT3BAP3dPcEFRwFIPhUHPrg/FQH+wT7BBX5NFYK/TQc+gAGDhz61Q4gUh33ChwFlAMcBcr4ehX7nvcu9573LsiuoNpoyBlL9wJoyDygTmgZ+577LQX3x/cUCvvHB/ue9y1Orjx2aE4ZS/sCaE6gPMhoGfee+y77nvsuTmh2PK5OGcv7Aq5O2nbIrhn3nvctBfvHB6od9xSLCvfHB/ee+y3IaNqgrsgZy/cCrsh22k6uGQ77/6B28wr8NPg0BkAK+1SECvw0/DT3LQr7VDIK+DT8NAZMCh73VDYK+DT4NAc7HQ79f4v31Pkw97gB+BT31AP5VPesFaF5nXUe+4QGdXl5dR/7hAd1nXmhHveEBqGdnaEf99D53BX3efuE9z/7avtg+yw0+0f7AB6AeY91nH73OPsRGIaTk4iUG5aXkZWTH8bVo6OjnAiaobSZuBvc1FlTS2tqPmgfM2P7DCP7DRpeB3WZaaEe94QGopyloR+LB6iw0MatHurA9xXU91IaDqAOoA6gDqAOoA77//iU+BTzChz7QCMKmR02Cg6gDqD3SQoB+ZT3lAMcBqMcBUYVvE2UZh4c+oAGZk2CWm6ibp93H/kM/QwF/ZT3NgovCh/6FPc/CvvU+ZQG+Qz5DAWfn6KoqBoOoHYBnwr3Ox0DVgocBSAVwGC2VoGCioiCHv3U+5QFY35vZmEa/lvBHflZB/mU94EF/K3BHQ4gi/eU+hSMCvoU95QDfh35VCsdpAofDqB0HfeU9xT5lNsdkAqrix0c+kBxHfmUB6BzonWkd/cj+wL3JPsE9x/7CAhM1ug+8xuMBowG8+jYytYf9x/3CPck9wT3I/cCpJ+ioaCjCP2UB/qvBDY5+wNKWB77GiL7GiH7GSEIYFYrL0UbigaKBkUr57ZWH/sZ9fsa9fsa9Agx0lLu9wYahh33OQqxhV9yH/cUsBWFChz6QHsd/tT3Bx0OoEodjwoD+hT7FBXjHXkdDuYKkAr6DRWpa5dzjx78itT7dfhbBZ6CeqF0G0gK+FX7gAWEl5mGmRuol6Ol2B3mChwEcfioFdP8OfwN91v8Dvtb1Pg5+8b3vfg6yfdR+BL3UfwS+DpNBfdxxxWpa5dzjx78itT7dfhbBZ6CeqF0G0gK+FX7gAWEl5mGmRuol6Km2B37/0odch0Dch33FxX3dlb37/u5Hmz7F/sf+1j7WPsX9x9s9z4K9wAq9zMf+f4G9zP3AOz3Nh/71PoRaQoO9yn7lO4KAYv3FPeU9xT3MQr3lPcUA/gUS0kK+pT9lLAK/pR+HbEdch0c+4CxHfwU+ZSwCvgU/BRJCvcU9zT3Bwoc+sBzChwGQJwdIKB29xEK+ZT4lBVXHX4dBFcd+hT8FBVXHX4dBFcdDqCgdq4K+JT3tDod+VQEJAr5FPvUOh39FJkdFcBgtlYe+9QGVmBgVh/7VAdWtmDAHvfUBsC2tsAf+RT71GwK/RSZHWwK+VQEJAoOoKB2rgr4lPe0Oh35VAQkCncK9yEd/lQGVmBgVh/7VMkKHPsAmR06HXcK9yEd/lQGVmBgVh/7VMkK+VQEQAr+VAZWYGBWH/tUyQoOoJkcBKQB9w0cBg4DHAaH+l4VpIGkeZ0e+xz3HKkK/ST9Jfu697upCvsc+xzRHff++/73HPsc0gr3HPcc+Wj5aPc3HQ77/452AfcCHASkAxwFEvdqFaSBpHmdHvu697r3uve69zcdpIGkeZ0e+xz3HKkK+7r7uvu697qpCvsc+xzRHfe6+7r7uvu60R33HPsc0gr3uve697r7utIK9xz3HPc3HQ4gi/eUzx2MCs8d95QU/Pc+Hft093QGLgpLBl8K+3T7dAdfCktEHfd0+3QGagoey04K93T3dAcsCvcUqysddx0fDiCL95TPHYwK+hT3lBTg9z4d/NQGXwpLRB341E4K9xSrKx13HR8O+xT3lAGL95T4FPcNHRRw9y0d94f7BPd0+1f3Jh5TtjqAYVJgU5c6w2EI9xYp1vsp+zYa+677evt6+677rvt693r3rvc21vcp9xbtHsO1l9xgw2HEO5ZSYAj7V/sm+wT7dPuHGvciHfg79+337fg7Hv0U+ZQV9wUdRVFRRR79FAdFxVHRpAoeDqD7FPeUAYv3lPcCHQP3lOsVnX2ZeR77VAZ5fX15H/tUwgr31IEd+9TCCvjUgR381MIK+lSBHf5UwgocBcCBHRz6QIAKDkoK+pT5FGod+JT3ARWcf5t6jh77S6eBrH2seqsZrbqwt625CJCSjpKUGpOJk4aRHmHGRclWvAiRhIKPghuCgoiFhR/7IiBumm2XbJUZb/dMBZyJe5h5G/tyBnl9f3uHH3tPhUqETmyBbH5ufPse9hiRg4KPghtp+xv7JmpzH4aEh4SCGoKPg5GEHrBer16tW3ttfm2Ba/tObxh8iH95fBr7cgd6l3uciB73S3CVaZlqnGsZaVxmX2ldCIaEiISCGoONg5CEHrVR0U3AWwiEkpSHlBuUlI6Rkh/3IfaofKl/qoEZp/tMBXqNm36dG/dyBp2Zl5uPH5vHkcySyKqVqpiomvce+wAYhpOUh5Qbrfcb9yerox+Rko6SlBqUh5SFkh5muGe3abybqJeplqv3TacYm46XnZoaDvv/dB36lPcU9xT3FAGaHQP4lPm0FV0K95T41BVdCveU+NQVXQr3FPsoFVtwb4Ye/dQGhnCnux/6SPoU/kgH/TT6yBW89wmOj5ORkYwZ99EGkIqUhY6Hu/sJGPh0a0Id+8kGRfc7Bbx3T7NWG/vUBlZPY1p3H0X7OwX7yQZRHev+TAb7AtMx4x751Abj0+n3Ah/6SOtrCh8OIKB2AX4d95QDch34tBWNi42KjR780/hu/NP8bgWJiomJGvx0KAr4FPgU95T8FPgUJx33c/i5FZaYiaB+lvtv90oY+CxcCvtXB/uI92BhrkeLYWgZ/WP8636AiXaWfhnJQZCFk4eTihmUipOOkpD5SPjVGPlI/NUFhpGSiZOMjIuMG5OMk4+QkcnVGA78f3Qd+ZT3FPgU90UKnx0D9xQWUB37FPd0+DT3FPi093QBi/d0+LT3FPg093QD+hT6dPcaCvv0+3QHUR331DEd+DTrFSMd9ymgdvfU91SfHQG9HAccA/rr+LAVe4x8f3wb+4gGfHyXm4wfjwej99T3NQr3Tvc1HaP71AWHB/mL/GcVs4CzfK8e/DX6qAWkgXChcBv75/c1HZr7VAV5jH59eRv7OgZ5fpmdjB+a91T3NQr75wZwcHVygR/8Nf6oBXxngGNjGm6TX7Ee+VQGen2ZnYwfn/eU9zUK96T3NR2f+5QFeYx9fXob+VQGsZO3qB8OIIv3FPcU95QBdwr3FPcU9xQDdwr3VIcd/GQG+xz7HAVnZlt3WBtYW5+vZh/7G/ccBfxlgQocBcA2CvvZ+g0VooF0m3Eb+5T4VAYzHfuUKh38VPuUB/crCvhU/FQY9ywd+FT4VJ6dkKeBoxkOYQr4NPeU+DT3dBQ4+vT49KId9/RcCvv0oAp+f4N/hh+Gf45+lIH31PvUGIWSk4iTG5OTjpGSH/fT99MF3wr79PjUOAphCvg095T4NPd0FDj68vkoFZCXiJiClfvU99QYkYSDjoMbg4OIhYQf+9P70wWFhIeDghp5mX2dHov3VPv0gAr39PdUB5iXk5eQH/vy+KA4CqB2+tT3VN4K+pP41BUs+1QF+9QGLPdUBfvQBo2QjJGNkPdo+IQY+VgG92j8hI2GjIWNhhn3WW0Vr4DAfa0e+4L4vAWsfWOlaBv91AZoY3FqfR/7gvy8BX1pgFZnGvx29AphCvrU93QDHASg+RQVon+gd5Ye/LT31HiXcot3gBl3f392dBr9FAfSHZaOkZUf+LT31AWflpegohr3FBYjHeUKi/eUE7BWCvcxHbUK+xb7FRj3Gfsh+1Pa+1kb/Dv77fvt/Dv3Ih33efds8PdE9yYflZiLnn+W+x33HhiRhIKOghuCioKHhoQI+xMp+ydD+zMb+677evd69673rvd693r3rvcX9xBZNOkfE9D7Hvse0Ar4VEEd5Qr3MB0TsBwF5/h0FZx9mvcSHXyBgn2GH3pjf2VzZAj7LC77OS/7Rhv7FfsRveMtH/cd9x11HTMd/FQqHfxUBxPQgh33FfcVBfsb9yL3UT73Vxv4Bfe494v39uAfjI2Ljo0apPm0FZIK+xb7FQX3Gvsi+1PZ+1gb/AX7u/uK+/c1H4mLiIkaepl8nR73WwaalZSZkB+cs5exo7II9yzo9znn90Yb9xX3EVoz6h/7HvsefQr4VEEdoIv3FPcU9xT3FPcU9xT3Hx33FHcK9xQD+BT39CEK99QEIR331AQhHX4d/FQVeQr31AR5CvfUBHkK9xT9FIsdHPpAcR351IUdHAXA9xAK/dQH9xT61BWFChz6QHsd/tT3Bx0O/P+gdpkd91QB9xT3VPiU91QD99T5lBX3VAfBCh6gCvfUK+AKa/dUBveK+173XvuK+4r7Xvte+4oe+1Rrkh0OoFId9xT3FAP31PcxHdJSxERuHV2kYrJ0Hhz7DkQdy04KHATyB7KipLS5GhwFwEtJHV/7Pfsc+zEbbG6QmW8fzPsf+w+/+zEb+yL7LVNL+xIfcX5ufXN7CHh9f3pzGv16By8Kl5WOkZYe1fce9zvT9zP3buP7IPdMG/cX9xHCyPcFH6iaopmwGg4goHaZHfdUAYv3VPfU9xSfHffU91QDkAr5HhX4L/wR9+/8V/xX/BH77/wv+wGfIbMoHp9a901qBfsBqO469wsbay0KyzEd+NSdHUtHCmsHKzhWPV8fR5cFeMmBy84a98L3v/ec9+n36fe/+5z7wkiBS3hNHkd/BdlfOMArG6sHXQqrB/cL7tz3Aagf902sn7wFs+6f9fcBGg7+f6uZHQGL+ZQDRgoO/P+rmR0B+pT3FANGCvgU+LQV707tLbAej4OCjIMbaG5vZx8/9wig+w37DfsIoD8aZ6hvrpOUjI+THumxyOzvGg4gHAVHdwH6lPcpHUYK+BT4tBXvTu0tsB6Pg4KMgxtobm9nHz/3CKD7DfsN+wigPxpnqG+uk5SMj5Me6bHI7O8a95QW91/7DvdR+1Da9zIKb5t4on8fpn2kf6N5CO5DxfsH+w4a+w5R+wcoQx5zeXJ/cH0IdH97eG8aTwqvk5SNjpMe91Da9w73UfdfGveUFvfH+0v3qvuu9w33MgpumnujfR+Zg5uGmoOnfKd6pXgI9zj7Dez7U/tgGvtgKvtT+zj7DR5xeG96b3x8g3uGfYMIc318e24aLwqUlI2Okx73rvcN90v3qvfHGg77/4v3FfcT9xSeCov3FPcU9xT3FPcU9xT3FBKOChPf+PgU+BQV+xR0HQb6FAT7FHQdBvc7HRX7FHQdBv6U/hMV+BP4FPwTB/wU+ZMV+BT4FPwUB/gUFvgU+BT8FAf9FPuUFf0U/RT5FAafChX7FHQdBveU9xQV+xT7FAYTIBj3FAb5FAT7FPsUBhOQMHQd/BT9FAYTIDj3FPgUBhPf+PcU+xT4FAb9lH4dFf0U/RT5FAb5lPkUFf0U/RT5FAYOoKB2oXYSi8qqq8qq9xKq6snqqquqq6rpyunKysrKyqrK6umqq6rKE3//wMoW+GuL+Gn4aBp2dot2G/xpi/xq/GkaoJ+LoRvKjBVbCoCBi4BPHZeUi5Yb6VgdlpWLlRv3MVgdl5T3Fx13igqhn4ufG/cSWB2WlYuVG8pYHZaVi5UbylgdE6AAAJaVi5Ub9zFXChNZwICinougG/cxVwqin4ufG/cSVwqhn4ugG/cSVwqhn4ugG+lXCqKei6Ab91FcHWtsi2xPHROAAMCrqouqG8pcHYCBi4BPHRNGPwCXlIuWG+mKFfhpi/hq+GkadnaLdhv8aYv8afxqGqKfi58bDksKDvcpSwr4FBbNHf1f+V4Fvlgqs0Qb+3QG0uxjWL4f+V/9XgWic5n3Oh19anR0Hvxq/GoFaK2lc78brayZoqMf+H/4gLIdIHQd9zEK9xT3lAGL9wQcBbzfAxwGZ/q2FXyfdpl0lIx5i3eFePvA/m8YZ4BgdmYb/i8GVEaXxXcfg6GMlJOXCJeUm46YG/n5BvcTpa33Lrof96b6Hpm6hbpxrxmucmGgXBv9jQZ6eoaHeh+MjvsTr4P7HWFNGXt0c3eHeIh5lXqJeoVWYyxzanx3dYGEdIV7lXSJdoZcaDJwXYF5eH2GeAiGepV1hniAV2k6bVl7cHZ6h3OJf5R+inuKc4d3iXd9ZYtfm14II7D3ATrxG/ovBuHjzeCkH/en+h6ZuYS6cq8Z/ryJoQo4+5ShCg78fyIcBekBi3cKAxwEjBwFgFQdIPsU9xT5FOAdAfeU9xT3MQr3FPcUA/gUFveU+hT7lAf+FPkUFfkU+RT7NDIK9zT8FAb3lEuZChb0NOIiHkv3lAbAbdRlsR77LPcsBbFlQqlWG/00hAr8tEsHIjQ0Ih/8NEQd93T7NMkd9zT3dAcsCg73KZ4KAYscB4AD+lT59BX7M/sV+xX7M/sz9xX7Ffcz9zP3FfcV9zM1HR/5VPg0Fft0Blj3HAXNcj3BRRv8lAZFPVVJch9Y+xwF+3QGgwof/hQH7woech33QAr6FAd2Ch79VBz7gBX3GR33Xa0d912tHftd9zwKHw4g+Cj3D/cRCvlp+mUVo1uqRbAusS+qO6JGbokYaor7AI77TI0I/Kr9IxXAw4+VxR+7kwV+90z3CIS8G42Vi5STGpaLnoqnHlqScJCDjFiSaZV5mgiAk4Wanxqak6aatR6/9yWu5pyx+FaJGOf7eLr7BgWPgI2AgRqBh4KDgx6FhnSCZIL7F28YiHKKcXAaxY33XJYFjKe4jMkbw8qJhdEfhtHLiMUbjJeLk5Eal4meh6UeZplplGuPa450k32Xg5B/nnysbcd2vX2ycNR1wnuvcchq2WbrZ+tf7V/y+2H4dBiAoAVWBnNyi3Eb+6z9aPuB/Px4Z3t1foEZfoJmgE+AZYRwhXyGiTwYDvv/+xTpQeb5Ne34uuE28RL3c/fSE2wTrPi/mhWEnIaalxqI96KM90EF9yQHkp6sjrwb9wLdgXXCH8J2umGyTAinXphPQBpCf09xWx5yWmJmU3AIcFNEfTIbYFyWoFkfE2x9+X4Viq2LpZwajO2M9wyI54fOGYmsi6WdGpTBto+sG/cG4HJZwx/EWadNQBohbUBQYB5fTzN2+wgbYWeNkGwf/LH+DRX3KZDljqyO9weS7pHfifdZhxjjiM2Rt5Phm8+fvKO8o7qvt7usr6OymbUInsOVwb4a4mzaTtEeE7RO0jK7+wmm2a++pKCbCBOstquqrqCxCKCxlra6GraEtH2xHn2xda5uqm6paaVkn2Ofa5dzkgidRkyUUBtBBml3jIOCgYIMIl6K/BB++5iFjzjIg7GHmooZrYmihpeDkIeQiI2GkX2PZ4xQkftujfsajFeN/IUYNohKhV8eiHuEeoB5a35igVmDcIh1hniHiS0YDv1/hnYBi/qUA/sSBJqMrI69kNiSxZCyivdaiRjhgryFlYkIiZiVipAbj5mLjaMfjJCTi5Ubj56OmI2UjpqOn4yiZpF1joSMZ49jkmCViZeKlI2Rl7gYtvd/sfcyyPfLmtKh8aj3GRmNoI+nkqyTspOok5+mlq2Vs5WzlLCWq5aRoI+cjpiNlo2XjZp9imiJVIcIhShEiF8bgXOLjWQf+9GZeCSUiZiKm4oZz4e7gqd8CHmMf4qDHoNZdfsbe0xu+zGKhnA9bfsxGX9LU/ugcPsfg2B9aXhzGXF+ZX5XfmiCcYV7hno2GA6g+w/3j/qU94/7L/cW+xD3DRL4kfeQ+FPS95X3FBMqpQoTGqvrk9inngiZn+jXHY9yiPscjPsJkPxAGI37Wof7JIcwsQqOrx+UZR334AeK9ywFEy6KnpHjjqgIj6WijJ0b9wv3D2wd+7kG+2uMBRMa7R0cBkkc+xwVO/qU2wa3maeucB8TyvsS9zZwrl+LcGgZ+xL7NgVocJlvtxvb/pQ7Bl99b2imH/cS+zamaLeLpq4Z9xL3NgUTGq6mfadfGw6L9xT69PcW+xD3DRKQ94/4FPeO+Br3j0jSE9qlChO6q+uT2KeeCJmf93HXHQiPcon7HPsJGpBfBftaifskhzAesQqPrx+TZR1XB4r3LAUT2oqekeOOqAiPpd6MnRv3C/dTbB370gb8UowFE7ztHRwFWhz7DRX7NvcSBWimb31fGjv+lNsHt2+ZaHAe+zb7Emhwi1+ucBn3NvsSBa5wp5m3Gtv6lDsHX6d9rqYe9zb3Eq6mi7dophkOQx38FNMKHPsAJgp3Cicd95TTChz6ACYKVgonHfwU0woc+4AmCn4dQR1DHfwU0wr+FCYK+hQnHfeU+JQVUgr8FNMK/RQmCvkUQR1DHfiUBDMdHPsAJgp3Cicd+JQEMx0c+gAmClYKJx34lAQzHRz7gCYKfh1BHUMd+JQEMB34lAQwHfiUBDAdDlEK95QD95T3dBXACvjUBMAK+NQEaR0c+gAcBUAVaR341AS6HfjUBLodDlEKjwoD+BT6dBWcfJp6g4KIhYUe+7T7tAWFhYiCgxqDjoKRhR73tPu0BYWRlIiTGywKch37VD8dUQqPCgP39PlUFZOIowr7tPe0BZGFgo6DG18K/NRTHfcmHR73tPe0BZGRjpSTGhwFoPx0Px2goHauCo8KHASgFaV7onSVHo6Dgo2DG3p7hX5/H/wn/CYF9zkHLR39VAb7M/sV+xX7Mx/9VCYd+VQG9zP3FfcV9zMf9zoH+Cf8JwV/Cg73KfcOCvdU+lRVHZAK9xQD+RT6VKsK+pT8FBX8NPg0/JT8lPs09zT71PvUBftUch0H634dFZyafHofHPtAB8Yd9zRrFYUKixz5wAeUHR8c+0BzChwGQJwd+xRVHQP3/xYg9xT7FPYG5ub3f/t/BfhE+dkVhYmFhoYe/LL8sgWGhoWJhRt+gpSYkY2RkJAf+LL4sgWQkJGNkRuYlIJ+H1X3VBX91P3UBfw0+DQH+dT51AX3n/fU9wsK+3/3fgWjc9Udc3Qf+zr7Ofg0/DT3Ovc6sh39f34djAr3JwoD+ZT6FGod95QW96/7efd5+6+2Ck6STKVUHvgB/ZoFX5+5cLsbu7mmt6Af+AD5mgWlwpLKyBoOYQoD+ZTrFUsdH/7UB/mU+LQVIAr9f4v3lPt/dhKL9xIK+pQTUBOQ+JT4FBWXHVLE0h4ToKSTo5efHpifwM+gzgiWjpWQkxuTlYaAjh+gSMBHmHcIl3eTc3IaE1CfChXwbelY2x5Y2/tq96M696IItn9ioGsba2N2YH4fOvui+2r7o1g7CBNgWTtsLSYaE1D0HQ6gi/cU9xTr+jRVHfiU6/i09xQD+gz39BVT6yvDBvcI9wj3LPssBffY+PAVlIKKfIKC+/L78hiCgnyKgpSClIyalJT38vfyGJSUmoyUggjb/OYVmIOWf5Aef5B+iYGBS0sYhYWIg4Ma+xJuCvnUBpqaiYeaH5aHl46UlLy8GJOTjpWJlomVhJSCjwicZmOTYxv91D8KK/o0Ff00/TQF+7T3tAf5NPk0Bfcw9zAVsLCLyWaw+yz3LBhmsE2LZmYvLxj3tPu05+cFDiD3KQr3FPdn+cH3FANyHfi3FZiCln+QHn+QfYeCgnt8eX53ggiAhYSAfxr7am4K9wQGkZCNjZAfsaK4n72cCJqOlpibGp18mXr3Qx37kz8K94H5hxX3Dx38FPgUGJd/e5J6G4OCiYiDH3SBe3RxGvtU+zQH/SA3+8j7oPtc9zP7dZKBH4ORlYaVG4+PjIyPH5iRlJmJmWz3eqP3KtzoCOTZ9yC193Ab9zSYCnGbdKKBHoiTlImTG5ybkZiXH/gU+BQFDiD3IApKdxL3IAoT2BO4ch348hWYg5Z/kB6Nh4eMhxuDg4iEhB9LSwWFhYiDgxr7kgczQ0P3JAoT2KgK+dQGmpqJh5ofio6Oio4bk5S4Cry8k5OOlYmWGYmVhJSCjwicZmOTYxv91D8K93v5uxWrq4u9a6v7AvcCGGurWYtra/0b/RsY+5v3m2urWYtraxn7AvsCa2uLWatrGfhC/EKra72Lq6sZ+cL5wgUOoPcnCgH5lPeUuwr8FPgU9xQH90Ydph38FPwU9xQGjR34FPwU+xQHJB2eHR/3EgpiCpybkpeXH/eU95R1HTMd+xT4FPgU+xQGgh33lPeUdR0O/X/yCov3lAP6ZxwFcxVtHRwFwOgKDqDyCov3lAMcBtP3BQr5WugKbR35WsAdIPIK9w4cBgYDHAZT9wUK+VroCv1a/VpycotjpHIZ+Vr9WgWkcp+Urhr5WsAd+//7HBwGEAGLHAV/AxwFaPj1Faqci6dsnBz60Pl2GGyccnxoGhz6QAdopHyqnB4OSgpWChwFQEkd/JQqHRz6gCgK+JQnHf4UHAWASR38lCodHPqAKAr4lEEdSgpWChwFQKYKIPIKixwGBvcBCv1a5wr5Wvla9w8dGf1a+VoFcqR3gmga/Vq/CqDyClYK95T3AQr9WucKbQr9Wr8K/X/yCvmU95QDuPsHFW0KHPpA5woO+333OwocBgIDmfjBFXJylHeuG/c5Cq6Un6RyH/1a+Vr3DQoZ+YEc+w0VKgr3lAczHRz6gCod+5QoCg78/0AcBhYBwPpqA/l6ZhW8Wd2Lvb3W1hi8vIvdWr38evh5GPh6+Hq8vIvdWr0ZQNZZvDmLWloZ/SD9H1pZizm8WhkO/P9AHAYWAfcJ+moD+t/5VBWtfax0oh79IPkfBaN01R1zdB8/QAV09yMdonMe+Hr8efx6/HoFdPcjHaJzHtdABXSi9z0d+SD5HwWio5msrRoO+xT31PoU99QBi/fU+hT31AOZHdMd+5T7lAY+CvcSCgepHfeU95QGRQr7lPeUB6AdH/sUB/fUyxUgCkod99T6FPfUA5kd0x39lAZobqiuH/cU9xYd+xQH99TLFSAKSgocBH34MhV6hHp/fx4xMQV/f3qEeht6e5KXfx/7SfdJ+0n7SQV/f3uEeht6epKXfx8x5QV/l4ScnBqckpuXlx73SfdJ+0n3SQV/l4SbnBqckpyXlx7l5QWXl5yS9zwdhH+XH/dJ+0n3SfdJBZeXm5KcG5ychH+XH+UxBZd/knp6GnqEe39/HvtJ+0n3SftJBZd/knt6GvgX93YVIAr7FFYKEoubChOgHAUE+bb3Nwr8s/yzBX9/eoR6G3t6kpd/H/v+9/4Ff5eFm5wanJGcl5ce5uXRCvd2+3b4LPgr0QrmMQWXf5F6ehr3kPs2fgoT0Modngr3lMv5VPeU3gr6FPc0Fagd91QH9x0d+1QH95T5NBX7LCNRP2AeXHBuWnQaiweoHa8H7Oze0qseyKempb8at1C0S2dqf396Hnh9d3lcTwiDhYGHghuEhI2Phh/7GO9+lYedlJkZ9yPh9w7R9zcb90D3VPsd+0sf+BT7VBUgCp4K93T31Pd09xT3dPc03gr6lPc09y4K/FSvHfc0Wgrr99Qrrx33NFoK99RaHfyU6wdfHfs0B/sU+hQVqB33NAf3HR37NAf5FPw0FSAK9ycKAfkU95QDHASt+JQVYPsk+wb7BvskYAj3AZoK+wEH+yS2+wb3BmD3JAj3AScdtwoe+wEGtvck9wb3Bvcktgj7AZsd9wEH9yRg9wb7Brb7JAj7ASYK9wEG9+f3HQr7IwZa92v7Pfc9+2u8CPcjmgr7Iwf7a1r7Pfs9WvtrCPsjJgr3Iwa8+2v3Pfs992taCPsjmx33Iwf3a7z3Pfc9vPdrCPcjQR1hCvrU93QD+t34XRXcCvsd9x0Y9x33HdwKGfsm9ybyHRn7Hfsd+x33HfIdGfsm+ybOHRn3Hfsd+x37Hc4dGfcm+ybxChn3Hfcd9x37HfEKGfcm9yYF92v3SxUjHWEK+tT3dAMcBJP5ZxX3Dx0l8Rj3DQr7p/unGPsn9yf3DQoZJSVycotjpHIZ97r7uqRys4ukpBn4Ovg6BfchOBUjHfsU93T62fd0AYutCgMcBSD5FxX7wvuI+4n7wPsBJazDNR75hvmFBcI2qyb7ARr+e/u/FVPhavH3Axr3wfeI94n3wPcD8mpR4R74aPxbFfg9++z37fw8/Dz77Pvt/D38Pvfs++34PPg89+z37fg+Hg4cBUt3AcscBcAD9y0dz17HQx79VAb3ufe5BaOjmaytGq19rHOjHkDVBaNza90Kc3Mf/R/9HgV0c84KaqJ0Hvkf/SD3Gh3W1wWjopmsrRqtfaxzoh77ufe6BflUBtO4x88fDhwFS3cBixwFwAMcBcD41BWtfqxzoh79H/kfBaNzaplpG2lrfXNzH0BABXP3Ix2jdB73ufu6Bf1UBkNeT0cf+xQHR7hP0x75VAb7ufu5BawKcx7WQAV0o6t9rRutrJmiox/5H/kfBaOjmKytGg4gHAVAd9sK+Mn3Cwr9H/kfBaNzapj3Sx1+c3Qf/R/9HwVzc84Ka6NzHtZABXOidQqjoh/3uve5Bf1UB0PHXs8e9xQGz8e40x/5VAf3uvu5BXOidQqjox/W1gWio5mrrRoOIEAcBcvbCvlU9wsKQNYFonPVHXR0H/u6+7oF+VT3FAr9VAf7uve6vAr9IAV0onUKoqMf+R/5ILIdoPsUHAZAAYv3agOPCvoUFZ0K/JT4lH0d+5T7dAf73PwsUfvt+x8fYSGA+wf7BBr7INH7S8T7FB6WdJZrmnYIgZKShJkbn5ebnpuHnYqbH4i0ibS0Gvhx96/e+EMe93T7lAaCHfiU+JR1HQ5KCvmH+HRbHfmh+fRdHQ77BxwF5gGYHAXmA/mU+NRdHfmH+vRbHQ6eCveU6/k095TeCmAK9xQc+yEVeX18eh6YCnl8mp0f91IHnZqanR73VAacmXx5H4n3LhV9inyAeRv7TQZ4fJaZH3r5AQWSjpKSjx6QkZSOlBv3cAaUlIiGkR+Sh46EhBoOi/cU9zsd91T3FAH3jPcU6/cc99T3HOv3FAP6NPdIFWhuemgemApobpyuH8MH+GgH91T31KAK/GgHUwf8XPngFVZgtsBGHa2jeX6WH/cS+zUF+IHrFVZgYFYe+1YG9xH3NQWYlqOdrRvAtmBWH/gM+5RCHfxMBvcQ7+/3EPcQJ+/7EEhNb1pkH/sU+zn7FPc5BbxkTadIG/sQJyf7EPsQ7yf3EB/8TEcK+9QtCuv8NAZMCh761DYK+DTrawofDqCgdvoU99+uCncK+dQVJB37ivsvSvs3+0keW15fW1pfCH9+fYR5G2huqK6dkpmXmB/3k/d793j3KPf2G6AdH/iU91oV4Gb3ufsFN3BcWFQe+x/7GPxI2vthRwj7sC37kft3+9IaaI5okWkej3elVoJR+1o6Ixp2koWUeh5dpp5syuLH92C9G7PrTHu7H2zm7nvrG/cs9yuzz/cbH/eq9x73XPdey/fLCJjLkszLGg77//dJCvcpdt4dch37NBUuChz6wAZfCktEHRwFQE4K+5T69BX35vuA90P7qPcTHoyKiIwFqk6uLkX7k/xUafwTGvvm94D7Q/eo+xMeioyPigVryGjo0feT+FSt+BMaDqCL9xT6BPckAfhU9yQDkAr41BX7nPs/+6j7TPvVG/vV+6j3TPec+z8f6vcn9xb3Evcw2whjR3Y9PBr7i/dd+12tHfdd94vadtljzx73MDv3FvsS6vsnCP1k+BQVcXV1cfsGLS37Btkd+eT8FBWkg6J/oB73wvtM++X3Yfv3G/v3++X7YfvC+0wff3aDdHIacpN0l3Ye+8L3TPfl+2H39xv39/fl92D3w/dMH5egk6KkGg6goHb6hPckAfhU9yQD+L/3XRX7RNr7J/cbI/c16vcn9xb3Evcw2whjR3Y9PBr7I9D7G/cINx73y/j+FXF1dXH7Bi0u+wfZHff/91MVloWVgZEel3YtxXkbf4GFgYUfVSoFllBOkU8b/AX7yftf+8T7Wh9+d4RycxpyknOYdx73B/tI9zf7KvdWMwiBemlVexp/kYGVhR5/oOpRnRuWlpGVkR+85Pdn+A33ZfgP92f4DRmMjYuQjRqw/FMVp4inhqce+6z8igX3Qc33B/c6904a+FT7FBWlhKB+oR499xX7EfcR+xDeTPsEGPcFPeom1fsH+zD7hvuL+0X7t3JB+xgY98H3ovcd93X3WB+yuLK8qr4ImKGSoKUaDqCeCveU9xSuCvqU9zUVeX181AqanR/3UgedmZqdHvcACnx5H/tSB4n4ChV+inyBeRv7TQZ4fJWYH3r4XQWRjpWSkB6QkZSRlBv3cAaUlIWGkR+Sho6DhRpr+G8VtHVgpVwbXGBxYnUf/ZQc+oB1ZIxbomQZZKK1c7gbVgoGuLWjsqIforKMu3WyCA77//c7ChwFegMcBWAcBWAVS8v7NEsrK/s0+zQY/S33M4GOf4eDhBn7FPsUhISIgIyCGY2BkYKUhviQ+6sY+5f7l/tWwAWMiYiLiBuDgoiFhR8rKoWEh4KMghmMgo+Ck4b3kPtRGPdR+5CRg5OHlYoZjIuLjBv3Jh0f6+uTlI6WiJYZVvdW95f3l/er/JCPgpOGlIkZio6Ni40bkpKNj5Af9xTrlZOQmIiXGfs0+Uz3Nfc16+vL9zRLyxkOIPdJCve0y/fUy/e09xcKq8ur9xT3NMv3NPcUq8ur9xT3FPcUA/cU+xQV9wsdyxb3Cgr9NPf0FffU97T71AfLFvfU99T71Af9NPgUFfcLHfhU/XQV9woK/VT5dBX3Cgr4VP10FfcLHf009/QV99T31PvUB/00+fSLHUtxHfe0hR3L9xAK+7QH+XT99BX31Pe0+9QH/TT4FBX3CgrLFvcLHfuU+HSLHUtxHfe0hR3LBpyafHphHaD3FPeU+RT3lK4K+S76sxX3Iib7F977Rhv7dEEK93QG9yvL+w37DcUfs+m06MPhCPr6/bMVih37lAf7K0v3DfcNUR9jLWIuVDUI+5j3TfdLrve9G/tUB3qafKsd+hQEih37lAf72fsW+6D7lvsDH3NSclFuUwj7AFNMMPsZG/t0QQr3dAb32fcW96D3lvcDH6PEpMWowwj3AMPK5vcZG/eUmAp5mn2rHQ6goHauCo8K+RQV9/b8Jfey/IP8g/wl+7P79fdGCh7jCpBzoHuhjaoKSgpWCvlUFcMd+0v7aYJgYPtplPdLHvcUB8Md/Cz31/u8+FH4UffX97z4LB7+lPmUSR38FCod/BQoCvgUJx36lPgUSR38FCod/BQoCvgUQR0g9wn6atsK99QVrX2sc6Me/R75HwWic9UddHQf/R/9HwWsCnQe1kAFc6J1CqOiH/h6+Hn4evx5BXOidQqjox/W1rIdIMD6atsK+dT3CwpA1gWic9UddHQf/Hr8evx6+Hq8Cv0fBXOidQqjox/5H/kfsh33KfcrHfoU95QDdwqrFZKIk4eRHvs091QFkoWBj4Ib/NT4FPdUBj0KmoaagZYf+9T4FAWZf3mTeBt4eYN9fx/71PwUBYGAhnx89y8d91T8NAb7NAdyhmSwHvpUTgr5FPg0SR37VPg0Bvc0B6SQsmYe/lQG90odhI6Dj4Yf9zT7VAWDkZWHlBv41PwU+1QuHXyQfJWAH/fU/BQFfZedgp4bnp2UmZcf99T4FAWVlpCamhoOIJ4Ki/cU9zEKEouQChz7APeU+RT3lBNw+RQW0lLERJcdxFLSdx0e+hQW0lLERERSUkT3JB0TrHcdH/cU+tRJHRz7Twa7gYrbRxv7lPUK92AG90X9ywV9blw+bPcvHfqU9z8K/iwGlZ+ZoKIaooKkh6Ee+qj3DgUTaKyPo6erGg4goHb3EQqQCvo08B39NG8d+w/wJvcPHpkd90gd9yn3OwocB1cDHAdX+NwVuFiWZx7+1AYz+wpVR1Ef++T8IAV7eXxzcxpevoCvHvrUBuP3CsHPxR/35PggBZudmqOjGvvr9+zwHfy0bx2DjIKDGpCR9+X4IAXr3Pcv0vcRG/nUBg7+f/uUjwr3JQoD+VSZHRWdCqYd/pT7FC4dnh0f9xIKYgqcm5KXlx/3lPeUdR0zHfsU+pT3FEEdoPcnCgGLHAcAuwr+lPcUB40d+pT7FAeCHfeU95R1HQ73KXQddwr3FAGL9xTuCvcUA/iU+JQV+5T8FPeUBvgU+hQV+5T+FPeUBvgU+RQV+5T9FPeUBvgU+pQV+5T+lPeUBvcUKxXGHZyafHofHPtAB/cUmR33Bwoc+0BzChwGQJwd+xT31AGL97QDdwr6MhVvYGdmYm4IjIKLgoIa+6r7aPvU/Bb7C/sCrsYuHombnIqcG+7lrcPTHy+NPshw3giJmJiJmBuemY6QnR8rnj7g8RqMi4yLHqt8rIGuighSsWnL1BqxlrCdqh7z+xT3Lzj3Q4IIh5qKnJsa9wjp6fcIx8JyYrEeu5S4nbSje1pqYV9xtpGzlrGcCPeU91YgHfsU9wP56vdZ92/3LwEcBTH3YwMcBRv4/hX7Q/0P+5r5D/sX92/3F/cXBvdH1fX3Zh73Q/tv+wIGOoVsUh/7AfdaB/di968gHaD3DgrJ+Lbp9xTN9xTL9xTLAYv3FPiU6/o09xQD+jT5VBU2HVZgYFY2HXl9mZ2UCp2ZfXke93T7Fkwd/pT80hX3FFYK+xQH/BT40hWwHf6U+RYV9xT4FPsUB/yU+1QV9xT5GAfL9xQF+dD7Hgb7Cgf3FPeUFdJSxEQeHPoABm4dHxz7APcRHVYKBncdHw6g+BT3VPkU91QBi/dU+RT3VAP51PqUFbgdbm+Sl3Eel3GSb24auB0hNeH19eHh9ainhH+lHn+lhKeoGvXh4fX14TUhHvnn/VQVqPur95tmsB6RhYKPgxt0Ly90cek6oHYfKyv79/f3Bdn0wPcU9xga9277K/cq+2373Pvc+9z73Ptt9yr7K/du9xj3FMDZ9B75M/0zBXmdpIGkG8PLy8OkgaR5nR/7cPdw6+sFdqDcLaUboufnoh8O9yl0HYd2uXb3lOAd95T3FBJ+HfeUEz76FPkUah35lPyUFUVSUURFUcTSpArRxVFFHvqUBEVSUURFUcTSpAoeE5LRxVFFH/wU/DkVmYGYfY4e+yyigqd/pn6mGaeyqa+osgiPkY6Rkhqn+wr3AHGjHpCFhI6DG4SEiYaFH/sKMnOXcpZxkxl09y0FmYl9ln0b+04GfX+BfYcfflqGVIZZcIJygXJ++wflGI+FhI6DG277BPsNcHcfhoWJhIQahI6Ej4Ueq2WpZqdjfnKAcoNx+y9zGH6JgXx+GvtNB32VfpmJHvcsc5Rvl3CZcBluZG1mbmUIh4WIhYQabvcKIKVzHoaRkoiTG5KTjZCQH/cK5KN/pIClgxmi+y0FfY2ZgJkb904GmZeVmY8fmLyQwpC+ppOklaSY9wcxGIeRkoiTG6j3BPcOpp8fkJCNkpIak4iRh5Eea7FtsG+zmKSWpJOl9y+jGJiNlZqYGvkU+/AV9xUdPh33LAoTPp1h74KfHvcTChwEjAT3FR0TQj4dE4L3LAqdYe+Cnx4TTvcTCg6goHauCnId+ZQV96/7z/d5/Bn3BB0eeB0f+BT7lBVOHfc26fP3JPc3Gg50HYv3DAqL9xT4FPYd98f3Efdk9xT3SfcULvcUM/cUE1eQE1eg95T3VBVVChOXwGhuqK6uqKiuoB0ffh341BVmbzFcih6gc5lcaxoTb5DvHY55jXh4GvsOPF77BR77DQb7CvsGrrH7Ah+eVS+vUxtr+RSrBhNXkNr3C/c/xbgfpKqjqqeo7PFq9y3LzAj3HaJA+wkf+worNvsJGvf09z8dE2+Q9x77CvcJ+x4e+0QGqcmdx9EazofFbMge7FonsCMbaWt9dHMfJymr+zJPS2ViaGBpXwgTl8BtZEcxZHEI+6YGbh0f/RT3ER33tAYTV6Cn3G2BqB9d9xj3GGH3IhsTV5DoBq8G1h2kt5i9vRqiiKOFoR6ru5zExRoO90kKnx2L9wwKi/Yd98b3Efdl9xT3DfcUR/cULvcUM/cUE0/AE9eI95T61BVVChM3wGhuqK6uqKiuoB0ffh381BVHTk9IHvv0BvsJ6zb7Chr7CXRA+x0eS8ys9y0q8W+oc6pyqgjFXvsL9z88G2sGE0/A+RSrB8Pnr57BH7H3AvcGrvcKG/cUBhNPoPcD1Vn7CR8TT5B4iXiIeR61dKJSXRoT14hzhXN/dh6ta55jXBprfVx2cx4TT5C6iqcxZhr3FIoVE0+gxXrEa7sekaGOo6IaE0/AvX69crcejZmMmpkay3bLZL0ekAcTt8D3T4z7F/cA+0ob+wQG+y77EWVZ+yQfgW46bW8b+7QGE0/Abh0f/RT3ER33pgaycc8xqWStX65gsWPGSmz7Mu8pCHSjq32tG/PvsOy8H6rHj8fNGtF5x23JHvdEBhPXiPce9wr3CfceHw79/zgcBjMBi/nUA/nUHAXgFYsHSAoFiwcOoHcK2x2QCvpAFftL+037PoiIHvzY/MP82fjEBYmN+033PvdLGvet91LG9zT3Kfc8+zVNvx6jbr2Lo6gIyb/3PPc19ykb9zT3UlD7rR/3FBZ5HeMdDiCL90MKA/kU6xWwZIZyHvu0BjND0+Mf+VT3Dh25Crh+z6ecfJp6H/vUBvsz+xX7FfszH/1UJh25Crh+z6cf+jT4tGgdDvsU9475Sun3hPeWAYv3gfd79xP3e/eG93v3gQP3gfcOFflK93v9Sgea+iAVSVlVOh6Ligc9WcHNz7+/2tq8V0eMH/jd/iAV+AcH6WrKOEtlYGJ6HoV8inZ3GvwY+3uLB475CYjMixr3eyaJBrupwtD3EBv3LPcGKPtpH/wiB/eB+nogHfz/fh33lAH3lPc0A/h0+TQVNh15fZmdHvhUawqdmX15HvxUB/k0+/QV9zj7EPcw+xge+JQHpAr3BR0f/RQGRVFRRUXFUdEf/JQH+xj7EPsw+zgvCh/4KAbX/HkFe46YgJsbi4yLi5uYmJuNHr74dwX4QUEdoO4dch349PcaCvvUbgr5VKcd/VQ/CvgUHASgSR38lC4dnh0f90T7RP0g/SAvHfcG+wY3Hfkg+SD3RPtE9xgdi/cU+pT3FAFyHfcUAxwEoPkUaB339Pf09gr71AZemEdvZrKQpB/3tAbj00MzH/1UB5QdHvvUBl6YR29qCh/31MQKIJ4K+hRVHfjU95T41PcUFDj4XvkhFftZtPsZ9xztGuv3lAf7Mav7DrUvHvrK96cVKfsZ+xz7WWIeteer9w73MRr3lCsG9xT3FOAK+7TrBoUK/NR7HSv7tPctCvsUB/tS93r7ZvfMfB6zWLBtnX0IwFuZWUsaS2tLKysrSysejQr51DEdywfrK8srK2vLy8uZvcC7Hp2ZsKmzvgj3zJr3evdm91IaDvsU92jGoXyid6GOqumZEov3X/cUpPdMsfk896oTj8D4HvdMFY+PiZSFkYSSgoyHhoaHjYKShZKElIqPkAgTQIBhyBWHkoOOhoeGiIuDkISQhJOIj44IiweQj4uThpIITscVjY+IkIWOhY2GiomIiYeOhpGIkIiRjY2OCKppFY+OipKGkYaQhI2Hh4eIjISQhZCGkomPjwj3FfsEFY2RhZKCjoONgoiJhYmFkYSUiQgTJYCTiJSOjZEIyoYVkoOQgooegoSGhYSShpWMHxMQgJSSkJEfxZUVipGDj4KKgomFhYyEjIWTh5SNlI2RkYqRCPpY+lD2CiId93QGq62Lux+diuRECqdzo11DJIv7A3IaW6yLqx73dMQKIPcOCveUAXcK9xT3FPcUA3cKy4cd/D8GQXBEVTgb+5QGOETB1XAf/D+BChwFwDYK+9n6XBWVooaneJ38VPhUGJh/epF7G3t6hX5/H/xU/FTQCveU/FQGKwr3lCcd+FT3lAelopujlR8O+xT3FfsV9x77AfcXHASw9xT7FPceMfcUEov3FPsR9xQh9xQcBLn3FDj3FBOSIBMyIBwFf/laFfuo+1r7xPubLh5uOPsEhDL7BvsDqvsGWVx1WhsTUSBte6KnH7ehtbkaE5Cg3HLa3Br3hdH3rPde9y0exrfWq8+mCK3h5a7oGxOGIPcL9wVb9wuyspSyG4+Qi4qPHxOSQJR7jHd4XoFeXRpVlnCeWx6bY5T7D1wa9xSNFcuA9xl0xR4TkiB/q4KZr7iVubga82Lc+wYeZGWBZfsJ+wW7+wsbE4pA+wMkZmIlHxOSIDxsNmZHVwj7gPtHNPvO+7AaE4YgOaQ8Ol11YVwaE1EgLNYy7h69u6i79wX3BG73Bhvz9w+Uru4f99D3BPd79/P34RoO90Idch33vBWSi5KIkh6EoFqhd5VSq1GqU6wIm3FrqWxOMvtJVRtwaKSZcx/7SvD7EvcSJvdKCH2jcq6mwfdJ5Mgaqm2re6UeasNsxWvEgZ91vHaSCI6EhIuEG2dFe3xqH1p2a1NyXghrUHhPSBousTeqNh6hTqZQrVT0+z73Yfth9z4iwmnGcMh1CGzg32XoG87HnqvGH7ikw6ugvAiarJvRrxoO+//uHfr09zEd49NDMx/91G4K+dQG97T7NPYKi/c4CvsV+xX7Mx/91CYd+dTECvx/dwpVHfqU9xQDfh33MR0c+yYH/Dv4KjLgMjb8O/wqBRwE2vqUB5f3FFQdXgp3CvfrFXF/WIFzHklt+xJbRhtITqaiTR/7b9v7gveCO/dvCHTJcMjOGtC79xLNqR6Vo76XpRuQkYuJkB+dhdX7JptvCJZ4oXR0X/sXSmQad51ylXke1fsY5jD3GEEIgZ2keZ+yzPcXtxuionWAnh+ne/cmQZF5CI2Gi4WGGveU+Z0gHSCgdgG3HAYoAxwGVPr8FVFyTHlKhM6zvsqj1k1mRXBCfQjKUDeyLhv7R/sk+yX7RnKOcpBzH/ugmfuD9xT7M/dYCG9be1RPGvsExCjiUR5WjVmaYKMIiouJihr7MfcD+xb3KG0ehHBuh24bdneNjncftPsU9wsu9yKICDT7A/sfWPsrG3ByjI5xHy/3I/c+VvdLG/jm99n4gPg/mYuZipkfyrnCxLfLCA7+f/lM97D3lPewAfc+9+kD+JP6aBX3IgfVkrP1Hvci97D7dwb7pSv7Hvt7H/s/+z77sPc+/cz36fnM93cHqfewBQ4xHAXaHPon90ESi/eq+mj3qhOwE3DWCvvn93D7tPfFJR6yhJmjn52KyEQKE7Cnc6NdQySLOHIad5hzspIe98Xx93D3tPfnGg4goHaZHfdUAfmU91T4lPdUA5AK+lQV9wIKHvtU/TSSHfjUB0AKK/dUBsEKHvuUKArLQR33KfcOCvdDCvcU95R3CvcUAxwG4PdLChz5wHsdHPtAcwocBkB6HZkdB4UKHPnA+xQVHAZA9xAK+3Qc+YD3dPcJChz7ABUc+cBxHfj0kAr89Ad8HRz6IPcUFfeU9xT7lAb4FPsUFZ8d/BQGDvdCHfgU91SrCviU+w8VevdpLvdd+yz3K/sr9yz7Xej7aZwIiYqLiRt7e4WAgB99f4R6eRr7GwdqpHCsiB73xW73hvuGqPvFCGqOpnKsG/cbBp2ckpmXH5eYkZyKnQj4lIkVeffy+yf33fuN94z7jPeN+933J/vynQiKiouKG3t7hX9/H35/hHt5GvsjB2qlb62JHvjZafhj/GOs/NkIaY2nca0b9yMGnZuSmJcfmJiRnIqcCA6L9xT3BPc09wT3FPiUVR35hPc06/c09wT3FAP6pPfUFbQK95QWtAr3BPs0ix0c+0BxHffUhR2ZHfcQCvvUBxz7Mvh0Ffcx+HYFnJCemJ0b+aIGnZ5+epAf9zH8dgX3Rvs0FaaDooOkHvtZ+PIF0XRIvEEb/aIGQUhaRXQf+1n88gWDcoN0cBr71HMKmR2cHaD6G/cNAVYK9xQDkAr6FBX4FAfpHfs0+1T71Pt0/BQb/HR7HftUcwr3DgZF+3Xh+0bF+0bnNveWjcn3DiHeMdzR9wc927T3H/cLs/fvbvez+1/3RvsoCKQKH/gUB3cd0lLERB/7FPzwFfuZ91z7kfcF+5KnCPeiB/eSp/eR9wf3mfdcCA4g+5Tb90T3FPsE9wR+HfeUEp8dy9vb91T3dPcUE82+Cv0t97QV93T3i/T30vffGvdZ9yXG90P3Q/clUPtZ+9/0+9L3dPuLHvdLFvuZ93H7D/fn9+Qa93X7IvcU+26lHpCWjpiYGkAKE61WYGBWfo5+kIAf90UdE8375PsP++f7mftxHqod+FQGE99IHfhU9wQKSgocBWD5FBX3Hvcbnp2SpoWkGYSkd59ykftQuxjA906SpISmeJ0ZeZ5wknKE+05WGFv3UIWkd59ykRlxknGEeXj7G/sfGPsb9x95nnCScoQZcoV3d4VyW/tQGPtOwHKScIR5eBl4eYRwknLA+04Y+1BbcoV3d4RyGYVyknCeefce+xsY+x77G3h5hHCRchmScp93pIX3UFsYVvtOhHKScJ55GZ14poSkkvdOwBi7+1CRcp53pYQZpIWmkp2e9xv3Hhj3G/seBX2YnoOeG5GSjIyRH6SSn5+RpLv3UBj3TlakhKaSnZ4Znp2SpoSkVvdOGPdQu6SRn5+SpBmRpISmeJ0IDsUK9xT3Lwqg9xQu9xP3vfcUE2+w95T3VBUTr9A4HRN3sHId+NQVRlBQRh773wagc5lcaxrvHRNvsI55jXh4GvsMPlz7BB77Vvs/9xT7Qxtr+RSrBvXS5dTLH7S5sbmswJigl6GXoQiilr73CKcbE3ew4NZrKx/7FCtKTBr41Pc/Hfce+wr3CfseHvwKBpq0kra3Gvc9+xXi+zMeE6/Q+xpg+z8uUR9tXGliZ2IIam5HNVsb+7QGbh0fE2+w/RT3ER33tAbK7mZ1yB9l8/Vs9wQb1h2gsJizjrUI9z0G9yD3CPcJ9yAfDsUK9733Ey73FEf3FWP3Lwr3FPcUE244HAVg9xQVE65Y+0P7PvsU+1sb+wNCvPcKHxNuuJ6Mno6dHmGidMS5GqORo5egHhNvOGmreLO6GquZuqCjHvvfBkZQxtDPyMfOH/jUBhN2OMorzPcUGuvWq+CmvfsFdJcel3SXdJl1rFaxXbRdCELL0jH1G6v9FAb3lMuZCvjUFdJSxEQeE284+7QGW0fhrG4fZ7RptG26COhRYPc/+xob+zP7FTT7PV+SYJpiH/wKBvse+wr7Cfse+yD3CPsJ9yAf9z0GjmGYY6BmCBNuuIl9inx9GkugS7NZHhOuWIqGBftTivcaI/dMG/cC9Kuw8R8TbjihyO6wyhv3tAZ3HR8O90kK9xT3Lwqg9xQu9xP3vcwdE+dgdwpLmQr5kBUT51D7VvsU+z/7Qxpr/RSrB/Ux0kLLHl20XbFWrHaYdZd1lwh0lvsIvqca4KvW6x4T5uD3FMwryhv41AfOx8jPHhPvYNDGUEYf+98HE/dgoKO6masburN4aasfl6CjkaMbE+dQucR0YaIfjp2ejZ4b9w25P/sFH/cUkBX3TfsD9xX7UYkesllLoEsbfXyKiX0fE/dQZqBjmGGOCPc9B/cg+wn3CPsg+x77CfsK+x4e/AoHmmJgkl8b+z00+xX7M/sa9z9g6FEfum20abRnCBPvYKxu4UdbGvu0BxPm4PckHfkUBncdH/e0B8qw7qHIHrHzqvX3BBoO90kK9733Ey73FEf3FWP3Lwr3FMwdE4+wch341BX7A1pC+woeE5eoeHiMjnkfYXRSdF0bc3ORl3YfaWtjeFwbal+an3Ef+98HE6+wRlBQRkdPyM4e+NQHTEor+xQbK2vW4Kb3Bb2ilx+il6KXoZnArLmxubQI1Mvl0vUaqwcTz7D5FGsGE49w+0P3FPs++1sa+xT5lBUkHWhuqK49Ch4Tl6igHR8Tj7D3lP2QFfcCa/Rm8R51yGbuyhr3tAfSUsREHhOXqP0UBm4dH/u0B1s1R2puHmJnYmlcbQguUfs/YPsaGvsz4/sV9zy1upGbsh78Cgf7HvcJ+wr3Hvcg9wn3CPcgHhOPcPc9B7KPuZmtnggTz7CJmZqKmRvLy6CzvR+QigUTr7D3U4rz9xr3TBoO+xSbChKL94/6mfeUE0h3CtMd/IoG91H7UQUTuJd/kXt6GhNI9xAdMDD3HB37/vf+MOanCubm9/73/scdBZd/knt6GnqEe39/HvtR+1EF+IoGE7j1HcsVIAr7FJsKEov3lPqZ948TWBwFBfkU9zcKMDD7/vv+BRO4f397hXobE1h6e5GXfx8w5gV/l4SbnBqckpuXlx73UfdRBfyK9xMd+IoG+1H3UacK5ubQHff++/7mMAWXf5F7ehr3jxYTuCAKngr6mfePEoubChOQHAUE+RX3NwowMAV/f3uEeht6e5KXfx/7UfdRBfyKBz4K+IoH+1H7UfcGCqcK9/73/ubmxx33/vv+BZd/kXt6GveQin4KE+jKHfsU94/6mfeUEoubChNQHAUE+RP3Nwr7/vv+MDD3Bgr7/vf+pwrm5tEK91H7UQX4igdFCvyKB/dR91HHHQWXf5F7ehr3kIx+ChPoyh37FPce94jC9yX3E4mU9x2a9xKanZ6cmrn3Ufs09wEumYul9pyMoa33JhKL97v3Raza3YKhuqellLufk792n/cIlBPdJ62AYAoT3yetgPem/J0VlpKdlJmHloiUh36CCBPtJ62AhYeCj4SJlImYh4eCpXxpeXqNCJOKcnyMGoKGf4uEgoOAlnh8j4V+dJKBfZZ/dXqAmoGHkICBhY+FjIWEh42Ml4GOigiGiYeHhhuQfoB9goOBg3SDiIl5en9yq4QIjItqiowfjX+QaHaYgZCFp4iWiJeKi4OXfnyJloCSCBPdJ62AgJF7iYWRfICAjoich4OTf4qIhoGCjYORfpVvenySCIyPh4mOH4h/hJKFhwgT7SetgISGhYGFhphyfXOMcAh3mGiegB6UhqmJlI+ZkYmWkJeQmJGRmoy2jWpohnmIfop8iX8IiZCQjJAbj46QjhqRgZ+IkZeSf5mCjX0IfY2YfHgbfZtvho0flnedg5+VCIOIdYCJHoGJeKCPloqHiIiIiYGXepGCl4mOcLSRjX2Fb5V+knaWiKhxh3mIhoR2kwh9kH+VfZJ7lG+UhZ+Fm42egpoIlYV5n34bl3SpjogfgJhjrpOfjY51k4eMj4GMgJCCkIGRgpGBlnmadYl1foePnoeThJh4i4aZCI2MjIuNjIyccpmPl32Wi6CBmYKYfJF+lIaOZ7mYjneGgbqOlwiLiYuMGo+XhMmbjICKiKaOkI2PmnyMiZGOkZOJkoiTgJKEkYiNY6WKio+SipKFkAh4fJWogY6HjIeOh4/F59zY68AIjJGTi5MbnYmVfJiCjZCHk4iQjpOXjZKNlIyYjZOHhZSEk4STioqIiYqJgJR2f4GHCIOHhIaDiIaJiIuHjAgT3SfdgKmbqpmslpGHkYSUhIWQi3SNhwiWfKOVmoq4hYIMJJKBi3yUgpSUfpWRlI2PnZCRjpKQf5KIjYGRZI6eopKTpIeThggT3Su+gJaFl4B8gZKKrIKGfgiRjpCUkxuUio12j4aZcqO9j4l5kq2UlIiSiJZzfowIE92HroCWgYx1d4x9jHuefnwIE91HrYCCgYd8goJ9fXiMeo2SinV0iYeFhIeDiYOJgY2AhoGckJRshIqgjpyLn4QIE92HroCZhqCFkXyPkZ6IkYmXhYx+joCPfJhynJOOjaGVg5EIE90XroCDkoKdk5WTlp6OkJkIk6JriJwalZiOipcelXyfl5IelZG7gZSFlIWng42CCImKi4kbE98nrYCThJJ8fYeUjaWBeYWRjpCJkY+Sj4+SlIaNipahkYqUio1+j4WPgpaIj4IIknqIe6KFkomelop8CI+PjY6MGox9kXucjQiLi3iJiB6FgnyNgoaIinN2joh+mnaLeod5iHqJeoSDh4OHhYSIh4Z5hoqVjZCWk5EIE90nrYD7N/4BFYqQipWMGoqbnJaKmoCOiJaNl42cmpeXlpeWjqKImYaji6SHo4yFnI2Og4+SjZSQkgiPkZKNkZCVkaCil32Vf3J+mICPk4eXk5ObnZZ3m4achpGFmICHj5+SjYwIno+TgJiBmYGhhIl3lYmRiJOIk4eWjZGFLyr7Dkf7HXMIDiD7fxwGawGgHAZpA/gUy0Ad+Rj4OBX7F78i9Ff3F/09/T0YrAp0HvX7APcaHfk++T4F+Q74RxWff5p3d/t8+yZ4ah77VfYF93QH97n3PQWUkZKWlhqXhZSBkh60TiyhQhuDHfuL9137XfeL91H3P/cP90bKH5arl7SsGg6gjgoBkAr3FAP6lPcUFfcU+RT7FAf+lPiUFfcU+pT7FAf8FPiUFfcU+BT7FAf3FP3UFXEK+ZQEcQr5lARxCg77//sUch3eHRwFexwE2RWigXSbcRsc+wAG9ysK+IH8gRj8egeeHR73EgoFfwr5egf4gfiBnp2Qp4GjGQ6goHafCvc7HQGfCvcU95T3FPcUFBz5FPcxHfcU+JT7FAf5FP0UFf00+zQGVQr71JwK9zT9NPx09wcd/ZT4dBX7lJ4KBvmU+PQVhQr79Pc0BkAK/NSECvs0+/QHlB0f/BSPCgcOSgocBQP6dxX3JPskYgqTlI2Okx+ilZuipRr4VAczHfxUBnF0e3OBH4F0kG+eefck+yQY+/f79/v39/f3JPcknp2Qp4GiGaOBdJtxG/xUKh38VAdxm3SjgR6IkpSJkxucm5KXlx/3JPck9/f79/v3+/f7JPckygr3Kh37JPckGPf39/f39/v3+yT7JNAK+FQnHfhUB7UK+yT7JBj79/f3BQ6gDqAOoA73KfuUjwoBixwHgAP45fkUFVfWbuXmGqGNoY6hHnxgX4Nd+xsj4HYb+xOO+6Q6+wPpW+8f9xoGztvpuPOOCPrD/REV93ZW9+/7uR5p+xD7H/tc+1z7EPcfafc+CvYq9zQf+f4G9zT27Pc2H/6UHAT9TB35VPwUaQr41Pt1FdyO96T7Ex52Izb7GxtdX5OaYB+OdY11dRowbjFXQB7ziOlezjsI9xoG7+m79wMf+xT49UwdDiD7BPdV+1UcBmD+NPdV+zX3VPiU91QSm/dU+1QcBmD+NPdT+zL3UxNCABOCABwFsPfUFfdHCgV6eXKCchtycpSdeR/7YvdjBXmdgaSkGqmXoqCfHmqsp2S+GzsdExEAvmSnaqweoJ+ilqgbpKSBeZ0f92T7ZAWdeZVzcRr9U/lVFW1/dHZ3Hqxqb7JYG1ZgYFZYsm+sah92d3SBbhtycpSdeR8TQgD7ZPdk4h2klaQbpKSBeZ0f92L7YwWdeZVychr6E/1VFdhu01TCHvtk92QFwVVBqT8bPEFrU1QfM+MFw8Kr1toa127UVcEe+2L3YwUTLIDCVUKpPhsTHIA/Qm5VVR/7J/smBVVWbEE/Gj6oQ8JUHvdk+2QFVcHVbdcb2tWrw8If4zMFU1RrQDwaE6EAP6hCwVUe92L7YwVUwdRt2BsTLIDX1KjBwR/3J/cmBcHAqtXXGg73Kfc7ChwHgAMcB4D4FBX3SvsT9yz7PrMepbOaur73CR1LUXRkXx73Tz77S/cX+2obtgp9jHyMfR/7LEQh+y/7Rxr7i/dd+133ix761AZ2HR8OIHcK9xQB9yYK9xT3FAMcBffjFfyL+a0F+CPLB9wd/JT1Csv8Iwb8i/2tBfsLQMAq9yEbfh0G9yHA7PcLQB/9n/lpFZ+qBbAH+CP3FPwjB2YHn2z3pPxBBf1cBg6g+xT3NIB29/T3NIv3FIv3NPfU9zQSjPcz+FT3M4zLy/cUE29A+lT5FBUkHS8K3B33wEsV+I/4Ip2YlKGJoBmIoX6eeJX7FMsYkIKBjYEbgICIhoIf/Ub8F/sCzYeNh42HjBmUqo+siKyC8kbu+wLQCME2KaktGzE/cFdTH1JXbj+SPZQl0Cj3AUUIVeDubekbw76Wn7cfkYKShJSF9w5CGBODAPsOQoKFhISFghmfX1iWUxstKG1VNh/7AUVGKIIlhD2oP8RWCFjD13DlGxNPAOntqcHgH/cC0dDtlPKOrIesgqqPjI+Nj433As0Y+Ub8FwWGlJaIlhuVlY2QlB/3FMuelZiejqEZjaCCoXmYCBz7XPkmFXNxYn9dGxOjAE5Fn7JOH/sAz2XwyMMIo6W0l7kbx9J3ZMgf9wBHsSZOUwg2/X0VZE5Ed08bExDAXWKXo3EfTsOx8PcAzwiyyNGfyBu5tH9zpR/IU2Um+wBHCPdG+PkVlJSNjY2Mjo4Zk5KRk5OTpaUY2lx9gwV3f352dBqAB/cU+zoV+zQrcaWDk4WTg5MZiI2JjImOgpMY9zTrBfcFB/mU+EP3FEv9dPzUBfj0/BQV/Nr325CNkIyOjxn3Rfce+Jz8LAUOoPuUYh33FIv3FPeU9xQSi/cUnx2L9xT3lPcUi/cUnx0T7rAcBqB+HRX8NAZkWXp0ZB/33AcT91BACvw0BlZBbGZmH/ws/CwFZmZsQVYa/TQyChPusPi0+7TJHZkdB0AK/LT7aRUT7tD7v/u/B/vp+T8V+7/7vwf4g/vwFWZmbEFWGvuU/JT5FPg0Bzsd+DT4FPw0BxPusPkU/vQV/hT5FPg0BhP3MDsd+DT4FAcO+//7EPcT+hb3FfeO9xABj/cU94r3FPmX9xMDHAV89ysV42bgTMke/Nn42QWzZFWiUxv7AjU1+wJUolSzZB/4LvwuBYWRk4eTG6DExKCTh5OFkR/8LvguBXybgaChGrKop7GhoYJ8mx742fzZBbFlpFdUGjZMTDZVVqSxZR79nPmdBVu7b8zPGvch9wL3B/ciz8xtXLse+PL88wWFkZOHlBugw8Ogk4eThZEf/PH48gXTQim0JRv7aPs7+z37aCa1KdJDH/md/ZwFTcngZeMb9zD3C/cL9zAfDnQdnx33lMwK9xTgHfcU9xT3FPcUA/gUFvgU+ZT8FAf3FBb4NAdACv3UhAr8NPsUdwr3FPw0Mgr41DYK+DQHn7J7fZkf9637rQWYfpxieBr+FAf8lPo0ix37VHEd99SFHfdU9xAK+9QH+RRrFcBt1GWxHvus96wFsWVCqVYb/jT3Bh0cBUA2Cg5KClYK+vQgHYuTHfcBHRTgVgr3VBVSCvkUBFIK+RQEUgoOoIuTHct3rgqfHasK+JQEXh1yHfw0FS4KHPtAKB2ZHQY3Ch8c+oD69KsKch38NBUuChz7QCgdmR0GNwof+VRwHRz7QCgdmR0GNwofDqD7lPcB9yf3lCnt9xTuqPeUnvcB9xTuEqv1nvcLaPcW+wn3EyT0E0qA+BE3FdBfv0ibHur3BwXj++H7LPUHE8EgwAcToSCrrI2rG4oHYGRqWGddpVMYtI7LiFMaY2Z6aGVin6RwHlIzBRPBIF64y3bKG/PhyfcCH435BxUiBhMCIE/7EweO2fdtrPcoGu47wi4/R2RGah7gUAWnnKiprhusoHlpHzf7dm/7TRp5jnmOeR73/gYcBYH7NLMdHPqA+tcVEwKA+wAGExAQ+CghB/sc+xPSP56cn5qWoRmNfwY6ijo6GiAGExRAKPfjB3Id+7SzHflUcB0TEBAc+0D3DwqgCnqZfJ0emR0GEwiALAoOoPsU9fiq9xT5JPcErgocBuD5FBUc+UAGUR0cBsCnHRz7A8sV+XsGcJ1rnGecR6lSoVuZ+yK0LrZfuAhfuHW5vBrFoby4sh6yuMif1xvb0m1Oxh+tZ65HrSaZiRjfhZeOBY6bjZqZGraGyILaHoS/hLOEpUGjUJtfkwiXQVSSZRv7QfsXYTYyHzI2XiX7DhpPm0yrSh6abpxwnnMI+I/7lBXQb7lzoXgIwVqmV1MaXXtgbGMebWNiblh6CHlZXIJhG1xekppjH2KZaJ5uo26jcKpzsoCder5m4CWJGF8Hd4dojVkejyuJV4MafgeAj4SPhx6Vg6KCsoD3IGMYdtXNicIb3s6SmcAfwJi9or2pvKqvpqOirKyirZqwCKfQmNLTGqyJqoanHg6L94j7CPcI+r3pMeg14xL3aPe4+Xb3BDn2E40TVbscBSEV3Ym8fZt0CJZ7kUT7Ehr74QckkDyWVB6aO6dKs1mzWcdi2mwIbNrqfPcCG+zglqHUH9Shx6m8sLuxsbSlt5ypmbSVvpW+lfGG9ysIE459+A6DnYsaiqSJn5ganpGYlJQekJCmkLqSqIynkKaSCI2XjZWUGpSJnIekHnmNTIRKhUeOGfthlQU3Bok1mYjvjaiMpX+hdBmZfJJtjmCPUBgTpZr7dpiG+0caI4Q/fVoegWh6ZHFjf3d1dmx0bHNqe2iACHhQS4JHG1FQmqtPH2Kha6p0smzBe86H3H33rBiK93kFmoqeoxrZj7eUlR6cmKWTsxu2tI6Rsx+UB4nLjJkFinxuimEbYIpaiVWJCBOViVRTilIbe1ONkC0fjmRljGgbfX6Lin4fjjMFE1WXiJqLnYoIHAXQHPp/9y4KHPpABhONcx3LWgocBcBaHQ4gi2Id95QBi/cU+BT3FNQdA/iU9zRNCvgUBGQK/JT5lBV5fX15HvvUBnl9mZ0f91QHnZmZnR731AadmX15H/tUB/iU/BRjCvyU+ZRjCvgUBCUd9xT31BWFChz6wHsd/tRzChwFQJwdICYcBmUBphwGZQMcBKb6TxUg9ve597n2IAX3LhachZt/lx77WvdaBZd/e5F6G3p7hX9/Hxz6+hz6+gV/f4V7ehp6kXuXfx73WvtaBX+Xm4X3PB2Rl5cfHAUGHAUGBZeXkZucGhz6ufdSwh33kPsYFU/3WE/7WPtYT/dYT8f7WMf3WPdYxwX5cvw2wh39dvkywh0OoPcOCvcMChLmHZ8d95T3FBP39yYK7B38FPiUFakHj5Gajo4e91f3VwWOjpqRjxv3MgYT7/uUB/oU/JTsHfeU+tRJHf6UKh37VPs0B2dbd3JyHxP3+1r7WgVUVJU8RBr3NgpB2ZW9H8sGSB34FAZIHb3ZgdUfDvsU98v5Mfc79xf3lgGL9433Kfcp95D3vfdQ95AD1gr7z/dR+6L3o/sLHonBjMyZxQiLmsnf9/gecryL1Isa9wbN4N3RrVZMRV4idCoeOXjHSdsb9ybt90/3cfc9+wb3Evti+337JftC+1ZIn1yqZh+Zeo2FhneHfYNph36Gd3uEepIIILdZ9wr3GBr3bvdM95r4APe691X7aft3+8L7PPt1+4s4Pbi+cR5e+0WCaYsae1BqUG5dCHbR04DXG8od+xT32Pkp9zn3FowK9yj3KPeM97r3TveUAxwE4PdLCiId90sGhcKC9qHnCIuayd739B5zvIvTixr3BMzf3NCsV01GXyN0Kx46eMdJ2hv3JOz3Tfdv9zv7BPcQ+2D7evsk+z/7VEifXalmH5l7jYSGeId9g2mIfoZ4e4R6kgght1n3CPcWGvds90r3l/f997b3U/tm+3X7vvs6+3P7iDk+t75wHl/7Q4Jpixp2OVU6alwI+WkG9zP3FfcV9zMf+lQHLR0O+pT3VMv3OR331vg59y34FPeUA/k6UhX3IPsX2SXSHo16e4t7G/sY+0ts+xNHH/sNr/cFOPcSG/gQBpKijqOjGvu59/MVarZtvcMaqpallageiHRziXQb+wQ0rOBBH/xFB/cMyfcXnvcajwj3QfiTFfcsOveP+037GEv7CPsK+yzv+4L3Rvcduu73Dh76ZuYV+5T7lPsU95T3SQr3lPeU9xT7lPeU6wYtHf5UBvs++wr7G/s5H/cb9wD3LLD3Oxv4SQb7G0sF+xsGmG2Yj6B4CNBLrPsBMPuc+3N1+xj7Ffe/WPusGlR+VnFaHvhoxAog+5Tn+KLH93rH98z3FPdF2hKL900/9033dfdasvdNSvch95v3FBP9YPoA0hX7Q/s6T/sp+zT7bNX3VPdk94i/9zicm4uJnB7xRPcXPfsgGvsM+fIV+w5cKPsd+0Yn94L3LPcKy/cI9xf3Td37j/ssHvsX+G8VTEyEfk4f+0pj+yf7NvtSGvtd9zz7I/dWoqKNjqMeE/tggWx/dWoaU6pZrGAe+0eG+6pdMvtICHZhe11cGvt896I790/3KPcxq+73Bx4T/WDg1cLo9wf3rPvAvvcV9xj3dJ/3nRr3BFn3DSjJHhP9oPcbBvcb2gX47vuUFfuU95T7FAYT/WD7lPuU+xT3EgoHE/ug9xT3lPeUBg73KYv3FOv3NPi09xTr90UK0sT3FPeUnwoD+ZT4FBXr9xT3tIkHe3J8gHN2PtsY9yj3HQX3BvxU9xQrBvcU95QV90r7Avd++2b7ZvsC+377SvtK9wL7fvdm92b3Avd+90oe+JT7lBWDCh8c+4AGdgoe+JQHQwoffh0G7woe/JQH9xT51EkdHPkAKh0c+4AoCo8KQR39f/fU+NToHfnUUAoO/X/3lPjU6B331BVNHf7/9xT6lAHL+NQD+RT61BWSCvxU/FQFf3+Ee3oanh0e+FT8VPcYHf7/9xT6lAGL+NQD+NT5FBW0HSQdH/4UB4Id+FT4VHUdDiB0HX4d95QBi/cU+RT3DAoUOPc0FoYK+vT5FBz7gAf5lKuLHfz0fh35FP70BvcUmR0VhQoc+sB7HRz7QHMKHAVAnB39fxwFQHfoHfhUUAr4FARNHf1/S/jU6B34VFAKDv1/HAVAd+gd+dQVTR2g+xRyHa4Kjwr5zhVtamluZ3L7O/sF+zz7Bvs3+woITTcjP/sBG4oGigb7ASPXyTcf+zf3C/s89wX7OvcFZqRpqG2sCP2u9wcd+tQE40LTNB4c+kAGIFY3KTDw+wXSWx/3L/sA9zH7APcv+wEIXsz3Ai/cG4wGjAbc9wLnuMwf9y/3Afcx9wD3MPcACOPI3vD3BBoO+Tb3mPs79yQSnvfe+e733RNw9/H6IxX73v5z994GoBwFERUTsOyKRdX7BRv7BEFBKizSP/cDH42LBvcH09fqih8cBI79bRX3xPs29yL7bR4TcPtGPShHYB8TsI33JPvdBouPLof+Fh6L9934vQepjqiToR7Go8HI5hv3C7sw+xkf/Kb33QcO5Qp3CveUE7AT0PctHfg7++337fw7+1n7Uzz7GfshHvsW9xXKChOw9yod+x33Hhji6PcQvfcXG/eu93r7evuu+677evt6+677M/sn0/cTKR+GkoKPgowIgoKIhYQfE9D7HfsegICKeJV+GROw+0T3JvdsJvd5G/g79+337fg7Hw6g+38cBsMBsxwGwwMcBusWzR37//f/BaJzaplpG2Vse3BwH/uU95T3EvcSBZSUkJeYGpiGl4KUHm2poW+5G6WilZ2eH6+tu6/BGqSBpHmdHvws+CwFnXlylXIbVWdbZ2kfeXiBdHEaXad1qW0elIJ/kH4bfn+GgoIf+/D78AWCgoZ/fhp+kH+Ugh6pbXWnXRtxdIF5eB9naVtnVRpylXKdeR74LPwsBXmdpIGkG8Gvu6+tH52elaKlGrlvoW2pHoKUl4aYG5iXkJSUH/cS9xL3EgoFcHB7bGUaaZlqo3Qe9//8AAV0onUKoqMf9vcAsh2gdB0cBIDbHfgU+BQ1CvdU+FQ1CvhA/HUVzF6tOXY6cCUiTSSmJaZN9KbyodzQwtqR8PgSGJStrqCtggiLB62Cn2iDaQj4w/vxNQr9FPkUNQr4VPtUNQr31PxUFfiC/Cb4JvyC/IL8Jvwm/IL7QLz7O+f7JB55l5+AoRscBXoGoZ+WnZcf5/clvPc690AaDqCL9xT6lNsd+hR+HRX4NPf0+377qvuq+/T7fvw0YF+OkGAfUpFgZTlDL1ImYRmluaTCntKm6xg0vQX7Qe0n9yL3KRr3qvf09374NB76FPyUFff2/CX3svyDHosH/IP8Jfuy+/b3Rgof4wp1kJ17n4yNi40bqgqgoHb3lPcU+ZT3FAH3IAoD+VR+HRX3zPec+0T7ZPtk+5z7RPvMV1iQlFkfVpVfbHd9dn52fxmu3yrDBfsU1UH19wIa92T3nPdE98we9xQE9wQdH3gd96/7z/d5/Bkf+coc+28V9zbp8/ck9zcaTh0O/f/7lJAKAYv6EwP6CfpeFZSCf5F+G4eHioqHH/wgKfc/+GMFjpGNkZEaoneech6L+9wHdnl+eIYf+139zYh9j3yXgRmEk5eHlhuPj4uMjx/4KvD7Wf28hnaYdqGEGYqQkIqPG52blZqTH/iwHASFkpqInICXGQ6g+NT3FAH3VPcU+JTgHRRwjwr3tOAKK/dUBukd/JT3VOs2CvfUB0AK+9SBCuv7VPyUBkVRUUUf+1Qr9y0K+9QyCvfUNgr31AdACiv3VPiU+1QrgQr31DYK99QHQAor91T4lPtUK4EK99Q2Cg4gdB0cBSD3NAGfHfeU9xQD+hT5WBWSdnaPdRt1doeEdh/82AdITk5ISE7IzjsKJB37H/cJ+wn3H/cf9wn3CfcfHvmU+L0VjouNio0e+A4x/AX3avwIG/wK/AH7avwOLx+KiYuJiBpqCpSSj5GSHsHFwbHeG+rd9wgdmBuZ9xUK3MbqG+rc9wgdmRuY9xUK3cbqG97BZVXFH4WSkoeUGywK/ZT5axU7ClUKKQegjKGMoKChiqAMJA6g90kK9yl2nwr4FPeU9xT3OR33lPgU9xTUHQP5lPsUFX4d+BT8NDIK+DT9FAb9FBwFoIsd/VRxHcuFHflU9xAKSwf3lP00Ffe/B/e/+78F92n7FBXAbdRlsR78LPgsgJZ/lH6TGffcB0AK/tT3Bh34tPs0yR0O/X/6tMv3NPcUEov3FPcj9xP3ePcTOsv3NPcUE+YT+vl0+lQV9wP7F7wu90odagrA9nBGagqGHfc0FktxSGFaHnh1dXZ3dEQ2TyeB+wUI+3gGgfcFT+9E4HeidaB4oQhhvHHOyxr3XPdf9wz3SR4T5vdJ91/7DPtcH/cUFvek+5f3RPuR+5H7l/tE+6QkrTLQPx4T+tA/5iCTIAhuenlrahpzlHSbeh57eoJ0cxpqnG2neR6DfYZ6exoT5kq+bMUeUaXFZcobysWxxaUfxb6qzJuGnIOZH6ednKmsGqOConucHpuclKKjGqx5q26cHpP25vbQ1wjQ163k8hoOoPcU9w0drgqPCvf0FZ18mXoeHPqg9zoKfJl6g4KIhYUe+9T71AWFhYiDghqDjoORhR730/vUBYWSk4eUG52Zmpwf91QcBWAHLAr5dASKHRz6oAdfCvtURB0cBWCYCnqafKsdDvcpi/d0AYscB4ADdwr49BWCh4OFhB778/vzBYWFgoiDG4KDjpGFH/v09/QFhZGIlJManJmanR73dPf0BoYd91T3EAr79Pd0B18d+RT7dFMK9ymL95QBixwHgAN3Cvk0FXp9fHke+3T79AZ8HftUcR339Pt0B3l9mZ2Uj5ORkh/38/fzBZGRlI6TG5STiIWRH/f0+/QFkYWOgoMa+RT7tFMK+//3Dgr2HfcU95T3FPeU+3T3VPc09xQT8/gU91QVOwokHS8KPQoeE/X6lE4V91tj9877gr8eqEeEPUIa2l68NjAayx33BR1FUVFFHssd9wodywesiKx1ph4T+0k3I2UgGyAjsc03H3VwiGpqGvtfB9dwv0I6GhPzuB0hNeH13L7U2KYe918HtJG0m7Ee+4JXY/vO+1sa+zf2K/c0Hvn+Bvc09uv3Nx/71PoRaQoO+/90HfcxCvfUdxKL9xT3lKwdi/cUi/cUE70AE/6Adwr51JkKFvU14SG4HTfARdZwHvwf7Qr3GAf3bab3O/c091Ua+JQHOwqFhoqKhh6ydWGmWxuXHcRS0qKhkpaeH/wm7Qr4JgeAnqGEoht3HdJSxERbYXBkdR8TvQCMhoaMhRskHR/8lAf7Vfc7+zT3bXAe+xgH+2j3XftArR33KB0e+B8HE/6A1qbA0d8aDqB3Cvc5Hfe093TgHfd097QD+RR+HRX3FPiU+xQH/fQWS+sdywb69PcxHfsU9zQGQAr81IQK+zT7FBz7APqUB/gU+rTwHUsc+wDL90gdIL4K+cT3tBX7mfdx+w/35/fkGvd1+yL3FPtupR6Qlo6YmBrAYLZWVmBgVn6OfpCAHvdFHfvk+w/75/uZ+3Eeqh34VAZIHfhU9wQK9ymeCvgU91T4FPdUAZAK91QDkAr6FBW4HR5L+BTLBvXhNSEfHPmA/ZQV7woedwr3QArL+ZQV92j7QPdA+2geHPuAKh39dPceCvlU9yIKq8sHdh0fDvv/+5SPCgGL9ykd+RQcBcAVOwpVCvcfCm6orh74NPdAHfcfCm6orh74NPdAHf0UBzq/QtdwHv2fB6od9xSLCvmfB9emv9TcGvmU+RRJHfuUBvchCh/9tEQd93T8lAaqHfcU9wQK/H/7FPcU95T3FPcU9xT3FPcU+BT3RQqfHQP6lPf0Qh39VAZRHflUMR331AQsHf1UBlEd+VQxHf4U/LQVUB37//uU9xT3lJEKAY4KA/gU93QhCvfUBCEd95TLNAr5lPxUFZx8mnoeSwZ6fHx6H0sHepp8nB7LBpyampwf+5T31DEK+ZT8VBWcfJp6HksGenx8eh9LB3qafJweywacmpqcH/uU99QVnHyaeh5LBnp8fHofSwd6mnycHssGnJqanB/7lPfUJQo3Ch/7lBz64NkKVgp+HRz6AAf3FBwGQEkdHPsAKh0c+YAoCncKQR37//uUrB33FPcU5h0Si/cU9xT3FOwK9xT3FBP3VfgU93QhCvfUBCEd95TLJQoTCEQsCvuU/bTZCn4d95RrMgr4VDYKE4QFq/eUHPuAB/wUHASgix1LcR3r+xQrB3wdS3Ed99SFHcv3EAor9xTrhR0TClTL9xAK+9QHE4dF+JSrSR371Pe0BhNwqkAK/FSECvu09zYKHxz7ACgKdwpBHfcp9w4K9wwK95T3FBLmHZ4K95T3FPeU9xSL95QT+aD3Jgo1CvwU+JQVqQeMkZCWjpD3V/dXGBP2wJCPlo+RjAj3MvuUBvoU/JQ1CvcU+TSIHc8KoAr3lPi0FRP5oDMdHPuAKh371Ps0B2had3JyHxP2wPta+1oFcnJ3Wmga9x8KqG6uH/cUBvsh9wb7B/ci9yL3BpUdHvgUBu8K9yL3BpUdHvdUQR2gngr5lPeU9xT3FBKL95Tr9zTnHYv3NOv3lBP5gHcK+DSIHRP2gM8KE/mAoAoT9oD9FPl0FfcU+JT7FAcT+YD+FBZr6x2rBhwEoPcxHfs09zQGQAr81IQK+zT7NBz7APrUB/f0+rTwHWsc+wCr90gd9ymLq/dU95Rr95Rr95T3VKsSixwHgBOsHAeA+NQVi4ur+7TLHvv0q/t0ywVLBvu59/QF0PdBHSsG+zQGS2vL/DQGE9z7NAb7VPd0BSsGa2sF+1Sra/cUgwf7VHMF+xQH91RzBYP7FGtroAqrawUTrOsG91T3dAX3NPw0S2vLBvc0Buv3QR1GBve59/QFywb3dMv39KsF97TLi6uLGg4goHb4FPcNHQH3FPeUA/kU+RQVfGeLPhtEUsTSH4uL9xT3FBr3lPwUBvqU/FQV+xT3VAX5tAfLq2v3VAX+VAZr+xQF/HQGa/sUy0sF+9QH+2j3QPtA92gelvWLlhv7FPtUBftUfh0HDl4Kdwr3VBU+CvfU/JT71Ac+CvoUB0UK+9T4lPfUB0UK/hQH95T6NCAdXgp3CtMd+9T71AY+CvfU+9QHqR331LkKRQr71PfUB/Ud+LQgHf1/2Pp6Abj6WgP5B/c0FXoK/B34Hfgd+B1ZHZOHlEIK+BQWegr8Hfgd+B34HVkdk4eUQgoO/X/Y+noBmPpaA/jn+NQVVh34FBZWHQ78//ch+lr3DB33dBUzCvgUBDMKDvz/90H6WvcMHfk0FTQd+BQENB0O/v/Y+noBuPjaA/kH+nQVlIeTQgp6Cvwd+B34HfgdWR0O/v/Y+noBmPjaA/jn+NQVjx1ZWQWFhYeCgxqDj4KRhR74Hfwd90gKBYWFh4KDGoKPg5GFHr1ZZQoO/P/3ofja9wwd9/QVMwoO/P/3wfja9wwd+bQVNB0O9ylyHVUdkAr3FAOPCvi0ix0c+cBxHfnU90IKnJp8eh/91Af3FPnU9wcK/tRzCvi0BjRLR2b3Lx34lCcdrkvT4Br4tJwd9ymL6yv3VEvLy/cU9zsdEveU9xTqHRNe+DT3lBX61Hod+VQHhQr+1Hsd/VRzCmv59BWGHfrU9xAK/VQHfB3+1HEdHAVg+3QVHPnABvs0KwZW02DjHhwGQAbj07bAH+sHE77+BCsV5AqChISCHw78/4vL9xTL9yAd9zEKA/cmCkAd+BT3NIsd/dRxHfpUhR351PcQCv5UB/cU+lQV40PTMx791Hsd/tRzCvnUnB3+f4u79zS7+ZTrq/c5Hev41OsD+GT3FBVfZ2dfX2evt7evr7e3r2dfHvdk9zSLHfyUcR35VIUd+JT3EAr9VAf7VPnkFYKEhIIe5Aof97SbFekd/JQGRVFRRR/+lAeqHfiU9wQKYQr61Pd0A/mUHASgOAogoHZ+HYwK+RT3lAP5lPjUZx36FPgUZx0OIIv3lAH3Jwr5FPeUA/mUmR1mCvoU+VRmCg77X54KW/d094T3VPek9zQS+TT3lPdk93T7VPc0m/dUE3r4hPdUFdtKyzw7S0s7O8tL2x4TiNrMy9sf+ET7VBXSUsRERFJSRPckHRNEdx0f/PT5FBXjQ9MzlB0z00Pj9yUd+qT8VBXJWb1NTVlZTfcICv3U+hQV7DzaKio8PCoq2jzsHhMh7Nra7B/4ZPdUqwr4tP0UFcBgtlZWYGBWTAoeExI7Hftk+FQVtAoOSgocBgD5FBUgCqD7FBwGQAEcBir3agOPCvg0FfcEgPcHYfUe9+37H/wsxfvcG/t095QGkgr8lPyUBX9/hHt6Gp4dHviU/JR8CveU93QH+EP3rzj8cWKJYohiH4p7h3l7GniXe5+ZkpKVkh6aoJarlqIIxPcU0fdL9yAaDiD7FOoBi/d09zT3DR33NPd0A/kU99QV2gr5FBbaCvc0FvvG+6xc+4ge+zwG+4j7rLr3xvct6Pcb9zfNy3+CzB+Dv7+IwBvAv46Tvx+UzcqXzRv3N+j7G/stH/d090QV9yZj9x8r9wUencGUxMQa1nrWac8e+zAmSC77Cx+hMCyVLRsjI4BzJh/p+wwm0PsyG2lHekBAGlKUUZ1UHiv7BGP7HvsmGvsDlvsLviYe+6L3HfgVdPecG/eY9/+l95/3GB+98Zb3CvcDGg4gi/cU9zEK9xT3RQr3Ox0DVgr3dBVWYGBWHvdKClZgtsAf+lQHRh0e99TzHUsHVrZg90EK/VQH9xT5VPAd/TRvHfsP8Cb3Dx6ZHfdIHfcpi/cU+JT3FPeU9xT3FPdFCvkU9xT3ifcUAxwG9fjxFXyCfoKAHvu6+/8FYWlFalYb/tQGdWySp5qUmJSXH/e69/8FtK3RrMAb+tQGoaqEbx8c+4v3NxUwIFhEUR/7lPvPBfnpB0YdHvfU8x1LMgr41PMd+zQH+In7NxWjhqKBoB7LbUeqRxv7VPc0BtUK/LRvHfsP8Cb3Dx761Abl9wG/0cQf97v3/wWmrZ61txoO/P+L9xT4FMwK1B0U/PoU+PRCHft093QGLB1LRwr7dPt0B1Ed93T7dAZ5mX2dHssxHfd093RrCh/3FPvUvR39VAf3FPlUFfcQJ+/7EB69Cg78/4v3FPgUzAr3MQoU4Po0fh0VvQr5VAf3ECfv+xAe6/40vR37NPu0FfzUBlEd+NSnHQ50HfdU9xT4VI4dHARu+GEVlq14rmqWaZZneIBpCCBqKEP7BBv7BCjT9mofgK1nnmqAaYB4aJZpCPs1vfcn+wD3PRv3Pfcn9wD3Nb0f/IL4RycKdB34VPcU91SOHRwEbvfHFfc1Wfsn9wD7PRv7Pfsn+wD7NVkfgGmeaK2ArICvnpatCPas7tP3BBv3BO5DIKwflmmveK2WrJaeroCtCPyC+OEnCnQdnx33lI4dfh34VEkd/RT1CvkUJx38lPhUJwr3KYv3VEv3tPg091QSi/dUHAXA95QTuPnU+FT3Lgr7VJgKE3hjHfsUrx33VKAKcx0TuPcUWgr3VLcdHvcUWh37VPdUB18d+xQH+NRLNQr3lPeUFRN4lx1SxNJ3HR4TuNLEUkQf95T7FBUTePev+3n3efuvHhO4/hQGtgr7r/d5+3n3r/cW9wq82uUf93AGPOX3Clr3Fhv3r/d593n3rx8O9ymL9xT3FPcU9xT3FPcU9xT3FPYdngqL9xTsCvcU9xT3FPcUE/6rgPgU+ASMHTId9xT39Iwd+3QGgoSEgh8rB4KShJQe93QGlJKSlB/7FPf0jB0yHfqU/DSMHRMhAAD99AaChISCHysHgpKElB759AaUkpKUH/0U9/SMHTId+xT39Iwdux0TckAAMh37FPf0jB27HRMwkAC7HTId/JT49IwdMh33lOuMHRNwJQAyHfeU64wdEzALACsGgoSEgh/7hPsEB4KEhIIfKweCkoSUHvd0BpSSkpQf9xT8JBUc+YD6FPcyHfcUFtJSxEQeHPmABm4dH/4U9xEd9zIddx0fDqD3o/cUl/cU+HH3FJP3FPcZChNekAr4fxVqTfsMUPsDG2Rpk5lvH2+ZBcAgJ777LhsT3vsZ+zxXTvsYH/jrB8v3CPcyyvcVG/cf9whYVvYfdba8gcD3Mwr8/Acc+sD5qRUTXtJSxERuHR4TflylYrF1Hhz7Di0KyzEdE94cBPIHvh33FB0TXuoKE954f392dRr9egcTftIdl46RlR/3Ax0TXssKE96glpmhoxoOoPej9xSX9xHCmPgw9xSS9xX3GQoTr/nU+KwV+xCB+yRd+whVCPdNB/cHxPcnvPcOlgigCvg2BPsQhvsiV/sKTgj3UQf3Asj3KMb3EpEI+1kH+dT8YxVqTfsMUPsDG2ltkZZwH/dQB36PfpB+kQjE+wf7EMH7K4WFi4Qb93IHjZybjJsb9yvpVVH3Bx+YhZiGmIcI+3QH9xpi9zPO5rgI+0wH+D8EMFj7Mz77GrEI91gHhaSliab3MwoTEvtRBxz6wPf+FdJSxERuHVylYrF1Hhz7Di0KyzEdHATyBxNKvh0TgfcUHeoKeH9/dnUa/XoH0h2XjpGVHxNK9wMdE7XLCqCWmaGjGg4gi/cUAZgcBnMD+N34vXQK+sv8XUId/lQGUR36VLIK9yn7AhwFXAG4HAcmA/j99x0V3Ar8HfgdGPgd+B3cChlZvfIdGfxm/GbOHRn4Zvxm8QoZvb0F+OP6vxWQnIGdepBNnBh7kHmBhnr8CRz69RiGepV5nIbJehibhp2VkJz4CRwFCxj5Jf0fdAoOoPsUHAZAAYv3dBwFSvdqA/kU+FoV/CH4Ia4dGfgh+CIF0IgKfh2rFfckefdm+yv3Lx77EvcV+1nU+6ieCPeaiAr3jwf3a3r3HljgLPD7BK37SG77pYp8lH2ahgiKjo6LjhuXlpGWkB+SmPcx98b3ZBoO5gocBKL41xVaXJdJx/v3+9L3PFCqBfpXB/cz+9apT82B9/hXBfdXlxW3tn21T5T8itQY+3X4WwWmfXqZeRuLB3l5fXB+H/t1/Fv8ikJPgn1htmAZ+AD79jX8iAVfhJtxqhuWmY+Tmh/4VfeA+FX7gAWDmpmHlhuqm6W3hB81+Ij3//f2BQ77//sUch3eHRwFeRwEoxWYpIapd54ImH97kXobgYGJhoIfHPsA/RRxfn1tkm4ZbpKkd6kb+NT81AZtn3KohB6KkJCKkBujoZihlh/5FHcKBQ4g9ysd+RT3lAP4wfeUFfjn+OcF/OcH/RS4Ffjn+OcH+MH9NEId+3T55wb3i/eKl5iLn3+YGX6Xd4t+f/uK+4sY/ef3dAY5Cvt0+3QHRR33dP30BnmZfZ0e+fT7dAZ5mX2dHrcdH/d093RrCh8O/X/7FOuZHeur6xKL64v3VIvr95Tr91TrE+v3tMsVVmBgVrUdHn4dBFZgYFa1HR75FPsUFVZgYFYeE/e1HR/rFvU14SEeE+u4HUSyTcRqH4n7ZSFf+05QWnxVelhyCBP3+IUHxKyyydIaE+v1NeEhuB1Esk3Eah79yAcT91JqZE1EGiHhNfX14eH10mTJUqwepQfsv6P3M70e9z7B95Tbjvf9CMSsssnSGg4g+wT3VFB2+DTL+FTL9+T3VBKb91T35Mv4VMv35PdUE3uA+Ev3nZEd9z1i1wr7dPi0Qh371AY2HXmZfZ0f99QxHROAgBwE8PsUFdht01XCHvvk9+R6nHiYd5cZefuD96b7pwWdeZVzcRr3RwpnZ0uMZ68Z+6X3pvuDeZd3mHicehkTe4D34vvjBVTB1G3YG9jTqMHBH/cn9yYFwsGp09ga/P35aBUTDAB/n36eepz74vfjGMJVQqk+Gz5DblVVH/sn+yYFVFVtQz4aPqlDwVQe9+T75Jx6nn6ffxkTe4Cd94T7pvem4h2jlaUbpaOBeZ0f96X7pveDnQX5DTdCHfvUBjYdeZl9nR/31DEd/LT4tNcK+Cv3PZEdDv7/i/cNHfdU99QBi/kUA/kU9x0KS/jUBsMdLwoey/wUSyYK+JQnHfsUHAUASR37lCod+1QoCveUQR3+/6B2Ae34UAP4lPe0SR37lCod+3QoCveUJx2p9zEdroxvqGgb+9QGaG9uaIwfp/2UBWiMqW6uG/eUBq6pqK6MH6f5lAUOi/c7+G33Emf3PPfr9yYSHAVT9zP7BvcSE8QTpJgdE8TlHQYT2Ps89x0Hewr5EfniFfsSO/t8Bpn3I/fgn/eEGvcZJuD7JTZOa2riCq2dsRvAumhXHxPE90QdeI19Ho5wBfiWBg77lPcS9xb3O/dG9yb3g/c8EhwFVfcz+wb3EhPUE/iYHRPU5R37PPcdBnsK+RNZFfsSO/t8Bpn3JPfgn/eDGvcZJuD7JTZObGniCqydshvAumhXH/dEHXmMfB6PcAX4lgYO9ymL9zkdHAeAA/cxChX9lAb35PgUBfmUBvk5+UkVuXZdqFkb/ZQGZmh7b3Mf/hT+lGplg1afXRldoLluvRv5lAawrpunox/6FPqUrLGTwHe5GQ4gnHaldvf790sS+HX3SxNwkAr4ShX0Uez7Bx77E1QqRhtobKGjdB9uqoW3tRrdlt2Y3B6NlZLGjo8IjQcTsIX7BvsGcfsHG0RBp90f9wL3A6v3Dhr3ATXGJSEqUfsHHvsT7FRGGmh1bHN0Hm5sX4VhGzk5lpg6H4GNUJKHjggTcP6UB4qOi42KHpiJnYieiZ2IGX7c3YDdG7W3kaiqH6Oioaqu0CrC9xMa9wfsxfTy4VD7AR77DvsDa/sCGjnVb9Lz85+V8h6MlpaLlhuQB4zYa9bZGtWpvdse9wKr+wP3Dhv3Acbh8h8O/P/7FFUd1B0UcH4d+dQVOwpZCgeDHfcZHfdd94se9xT3QB37FAf7vPd0+4j3tGselQr7lPiUFfdE+yT3JPtE9yEKHvyUB/tE9yT7JPdE9yMKHg77/3Qd9xj3EAH3FPcU1B0UOPej+OMVgq+FsbIa9xT3QB37FAc/mkOmSR7w8AX67vjuFdwKOd0Y8h0c+y4c+y4Yzh3dORjxCveS95IY0WDbbuCCCJUK9xT3QB37FAeDHUFFnqtOHuvrBX+tsISxG/cjCh/3FAf3/ff9BfwQ9xgV9w5e+wrk+x4b9yEKH/yUB/kB+QEFDvx/mR33VAH61PdUA/rU+NQV+yX7FPsXIDceO0w5XFhwCBwEcfhU/RQH91T5lEkdHPuAKh39lAf8Ofjh+56kgB6Th5SJlJSUjZMMJKSW+OH3nvg5Gg4g90kK+pT3Fwr3FPcU+BT3FPcU9xT3FPcUA/cU+xQV+pRyHf6UB/6UmR33LgpLrx33tFoKy1od+7QH+ZQWYx1Lrx33tFoKywadmX15YR37/+od9xTrEve06+v3NPsU6xOw+JQcBUBAHfoUqxWVh5SDkR6QhYSNhBuJiYuKiB/8VCsFfYiAfnwa+8IGlJ+QoKIa40PTM5Qda5VumnIeE+j7XUon+1aGgXtrmGWqewiGlJWJlRuiopihlh+NjPcG92/3aBur+wMG+xZjLfsO+yMa/bQoCviUJx35tAf3L/sC9xX7Jqke8feUB3yWfpmIHvhUKwWKjo2LjRuSko2QkR8TsJORj5SVGg4g+3QcBmABqxwGYAMcBaD61BVWYGBWtR0e93T3tBWde5l5+/D7Uzv7jfuOHlJRUElPRPwPdxiBioGFhYL7dPwUGIR/jXuVgMtLGIWRlIiTG46Oi4yOH/eo4Pet+602+6iIgI5/k4IZy0sFhZKTiJMbkZCMjpAf+BT3dJSRkZWMlRmf+A/Sx83GxcQZ94H3guf3cffgGg6goHb6VPfUAYscBrYDHAas+gUVovcCeuhR2QjZUTmzIhsc+40G+6Qc+wAF98QG92H6VAX3xAb7YP5UBffDBvdh+lQF91kGmpiIhZcfloWVg5KBk4GQgI59jX2LfYh8+0n95Rj3xAb3UPoFBQ77FPeO+qD3jt4K+iH3IRXfHfxa+FoYrh34WvhaGN0d8SUYzQr7x/vHGPfH+8fNChn4ofghFSAK+xT3jvqg947eCvlh9yEV3x0l8RiuHffH98cY+8f3x64dGfHx3R0Z+Fr8Ws0KGfgBuBUgCkod9476oPeOAxwEjfghFd8d+8f3xxj7x/vH3x0ZJfGuHRn4Wvha3R0Z+Fr8Ws0KGfeh9yEVIApKHfeO+qD3jgP5wfeBFd8d/Fr4WhiuHfHxGN0d98f7xxj3x/fH3R0Z8SXNChn3oVgVIAr7//iA4/dG90n3Q/e63h36/vo/Ff02Bpr7SQX5GAZZ/LT7+ygFiocH+/7vdfeqBfdDBpj7IPdYVvdZwKH3eAX8+AZc+KoF+ggGHPuG97oV9xQc+mL40vs2+Nb3NvcUHAWeBQ6g+QP3vfdT970BlxwG6AP3p/dLClD7vQUcBLgGZftTBRz7RwZR+70FHAS4Bkf75/x6+zX8Ovc1qPcnBfu9BkT7+PlO+5/5uPef954cBTUFDqD5FPeU+FT3VBKL9yj4gPdUS/eUS/dU+ID3KBPI+lQcBQBAHfnU/jRCHfv0Bn5/g3+GH4Z/jn6Uge8nGDH7DftBM/tacAj5G/dUByoKtwoe+1T3NwbXt7/d6vcJHYMKLL85118e+zcHE9b7VCod+xQHE8grCvdU/RsG+1qm+0HjMfcN7+8YlJWOmIaXCJeGf5N+G/v0BhPUMAr79Ad+k3+Xhh6Kj4+Kjxv3Jh0f6OgF+1H3Mfeu+w33yRv3yfeu9w33UfcxH+guBYWSk4iTG4+PjIyPHxPql5CTl5gaDvz/oHYcBUD3VAH3FPdU+JT3VAP6tPmUFf10uQrBCisKywY9CvcCCh/71GuSHfjUB0AKDvsU9xYKAYv3FgoD+pT5FEwd9xQWsB33FBb3r/t593n7r7YK9B33FBb79fuz+7P79fv1+7P3s/f19/X3s/ez9/X39fez+7P79R73FBYgCvv/+JT4FN4d+BT5tBU8CviU91QVPAr4lPdUFTwKDhz6lfc7CvgUA/gU97QVPAr5VAQ8CvlUBDwKDp4K+nP3tQGL95T6c/e1A/cnCjUK9/MtFYyCh4KF9xsdmJyKH3z3Yfs59zn7YZoIeox+9xsKkZSPlIr3ynr3ivuKnPvKCPgUihWMgoiDhPcbHZmcih98+DP75vfm/DOaCHqMffcbCpKSjpWK+Jx6+Dn8OZz8nAj3tfpTIB1KCmAK+BT9yxX8tPvUBYWBgIiAG4CAjpCBH3eXf6CiGvkUB6KXoJ+XHp+WpIuef/i0+9QYn4CXdnQadH92d4AeDqD7XxwGlfu197USwfe0+7QcBpX7tfe1E5D6lPrQFfzQ/ND30PvQ+ND40AX8o/0rFbYd+/73/q4dGfj++P6jo7WLo3MZ9/77/s0KGfejnhW8vIvdWr37EvcRGEBA+w6LQNZA1ov3DtbWCBOg+xH3EVm9OYtaWRkTaP4f/h5ZWYs5vVoZ9xH7EtbW9w6L1kAZ1kCL+w5AQPcS+xIYvFrdi728+h/6IBgOSh33Lh0DdwrTHf4U9xMd+hQG9R34tCAd+//nHfiU9xQB9yAKFOB+Hfl0Qh391AZRHfnUMR33FPwUFXIK+dQG49NDMx/91Af3FPnU9gr91D8KDv1/i/eUAfcnCgP6jvo5FZahh6Z7nvvU+BQYc6hZi3Nu+9T8FBh7eIhwlXUIdJahfaQb91T9FPvUBoKBh4SFH/s0+1SDgYp+kH8ZgJCXhJcb+VQxHfn091QHpKGZopYfDv1/+pT3lAH3JwoDq/cxHX9/g4CGH4aAjH2Tgvc0+1QYhJKUh5Qb99T9FJgKcnV8dYAfgXSOcJt499T8FBijbr2Lo6j31PgUGJuej6aAogihgHWachv7VPnzBp19mnkeDkod92764PduA/lB94EV3x37+vf6GK4d8fEY3R33Z/tnGPhn+GfdHRnxJc0KGfeB96EgHZ4K91TD+ZT3nAGL95T3VMP5lPecA/go+EAVV1cFU+srwwe/vwX3mviyFYSTfYmCgvu3+7cYgoKJfZOEkoOZjZSU97f3txiUlI2Zg5II+6b9RhX7tPe0Bvi0+LT3tPu0BcvLFfu097Tn57CwyYuwZhn3LPsssGaLTWZmGfe497ggHfsU9676eveUAYv3rvp695QDdwr49BVxe3R0gR6Ig4KJgxt6e5GYfx/7JPck/Kr8qt8dGSXxrh0Z+Kr4qvsk9yR4nYanlaMZopWim6Ub+HRkHfx0B/eU+JQgHfsU9zSZHfc0AYv3lPr09zQD+oH4RxV/f3uEehuDgo2OhB9zlXuipRr3NAf7TyFtRk4fQjl4+yqp+4WNfYN9foYIiYeGiocbgoKPk4QfhZP7NfdX910a94vN99340h73NAelm6KjlR6ilaeGnXj39Pv0GM0KCPdH9+EgHWEK97T3FPeU9xT3tPd0A/kU+FQV95QH95T7FAX3FPhjFfyU+5QF/LIH9ycKBfe09yMVIx1eChwEefnxFaGAdZhzG/0UBnN1fnWAH4B2jXGZePfU/FQYepeegaAboJ6VnJcf99T4VJmejaWAoBn3G/1Rix3+VHEd+lSFHfpU9xAK/lQH95T6VCAdXgocBHn4NxWWoImlfZ771PhUGJx/eJV2G3Z4gXp/H/vU/FR9eIlxlnYZdZahfqMb+RQGo6GYoZYf9xv7l4sd/lRxHfpUhR36VPcQCv5UB/eU+lQgHV4K+tT5FBWggZ56lx78VPfUeJlxjXaAGXWAfnVzGv0UB3OYdaGAHqCApY2emfhU99QYnJeVnqAa91T8dPcuCv5Urx36VFoK+lRaHf5UB/eU+lQgHf1/i/d495L3RfT3RveE93YB7vePA/pk93kViZOGk4OQg4+BjIOICIpEczQb+z77JO33MEsf+BcGmpiWmo4fo/cEjZSJlYWTGZKFgpCBG/xfBomyiq2Oqwj4fAabmJaajh+j9waNlIiVhZIZk4WCj4Eb/GgG9ynO9yHm9zzSz3qMG5yGnJWPnLb3MxiNk4qUh5KGkoSRg40IjIc1oSMb+7/7lPtO+6wyHylHCvsGLQrOBoloi2WMawhJ9w8K+wUHepl8nR7qBvu63/eP+1D3zBv3DOirjI8fmpCUm4ebCA79f4v3avtq9274D/dX+BX3exL3FfeP+DL3dhN8+pD4I0Id+zYGE7wwCvtJ/DIHE3z4D/fFawof9xedHfvF92sG8dfP9wXw4UeKjB6RhpSIk4yUjJKPkZLy9xMYlZiKnn+WCJCF+xX3DPtcG/uS+0z7Oft4H/tzLAcwCvsXLQrq/BMq9w8K+yotCvpQsgr9f/uUjwoBz/eS7vdb9PeRA/pm9/MV94X7ZNz7TNIe+yLC+w669Rrm48r3E/cq9w0giowek4WUiJWNlYyTkZCU3PcmGJKXiZqBloeP+wD3Avtfogj3RJ0d+xsGenx9eR/7SAf7ZWP7JPss+0wa+4/3dDH3SEQe9xtV9wpcKxr7BSFXKftF+yD3GoyJHoWSgo6CioKKgoeGhCT7GxiCf4x6lX+QhfcU+yD3fmoI+0MHeZp9nB73GzEd90MH92iu9yb3NfdgGg79/aB2+jj3Ovck9zoBi/oWA/oW+r5CHfs/BoDCdrtrtAj3fTEd8Z0d/dRHCvsZB3qZfJ0e9yUG9yDlZUCxH/wxRwolLQr4Pwb7AW77AlD7RBv7BPcPCvsTB4OOg5GFHvdR+133KPtF9zX7VQiDkZSHlRv3VwaYlpKWkB+RlomZg5T7K/dN+zP3VPsp9zP3d6b3J/cRqvdUCPc8sgr9fKB29/73O+D3PAH4I/eAA/jvFpyamZ0f9973tmsKH/KdHfu24Pe2MR3zB5x9mnke+2sG983415CVi5eFlBmVhYGRgBv7UwZ/f4R/hh/7U/w4eF91YXpgGXuxe7Nzuvtr+D0YloWAkn8b+1YGgICFgYUfhoGLf5CB99X81hj7avcPCiMtCve0Nvu0RwokLQr3tPveBnmZfZ0e90AGDiCHdqT3dPjU93T3NPd0Evg095T3dPeU95T3lBN+kAr39IEdSwc+CviU93QHE746Ch/3NJ0dHPtARwr7NC0KE373lAaD/FT7P0r7K1F+hn6Hf4Z7hIN5knrS+0YYfpCXhJgbj4+MjI8flY+Wj5aQ90vQ98L3B5b5Bgj3dPx0BvtE9yT7JPdEHvcUBvcjCh/8FPq0Qh3+VEcK+zQtCvpUsgqgoHb3Jgr3FPcUrgr4lvfpFYmKiIkaio2LjYqNQPfAGPczBq73FBX7dQZr9xQF97gG9zH7FBWt9xQF0Qau+xQF98r8QBWJiomJGoqNi42Kjjr3vxj3Ngas9xQV+3oGafcUBfe9BvgN+zRCHftHBq33FAX3Jacd+wMG5vfsjpSJloWTGZKFgZCBG/sdBnx+gX2IHy77/AX8AQYp9/wFmYd/lXwb+xIGfX6BfYcfKvv8Bfv7BjH3/AWZiH6VfBv7HQaBgYaEhR+Fg4mBjoHk++wY+wEGUR33Igas+xQF+0MGUR33ZAb3NPz8BX2OmIGZG/czBpqXlZmPH/c7+PwF92UG9zr8/AV9j5iBmRv3MwaZmJWZjx/3OPj8Bfdpsgr8f4b3T/tK90v35fcu98f3Svs/9zcS95T3nvsx9y73DvcuE0scBI/6FBV690r7Mcj7WpwI95D7LgcTU/uJB2NiiopiH/eL+y4HE0v7kAeKamqLbBuLB/tojAUTTfs4B/cFjYmJixrKn2drkR/7swePkYuKkR+GhYuGG/wmB3eIf2xgG4uNifsFjR5s+0sFE0v3XAawr4qvG/uTBxOL9y73kAaKtbSLshv7jwcTS/cu95MG95aZ90jMoveHnfdXL+L7Jq4IE7XjuMPbfvcZCPtr/LUV+1P72qEjHvfmB/P32qj7Wh9E+HAV+0H7pJ80HvfHB+L3pKb7SR8O/H9KHXcKA3cK+ZRrHfx/ngr3FPcU9xSMCvmU95QU4PqU9zQVswoEswr39GsdIPuU9wb4sPcG95T19yT3Avex9w/FHfr8vx3+nCIKE/6A3wr52PsL9zQKiYIffYkFjQeWltgK93wHugrk+v7rCgYT/UDaHQ4g+5T19yT3Avex9w/3lPcG+LD3BsUd878dgyIKE/6A3wr6MfuK6wraHTIcBOn3NAqKgh99iAWOB5aV2AoHE/1A93wGugoOxgr5dOsiCt8K+rT7FEId/dRBCvnU9wMK/RRBCvkU9wMK/FRBCvhU9wMK+5RBCveUsgrGCpkda0Id+5RBCveUMR38dPfUIgrfCvk0+BRCHfxUQQr4VDEd91T5VEId/RRBCvkUMR33VPlUQh391EEK+dSyCvuU90cd95T3Bvhpd+Qd93PhCvsTIgrfCvmC0GAdbflhkB0O+5T3Bvoi90cd5B0cBN/hChz7gSIK3wr5ZPuCkB2pHAWlYB0OIIv3Hx33NAP3lPdUFWdub2hnb6evrqeor6AdHvc00wr7tCod/RQoCve0Jx0cBKD5FBXzM+MjHvupBpOrlZWWoQimv6jF3RrYi/dH+3SWCh5gYX9NgFB/UYBPZGRsbGlgZ11fUSv7C2aICGqIb29qGv0VB2ipb62KHq6Kx3bKdQhm9wD3G1z3IxucBtcGnZmLjxvjjM2ltr6xuJzIhdako56slbCWs4uzgLCps5q6ib0ImYepgKserbKgxMAaDiD3MQoB9xT3FAP3lPpUFa9up2hnb29naKdurz0KHvc0/JQVVQr7tJwK+RQHPQoe97RkHf0UB/r99ykVlquPqZkajb18um2zlrCLs4CzgbB4rHKjkdZ6yGW4YL5JpTOMCId9i3kbPwZ6Bvsj+xtcZvsAH0x1T3Zoighpim1vaBr9FQdqp2+siB6wiOv7C7dRr12tYKpssmSWT5dRllCXTbZhCHAK93SL90fY3W3Fcb8fgKGBlYOrCPepBvPi4/OMH8B2xWmxHg77FPcD9yDI9wjC4Me+0fcUzviF6hKL9273NNXlzV7ml85/y5DOhsKXzYDGj83Nzt33bhOv1LD6K/d9FWqBe3iAgJCWgB73dAeWlpaQlhuelXpqH/sxBxOHIpD3TPcOFa0HrZacoaGWemkeaQf9EfeeFft8Rdn8O9X4O9sG911TFUj7rAZ2fH6BfRuChpCVih+KjYuUmhr3okn7tgdxjXqPgB54kZqCoBukpJqppR9jzgf3kPeUFa6Jo4aaHqeDeZlwG3N0fXF2H/c1SPyBzq8HcKGifaIbpp2Zp5MfkJqNpKwa94+cFUcGcYp8hxp6h4GCext0gJytH8z3GdcHsoSnfZ4epHlwmGobaXB+cngffXiFb2Qa+xUHZJJumXkecp6mfq4braeYpp0fk5eQmI2aCIySjJmhGvxX+dUVrYCddnWBeWke+zAHaZV6oaCWnK0e+Kn8wRUTeNVgNoswdzceflFbYFKECHz7Hfsei/sdG/sd+x6LmvsdH1KSW7Z+xQh334vm4BqLB+GM5p7eHpjGu7bFkQia9xz3Hov3HRv3Hvcei3z3HB/EhbtgmVAInjiLMDUaiwf9h/kfFftdQfddB4SvfL9z0Xy5erl8uQjZBsD7V773VwXWBvdb/A0VZIRtfXkecnhxfmobaXGYpHkffZ6EqLIa9xYHspKomZ4epJ2lmK0brKV+cp4fmXiSbmQa+xYH90n7DBWzB21wcnxyG3Z8lJ2EH4eXiZylGve5zvukBxMCCAB7i4OMiR6AjJGGlBuYmZWgmh/3r878Bgf4SPfEIB37lPdY9z/G1vcG1tbp90He3ffx3IV3Eqb3bO/3DETvx9p65ZvZg+aR33vmmdGG5o7j5vcDE/3UqPpf97gVt36icXx8hHx8HvvBB3yamoSaG6WYobgf9+b3ZhW4fKJtbXx0Xh5d5Qf+WvecFfzNJwcT+NVY+M0i6ffMLQf3SfzNFcEHYmdpd2sbbnaXpIMfhpqIoq4a+Bvk/AAHdouAjIgefY2ShJcbnZ6Zp58f+A7k/IIH9+j3KBVdiWqEdh5ngHJ4aBtrbJ2wbR9bMvkr5AcTBioA+20Hr6iqnawbrqR4ZpYfkneNal0a+1kH9+aVFW6Ld4mCHol3g3mAewhoc2Z5XBtcaJytcR94o4GywBr3QQfAlLGepB6tpa6cuRu4rnpppR+dcpRlVhok+0c0B12adKqhmJejkB6MkIyfrxrmfgb89PolFV1+c21ufaO5HvdmB7mZoqipmHRdHvtmB/lj/YMV9wiL9w5x9wQeedpKxT6UCJ/7TPtOi/tNG/tN+06Ld/tLHz2CS1F4PAhy+wSK+w77CBqLB/sHi/sPpfsEHp08zFHYgwh290z3Tov3TRv3TfdOi6D3TB/Yk8vFntoIpPcEjPcP9wca/nocBPwVR/ubRPebBSEGoE2hTKFNqy6fRZRaCPuj7/ejB/cN+CMF96D74RXAgrJ4pB6tcmicXRteaHppch94coJkVhr7QwdWlGSecR5ppK56uBu5rpytpB+epJSzwBr34/flFTD8EQZud3h9eRt/hJOZiR+KjYuXoBr4AzD8HgdnjnOQfB5ylKB/qBusrZ+1rx9UBxMFAKDmBg77//sUHAZ23h346fn5FYuKjPs397EeoH95o2cb+4MGfX+GgYUfhIGMfZJ+9zX7qxiKjIuLihv7kfxUhH6MfpGBGYGRloSZG/eDBq6co6GYH/eL+EuVnIsa+br5FhWVhYCQfRv7hQZnfHV0fh/8lv4kem2LGouLivfn/QEedpaec68b94MGmZaQlZIfkZWLmYSY++T4+xiKi4yMG/ik+jqSmIuZhJUZDnQddwr3OR33c/rW93MD+UH5lxWLhH77VPvnHnqCfXhwG/tNBoCDkJOGH4aTipWRlfdY9+4YjIuLix77EfdshpWKlpCTGZKQlI+XG/dMBqeZeXuVH/cS+3GLiosa+QT4hRWQg4uBhoH8Lf1nGIuLiose95j8cJGBi4GGgxmDhoKHgBv7TAZufZ6bgh/7mvh0i4yLGouYovgi+VYenZWXnKYb908GlpOHg5Af93f7KCAdoKB2+pT3lK4Kdwr5FBV1gHZ4gB78lPvUBYSBf4h/G4CBjpCBH3eWfqGiGvkUB6KYoZ+WHp+WpIuffviU+9QYnoCWdnUa+JQW9yOL9yxs9x8ede090y2WCKT7cvt1i/t0G/t0+3WLcvtyHy2APkN1KQhr+x+L+yz7Ixr7I4v7LKr7Hx6hKdlD6YAIcvdy93WL93Qb93T3dYuk93If6ZbZ06DtCKv3H4v3LPcjGg6g+xQcBgoBy5AKA/gm+dEV++b7o/h++9P36vexBfiA+44V+ycr++v3sAWNB4qKiowFiQf76vuw+yfrBfsAB/h9+7kFigeMjIyKBYwH+H73uQX91hwE5BX8fvvT9+b7oviC98QF+IL7xBX8gvvF9+v7sfh999MF/H358BX76/ux+IL7xPfm96IFDvv/+5T3C/cM9ysBi/cN+jT3DAP6NPcbFf1XigX7Kwf5V4wF94X4hRX7DPz+/jT4/vsN/XSMBouLiq4eHARsjAaLjIuuGv40+PkVffsq+VVKmPcqBf0Q+BEVZPsm+T/7S7L3JgX8nPioFT77Fvj1+/zY9xYF+435RxX7ETX4I/zc9xDgBcL5cBX7KXH3Df1N9ymlBQ77FPdF9wf3SPgy90T3w/c/AYv3P/cN9z34/fc99wf3QgMcBVL3AhVpcHBpHv7BBmlwpq0f+Rz3IQd+YoReXhr7lPdq+2P3m/ec92r3Y/eUuIS4frQe9xuLBv0cB/uw+KkV+zn7Hvsa+z/7Pvse9xr3Ofc59x73Gvc+9z/3Hvsa+zke97D3/BVlbGxlHvtCBmVsqrEf9zkHsaqqsR6L90IHsapsZR/7OQf3QvdkFfcAMuT7AB4c+4qLBvsAMjL7AB8c+4oH+wDkMvcAHhwEdgb3AOTk9wAfDkod96b4PPcg+Dz3phRwHATg90sKIh36VAb3M/cV9xX3Mx/6VActHfy6/ZQVyAr4yBbICg5KCvmU+iYV+137xgX4Jgb3OPt0FSP3NAX8ngYj+zQFLQb4X/lH+F/9RwX3yfeUFSAK+//7Q/fl9xH3M/cD93X3A/eR91j3BAH45fdy+CCjA/nD+TkV2SrBSGIePWeL+xPbaNJg8c2A3wj3A6AVmvsOLPsL+w6A+w6A+wjvhvcOh+jD496w9xfG9zUtnfsiCPeD+LIVTU0vgziB+yh4+yyM+yieOZUwlEvHssPRlsmV90+s91SK909tzYDWgbdRCMT+nxWMra7EXJn7v/tZ/DWL+773WXmCGIV7mymbKaQrGcQp9w5q83j3WWj3bZb3R+7zxHv3GKftCPdJ+lUVkK6TsnOqVs43qz2i+2/L+3uT+3Z1IYEgeidmQG8mZH8xpPtjs/thrvthlVCLRcBiCPcFNPciZvcffPdhdfdum/dP6b+mya+Wy7H3brL3bq33bwgO+xT3SfeG5vcG2/c32/dK9yHc90kBi/eY9+/b9zXb9/D3mAP55PkuFZNPQlxXqlGji+fEpgi7qNFkUhrbmxV+8fsIzy1hT3BiS45JjzLeQ+OT45PQ4YDjCPdA+BsVbLRVk1uS+xuh+x6M+xtzXoRZg29juWDMhMaD9wB+9wGK9pnGks6Rt7gItf1+FXZElyxAYfsVRPsxg/sipUCYM6Ni0nnQgNJ/0ZCXGJeR92z7IvfAi/dr9yIZrYFyYnMa9xb5SRVy+zNw+zFv+zGDXV9xZXf7G0f7MYD7KJsnliSmOsllqYu9g7Vy9ylu9yd59yqUy9SnwaAI06XYmNiS9zab9zuF9zJdxHrHdLFbnHWGbodzCPec7yAd/X/5n/eFAfga928D+Br3SwqBPHlKcVdxWGlfYGZgZ1dvT3cI+233PvyvB0WSVZpmHplmpmixarFruXHBegh5wcmC0RvJxZGYwB/Al8ahzaoI94YHWD4+cj0bX2SVoGkfcpp5n4KkCIGlh8TkGvge+AD3hfwA+BgHDvsU91R+HfdU3gr69/cTFVp0XnpjggiCY2CGXRtWXJKYYx9jmGiebqRvo3emgKYIgKeFs8Aa+Cj7E/c3B7iasqCrpqynpayesZ+ymLySxgj3OPu396b7Sfum+7sGSI9gkngekniYfJ6ACHulqISsG8XFnrDFH/tJB/gx+nUgHf5/+1T3NB33gRWXhoCSfhv7dBwE4AY5Chz7IPt0B36Ag4CGH4Z/jX6Tgff3/BQYhZGUh5Qb9ygKlJOPkZEe9/L4FJOVjZiGlxkO/n/7lPc0HfqnFZCXiZiDlfv3+BQYkYWCj4Ib9ygKgoOHhYUe+/L8FIOBiX6Qfxl/kJaEmBv3dBz7IAZ5mX2dHrcdHxwE4Pd0B5iWk5aQHw6g9ycKAcscBsADjwr5dEIdHPsg93QGmIOWgJAef5B+iYGC/BT79hiFhYeCghrpCoKPg5GFHvgU+/KVg5iJl5AZl5CSlpga93QcBOBrCh8OoPcnCgGLHAbAAxwGwPkXFekKlIeThZEe/BT38oGTfo1/hhl/hoSAfhr7dBz7IAdFHRwE4Pt0Bn6TgJaGHpeGmI2VlPgU9/YYkZGPlJQaDvv/+xSQCgGLHAVxAxwFcffVFVCdVrVdzQhdzXTW3RrXodC2yR6jrrGyv7dptWitaKMItk1EoTsbWlF/dUkfdElbgG4bdF2Vn0Yfn0VRlVob+wctWytAH0AqZfsQ+y0a+zi9+zvs+0Ae+0Du7jTyG6y3lqLCH6HBu5azG7S+gXXGH3bHuYCtG+DhzPcX4R/F4rPfpNoI/AwcBJUVkoqRkhqKkYmSiZT7CHA3WllDWUNxNYkouo+tkaKSr5evo6+vtbWquZ+9CJ68lbm0Gg4ghXb3EQr5PvimFYv9PvzBB/k+LQUcBXIE/T4tBfzJ+T4H+mo3Ff4f/SkG+h/7EQWQCgT+H/sRBf0x+h8HDvv/+gr3OwGL92H3dfdh9x73Yvd092ED+IH6sRV2ep2goJydoKGceXZ2enl1H/g6FnV6naCgnJ2hoJx5dnZ6eXYf/cD7TBVSXV1TH/xCB1K5XcTEuLnEHvhCB8NduVMe+rh4Ff4q/S4GTrxayB7VBoz7dwVSuV3DxLm5xB73d/ce+3cHUrldxMS5ucQe93fWB8e8vMgf+3z6wxXS9xePkomUhI8ZhI6CiYeEQ/sYGKZOR5pDG0NHfHBOH0P3GIeSgo2EiBmEh4mCj4TS+xcY+yFDLPse+zMa+jEG9zMs9x77INMe+HH8fBXEXbhSU11eUh78QgdSuV3DxLm5xB4O+5S8X7S6oHfr9+Gc+L3Ot5/3B5+Nn32ahKm7oHydEpKpd56Lq/ck6ezklLtrqpW0abHM4aa/rZuuxa+h90n3N4Ka9xGgE55Kyez5K/r5FWuNiXSVjAiWhJ2Nnx+LB+J9FZWPgZ9ufgiLB52QjHiVjgj78/w/FZOIhoKGeoV9fX+GjAiLB32NnZWSmJSZiZ2UiAj56/v7FWKs+w+RiDsIdXuJe34fEygAADBZULn7CoZLCBMWAMgAh1N7VINTbYyOoJSqCBMCABAAlKaYrIyrjKmInYOPhJCAgntxaVRBc0aDR4JLkmmxgJh3eomIiIaZgpZ3CBMAMAYAm2+aX2V3jPBrkWrJCIsHEwkIItDLkpTPbKhzpPse8Wizep10lIKgdbt80Ka8kJSPh4d5CBMoAAAwdSLPNZq3lqmBwZG3CBMAQEIAldfQ9yeqk1zj8c+K2Iq9uPsDuHO9ccLX2bGhlqeXiZUIEwAwBECCuC4mN4hlin2UfJlftrxnzZeokJWQqpirl66erpUIE4gIAaykkYmegZCGjoOLhIB8cUR8dYRugmyDYY1LjZqpXaV+ko+fnJ2VlKSRmKAIjY6bnJiUj46L2WSMCBMCACAQaYyBcYxxCHGNmXWUG52MeneBiHyGd8qOqY2rm8Oziq+KpV6KPQh+xZ6fdh6ZfU33LPcelq+Ern+ZN4aDmVF1hHCCepWbpZWlgc1Uh1OIkyiaiZqJsXCmhgjiektZlk4IExAAkACYR7idtPtKk4Ctgaz7IKj7EWIv0ZObjKOQla+l52P3A2PWdLd1qH+VuXDGNJlLCJ02l2dwMQibhLJ6eRr9CPnPFYiJi4oeE0AEiACCipOXjR+UjYaRhxuLB4WJiZ2XiJGJl3mHcgj4N/tZFY59gnt/jXePXLugoggTCAEAAIsHEwgCAACSko93nn+bgZmSj3gI+0b3aRWIgYeNGomag5mDjQiLB4WNh5GYjJCMoH+KcwjB930VhoB0joaJeISFeYKSgZOalI+WCIsHjpWBoJ+NCJOThIOTH5SEmIWKhgj4yRz6wxVvnUeehfcWcXSO+w3Tc9twvV77KVgIExABAAApaXqBPUo8SfsKpaD3HpbUkcZ5yoKph7ORppbBqJuoWJ1qkWXLiAgTUAQAAO+Hn/CrkKCOoch77Xn0Tfc5PN8IE4AAAARJ0WLIceJ11X/Sj9CR41r3Dz3FWq8+n0aKCGRmhXxvH/sITHsxjSSNK477ApYjfltHMGBTUVJu+wNlKndYanOISYp4jFucmc+/4PsY9xX7XgiLB6Nk4vs3+yx2WIQ5rzyfRJxClmOWcpKBlImVhaavsYyrjat+nIClgKWIn5SWCJGUmY6iiaiIrpGel6qemrJ9uwhce3pldR5nd1SccXRtcbRGiFiIZWNfnWQIE4gIAaydZOCG43n3EnHUXcWJ4IiY4PcYjrKMsY2xjAi2touKtx/jiG1dxG68cuKVoJ+nptfLxKgIEwCAAEDUsPc9yvsP1wgO+xT3BPjj8Xv3Bvid9wQSi/cEHAUg9wQT3PqUrxVqPDV4MBv7M/slxOj7Bh+LlIWRhh73Evem+Bn3HIsajI2MjBvn+4Sx+1yVUQj7TfjzFYOIgomCiAiL+/b7BvtH+9Me6Qoj9whL9y73PBoTKJKLkoySHpb32IPw9+YfnmadZptmCCD3aBUT3Dj7z/umjnobtvdf9xz3PfdL4ZR/9w37OPcG+14I+UD70xVt+0sj+zL7JyiEsmj3VTX3gfdorPdLUZmHCP25+XkVioqKix+MjIuLjBv44vslFYmILvsi+4sv+wT3YvsQ9zeBmAiXvb+SwBsTJPc69yxNJfcHH/dz/HkVg4z7c7z7dm4IE1iGloeXhpZ9q3yrfKr3l/X09yyNjef7BML7I437Lwj3BIQVIApL94T6Pfd7EvcwHRz6QPfM+bH3vxPgHASV+G0V+1/7WC37UPt1+1Dv9w/Cqr3RHvaV+y73TRvjxLK+y1SVMqEf+yavBfsmrvsEx/c8Gvdf913W90H3UfdTQPsHUWRYSh4qiPcH+zEbM1NzVlHEftd5H/NzBfcia/c9T/tCGvf/+20V423cWcwelbuRvr4a+Bn7z/fP/BlYWIWBWx69SjqpMxv7aPtA+0D7aDOpOr1KH4FbhVhYGvwZ98/7z/gZvr6RlbseWczcbeMbE9h2HR8OIPsU94P7g1YKEov3ahNgHAXL+JQV0tKL9wZE0omOGPz//P8FcHFnfWYbbwaFj3KRdJh4nRn8KvgsBXCmfK6xGrCar6alHvcM9w0FpaWvmrEbsK97caUf91D7UPgi+CP7nfedBROgRNL7BotERPzf/N8YRESL+wbSRPjf/N8Y0kT3B4vR0vjf+N8YPvkGFZWBfpB+G31/hoGBH/zS/NP7kPeQBZWCfpB9G35+hoGCH/sN+wx4eItrnncZ+Cv8LJODloaWihmKjY2LjRvpChNgiweZmJGUlR/5bvlunp+Lq3ifGQ77FPe0+tT3NAGL9zT4tPcU+LT3NBQ4+VT3VPcuCvx0rx36lFoK+HRaHf6UB/k0+BT3Lgr8dK8d+RRaCvh0Wh39FAf3NPmUpgr8f/mU95QBi3cKA3cK+HQVnoWegZoe+5T4FAXGY027QRv8FAZBTVtQYx/7lPwUBYF8hXh4GkwKq6mbpp0e93f36QW4+xgG+4v8LwWFgYiAf/cvHfdU+6QGTb5ZyB73NAbJvb3JH/ek91QHPQqXiJaFlR/7i/gvBfcYuAf3d/vpBXCdqXurGzsd/DT5tMQd/X/5lPeUAYv3VMv3dMv3dMv3VAP6lPnU9zgdHv0UBrgdH/w0B0wKRh0e9/TL/iQH9wgK+GTL/GQH9wgK+iTL+/QHTApGHR77tPn0xB1KCvmZ934V+/H4bXCwa/cL8M4Z4sPdYLZZCHmbpnW/G7+noZ2bH7a93bbhU/FIa/sLcGYI+DFIFSAKoPuUHAb/+9P30xL3eOd+HecTsBwFwPkUFfvS+5b7lvvS+9L7lveW99L30veW95b30vfS95b7lvvSHveo+6kVjpWKloWT+0j3jBj3SPeMkZSMlYiVGYiVg5KCjvu46xj3xgeVhpWDkR6CkYGNgYf7uC0Y+0j3jH+bb4t/exn7SPuM+7jpgY+BiYKFGYOFhoGBGvvGB/u4K4KIg4SIgRmIgYyBkYL3SPuMGPtI+4yFg4qAjoEZjoGThJSI97grGPvGB4GQgZOFHpSFlYmVj/e46Rj3SPuMBYORlYaVG5WVkJORH/dI94z3uC2Vh5WNlJEZk5GQlZUa98YH97jrBRNwlI6Tko6VCA50Hfd0VR339PcUAxwE7vd9Ffsl+wz7STP7VRv79fuz97P39fe291L3iPee2h9IIWb7EPsTGvwH98H7wfgHsLCOka8e91/gFZajhqh4nnieb5BygAhpQj96PBulHfeI98D3Lsr3IvcG8x+enZKogKSBo3Sbb4oI/DJ8+9n75fwzGvciHfe+96b3Q/ej9xEeDqD5lPdUAcuQCgP61PlUFVUK+5QGaG6orioK95RkHfjU9x0KHPqAKh3+VCgKch0nHcscBYBJHRz6ACod+5QoClYKQR0goHafCveU9xT3FPfUAascBkADHAZg+NRJHft0BvcUi+/NGvdB90H3Dx0Z9w0K+0H7QRj94Ab7QfdB9w0KGXJyi2OkcvdB+0EYSYsn+xQa+3T1Cvd0BvsIojKuRh77Xvt3dHCNY6VzGYCYmoaaG52ckpmYH/dL92MFi/cY+xj3SR73MQr+FAf3PvcX9wyLH/da+1kF9ywd9w8d+2T3ZRiz0qbp9xEa93QnHfx0+NQV90X7I/cj+0X7Rfsj+yP7RR75FAYO9ymhdvqLqIOSEhwHb5oT0BwHffqMFYt9szSAHvu0iQV1jnuCixqLeoKDdR5c+w1PI4sa+xT7bld/dpkIWqqY6s8a92ir4yyiHmySdJA6jCSMNIpac2p7cmeaiZ6ItoKibAiLpGKPMR6W+41YbIsaZHZHrif3YgiLUfFe9wQeg6B7losai3mZcY8eE7D7pokFYXx4i4t8e5lqH/dq/Iv3iPuQixqL93P7ffeRmx6L9wcHro6dnosai5udiqweifcu06KLGtGh5fs/60kIi9RZwpYe95SPBfcbjEv3BIsahpRr0Psu9yMIE9D7NPcpoHP3VveW9wr3MbrrfLQIDqA18dT3AvdH92P3Jfcx+wD3Qfeo9x0S+CDs91iW1fdS+Gb3CvX3HhP34Pk395AVbl1Nd12gXqB9wKi4p7fHn7h4uneaVm9dCOn3DRWBeXSDeZJ5k4aelZ2VnKGTnYWdhJF3gXkI90IgFcf3GkH3Hvsnsfshr/szRU37EE37E8f7IfcjXQgTCID3KFv3QtXH9xwI98z3NBWe+1f7dPtJ+71tCBOQQPu9bvuU9xp491d491f3dPdJ972p972o95T7Gp77Vwj3yIcV9xz7Btgkqx5yk3qQmKyn047JbLdR3vszh/tKPgiMUnGZuR6n5YfXX7Yo7vubJft2+3YIE/fg+z37PSn7R/svGvu9+BD7SPgI+Hv32Pev93UeQfkEFVLLNqM9eggTCEBrhHdskmuRa6t3q5IIE/fgiwexk7R/p2ynbJNhf2UIiweBbJxqqoGqgayclaqk13viUsoI90n3NxX7CvcX+0G8+zVpCIsHZoNzZ5Nmk2awc7CT9waj9w9o3y7fL6H7E2f7AwiLB4Bnn2Wvf69/sZ+XrwjpCr33MGz3RvsK9xYIDvcp6/rMAfkO91j3mfdXA/m59zehHfuVYPtY+3T7oRr7Grz7D9stHvdS5/ca92T3hxr4jfczFTrr+wbO+xWhCPvpB4sH+4j3Gftm91MvHjvpW/cP9xoa9xq79w7b6h75PP3QoR37FXX7CUg5KwjcLL/7DvsaGvsaV/sPOi33Qx33U+f3Hfdk94ca+Q77VBX3oftY93T7lbYe++kHiwf7iPca+2b3Ui8e3Om79w/3GhoOoA6gDqAOcKYcBUCmBvcUCvcUC/cU9xQMDPcU9xQMDRwGABQcBusVrhMBIwIAAQANABEAQABHAFIAcAB3AL0AwQDKAM4A0gDWAN0A4wDnAOsBDQESATIBOQFHAUsBUAF6AYMBiAGNAZgBnQGiAb0BwwHHAd8B5gJYAmACfwKDAroC4QLoAy0DMgM2AzoDPgNaA2EDbQOxA7gDvAPAA8YDywPQA9QD3QPhA+4D+AP9BB4EJwQrBC8EOARBBGsEcwR5BJYEmwSfBKgEtwS7BMMEygTbBOQE6wUQBRgFIAUkBSkFOAU9BXMFeAWCBYYFmQWfBaYFsQW5Bb0FwwXJBc0F4wX2BfwGAQYIBgwGEAYUBhgGHQYjBigGLQZMBlIGWQZdBmIGagZ1BnkGgAaFBooGjga0BrwGwQbGBuoG9gcEBw8HHQc+B0IHSQdQB1YHWwdrB40HkAeiB7QHwQfKB9AH1QfZB/kICggcCDsIWghiCG0Idwh8CIMIjgidCK4IugjUCNsI8AkJCRAJFwkdCSgJNglDCVEJVglcCWQJcgmCCZgJqAm+CcgJzwnVCdoJ4QnlCfoKDwojCjcKPgpHCk8KVwpcCm8KggqVCqYKrAqzCroKwQrICtEK1wrdCuEK5gruCvgLAQsECwsLEQsaCyQLKgsyCzYLPAtDC0gLTwtWC1wLYQtwC3wLiwuZC6MLqAu1C7sLyQvPC9QL3QvkC+oL8wv8DAUMCwwRDBYMGwwgDCgMLQw6DEcMSwxPDFYMWwxgDGoMdgyCDIoMkAyVDJsMoAylDKoMrwy1DMAMxAzJDNAM1QzbDOAM5gzxDPwNAQ0GDQsND4kK+Dz37Pfs+DweDhUhHQuiHRwFYFwKHPqgoAp+f4N/hh+Gf45+lIH31PvUGIWSk4iTG5OTjpGSH/fT99MFC4QK+1QyCgtACvvUIwr31DYKCzQK+ZT8VDEK+JT7VDQK95TLFS4KSwZfCktEHcsGCyod+xQoCgsV0lLERJcdxFLSdx0e+JQW0lLERJcdxFLSdx0e9xIKFfv1+7P7s/v1+/X7s/ez9/X39fez97P39ff197P7s/v1HvcUFiAKBysKC/g8++z37Pw8Cz0KHwsvCh4LNwofCwd5mX2dHgucfJp6HgtPCq4LNh0fCxWcfJp6HksGenx8eh9LB3qafJweywacmpqcH/uU99Q0CgsHTAoeC48d/Gb8ZsMK+B34Hfgd/B0FhZGUh5MblJO4Cr29WR0LPB331CEKCxWXHVLE0ncd0sRSRB4LBjsdC5yampwLFffA94i5HaUduR1LHR/5lPy0FSkKHosH/Dz77Pvs/Dz8PPfs++z4PModnX2Z1Ap9eR8LnZmZnQuubqhoC0AK+1QjCvdUNgoLrqiorgtZCpwKCwb7M/sV+xX7Mx/91CYd+dQG9zP3FfcV9zMfC8BgtlYeCwZFHQuFkR5ZvTkd/Gb8Zi8d+Gb8Zjcdvb1ZHQv3IfcHlR0LyxqL+2pdXvcdHoto5FmiHotFu9aKHovXhbVCHs77CvcErbefkr2frKGfCPs/nvtHzfe6Gt+p0LzAHoOfcdm09QjMn/cnKIsanMjNlMwbzM2Cesgfi/cn7st3HrUhcT2Ddwi8VqlGNxr7u/tISvs/eB4LPQoe9xRkHQv5lBwEoBWSCvvh++EF+5oqHfwUKAr3mgb34fvhfAoLBjAKC3R6dXiCH/t1/Fv8ikIFcodsf20aeZh6l34e+AD79jX8iAWKhIqFhBpxmHOomZiQkpge+FX3gAsVaG5uaB77FAZobqiuH/cUB66oqK4e9xQGrqhuaB/7FAf4FARnCgtKHRwGAAMLmR33VAGL91QD+FT61DUK+r/81PcLCv1f+V4Fvlgqs0Qb/DQGRVFRRR/8NAdEsyq+WR75X/1gBXSidQqiox/4f/iAogoLVrZgwAsVJR0LBiwKC2iobgtJHf4ULh2eHR/4VPxUYgqcm5KXlx/4VPhUdR0LoItHHQGLCzMdHPqAJgpyHScdCxX3RvsP9y/7QrQeprSZu7z3CR1OUHVjXR73VDz7T/cS+2Qbtgp9jH2MfB/7MUIm+zL7Qhr7i/dd+133ix761AZ2HR8OTgr41HAdCyQdHgscBgALXB12igoL9yFDCgtVCvsUC2sKHgv4aov4afhoGgsHOQoLLB1LRwr81C0KyzEdC/ceHQGL9y4dAwv3Sh0fC/mU90sK/Dz77Pvs/Dz8PPfs++z4PPg89+z37Pg8KQofC/sUrQoBi/d0CwVwCgsVZAoLJR34lPwUTQoLNx34ZvhmWR0L9zgdHvwUBrgdH/wUByHhNfUe93TzHWsHgwoeSyYKywb3rvd693r3rh8LKR34FAQpHQv3FAc9CgsV92j7QPdA+2j7aPtA+0D7aPto90D7QPdodh0eC3qafJwLBzoKCzod+RT71DodC8gd/TqbHXIdmgr9OoAdCwdyCgsFl397knobC3+Xm4ScGwszHRz5gCod+5QoChwGgCcdCzNDQ/ckCqgKCwcz00PjHgsV3Ar8ZvhmGPIdWVkYzh34HfwdGPdICs4dGb1Z8QoZ+Gb4ZgULrH2tG62smQv3IfcwCvshCxwFAAtaHaAKCy4K/lQGXwpLRB36VE4KC5OHowoL9037pPtZ+7cF+xT7O/eWBvcv946Vm5SbkZcZjpKPko2SCI4GjYSOhJGEo2EY9zP7kAX3jAYLYgoqCgsFf3+Ee3r3Lx0LhwoeC36Xm4WcG5OUjY6TH6KVm6KlGgstCrcdHwuECvvUMgoL95T3FPeU9xT3lAv7IfsH9xgKCwY9HQvjQ9MzHgt6fJqcHwsViQoLB7UK/JT8lBhycotjpHL4lPyUGH8KCykK/Dz77Pvs/Dz8PPfs++z4PAt2i3ZPHQsGpAofC/eUAYv3lAtLLQoLi5EKCxwHAAscBoAL9xSaHQs7CpYKHgv3FAeuC+PT0+ML+xj7lAckHS8KH/kU9z8K+5T3GAb3tKv3dPeI97waC3p7hH9/C3oKWb05HQv7VAYLQB33FAsHMx37FCodC/eQ+5BWCvuQ95ALBmYdC5yEm3+XHgv7FPeUC/iU9xQL+1QHCxWgywWdkZ6ZnBv49AadlX15hR92SwV5hXh9ehv89AZ5gZmdkR8LBaKimaytGguUhZEeC9HFxdEL3BwFfxU6igWLbYt/i1+L+yuLYyEMJZOAnnyoeQiTopynlB8LSR0c+oAqHRz6gPQKBX+XhZucGpyRm5eXHgszQ9PjH/nU9w4dCwWdeXKVchtycoF5eR8LspCykq+V90G39zDd9xf3CAiGuryIvBv4g/gl97L39h8OFV4dC3Nzzgpqowv3dPrU93QLAYuPCgMLqK6uqAsVVQr9lJwK+JT3Fh38lAcLiXSHeIV9cnxHekl5ZIBxe311CIIHjHEFhYyCjIAelqKMCzEdDmMd/VSvHctaCvlUWh1LB/eUC7dnr19fZ2dfX69nt7evr7ceC6V7onSVHnOVb4Z5eAv7r/t5+3n7rwv3FAc7CguPkZEfC/fUBguXlYyNkx+Rj4yPG4gHgIKGhoOBg38Z/AX8pQUx+NwHCwOPCvkUFZ0K+5T3lH0d+xQLBaJ01R10cx9BQAWsCnQe+R8L/VQG+xAnJ/sQH/1UB/sP7yb3EB75VAb3EO/w9w8fC/nk+zQVgoSEgio82uyUkpKUlJKEgjzMStqUkoSCHguAHRz6QOcKDi4K+1QoHfdUTgoLQwr3IfcH9xgKC4AK+BQLLx29WTcdCwb3M/cV9xX3Mx8OoHQdi/cUnx3mHRKL9xQLoPuU95T3Kgr3JQr4FPfUAwv9Wv1ahYWHhYiEGQv7CSws+wn7CSzq9wn3Cerq9wn3Ceos+wkeCzIK+lQ2Cgt5nm+QdIEZc4F7dHEa/FQoCvhUBgunfQV0ucB/xhv3Lvcr3a3LH5KPkY6PjQgL9xT4FFUdC6Ryi2Nycgt99zodmQv3HR37dPd0B18dC3h5hm+VdBlzlaJ7pRsLBZeXm5L3PB2Ef5cfCwV5naSBpBukpJWdnR8L+JRJHQv3Eh15fQv3Dybw+w8eC/ctHSkK/Dz77Pvs/DwLFZ19mXmWHQd5mX2dOgoeC5KTk5SRlBn4BfimBeT8y/t59wz3BwsV93QHLgr71AZfCvt0/BQL1GX3CzExZfsLQkKx+wvl5bH3C9QeCwHAHAYWAxwGSwuYmIuffpgLmfdLHX0L9wEdAwuRko+TlBoLFUAKCxVTVGRKLF3I09W3xNHbzjQ5Hvz2C2Eecnd3dnly9C8YlpiXmZiWCKCkC1z7O0NPTER8eXp8kHIIi4uLihoL+zQGgoSSlJSSkpQf9zQGlJKEggv3Hh1LdxILIDgcBjP3EQoLB2ifgqSkHgsHrneUcnIeC/coCh4Lw/sH+xzI+zsb+2b7dvsRZUsfCxVFBvt6+SoF+zYG+3r9KgVFIQuL9xSL9xSL9xSL9xSL9xSL9xQLB/sh+yT7B/tE+0T7JJUdHgv3Ah33FAv7IaQd9yEL9xT3FJ8dC5h+n4uYmAv7FRwGAgEL3h1yHfm04AoLKApyHUEdLh0vCh8LFS0dC/c6CpkLA7j7BxXIHQv3i/td9133PAoLMR37VPlUQh0LiwoOHAVzFccKC/ccHTDmCxWFChz5wHsdC029WcnJvb3JHguFHRwGQAv3tPfU+7QHCxXNHQv3FPcmCgtypGOLcnILdB33FAsGeX18eh8LBpyafHofCwGLkAoDC/eU+5QLl5uVnJOeCJ+N9xWZmhoLB+kd+xQGRVFRRR8Lk5GWkh+WnJSdl5wI1sEL9xT3FPcU9zsd9xT3FAv3NPf09x8d9xQL+wf7IQsS9xT3FMv3FJkd9xQLQh1LRwoLmZwa9xQHlI+TkZEekQtvCpYKHwv3VEkdCwf7D/Am9w8eC/w0ByQdaAuL9xTqHQv7RPsk+yT7RAsG9w/w8PcPHwv3RPck9yT3RAszHv3UBgsB95T3lAv5FPcUC/iU95QLi4uLiwv3IAoBi/cUC/eUkx0LcXR7dIEfgXOQb555C5D2y5KXH46NjI2OGgsHPR0LFWMdC/cU+TT3FAv7B/cHC/oU9xQLHo6Dgo2CGyQdCxuLB/cG9wS7ttsfCxX7DfsL+4wGf4KLCwWdjJuZnBsL+9QHJB0LFfcQHQv91Af7MwscBcAGC/dUBp0LoHYBiwv7i4MdCx6ZHU4KCxv7uVb77/t2+zYLBtwdCwZDCh8LwB75VPMdC/cJCgYL9xT3IB0L9xTwCgv3FAHnHQv7X/cY+0n3YvsJC3KBc3l5Hvsn+yYL/B38HQv7lPcUCxz7QAYLch0VCwAA') format('truetype');font-weight:normal;font-style:normal}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em}[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none}.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em}a [class^="icon-"],a [class*=" icon-"]{display:inline}[class^="icon-"].icon-fixed-width,[class*=" icon-"].icon-fixed-width{display:inline-block;width:1.1428571428571428em;text-align:right;padding-right:.2857142857142857em}[class^="icon-"].icon-fixed-width.icon-large,[class*=" icon-"].icon-fixed-width.icon-large{width:1.4285714285714286em}.icons-ul{margin-left:2.142857142857143em;list-style-type:none}.icons-ul>li{position:relative}.icons-ul .icon-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;text-align:center;line-height:inherit}[class^="icon-"].hide,[class*=" icon-"].hide{display:none}.icon-muted{color:#eee}.icon-light{color:#fff}.icon-dark{color:#333}.icon-border{border:solid 1px #eee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.icon-2x{font-size:2em}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.icon-3x{font-size:3em}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.icon-4x{font-size:4em}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.icon-5x{font-size:5em}.icon-5x.icon-border{border-width:5px;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.pull-right{float:right}.pull-left{float:left}[class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em}[class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em}[class^="icon-"],[class*=" icon-"]{display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none}.btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em}.btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block}.nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em}.btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em}.btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em}.btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em}.btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em}.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{line-height:inherit}.icon-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:-35%}.icon-stack [class^="icon-"],.icon-stack [class*=" icon-"]{display:block;text-align:center;position:absolute;width:100%;height:100%;font-size:1em;line-height:inherit;*line-height:2em}.icon-stack .icon-stack-base{font-size:2em;*line-height:1em}.icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}a .icon-stack,a .icon-spin{display:inline-block;text-decoration:none}@-moz-keyframes spin{0{-moz-transform:rotate(0)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0{-o-transform:rotate(0)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0{-ms-transform:rotate(0)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0{transform:rotate(0)}100%{transform:rotate(359deg)}}.icon-rotate-90:before{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1)}.icon-rotate-180:before{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2)}.icon-rotate-270:before{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3)}.icon-flip-horizontal:before{-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.icon-flip-vertical:before{-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}a .icon-rotate-90:before,a .icon-rotate-180:before,a .icon-rotate-270:before,a .icon-flip-horizontal:before,a .icon-flip-vertical:before{display:inline-block}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope-alt:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-power-off:before,.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-gear:before,.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file-alt:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-rotate-right:before,.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-mail-forward:before,.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-gears:before,.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up-alt:before{content:"\f087"}.icon-thumbs-down-alt:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-unchecked:before,.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paperclip:before,.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-rotate-left:before,.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-lightbulb:before{content:"\f0eb"}.icon-exchange:before{content:"\f0ec"}.icon-cloud-download:before{content:"\f0ed"}.icon-cloud-upload:before{content:"\f0ee"}.icon-user-md:before{content:"\f0f0"}.icon-stethoscope:before{content:"\f0f1"}.icon-suitcase:before{content:"\f0f2"}.icon-bell-alt:before{content:"\f0f3"}.icon-coffee:before{content:"\f0f4"}.icon-food:before{content:"\f0f5"}.icon-file-text-alt:before{content:"\f0f6"}.icon-building:before{content:"\f0f7"}.icon-hospital:before{content:"\f0f8"}.icon-ambulance:before{content:"\f0f9"}.icon-medkit:before{content:"\f0fa"}.icon-fighter-jet:before{content:"\f0fb"}.icon-beer:before{content:"\f0fc"}.icon-h-sign:before{content:"\f0fd"}.icon-plus-sign-alt:before{content:"\f0fe"}.icon-double-angle-left:before{content:"\f100"}.icon-double-angle-right:before{content:"\f101"}.icon-double-angle-up:before{content:"\f102"}.icon-double-angle-down:before{content:"\f103"}.icon-angle-left:before{content:"\f104"}.icon-angle-right:before{content:"\f105"}.icon-angle-up:before{content:"\f106"}.icon-angle-down:before{content:"\f107"}.icon-desktop:before{content:"\f108"}.icon-laptop:before{content:"\f109"}.icon-tablet:before{content:"\f10a"}.icon-mobile-phone:before{content:"\f10b"}.icon-circle-blank:before{content:"\f10c"}.icon-quote-left:before{content:"\f10d"}.icon-quote-right:before{content:"\f10e"}.icon-spinner:before{content:"\f110"}.icon-circle:before{content:"\f111"}.icon-mail-reply:before,.icon-reply:before{content:"\f112"}.icon-github-alt:before{content:"\f113"}.icon-folder-close-alt:before{content:"\f114"}.icon-folder-open-alt:before{content:"\f115"}.icon-expand-alt:before{content:"\f116"}.icon-collapse-alt:before{content:"\f117"}.icon-smile:before{content:"\f118"}.icon-frown:before{content:"\f119"}.icon-meh:before{content:"\f11a"}.icon-gamepad:before{content:"\f11b"}.icon-keyboard:before{content:"\f11c"}.icon-flag-alt:before{content:"\f11d"}.icon-flag-checkered:before{content:"\f11e"}.icon-terminal:before{content:"\f120"}.icon-code:before{content:"\f121"}.icon-reply-all:before{content:"\f122"}.icon-mail-reply-all:before{content:"\f122"}.icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123"}.icon-location-arrow:before{content:"\f124"}.icon-crop:before{content:"\f125"}.icon-code-fork:before{content:"\f126"}.icon-unlink:before{content:"\f127"}.icon-question:before{content:"\f128"}.icon-info:before{content:"\f129"}.icon-exclamation:before{content:"\f12a"}.icon-superscript:before{content:"\f12b"}.icon-subscript:before{content:"\f12c"}.icon-eraser:before{content:"\f12d"}.icon-puzzle-piece:before{content:"\f12e"}.icon-microphone:before{content:"\f130"}.icon-microphone-off:before{content:"\f131"}.icon-shield:before{content:"\f132"}.icon-calendar-empty:before{content:"\f133"}.icon-fire-extinguisher:before{content:"\f134"}.icon-rocket:before{content:"\f135"}.icon-maxcdn:before{content:"\f136"}.icon-chevron-sign-left:before{content:"\f137"}.icon-chevron-sign-right:before{content:"\f138"}.icon-chevron-sign-up:before{content:"\f139"}.icon-chevron-sign-down:before{content:"\f13a"}.icon-html5:before{content:"\f13b"}.icon-css3:before{content:"\f13c"}.icon-anchor:before{content:"\f13d"}.icon-unlock-alt:before{content:"\f13e"}.icon-bullseye:before{content:"\f140"}.icon-ellipsis-horizontal:before{content:"\f141"}.icon-ellipsis-vertical:before{content:"\f142"}.icon-rss-sign:before{content:"\f143"}.icon-play-sign:before{content:"\f144"}.icon-ticket:before{content:"\f145"}.icon-minus-sign-alt:before{content:"\f146"}.icon-check-minus:before{content:"\f147"}.icon-level-up:before{content:"\f148"}.icon-level-down:before{content:"\f149"}.icon-check-sign:before{content:"\f14a"}.icon-edit-sign:before{content:"\f14b"}.icon-external-link-sign:before{content:"\f14c"}.icon-share-sign:before{content:"\f14d"}.icon-compass:before{content:"\f14e"}.icon-collapse:before{content:"\f150"}.icon-collapse-top:before{content:"\f151"}.icon-expand:before{content:"\f152"}.icon-euro:before,.icon-eur:before{content:"\f153"}.icon-gbp:before{content:"\f154"}.icon-dollar:before,.icon-usd:before{content:"\f155"}.icon-rupee:before,.icon-inr:before{content:"\f156"}.icon-yen:before,.icon-jpy:before{content:"\f157"}.icon-renminbi:before,.icon-cny:before{content:"\f158"}.icon-won:before,.icon-krw:before{content:"\f159"}.icon-bitcoin:before,.icon-btc:before{content:"\f15a"}.icon-file:before{content:"\f15b"}.icon-file-text:before{content:"\f15c"}.icon-sort-by-alphabet:before{content:"\f15d"}.icon-sort-by-alphabet-alt:before{content:"\f15e"}.icon-sort-by-attributes:before{content:"\f160"}.icon-sort-by-attributes-alt:before{content:"\f161"}.icon-sort-by-order:before{content:"\f162"}.icon-sort-by-order-alt:before{content:"\f163"}.icon-thumbs-up:before{content:"\f164"}.icon-thumbs-down:before{content:"\f165"}.icon-youtube-sign:before{content:"\f166"}.icon-youtube:before{content:"\f167"}.icon-xing:before{content:"\f168"}.icon-xing-sign:before{content:"\f169"}.icon-youtube-play:before{content:"\f16a"}.icon-dropbox:before{content:"\f16b"}.icon-stackexchange:before{content:"\f16c"}.icon-instagram:before{content:"\f16d"}.icon-flickr:before{content:"\f16e"}.icon-adn:before{content:"\f170"}.icon-bitbucket:before{content:"\f171"}.icon-bitbucket-sign:before{content:"\f172"}.icon-tumblr:before{content:"\f173"}.icon-tumblr-sign:before{content:"\f174"}.icon-long-arrow-down:before{content:"\f175"}.icon-long-arrow-up:before{content:"\f176"}.icon-long-arrow-left:before{content:"\f177"}.icon-long-arrow-right:before{content:"\f178"}.icon-apple:before{content:"\f179"}.icon-windows:before{content:"\f17a"}.icon-android:before{content:"\f17b"}.icon-linux:before{content:"\f17c"}.icon-dribbble:before{content:"\f17d"}.icon-skype:before{content:"\f17e"}.icon-foursquare:before{content:"\f180"}.icon-trello:before{content:"\f181"}.icon-female:before{content:"\f182"}.icon-male:before{content:"\f183"}.icon-gittip:before{content:"\f184"}.icon-sun:before{content:"\f185"}.icon-moon:before{content:"\f186"}.icon-archive:before{content:"\f187"}.icon-bug:before{content:"\f188"}.icon-vk:before{content:"\f189"}.icon-weibo:before{content:"\f18a"}.icon-renren:before{content:"\f18b"}
WRFILE: bootstrap.min.js

/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under the MIT license
 */
if(typeof jQuery==="undefined"){throw new Error("Bootstrap's JavaScript requires jQuery")}+function(b){var a=b.fn.jquery.split(" ")[0].split(".");if((a[0]<2&&a[1]<9)||(a[0]==1&&a[1]==9&&a[2]<1)||(a[0]>3)){throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}}(jQuery);+function(b){function a(){var e=document.createElement("bootstrap");var d={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in d){if(e.style[c]!==undefined){return{end:d[c]}}}return false}b.fn.emulateTransitionEnd=function(e){var d=false;var c=this;b(this).one("bsTransitionEnd",function(){d=true});var f=function(){if(!d){b(c).trigger(b.support.transition.end)}};setTimeout(f,e);return this};b(function(){b.support.transition=a();if(!b.support.transition){return}b.event.special.bsTransitionEnd={bindType:b.support.transition.end,delegateType:b.support.transition.end,handle:function(c){if(b(c.target).is(this)){return c.handleObj.handler.apply(this,arguments)}}}})}(jQuery);+function(e){var d='[data-dismiss="alert"]';var b=function(f){e(f).on("click",d,this.close)};b.VERSION="3.3.7";b.TRANSITION_DURATION=150;b.prototype.close=function(j){var i=e(this);var g=i.attr("data-target");if(!g){g=i.attr("href");g=g&&g.replace(/.*(?=#[^\s]*$)/,"")}var h=e(g==="#"?[]:g);if(j){j.preventDefault()}if(!h.length){h=i.closest(".alert")}h.trigger(j=e.Event("close.bs.alert"));if(j.isDefaultPrevented()){return}h.removeClass("in");function f(){h.detach().trigger("closed.bs.alert").remove()}e.support.transition&&h.hasClass("fade")?h.one("bsTransitionEnd",f).emulateTransitionEnd(b.TRANSITION_DURATION):f()};function c(f){return this.each(function(){var h=e(this);var g=h.data("bs.alert");if(!g){h.data("bs.alert",(g=new b(this)))}if(typeof f=="string"){g[f].call(h)}})}var a=e.fn.alert;e.fn.alert=c;e.fn.alert.Constructor=b;e.fn.alert.noConflict=function(){e.fn.alert=a;return this};e(document).on("click.bs.alert.data-api",d,b.prototype.close)}(jQuery);+function(d){var b=function(f,e){this.$element=d(f);this.options=d.extend({},b.DEFAULTS,e);this.isLoading=false};b.VERSION="3.3.7";b.DEFAULTS={loadingText:"loading..."};b.prototype.setState=function(g){var i="disabled";var e=this.$element;var h=e.is("input")?"val":"html";var f=e.data();g+="Text";if(f.resetText==null){e.data("resetText",e[h]())}setTimeout(d.proxy(function(){e[h](f[g]==null?this.options[g]:f[g]);if(g=="loadingText"){this.isLoading=true;e.addClass(i).attr(i,i).prop(i,true)}else{if(this.isLoading){this.isLoading=false;e.removeClass(i).removeAttr(i).prop(i,false)}}},this),0)};b.prototype.toggle=function(){var f=true;var e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var g=this.$element.find("input");if(g.prop("type")=="radio"){if(g.prop("checked")){f=false}e.find(".active").removeClass("active");this.$element.addClass("active")}else{if(g.prop("type")=="checkbox"){if((g.prop("checked"))!==this.$element.hasClass("active")){f=false}this.$element.toggleClass("active")}}g.prop("checked",this.$element.hasClass("active"));if(f){g.trigger("change")}}else{this.$element.attr("aria-pressed",!this.$element.hasClass("active"));this.$element.toggleClass("active")}};function c(e){return this.each(function(){var h=d(this);var g=h.data("bs.button");var f=typeof e=="object"&&e;if(!g){h.data("bs.button",(g=new b(this,f)))}if(e=="toggle"){g.toggle()}else{if(e){g.setState(e)}}})}var a=d.fn.button;d.fn.button=c;d.fn.button.Constructor=b;d.fn.button.noConflict=function(){d.fn.button=a;return this};d(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(g){var f=d(g.target).closest(".btn");c.call(f,"toggle");if(!(d(g.target).is('input[type="radio"], input[type="checkbox"]'))){g.preventDefault();if(f.is("input,button")){f.trigger("focus")}else{f.find("input:visible,button:visible").first().trigger("focus")}}}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(f){d(f.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(f.type))})}(jQuery);+function(c){var d=function(g,f){this.$element=c(g);this.$indicators=this.$element.find(".carousel-indicators");this.options=f;this.paused=null;this.sliding=null;this.interval=null;this.$active=null;this.$items=null;this.options.keyboard&&this.$element.on("keydown.bs.carousel",c.proxy(this.keydown,this));this.options.pause=="hover"&&!("ontouchstart" in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",c.proxy(this.pause,this)).on("mouseleave.bs.carousel",c.proxy(this.cycle,this))};d.VERSION="3.3.7";d.TRANSITION_DURATION=600;d.DEFAULTS={interval:5000,pause:"hover",wrap:true,keyboard:true};d.prototype.keydown=function(f){if(/input|textarea/i.test(f.target.tagName)){return}switch(f.which){case 37:this.prev();break;case 39:this.next();break;default:return}f.preventDefault()};d.prototype.cycle=function(f){f||(this.paused=false);this.interval&&clearInterval(this.interval);this.options.interval&&!this.paused&&(this.interval=setInterval(c.proxy(this.next,this),this.options.interval));return this};d.prototype.getItemIndex=function(f){this.$items=f.parent().children(".item");return this.$items.index(f||this.$active)};d.prototype.getItemForDirection=function(j,i){var f=this.getItemIndex(i);var g=(j=="prev"&&f===0)||(j=="next"&&f==(this.$items.length-1));if(g&&!this.options.wrap){return i}var k=j=="prev"?-1:1;var h=(f+k)%this.$items.length;return this.$items.eq(h)};d.prototype.to=function(h){var g=this;var f=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(h>(this.$items.length-1)||h<0){return}if(this.sliding){return this.$element.one("slid.bs.carousel",function(){g.to(h)})}if(f==h){return this.pause().cycle()}return this.slide(h>f?"next":"prev",this.$items.eq(h))};d.prototype.pause=function(f){f||(this.paused=true);if(this.$element.find(".next, .prev").length&&c.support.transition){this.$element.trigger(c.support.transition.end);this.cycle(true)}this.interval=clearInterval(this.interval);return this};d.prototype.next=function(){if(this.sliding){return}return this.slide("next")};d.prototype.prev=function(){if(this.sliding){return}return this.slide("prev")};d.prototype.slide=function(m,i){var p=this.$element.find(".item.active");var g=i||this.getItemForDirection(m,p);var k=this.interval;var n=m=="next"?"left":"right";var j=this;if(g.hasClass("active")){return(this.sliding=false)}var l=g[0];var f=c.Event("slide.bs.carousel",{relatedTarget:l,direction:n});this.$element.trigger(f);if(f.isDefaultPrevented()){return}this.sliding=true;k&&this.pause();if(this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=c(this.$indicators.children()[this.getItemIndex(g)]);h&&h.addClass("active")}var o=c.Event("slid.bs.carousel",{relatedTarget:l,direction:n});if(c.support.transition&&this.$element.hasClass("slide")){g.addClass(m);g[0].offsetWidth;p.addClass(n);g.addClass(n);p.one("bsTransitionEnd",function(){g.removeClass([m,n].join(" ")).addClass("active");p.removeClass(["active",n].join(" "));j.sliding=false;setTimeout(function(){j.$element.trigger(o)},0)}).emulateTransitionEnd(d.TRANSITION_DURATION)}else{p.removeClass("active");g.addClass("active");this.sliding=false;this.$element.trigger(o)}k&&this.cycle();return this};function b(f){return this.each(function(){var j=c(this);var i=j.data("bs.carousel");var g=c.extend({},d.DEFAULTS,j.data(),typeof f=="object"&&f);var h=typeof f=="string"?f:g.slide;if(!i){j.data("bs.carousel",(i=new d(this,g)))}if(typeof f=="number"){i.to(f)}else{if(h){i[h]()}else{if(g.interval){i.pause().cycle()}}}})}var a=c.fn.carousel;c.fn.carousel=b;c.fn.carousel.Constructor=d;c.fn.carousel.noConflict=function(){c.fn.carousel=a;return this};var e=function(k){var g;var j=c(this);var f=c(j.attr("data-target")||(g=j.attr("href"))&&g.replace(/.*(?=#[^\s]+$)/,""));if(!f.hasClass("carousel")){return}var h=c.extend({},f.data(),j.data());var i=j.attr("data-slide-to");if(i){h.interval=false}b.call(f,h);if(i){f.data("bs.carousel").to(i)}k.preventDefault()};c(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e);c(window).on("load",function(){c('[data-ride="carousel"]').each(function(){var f=c(this);b.call(f,f.data())})})}(jQuery);+function(d){var e=function(g,f){this.$element=d(g);this.options=d.extend({},e.DEFAULTS,f);this.$trigger=d('[data-toggle="collapse"][href="#'+g.id+'"],[data-toggle="collapse"][data-target="#'+g.id+'"]');this.transitioning=null;if(this.options.parent){this.$parent=this.getParent()}else{this.addAriaAndCollapsedClass(this.$element,this.$trigger)}if(this.options.toggle){this.toggle()}};e.VERSION="3.3.7";e.TRANSITION_DURATION=350;e.DEFAULTS={toggle:true};e.prototype.dimension=function(){var f=this.$element.hasClass("width");return f?"width":"height"};e.prototype.show=function(){if(this.transitioning||this.$element.hasClass("in")){return}var h;var j=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(j&&j.length){h=j.data("bs.collapse");if(h&&h.transitioning){return}}var g=d.Event("show.bs.collapse");this.$element.trigger(g);if(g.isDefaultPrevented()){return}if(j&&j.length){b.call(j,"hide");h||j.data("bs.collapse",null)}var k=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[k](0).attr("aria-expanded",true);this.$trigger.removeClass("collapsed").attr("aria-expanded",true);this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[k]("");this.transitioning=0;this.$element.trigger("shown.bs.collapse")};if(!d.support.transition){return f.call(this)}var i=d.camelCase(["scroll",k].join("-"));this.$element.one("bsTransitionEnd",d.proxy(f,this)).emulateTransitionEnd(e.TRANSITION_DURATION)[k](this.$element[0][i])};e.prototype.hide=function(){if(this.transitioning||!this.$element.hasClass("in")){return}var g=d.Event("hide.bs.collapse");this.$element.trigger(g);if(g.isDefaultPrevented()){return}var h=this.dimension();this.$element[h](this.$element[h]())[0].offsetHeight;this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",false);this.$trigger.addClass("collapsed").attr("aria-expanded",false);this.transitioning=1;var f=function(){this.transitioning=0;this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};if(!d.support.transition){return f.call(this)}this.$element[h](0).one("bsTransitionEnd",d.proxy(f,this)).emulateTransitionEnd(e.TRANSITION_DURATION)};e.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};e.prototype.getParent=function(){return d(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(d.proxy(function(h,g){var f=d(g);this.addAriaAndCollapsedClass(c(f),f)},this)).end()};e.prototype.addAriaAndCollapsedClass=function(g,f){var h=g.hasClass("in");g.attr("aria-expanded",h);f.toggleClass("collapsed",!h).attr("aria-expanded",h)};function c(f){var g;var h=f.attr("data-target")||(g=f.attr("href"))&&g.replace(/.*(?=#[^\s]+$)/,"");return d(h)}function b(f){return this.each(function(){var i=d(this);var h=i.data("bs.collapse");var g=d.extend({},e.DEFAULTS,i.data(),typeof f=="object"&&f);if(!h&&g.toggle&&/show|hide/.test(f)){g.toggle=false}if(!h){i.data("bs.collapse",(h=new e(this,g)))}if(typeof f=="string"){h[f]()}})}var a=d.fn.collapse;d.fn.collapse=b;d.fn.collapse.Constructor=e;d.fn.collapse.noConflict=function(){d.fn.collapse=a;return this};d(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(j){var i=d(this);if(!i.attr("data-target")){j.preventDefault()}var f=c(i);var h=f.data("bs.collapse");var g=h?"toggle":i.data();b.call(f,g)})}(jQuery);+function(h){var e=".dropdown-backdrop";var b='[data-toggle="dropdown"]';var a=function(i){h(i).on("click.bs.dropdown",this.toggle)};a.VERSION="3.3.7";function f(k){var i=k.attr("data-target");if(!i){i=k.attr("href");i=i&&/#[A-Za-z]/.test(i)&&i.replace(/.*(?=#[^\s]*$)/,"")}var j=i&&h(i);return j&&j.length?j:k.parent()}function d(i){if(i&&i.which===3){return}h(e).remove();h(b).each(function(){var l=h(this);var k=f(l);var j={relatedTarget:this};if(!k.hasClass("open")){return}if(i&&i.type=="click"&&/input|textarea/i.test(i.target.tagName)&&h.contains(k[0],i.target)){return}k.trigger(i=h.Event("hide.bs.dropdown",j));if(i.isDefaultPrevented()){return}l.attr("aria-expanded","false");k.removeClass("open").trigger(h.Event("hidden.bs.dropdown",j))})}a.prototype.toggle=function(m){var l=h(this);if(l.is(".disabled, :disabled")){return}var k=f(l);var j=k.hasClass("open");d();if(!j){if("ontouchstart" in document.documentElement&&!k.closest(".navbar-nav").length){h(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(h(this)).on("click",d)}var i={relatedTarget:this};k.trigger(m=h.Event("show.bs.dropdown",i));if(m.isDefaultPrevented()){return}l.trigger("focus").attr("aria-expanded","true");k.toggleClass("open").trigger(h.Event("shown.bs.dropdown",i))}return false};a.prototype.keydown=function(m){if(!/(38|40|27|32)/.test(m.which)||/input|textarea/i.test(m.target.tagName)){return}var l=h(this);m.preventDefault();m.stopPropagation();if(l.is(".disabled, :disabled")){return}var k=f(l);var j=k.hasClass("open");if(!j&&m.which!=27||j&&m.which==27){if(m.which==27){k.find(b).trigger("focus")}return l.trigger("click")}var n=" li:not(.disabled):visible a";var o=k.find(".dropdown-menu"+n);if(!o.length){return}var i=o.index(m.target);if(m.which==38&&i>0){i--}if(m.which==40&&i<o.length-1){i++}if(!~i){i=0}o.eq(i).trigger("focus")};function g(i){return this.each(function(){var k=h(this);var j=k.data("bs.dropdown");if(!j){k.data("bs.dropdown",(j=new a(this)))}if(typeof i=="string"){j[i].call(k)}})}var c=h.fn.dropdown;h.fn.dropdown=g;h.fn.dropdown.Constructor=a;h.fn.dropdown.noConflict=function(){h.fn.dropdown=c;return this};h(document).on("click.bs.dropdown.data-api",d).on("click.bs.dropdown.data-api",".dropdown form",function(i){i.stopPropagation()}).on("click.bs.dropdown.data-api",b,a.prototype.toggle).on("keydown.bs.dropdown.data-api",b,a.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",a.prototype.keydown)}(jQuery);+function(d){var b=function(f,e){this.options=e;this.$body=d(document.body);this.$element=d(f);this.$dialog=this.$element.find(".modal-dialog");this.$backdrop=null;this.isShown=null;this.originalBodyPad=null;this.scrollbarWidth=0;this.ignoreBackdropClick=false;if(this.options.remote){this.$element.find(".modal-content").load(this.options.remote,d.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))}};b.VERSION="3.3.7";b.TRANSITION_DURATION=300;b.BACKDROP_TRANSITION_DURATION=150;b.DEFAULTS={backdrop:true,keyboard:true,show:true};b.prototype.toggle=function(e){return this.isShown?this.hide():this.show(e)};b.prototype.show=function(h){var f=this;var g=d.Event("show.bs.modal",{relatedTarget:h});this.$element.trigger(g);if(this.isShown||g.isDefaultPrevented()){return}this.isShown=true;this.checkScrollbar();this.setScrollbar();this.$body.addClass("modal-open");this.escape();this.resize();this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',d.proxy(this.hide,this));this.$dialog.on("mousedown.dismiss.bs.modal",function(){f.$element.one("mouseup.dismiss.bs.modal",function(i){if(d(i.target).is(f.$element)){f.ignoreBackdropClick=true}})});this.backdrop(function(){var j=d.support.transition&&f.$element.hasClass("fade");if(!f.$element.parent().length){f.$element.appendTo(f.$body)}f.$element.show().scrollTop(0);f.adjustDialog();if(j){f.$element[0].offsetWidth}f.$element.addClass("in");f.enforceFocus();var i=d.Event("shown.bs.modal",{relatedTarget:h});j?f.$dialog.one("bsTransitionEnd",function(){f.$element.trigger("focus").trigger(i)}).emulateTransitionEnd(b.TRANSITION_DURATION):f.$element.trigger("focus").trigger(i)})};b.prototype.hide=function(f){if(f){f.preventDefault()}f=d.Event("hide.bs.modal");this.$element.trigger(f);if(!this.isShown||f.isDefaultPrevented()){return}this.isShown=false;this.escape();this.resize();d(document).off("focusin.bs.modal");this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal");this.$dialog.off("mousedown.dismiss.bs.modal");d.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",d.proxy(this.hideModal,this)).emulateTransitionEnd(b.TRANSITION_DURATION):this.hideModal()};b.prototype.enforceFocus=function(){d(document).off("focusin.bs.modal").on("focusin.bs.modal",d.proxy(function(f){if(document!==f.target&&this.$element[0]!==f.target&&!this.$element.has(f.target).length){this.$element.trigger("focus")}},this))};b.prototype.escape=function(){if(this.isShown&&this.options.keyboard){this.$element.on("keydown.dismiss.bs.modal",d.proxy(function(f){f.which==27&&this.hide()},this))}else{if(!this.isShown){this.$element.off("keydown.dismiss.bs.modal")}}};b.prototype.resize=function(){if(this.isShown){d(window).on("resize.bs.modal",d.proxy(this.handleUpdate,this))}else{d(window).off("resize.bs.modal")}};b.prototype.hideModal=function(){var e=this;this.$element.hide();this.backdrop(function(){e.$body.removeClass("modal-open");e.resetAdjustments();e.resetScrollbar();e.$element.trigger("hidden.bs.modal")})};b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove();this.$backdrop=null};b.prototype.backdrop=function(i){var h=this;var f=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=d.support.transition&&f;this.$backdrop=d(document.createElement("div")).addClass("modal-backdrop "+f).appendTo(this.$body);this.$element.on("click.dismiss.bs.modal",d.proxy(function(j){if(this.ignoreBackdropClick){this.ignoreBackdropClick=false;return}if(j.target!==j.currentTarget){return}this.options.backdrop=="static"?this.$element[0].focus():this.hide()},this));if(e){this.$backdrop[0].offsetWidth}this.$backdrop.addClass("in");if(!i){return}e?this.$backdrop.one("bsTransitionEnd",i).emulateTransitionEnd(b.BACKDROP_TRANSITION_DURATION):i()}else{if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){h.removeBackdrop();i&&i()};d.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(b.BACKDROP_TRANSITION_DURATION):g()}else{if(i){i()}}}};b.prototype.handleUpdate=function(){this.adjustDialog()};b.prototype.adjustDialog=function(){var e=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&e?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!e?this.scrollbarWidth:""})};b.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})};b.prototype.checkScrollbar=function(){var f=window.innerWidth;if(!f){var e=document.documentElement.getBoundingClientRect();f=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth<f;this.scrollbarWidth=this.measureScrollbar()};b.prototype.setScrollbar=function(){var e=parseInt((this.$body.css("padding-right")||0),10);this.originalBodyPad=document.body.style.paddingRight||"";if(this.bodyIsOverflowing){this.$body.css("padding-right",e+this.scrollbarWidth)}};b.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)};b.prototype.measureScrollbar=function(){var f=document.createElement("div");f.className="modal-scrollbar-measure";this.$body.append(f);var e=f.offsetWidth-f.clientWidth;this.$body[0].removeChild(f);return e};function c(e,f){return this.each(function(){var i=d(this);var h=i.data("bs.modal");var g=d.extend({},b.DEFAULTS,i.data(),typeof e=="object"&&e);if(!h){i.data("bs.modal",(h=new b(this,g)))}if(typeof e=="string"){h[e](f)}else{if(g.show){h.show(f)}}})}var a=d.fn.modal;d.fn.modal=c;d.fn.modal.Constructor=b;d.fn.modal.noConflict=function(){d.fn.modal=a;return this};d(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(j){var i=d(this);var g=i.attr("href");var f=d(i.attr("data-target")||(g&&g.replace(/.*(?=#[^\s]+$)/,"")));var h=f.data("bs.modal")?"toggle":d.extend({remote:!/#/.test(g)&&g},f.data(),i.data());if(i.is("a")){j.preventDefault()}f.one("show.bs.modal",function(e){if(e.isDefaultPrevented()){return}f.one("hidden.bs.modal",function(){i.is(":visible")&&i.trigger("focus")})});c.call(f,h,this)})}(jQuery);+function(d){var c=function(f,e){this.type=null;this.options=null;this.enabled=null;this.timeout=null;this.hoverState=null;this.$element=null;this.inState=null;this.init("tooltip",f,e)};c.VERSION="3.3.7";c.TRANSITION_DURATION=150;c.DEFAULTS={animation:true,placement:"top",selector:false,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:false,container:false,viewport:{selector:"body",padding:0}};c.prototype.init=function(l,j,g){this.enabled=true;this.type=l;this.$element=d(j);this.options=this.getOptions(g);this.$viewport=this.options.viewport&&d(d.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):(this.options.viewport.selector||this.options.viewport));this.inState={click:false,hover:false,focus:false};if(this.$element[0] instanceof document.constructor&&!this.options.selector){throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!")}var k=this.options.trigger.split(" ");for(var h=k.length;h--;){var f=k[h];if(f=="click"){this.$element.on("click."+this.type,this.options.selector,d.proxy(this.toggle,this))}else{if(f!="manual"){var m=f=="hover"?"mouseenter":"focusin";var e=f=="hover"?"mouseleave":"focusout";this.$element.on(m+"."+this.type,this.options.selector,d.proxy(this.enter,this));this.$element.on(e+"."+this.type,this.options.selector,d.proxy(this.leave,this))}}}this.options.selector?(this._options=d.extend({},this.options,{trigger:"manual",selector:""})):this.fixTitle()};c.prototype.getDefaults=function(){return c.DEFAULTS};c.prototype.getOptions=function(e){e=d.extend({},this.getDefaults(),this.$element.data(),e);if(e.delay&&typeof e.delay=="number"){e.delay={show:e.delay,hide:e.delay}}return e};c.prototype.getDelegateOptions=function(){var e={};var f=this.getDefaults();this._options&&d.each(this._options,function(g,h){if(f[g]!=h){e[g]=h}});return e};c.prototype.enter=function(f){var e=f instanceof this.constructor?f:d(f.currentTarget).data("bs."+this.type);if(!e){e=new this.constructor(f.currentTarget,this.getDelegateOptions());d(f.currentTarget).data("bs."+this.type,e)}if(f instanceof d.Event){e.inState[f.type=="focusin"?"focus":"hover"]=true}if(e.tip().hasClass("in")||e.hoverState=="in"){e.hoverState="in";return}clearTimeout(e.timeout);e.hoverState="in";if(!e.options.delay||!e.options.delay.show){return e.show()}e.timeout=setTimeout(function(){if(e.hoverState=="in"){e.show()}},e.options.delay.show)};c.prototype.isInStateTrue=function(){for(var e in this.inState){if(this.inState[e]){return true}}return false};c.prototype.leave=function(f){var e=f instanceof this.constructor?f:d(f.currentTarget).data("bs."+this.type);if(!e){e=new this.constructor(f.currentTarget,this.getDelegateOptions());d(f.currentTarget).data("bs."+this.type,e)}if(f instanceof d.Event){e.inState[f.type=="focusout"?"focus":"hover"]=false}if(e.isInStateTrue()){return}clearTimeout(e.timeout);e.hoverState="out";if(!e.options.delay||!e.options.delay.hide){return e.hide()}e.timeout=setTimeout(function(){if(e.hoverState=="out"){e.hide()}},e.options.delay.hide)};c.prototype.show=function(){var o=d.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(o);var p=d.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(o.isDefaultPrevented()||!p){return}var n=this;var l=this.tip();var h=this.getUID(this.type);this.setContent();l.attr("id",h);this.$element.attr("aria-describedby",h);if(this.options.animation){l.addClass("fade")}var k=typeof this.options.placement=="function"?this.options.placement.call(this,l[0],this.$element[0]):this.options.placement;var s=/\s?auto?\s?/i;var t=s.test(k);if(t){k=k.replace(s,"")||"top"}l.detach().css({top:0,left:0,display:"block"}).addClass(k).data("bs."+this.type,this);this.options.container?l.appendTo(this.options.container):l.insertAfter(this.$element);this.$element.trigger("inserted.bs."+this.type);var q=this.getPosition();var f=l[0].offsetWidth;var m=l[0].offsetHeight;if(t){var j=k;var r=this.getPosition(this.$viewport);k=k=="bottom"&&q.bottom+m>r.bottom?"top":k=="top"&&q.top-m<r.top?"bottom":k=="right"&&q.right+f>r.width?"left":k=="left"&&q.left-f<r.left?"right":k;l.removeClass(j).addClass(k)}var i=this.getCalculatedOffset(k,q,f,m);this.applyPlacement(i,k);var g=function(){var e=n.hoverState;n.$element.trigger("shown.bs."+n.type);n.hoverState=null;if(e=="out"){n.leave(n)}};d.support.transition&&this.$tip.hasClass("fade")?l.one("bsTransitionEnd",g).emulateTransitionEnd(c.TRANSITION_DURATION):g()}};c.prototype.applyPlacement=function(j,k){var l=this.tip();var g=l[0].offsetWidth;var q=l[0].offsetHeight;var f=parseInt(l.css("margin-top"),10);var i=parseInt(l.css("margin-left"),10);if(isNaN(f)){f=0}if(isNaN(i)){i=0}j.top+=f;j.left+=i;d.offset.setOffset(l[0],d.extend({using:function(r){l.css({top:Math.round(r.top),left:Math.round(r.left)})}},j),0);l.addClass("in");var e=l[0].offsetWidth;var m=l[0].offsetHeight;if(k=="top"&&m!=q){j.top=j.top+q-m}var p=this.getViewportAdjustedDelta(k,j,e,m);if(p.left){j.left+=p.left}else{j.top+=p.top}var n=/top|bottom/.test(k);var h=n?p.left*2-g+e:p.top*2-q+m;var o=n?"offsetWidth":"offsetHeight";l.offset(j);this.replaceArrow(h,l[0][o],n)};c.prototype.replaceArrow=function(g,e,f){this.arrow().css(f?"left":"top",50*(1-g/e)+"%").css(f?"top":"left","")};c.prototype.setContent=function(){var f=this.tip();var e=this.getTitle();f.find(".tooltip-inner")[this.options.html?"html":"text"](e);f.removeClass("fade in top bottom left right")};c.prototype.hide=function(j){var g=this;var i=d(this.$tip);var h=d.Event("hide.bs."+this.type);function f(){if(g.hoverState!="in"){i.detach()}if(g.$element){g.$element.removeAttr("aria-describedby").trigger("hidden.bs."+g.type)}j&&j()}this.$element.trigger(h);if(h.isDefaultPrevented()){return}i.removeClass("in");d.support.transition&&i.hasClass("fade")?i.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f();this.hoverState=null;return this};c.prototype.fixTitle=function(){var e=this.$element;if(e.attr("title")||typeof e.attr("data-original-title")!="string"){e.attr("data-original-title",e.attr("title")||"").attr("title","")}};c.prototype.hasContent=function(){return this.getTitle()};c.prototype.getPosition=function(g){g=g||this.$element;var i=g[0];var f=i.tagName=="BODY";var h=i.getBoundingClientRect();if(h.width==null){h=d.extend({},h,{width:h.right-h.left,height:h.bottom-h.top})}var k=window.SVGElement&&i instanceof window.SVGElement;var l=f?{top:0,left:0}:(k?null:g.offset());var e={scroll:f?document.documentElement.scrollTop||document.body.scrollTop:g.scrollTop()};var j=f?{width:d(window).width(),height:d(window).height()}:null;return d.extend({},h,e,j,l)};c.prototype.getCalculatedOffset=function(e,h,f,g){return e=="bottom"?{top:h.top+h.height,left:h.left+h.width/2-f/2}:e=="top"?{top:h.top-g,left:h.left+h.width/2-f/2}:e=="left"?{top:h.top+h.height/2-g/2,left:h.left-f}:{top:h.top+h.height/2-g/2,left:h.left+h.width}};c.prototype.getViewportAdjustedDelta=function(h,k,e,j){var m={top:0,left:0};if(!this.$viewport){return m}var g=this.options.viewport&&this.options.viewport.padding||0;var l=this.getPosition(this.$viewport);if(/right|left/.test(h)){var n=k.top-g-l.scroll;var i=k.top+g-l.scroll+j;if(n<l.top){m.top=l.top-n}else{if(i>l.top+l.height){m.top=l.top+l.height-i}}}else{var o=k.left-g;var f=k.left+g+e;if(o<l.left){m.left=l.left-o}else{if(f>l.right){m.left=l.left+l.width-f}}}return m};c.prototype.getTitle=function(){var g;var e=this.$element;var f=this.options;g=e.attr("data-original-title")||(typeof f.title=="function"?f.title.call(e[0]):f.title);return g};c.prototype.getUID=function(e){do{e+=~~(Math.random()*1000000)}while(document.getElementById(e));return e};c.prototype.tip=function(){if(!this.$tip){this.$tip=d(this.options.template);if(this.$tip.length!=1){throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!")}}return this.$tip};c.prototype.arrow=function(){return(this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow"))};c.prototype.enable=function(){this.enabled=true};c.prototype.disable=function(){this.enabled=false};c.prototype.toggleEnabled=function(){this.enabled=!this.enabled};c.prototype.toggle=function(g){var f=this;if(g){f=d(g.currentTarget).data("bs."+this.type);if(!f){f=new this.constructor(g.currentTarget,this.getDelegateOptions());d(g.currentTarget).data("bs."+this.type,f)}}if(g){f.inState.click=!f.inState.click;if(f.isInStateTrue()){f.enter(f)}else{f.leave(f)}}else{f.tip().hasClass("in")?f.leave(f):f.enter(f)}};c.prototype.destroy=function(){var e=this;clearTimeout(this.timeout);this.hide(function(){e.$element.off("."+e.type).removeData("bs."+e.type);if(e.$tip){e.$tip.detach()}e.$tip=null;e.$arrow=null;e.$viewport=null;e.$element=null})};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.tooltip");var f=typeof e=="object"&&e;if(!g&&/destroy|hide/.test(e)){return}if(!g){h.data("bs.tooltip",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.tooltip;d.fn.tooltip=b;d.fn.tooltip.Constructor=c;d.fn.tooltip.noConflict=function(){d.fn.tooltip=a;return this}}(jQuery);+function(d){var c=function(f,e){this.init("popover",f,e)};if(!d.fn.tooltip){throw new Error("Popover requires tooltip.js")}c.VERSION="3.3.7";c.DEFAULTS=d.extend({},d.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'});c.prototype=d.extend({},d.fn.tooltip.Constructor.prototype);c.prototype.constructor=c;c.prototype.getDefaults=function(){return c.DEFAULTS};c.prototype.setContent=function(){var g=this.tip();var f=this.getTitle();var e=this.getContent();g.find(".popover-title")[this.options.html?"html":"text"](f);g.find(".popover-content").children().detach().end()[this.options.html?(typeof e=="string"?"html":"append"):"text"](e);g.removeClass("fade top bottom left right in");if(!g.find(".popover-title").html()){g.find(".popover-title").hide()}};c.prototype.hasContent=function(){return this.getTitle()||this.getContent()};c.prototype.getContent=function(){var e=this.$element;var f=this.options;return e.attr("data-content")||(typeof f.content=="function"?f.content.call(e[0]):f.content)};c.prototype.arrow=function(){return(this.$arrow=this.$arrow||this.tip().find(".arrow"))};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.popover");var f=typeof e=="object"&&e;if(!g&&/destroy|hide/.test(e)){return}if(!g){h.data("bs.popover",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.popover;d.fn.popover=b;d.fn.popover.Constructor=c;d.fn.popover.noConflict=function(){d.fn.popover=a;return this}}(jQuery);+function(d){function c(f,e){this.$body=d(document.body);this.$scrollElement=d(f).is(document.body)?d(window):d(f);this.options=d.extend({},c.DEFAULTS,e);this.selector=(this.options.target||"")+" .nav li > a";this.offsets=[];this.targets=[];this.activeTarget=null;this.scrollHeight=0;this.$scrollElement.on("scroll.bs.scrollspy",d.proxy(this.process,this));this.refresh();this.process()}c.VERSION="3.3.7";c.DEFAULTS={offset:10};c.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)};c.prototype.refresh=function(){var g=this;var e="offset";var f=0;this.offsets=[];this.targets=[];this.scrollHeight=this.getScrollHeight();if(!d.isWindow(this.$scrollElement[0])){e="position";f=this.$scrollElement.scrollTop()}this.$body.find(this.selector).map(function(){var i=d(this);var h=i.data("target")||i.attr("href");var j=/^#./.test(h)&&d(h);return(j&&j.length&&j.is(":visible")&&[[j[e]().top+f,h]])||null}).sort(function(i,h){return i[0]-h[0]}).each(function(){g.offsets.push(this[0]);g.targets.push(this[1])})};c.prototype.process=function(){var k=this.$scrollElement.scrollTop()+this.options.offset;var g=this.getScrollHeight();var j=this.options.offset+g-this.$scrollElement.height();var h=this.offsets;var e=this.targets;var l=this.activeTarget;var f;if(this.scrollHeight!=g){this.refresh()}if(k>=j){return l!=(f=e[e.length-1])&&this.activate(f)}if(l&&k<h[0]){this.activeTarget=null;return this.clear()}for(f=h.length;f--;){l!=e[f]&&k>=h[f]&&(h[f+1]===undefined||k<h[f+1])&&this.activate(e[f])}};c.prototype.activate=function(g){this.activeTarget=g;this.clear();var e=this.selector+'[data-target="'+g+'"],'+this.selector+'[href="'+g+'"]';var f=d(e).parents("li").addClass("active");if(f.parent(".dropdown-menu").length){f=f.closest("li.dropdown").addClass("active")}f.trigger("activate.bs.scrollspy")};c.prototype.clear=function(){d(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.scrollspy");var f=typeof e=="object"&&e;if(!g){h.data("bs.scrollspy",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.scrollspy;d.fn.scrollspy=b;d.fn.scrollspy.Constructor=c;d.fn.scrollspy.noConflict=function(){d.fn.scrollspy=a;return this};d(window).on("load.bs.scrollspy.data-api",function(){d('[data-spy="scroll"]').each(function(){var e=d(this);b.call(e,e.data())})})}(jQuery);+function(d){var b=function(f){this.element=d(f)};b.VERSION="3.3.7";b.TRANSITION_DURATION=150;b.prototype.show=function(){var l=this.element;var h=l.closest("ul:not(.dropdown-menu)");var g=l.data("target");if(!g){g=l.attr("href");g=g&&g.replace(/.*(?=#[^\s]*$)/,"")}if(l.parent("li").hasClass("active")){return}var j=h.find(".active:last a");var k=d.Event("hide.bs.tab",{relatedTarget:l[0]});var i=d.Event("show.bs.tab",{relatedTarget:j[0]});j.trigger(k);l.trigger(i);if(i.isDefaultPrevented()||k.isDefaultPrevented()){return}var f=d(g);this.activate(l.closest("li"),h);this.activate(f,f.parent(),function(){j.trigger({type:"hidden.bs.tab",relatedTarget:l[0]});l.trigger({type:"shown.bs.tab",relatedTarget:j[0]})})};b.prototype.activate=function(h,g,k){var f=g.find("> .active");var j=k&&d.support.transition&&(f.length&&f.hasClass("fade")||!!g.find("> .fade").length);function i(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",false);h.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",true);if(j){h[0].offsetWidth;h.addClass("in")}else{h.removeClass("fade")}if(h.parent(".dropdown-menu").length){h.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",true)}k&&k()}f.length&&j?f.one("bsTransitionEnd",i).emulateTransitionEnd(b.TRANSITION_DURATION):i();f.removeClass("in")};function c(f){return this.each(function(){var h=d(this);var g=h.data("bs.tab");if(!g){h.data("bs.tab",(g=new b(this)))}if(typeof f=="string"){g[f]()}})}var a=d.fn.tab;d.fn.tab=c;d.fn.tab.Constructor=b;d.fn.tab.noConflict=function(){d.fn.tab=a;return this};var e=function(f){f.preventDefault();c.call(d(this),"show")};d(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery);+function(d){var c=function(f,e){this.options=d.extend({},c.DEFAULTS,e);this.$target=d(this.options.target).on("scroll.bs.affix.data-api",d.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",d.proxy(this.checkPositionWithEventLoop,this));this.$element=d(f);this.affixed=null;this.unpin=null;this.pinnedOffset=null;this.checkPosition()};c.VERSION="3.3.7";c.RESET="affix affix-top affix-bottom";c.DEFAULTS={offset:0,target:window};c.prototype.getState=function(n,m,f,g){var e=this.$target.scrollTop();var i=this.$element.offset();var j=this.$target.height();if(f!=null&&this.affixed=="top"){return e<f?"top":false}if(this.affixed=="bottom"){if(f!=null){return(e+this.unpin<=i.top)?false:"bottom"}return(e+j<=n-g)?false:"bottom"}var h=this.affixed==null;var l=h?e:i.top;var k=h?j:m;if(f!=null&&e<=f){return"top"}if(g!=null&&(l+k>=n-g)){return"bottom"}return false};c.prototype.getPinnedOffset=function(){if(this.pinnedOffset){return this.pinnedOffset}this.$element.removeClass(c.RESET).addClass("affix");var f=this.$target.scrollTop();var e=this.$element.offset();return(this.pinnedOffset=e.top-f)};c.prototype.checkPositionWithEventLoop=function(){setTimeout(d.proxy(this.checkPosition,this),1)};c.prototype.checkPosition=function(){if(!this.$element.is(":visible")){return}var f=this.$element.height();var l=this.options.offset;var j=l.top;var h=l.bottom;var i=Math.max(d(document).height(),d(document.body).height());if(typeof l!="object"){h=j=l}if(typeof j=="function"){j=l.top(this.$element)}if(typeof h=="function"){h=l.bottom(this.$element)}var g=this.getState(i,f,j,h);if(this.affixed!=g){if(this.unpin!=null){this.$element.css("top","")}var m="affix"+(g?"-"+g:"");var k=d.Event(m+".bs.affix");this.$element.trigger(k);if(k.isDefaultPrevented()){return}this.affixed=g;this.unpin=g=="bottom"?this.getPinnedOffset():null;this.$element.removeClass(c.RESET).addClass(m).trigger(m.replace("affix","affixed")+".bs.affix")}if(g=="bottom"){this.$element.offset({top:i-f-h})}};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.affix");var f=typeof e=="object"&&e;if(!g){h.data("bs.affix",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.affix;d.fn.affix=b;d.fn.affix.Constructor=c;d.fn.affix.noConflict=function(){d.fn.affix=a;return this};d(window).on("load",function(){d('[data-spy="affix"]').each(function(){var f=d(this);var e=f.data();e.offset=e.offset||{};if(e.offsetBottom!=null){e.offset.bottom=e.offsetBottom}if(e.offsetTop!=null){e.offset.top=e.offsetTop}b.call(f,e)})})}(jQuery);
WRFILE: pgbadger_slide.min.js

jQuery(function(){jQuery("#pgbadger-brand").tooltip();jQuery("#pop-infos").popover("hide");jQuery(".slide").hide();jQuery(".active-slide").show();var a=location.hash;if(a){a=a.substring(1);var d=document.getElementById(a);var c=jQuery(d).parent().attr("id");if(c!=undefined){var b="#"+c;jQuery("#main-container li.slide").removeClass("active-slide").hide();jQuery(b).addClass("active-slide").fadeIn();window.location.hash="#"+a}}jQuery(".navbar li.dropdown").click(function(){var g=jQuery(this).attr("id");g=g.substring(5);var e="#"+g+"-slide";var f=jQuery("#main-container .active-slide").attr("id");f="#"+f;if(e!=f){jQuery("#main-container li.slide").removeClass("active-slide").hide();jQuery(e).addClass("active-slide").fadeIn()}scrollTo(0,0);draw_charts()});jQuery(".navbar li ul li").click(function(){var f=jQuery(this).parent().parent().attr("id");var g=f.substring(5);var e="#"+g+"-slide";jQuery("#main-container li.slide").removeClass("active-slide").hide();jQuery(e).addClass("active-slide").fadeIn();draw_charts()});draw_charts()});jQuery(document).ready(function(){jQuery(".sql").dblclick(function(){if(this.style==undefined||this.style.whiteSpace=="pre"){this.style.whiteSpace="normal"}else{this.style.whiteSpace="pre"}});jQuery(".icon-copy").click(function(){var e=$(this).parent()[0];if(window.getSelection){var d=window.getSelection();d.removeAllRanges();var b=document.createRange();b.selectNodeContents(e);d.addRange(b)}else{if(document.selection){var c=document.body.createTextRange();c.moveToElementText(e);c.select()}}});function a(){scrollBy(0,-50)}if(location.hash){a()}window.addEventListener("hashchange",a)});
WRFILE: pgbadger.min.css

body{background-color:#cdd5da;background:-webkit-linear-gradient(bottom,#cdd5da,#e8e7e7);background:-moz-linear-gradient(bottom,#cdd5da,#e8e7e7);background:-ms-linear-gradient(bottom,#cdd5da,#e8e7e7);background:-o-linear-gradient(bottom,#cdd5da,#e8e7e7);background:linear-gradient(to bottom,#cdd5da,#e8e7e7);margin-top:50px}ul.nav li.dropdown:hover ul.dropdown-menu{display:block}ul.nav li.dropdown ul.dropdown-menu{margin:0}#pgbadger-brand{font-size:1.1em;font-weight:bold}ul#slides li{list-style-type:none}h1{font-size:2em}h2{font-size:1.6em}h3,h3 small{font-size:1.1em;text-transform:uppercase;letter-spacing:.1em}h3 small{font-size:1em}.analysis-item{background:#fff;margin-bottom:2em;padding-bottom:15px}h3{margin:0;padding:0;color:#5f5555}h1.page-header{margin:1em 0 1em 0;padding:0;color:#5f5555;border-bottom:0}h2{color:#5f5555}.nav-pills,.nav-tabs{margin:0 1em}footer{margin-top:60px}.col-md-8 .tabbable{margin-top:1em}#global-stats .tab-content{margin:2em 0 3em 0}#global-stats .tab-content li{display:block;width:12%;float:left;margin-left:2.5%}#global-stats .tab-content li.first{margin-left:0}.well{background:#f9f9f9;border-radius:0}.key-figures ul{margin:0;padding:0}.key-figures li{list-style-type:none;margin-bottom:2em}.figure{font-weight:bold;font-size:1.4em;color:#2e8aa5}.figure-label{display:block;color:#666}.mfigure{font-weight:bold;font-size:1.4em;color:#d26115;margin-left:5px}.smfigure{font-weight:bold;font-size:1.1em;color:#d26115}.mfigure small{font-weight:bold;font-size:.6em;color:#fff}.smfigure small{font-weight:bold;font-size:.6em;color:#fff}.hfigure{font-weight:bold;font-size:1.0;color:#8dbd0f}.hfigure small{font-weight:bold;font-size:.6em;color:#fff}.navbar-inverse{background:#5f5555;border:0}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#eee}.linegraph{width:100%;height:400px}.piegraph{width:100%;height:400px}.histo-graph{width:100%;height:140px}.duration-histo-graph{width:100%;height:400px}@media(min-width:750px){#show-hide-menu{position:absolute;left:-9999px}.navbar ul.collapse{overflow:visible}}@media(max-width:749px){#show-hide-menu{position:inherit}#global-stats .tab-content li{display:block;width:auto;float:none;margin-left:0;margin-bottom:1em}ul#slides{margin:0;padding:0}ul#slides li div div{padding:0 1.5em}.linegraph{width:94.5%}.piegraph{width:94.5%}.histo-graph{width:84.5%}.duration-histo-graph{width:94.5%}.key-figures ul{margin-top:1.5em}.navbar .nav{margin:0 3em 2em 3em}.navbar .nav>li{float:none}.navbar ul.collapse:hover{overflow:visible}}div#littleToc{display:none}html>body div#littleToc{display:block;background-color:white;color:black;position:fixed;bottom:10px;right:10px;width:50px;font-size:11px;text-align:left;border:0}div#littleToc div#littleTocTitle{font-weight:bold;text-align:center;padding:2px}div#littleToc ul{padding:0;text-indent:0;margin:0}div#littleToc li{font-size:11px;list-style-type:none;padding:0;text-indent:0;margin:0}div#littleToc a{color:#000;padding:2px;margin:2px;display:block;text-decoration:none;border:1px solid #ccc}div#littleToc a:hover{text-decoration:none;background-color:#ddd}.jqplot-graph{color:#ac1316;z-index:99}.sql{font-family:monospace}.sql .imp{font-weight:bold;color:red}.sql .kw1{color:#933;font-weight:bold;text-transform:uppercase}.sql .kw2{color:#933;font-style:italic}.sql .kw3{color:#933;text-transform:uppercase}.sql .co1{color:gray;font-style:italic}.sql .co2{color:gray;font-style:italic}.sql .coMULTI{color:gray;font-style:italic}.sql .es0{color:#009;font-weight:bold}.sql .br0{color:#6c6}.sql .sy0{color:#000}.sql .st0{color:red}.sql .nu0{color:#c6c}.sql span.xtra{display:block}.sql-smallsize{width:450px}.sql-mediumsize{width:600px;max-height:200px;overflow:auto}.sql-largesize{width:950px;max-height:200px;overflow:auto}.pre-smallfont{font-size:10px}.jqplot-target{position:relative;color:#333;font-size:1.2em}.jqplot-highlighter-tooltip{border:0;font-size:1.0;white-space:nowrap;font-weight:bold;margin:5px;padding:5px;color:#fff;background:#5f5555;border:1px solid #5f5555;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.jqplot-title{font-size:1.1em;text-transform:uppercase;letter-spacing:.1em;margin:0;padding:0;color:#5f5555}#pgbadgerModal .modal-dialog{width:850px;overflow-y:hidden}#pgbadgerModal .modal-body{height:100%;width:830px;background-color:white}.error-pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}
WRFILE: pgbadger.min.js

function create_download_button(a,b){if(b==undefined){b="btn btn-info"}document.writeln('<button type="button" id="download'+a+'" class="'+b+'">Download</button>')}function add_download_button_event(a,b){jQuery("#download"+a).click(function(){$("#pgbadgerModal img").attr("src",$("#"+b).jqplotToImageStr({}));$("#pgbadgerModal").modal("toggle")})}function create_linegraph(e,c,d,a,b){return $.jqplot(e,b,{seriesColors:["#6e9dc9","#f4ab3a","#ac7fa8","#8dbd0f","#958c12","#953579","#4b5de4","#d8b83f","#ff5800","#0085cc"],seriesDefaults:{markerOptions:{show:false},lineWidth:1},grid:{borderWidth:1,background:"#ffffff"},title:c,series:a,axes:{xaxis:{renderer:$.jqplot.DateAxisRenderer,tickOptions:{angle:-30,textColor:"#333"}},yaxis:{renderer:$.jqplot.LogAxisRenderer,labelRenderer:$.jqplot.CanvasAxisLabelRenderer,tickRenderer:$.jqplot.CanvasAxisTickRenderer,tickOptions:{textColor:"#333",formatter:function(g,f){return pretty_print_number(f,0,d)}}}},legend:{show:true,location:"nw"},cursor:{show:true,zoom:true,showTooltip:false,looseZoom:true,followMouse:true},highlighter:{show:true,tooltipContentEditor:function(m,f,j,k){var h=new Date(k.data[f][j][0]);var l="<div>On "+h.toString();for(var g=0;g<k.data.length;g++){l+='<br><span class="mfigure">'+pretty_print_number(k.data[g][j][1],2,k.series[g].label)+" <small>"+k.series[g].label+"</small></span>"}l+="</div>";return l}}})}function create_piechart(c,b,a){return $.jqplot(c,[a],{seriesColors:["#6e9dc9","#f4ab3a","#ac7fa8","#8dbd0f","#958c12","#953579","#4b5de4","#d8b83f","#ff5800","#0085cc","#4bb2c5","#c5b47f","#EAA228","#579575","#839557","#498991","#C08840","#9F9274","#546D61","#646C4A","#6F6621","#6E3F5F","#4F64B0","#A89050","#C45923","#187399","#945381","#959E5C","#C7AF7B","#478396","#907294"],grid:{borderWidth:1,background:"#ffffff"},title:b,seriesDefaults:{renderer:$.jqplot.PieRenderer,rendererOptions:{showDataLabels:true}},legend:{show:true,location:"e"},highlighter:{show:true,tooltipLocation:"sw",useAxesFormatters:false,tooltipContentEditor:function(h,d,e,f){var g="<div>";g+='<span class="mfigure">'+format_number(f.data[0][e][1])+" <small>"+f.data[0][e][0]+"</small></span>";g+="</div>";return g}}})}function create_bargraph(e,d,a,c,b){return $.jqplot(e,c,{grid:{borderWidth:1,background:"#ffffff"},title:d,seriesDefaults:{rendererOptions:{barPadding:4,barMargin:5}},seriesColors:["#6e9dc9","#8dbd0f","#f4ab3a","#ac7fa8","#958c12","#953579","#4b5de4","#d8b83f","#ff5800","#0085cc"],series:[{renderer:$.jqplot.BarRenderer,label:a},{yaxis:"y2axis",label:b,markerOptions:{show:false},lineWidth:1}],axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer,drawMajorGridlines:false,drawMajorTickMarks:false,tickRenderer:$.jqplot.CanvasAxisTickRenderer,tickOptions:{angle:-30,textColor:"#333",formatString:"%H:%M",fontFamily:"Helvetica",fontSize:"8pt"}},yaxis:{autoscale:true,labelRenderer:$.jqplot.CanvasAxisLabelRenderer,tickOptions:{textColor:"#333"},tickRenderer:$.jqplot.CanvasAxisTickRenderer,tickOptions:{textColor:"#333",formatter:function(g,f){return pretty_print_number(f,1,a)},fontFamily:"Helvetica",fontSize:"8pt"},label:a},y2axis:{autoscale:true,labelRenderer:$.jqplot.CanvasAxisLabelRenderer,tickRenderer:$.jqplot.CanvasAxisTickRenderer,tickOptions:{textColor:"#8dbd0f",formatter:function(g,f){return pretty_print_number(f,1,b)},fontFamily:"Helvetica",fontSize:"8pt"},rendererOptions:{alignTicks:true},label:b}},highlighter:{show:true,tooltipLocation:"ne",useAxesFormatters:false,tooltipContentEditor:function(l,f,h,j){var k='<div style="z-index: 99;">At '+j.data[0][h][0];for(var g=0;g<j.data.length;g++){k+='<br><span class="mfigure">'+pretty_print_number(j.data[g][h][1],2,j.series[g].label)+" <small>"+j.series[g].label+"</small></span>"}k+="</div>";return k}}})}function pretty_print_number(c,b,a){if((b==undefined)||((b==0)&&(c!=0))){b=1}if(a!=undefined){a=a.toLowerCase();if(a.search("size")>=0){if(Math.abs(c)>=1125899906842624){c=(c/1125899906842624);return c.toFixed(b)+" PiB"}else{if(Math.abs(c)>=1099511627776){c=(c/1099511627776);return c.toFixed(b)+" TiB"}else{if(Math.abs(c)>=1073741824){c=(c/1073741824);return c.toFixed(b)+" GiB"}else{if(Math.abs(c)>=1048576){c=(c/1048576);return c.toFixed(b)+" MiB"}else{if(Math.abs(c)>=1024){c=(c/1024);return c.toFixed(b)+" KiB"}else{return c+" B"}}}}}}else{if(a.search("duration")>=0){if(Math.abs(c)>=1000){c=(c/1000);return c.toFixed(b)+" sec"}else{return c.toFixed(b)+" ms"}}else{if(Math.abs(c)>=1000000000000000){c=(c/1000000000000000);return c.toFixed(b)+" P"}else{if(Math.abs(c)>=1000000000000){c=(c/1000000000000);return c.toFixed(b)+" T"}else{if(Math.abs(c)>=1000000000){c=(c/1000000000);return c.toFixed(b)+" G"}else{if(Math.abs(c)>=1000000){c=(c/1000000);return c.toFixed(b)+" M"}else{if(Math.abs(c)>=1000){c=(c/1000);return c.toFixed(b)+" K"}}}}}}}}return c.toFixed(b)}function format_number(a){var f=2;var h=",";var k=Math.round(Math.pow(10,f)*(Math.abs(a)-Math.floor(Math.abs(a))));a=Math.floor(Math.abs(a));if((f==0)||(k==Math.pow(10,f))){k=0}var c=a+"";var g=c.length;for(var e=1;e<4;e++){if(a>=Math.pow(10,(3*e))){c=c.substring(0,g-(3*e))+h+c.substring(g-(3*e))}}if(f>0){var b="";for(var d=0;d<(f-k.toString().length);d++){b+="0"}k=b+k.toString();if(k>0){c=c+"."+k}}if(parseFloat(a)<0){c="-"+c}return c}function draw_charts(){window.charts=$.grep(window.charts,function(c){var a=c.slice();var b=a.shift();var d=c[1];if($("#"+d).is(":visible")){window["create_"+b].apply(null,a);return false}return true})};
