diff --git a/pkgs/plt-services/meta/drdr/INSTALL b/pkgs/plt-services/meta/drdr/INSTALL deleted file mode 100644 index c9f98c6026..0000000000 --- a/pkgs/plt-services/meta/drdr/INSTALL +++ /dev/null @@ -1,52 +0,0 @@ -0. Copy source to /opt/plt/drdr - -1. Create - -/opt/plt -/opt/plt/plt (Racket install) -/opt/plt/builds -/opt/plt/future-builds -/opt/plt/logs -/opt/plt/builds/ (for the first build) - -2. Install stuff - -sudo apt-get install xorg fluxbox python-software-properties gcc libcairo2 libpango1.0-0 libgtk2.0-0 texlive lib32gmp3 libreadline5 libpcre3-dev libgmp3-dev -sudo add-apt-repository ppa:git-core/ppa -sudo apt-get update -sudo apt-get install git-core - -3. Setup git - -cd /opt/plt -git clone http://git.racket-lang.org/plt.git repo - -4. Setup firewall - -sudo ufw allow 22 -sudo ufw enable - -sudo vim /etc/ufw/before.rules - -*nat -:PREROUTING ACCEPT [0:0] --A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 9000 -COMMIT - -sudo ufw allow 80 -sudo ufw allow 9000 -sudo service ufw restart - -5. - -setuid on /usr/bin/Xorg - -6. - -sudo apt-get install postfix - -# https://help.ubuntu.com/10.04/serverguide/certificates-and-security.html -# https://www.wormly.com/blog/2008/11/05/relay-gmail-google-smtp-postfix/ - -# Use the Internet site setup -# Set a relyhost of mail.cs.byu.edu diff --git a/pkgs/plt-services/meta/drdr/README b/pkgs/plt-services/meta/drdr/README deleted file mode 100644 index c5f01525e8..0000000000 --- a/pkgs/plt-services/meta/drdr/README +++ /dev/null @@ -1,7 +0,0 @@ -This is the implementation of DrDr. - -It currently only runs on a single machine that is set up in an intricate way. --- In particular, config.rkt mentions many of those details --- Also, static/data must be a link to a data directory (/opt/plt/data) - -It uses a few of my PLaneT packages and some other ones as well. diff --git a/pkgs/plt-services/meta/drdr/README-PORTS b/pkgs/plt-services/meta/drdr/README-PORTS deleted file mode 100644 index 4b213a335a..0000000000 --- a/pkgs/plt-services/meta/drdr/README-PORTS +++ /dev/null @@ -1,18 +0,0 @@ -Please register which TCP ports your tests are using in this file so -others don't accidentally conflict. - -6000 - DrDr X11 server -.... -6100 - DrDr X11 server -8887 - tests/racket/benchmarks/shootout/echo -8888 - tests/racket/benchmarks/shootout/typed/echo (non-optimized) -8889 - tests/racket/benchmarks/shootout/typed/echo (optimized) -9000 - DrDr Web server -9001 - tests/net -9990 - tests/pkg -9997 - tests/pkg -9998 - tests/pkg -9999 - tests/web-server -19200 - 2htdp/tests -... -19209 - 2htdp/tests diff --git a/pkgs/plt-services/meta/drdr/analyze.rkt b/pkgs/plt-services/meta/drdr/analyze.rkt deleted file mode 100644 index 5ef87a5612..0000000000 --- a/pkgs/plt-services/meta/drdr/analyze.rkt +++ /dev/null @@ -1,377 +0,0 @@ -#lang racket -(require racket/file - "diff.rkt" - "scm.rkt" - "list-count.rkt" - "notify.rkt" - "cache.rkt" - "dirstruct.rkt" - "status.rkt" - "metadata.rkt" - "path-utils.rkt" - "rendering.rkt") -(provide (all-from-out "rendering.rkt")) - -; Email -(require net/sendmail - "formats.rkt") - -(define list@ - (match-lambda - [(and c (cons x y)) - (if (lc-zero? x) - empty - (list c))])) - -(define (list-limit l n) - (for/list ([e (in-list l)] - [i (in-range n)]) - e)) - -(define responsible-ht-id->str - #hasheq([timeout . "Timeout"] - [unclean . "Unclean Exit"] - [stderr . "STDERR Output"] - [changes . "Changes"])) -(define responsible-ht-severity - '(timeout unclean stderr changes)) -(define (rev->responsible-ht rev) - (define log-dir (revision-log-dir rev)) - (define top-analyze - (parameterize ([cache/file-mode 'no-cache] - [current-rev rev]) - (dir-rendering log-dir))) - (rendering->responsible-ht rev top-analyze)) - -(define (rendering->responsible-ht rev top-analyze) - (match-define - (struct rendering (_ _ _ timeout unclean stderr _ changes)) - top-analyze) - (statuses->responsible-ht rev timeout unclean stderr changes)) - -(define (statuses->responsible-ht rev timeout unclean stderr changes) - (parameterize ([current-rev rev]) - (define log-dir (revision-log-dir rev)) - (define base-path - (rebase-path log-dir "/")) - - (define responsible->problems (make-hash)) - (for ([lc (in-list (list timeout unclean stderr changes))] - [id (in-list responsible-ht-severity)]) - (for ([pp (in-list (lc->list lc))]) - (define p (bytes->string/utf-8 pp)) - (define bp (base-path p)) - (for ([responsible - (in-list - (rendering-responsibles (log-rendering p)))]) - (hash-update! - (hash-ref! responsible->problems responsible make-hasheq) - id - (curry list* bp) - empty)))) - - responsible->problems)) - -(define (2hash-copy ht) - (define 2ht (make-hash)) - (for ([(r ht) (in-hash ht)]) - (hash-set! 2ht r (hash-copy ht))) - 2ht) -(define (responsible-ht-difference old new) - (let ([ht (2hash-copy new)]) - (for ([(r rht) (in-hash old)]) - (define nrht (hash-ref! ht r make-hash)) - (for ([(id ps) (in-hash rht)]) - (hash-update! nrht id - (curry remove* ps) - empty) - (when (zero? (length (hash-ref nrht id))) - (hash-remove! nrht id))) - (when (zero? (hash-count nrht)) - (hash-remove! ht r))) - ht)) - -(define responsible-ht/c - (hash/c string? (hash/c symbol? (listof path?)))) - -(define (responsible-ht->status-ht diff) - (for/hash ([id (in-list responsible-ht-severity)]) - (define id-l - (for*/list ([(_ ht) (in-hash diff)] - [f (in-list (hash-ref ht id empty))]) - f)) - (values id (remove-duplicates id-l)))) - -(provide/contract - [rendering->responsible-ht - (exact-positive-integer? rendering? . -> . responsible-ht/c)] - [statuses->responsible-ht - (exact-positive-integer? list/count list/count list/count list/count . -> . responsible-ht/c)] - [responsible-ht-severity (listof symbol?)] - [responsible-ht-id->str (hash/c symbol? string?)] - [responsible-ht-difference (responsible-ht/c responsible-ht/c . -> . responsible-ht/c)]) - -(define ERROR-LIMIT 50) -(define (notify cur-rev - start end - duration - timeout unclean stderr changes) - (define abs-dur (- end start)) - (define nums - (map lc->number - (list timeout unclean stderr changes))) - (define totals - (apply - format - "(timeout ~a) (unclean ~a) (stderr ~a) (changes ~a)" - (map number->string nums))) - (define (path->url pth) - (format "http://drdr.racket-lang.org/~a~a" cur-rev pth)) - (define responsible-ht - (statuses->responsible-ht - cur-rev - timeout - unclean - stderr - changes)) - (define responsibles - (for/list ([(responsible ht) (in-hash responsible-ht)] - #:when (ormap (curry hash-has-key? ht) - (take responsible-ht-severity 3))) - (match responsible - ["nobody" "drdr-nobody"] - [x x]))) - (define committer - (with-handlers ([exn:fail? (lambda (x) #f)]) - (scm-commit-author - (read-cache* - (revision-commit-msg cur-rev))))) - (define diff - (with-handlers ([exn:fail? (lambda (x) #t)]) - (define old (rev->responsible-ht (previous-rev))) - (responsible-ht-difference old responsible-ht))) - (define include-committer? - (and ; The committer can be found - committer - ; There is a condition - (not (empty? responsibles)) - ; It is different from before - (hash? diff) - (for*/or ([(r ht) (in-hash diff)] - [(id ps) (in-hash ht)]) - (and - (for/or ([p (in-list ps)]) - ;; XXX This squelch should be disabled if the committer changed this file - ;; XXX But even then it can lead to problems - (not (path-random? (build-path (revision-trunk-dir cur-rev) - (substring (path->string* p) 1))))) - (not (symbol=? id 'changes)))))) - (define mail-recipients - (remove-duplicates - (append (if include-committer? - (list committer) - empty) - responsibles))) - - ; Send messages to everyone... - (unless (andmap zero? nums) - (for ([r (in-list mail-recipients)]) - (send-mail-message - "drdr@racket-lang.org" - (format "[DrDr] R~a ~a" - cur-rev totals) - (list (format "~a@racket-lang.org" r)) - empty empty - (flatten - (list (format "DrDr has finished building push #~a after ~a." - cur-rev - (format-duration-ms abs-dur)) - "" - (format "http://drdr.racket-lang.org/~a/" - cur-rev) - "" - (if (and include-committer? (equal? committer r)) - (list - (format "Push #~a (which you did) contained a NEW condition that may need inspecting." cur-rev) - (let ([diff-smash (responsible-ht->status-ht diff)]) - (for/list ([(id paths) (in-hash diff-smash)] - #:when (not (symbol=? id 'changes))) - (if (empty? paths) - empty - (list (format " ~a" id) - (for/list ([f (in-list paths)] - [i (in-range ERROR-LIMIT)] - #:when (not (path-random? - (build-path (revision-trunk-dir cur-rev) - (substring (path->string* f) 1))))) - (format " ~a" (path->url f))) - "")))) - "") - empty) - (if (hash-has-key? responsible-ht r) - (list* "A file you are responsible for has a condition that may need inspecting." - (for/list ([(id files) (in-hash (hash-ref responsible-ht r))] - #:when (not (symbol=? id 'changes))) - (list (format " ~a:" id) - (for/list ([f (in-list files)] - [i (in-range ERROR-LIMIT)]) - (format " ~a" (path->url f))) - "")) - "") - empty)))))) - - ; Send message to IRC - (send-mail-message "drdr@racket-lang.org" - (format "http://drdr.racket-lang.org/~a/" - cur-rev) - (list "eli+ircbot@eli.barzilay.org") - empty empty - (list* (format " (abs ~a) (sum ~a) ~a" - (format-duration-ms abs-dur) - (format-duration-ms duration) - totals) - (if (empty? responsibles) - empty - (list (apply string-append (add-between responsibles " "))))))) -; End Email - -(define (trunk-path pth) - (define rev (current-rev)) - ((rebase-path (revision-log-dir rev) (revision-trunk-dir rev)) - pth)) - -(define (analyze-path pth dir?) - (define rev (current-rev)) - (define log-dir (revision-log-dir rev)) - (define analyze-dir (revision-analyze-dir rev)) - (define the-analyze-path - ((rebase-path log-dir analyze-dir) pth)) - (if dir? - (build-path the-analyze-path "index.analyze") - (path-add-suffix the-analyze-path ".analyze"))) - -(define (analyze-revision cur-rev) - (cache/file/timestamp - (build-path (revision-dir cur-rev) "analyzed") - (lambda () - (match (analyze-logs cur-rev) - [(struct rendering (start end duration timeout unclean stderr _ changes)) - (notify cur-rev - start end - duration - timeout unclean stderr changes)] - [#f - (void)]) - (safely-delete-directory (revision-trunk-dir cur-rev)) - (void)))) - -(define (analyze-logs rev) - (define log-dir (revision-log-dir rev)) - (define analyze-dir (revision-analyze-dir rev)) - (make-directory* analyze-dir) - (parameterize ([current-rev rev]) - (dir-rendering log-dir #:committer? #t))) - -(define (drdr-random-notification? l) - (and (stdout? l) - (regexp-match #rx"DrDr: This file has random output." - (stdout-bytes l)))) - -(define (log-rendering log-pth) - ; XXX - (if (or #t (file-exists? log-pth)) - (cache/file - (analyze-path log-pth #f) - (lambda () - #;(notify! "Analyzing log: ~S" log-pth) - (match (read-cache log-pth) - [(? eof-object?) - #f] - [(and log (struct status (start end command-line output-log))) - (define dur (status-duration log)) - (define any-stderr? (ormap stderr? output-log)) - (define changed? - (if (and (previous-rev) - (not (path-random? (trunk-path log-pth))) - (not (ormap drdr-random-notification? output-log))) - (with-handlers ([exn:fail? - ;; This #f means that new files are - ;; NOT considered changed - (lambda (x) #f)]) - (define prev-log-pth - ((rebase-path (revision-log-dir (current-rev)) - (revision-log-dir (previous-rev))) - log-pth)) - (log-different? output-log - (status-output-log (read-cache prev-log-pth)))) - #f)) - (define responsible - (or (path-responsible (trunk-path log-pth)) - (and (regexp-match #rx"/planet/" (path->string* log-pth)) - "jay") - ; XXX maybe mflatt, eli, or tewk - (and (regexp-match #rx"/src/" (path->string* log-pth)) - "jay") - "nobody")) - (define lc - (list (path->bytes log-pth))) - (make-rendering start end dur - (if (timeout? log) lc empty) - (if (exit? log) - (if (zero? (exit-code log)) empty lc) - empty) - (if any-stderr? lc empty) - responsible - (if changed? lc empty))]))) - #f)) - -(define (dir-rendering dir-pth - #:committer? [committer? #f]) - ; XXX - (if (or #t (directory-exists? dir-pth)) - (cache/file - (analyze-path dir-pth #t) - (lambda () - (notify! "Analyzing dir: ~S" dir-pth) - (foldl (lambda (sub-pth acc) - (define pth (build-path dir-pth sub-pth)) - (define directory? (directory-exists? pth)) - (define (next-rendering) - (if directory? - (dir-rendering pth) - (log-rendering pth))) - (match (next-rendering) - [#f - acc] - [(and n (struct rendering (pth-start pth-end pth-dur pth-timeouts pth-unclean-exits pth-stderrs _pth-responsible pth-changed))) - (match acc - [#f n] - [(struct rendering (acc-start acc-end acc-dur acc-timeouts acc-unclean-exits acc-stderrs acc-responsible acc-changed)) - (make-rendering (min pth-start acc-start) - (max pth-end acc-end) - (+ pth-dur acc-dur) - (lc+ pth-timeouts acc-timeouts) - (lc+ pth-unclean-exits acc-unclean-exits) - (lc+ pth-stderrs acc-stderrs) - acc-responsible - (lc+ pth-changed acc-changed))])])) - (make-rendering - +inf.0 -inf.0 0 - empty empty empty - - (or - (and committer? - (with-handlers ([exn:fail? (lambda (x) #f)]) - (scm-commit-author (read-cache (revision-commit-msg (current-rev)))))) - (or (path-responsible (trunk-path dir-pth)) - "nobody")) - - empty) - (directory-list* dir-pth)))) - #f)) - -(provide/contract - [analyze-revision (exact-nonnegative-integer? . -> . void)] - [analyze-logs (exact-nonnegative-integer? . -> . void)] - [log-rendering (path-string? . -> . (or/c rendering? false/c))] - [dir-rendering (path-string? . -> . (or/c rendering? false/c))]) diff --git a/pkgs/plt-services/meta/drdr/archive-repair.rkt b/pkgs/plt-services/meta/drdr/archive-repair.rkt deleted file mode 100644 index dde4a684d5..0000000000 --- a/pkgs/plt-services/meta/drdr/archive-repair.rkt +++ /dev/null @@ -1,17 +0,0 @@ -#lang racket -(require "config.rkt" - "archive.rkt" - "path-utils.rkt" - "dirstruct.rkt" - "make-archive-lib.rkt") - -(init-revisions!) - -(define rev - (command-line #:program "archive-repair" - #:args (n) (string->number n))) - -(when (file-exists? (revision-archive rev)) - (archive-extract-to (revision-archive rev) (revision-dir rev) (revision-dir rev)) - (delete-file (revision-archive rev)) - (make-archive rev)) diff --git a/pkgs/plt-services/meta/drdr/archive-repair.sh b/pkgs/plt-services/meta/drdr/archive-repair.sh deleted file mode 100755 index d14804aaa7..0000000000 --- a/pkgs/plt-services/meta/drdr/archive-repair.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -cd /opt/plt/builds - -du -h */archive.db | awk '{print $1}' | sort -n | uniq -c -echo - -for rev in $(du -h */archive.db | sort -n | tail | awk '{print $2}' | awk -F/ '{print $1}' | tac) ; do - du -h ${rev}/archive.db - /opt/plt/plt/bin/racket -t /opt/svn/drdr/archive-repair.rkt -- $rev > /dev/null -done -echo - -du -h */archive.db | awk '{print $1}' | sort -n | uniq -c -echo - -df -h diff --git a/pkgs/plt-services/meta/drdr/archive-test.rkt b/pkgs/plt-services/meta/drdr/archive-test.rkt deleted file mode 100644 index d42acc14d7..0000000000 --- a/pkgs/plt-services/meta/drdr/archive-test.rkt +++ /dev/null @@ -1,32 +0,0 @@ -#lang racket -(require "path-utils.rkt" - "archive.rkt" - tests/eli-tester) - -(define archive - "../test.archive") - -(test - (create-archive archive (current-directory)) - - (for ([fp (in-list (directory-list* (current-directory)))] - #:when (file-exists? fp)) - (test - (archive-extract-file archive (build-path (current-directory) fp)) => (file->bytes fp))) - (archive-extract-file archive "test") =error> #rx"not in the archive" - (archive-extract-file archive (build-path (current-directory) "test")) =error> #rx"not in the archive" - (archive-extract-file archive (build-path (current-directory) "static")) =error> #rx"not a file" - - (archive-extract-file "archive-test.rkt" (build-path (current-directory) "archive-test.rkt")) =error> #rx"not a valid archive" - - (directory-list->directory-list* (archive-directory-list archive (current-directory))) - => (directory-list* (current-directory)) - - (archive-directory-exists? archive (current-directory)) => #t - (archive-directory-exists? archive (build-path (current-directory) "static")) => #t - - (archive-directory-exists? archive (build-path (current-directory) "unknown")) => #f - - (archive-directory-exists? archive (build-path (current-directory) "archive-test.rkt")) => #f - ) - diff --git a/pkgs/plt-services/meta/drdr/archive.rkt b/pkgs/plt-services/meta/drdr/archive.rkt deleted file mode 100644 index 7bca775151..0000000000 --- a/pkgs/plt-services/meta/drdr/archive.rkt +++ /dev/null @@ -1,150 +0,0 @@ -#lang racket -(require "path-utils.rkt") - -(define (value->bytes v) - (with-output-to-bytes (lambda () (write v)))) -(define (bytes->value bs ? err) - (define v (with-input-from-bytes bs read)) - (unless (? v) (err)) - v) - -(define (create-archive archive-path root) - (define start 0) - (define vals empty) - (define (make-table path) - (for/hash ([p (in-list (directory-list path))]) - (define fp (build-path path p)) - (define directory? - (directory-exists? fp)) - (define val - (if directory? - (value->bytes (make-table fp)) - (file->bytes fp))) - (define len (bytes-length val)) - (begin0 - (values (path->string p) - (vector directory? start len)) - (set! start (+ start len)) - (set! vals (cons val vals))))) - (define root-table - (value->bytes (make-table root))) - - (with-output-to-file archive-path - #:exists 'replace - (lambda () - (write (path->string* root)) - (write root-table) - - (for ([v (in-list (reverse vals))]) - (write-bytes v))))) - -(define (read/? p ? err) - (with-handlers ([exn:fail? (lambda (x) (err))]) - (define v (read p)) - (if (? v) v - (err)))) - -(define (archive-extract-path archive-path p) - (define ps (explode-path p)) - (define (not-in-archive) - (error 'archive-extract-path "~e is not in the archive" p)) - (define (bad-archive) - (error 'archive-extract-path "~e is not a valid archive" archive-path)) - (call-with-input-file - archive-path - (lambda (fport) - (dynamic-wind - void - (lambda () - (define root-string (read/? fport string? bad-archive)) - (define root (string->path root-string)) - (define roots (explode-path root)) - (define root-len (length roots)) - (unless (root-len . <= . (length ps)) - (not-in-archive)) - (local [(define ps-roots (list-tail ps root-len)) - (define root-table-bytes (read/? fport bytes? bad-archive)) - (define root-table (bytes->value root-table-bytes hash? bad-archive)) - (define heap-start (file-position fport)) - (define (extract-bytes t p) - (match (hash-ref t (path->string p) not-in-archive) - [(vector directory? file-start len) - ; Jump ahead in the file - (file-position fport (+ heap-start file-start)) - ; Read the bytes - (local [(define bs (read-bytes len fport))] - (unless (= (bytes-length bs) len) - (bad-archive)) - (values directory? bs))])) - (define (extract-table t p) - (define-values (dir? bs) (extract-bytes t p)) - (if dir? - (bytes->value bs hash? bad-archive) - (not-in-archive))) - (define (find-file ps-roots table) - (match ps-roots - [(list p) - (extract-bytes table p)] - [(list-rest p rst) - (find-file rst (extract-table table p))]))] - (if (empty? ps-roots) - (values #t root-table-bytes) - (find-file ps-roots root-table)))) - (lambda () - (close-input-port fport)))))) - -(define (archive-extract-file archive-path fp) - (define-values (dir? bs) (archive-extract-path archive-path fp)) - (if dir? - (error 'archive-extract-file "~e is not a file" fp) - bs)) - -(define (archive-directory-list archive-path fp) - (define (bad-archive) - (error 'archive-directory-list "~e is not a valid archive" archive-path)) - (define-values (dir? bs) (archive-extract-path archive-path fp)) - (if dir? - (for/list ([k (in-hash-keys (bytes->value bs hash? bad-archive))]) - (build-path k)) - (error 'archive-directory-list "~e is not a directory" fp))) - -(define (archive-directory-exists? archive-path fp) - (define-values (dir? _) - (with-handlers ([exn:fail? (lambda (x) (values #f #f))]) - (archive-extract-path archive-path fp))) - dir?) - -(define (archive-extract-to archive-file-path archive-inner-path to) - (printf "~a " to) - (cond - [(archive-directory-exists? archive-file-path archive-inner-path) - (printf "D\n") - (make-directory* to) - (for ([p (in-list (archive-directory-list archive-file-path archive-inner-path))]) - (archive-extract-to archive-file-path - (build-path archive-inner-path p) - (build-path to p)))] - [else - (printf "F\n") - (unless (file-exists? to) - (with-output-to-file to - #:exists 'error - (λ () - (write-bytes (archive-extract-file archive-file-path archive-inner-path)))))])) - -(provide/contract - [create-archive - (-> path-string? path-string? - void)] - [archive-extract-to - (-> path-string? path-string? path-string? - void)] - [archive-extract-file - (-> path-string? path-string? - bytes?)] - [archive-directory-list - (-> path-string? path-string? - (listof path?))] - [archive-directory-exists? - (-> path-string? path-string? - boolean?)]) diff --git a/pkgs/plt-services/meta/drdr/cache.rkt b/pkgs/plt-services/meta/drdr/cache.rkt deleted file mode 100644 index f94c9c417b..0000000000 --- a/pkgs/plt-services/meta/drdr/cache.rkt +++ /dev/null @@ -1,88 +0,0 @@ -#lang racket -(require "path-utils.rkt") - -; (symbols 'always 'cache 'no-cache) -(define cache/file-mode (make-parameter 'cache)) -(define (cache/file pth thnk) - (define mode (cache/file-mode)) - (define (recompute!) - (define v (thnk)) - (write-cache! pth v) - v) - (case mode - [(always) (recompute!)] - [(cache no-cache) - (with-handlers - ([exn:fail? - (lambda (x) - (case mode - [(no-cache) (error 'cache/file "No cache available: ~a" pth)] - [(cache always) - #;(printf "cache/file: running ~S for ~a\n" thnk pth) - (recompute!)]))]) - (read-cache pth))])) - -(define (cache/file/timestamp pth thnk) - (cache/file - pth - (lambda () - (thnk) - (current-seconds))) - (void)) - -(require "archive.rkt" - "dirstruct.rkt") - -(define (consult-archive pth) - (define rev (path->revision pth)) - (define archive-path (revision-archive rev)) - (define file-bytes - (archive-extract-file archive-path pth)) - (with-input-from-bytes file-bytes read)) - -(define (consult-archive/directory-list* pth) - (define rev (path->revision pth)) - (define archive-path (revision-archive rev)) - (directory-list->directory-list* (archive-directory-list archive-path pth))) - -(define (consult-archive/directory-exists? pth) - (define rev (path->revision pth)) - (define archive-path (revision-archive rev)) - (archive-directory-exists? archive-path pth)) - -(define (cached-directory-list* dir-pth) - (if (directory-exists? dir-pth) - (directory-list* dir-pth) - (or (with-handlers ([exn:fail? (lambda _ #f)]) (consult-archive/directory-list* dir-pth)) - (error 'cached-directory-list* "Directory list is not cached: ~e" dir-pth)))) - -(define (cached-directory-exists? dir-pth) - (if (file-exists? dir-pth) - #f - (or (directory-exists? dir-pth) - (with-handlers ([exn:fail? (lambda _ #f)]) (consult-archive/directory-exists? dir-pth))))) - -(define (read-cache pth) - (if (file-exists? pth) - (file->value pth) - (or (with-handlers ([exn:fail? (lambda _ #f)]) (consult-archive pth)) - (error 'read-cache "File is not cached: ~e" pth)))) -(define (read-cache* pth) - (with-handlers ([exn:fail? (lambda (x) #f)]) - (read-cache pth))) -(define (write-cache! pth v) - (write-to-file* v pth)) -(define (delete-cache! pth) - (with-handlers ([exn:fail? void]) - (delete-file pth))) - -(provide/contract - [cache/file-mode (parameter/c (symbols 'always 'cache 'no-cache))] - [cache/file (path-string? (-> any/c) . -> . any/c)] - [cache/file/timestamp (path-string? (-> void) . -> . void)] - [cached-directory-list* (path-string? . -> . (listof path-string?))] - [cached-directory-exists? (path-string? . -> . boolean?)] - [read-cache (path-string? . -> . any/c)] - [read-cache* (path-string? . -> . any/c)] - [write-cache! (path-string? any/c . -> . void)] - [delete-cache! (path-string? . -> . void)]) diff --git a/pkgs/plt-services/meta/drdr/cc.rkt b/pkgs/plt-services/meta/drdr/cc.rkt deleted file mode 100644 index abd6082c97..0000000000 --- a/pkgs/plt-services/meta/drdr/cc.rkt +++ /dev/null @@ -1,81 +0,0 @@ -#lang racket -(require "path-utils.rkt" - "run-collect.rkt" - "replay.rkt" - racket/runtime-path - racket/system) - -(match-define - (list* command real-args) - (vector->list (current-command-line-arguments))) - -(define-match-expander solo-flag - (syntax-rules () - [(_ [flag ...] everything-else) - (list* (or (regexp (string-append "^" (regexp-quote flag) "$" ) (list _)) - ...) - everything-else)])) -(define-match-expander emopt-flag - (syntax-rules () - [(_ [flag ...] everything-else) - (list* (or (regexp (string-append "^" (regexp-quote flag) "(.+)$") (list _ _)) - ...) - everything-else)])) -(define-match-expander opt-flag - (syntax-rules () - [(_ [flag ...] opt everything-else) - (list* (or (regexp (string-append "^" (regexp-quote flag) "$") (list _)) - ...) - (and opt (not (? flag?))) - everything-else)])) - -(define (flag? x) - (equal? #\- (string-ref x 0))) - -(define-syntax-rule (define-snocer var setter!) - (begin (define var empty) - (define (setter! x) - (set! var (append var (list x)))))) - -(define-snocer outputs output!) -(define-snocer inputs input!) - -(define loop - (match-lambda - [(solo-flag ["--version" "-c" "-V" "-v" "-E" "-traditional-cpp" "-g" "-print-search-dirs" "-print-multi-os-directory" "-pthread" "-dynamiclib" "-all_load"] as) (loop as)] - [(emopt-flag ["-O" "-X" "-D" "-m" "-l" "-W" "-I" "-f" "-F"] as) (loop as)] - [(opt-flag ["-install_name" "-compatibility_version" "-current_version" "-framework"] f as) (loop as)] - [(opt-flag ["-o"] f as) (output! f) (loop as)] - [(list* (and (not (? flag?)) f) as) (input! f) (loop as)] - [args - (unless (empty? args) - (error 'drdr-cc "Unhandled args: ~S [~S]" args real-args))])) - -(loop real-args) - -(define cc-path - (find-executable-path command)) - -(define the-input - (match inputs - [(list f) f] - [_ #f])) - -(define-runtime-path output-dir "output") - -(if the-input - (local [(define the-input-base - (apply build-path output-dir (filter path-for-some-system? (explode-path the-input)))) - (define status - (run/collect/wait - #:env (make-hash) - #:timeout (* 60 60) - (path->string cc-path) - real-args))] - - (make-parent-directory the-input-base) - (with-output-to-file (path-add-suffix the-input-base ".log") #:exists 'truncate/replace - (lambda () (write status))) - - (replay-status status)) - (exit (apply system*/exit-code cc-path real-args))) diff --git a/pkgs/plt-services/meta/drdr/config.rkt b/pkgs/plt-services/meta/drdr/config.rkt deleted file mode 100644 index d3a407203a..0000000000 --- a/pkgs/plt-services/meta/drdr/config.rkt +++ /dev/null @@ -1,57 +0,0 @@ -#lang racket - -(require "cache.rkt" - "dirstruct.rkt" - "scm.rkt" - "monitor-scm.rkt") - -(plt-directory "/opt/plt") -(drdr-directory "/opt/svn/drdr") -(git-path "/usr/bin/git") -(Xvfb-path "/usr/bin/Xnest") -(fluxbox-path "/usr/bin/metacity") -(vncviewer-path "/usr/bin/vncviewer") -(current-make-install-timeout-seconds (* 90 60)) -(current-make-timeout-seconds (* 90 60)) -(current-subprocess-timeout-seconds 90) -(current-monitoring-interval-seconds 60) -(number-of-cpus 12) - -(define (string->number* s) - (with-handlers ([exn:fail? (lambda (x) #f)]) - (let ([v (string->number s)]) - (and (number? v) - v)))) - -(define revisions #f) - -(define (init-revisions!) - (set! revisions - (sort - (filter-map - (compose string->number* path->string) - (directory-list (plt-build-directory))) - <))) - -(define (newest-revision) - (last revisions)) - -(define (second-to-last l) - (list-ref l (- (length l) 2))) - -(define (second-newest-revision) - (with-handlers ([exn:fail? (lambda (x) #f)]) - (second-to-last revisions))) - -(define (newest-completed-revision) - (define n (newest-revision)) - (if (read-cache* (build-path (revision-dir n) "analyzed")) - n - (second-newest-revision))) - -(provide/contract - [revisions (or/c false/c (listof exact-nonnegative-integer?))] - [init-revisions! (-> void)] - [newest-revision (-> exact-nonnegative-integer?)] - [second-newest-revision (-> (or/c false/c exact-nonnegative-integer?))] - [newest-completed-revision (-> (or/c false/c exact-nonnegative-integer?))]) diff --git a/pkgs/plt-services/meta/drdr/copy.sh b/pkgs/plt-services/meta/drdr/copy.sh deleted file mode 100755 index 62c2898bfc..0000000000 --- a/pkgs/plt-services/meta/drdr/copy.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -rsync -avz . ${1}drdr:/opt/svn/drdr/ --exclude=compiled --delete --exclude=data --exclude=builds diff --git a/pkgs/plt-services/meta/drdr/diff.rkt b/pkgs/plt-services/meta/drdr/diff.rkt deleted file mode 100644 index e3160005f7..0000000000 --- a/pkgs/plt-services/meta/drdr/diff.rkt +++ /dev/null @@ -1,84 +0,0 @@ -#lang racket -(require "status.rkt") - -(define (timing? bs) - (regexp-match #px#"cpu time: \\d+ real time: \\d+ gc time: \\d+" bs)) - -(define do-not-compare? timing?) - -(define (find-next p? l) - (match l - [(list) - (values)] - [(list-rest (? p? e) l) - (values e l)] - [(list-rest n l) - (call-with-values - (lambda () - (find-next p? l)) - (case-lambda - [() - (values)] - [(e r) - (values e (list* n r))]))])) - -(define (same? b1 b2) - (or (and (do-not-compare? b1) (do-not-compare? b2)) - (bytes=? b1 b2))) -(define (different? b1 b2) - (not (same? b1 b2))) - -(define (log-different? l1 l2) - (let loop ([l1 l1] [l2 l2]) - (match l1 - [(list) - (not (empty? l2))] - [(list-rest e1 r1) - (define (inner bs p? p-bytes) - (call-with-values - (lambda () (find-next p? l2)) - (case-lambda - [() #t] - [(e2 r2) - (or (different? bs (p-bytes e2)) - (loop r1 r2))]))) - (match e1 - [(struct stdout (bs)) - (inner bs stdout? stdout-bytes)] - [(struct stderr (bs)) - (inner bs stderr? stderr-bytes)])]))) - -(define-struct difference (old new)) -(define-struct same-itude (e)) - -(define (render-log-difference l1 l2) - (let loop ([l1 l1] [l2 l2]) - (match l1 - [(list) - (map (match-lambda - [(? stdout? e2) - (make-difference (make-stdout #"") e2)] - [(? stderr? e2) - (make-difference (make-stderr #"") e2)]) - l2)] - [(list-rest e1 r1) - (define (inner bs make-p p? p-bytes) - (call-with-values - (lambda () (find-next p? l2)) - (case-lambda - [() - (list* (make-difference e1 (make-p #"")) - (loop r1 l2))] - [(e2 r2) - (if (different? bs (p-bytes e2)) - (list* (make-difference e1 e2) - (loop r1 r2)) - (list* (make-same-itude e1) - (loop r1 r2)))]))) - (match e1 - [(struct stdout (bs)) - (inner bs make-stdout stdout? stdout-bytes)] - [(struct stderr (bs)) - (inner bs make-stderr stderr? stderr-bytes)])]))) - -(provide (all-defined-out)) diff --git a/pkgs/plt-services/meta/drdr/diffcmd.rkt b/pkgs/plt-services/meta/drdr/diffcmd.rkt deleted file mode 100644 index 39e04f463f..0000000000 --- a/pkgs/plt-services/meta/drdr/diffcmd.rkt +++ /dev/null @@ -1,35 +0,0 @@ -#lang racket -(require racket/system - "dirstruct.rkt" - "status.rkt" - (except-in "diff.rkt" - log-different?) - "path-utils.rkt" - "cache.rkt" - "config.rkt") - -(define event-print - (match-lambda - [(struct stdout (bs)) - (display bs) (newline)] - [(struct stdout (bs)) - (display bs (current-error-port)) (newline)])) - -(define (render-output-diff r1 r2 f) - (define l1 (status-output-log (read-cache (build-path (revision-log-dir r1) f)))) - (define l2 (status-output-log (read-cache (build-path (revision-log-dir r2) f)))) - - (for ([d (in-list (render-log-difference l1 l2))]) - (match d - [(struct difference (e1 e2)) - (printf "! ") - (event-print e1)] - [(struct same-itude (e)) - (printf " ") - (event-print e)]))) - -(command-line #:program "diffcmd" - #:args (rev1 rev2 filename) - (render-output-diff (string->number rev1) - (string->number rev2) - filename)) diff --git a/pkgs/plt-services/meta/drdr/dirstruct.rkt b/pkgs/plt-services/meta/drdr/dirstruct.rkt deleted file mode 100644 index 7651c17da1..0000000000 --- a/pkgs/plt-services/meta/drdr/dirstruct.rkt +++ /dev/null @@ -1,133 +0,0 @@ -#lang racket -(require "path-utils.rkt") - -(define number-of-cpus - (make-parameter 1)) - -(define current-subprocess-timeout-seconds - (make-parameter (* 60 10))) - -(define plt-directory - (make-parameter (build-path (current-directory)))) - -(define (plt-build-directory) - (build-path (plt-directory) "builds")) - -(define (plt-future-build-directory) - (build-path (plt-directory) "future-builds")) - -(define (plt-data-directory) - (build-path (plt-directory) "data")) - -(define drdr-directory - (make-parameter (build-path (current-directory) "drdr"))) - -(define make-path - (make-parameter "/usr/bin/make")) -(define tar-path - (make-parameter "/bin/tar")) - -(define Xvfb-path - (make-parameter "/usr/bin/Xvfb")) - -(define fluxbox-path - (make-parameter "/usr/bin/fluxbox")) - -(define vncviewer-path - (make-parameter "/usr/bin/vncviewer")) - -(define (plt-repository) - (build-path (plt-directory) "repo")) - -(define current-make-timeout-seconds - (make-parameter (* 60 30))) - -(define current-make-install-timeout-seconds - (make-parameter (* 60 30))) - -(define current-rev - (make-parameter #f)) - -(define previous-rev - (make-parameter #f)) - -(define (revision-dir rev) - (build-path (plt-build-directory) (number->string rev))) - -(define (revision-log-dir rev) - (build-path (revision-dir rev) "logs")) - -(define (revision-analyze-dir rev) - (build-path (revision-dir rev) "analyze")) - -(define (revision-trunk-dir rev) - (build-path (revision-dir rev) "trunk")) -(define (revision-trunk.tgz rev) - (build-path (revision-dir rev) "trunk.tgz")) -(define (revision-trunk.tar.7z rev) - (build-path (revision-dir rev) "trunk.tar.7z")) - -(define (revision-commit-msg rev) - (build-path (revision-dir rev) "commit-msg")) - -(define (path->revision pth) - (define builds (explode-path (plt-build-directory))) - (define builds-len (length builds)) - (define pths (explode-path pth)) - (string->number (path->string* (list-ref pths builds-len)))) - -(define (revision-archive rev) - (build-path (revision-dir rev) "archive.db")) - -(define (future-record-path n) - (build-path (plt-future-build-directory) (number->string n))) - -(define (path-timing-log p) - (path-add-suffix (build-path (plt-data-directory) p) #".timing")) - -(define (path-timing-png p) - (path-add-suffix (path-timing-log p) #".png")) -(define (path-timing-html p) - (path-add-suffix (path-timing-log p) #".html")) -(define (path-timing-png-prefix p) - (path-timing-log p)) - -(define build? (make-parameter #t)) - -(define (on-unix?) - (symbol=? 'unix (system-type 'os))) - -(provide/contract - [current-subprocess-timeout-seconds (parameter/c exact-nonnegative-integer?)] - [number-of-cpus (parameter/c exact-nonnegative-integer?)] - [current-rev (parameter/c (or/c false/c exact-nonnegative-integer?))] - [previous-rev (parameter/c (or/c false/c exact-nonnegative-integer?))] - [plt-directory (parameter/c path-string?)] - [plt-build-directory (-> path?)] - [plt-data-directory (-> path?)] - [plt-future-build-directory (-> path?)] - [drdr-directory (parameter/c path-string?)] - [tar-path (parameter/c (or/c false/c string?))] - [make-path (parameter/c (or/c false/c string?))] - [Xvfb-path (parameter/c (or/c false/c string?))] - [vncviewer-path (parameter/c (or/c false/c string?))] - [fluxbox-path (parameter/c (or/c false/c string?))] - [build? (parameter/c boolean?)] - [on-unix? (-> boolean?)] - [plt-repository (-> path?)] - [path-timing-log (path-string? . -> . path?)] - [path-timing-png (path-string? . -> . path?)] - [path-timing-png-prefix (path-string? . -> . path?)] - [path-timing-html (path-string? . -> . path?)] - [future-record-path (exact-nonnegative-integer? . -> . path?)] - [current-make-timeout-seconds (parameter/c exact-nonnegative-integer?)] - [current-make-install-timeout-seconds (parameter/c exact-nonnegative-integer?)] - [revision-dir (exact-nonnegative-integer? . -> . path?)] - [revision-commit-msg (exact-nonnegative-integer? . -> . path?)] - [revision-log-dir (exact-nonnegative-integer? . -> . path?)] - [revision-analyze-dir (exact-nonnegative-integer? . -> . path-string?)] - [revision-trunk-dir (exact-nonnegative-integer? . -> . path?)] - [revision-trunk.tgz (exact-nonnegative-integer? . -> . path?)] - [revision-trunk.tar.7z (exact-nonnegative-integer? . -> . path?)] - [revision-archive (exact-nonnegative-integer? . -> . path?)] - [path->revision (path-string? . -> . exact-nonnegative-integer?)]) diff --git a/pkgs/plt-services/meta/drdr/example.timing b/pkgs/plt-services/meta/drdr/example.timing deleted file mode 100644 index 2bd57d33ce..0000000000 --- a/pkgs/plt-services/meta/drdr/example.timing +++ /dev/null @@ -1,1799 +0,0 @@ -(14986 444.303955078125 ()) -(14988 447.473876953125 ()) -(15328 653.8251953125 ()) -(15329 610.94189453125 ()) -(15330 720.466064453125 ()) -(15332 507.7529296875 ()) -(15334 517.630859375 ()) -(15335 615.64306640625 ()) -(15336 522.546875 ()) -(15338 530.48388671875 ()) -(15340 595.703125 ()) -(15343 656.916015625 ()) -(15344 782.664794921875 ()) -(15345 780.534912109375 ()) -(15346 776.857177734375 ()) -(15347 857.77197265625 ()) -(15348 867.7041015625 ()) -(15350 460.690185546875 ()) -(15351 527.587890625 ()) -(15352 731.757080078125 ()) -(15353 578.455810546875 ()) -(15354 665.490966796875 ()) -(15356 652.208984375 ()) -(15357 736.23388671875 ()) -(15360 497.2021484375 ()) -(15361 634.10302734375 ()) -(15362 558.468017578125 ()) -(15363 468.43505859375 ()) -(15364 689.364013671875 ()) -(15365 710.31103515625 ()) -(15366 739.431884765625 ()) -(15367 430.576904296875 ()) -(15368 623.135986328125 ()) -(15376 479.695068359375 ()) -(15378 438.2119140625 ()) -(15379 449.68994140625 ()) -(15380 450.225830078125 ()) -(15384 461.43896484375 ()) -(15385 431.71484375 ()) -(15386 469.81396484375 ()) -(15387 449.88818359375 ()) -(15388 461.0859375 ()) -(15389 503.448974609375 ()) -(15394 456.789794921875 ()) -(15395 520.847900390625 ()) -(15396 471.989013671875 ()) -(15397 459.48193359375 ()) -(15398 455.37109375 ()) -(15399 482.2880859375 ()) -(15400 475.605224609375 ()) -(15401 496.02392578125 ()) -(15402 452.22412109375 ()) -(15403 460.263916015625 ()) -(15404 431.662841796875 ()) -(15405 454.468017578125 ()) -(15408 482.48193359375 ()) -(15411 422.669921875 ()) -(15413 496.782958984375 ()) -(15466 451.36083984375 ()) -(15467 456.775146484375 ()) -(15477 286.489013671875 ()) -(15479 397.10986328125 ()) -(15483 439.69091796875 ()) -(15484 411.06005859375 ()) -(15485 441.35595703125 ()) -(15486 433.52587890625 ()) -(15487 438.72705078125 ()) -(15488 476.51513671875 ()) -(15489 433.97314453125 ()) -(15490 425.508056640625 ()) -(15493 441.471923828125 ()) -(15494 441.595947265625 ()) -(15495 428.173095703125 ()) -(15496 440.93408203125 ()) -(15499 473.921875 ()) -(15500 449.527099609375 ()) -(15502 417.338134765625 ()) -(15504 445.8251953125 ()) -(15505 742.39306640625 ()) -(15506 478.7529296875 ()) -(15507 672.31201171875 ()) -(15508 453.753173828125 ()) -(15509 544.48193359375 ()) -(15511 493.93896484375 ()) -(15512 444.745849609375 ()) -(15515 454.594970703125 ()) -(15516 456.83203125 ()) -(15517 508.763916015625 ()) -(15518 469.7021484375 ()) -(15520 443.346923828125 ()) -(15521 504.35595703125 ()) -(15523 445.697998046875 ()) -(15524 474.552001953125 ()) -(15525 616.705078125 ()) -(15526 41561.47900390625 ()) -(15527 883.72412109375 ()) -(15528 783.97802734375 ()) -(15529 715.884033203125 ()) -(15530 699.578125 ()) -(15531 781.596923828125 ()) -(15532 751.951171875 ()) -(15533 506.2490234375 ()) -(15538 451.7958984375 ()) -(15539 534.5361328125 ()) -(15540 423.35302734375 ()) -(15545 461.740966796875 ()) -(15546 448.0 ()) -(15547 424.257080078125 ()) -(15548 465.468994140625 ()) -(15550 465.366943359375 ()) -(15552 436.308837890625 ()) -(15553 490.545166015625 ()) -(15554 478.658935546875 ()) -(15555 442.68896484375 ()) -(15556 512.80908203125 ()) -(15557 444.10302734375 ()) -(15559 447.054931640625 ()) -(15560 476.343994140625 ()) -(15561 470.6201171875 ()) -(15565 455.5048828125 ()) -(15566 454.35498046875 ()) -(15569 443.97998046875 ()) -(15570 435.91796875 ()) -(15571 455.356201171875 ()) -(15572 439.757080078125 ()) -(15573 451.35107421875 ()) -(15574 464.68896484375 ()) -(15575 441.43701171875 ()) -(15576 446.91015625 ()) -(15577 476.139892578125 ()) -(15579 444.281005859375 ()) -(15581 443.1640625 ()) -(15582 423.2900390625 ()) -(15583 443.77001953125 ()) -(15584 196.135986328125 ()) -(15585 258.785888671875 ()) -(15586 223.387939453125 ()) -(15587 174.01416015625 ()) -(15588 443.005859375 ()) -(15589 449.7900390625 ()) -(15590 254.305908203125 ()) -(15591 212.2080078125 ()) -(15592 250.468017578125 ()) -(15593 1373.671142578125 ()) -(15594 688.900146484375 ()) -(15595 820.734130859375 ()) -(15596 279.718994140625 ()) -(15597 223.984130859375 ()) -(15598 200.093017578125 ()) -(15599 250.931884765625 ()) -(15600 226.546142578125 ()) -(15603 686.795166015625 ()) -(15604 212.97216796875 ()) -(15607 450.7509765625 ()) -(15608 215.321044921875 ()) -(15609 919.259033203125 ()) -(15610 659.592041015625 ()) -(15611 641.572021484375 ()) -(15612 216.184814453125 ()) -(15613 465.56005859375 ()) -(15614 768.429931640625 ()) -(15616 328.30810546875 ()) -(15617 209.258056640625 ()) -(15618 184.097900390625 ()) -(15619 256.346923828125 ()) -(15621 252.774169921875 ()) -(15622 727.072998046875 ()) -(15623 598.487060546875 ()) -(15624 190.60791015625 ()) -(15625 234.010986328125 ()) -(15626 202.8359375 ()) -(15632 255.149169921875 ()) -(15634 326.754150390625 ()) -(15635 641.169921875 ()) -(15640 617.5849609375 ()) -(15641 281.391845703125 ()) -(15642 1208.906982421875 ()) -(15643 224.631103515625 ()) -(15644 287.325927734375 ()) -(15645 395.14013671875 ()) -(15646 237.5009765625 ()) -(15647 793.87890625 ()) -(15648 773.945068359375 ()) -(15649 485.364990234375 ()) -(15650 799.066162109375 ()) -(15651 241.68994140625 ()) -(15652 235.673095703125 ()) -(15653 837.972900390625 ()) -(15654 263.431884765625 ()) -(15655 221.04296875 ()) -(15656 305.97900390625 ()) -(15657 460.364013671875 ()) -(15658 177.598876953125 ()) -(15659 215.072021484375 ()) -(15660 239.223876953125 ()) -(15661 236.049072265625 ()) -(15662 189.473876953125 ()) -(15663 199.652099609375 ()) -(15664 295.344970703125 ()) -(15665 429.83203125 ()) -(15666 471.344970703125 ()) -(15667 374.429931640625 ()) -(15668 301.03076171875 ()) -(15669 169.170166015625 ()) -(15670 256.81005859375 ()) -(15671 195.1240234375 ()) -(15672 223.08203125 ()) -(15673 199.81787109375 ()) -(15674 218.2490234375 ()) -(15675 247.105224609375 ()) -(15676 232.369873046875 ()) -(15677 393.39501953125 ()) -(15678 263.345947265625 ()) -(15679 344.31591796875 ()) -(15680 245.702880859375 ()) -(15681 435.109130859375 ()) -(15682 356.60791015625 ()) -(15683 477.943115234375 ()) -(15684 651.281005859375 ()) -(15685 1494.45703125 ()) -(15686 146.137939453125 ()) -(15687 209.44189453125 ()) -(15688 286.469970703125 ()) -(15689 531.31103515625 ()) -(15690 327.565185546875 ()) -(15691 514.043212890625 ()) -(15692 1235.074951171875 ()) -(15693 698.278076171875 ()) -(15694 307.04296875 ()) -(15695 842.059814453125 ()) -(15696 193.244140625 ()) -(15697 643.947021484375 ()) -(15698 415.264892578125 ()) -(15699 334.973876953125 ()) -(15700 175.7900390625 ()) -(15701 456.091064453125 ()) -(15702 457.385009765625 ()) -(15703 338.368896484375 ()) -(15704 243.86083984375 ()) -(15705 533.7109375 ()) -(15706 444.51904296875 ()) -(15707 582.884033203125 ()) -(15708 265.97900390625 ()) -(15709 449.925048828125 ()) -(15710 400.548095703125 ()) -(15711 598.43115234375 ()) -(15712 287.118896484375 ()) -(15713 879.7939453125 ()) -(15714 202.06591796875 ()) -(15715 284.866943359375 ()) -(15716 508.63916015625 ()) -(15717 547.975830078125 ()) -(15718 239.833984375 ()) -(15719 767.123046875 ()) -(15720 487.169921875 ()) -(15721 464.330810546875 ()) -(15722 246.111083984375 ()) -(15723 640.0849609375 ()) -(15724 409.73486328125 ()) -(15725 494.302001953125 ()) -(15726 384.080078125 ()) -(15727 197.433837890625 ()) -(15728 195.8779296875 ()) -(15729 614.31396484375 ()) -(15730 228.64697265625 ()) -(15731 913.765869140625 ()) -(15732 286.763916015625 ()) -(15736 398.739990234375 ()) -(15737 587.573974609375 ()) -(15738 317.2119140625 ()) -(15739 339.884033203125 ()) -(15740 234.06201171875 ()) -(15741 632.608154296875 ()) -(15742 769.010986328125 ()) -(15743 564.911865234375 ()) -(15744 216.08203125 ()) -(15745 587.2421875 ()) -(15746 539.075927734375 ()) -(15747 226.077880859375 ()) -(15748 198.10693359375 ()) -(15749 221.738037109375 ()) -(15750 205.7080078125 ()) -(15751 226.31201171875 ()) -(15752 1287.4951171875 ()) -(15755 408.9140625 ()) -(15759 498.678955078125 ()) -(15767 192.51708984375 ()) -(15768 557.19921875 ()) -(15769 590.60400390625 ()) -(15770 245.671875 ()) -(15771 276.01806640625 ()) -(15772 289.384033203125 ()) -(15773 16.66015625 ()) -(15774 231.35205078125 ()) -(15775 356.646240234375 ()) -(15776 415.31396484375 ()) -(15777 464.050048828125 ()) -(15778 447.287109375 ()) -(15779 240.649169921875 ()) -(15780 649.724853515625 ()) -(15781 422.251953125 ()) -(15782 407.904052734375 ()) -(15783 258.493896484375 ()) -(15784 337.39697265625 ()) -(15785 468.034912109375 ()) -(15786 216.653076171875 ()) -(15787 236.393798828125 ()) -(15788 605.47998046875 ()) -(15789 210.778076171875 ()) -(15790 536.826904296875 ()) -(15791 503.030029296875 ()) -(15792 196.392822265625 ()) -(15793 215.609130859375 ()) -(15794 201.367919921875 ()) -(15795 324.80810546875 ()) -(15796 1048.713134765625 ()) -(15797 224.572998046875 ()) -(15798 843.8759765625 ()) -(15799 210.77783203125 ()) -(15800 559.095947265625 ()) -(15801 513.631103515625 ()) -(15802 210.052978515625 ()) -(15803 226.205078125 ()) -(15804 381.966796875 ()) -(15805 686.60498046875 ()) -(15806 229.447998046875 ()) -(15807 590.523193359375 ()) -(15808 699.9248046875 ()) -(15809 562.322998046875 ()) -(15810 353.248046875 ()) -(15811 499.281982421875 ()) -(15812 325.01708984375 ()) -(15813 633.431884765625 ()) -(15814 469.39306640625 ()) -(15815 527.76708984375 ()) -(15816 561.2939453125 ()) -(15817 701.816162109375 ()) -(15818 1168.94287109375 ()) -(15819 258.35693359375 ()) -(15820 529.462890625 ()) -(15821 263.031005859375 ()) -(15822 496.611083984375 ()) -(15823 526.16796875 ()) -(15824 462.18701171875 ()) -(15825 561.541015625 ()) -(15827 459.070068359375 ()) -(15828 519.02001953125 ()) -(15829 485.58984375 ()) -(15830 751.323974609375 ()) -(15831 568.823974609375 ()) -(15832 391.48681640625 ()) -(15833 717.18115234375 ()) -(15834 649.35400390625 ()) -(15835 455.14697265625 ()) -(15836 328.43212890625 ()) -(15837 417.223876953125 ()) -(15838 188.97509765625 ()) -(15839 565.114990234375 ()) -(15840 283.548828125 ()) -(15841 373.027099609375 ()) -(15842 583.48291015625 ()) -(15843 833.76806640625 ()) -(15846 593.83203125 ()) -(15847 661.364013671875 ()) -(15848 391.136962890625 ()) -(15849 535.842041015625 ()) -(15850 1230.958984375 ()) -(15851 434.945068359375 ()) -(15852 551.73486328125 ()) -(15853 256.20703125 ()) -(15854 202.408935546875 ()) -(15855 1112.16796875 ()) -(15856 315.510986328125 ()) -(15857 430.666015625 ()) -(15858 355.39404296875 ()) -(15859 172.89599609375 ()) -(15860 569.90087890625 ()) -(15861 219.0390625 ()) -(15862 383.845947265625 ()) -(15863 304.763916015625 ()) -(15864 675.72119140625 ()) -(15865 1212.755859375 ()) -(15866 784.4921875 ()) -(15867 536.5029296875 ()) -(15868 532.23681640625 ()) -(15869 323.82080078125 ()) -(15870 824.802978515625 ()) -(15871 396.486083984375 ()) -(15872 530.47802734375 ()) -(15873 392.758056640625 ()) -(15874 190.71484375 ()) -(15875 255.969970703125 ()) -(15876 181.10595703125 ()) -(15877 429.621826171875 ()) -(15878 327.273193359375 ()) -(15879 236.19580078125 ()) -(15880 458.833984375 ()) -(15881 456.135986328125 ()) -(15882 664.23095703125 ()) -(15883 424.02099609375 ()) -(15884 689.650146484375 ()) -(15885 509.345947265625 ()) -(15886 552.26611328125 ()) -(15887 248.4658203125 ()) -(15888 458.81005859375 ()) -(15889 476.287109375 ()) -(15890 435.634033203125 ()) -(15891 703.412841796875 ()) -(15892 226.43994140625 ()) -(15895 242.18701171875 ()) -(15899 517.9541015625 ()) -(15900 462.45703125 ()) -(15901 605.09521484375 ()) -(15902 581.179931640625 ()) -(15903 394.39794921875 ()) -(15904 200.11376953125 ()) -(15905 392.057861328125 ()) -(15906 211.39404296875 ()) -(15907 392.156005859375 ()) -(15908 993.780029296875 ()) -(15909 466.470947265625 ()) -(15910 491.529052734375 ()) -(15911 424.606201171875 ()) -(15912 629.114013671875 ()) -(15913 318.975830078125 ()) -(15914 229.8828125 ()) -(15915 627.77294921875 ()) -(15916 361.998046875 ()) -(15917 316.257080078125 ()) -(15918 341.94091796875 ()) -(15919 506.305908203125 ()) -(15920 162.06201171875 ()) -(15921 343.548828125 ()) -(15922 514.7109375 ()) -(15923 992.048828125 ()) -(15924 406.94091796875 ()) -(15925 258.0048828125 ()) -(15926 450.123046875 ()) -(15927 535.22509765625 ()) -(15928 494.949951171875 ()) -(15929 374.06396484375 ()) -(15930 186.559814453125 ()) -(15931 1459.48095703125 ()) -(15932 426.8759765625 ()) -(15933 420.465087890625 ()) -(15934 224.06396484375 ()) -(15935 150.10400390625 ()) -(15936 1041.504150390625 ()) -(15937 223.2578125 ()) -(15938 1223.419921875 ()) -(15939 802.94677734375 ()) -(15940 229.93505859375 ()) -(15941 432.064208984375 ()) -(15942 306.322998046875 ()) -(15943 354.464111328125 ()) -(15944 330.275146484375 ()) -(15945 422.1259765625 ()) -(15946 226.721923828125 ()) -(15947 397.39208984375 ()) -(15948 289.859130859375 ()) -(15949 357.3388671875 ()) -(15950 493.26904296875 ()) -(15952 387.22802734375 ()) -(15953 209.0888671875 ()) -(15954 715.441162109375 ()) -(15955 293.553955078125 ()) -(15956 322.52001953125 ()) -(15957 307.576904296875 ()) -(15958 605.00390625 ()) -(15959 293.6181640625 ()) -(15963 730.260009765625 ()) -(15964 367.532958984375 ()) -(15965 363.537109375 ()) -(15966 228.083984375 ()) -(15967 217.27392578125 ()) -(15968 371.88916015625 ()) -(15969 561.718994140625 ()) -(15970 303.572998046875 ()) -(15971 2620.057861328125 ()) -(15972 205.68798828125 ()) -(15973 205.760986328125 ()) -(15974 178.60107421875 ()) -(15975 191.77392578125 ()) -(15976 309.93994140625 ()) -(15977 337.927001953125 ()) -(15978 251.842041015625 ()) -(15979 250.286865234375 ()) -(15980 522.75 ()) -(15981 547.373046875 ()) -(15982 342.70703125 ()) -(15983 557.0771484375 ()) -(15984 643.68798828125 ()) -(15985 916.658203125 ()) -(15986 290.666015625 ()) -(15987 772.87109375 ()) -(15988 299.85595703125 ()) -(15989 194.2890625 ()) -(15990 221.6640625 ()) -(15991 324.957763671875 ()) -(15992 268.873046875 ()) -(15993 457.659912109375 ()) -(15994 249.629150390625 ()) -(15995 209.85498046875 ()) -(15996 330.409912109375 ()) -(15997 209.594970703125 ()) -(15998 248.684814453125 ()) -(15999 582.60302734375 ()) -(16000 222.5791015625 ()) -(16001 260.048095703125 ()) -(16002 232.549072265625 ()) -(16003 228.5849609375 ()) -(16004 276.406982421875 ()) -(16005 358.406005859375 ()) -(16006 556.02490234375 ()) -(16007 325.554931640625 ()) -(16008 496.007080078125 ()) -(16009 512.574951171875 ()) -(16010 1001.76220703125 ()) -(16011 253.39404296875 ()) -(16012 433.5791015625 ()) -(16013 192.968017578125 ()) -(16014 541.817138671875 ()) -(16015 242.385986328125 ()) -(16016 237.47900390625 ()) -(16017 631.14990234375 ()) -(16018 378.4619140625 ()) -(16019 194.06201171875 ()) -(16020 461.69189453125 ()) -(16021 261.56298828125 ()) -(16022 230.1689453125 ()) -(16023 206.618896484375 ()) -(16024 219.328857421875 ()) -(16025 256.573974609375 ()) -(16026 311.30810546875 ()) -(16027 322.574951171875 ()) -(16028 213.034912109375 ()) -(16030 276.02490234375 ()) -(16032 228.838134765625 ()) -(16033 229.705078125 ()) -(16034 238.4599609375 ()) -(16035 644.81103515625 ()) -(16036 492.927001953125 ()) -(16037 498.39794921875 ()) -(16038 217.616943359375 ()) -(16039 429.0439453125 ()) -(16040 209.6279296875 ()) -(16041 45.5029296875 ()) -(16042 459.52197265625 ()) -(16043 507.641845703125 ()) -(16044 527.366943359375 ()) -(16045 574.68798828125 ()) -(16046 365.7509765625 ()) -(16047 449.2890625 ()) -(16048 429.643798828125 ()) -(16049 222.536865234375 ()) -(16050 217.44482421875 ()) -(16051 941.8369140625 ()) -(16052 399.701171875 ()) -(16053 581.114013671875 ()) -(16054 462.725830078125 ()) -(16055 278.2138671875 ()) -(16056 319.102783203125 ()) -(16057 332.89697265625 ()) -(16058 582.469970703125 ()) -(16059 478.302978515625 ()) -(16060 292.0908203125 ()) -(16061 722.755126953125 ()) -(16062 351.126953125 ()) -(16063 187.677978515625 ()) -(16064 602.450927734375 ()) -(16065 365.83203125 ()) -(16066 370.548095703125 ()) -(16067 275.233154296875 ()) -(16068 921.22900390625 ()) -(16069 495.089111328125 ()) -(16070 246.948974609375 ()) -(16071 571.5419921875 ()) -(16072 477.18408203125 ()) -(16073 389.261962890625 ()) -(16074 519.200927734375 ()) -(16075 241.070068359375 ()) -(16076 448.095947265625 ()) -(16077 317.653076171875 ()) -(16078 394.840087890625 ()) -(16079 568.2451171875 ()) -(16080 585.0751953125 ()) -(16081 226.565185546875 ()) -(16086 260.760009765625 ()) -(16087 453.522216796875 ()) -(16088 268.64013671875 ()) -(16089 681.573974609375 ()) -(16091 709.243896484375 ()) -(16092 760.3828125 ()) -(16094 304.609130859375 ()) -(16095 795.129150390625 ()) -(16097 481.891845703125 ()) -(16098 542.009033203125 ()) -(16101 1049.608154296875 ()) -(16102 220.971923828125 ()) -(16103 477.595947265625 ()) -(16105 533.1640625 ()) -(16106 399.955078125 ()) -(16107 796.04296875 ()) -(16110 642.503173828125 ()) -(16112 423.424072265625 ()) -(16113 1084.260009765625 ()) -(16114 224.635009765625 ()) -(16115 782.483154296875 ()) -(16116 359.394775390625 ()) -(16117 426.10302734375 ()) -(16118 238.4599609375 ()) -(16119 462.40185546875 ()) -(16120 367.791015625 ()) -(16121 381.7548828125 ()) -(16122 445.27197265625 ()) -(16123 282.282958984375 ()) -(16124 385.422119140625 ()) -(16125 282.541015625 ()) -(16126 329.614990234375 ()) -(16127 977.18603515625 ()) -(16128 317.192138671875 ()) -(16129 884.8388671875 ()) -(16130 456.661865234375 ()) -(16131 777.60693359375 ()) -(16132 473.801025390625 ()) -(16133 564.652099609375 ()) -(16134 655.89111328125 ()) -(16135 385.251953125 ()) -(16136 252.64404296875 ()) -(16139 415.08203125 ()) -(16140 256.448974609375 ()) -(16141 422.93603515625 ()) -(16144 561.31494140625 ()) -(16145 925.7080078125 ()) -(16146 430.986083984375 ()) -(16147 729.75390625 ()) -(16148 1042.30908203125 ()) -(16149 339.299072265625 ()) -(16150 586.493896484375 ()) -(16151 236.6650390625 ()) -(16152 429.97802734375 ()) -(16153 288.087890625 ()) -(16154 226.89599609375 ()) -(16155 218.2138671875 ()) -(16156 460.741943359375 ()) -(16157 783.9150390625 ()) -(16158 285.89208984375 ()) -(16159 499.791015625 ()) -(16160 498.715087890625 ()) -(16161 348.01904296875 ()) -(16162 581.072998046875 ()) -(16163 966.65283203125 ()) -(16164 354.2890625 ()) -(16165 494.757080078125 ()) -(16166 369.88818359375 ()) -(16167 380.47412109375 ()) -(16168 732.18994140625 ()) -(16169 429.572998046875 ()) -(16170 768.97900390625 ()) -(16171 459.44189453125 ()) -(16172 331.961181640625 ()) -(16173 246.275146484375 ()) -(16174 384.055908203125 ()) -(16175 575.176025390625 ()) -(16176 547.09912109375 ()) -(16177 382.4169921875 ()) -(16178 255.4541015625 ()) -(16179 507.828125 ()) -(16180 526.946044921875 ()) -(16181 353.119873046875 ()) -(16182 833.386962890625 ()) -(16185 669.550048828125 ()) -(16186 326.64794921875 ()) -(16187 527.888916015625 ()) -(16188 493.185791015625 ()) -(16189 231.998046875 ()) -(16190 232.23388671875 ()) -(16191 669.217041015625 ()) -(16192 332.074951171875 ()) -(16193 957.56396484375 ()) -(16194 916.474853515625 ()) -(16195 198.218017578125 ()) -(16196 332.80810546875 ()) -(16197 781.879150390625 ()) -(16198 412.155029296875 ()) -(16199 270.995849609375 ()) -(16200 632.1162109375 ()) -(16201 911.845947265625 ()) -(16202 681.420166015625 ()) -(16203 551.514892578125 ()) -(16204 236.465087890625 ()) -(16205 665.675048828125 ()) -(16206 547.197998046875 ()) -(16207 427.64501953125 ()) -(16208 303.22802734375 ()) -(16209 513.6220703125 ()) -(16210 495.032958984375 ()) -(16211 534.262939453125 ()) -(16215 382.630859375 ()) -(16216 915.5810546875 ()) -(16217 376.215087890625 ()) -(16218 235.199951171875 ()) -(16219 355.087158203125 ()) -(16220 587.18994140625 ()) -(16221 252.471923828125 ()) -(16223 488.8779296875 ()) -(16225 220.072998046875 ()) -(16226 483.4599609375 ()) -(16227 283.633056640625 ()) -(16228 688.692138671875 ()) -(16229 250.291015625 ()) -(16230 253.51513671875 ()) -(16231 714.90185546875 ()) -(16232 318.041015625 ()) -(16233 594.220947265625 ()) -(16234 259.0439453125 ()) -(16235 485.122802734375 ()) -(16236 275.239013671875 ()) -(16239 990.152099609375 ()) -(16240 319.3349609375 ()) -(16241 479.781982421875 ()) -(16242 560.60302734375 ()) -(16243 335.64990234375 ()) -(16244 392.14111328125 ()) -(16245 380.403076171875 ()) -(16246 315.04296875 ()) -(16248 416.600830078125 ()) -(16249 953.3349609375 ()) -(16250 243.77197265625 ()) -(16251 431.7900390625 ()) -(16252 431.870849609375 ()) -(16253 483.5859375 ()) -(16254 268.430908203125 ()) -(16255 1504.27685546875 ()) -(16260 801.113037109375 ()) -(16261 739.22705078125 ()) -(16263 222.2939453125 ()) -(16264 474.598876953125 ()) -(16265 303.739013671875 ()) -(16274 242.988037109375 ()) -(16275 507.421142578125 ()) -(16276 277.60205078125 ()) -(16277 485.847900390625 ()) -(16278 622.85498046875 ()) -(16279 267.595947265625 ()) -(16280 527.323974609375 ()) -(16281 648.083984375 ()) -(16282 804.114990234375 ()) -(16283 223.593994140625 ()) -(16284 233.02001953125 ()) -(16286 654.76318359375 ()) -(16287 403.125 ()) -(16289 722.501953125 ()) -(16290 1150.387939453125 ()) -(16291 682.135986328125 ()) -(16292 367.455810546875 ()) -(16293 502.0439453125 ()) -(16294 515.9970703125 ()) -(16295 229.33203125 ()) -(16296 295.573974609375 ()) -(16297 531.136962890625 ()) -(16298 537.753173828125 ()) -(16299 273.0830078125 ()) -(16300 925.72802734375 ()) -(16301 498.235107421875 ()) -(16302 449.69091796875 ()) -(16303 322.486083984375 ()) -(16304 279.120849609375 ()) -(16305 574.655029296875 ()) -(16306 812.198974609375 ()) -(16307 251.531982421875 ()) -(16308 568.860107421875 ()) -(16309 983.64697265625 ()) -(16310 428.370849609375 ()) -(16311 1564.387939453125 ()) -(16312 337.727783203125 ()) -(16313 568.9619140625 ()) -(16314 497.072021484375 ()) -(16315 246.1318359375 ()) -(16316 228.7109375 ()) -(16317 592.886962890625 ()) -(16318 570.9140625 ()) -(16319 873.65087890625 ()) -(16320 458.76806640625 ()) -(16321 227.27783203125 ()) -(16322 235.716064453125 ()) -(16323 1046.78515625 ()) -(16324 889.33203125 ()) -(16325 458.661865234375 ()) -(16326 271.39794921875 ()) -(16327 766.5458984375 ()) -(16328 283.158935546875 ()) -(16329 452.702880859375 ()) -(16340 251.81591796875 ()) -(16341 526.10302734375 ()) -(16342 237.93310546875 ()) -(16343 363.012939453125 ()) -(16344 209.64599609375 ()) -(16345 229.85205078125 ()) -(16346 216.89306640625 ()) -(16347 244.5419921875 ()) -(16348 213.53515625 ()) -(16349 230.06103515625 ()) -(16350 241.971923828125 ()) -(16351 258.141845703125 ()) -(16352 208.779052734375 ()) -(16353 209.94287109375 ()) -(16354 246.416015625 ()) -(16355 384.411865234375 ()) -(16356 229.654052734375 ()) -(16357 211.258056640625 ()) -(16358 212.087890625 ()) -(16359 216.35791015625 ()) -(16360 222.781982421875 ()) -(16361 229.4560546875 ()) -(16362 226.7880859375 ()) -(16363 221.351806640625 ()) -(16364 221.574951171875 ()) -(16365 211.266845703125 ()) -(16366 217.699951171875 ()) -(16367 247.52294921875 ()) -(16368 239.717041015625 ()) -(16369 240.943115234375 ()) -(16370 209.614990234375 ()) -(16371 223.19287109375 ()) -(16372 216.039794921875 ()) -(16373 234.952880859375 ()) -(16374 213.77880859375 ()) -(16375 211.883056640625 ()) -(16376 322.31103515625 ()) -(16377 213.85302734375 ()) -(16378 226.153076171875 ()) -(16379 363.412841796875 ()) -(16380 239.322998046875 ()) -(16381 205.22998046875 ()) -(16382 608.02490234375 ()) -(16389 543.057861328125 ()) -(16390 251.5888671875 ()) -(16391 221.166015625 ()) -(16392 219.298095703125 ()) -(16393 205.2529296875 ()) -(16396 183.85107421875 ()) -(16397 216.27197265625 ()) -(16398 177.943115234375 ()) -(16399 177.743896484375 ()) -(16400 190.68798828125 ()) -(16401 318.9677734375 ()) -(16402 208.6220703125 ()) -(16403 384.4580078125 ()) -(16404 183.884033203125 ()) -(16405 259.89306640625 ()) -(16406 312.045166015625 ()) -(16407 176.055908203125 ()) -(16408 187.572998046875 ()) -(16409 192.9609375 ()) -(16411 242.077880859375 ()) -(16412 189.179931640625 ()) -(16413 187.306884765625 ()) -(16414 190.513916015625 ()) -(16416 233.548095703125 ()) -(16417 197.420166015625 ()) -(16418 184.3837890625 ()) -(16421 199.77001953125 ()) -(16423 180.20703125 ()) -(16424 330.43798828125 ()) -(16425 174.635009765625 ()) -(16426 167.7958984375 ()) -(16427 216.823974609375 ()) -(16429 187.3359375 ()) -(16430 182.987060546875 ()) -(16431 178.02099609375 ()) -(16432 179.489013671875 ()) -(16433 185.18212890625 ()) -(16434 183.64306640625 ()) -(16435 205.6748046875 ()) -(16436 202.517822265625 ()) -(16437 197.260009765625 ()) -(16439 173.6640625 ()) -(16440 168.208984375 ()) -(16441 170.39697265625 ()) -(16443 186.3720703125 ()) -(16444 180.9580078125 ()) -(16445 206.796875 ()) -(16446 177.364013671875 ()) -(16447 182.151123046875 ()) -(16448 204.60400390625 ()) -(16449 206.162841796875 ()) -(16451 197.012939453125 ()) -(16452 210.779052734375 ()) -(16453 178.842041015625 ()) -(16454 241.130126953125 ()) -(16455 213.7041015625 ()) -(16456 195.207763671875 ()) -(16457 226.957763671875 ()) -(16458 208.3359375 ()) -(16459 179.782958984375 ()) -(16460 190.325927734375 ()) -(16461 186.655029296875 ()) -(16462 186.796875 ()) -(16463 163.381103515625 ()) -(16464 182.569091796875 ()) -(16465 194.77490234375 ()) -(16466 423.47802734375 ()) -(16467 191.93896484375 ()) -(16468 201.072021484375 ()) -(16469 243.947021484375 ()) -(16470 195.398193359375 ()) -(16471 181.863037109375 ()) -(16472 187.328125 ()) -(16473 126.35302734375 ()) -(16474 176.489013671875 ()) -(16475 205.6669921875 ()) -(16477 197.93505859375 ()) -(16478 173.083984375 ()) -(16479 209.406005859375 ()) -(16480 183.35302734375 ()) -(16481 170.8349609375 ()) -(16482 212.918212890625 ()) -(16483 230.85205078125 ()) -(16486 172.767822265625 ()) -(16487 178.2060546875 ()) -(16490 192.494140625 ()) -(16491 183.657958984375 ()) -(16492 243.934814453125 ()) -(16493 178.39990234375 ()) -(16494 189.97802734375 ()) -(16495 209.573974609375 ()) -(16496 242.675048828125 ()) -(16497 224.284912109375 ()) -(16498 193.166015625 ()) -(16499 177.94189453125 ()) -(16500 214.81787109375 ()) -(16501 232.40087890625 ()) -(16502 264.31494140625 ()) -(16503 215.15380859375 ()) -(16504 679.571044921875 ()) -(16505 224.298095703125 ()) -(16506 178.9970703125 ()) -(16507 237.56396484375 ()) -(16508 220.278076171875 ()) -(16509 210.77197265625 ()) -(16510 226.58984375 ()) -(16511 888.60693359375 ()) -(16512 205.093017578125 ()) -(16513 211.7978515625 ()) -(16514 352.9990234375 ()) -(16515 197.691162109375 ()) -(16516 224.19091796875 ()) -(16517 219.471923828125 ()) -(16518 299.309814453125 ()) -(16519 215.309814453125 ()) -(16520 346.906005859375 ()) -(16521 349.116943359375 ()) -(16523 863.421875 ()) -(16524 187.02099609375 ()) -(16525 346.203125 ()) -(16527 188.638916015625 ()) -(16528 199.93798828125 ()) -(16529 238.1728515625 ()) -(16530 190.02001953125 ()) -(16531 359.90478515625 ()) -(16532 207.64990234375 ()) -(16533 206.2509765625 ()) -(16534 215.951171875 ()) -(16535 184.153076171875 ()) -(16536 191.721923828125 ()) -(16542 213.114990234375 ()) -(16543 248.17822265625 ()) -(16544 320.47802734375 ()) -(16545 195.9619140625 ()) -(16546 250.73291015625 ()) -(16548 277.4521484375 ()) -(16549 228.73388671875 ()) -(16553 210.765869140625 ()) -(16554 192.657958984375 ()) -(16555 207.76904296875 ()) -(16556 198.236083984375 ()) -(16557 211.504150390625 ()) -(16558 205.910888671875 ()) -(16559 285.55810546875 ()) -(16560 207.458984375 ()) -(16561 292.326904296875 ()) -(16563 195.2548828125 ()) -(16564 201.739990234375 ()) -(16565 192.802978515625 ()) -(16567 241.324951171875 ()) -(16569 397.19287109375 ()) -(16570 352.01904296875 ()) -(16571 219.781982421875 ()) -(16574 521.779052734375 ()) -(16582 184.451904296875 ()) -(16585 401.257080078125 ()) -(16587 201.429931640625 ()) -(16588 264.52197265625 ()) -(16592 248.201171875 ()) -(16593 194.067138671875 ()) -(16595 970.948974609375 ()) -(16601 214.598876953125 ()) -(16602 201.134033203125 ()) -(16603 260.43505859375 ()) -(16606 233.05810546875 ()) -(16607 241.045166015625 ()) -(16608 206.050048828125 ()) -(16609 221.643798828125 ()) -(16611 183.095947265625 ()) -(16616 220.098876953125 ()) -(16617 205.305908203125 ()) -(16618 849.932861328125 ()) -(16619 359.705078125 ()) -(16620 254.906005859375 ()) -(16621 190.465087890625 ()) -(16622 197.618896484375 ()) -(16623 197.446044921875 ()) -(16624 219.958984375 ()) -(16625 229.06494140625 ()) -(16626 233.598876953125 ()) -(16627 186.93896484375 ()) -(16628 187.68798828125 ()) -(16629 202.05419921875 ()) -(16630 208.458984375 ()) -(16631 872.306884765625 ()) -(16632 211.154052734375 ()) -(16633 225.10693359375 ()) -(16634 333.2919921875 ()) -(16635 184.89697265625 ()) -(16637 189.94091796875 ()) -(16638 237.405029296875 ()) -(16641 182.572998046875 ()) -(16643 317.869873046875 ()) -(16644 243.06005859375 ()) -(16645 225.5078125 ()) -(16648 196.6669921875 ()) -(16649 262.843017578125 ()) -(16650 211.369140625 ()) -(16651 212.383056640625 ()) -(16652 950.346923828125 ()) -(16653 211.89404296875 ()) -(16654 178.9560546875 ()) -(16656 387.43310546875 ()) -(16660 202.284912109375 ()) -(16661 198.52001953125 ()) -(16662 235.009033203125 ()) -(16663 212.117919921875 ()) -(16665 209.26220703125 ()) -(16668 201.902099609375 ()) -(16673 198.988037109375 ()) -(16676 196.049072265625 ()) -(16677 206.992919921875 ()) -(16678 184.908935546875 ()) -(16680 203.02294921875 ()) -(16681 215.60498046875 ()) -(16682 191.3681640625 ()) -(16683 170.2568359375 ()) -(16690 171.584228515625 ()) -(16691 163.10791015625 ()) -(16692 197.02001953125 ()) -(16693 165.93505859375 ()) -(16694 260.975830078125 ()) -(16695 439.48193359375 ()) -(16696 214.279052734375 ()) -(16697 185.634033203125 ()) -(16699 229.569091796875 ()) -(16700 219.2509765625 ()) -(16704 205.143798828125 ()) -(16712 202.64990234375 ()) -(16716 200.900146484375 ()) -(16723 189.066162109375 ()) -(16727 231.89501953125 ()) -(16730 199.824951171875 ()) -(16732 404.047119140625 ()) -(16733 186.06201171875 ()) -(16734 182.9560546875 ()) -(16735 243.40087890625 ()) -(16736 230.093017578125 ()) -(16737 180.5849609375 ()) -(16738 193.166015625 ()) -(16739 189.429931640625 ()) -(16740 198.22412109375 ()) -(16741 185.5771484375 ()) -(16742 183.212890625 ()) -(16743 202.09912109375 ()) -(16744 189.7529296875 ()) -(16745 186.493896484375 ()) -(16746 207.85888671875 ()) -(16747 208.818115234375 ()) -(16748 182.611083984375 ()) -(16749 211.0908203125 ()) -(16750 199.449951171875 ()) -(16751 178.85302734375 ()) -(16752 194.828125 ()) -(16754 178.84521484375 ()) -(16755 184.655029296875 ()) -(16756 180.375 ()) -(16762 189.15283203125 ()) -(16763 199.60400390625 ()) -(16764 211.116943359375 ()) -(16765 177.40478515625 ()) -(16766 185.541015625 ()) -(16767 199.037841796875 ()) -(16768 200.251953125 ()) -(16769 202.60498046875 ()) -(16770 193.923095703125 ()) -(16771 207.864013671875 ()) -(16772 194.7138671875 ()) -(16773 202.98486328125 ()) -(16774 223.223876953125 ()) -(16775 203.568115234375 ()) -(16776 194.408935546875 ()) -(16777 212.695068359375 ()) -(16778 203.11279296875 ()) -(16779 238.057861328125 ()) -(16780 200.115966796875 ()) -(16781 199.05712890625 ()) -(16782 186.1240234375 ()) -(16783 211.912109375 ()) -(16784 203.912841796875 ()) -(16785 213.075927734375 ()) -(16786 206.216064453125 ()) -(16787 205.449951171875 ()) -(16788 208.755126953125 ()) -(16789 256.123046875 ()) -(16790 190.243896484375 ()) -(16791 201.758056640625 ()) -(16792 195.049072265625 ()) -(16793 226.89697265625 ()) -(16794 244.4111328125 ()) -(16795 203.58203125 ()) -(16796 185.989990234375 ()) -(16797 224.840087890625 ()) -(16798 212.745849609375 ()) -(16799 211.712890625 ()) -(16800 223.672119140625 ()) -(16801 195.1328125 ()) -(16802 197.14404296875 ()) -(16803 233.692138671875 ()) -(16804 210.399169921875 ()) -(16805 190.826904296875 ()) -(16806 204.862060546875 ()) -(16807 230.3740234375 ()) -(16808 186.205078125 ()) -(16809 211.60302734375 ()) -(16810 213.5390625 ()) -(16811 195.259033203125 ()) -(16812 199.7138671875 ()) -(16813 203.4619140625 ()) -(16814 177.3779296875 ()) -(16815 203.6279296875 ()) -(16816 200.198974609375 ()) -(16817 197.90087890625 ()) -(16818 188.576171875 ()) -(16819 198.560791015625 ()) -(16820 275.06201171875 ()) -(16822 190.712890625 ()) -(16824 262.10302734375 ()) -(16825 235.7041015625 ()) -(16828 192.034912109375 ()) -(16829 188.7958984375 ()) -(16830 197.3291015625 ()) -(16831 202.4599609375 ()) -(16832 205.700927734375 ()) -(16833 188.029052734375 ()) -(16834 195.007080078125 ()) -(16835 197.3349609375 ()) -(16838 218.218994140625 ()) -(16839 227.39599609375 ()) -(16840 200.93896484375 ()) -(16841 144.56396484375 ()) -(16842 29.4560546875 ()) -(16843 216.23486328125 ()) -(16844 255.453857421875 ()) -(16845 202.64892578125 ()) -(16847 189.176025390625 ()) -(16848 213.56103515625 ()) -(16849 220.805908203125 ()) -(16851 210.464111328125 ()) -(16852 191.9951171875 ()) -(16854 186.924072265625 ()) -(16855 272.10693359375 ()) -(16857 210.90185546875 ()) -(16858 218.177001953125 ()) -(16859 204.4501953125 ()) -(16860 14617.587158203125 ()) -(16861 15060.81787109375 ()) -(16862 15170.137939453125 ()) -(16863 197.760986328125 ()) -(16864 214.0849609375 ()) -(16865 197.380126953125 ()) -(16866 190.16796875 ()) -(16867 113.2568359375 ()) -(16868 198.14794921875 ()) -(16869 99.385009765625 ()) -(16870 204.52099609375 ()) -(16871 215.2470703125 ()) -(16872 207.055908203125 ()) -(16873 216.625 ()) -(16874 25.5869140625 ()) -(16875 230.211181640625 ()) -(16876 59.76416015625 ()) -(16879 185.7138671875 ()) -(16880 213.032958984375 ()) -(16881 214.452880859375 ()) -(16882 216.114013671875 ()) -(16883 205.94189453125 ()) -(16884 208.364990234375 ()) -(16885 180.194091796875 ()) -(16886 187.244873046875 ()) -(16887 196.23095703125 ()) -(16888 202.48095703125 ()) -(16889 196.5419921875 ()) -(16890 193.64208984375 ()) -(16891 345.0859375 ()) -(16892 1058.5458984375 ()) -(16893 190.4189453125 ()) -(16894 201.93896484375 ()) -(16897 191.27197265625 ()) -(16898 239.26806640625 ()) -(16899 66.447021484375 ()) -(16900 18.114013671875 ()) -(16901 255.166015625 ()) -(16903 337.955810546875 ()) -(16904 214.291015625 ()) -(16906 193.826904296875 ()) -(16907 214.5810546875 ()) -(16910 178.768798828125 ()) -(16911 212.889892578125 ()) -(16912 175.489990234375 ()) -(16914 194.260986328125 ()) -(16916 193.671142578125 ()) -(16917 208.9912109375 ()) -(16918 209.39306640625 ()) -(16919 216.364990234375 ()) -(16920 297.22119140625 ()) -(16921 215.1591796875 ()) -(16923 189.369140625 ()) -(16924 263.014892578125 ()) -(16925 212.025146484375 ()) -(16926 197.60791015625 ()) -(16927 193.471923828125 ()) -(16928 194.138916015625 ()) -(16929 200.7880859375 ()) -(16930 193.0478515625 ()) -(16932 237.14794921875 ()) -(16933 200.5419921875 ()) -(16934 190.44384765625 ()) -(16936 199.2880859375 ()) -(16938 201.802001953125 ()) -(16940 192.136962890625 ()) -(16941 198.775146484375 ()) -(16942 210.487060546875 ()) -(16943 208.64306640625 ()) -(16944 213.342041015625 ()) -(16945 196.216796875 ()) -(16951 218.64404296875 ()) -(16952 190.072998046875 ()) -(16953 232.18798828125 ()) -(16955 193.2470703125 ()) -(16961 211.671142578125 ()) -(16962 186.18212890625 ()) -(16963 198.68603515625 ()) -(16964 196.89892578125 ()) -(16966 221.346923828125 ()) -(16972 203.845947265625 ()) -(16976 205.02099609375 ()) -(16989 193.005126953125 ()) -(16990 193.461181640625 ()) -(16991 196.2958984375 ()) -(16992 190.001953125 ()) -(16993 190.759033203125 ()) -(16994 230.097900390625 ()) -(16995 189.9169921875 ()) -(16996 187.780029296875 ()) -(16997 207.126953125 ()) -(16998 262.45703125 ()) -(16999 179.601806640625 ()) -(17001 91.85205078125 ()) -(17002 34.760986328125 ()) -(17003 17.264892578125 ()) -(17004 180.484130859375 ()) -(17005 190.298828125 ()) -(17006 198.03515625 ()) -(17007 222.76318359375 ()) -(17008 189.10888671875 ()) -(17009 209.51904296875 ()) -(17010 193.699951171875 ()) -(17011 177.136962890625 ()) -(17012 270.39599609375 ()) -(17013 162.427978515625 ()) -(17014 182.485107421875 ()) -(17016 215.825927734375 ()) -(17017 172.221923828125 ()) -(17018 187.931884765625 ()) -(17019 222.212890625 ()) -(17020 213.64501953125 ()) -(17026 180.02490234375 ()) -(17027 446.798095703125 ()) -(17028 192.994140625 ()) -(17029 436.069091796875 ()) -(17030 214.868896484375 ()) -(17031 263.97509765625 ()) -(17032 357.719970703125 ()) -(17033 202.324951171875 ()) -(17037 198.5390625 ()) -(17038 175.075927734375 ()) -(17039 192.52587890625 ()) -(17040 535.448974609375 ()) -(17041 221.321044921875 ()) -(17042 326.757080078125 ()) -(17043 227.946044921875 ()) -(17044 192.694091796875 ()) -(17050 170.216064453125 ()) -(17051 226.261962890625 ()) -(17052 215.126220703125 ()) -(17053 199.716064453125 ()) -(17057 169.346923828125 ()) -(17060 206.803955078125 ()) -(17065 192.349853515625 ()) -(17066 202.01904296875 ()) -(17067 206.192138671875 ()) -(17068 428.760009765625 ()) -(17069 190.075927734375 ()) -(17070 194.93603515625 ()) -(17071 229.93994140625 ()) -(17072 283.611083984375 ()) -(17073 210.587890625 ()) -(17074 200.0751953125 ()) -(17075 214.56396484375 ()) -(17076 226.030029296875 ()) -(17077 215.670166015625 ()) -(17080 190.373046875 ()) -(17081 600.232177734375 ()) -(17082 199.87890625 ()) -(17084 244.818115234375 ()) -(17085 209.7490234375 ()) -(17091 208.197998046875 ()) -(17092 235.91796875 ()) -(17093 218.012939453125 ()) -(17102 194.30810546875 ()) -(17105 205.85498046875 ()) -(17106 197.626953125 ()) -(17107 191.76318359375 ()) -(17108 187.281982421875 ()) -(17109 202.89501953125 ()) -(17110 201.593994140625 ()) -(17111 192.18505859375 ()) -(17112 209.367919921875 ()) -(17113 213.373046875 ()) -(17114 203.2109375 ()) -(17115 200.745849609375 ()) -(17118 192.916015625 ()) -(17121 183.267822265625 ()) -(17122 203.828125 ()) -(17123 230.18505859375 ()) -(17124 219.802978515625 ()) -(17125 218.867919921875 ()) -(17129 212.7509765625 ()) -(17132 211.821044921875 ()) -(17133 191.391845703125 ()) -(17134 263.070068359375 ()) -(17135 199.09619140625 ()) -(17136 208.56005859375 ()) -(17137 202.587890625 ()) -(17138 209.425048828125 ()) -(17139 227.261962890625 ()) -(17140 233.823974609375 ()) -(17141 214.3349609375 ()) -(17142 236.919921875 ()) -(17143 223.39013671875 ()) -(17144 222.508056640625 ()) -(17146 227.2958984375 ()) -(17147 217.656005859375 ()) -(17149 236.881103515625 ()) -(17156 220.18994140625 ()) -(17157 217.64013671875 ()) -(17158 228.72802734375 ()) -(17159 207.43212890625 ()) -(17161 219.03515625 ()) -(17162 208.52099609375 ()) -(17163 226.407958984375 ()) -(17164 437.928955078125 ()) -(17165 223.27490234375 ()) -(17166 236.44384765625 ()) -(17167 399.708984375 ()) -(17168 218.2041015625 ()) -(17169 225.22900390625 ()) -(17170 208.5 ()) -(17171 226.721923828125 ()) -(17172 221.023193359375 ()) -(17173 219.766845703125 ()) -(17175 238.425048828125 ()) -(17176 221.861083984375 ()) -(17177 258.929931640625 ()) -(17178 236.23095703125 ()) -(17179 231.282958984375 ()) -(17181 200.89892578125 ()) -(17184 313.18896484375 ()) -(17185 214.4130859375 ()) -(17186 223.60498046875 ()) -(17187 233.48388671875 ()) -(17188 216.93310546875 ()) -(17189 216.446044921875 ()) -(17190 225.37109375 ()) -(17191 235.7109375 ()) -(17192 222.200927734375 ()) -(17193 240.18896484375 ()) -(17194 217.94580078125 ()) -(17195 263.30908203125 ()) -(17196 296.843994140625 ()) -(17197 210.338134765625 ()) -(17198 216.77197265625 ()) -(17202 219.666015625 ()) -(17205 226.297119140625 ()) -(17207 241.350830078125 ()) -(17208 256.35498046875 ()) -(17210 256.73388671875 ()) -(17212 205.22412109375 ()) -(17215 232.092041015625 ()) -(17217 205.303955078125 ()) -(17218 235.501953125 ()) -(17219 223.913818359375 ()) -(17222 233.551025390625 ()) -(17223 225.380126953125 ()) -(17226 204.39697265625 ()) -(17227 239.22216796875 ()) -(17228 252.01708984375 ()) -(17229 264.679931640625 ()) -(17230 232.80712890625 ()) -(17231 272.929931640625 ()) -(17233 359.830078125 ()) -(17234 288.55419921875 ()) -(17235 184.576904296875 ()) -(17236 243.380859375 ()) -(17237 239.4521484375 ()) -(17238 245.555908203125 ()) -(17239 213.405029296875 ()) -(17240 239.93896484375 ()) -(17241 255.9189453125 ()) -(17242 232.34912109375 ()) -(17243 211.257080078125 ()) -(17244 213.48486328125 ()) -(17245 281.444091796875 ()) -(17246 236.52001953125 ()) -(17247 311.158935546875 ()) -(17248 274.781982421875 ()) -(17252 274.2919921875 ()) -(17256 213.39892578125 ()) -(17257 236.177001953125 ()) -(17259 262.18798828125 ()) -(17260 229.6650390625 ()) -(17261 221.5830078125 ()) -(17266 227.7900390625 ()) -(17267 231.2880859375 ()) -(17268 227.113037109375 ()) -(17271 297.106201171875 ()) -(17274 233.030029296875 ()) -(17275 231.2060546875 ()) -(17278 201.431884765625 ()) -(17279 215.219970703125 ()) -(17280 361.47119140625 ()) -(17281 252.9951171875 ()) -(17282 220.27197265625 ()) -(17283 242.26904296875 ()) -(17284 271.56689453125 ()) -(17285 232.130859375 ()) -(17286 257.38818359375 ()) -(17287 217.986083984375 ()) -(17288 224.260986328125 ()) -(17289 259.208984375 ()) -(17290 212.091796875 ()) -(17291 207.217041015625 ()) -(17292 206.427001953125 ()) -(17293 221.860107421875 ()) -(17294 206.3310546875 ()) -(17295 230.109130859375 ()) -(17296 214.906005859375 ()) -(17297 332.05712890625 ()) -(17298 717.22314453125 ()) -(17299 220.205810546875 ()) -(17300 388.580078125 ()) -(17301 213.0830078125 ()) -(17302 232.573974609375 ()) -(17303 245.802001953125 ()) -(17304 281.2841796875 ()) -(17305 241.3662109375 ()) -(17306 360.838134765625 ()) -(17307 214.51708984375 ()) -(17308 223.68701171875 ()) -(17309 251.799072265625 ()) -(17310 213.880126953125 ()) -(17311 353.569091796875 ()) -(17312 358.68896484375 ()) -(17313 216.494140625 ()) -(17314 222.054931640625 ()) -(17315 200.630126953125 ()) -(17316 235.64599609375 ()) -(17317 309.95703125 ()) -(17319 213.553955078125 ()) -(17328 240.906005859375 ()) -(17330 567.9072265625 ()) -(17331 234.177001953125 ()) -(17332 255.843994140625 ()) -(17333 225.530029296875 ()) -(17334 203.8759765625 ()) -(17335 206.27880859375 ()) -(17336 271.05615234375 ()) -(17337 231.291015625 ()) -(17338 238.06103515625 ()) -(17339 215.442138671875 ()) -(17340 206.33984375 ()) -(17341 236.4599609375 ()) -(17343 278.5390625 ()) -(17344 232.26904296875 ()) -(17345 258.367919921875 ()) -(17346 242.009033203125 ()) -(17347 237.113037109375 ()) -(17348 252.596923828125 ()) -(17349 337.533935546875 ()) -(17350 204.35693359375 ()) -(17351 216.470947265625 ()) -(17352 204.947998046875 ()) -(17353 267.7080078125 ()) -(17354 559.06494140625 ()) -(17355 243.657958984375 ()) -(17356 224.35400390625 ()) -(17357 229.80810546875 ()) -(17358 252.705810546875 ()) -(17359 244.622802734375 ()) -(17360 233.283935546875 ()) -(17361 257.22021484375 ()) -(17362 268.10107421875 ()) -(17363 249.962890625 ()) -(17364 265.905029296875 ()) -(17365 215.3671875 ()) -(17366 257.8330078125 ()) -(17367 246.51220703125 ()) -(17368 238.80615234375 ()) -(17369 219.589111328125 ()) -(17370 254.156982421875 ()) -(17371 220.743896484375 ()) -(17372 255.90185546875 ()) -(17373 228.7099609375 ()) -(17374 286.965087890625 ()) -(17375 376.18603515625 ()) -(17376 276.0849609375 ()) -(17377 253.81982421875 ()) -(17378 274.2548828125 ()) -(17379 223.541015625 ()) -(17380 383.072021484375 ()) -(17381 252.4560546875 ()) -(17382 251.39599609375 ()) -(17383 225.555908203125 ()) -(17384 213.406005859375 ()) -(17385 204.450927734375 ()) -(17386 293.4658203125 ()) -(17387 274.966064453125 ()) -(17388 252.80517578125 ()) -(17389 209.25 ()) -(17390 210.18701171875 ()) -(17391 468.68408203125 ()) -(17392 222.483154296875 ()) -(17393 251.48095703125 ()) -(17394 210.875 ()) -(17395 345.056884765625 ()) -(17396 235.412841796875 ()) -(17397 244.77099609375 ()) -(17398 220.72216796875 ()) -(17399 250.878173828125 ()) -(17400 274.295166015625 ()) -(17401 262.614013671875 ()) -(17402 210.541015625 ()) -(17403 210.696044921875 ()) -(17404 217.849853515625 ()) -(17405 522.740966796875 ()) -(17406 216.107177734375 ()) -(17407 208.11279296875 ()) -(17408 261.966064453125 ()) -(17409 223.9970703125 ()) -(17410 220.125 ()) -(17411 204.85400390625 ()) -(17412 239.387939453125 ()) -(17413 232.327880859375 ()) -(17414 230.650146484375 ()) -(17415 216.077880859375 ()) -(17416 220.302978515625 ()) -(17417 235.83203125 ()) -(17418 233.0009765625 ()) -(17419 239.639892578125 ()) -(17420 240.087890625 ()) -(17421 210.804931640625 ()) -(17422 219.835205078125 ()) -(17423 212.989013671875 ()) -(17424 222.77294921875 ()) -(17425 250.509033203125 ()) -(17426 426.703125 ()) -(17427 236.199951171875 ()) -(17428 234.98681640625 ()) -(17429 251.23291015625 ()) -(17430 230.822998046875 ()) -(17431 203.14111328125 ()) -(17432 234.0498046875 ()) -(17433 255.175048828125 ()) -(17434 274.951171875 ()) -(17435 233.765869140625 ()) -(17436 219.5830078125 ()) -(17437 282.845947265625 ()) -(17438 264.966796875 ()) -(17439 223.4658203125 ()) -(17440 348.634033203125 ()) -(17441 243.40478515625 ()) -(17442 208.2177734375 ()) -(17443 222.010986328125 ()) -(17444 204.924072265625 ()) -(17445 238.264892578125 ()) -(17446 247.196044921875 ()) -(17447 254.76220703125 ()) -(17448 387.44384765625 ()) -(17449 236.927001953125 ()) -(17450 235.263916015625 ()) -(17451 420.284912109375 ()) -(17452 228.743896484375 ()) -(17453 229.424072265625 ()) -(17454 254.024169921875 ()) -(17455 277.580078125 ()) -(17456 764.60595703125 ()) -(17457 648.06201171875 ()) -(17458 468.030029296875 ()) -(17459 234.14794921875 ()) -(17460 209.182861328125 ()) -(17461 256.89404296875 ()) -(17462 223.7958984375 ()) -(17463 213.338134765625 ()) -(17464 254.02392578125 ()) -(17465 217.4140625 ()) -(17466 235.7080078125 ()) -(17467 432.0771484375 ()) -(17468 358.671875 ()) -(17469 595.58203125 ()) -(17470 663.305908203125 ()) -(17471 218.992919921875 ()) -(17472 258.255859375 ()) -(17473 434.033935546875 ()) -(17474 474.484130859375 ()) -(17475 240.152099609375 ()) -(17476 541.37890625 ()) -(17477 236.882080078125 ()) -(17478 237.993896484375 ()) -(17479 279.330810546875 ()) -(17480 243.621826171875 ()) -(17481 201.067138671875 ()) -(17482 212.14111328125 ()) -(17483 173.16015625 ()) -(17484 268.7568359375 ()) -(17485 284.308837890625 ()) -(17486 262.961181640625 ()) -(17487 242.0390625 ()) -(17488 213.126953125 ()) -(17489 242.72607421875 ()) -(17490 242.81689453125 ()) -(17491 207.220947265625 ()) -(17492 594.4609375 ()) -(17493 415.7041015625 ()) -(17494 313.47802734375 ()) -(17495 255.364990234375 ()) -(17496 477.849853515625 ()) -(17498 233.712890625 ()) -(17499 244.6630859375 ()) -(17504 244.420166015625 ()) -(17505 323.117919921875 ()) -(17506 226.654052734375 ()) -(17507 211.0009765625 ()) -(17509 201.031005859375 ()) -(17513 254.43505859375 ()) -(17514 250.8720703125 ()) -(17515 411.81103515625 ()) -(17516 248.783935546875 ()) -(17517 219.93798828125 ()) -(17518 225.68212890625 ()) -(17519 326.4130859375 ()) -(17520 261.09619140625 ()) -(17521 252.19384765625 ()) -(17522 237.51806640625 ()) -(17523 251.5 ()) -(17524 242.836181640625 ()) -(17525 229.364990234375 ()) -(17526 261.279052734375 ()) -(17527 421.988037109375 ()) -(17528 636.613037109375 ()) -(17529 920.384033203125 ()) -(17530 209.146240234375 ()) -(17531 266.985107421875 ()) -(17532 363.7880859375 ()) -(17533 242.742919921875 ()) -(17534 275.508056640625 ()) -(17535 223.19091796875 ()) -(17536 176.047119140625 ()) -(17537 207.47900390625 ()) -(17538 222.183837890625 ()) -(17539 214.26611328125 ()) -(17540 209.31298828125 ()) -(17541 232.140869140625 ()) -(17542 239.55908203125 ()) -(17543 524.740966796875 ()) -(17544 257.030029296875 ()) -(17545 193.010986328125 ()) -(17546 298.0771484375 ()) -(17547 326.202880859375 ()) -(17548 274.125 ()) -(17549 415.8740234375 ()) -(17550 407.7509765625 ()) -(17551 235.861083984375 ()) -(17552 235.416015625 ()) -(17553 333.131103515625 ()) -(17554 583.5458984375 ()) -(17555 299.700927734375 ()) -(17556 358.70703125 ()) -(17557 259.166015625 ()) -(17558 347.77197265625 ()) -(17559 229.610107421875 ()) -(17560 496.76513671875 ()) -(17561 439.65185546875 ()) -(17562 273.4541015625 ()) -(17563 265.920166015625 ()) -(17564 472.462890625 ()) -(17565 353.41796875 ()) -(17566 224.5810546875 ()) -(17567 680.43603515625 ()) -(17568 413.47802734375 ()) -(17570 389.56982421875 ()) -(17571 528.2548828125 ()) -(17573 350.60205078125 ()) -(17574 327.398193359375 ()) -(17575 219.421142578125 ()) -(17576 493.19482421875 ()) -(17577 249.26708984375 ()) -(17578 298.98193359375 ()) -(17579 340.991943359375 ()) -(17580 325.55078125 ()) -(17581 282.626953125 ()) -(17582 223.893798828125 ()) -(17583 231.52197265625 ()) -(17584 292.866943359375 ()) -(17585 484.120849609375 ()) -(17586 252.243896484375 ()) -(17587 377.448974609375 ()) -(17588 260.751953125 ()) -(17589 444.769775390625 ()) -(17591 321.16796875 ()) -(17592 654.948974609375 ()) -(17593 241.468994140625 ()) -(17594 263.77490234375 ()) -(17595 345.7158203125 ()) -(17596 237.75 ()) -(17597 408.7841796875 ()) -(17598 495.844970703125 ()) -(17599 385.099853515625 ()) -(17600 215.09716796875 ()) -(17601 666.43994140625 ()) -(17602 203.1328125 ()) -(17603 339.262939453125 ()) -(17604 361.69482421875 ()) -(17605 182.296142578125 ()) -(17606 190.998046875 ()) -(17608 206.75390625 ()) -(17609 182.032958984375 ()) -(17612 175.51904296875 ()) -(17613 173.717041015625 ()) -(17614 174.5458984375 ()) -(17615 324.10888671875 ()) -(17616 298.1728515625 ()) -(17617 175.35595703125 ()) -(17619 181.29296875 ()) -(17620 241.027099609375 ()) -(17621 449.5869140625 ()) -(17623 180.214111328125 ()) -(17624 221.004150390625 ()) -(17626 214.345947265625 ()) -(17628 189.39208984375 ()) -(17629 308.556884765625 ()) -(17630 332.678955078125 ()) -(17630 332.678955078125 ()) -(17632 411.300048828125 ()) -(17634 285.131103515625 ()) -(17635 168.318115234375 ()) -(17636 170.350830078125 ()) -(17637 177.697998046875 ()) -(17639 240.787841796875 ()) -(17640 322.679931640625 ()) -(17641 404.594970703125 ()) -(17642 192.991943359375 ()) -(17643 175.763916015625 ()) -(17644 196.37109375 ()) -(17645 173.511962890625 ()) -(17647 172.442138671875 ()) -(17648 172.3798828125 ()) -(17649 447.531005859375 ()) -(17651 159.703857421875 ()) -(17652 312.0439453125 ()) -(17653 219.493896484375 ()) -(17654 156.47900390625 ()) -(17655 170.059814453125 ()) diff --git a/pkgs/plt-services/meta/drdr/formats.rkt b/pkgs/plt-services/meta/drdr/formats.rkt deleted file mode 100644 index ed03a64a75..0000000000 --- a/pkgs/plt-services/meta/drdr/formats.rkt +++ /dev/null @@ -1,34 +0,0 @@ -#lang racket -(define (formats v u) - (if (equal? v -inf.0) - "ε" - (with-handlers ([exn:fail? (lambda (x) - (format "~a~a" - (number->string v) u))]) - (format "~a~a" - (real->decimal-string v 2) u)))) - -(define (format-duration-h h) - (formats h "h")) - -(define (format-duration-m m) - (if (m . >= . 60) - (format-duration-h (/ m 60)) - (formats m "m"))) - -(define (format-duration-s s) - (if (s . >= . 60) - (format-duration-m (/ s 60)) - (formats s "s"))) - -(define (format-duration-ms ms) - (if (ms . >= . 1000) - (format-duration-s (/ ms 1000)) - (formats ms "ms"))) - -(provide/contract - [formats (number? string? . -> . string?)] - [format-duration-h (number? . -> . string?)] - [format-duration-m (number? . -> . string?)] - [format-duration-s (number? . -> . string?)] - [format-duration-ms (number? . -> . string?)]) diff --git a/pkgs/plt-services/meta/drdr/good-init.sh b/pkgs/plt-services/meta/drdr/good-init.sh deleted file mode 100755 index d50f8bc389..0000000000 --- a/pkgs/plt-services/meta/drdr/good-init.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh - -export PLTSTDERR="info" -PLTROOT="/opt/plt/plt" -LOGS="/opt/plt/logs" -R="$PLTROOT/bin/racket" -DRDR="/opt/svn/drdr" - -cd "$DRDR" - -kill_all() { - cat "$LOGS/"*.pid > /tmp/leave-pids-$$ - KILL=`pgrep '^(Xorg|Xnest|Xvfb|Xvnc|fluxbox|racket|gracket(-text)?)$' | grep -w -v -f /tmp/leave-pids-$$` - rm /tmp/leave-pids-$$ - kill -15 $KILL - sleep 2 - kill -9 $KILL - sleep 1 -} - -run_loop () { # - while true; do - if [ "x$2" = "xyes" ]; then - echo "clearing unattached shm regions" - ipcs -ma | awk '0 == $6 {print $2}' | xargs -n 1 ipcrm -m - fi - echo "$1: compiling" - "$PLTROOT/bin/raco" make "$1.rkt" - echo "$1: running" - "$R" -t "$1.rkt" & - echo "$!" > "$LOGS/$1.pid" - wait "$!" - echo "$1: died" - rm "$LOGS/$1.pid" - if [ "x$2" = "xyes" ]; then - echo "killing processes" - kill_all - fi - done -} - -exec - -run_loop render & -run_loop main yes & diff --git a/pkgs/plt-services/meta/drdr/house-call.rkt b/pkgs/plt-services/meta/drdr/house-call.rkt deleted file mode 100644 index 1f1f645558..0000000000 --- a/pkgs/plt-services/meta/drdr/house-call.rkt +++ /dev/null @@ -1,115 +0,0 @@ -#lang racket -(require racket/runtime-path - racket/date - "list-count.rkt" - "scm.rkt" - "formats.rkt" - "cache.rkt" - "metadata.rkt" - "analyze.rkt" - "rendering.rkt" - "plt-build.rkt" - "status.rkt" - "replay.rkt" - "notify.rkt" - "path-utils.rkt" - "dirstruct.rkt") - -(build? #f) - -(define show-log - (command-line #:program "house-call" - #:once-each - [("-j" "--jobs") jobs "How many processes to run simultaneously" (number-of-cpus (string->number jobs))] - ["--build" "Build the source first" (build? #t)] - #:args log-to-view - log-to-view)) - -; Find paths we need -(define (path->string^ p) - (and p (path->string p))) - -(git-path (path->string^ (find-executable-path "git"))) -(Xvfb-path (and (on-unix?) (path->string^ (find-executable-path "Xvfb")))) -(fluxbox-path (and (on-unix?) (path->string^ (find-executable-path "fluxbox")))) - -; Find where we are -(define-runtime-path here ".") -(drdr-directory here) -(define this-rev-dir (build-path here 'up 'up 'up)) - -; Setup directories that DrDr needs -(define (make-file-or-directory-link* from to) - (unless (link-exists? to) - (make-file-or-directory-link from to))) - -(define house-calls (build-path this-rev-dir "house-calls")) -(plt-directory house-calls) -(for ([d (in-list (list "builds" "future-builds" "data"))]) - (make-directory* (build-path house-calls d))) - -(make-file-or-directory-link* this-rev-dir (build-path house-calls "repo")) -(make-file-or-directory-link* this-rev-dir (build-path house-calls "plt")) - -; Make up a revision and link it in -(define fake-rev (date->julian/scalinger (current-date))) -(current-rev fake-rev) -(define fake-trunk (revision-trunk-dir fake-rev)) -(make-parent-directory fake-trunk) -(make-file-or-directory-link* this-rev-dir fake-trunk) -(write-cache! (revision-commit-msg fake-rev) - (make-git-push fake-rev "you!" empty)) - -; Override the props file -(hash-set! props-cache fake-rev - (dynamic-require `(file ,(path->string (build-path this-rev-dir "collects" "meta" "props"))) - 'get-prop)) - -; Setup the logger -(void - (thread - (lambda () - (define recv (make-log-receiver (current-logger) 'info)) - (let loop () - (match-define (vector level msg val) (sync recv)) - (display msg) (newline) - (loop))))) - -; Do it! -(notify! "DrDr is making a house call...") -(integrate-revision fake-rev) - -(define re (rebase-path (revision-log-dir fake-rev) "/")) -(define (print-lc label lc) - (define l (lc->list lc)) - (unless (empty? l) - (printf "~a:\n" label) - (for ([bs (in-list l)]) - (printf "\t~a\n" - (substring (path->string* (re (bytes->path bs))) 1))) - (newline))) - -(match (analyze-logs fake-rev) - [(struct rendering (start end duration timeout unclean stderr _ _)) - - (print-lc "Timeout" timeout) - (print-lc "Unclean Exit" unclean) - (print-lc "STDERR Output" stderr) - - (printf "Duration (Abs): ~a\n" - (format-duration-ms (- end start))) - (printf "Duration (Sum): ~a\n" - (format-duration-ms duration))] - [#f - (void)]) - -(for ([p (in-list show-log)]) - (define lp (build-path (revision-log-dir fake-rev) p)) - (match (read-cache lp) - [(? status? s) - (newline) - (printf "Replaying ~a:\n" p) - (printf "~a\n" (regexp-replace* #rx"" (apply string-append (add-between (status-command-line s) " ")) (number->string fake-rev))) - (replay-status s)] - [x - (printf "Could not get ~a's log; got: ~s\n" p x)])) diff --git a/pkgs/plt-services/meta/drdr/info.rkt b/pkgs/plt-services/meta/drdr/info.rkt deleted file mode 100644 index eee3ba17a6..0000000000 --- a/pkgs/plt-services/meta/drdr/info.rkt +++ /dev/null @@ -1,6 +0,0 @@ -#lang info - -(define name "DrDr") -(define compile-omit-paths 'all) - -(define test-responsibles '((all jay))) diff --git a/pkgs/plt-services/meta/drdr/installed-software b/pkgs/plt-services/meta/drdr/installed-software deleted file mode 100644 index 6b516aff39..0000000000 --- a/pkgs/plt-services/meta/drdr/installed-software +++ /dev/null @@ -1,413 +0,0 @@ -adduser install -apparmor install -apparmor-utils install -apt install -apt-utils install -aptitude install -ash install -at install -autoconf install -automake install -autotools-dev install -base-files install -base-passwd install -bash install -bash-completion install -belocs-locales-bin install -bind9-host install -binutils install -binutils-static install -bsdmainutils install -bsdutils install -busybox-initramfs install -bzip2 install -ca-certificates install -command-not-found install -command-not-found-data install -console-setup install -console-terminus install -coreutils install -cpio install -cpp install -cpp-4.2 install -cpp-4.3 install -cron install -dash install -debconf install -debconf-i18n install -debianutils install -defoma install -dhcp3-client install -dhcp3-common install -diff install -dmidecode install -dmsetup install -dnsutils install -dosfstools install -dpkg install -e2fslibs install -e2fsprogs install -ed install -eject install -ethtool install -fdutils install -file install -findutils install -fontconfig install -fontconfig-config install -friendly-recovery install -ftp install -fuse-utils install -g++ install -g++-4.3 install -gcc install -gcc-4.2 install -gcc-4.2-base install -gcc-4.3 install -gcc-4.3-base install -gdb install -gettext-base install -gnupg install -gpgv install -grep install -groff-base install -grub install -gzip install -hdparm install -hostname install -ifupdown install -info install -initramfs-tools install -initscripts install -inputattach install -installation-report install -iproute install -iptables install -iputils-arping install -iputils-ping install -iputils-tracepath install -kbd install -klibc-utils install -klogd install -laptop-detect install -less install -libacl1 install -libapparmor-perl install -libapparmor1 install -libapr1 install -libaprutil1 install -libatm1 install -libattr1 install -libbind9-40 install -libblkid1 install -libbz2-1.0 install -libc6 install -libc6-dev install -libc6-i686 install -libcap1 install -libcap2 install -libck-connector0 install -libclass-accessor-perl install -libcomerr2 install -libcompress-raw-zlib-perl install -libcompress-zlib-perl install -libconsole install -libcurl3-gnutls install -libcwidget3 install -libdb4.6 install -libdb4.7 install -libdbus-1-3 install -libdevmapper1.02.1 install -libdns43 install -libdrm2 install -libedit2 install -libelf1 install -libelfg0 install -libept0 install -libexpat1 install -libfont-afm-perl install -libfontconfig1 install -libfontenc1 install -libfreetype6 install -libfribidi0 install -libfuse2 install -libgc1c2 install -libgcc1 install -libgcrypt11 install -libgdbm3 install -libgl1-mesa-dev install -libgl1-mesa-dri install -libgl1-mesa-glx install -libglu1-mesa install -libglu1-mesa-dev install -libgmp3c2 install -libgnutls26 install -libgomp1 install -libgpg-error0 install -libgpm2 install -libhal1 install -libhtml-format-perl install -libhtml-parser-perl install -libhtml-tagset-perl install -libhtml-template-perl install -libhtml-tree-perl install -libice-dev install -libice6 install -libidn11 install -libio-compress-base-perl install -libio-compress-zlib-perl install -libio-string-perl install -libisc44 install -libisccc40 install -libisccfg40 install -libiw29 install -libkeyutils1 install -libklibc install -libkrb53 install -libldap-2.4-2 install -liblocale-gettext-perl install -liblockfile1 install -libltdl7 install -libltdl7-dev install -liblwres40 install -liblzo2-2 install -libmagic1 install -libmailtools-perl install -libmpfr1ldbl install -libmysqlclient15off install -libncurses5 install -libncursesw5 install -libneon27-gnutls install -libnewt0.52 install -libntfs-3g28 install -libpam-modules install -libpam-runtime install -libpam0g install -libparse-debianchangelog-perl install -libparted1.8-9 install -libpcap0.8 install -libpci3 install -libpcre3 install -libpcre3-dev install -libpcrecpp0 install -libpcsclite1 install -libpixman-1-0 install -libpopt0 install -libpq5 install -libpthread-stubs0 install -libpthread-stubs0-dev install -libreadline5 install -librpc-xml-perl install -libsasl2-2 install -libsasl2-modules install -libselinux1 install -libsepol1 install -libsigc++-2.0-0c2a install -libslang2 install -libsm-dev install -libsm6 install -libsqlite3-0 install -libsqlite3-dev install -libss2 install -libssl0.9.8 install -libstdc++6 install -libstdc++6-4.3-dev install -libsvn1 install -libsysfs2 install -libtasn1-3 install -libterm-readkey-perl install -libtext-charwidth-perl install -libtext-iconv-perl install -libtext-wrapi18n-perl install -libtimedate-perl install -libtool install -liburi-perl install -libusb-0.1-4 install -libuuid1 install -libvolume-id0 install -libwrap0 install -libwww-perl install -libx11-6 install -libx11-data install -libx11-dev install -libxapian15 install -libxau-dev install -libxau6 install -libxaw7 install -libxaw7-dev install -libxcb-xlib0 install -libxcb-xlib0-dev install -libxcb1 install -libxcb1-dev install -libxdamage1 install -libxdmcp-dev install -libxdmcp6 install -libxext-dev install -libxext6 install -libxfixes3 install -libxfont1 install -libxi-dev install -libxi6 install -libxkbfile1 install -libxml-namespacesupport-perl install -libxml-parser-perl install -libxml-sax-expat-perl install -libxml-sax-perl install -libxml-simple-perl install -libxml2 install -libxmu-dev install -libxmu-headers install -libxmu6 install -libxmuu1 install -libxpm-dev install -libxpm4 install -libxt-dev install -libxt6 install -libxxf86vm1 install -links install -linux-firmware install -linux-image-2.6.24-19-server install -linux-image-2.6.27-14-server install -linux-image-server install -linux-libc-dev install -linux-restricted-modules-2.6.27-14-server install -linux-restricted-modules-common install -linux-restricted-modules-server install -linux-server install -linux-ubuntu-modules-2.6.24-19-server install -locales install -lockfile-progs install -login install -logrotate install -lsb-base install -lsb-release install -lshw install -lsof install -ltrace install -lzma install -m4 install -make install -makedev install -man-db install -manpages install -mawk install -memtest86+ install -mesa-common-dev install -mii-diag install -mime-support install -mktemp install -mlocate install -module-init-tools install -mount install -mtr-tiny install -mysql-common install -nano install -ncurses-base install -ncurses-bin install -net-tools install -netbase install -netcat install -netcat-traditional install -ntfs-3g install -ntp install -ntpdate install -openssh-blacklist install -openssh-client install -openssh-server install -openssl install -parted install -passwd install -pciutils install -pcmciautils install -perl install -perl-base install -perl-modules install -popularity-contest install -ppp install -pppconfig install -pppoeconf install -procmail install -procps install -psmisc install -python install -python-apt install -python-central install -python-gdbm install -python-gnupginterface install -python-minimal install -python-support install -python2.5 install -python2.5-minimal install -readline-common install -reiserfsprogs install -rsync install -sed install -sendmail install -sendmail-base install -sendmail-bin install -sendmail-cf install -sensible-mda install -sgml-base install -startup-tasks install -strace install -subversion install -sudo install -sysklogd install -system-services install -sysv-rc install -sysvinit-utils install -sysvutils install -tar install -tasksel install -tasksel-data install -tcpd install -tcpdump install -telnet install -time install -ttf-dejavu install -ttf-dejavu-core install -ttf-dejavu-extra install -ttf-xfree86-nonfree install -tzdata install -ubuntu-keyring install -ubuntu-minimal install -ubuntu-standard install -ucf install -udev install -ufw install -update-inetd install -update-manager-core install -upstart install -upstart-compat-sysv install -upstart-logd install -usbutils install -util-linux install -util-linux-locales install -uuid-runtime install -vim-common install -vim-tiny install -w3m install -wget install -whiptail install -wireless-tools install -wpasupplicant install -x-ttcidfont-conf install -x11-common install -x11-xkb-utils install -x11proto-core-dev install -x11proto-input-dev install -x11proto-kb-dev install -x11proto-xext-dev install -xauth install -xfonts-100dpi install -xfonts-75dpi install -xfonts-base install -xfonts-cyrillic install -xfonts-encodings install -xfonts-utils install -xkb-data install -xml-core install -xserver-common install -xtrans-dev install -xvfb install -zlib1g install diff --git a/pkgs/plt-services/meta/drdr/job-queue.rkt b/pkgs/plt-services/meta/drdr/job-queue.rkt deleted file mode 100644 index 4718f8fb57..0000000000 --- a/pkgs/plt-services/meta/drdr/job-queue.rkt +++ /dev/null @@ -1,105 +0,0 @@ -#lang racket/base -(require racket/list - racket/match - racket/local - racket/contract - racket/async-channel) - -(define current-worker (make-parameter #f)) - -(define-struct job-queue (async-channel)) -(define-struct job (paramz thunk)) -(define-struct done ()) - -(define (make-queue how-many) - (define jobs-ch (make-async-channel)) - (define work-ch (make-async-channel)) - (define done-ch (make-async-channel)) - (define (working-manager spaces accept-new? jobs continues) - (if (and (not accept-new?) - (empty? jobs) - (empty? continues)) - (killing-manager how-many) - (apply - sync - (if (and accept-new? - (not (zero? spaces))) - (handle-evt - jobs-ch - (match-lambda - [(? job? the-job) - (working-manager (sub1 spaces) accept-new? - (list* the-job jobs) continues)] - [(? done?) - (working-manager spaces #f jobs continues)])) - never-evt) - (handle-evt - done-ch - (lambda (reply-ch) - (working-manager spaces accept-new? - jobs (list* reply-ch continues)))) - (if (empty? jobs) - never-evt - (handle-evt - (async-channel-put-evt work-ch (first jobs)) - (lambda (_) - (working-manager spaces accept-new? - (rest jobs) continues)))) - (map - (lambda (reply-ch) - (handle-evt - (async-channel-put-evt reply-ch 'continue) - (lambda (_) - (working-manager (add1 spaces) accept-new? - jobs (remq reply-ch continues))))) - continues)))) - (define (killing-manager left) - (unless (zero? left) - (sync - (handle-evt - done-ch - (lambda (reply-ch) - (async-channel-put reply-ch 'stop) - (killing-manager (sub1 left))))))) - (define (worker i) - (match (async-channel-get work-ch) - [(struct job (paramz thunk)) - (call-with-parameterization - paramz - (lambda () - (parameterize ([current-worker i]) - (thunk)))) - (local [(define reply-ch (make-async-channel))] - (async-channel-put done-ch reply-ch) - (local [(define reply-v (async-channel-get reply-ch))] - (case reply-v - [(continue) (worker i)] - [(stop) (void)] - [else - (error 'worker "Unknown reply command")])))])) - (define the-workers - (for/list ([i (in-range 0 how-many)]) - (thread (lambda () - (worker i))))) - (define the-manager - (thread (lambda () (working-manager how-many #t empty empty)))) - (make-job-queue jobs-ch)) - -(define (submit-job! jobq thunk) - (async-channel-put - (job-queue-async-channel jobq) - (make-job (current-parameterization) - thunk))) - -(define (stop-job-queue! jobq) - (async-channel-put - (job-queue-async-channel jobq) - (make-done))) - -(provide/contract - [current-worker (parameter/c (or/c false/c exact-nonnegative-integer?))] - [job-queue? (any/c . -> . boolean?)] - [rename make-queue make-job-queue - (exact-nonnegative-integer? . -> . job-queue?)] - [submit-job! (job-queue? (-> any) . -> . void)] - [stop-job-queue! (job-queue? . -> . void)]) diff --git a/pkgs/plt-services/meta/drdr/list-count.rkt b/pkgs/plt-services/meta/drdr/list-count.rkt deleted file mode 100644 index b05e4dfb39..0000000000 --- a/pkgs/plt-services/meta/drdr/list-count.rkt +++ /dev/null @@ -1,37 +0,0 @@ -#lang racket - -(define list/count - (or/c exact-nonnegative-integer? (listof bytes?))) -(define lc->number - (match-lambda - [(? number? x) - x] - [(? list? x) - (length x)])) -(define lc->list - (match-lambda - [(? number? x) - empty] - [(? list? x) - x])) -(define lc-zero? - (match-lambda - [(? number? x) - (zero? x)] - [(? list? x) - (eq? empty x)])) -(define (lc+ x y) - (cond - [(number? x) - (+ x (lc->number y))] - [(number? y) - (+ (lc->number x) y)] - [else - (append x y)])) - -(provide/contract - [list/count contract?] - [lc+ (list/count list/count . -> . list/count)] - [lc->number (list/count . -> . exact-nonnegative-integer?)] - [lc->list (list/count . -> . (listof bytes?))] - [lc-zero? (list/count . -> . boolean?)]) diff --git a/pkgs/plt-services/meta/drdr/main.rkt b/pkgs/plt-services/meta/drdr/main.rkt deleted file mode 100644 index aa8e269b4f..0000000000 --- a/pkgs/plt-services/meta/drdr/main.rkt +++ /dev/null @@ -1,81 +0,0 @@ -#lang racket - -(require racket/system - "dirstruct.rkt" - "analyze.rkt" - "monitor-scm.rkt" - "notify.rkt" - "retry.rkt" - "config.rkt" - "plt-build.rkt" - "scm.rkt" - "cache.rkt" - "path-utils.rkt") - -(init-revisions!) -(define cur-rev (newest-revision)) -(define prev-rev (second-newest-revision)) - -(define (handle-revision prev-rev cur-rev) - (define rev-dir (revision-dir cur-rev)) - (parameterize ([current-rev cur-rev] - [previous-rev prev-rev]) - (notify! "Removing future record for r~a" cur-rev) - (safely-delete-directory (future-record-path cur-rev)) - - (notify! "Starting to integrate revision r~a" cur-rev) - (integrate-revision cur-rev) - - (notify! "Analyzing logs of r~a [prev: r~a]" cur-rev prev-rev) - (analyze-revision cur-rev) - - (notify! "Recording timing data") - (cache/file/timestamp - (build-path rev-dir "timing-done") - (lambda () - (system*/exit-code - (path->string - (build-path (plt-directory) "plt" "bin" "racket")) - "-t" - (path->string (build-path (drdr-directory) "time.rkt")) - "--" - "-r" (number->string cur-rev)))) - - (notify! "Recompressing") - (cache/file/timestamp - (build-path rev-dir "recompressing") - (lambda () - (parameterize ([current-directory rev-dir]) - (system*/exit-code - "/bin/bash" - (path->string - (build-path (drdr-directory) "recompress.sh")))))) - - (notify! "Archiving old revisions") - (cache/file/timestamp - (build-path rev-dir "archiving-done") - (lambda () - (system*/exit-code - (path->string - (build-path (plt-directory) "plt" "bin" "racket")) - "-t" - (path->string - (build-path (drdr-directory) "make-archive.rkt")) - "--" - "--many" (number->string 45)))))) - -(notify! "Last revision is r~a" cur-rev) -(handle-revision prev-rev cur-rev) -(notify! "Starting to monitor @ r~a" cur-rev) -(monitor-scm (plt-repository) - cur-rev - (lambda (newer) - (for ([rev (in-list newer)]) - (write-cache! - (future-record-path rev) - (get-scm-commit-msg rev (plt-repository))))) - (lambda (prev-rev cur-rev) - (handle-revision prev-rev cur-rev) - - ;; We have problems running for a long time so just restart after each rev - (exit 0))) diff --git a/pkgs/plt-services/meta/drdr/make-archive-lib.rkt b/pkgs/plt-services/meta/drdr/make-archive-lib.rkt deleted file mode 100644 index cda1273fb8..0000000000 --- a/pkgs/plt-services/meta/drdr/make-archive-lib.rkt +++ /dev/null @@ -1,23 +0,0 @@ -#lang racket -(require racket/system - "config.rkt" - "archive.rkt" - "path-utils.rkt" - "dirstruct.rkt") - -(define (make-archive rev) - (define archive-path (revision-archive rev)) - (if (file-exists? archive-path) - (begin (printf "r~a is already archived\n" rev) - #t) - (begin (local [(define tmp-path (make-temporary-file))] - (printf "Archiving r~a\n" rev) - (safely-delete-directory (revision-trunk.tgz rev)) - (safely-delete-directory (revision-trunk.tar.7z rev)) - (create-archive tmp-path (revision-dir rev)) - (rename-file-or-directory tmp-path archive-path) - (safely-delete-directory (revision-log-dir rev)) - (safely-delete-directory (revision-analyze-dir rev))) - #f))) - -(provide make-archive) diff --git a/pkgs/plt-services/meta/drdr/make-archive.rkt b/pkgs/plt-services/meta/drdr/make-archive.rkt deleted file mode 100644 index 8ecbac180d..0000000000 --- a/pkgs/plt-services/meta/drdr/make-archive.rkt +++ /dev/null @@ -1,26 +0,0 @@ -#lang racket -(require racket/system - "config.rkt" - "archive.rkt" - "path-utils.rkt" - "dirstruct.rkt" - "make-archive-lib.rkt") - -(define mode (make-parameter 'single)) - -(init-revisions!) - -(command-line #:program "make-archive" - #:once-any - ["--single" "Archive a single revision" (mode 'single)] - ["--many" "Archive many revisions" (mode 'many)] - #:args (ns) - (local [(define n (string->number ns))] - (case (mode) - [(many) - (local [(define all-revisions - (sort revisions >=))] - (for/or ([rev (in-list (list-tail all-revisions n))]) - (make-archive rev)))] - [(single) - (make-archive n)]))) diff --git a/pkgs/plt-services/meta/drdr/metadata.rkt b/pkgs/plt-services/meta/drdr/metadata.rkt deleted file mode 100644 index 471ee99733..0000000000 --- a/pkgs/plt-services/meta/drdr/metadata.rkt +++ /dev/null @@ -1,77 +0,0 @@ -#lang racket -(require "path-utils.rkt" - "dirstruct.rkt" - "scm.rkt") - -(define PROP:command-line "drdr:command-line") -(define PROP:timeout "drdr:timeout") - -(define (path-command-line a-path a-timeout) - (define suffix (filename-extension a-path)) - (define default-cmd - `(raco "test" "-m" "--timeout" ,(number->string a-timeout) *)) - (define (replace-* s) - (cond - [(eq? '* s) - (path->string* a-path)] - [(not (string? s)) - (format "~a" s)] - [else - s])) - (match (get-prop a-path 'drdr:command-line default-cmd) - [#f #f] - [(? list? l) - (cons (first l) - (map replace-* (rest l)))])) - -(define (path-timeout a-path) - (get-prop a-path 'drdr:timeout #f)) - -(define (path-responsible a-path) - (get-prop a-path 'responsible #:as-string? #t)) - -(define (path-random? a-path) - (get-prop a-path 'drdr:random)) - -(provide/contract - [PROP:command-line string?] - [PROP:timeout string?] - [path-responsible - (path-string? . -> . (or/c string? false/c))] - [path-command-line - (-> path-string? exact-nonnegative-integer? - (or/c (cons/c symbol? (listof string?)) false/c))] - [path-random? (path-string? . -> . boolean?)] - [path-timeout (path-string? . -> . (or/c exact-nonnegative-integer? false/c))]) - -;;; Property lookup -(provide props-cache) -(define props-cache (make-hasheq)) -(define (get-prop a-fs-path prop [def #f] #:as-string? [as-string? #f]) - (define rev (current-rev)) - (define a-path - (substring - (path->string - ((rebase-path (revision-trunk-dir rev) "/") a-fs-path)) - 1)) - (define props:get-prop - (hash-ref! props-cache rev - (lambda () - (define tmp-file (make-temporary-file "props~a.rkt" #f (current-temporary-directory))) - (and - ;; Checkout the props file - (scm-export-file - rev - (plt-repository) - "pkgs/plt-services/meta/props" - tmp-file) - ;; Dynamic require it - (begin0 - (with-handlers ([exn? (λ (x) #f)]) - (dynamic-require `(file ,(path->string tmp-file)) - 'get-prop)) - (delete-file tmp-file)))))) - ;; XXX get-prop is stupid and errors when a-path is invalid rather than returning def - (with-handlers ([exn? (lambda (x) def)]) - (props:get-prop a-path prop def - #:as-string? as-string?))) diff --git a/pkgs/plt-services/meta/drdr/monitor-drdr.rkt b/pkgs/plt-services/meta/drdr/monitor-drdr.rkt deleted file mode 100644 index 47e41db74b..0000000000 --- a/pkgs/plt-services/meta/drdr/monitor-drdr.rkt +++ /dev/null @@ -1,30 +0,0 @@ -#lang racket -(require xml - net/url - tests/web-server/util - "scm.rkt") - -(define drdr-url - (string->url "http://drdr.racket-lang.org")) - -(define drdr-xml - (call/input-url drdr-url get-pure-port read-xml/element)) -(define drdr-xexpr - (xml->xexpr drdr-xml)) - -(define-values - (building done) - (for/fold ([building empty] - [done empty]) - ([tr (in-list (reverse (simple-xpath*/list '(tbody) drdr-xexpr)))]) - (define rev (string->number (simple-xpath* '(a) tr))) - (define building? (simple-xpath* '(td #:class) tr)) - (if building? - (values (list* rev building) done) - (values building (list* rev done))))) - -(if (empty? building) - (if (= (first done) (newest-push)) - (void) - (error 'monitor-drdr "DrDr is not building, but is not at the most recent push")) - (void)) diff --git a/pkgs/plt-services/meta/drdr/monitor-scm.rkt b/pkgs/plt-services/meta/drdr/monitor-scm.rkt deleted file mode 100644 index 39da73599e..0000000000 --- a/pkgs/plt-services/meta/drdr/monitor-scm.rkt +++ /dev/null @@ -1,37 +0,0 @@ -#lang racket -(require "scm.rkt" - "retry.rkt") - -(define current-monitoring-interval-seconds - (make-parameter 60)) - -(define (monitor-scm repos start-rev notify-newer! notify-user!) - (define (monitor-w/o-wait prev-rev) - (define new-revs - (scm-revisions-after prev-rev repos)) - (match new-revs - [(list) - ; There has not yet been more revisions - (monitor prev-rev)] - [(cons new-rev newer) - (scm-update repos) - ; Notify of newer ones - (notify-newer! newer) - ; There was a commit that we care about. Notify, then recur - (retry-until-success - (format "Notifying of revision ~a" new-rev) - (notify-user! prev-rev new-rev)) - (monitor new-rev)])) - (define (monitor prev-rev) - (sleep (current-monitoring-interval-seconds)) - (monitor-w/o-wait prev-rev)) - (monitor-w/o-wait start-rev)) - -(provide/contract - [current-monitoring-interval-seconds - (parameter/c exact-nonnegative-integer?)] - [monitor-scm - (path-string? exact-nonnegative-integer? - ((listof exact-nonnegative-integer?) . -> . void) - (exact-nonnegative-integer? exact-nonnegative-integer? . -> . void) - . -> . any)]) diff --git a/pkgs/plt-services/meta/drdr/notify.rkt b/pkgs/plt-services/meta/drdr/notify.rkt deleted file mode 100644 index cdcac7da13..0000000000 --- a/pkgs/plt-services/meta/drdr/notify.rkt +++ /dev/null @@ -1,6 +0,0 @@ -#lang racket -(define (notify! fmt . args) - (log-info (format "[~a] ~a" (current-seconds) (apply format fmt args)))) - -(provide/contract - [notify! ((string?) () #:rest (listof any/c) . ->* . void)]) diff --git a/pkgs/plt-services/meta/drdr/path-utils.rkt b/pkgs/plt-services/meta/drdr/path-utils.rkt deleted file mode 100644 index 4a17216360..0000000000 --- a/pkgs/plt-services/meta/drdr/path-utils.rkt +++ /dev/null @@ -1,54 +0,0 @@ -#lang racket -(require racket/file) - -(define current-temporary-directory - (make-parameter #f)) - -(define (directory-list->directory-list* l) - (sort (filter-not (compose - (lambda (s) - (or (regexp-match #rx"^\\." s) - (string=? "compiled" s) - (link-exists? s))) - path->string) - l) - string<=? #:key path->string #:cache-keys? #t)) - -(define (directory-list* pth) - (directory-list->directory-list* (directory-list pth))) - -(define (safely-delete-directory pth) - (with-handlers ([exn:fail? (lambda (x) (void))]) - (delete-directory/files pth))) - -(define (make-parent-directory pth) - (define pth-dir (path-only pth)) - (make-directory* pth-dir)) - -(define (write-to-file* v pth) - (define tpth (make-temporary-file)) - (write-to-file v tpth #:exists 'truncate) - (make-parent-directory pth) - (rename-file-or-directory tpth pth #t)) - -(define (rebase-path from to) - (define froms (explode-path from)) - (define froms-len (length froms)) - (lambda (pth) - (define pths (explode-path pth)) - (apply build-path to (list-tail pths froms-len)))) - -(define (path->string* pth-string) - (if (string? pth-string) - pth-string - (path->string pth-string))) - -(provide/contract - [current-temporary-directory (parameter/c (or/c false/c path-string?))] - [safely-delete-directory (path-string? . -> . void)] - [directory-list->directory-list* ((listof path?) . -> . (listof path?))] - [directory-list* (path-string? . -> . (listof path?))] - [write-to-file* (any/c path-string? . -> . void)] - [make-parent-directory (path-string? . -> . void)] - [rebase-path (path-string? path-string? . -> . (path-string? . -> . path?))] - [path->string* (path-string? . -> . string?)]) diff --git a/pkgs/plt-services/meta/drdr/plt-build.rkt b/pkgs/plt-services/meta/drdr/plt-build.rkt deleted file mode 100644 index 13edb2adee..0000000000 --- a/pkgs/plt-services/meta/drdr/plt-build.rkt +++ /dev/null @@ -1,439 +0,0 @@ -#lang racket -(require racket/file - racket/runtime-path - "job-queue.rkt" - "metadata.rkt" - "run-collect.rkt" - "cache.rkt" - "dirstruct.rkt" - "replay.rkt" - "notify.rkt" - "path-utils.rkt" - "sema.rkt" - "scm.rkt") - -(define current-env (make-parameter (make-immutable-hash empty))) -(define-syntax-rule (with-env ([env-expr val-expr] ...) expr ...) - (parameterize ([current-env - (for/fold ([env (current-env)]) - ([k (in-list (list env-expr ...))] - [v (in-list (list val-expr ...))]) - (hash-set env k v))]) - expr ...)) - -(define (build-revision rev) - (define rev-dir (revision-dir rev)) - (define co-dir (revision-trunk-dir rev)) - (define log-dir (revision-log-dir rev)) - (define trunk-dir (revision-trunk-dir rev)) - ;; Checkout the repository revision - (cache/file/timestamp - (build-path rev-dir "checkout-done") - (lambda () - (notify! "Removing checkout directory: ~a" co-dir) - (safely-delete-directory co-dir) - (local [(define repo (plt-repository)) - (define to-dir - (path->string co-dir))] - (notify! "Checking out ~a@~a into ~a" - repo rev to-dir) - (scm-export-repo rev repo to-dir)))) - (parameterize ([current-directory co-dir]) - (with-env - (["PLT_SETUP_OPTIONS" (format "-j ~a" (number-of-cpus))]) - (run/collect/wait/log - #:timeout (current-make-install-timeout-seconds) - #:env (current-env) - (build-path log-dir "pkg-src" "build" "make") - (make-path) - (list "-j" (number->string (number-of-cpus)))))) - (run/collect/wait/log - #:timeout (current-make-install-timeout-seconds) - #:env (current-env) - (build-path log-dir "pkg-src" "build" "archive") - (tar-path) - (list "-czvf" - (path->string (revision-trunk.tgz rev)) - "-C" (path->string rev-dir) - "trunk"))) - -(define (call-with-temporary-directory thunk) - (define tempdir (symbol->string (gensym 'tmpdir))) - (dynamic-wind - (lambda () - (make-directory* tempdir)) - (lambda () - (parameterize ([current-directory tempdir]) - (thunk))) - (lambda () - (delete-directory/files tempdir)))) -(define-syntax-rule (with-temporary-directory e) - (call-with-temporary-directory (lambda () e))) - -(define-syntax-rule - (define-with-temporary-planet-directory with-temporary-planet-directory env-str) - (begin - (define (call-with-temporary-planet-directory thunk) - (define tempdir - (build-path (current-directory) - (symbol->string (gensym 'planetdir)))) - (dynamic-wind - (lambda () - (make-directory* tempdir)) - (lambda () - (with-env ([env-str (path->string tempdir)]) - (thunk))) - (lambda () - (delete-directory/files tempdir)))) - (define-syntax-rule (with-temporary-planet-directory e) - (call-with-temporary-planet-directory (lambda () e))))) -(define-with-temporary-planet-directory with-temporary-planet-directory "PLTPLANETDIR") -(define-with-temporary-planet-directory with-temporary-tmp-directory "TMPDIR") - -(define (call-with-temporary-home-directory thunk) - (define new-dir - (make-temporary-file - "home~a" - 'directory - (current-temporary-directory))) - (dynamic-wind - (lambda () - (with-handlers ([exn:fail? void]) - (copy-directory/files - (hash-ref (current-env) "HOME") - new-dir))) - (lambda () - (with-env (["HOME" (path->string new-dir)]) - (thunk))) - (lambda () - (delete-directory/files new-dir)))) -(define-syntax-rule (with-temporary-home-directory e) - (call-with-temporary-home-directory (lambda () e))) - -(define (with-running-program command args thunk) - (if command - (let () - (define-values (new-command new-args) - (command+args+env->command+args - #:env (current-env) - command args)) - (define-values - (the-process _stdout stdin _stderr) - (parameterize ([subprocess-group-enabled #t]) - (apply subprocess - (current-error-port) - #f - (current-error-port) - new-command new-args))) - ;; Die if this program does - (define parent - (current-thread)) - (define waiter - (thread - (lambda () - (subprocess-wait the-process) - (eprintf "Killing parent because wrapper (~a) is dead...\n" (list* command args)) - (kill-thread parent)))) - - ;; Run without stdin - (close-output-port stdin) - - (dynamic-wind - void - ;; Run the thunk - thunk - (λ () - ;; Close the output ports - ;;(close-input-port stdout) - ;;(close-input-port stderr) - - ;; Kill the guard - (kill-thread waiter) - - ;; Kill the process - (subprocess-kill the-process #f) - (sleep) - (subprocess-kill the-process #t)))) - (thunk))) - -(define (tested-packages) - (define tmp-file (make-temporary-file "pkgs~a.rktd" #f (current-temporary-directory))) - ;; Checkout the pkgs list - (scm-export-file (current-rev) (plt-repository) "pkgs/plt-services/meta/drdr/pkgs.rktd" tmp-file) - ;; Read it in - (define val (file->value tmp-file)) - (delete-file tmp-file)) - -(define (test-revision rev) - (define rev-dir (revision-dir rev)) - (define trunk-dir - (revision-trunk-dir rev)) - (define log-dir - (revision-log-dir rev)) - (define trunk->log - (rebase-path trunk-dir log-dir)) - (define racket-path - (path->string (build-path trunk-dir "racket" "bin" "racket"))) - (define raco-path - (path->string (build-path trunk-dir "racket" "bin" "raco"))) - ;; XXX Remove - (define mzc-path - (path->string (build-path trunk-dir "racket" "bin" "mzc"))) - (define gracket-path - (path->string (build-path trunk-dir "racket" "bin" "gracket"))) - (define gui-workers (make-job-queue 1)) - (define test-workers (make-job-queue (number-of-cpus))) - - (define pkgs-pths - (list (build-path trunk-dir "racket" "collects") - (build-path trunk-dir "pkgs") - (build-path trunk-dir "racket" "share" "pkgs"))) - (define (test-directory dir-pth upper-sema) - (define dir-log (build-path (trunk->log dir-pth) ".index.test")) - (cond - [(read-cache* dir-log) - (semaphore-post upper-sema)] - [else - (notify! "Testing in ~S" dir-pth) - (define files/unsorted (directory-list* dir-pth)) - (define dir-sema (make-semaphore 0)) - (define files - (sort files/unsorted < - #:key (λ (p) - (if (bytes=? #"tests" (path->bytes p)) - 0 - 1)) - #:cache-keys? #t)) - (for ([sub-pth (in-list files)]) - (define pth (build-path dir-pth sub-pth)) - (define directory? (directory-exists? pth)) - (cond - [directory? - ;; XXX do this in parallel? - (test-directory pth dir-sema)] - [else - (define log-pth (trunk->log pth)) - (cond - [(file-exists? log-pth) - (semaphore-post dir-sema)] - [else - (define pth-timeout - (or (path-timeout pth) - (current-subprocess-timeout-seconds))) - (define pth-cmd/general - (path-command-line pth pth-timeout)) - (define-values - (pth-cmd the-queue) - (match pth-cmd/general - [#f - (values #f #f)] - [(list-rest (or 'mzscheme 'racket) rst) - (values - (lambda (k) - (k (list* racket-path rst))) - test-workers)] - [(list-rest 'mzc rst) - (values - (lambda (k) (k (list* mzc-path rst))) - test-workers)] - [(list-rest 'raco rst) - (values - (lambda (k) (k (list* raco-path rst))) - test-workers)] - [(list-rest (or 'mred 'mred-text - 'gracket 'gracket-text) - rst) - (values - (if (on-unix?) - (lambda (k) - (k - (list* gracket-path - "-display" - (format - ":~a" - (cpu->child - (current-worker))) - rst))) - #f) - gui-workers)] - [_ - (values #f #f)])) - (cond - [pth-cmd - (submit-job! - the-queue - (lambda () - (dynamic-wind - void - (λ () - (pth-cmd - (λ (l) - (with-env - (["DISPLAY" - (format ":~a" - (cpu->child - (current-worker)))]) - (with-temporary-tmp-directory - (with-temporary-planet-directory - (with-temporary-home-directory - (with-temporary-directory - (run/collect/wait/log - log-pth - #:timeout pth-timeout - #:env (current-env) - (first l) - (rest l)))))))))) - (λ () - (semaphore-post dir-sema)))))] - [else - (semaphore-post dir-sema)])])])) - (thread - (lambda () - (define how-many (length files)) - (semaphore-wait* dir-sema how-many) - (notify! "Done with dir: ~a" dir-pth) - (write-cache! dir-log (current-seconds)) - (semaphore-post upper-sema)))])) - ;; Some setup - (for ([pp (in-list (tested-packages))]) - (define (run name source) - (run/collect/wait/log - ;; XXX Give it its own timeout - #:timeout (current-make-install-timeout-seconds) - #:env (current-env) - (build-path log-dir "pkg" name) - raco-path - (list "pkg" "install" "--skip-installed" "-i" "--deps" "fail" "--name" name source))) - (match pp - [`(,name ,source) (run name source)] - [(? string? name) (run name name)])) - (run/collect/wait/log - #:timeout (current-subprocess-timeout-seconds) - #:env (current-env) - (build-path log-dir "pkg-src" "build" "set-browser.rkt") - racket-path - (list "-t" - (path->string* - (build-path (drdr-directory) "set-browser.rkt")))) - ;; And go - (define (test-directories ps upper-sema) - (define list-sema (make-semaphore 0)) - (define how-many - (for/sum ([p (in-list ps)] #:when (directory-exists? p)) - (test-directory p list-sema) - 1)) - (and (not (zero? how-many)) - (thread - (lambda () - (semaphore-wait* list-sema how-many) - (semaphore-post upper-sema))))) - - (define top-sema (make-semaphore 0)) - (notify! "Starting testing") - (when (test-directories pkgs-pths top-sema) - (notify! "All testing scheduled... waiting for completion") - (sync - top-sema - (handle-evt - (alarm-evt - (+ (current-inexact-milliseconds) - (* 1000 (* 2 (current-make-install-timeout-seconds))))) - (λ _ - (kill-thread (current-thread)))))) - (notify! "Stopping testing") - (stop-job-queue! test-workers) - (stop-job-queue! gui-workers)) - -(define (recur-many i r f) - (if (zero? i) - (f) - (r (sub1 i) (lambda () - (recur-many (sub1 i) r f))))) - -(define XSERVER-OFFSET 20) -(define ROOTX XSERVER-OFFSET) -(define (cpu->child cpu-i) - ROOTX - #; - (+ XSERVER-OFFSET cpu-i 1)) - -(define (remove-X-locks tmp-dir i) - (for ([dir (in-list (list "/tmp" tmp-dir))]) - (safely-delete-directory - (build-path dir (format ".X~a-lock" i))) - (safely-delete-directory - (build-path dir ".X11-unix" (format ".X~a-lock" i))) - (safely-delete-directory - (build-path dir (format ".tX~a-lock" i))))) - -(define (integrate-revision rev) - (define test-dir - (build-path (revision-dir rev) "test")) - (define planet-dir - (build-path test-dir "planet")) - (define home-dir - (build-path test-dir "home")) - (define tmp-dir - (build-path test-dir "tmp")) - (define lock-dir - (build-path test-dir "locks")) - (define trunk-dir - (revision-trunk-dir rev)) - (cache/file/timestamp - (build-path (revision-dir rev) "integrated") - (lambda () - (make-directory* test-dir) - (make-directory* planet-dir) - (make-directory* home-dir) - (make-directory* tmp-dir) - (make-directory* lock-dir) - ;; We are running inside of a test directory so that random files are stored there - (parameterize ([current-directory test-dir] - [current-temporary-directory tmp-dir] - [current-rev rev]) - (with-env (["PLTSTDERR" "error"] - ["GIT_DIR" (path->string (plt-repository))] - ["TMPDIR" (path->string tmp-dir)] - ["PLTDRDR" "yes"] - ["PATH" - (format "~a:~a" - (path->string - (build-path trunk-dir "bin")) - (getenv "PATH"))] - ["PLTLOCKDIR" (path->string lock-dir)] - ["PLTPLANETDIR" (path->string planet-dir)] - ["HOME" (path->string home-dir)]) - (unless (read-cache* (revision-commit-msg rev)) - (write-cache! (revision-commit-msg rev) - (get-scm-commit-msg rev (plt-repository)))) - (when (build?) - (build-revision rev)) - - (define (start-x-server i inner) - (notify! "Starting X server #~a" i) - (remove-X-locks tmp-dir i) - (with-running-program - "/usr/bin/Xorg" (list (format ":~a" i)) - (lambda () - (with-env - (["DISPLAY" (format ":~a" i)]) - (sleep 2) - (notify! "Starting WM #~a" i) - (with-running-program - (fluxbox-path) - (list "-d" (format ":~a" i) - "--sm-disable" - "--no-composite") - inner))))) - - (start-x-server - ROOTX - (lambda () - (sleep 2) - (notify! "Starting test of rev ~a" rev) - (test-revision rev))))) - ;; Remove the test directory - (safely-delete-directory test-dir)))) - -(provide/contract - [integrate-revision (exact-nonnegative-integer? . -> . void)]) diff --git a/pkgs/plt-services/meta/drdr/recompress.sh b/pkgs/plt-services/meta/drdr/recompress.sh deleted file mode 100755 index 2bce3187bd..0000000000 --- a/pkgs/plt-services/meta/drdr/recompress.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -unset a i -while IFS= read -r -d $'\0' file; do - newfile=$(dirname "${file}")/$(basename "${file}" .tgz).tar.7z - if [ -f "${newfile}" ] ; then - rm -f "${newfile}" - fi - 7z x "${file}" -so | 7z a "${newfile}" -t7z -m0=lzma -mfb=64 -ms=on -mx=9 -si && rm -f ${file} -done < <(find . -name '*.tgz' -print0) - diff --git a/pkgs/plt-services/meta/drdr/render.rkt b/pkgs/plt-services/meta/drdr/render.rkt deleted file mode 100644 index 9f37146f02..0000000000 --- a/pkgs/plt-services/meta/drdr/render.rkt +++ /dev/null @@ -1,1116 +0,0 @@ -#lang at-exp racket -(require racket/date - racket/runtime-path - xml - "config.rkt" - "diff.rkt" - "list-count.rkt" - "cache.rkt" - (except-in "dirstruct.rkt" - revision-trunk-dir) - "status.rkt" - "monitor-scm.rkt" - (only-in "metadata.rkt" - PROP:command-line - PROP:timeout) - "formats.rkt" - "path-utils.rkt" - "analyze.rkt" - "status-analyze.rkt") - -(define (base-path pth) - (define rev (current-rev)) - (define log-dir (revision-log-dir rev)) - ((rebase-path log-dir "/") pth)) - -(define-runtime-path static "static") - -(define (snoc l x) (append l (list x))) -(define (list-head l n) - (if (zero? n) - empty - (list* (first l) - (list-head (rest l) (sub1 n))))) -(define (all-but-last l) (list-head l (sub1 (length l)))) - -(define (to-index i) - (cond - [(<= i 0) "."] - [else - (apply string-append (snoc (add-between (make-list i "..") "/") "/"))])) - -(define (current-depth log-pth directory?) - (define new-pth ((rebase-path (revision-log-dir (current-rev)) "/") log-pth)) - (define depth (sub1 (length (explode-path new-pth)))) - (if directory? - depth - (sub1 depth))) - -(define (next-rev) - (init-revisions!) - (local [(define end (newest-completed-revision))] - (let loop ([rev (add1 (current-rev))]) - (cond - [(not end) - #f] - [(<= end rev) - end] - [(read-cache* (build-path (revision-dir rev) "analyzed")) - rev] - [else - (loop (add1 rev))])))) - -(define (path->breadcrumb pth directory?) - (define the-rev (current-rev)) - (define new-pth ((rebase-path (revision-log-dir the-rev) "/") pth)) - (define parts (rest (explode-path new-pth))) - (define string-parts (list* (format "R~a" the-rev) (map path->string parts))) - (define (parent-a href sp) - `(a ([class "parent"] [href ,href]) ,sp)) - (define the-base-path* - (format "~a~a" - (base-path pth) - (if directory? "/" ""))) - (define the-base-path - (if (string=? the-base-path* "//") - "/" - the-base-path*)) - (define prev-rev-url (format "/~a~a" (previous-rev) the-base-path)) - (define next-rev-url (format "/~a~a" (next-rev) the-base-path)) - (define prev-change-url (format "/previous-change/~a~a" the-rev the-base-path)) - (define next-change-url (format "/next-change/~a~a" the-rev the-base-path)) - (define cur-rev-url (format "/~a~a" "current" the-base-path)) - ; XXX Don't special case top level - (values (apply string-append - (add-between (list* "DrDr" string-parts) " / ")) - `(span - (span ([class "breadcrumb"]) - ,(parent-a "/" "DrDr") " / " - ,@(add-between - (snoc - (for/list - ([sp (in-list (all-but-last string-parts))] - [from-root (in-naturals)]) - (define the-depth - (current-depth pth directory?)) - (parent-a - (to-index (- the-depth from-root)) sp)) - `(span ([class "this"]) - ,(last string-parts))) - " / ")) - (span ([class "revnav"]) - ,@(if directory? - empty - `((a ([href ,prev-change-url]) - (img ([src "/images/rewind-change.png"]))))) - (a ([href ,prev-rev-url]) - (img ([src "/images/rewind.png"]))) - (a ([href ,next-rev-url]) - (img ([src "/images/fast-forward.png"]))) - ,@(if directory? - empty - `((a ([href ,next-change-url]) - (img ([src "/images/fast-forward-change.png"]))))) - (a ([href ,cur-rev-url]) - (img ([src "/images/skip-forward1.png"]))))))) - -(define (looks-like-directory? pth) - (and (regexp-match #rx"/$" pth) #t)) - -(define (svn-date->nice-date date) - (regexp-replace "^(....-..-..)T(..:..:..).*Z$" date "\\1 \\2")) -(define (git-date->nice-date date) - (regexp-replace "^(....-..-..) (..:..:..).*$" date "\\1 \\2")) -(define (log->url log) - (define start-commit (git-push-start-commit log)) - (define end-commit (git-push-end-commit log)) - (if (string=? start-commit end-commit) - (format "http://github.com/plt/racket/commit/~a" end-commit) - (format "http://github.com/plt/racket/compare/~a...~a" - (git-push-previous-commit log) end-commit))) - -(define (format-commit-msg) - (define pth (revision-commit-msg (current-rev))) - (define (timestamp pth) - (with-handlers ([exn:fail? (lambda (x) "")]) - (date->string - (seconds->date - (read-cache - (build-path (revision-dir (current-rev)) pth))) #t))) - (define bdate/s (timestamp "checkout-done")) - (define bdate/e (timestamp "integrated")) - (match (read-cache* pth) - [(and gp (struct git-push (num author commits))) - (define start-commit (git-push-start-commit gp)) - (define end-commit (git-push-end-commit gp)) - `(table - ([class "data"]) - (tr ([class "author"]) (td "Author:") (td ,author)) - (tr ([class "date"]) (td "Build Start:") (td ,bdate/s)) - (tr ([class "date"]) (td "Build End:") (td ,bdate/e)) - ,@(if (file-exists? (revision-trunk.tgz (current-rev))) - `((tr ([class "date"]) - (td "Archive") - (td (a - ([href - ,(format "/builds/~a/trunk.tgz" - (current-rev))]) - "trunk.tgz")))) - `()) - ,@(if (file-exists? (revision-trunk.tar.7z (current-rev))) - `((tr ([class "date"]) - (td "Archive") - (td (a - ([href - ,(format "/builds/~a/trunk.tar.7z" - (current-rev))]) - "trunk.tar.7z")))) - `()) - (tr ([class "hash"]) - (td "Diff:") - (td (a ([href ,(log->url gp)]) - ,(substring start-commit 0 8) - ".." ,(substring end-commit 0 8)))) - ,@(append-map - (match-lambda - [(or (and (struct git-merge (hash author date msg from to)) - (app (λ (x) #f) branch)) - (struct git-merge* (branch hash author date msg from to))) - ; Don't display these "meaningless" commits - empty] - [(or (and (struct git-diff (hash author date msg mfiles)) - (app (λ (x) #f) branch)) - (struct git-diff* (branch hash author date msg mfiles))) - (define cg-id (symbol->string (gensym 'changes))) - (define ccss-id - (symbol->string (gensym 'changes))) - `(,@(if branch - (list `(tr ([class "branch"]) (td "Branch:") (td ,branch))) - empty) - (tr - ([class "hash"]) - (td "Commit:") - (td - (a - ([href - ,(format "http://github.com/plt/racket/commit/~a" - hash)]) - ,hash))) - (tr ([class "date"]) - (td "Date:") - (td ,(git-date->nice-date date))) - (tr ([class "author"]) (td "Author:") (td ,author)) - (tr ([class "msg"]) (td "Log:") (td (pre ,@(add-between msg "\n")))) - (tr ([class "changes"]) - (td - (a ([href ,(format "javascript:TocviewToggle(\"~a\",\"~a\");" cg-id ccss-id)]) - (span ([id ,cg-id]) 9658) "Changes:")) - (td - (div - ([id ,ccss-id] - [style "display: none;"]) - ,@(for/list ([path (in-list mfiles)]) - `(p - ([class "output"]) - ,(if - (regexp-match #rx"^collects" path) - (let () - (define path-w/o-trunk - (apply build-path - (explode-path path))) - (define html-path - (if (looks-like-directory? path) - (format "~a/" path-w/o-trunk) - path-w/o-trunk)) - (define path-url - (path->string* html-path)) - (define path-tested? - #t) - (if path-tested? - `(a ([href ,path-url]) ,path) - path)) - path)))))))]) - commits))] - - [(struct svn-rev-log (num author date msg changes)) - (define url (format "http://svn.racket-lang.org/view?view=rev&revision=~a" num)) - (define cg-id (symbol->string (gensym 'changes))) - (define ccss-id (symbol->string (gensym 'changes))) - `(table - ([class "data"]) - (tr ([class "author"]) (td "Author:") (td ,author)) - (tr ([class "date"]) - (td "Build Start:") - (td ,bdate/s)) - (tr ([class "date"]) (td "Build End:") (td ,bdate/e)) - (tr ([class "rev"]) - (td "Commit:") - (td (a ([href ,url]) ,(number->string num)))) - (tr ([class "date"]) - (td "Date:") - (td ,(svn-date->nice-date date))) - (tr ([class "msg"]) (td "Log:") (td (pre ,msg))) - (tr ([class "changes"]) - (td - (a ([href - ,(format - "javascript:TocviewToggle(\"~a\",\"~a\");" - cg-id ccss-id)]) - (span ([id ,cg-id]) 9658) "Changes:")) - (td - (div - ([id ,ccss-id] - [style "display: none;"]) - ,@(map - (match-lambda - [(struct svn-change (action path)) - `(p ([class "output"]) - ,(symbol->string action) " " - ,(if (regexp-match - #rx"^/trunk/collects" - path) - (local - [(define path-w/o-trunk - (apply build-path - (list-tail - (explode-path path) 2))) - (define html-path - (if (looks-like-directory? path) - (format "~a/" path-w/o-trunk) - path-w/o-trunk)) - (define path-url - (path->string* html-path)) - (define path-tested? - #t)] - (if path-tested? - `(a ([href ,path-url]) ,path) - path)) - path))]) - changes)))))] - [else - '" "])) - -(define drdr-start-request (make-parameter #f)) -(define (footer) - `(div ([id "footer"]) - "Powered by " (a ([href "http://racket-lang.org/"]) "Racket") ". " - "Written by " (a ([href "http://faculty.cs.byu.edu/~jay"]) "Jay McCarthy") ". " - (a ([href "/help"]) - "Need help?") - (br) - "Current time: " ,(date->string (seconds->date (current-seconds)) #t) - "Render time: " - ,(real->decimal-string - (- (current-inexact-milliseconds) (drdr-start-request))) - "ms")) - -(define (render-event e) - (with-handlers ([exn:fail? - (lambda (x) - `(pre ([class "unprintable"]) "UNPRINTABLE"))]) - (match e - [(struct stdout (bs)) - `(pre ([class "stdout"]) ,(bytes->string/utf-8 bs))] - [(struct stderr (bs)) - `(pre ([class "stderr"]) ,(bytes->string/utf-8 bs))]))) - -(define (json-out out x) - (cond - [(list? x) - (fprintf out "[") - (let loop ([l x]) - (match l - [(list) - (void)] - [(list e) - (json-out out e)] - [(list-rest e es) - (json-out out e) - (fprintf out ",") - (loop es)])) - (fprintf out "]")] - [else - (display x out)])) - -(define (json-timing req path-to-file) - (define timing-pth (path-timing-log (apply build-path path-to-file))) - (define ts (file->list timing-pth)) - (response - 200 #"Okay" - (file-or-directory-modify-seconds timing-pth) - #"application/json" - (list (make-header #"Access-Control-Allow-Origin" - #"*")) - (lambda (out) - (fprintf out "[") - (for ([l (in-list (add-between ts ","))]) - (json-out out l)) - (fprintf out "]")))) - -(define (render-log log-pth) - (match (log-rendering log-pth) - [#f - (file-not-found log-pth)] - [(and the-log-rendering (struct rendering (_ _ dur _ _ _ responsible changed))) - (match (read-cache log-pth) - [(and log (struct status (_ _ command-line output-log))) - (define-values (title breadcrumb) (path->breadcrumb log-pth #f)) - (define the-base-path - (base-path log-pth)) - (define scm-url - (if ((current-rev) . < . 20000) - (format "http://svn.racket-lang.org/view/trunk/~a?view=markup&pathrev=~a" - the-base-path - (current-rev)) - (local [(define msg (read-cache* (revision-commit-msg (current-rev))))] - (if msg - (format "http://github.com/plt/racket/blob/~a~a" - (git-push-end-commit msg) the-base-path) - "#")))) - (define prev-rev-url (format "/~a~a" (previous-rev) the-base-path)) - (define cur-rev-url (format "/~a~a" "current" the-base-path)) - (define s-output-log (log-divide output-log)) - (response/xexpr - `(html - (head (title ,title) - (script ([language "javascript"] [type "text/javascript"] - [src "/jquery-1.6.2.min.js"]) "") - (script ([language "javascript"] [type "text/javascript"] - [src "/jquery.flot.js"]) "") - (script ([language "javascript"] [type "text/javascript"] - [src "/jquery.flot.selection.js"]) "") - (link ([rel "stylesheet"] [type "text/css"] [href "/render.css"]))) - (body - (div ([class "log, content"]) - ,breadcrumb - (table ([class "data"]) - (tr (td "Responsible:") - (td ,responsible)) - (tr (td "Command-line:") - (td ,@(add-between - (map (lambda (s) - `(span ([class "commandline"]) ,s)) - command-line) - " "))) - (tr (td "Duration:") - (td ,(format-duration-ms dur) - nbsp (a ([href ,(format "/data~a" (path-add-suffix the-base-path #".timing"))]) - "(timing data)"))) - (tr (td "Timeout:") (td ,(if (timeout? log) checkmark-entity ""))) - (tr (td "Exit Code:") (td ,(if (exit? log) (number->string (exit-code log)) ""))) - (tr (td " ") (td (a ([href ,scm-url]) "View File")))) - ,(if (lc-zero? changed) - "" - `(div ([class "error"]) - "The result of executing this file has changed since the previous push." - " " - (a ([href ,(format "/diff/~a/~a~a" (previous-rev) (current-rev) the-base-path)]) - "See the difference"))) - ,@(if (empty? output-log) - '() - (append* - (for/list ([o-block (in-list s-output-log)] - [i (in-naturals)]) - `((span ([id ,(format "output~a" i)]) " ") - ,(if (> (length s-output-log) (add1 i)) - `(div ([class "error"]) - (a ([href ,(format "#output~a" (add1 i))]) - "Skip to the next STDERR block.")) - "") - (div - ([class "output"]) - " " - ,@(map render-event o-block)))))) - - (p) - - (div ([id "_chart"] [style "width:800px;height:300px;"]) "") - (script ([language "javascript"] [type "text/javascript"] [src "/chart.js"]) "") - (script ([language "javascript"] [type "text/javascript"]) - ,(format "get_data('~a');" the-base-path)) - (button ([onclick "reset_chart()"]) "Reset") - (button ([id "setlegend"] [onclick "set_legend(!cur_options.legend.show)"]) - "Hide Legend") - - ,(footer)))))])])) - -(define (number->string/zero v) - (cond - [(zero? v) - '" "] - [else - (number->string v)])) - -(define checkmark-entity - 10004) - -(define (path->url pth) - (format "http://drdr.racket-lang.org/~a~a" (current-rev) pth)) - -(define (render-logs/dir dir-pth #:show-commit-msg? [show-commit-msg? #f]) - (match (dir-rendering dir-pth) - [#f - (dir-not-found dir-pth)] - [(and pth-rendering (struct rendering (tot-start tot-end tot-dur tot-timeout tot-unclean tot-stderr tot-responsible tot-changes))) - (define files - (foldl (lambda (sub-pth files) - (define pth (build-path dir-pth sub-pth)) - (define directory? (cached-directory-exists? pth)) - (define pth-rendering - (if directory? - (dir-rendering pth) - (log-rendering pth))) - (list* (list directory? sub-pth pth-rendering) files)) - empty - (cached-directory-list* dir-pth))) - (define-values (title breadcrumb) (path->breadcrumb dir-pth #t)) - (response/xexpr - `(html (head (title ,title) - (script ([src "/sorttable.js"]) " ") - (link ([rel "stylesheet"] [type "text/css"] [href "/render.css"]))) - (body - (div ([class "dirlog, content"]) - ,breadcrumb - ,(if show-commit-msg? - (format-commit-msg) - "") - - ; All files with a status - ,(let () - (define log-dir (revision-log-dir (current-rev))) - (define base-path - (rebase-path log-dir "/")) - `(div ([class "status"]) - (div ([class "tag"]) "by status") - ,@(for/list ([status (in-list responsible-ht-severity)] - [rendering->list-count (in-list (list rendering-timeout? rendering-unclean-exit? - rendering-stderr? rendering-changed?))]) - (define lc (rendering->list-count pth-rendering)) - (define rcss-id (symbol->string (gensym))) - (define rg-id (symbol->string (gensym 'glyph))) - - `(div (a ([href ,(format "javascript:TocviewToggle(\"~a\",\"~a\");" rg-id rcss-id)]) - (span ([id ,rg-id]) 9658) " " - ,(format "~a [~a]" - status - (lc->number lc))) - (ul ([id ,rcss-id] - [style ,(format "display: ~a" - "none")]) - ,@(for/list ([pp (lc->list lc)]) - (define p (bytes->string/utf-8 pp)) - (define bp (base-path p)) - `(li (a ([href ,(path->url bp)]) ,(path->string bp))))))))) - - ,(local [(define responsible->problems - (rendering->responsible-ht (current-rev) pth-rendering)) - (define last-responsible->problems - (with-handlers ([exn:fail? (lambda (x) (make-hash))]) - (define prev-dir-pth ((rebase-path (revision-log-dir (current-rev)) - (revision-log-dir (previous-rev))) - dir-pth)) - (define previous-pth-rendering - (parameterize ([current-rev (previous-rev)]) - (dir-rendering prev-dir-pth))) - (rendering->responsible-ht (previous-rev) previous-pth-rendering))) - (define new-responsible->problems - (responsible-ht-difference last-responsible->problems responsible->problems)) - - (define (render-responsible->problems tag responsible->problems) - (if (zero? (hash-count responsible->problems)) - "" - `(div ([class "status"]) - (div ([class "tag"]) ,tag) - ,@(for/list ([(responsible ht) (in-hash responsible->problems)]) - (define rcss-id (symbol->string (gensym))) - (define rg-id (symbol->string (gensym 'glyph))) - (define summary - (for/fold ([s ""]) - ([id (in-list responsible-ht-severity)]) - (define llc (hash-ref ht id empty)) - (if (empty? llc) - s - (format "~a [~a: ~a]" s id (length llc))))) - `(div (a ([href ,(format "javascript:TocviewToggle(\"~a\",\"~a\");" rg-id rcss-id)]) - (span ([id ,rg-id]) 9658) " " - ,responsible - " " ,summary) - (blockquote - ([id ,rcss-id] - [style "display: none;"]) - ,@(local [(define i 0)] - (for/list ([id (in-list responsible-ht-severity)]) - (define llc (hash-ref ht id empty)) - (if (empty? llc) - "" - (local [(define display? (< i 2)) - (define css-id (symbol->string (gensym 'ul))) - (define glyph-id (symbol->string (gensym 'glyph)))] - (set! i (add1 i)) - `(div (a ([href ,(format "javascript:TocviewToggle(\"~a\",\"~a\");" glyph-id css-id)]) - (span ([id ,glyph-id]) ,(if display? 9660 9658)) " " - ,(hash-ref responsible-ht-id->str id)) - (ul ([id ,css-id] - [style ,(format "display: ~a" - (if display? "block" "none"))]) - ,@(for/list ([p llc]) - `(li (a ([href ,(path->url p)]) ,(path->string p))))))))))))))))] - `(div ,(render-responsible->problems "all" responsible->problems) - ,(render-responsible->problems "new" new-responsible->problems))) - (table ([class "sortable, dirlist"]) - (thead - (tr (td "Path") - (td "Duration (Abs)") - (td "Duration (Sum)") - (td "Timeout?") - (td "Unclean Exit?") - (td "STDERR Output") - (td "Changes") - (td "Responsible"))) - (tbody - ,@(map (match-lambda - [(list directory? sub-pth (struct rendering (start end dur timeout unclean stderr responsible-party changes))) - (define name (path->string sub-pth)) - (define abs-dur (- end start)) - (define url - (if directory? - (format "~a/" name) - name)) - `(tr ([class ,(if directory? "dir" "file")] - [onclick ,(format "document.location = ~S" url)]) - (td ([sorttable_customkey - ,(format "~a:~a" - (if directory? "dir" "file") - name)]) - (a ([href ,url]) ,name ,(if directory? "/" ""))) - (td ([sorttable_customkey ,(number->string abs-dur)]) - ,(format-duration-ms abs-dur)) - (td ([sorttable_customkey ,(number->string dur)]) - ,(format-duration-ms dur)) - ,@(map (lambda (vv) - (define v (lc->number vv)) - `(td ([sorttable_customkey ,(number->string v)]) - ,(if directory? - (number->string/zero v) - (if (zero? v) - '" " - checkmark-entity)))) - (list timeout unclean stderr changes)) - (td ,responsible-party))]) - (sort files - (match-lambda* - [(list (list dir?1 name1 _) - (list dir?2 name2 _)) - (cond - [(and dir?1 dir?2) - (string<=? (path->string name1) - (path->string name2))] - [dir?1 #t] - [dir?2 #f])])))) - (tfoot - (tr ([class "total"]) - (td "Total") - (td ,(format-duration-ms (- tot-end tot-start))) - (td ,(format-duration-ms tot-dur)) - (td ,(number->string/zero (lc->number tot-timeout))) - (td ,(number->string/zero (lc->number tot-unclean))) - (td ,(number->string/zero (lc->number tot-stderr))) - (td ,(number->string/zero (lc->number tot-changes))) - (td " ")))) - ,(footer)))))])) - -(define (show-help req) - (response/xexpr - `(html - (head (title "DrDr > Help") - (link ([rel "stylesheet"] [type "text/css"] [href "/render.css"]))) - (body - (div ([class "dirlog, content"]) - ; XXX Use same function as above - (span ([class "breadcrumb"]) - (a ([class "parent"] [href "/"]) "DrDr") " / " - (span ([class "this"]) - "Help")) - @div[[(class "help")]]{ - @h1{What is DrDr?} - @p{DrDr is a server at @a[[(href "http://www.byu.edu")]]{Brigham Young University} that builds - and "tests" every push to the Racket code base.} - - @h1{What kind of server?} - @p{Here is the result of calling @code{uname -a}:} - @pre{@,(with-output-to-string (λ () (system "uname -a")))} - @p{Here is the result of calling @code{cat /etc/issue}:} - @pre{@,(with-output-to-string (λ () (system "cat /etc/issue")))} - @p{The machine has @,(number->string (number-of-cpus)) cores and runs Racket @,(version).} - - @h1{How is the build run?} - @p{Every push is built from a clean checkout with the standard separate build directory command sequence, except that @code{make} - is passed @code{-j} with the number of cores. Each push also has a fresh home directory and PLaneT cache.} - - @h1{How long does it take for a build to start after a check-in?} - @p{Only one build runs at a time and when none is running the git repository is polled every @,(number->string (current-monitoring-interval-seconds)) seconds.} - - @h1{How is the push "tested"?} - @p{Each file's @code{@,PROP:command-line} property is consulted. If it is the empty string, the file is ignored. If it is a string, then a single @code{~s} is replaced with the file's path, @code{racket}, @code{mzc}, @code{raco} with their path (for the current push), and @code{gracket} and @code{gracket-text} with @code{gracket}'s path (for the current push); then the resulting command-line is executed. - (Currently no other executables are allowed, so you can't @code{rm -fr /}.) - If there is no property value, the default @code{raco test ~s} is used if the file's suffix is @code{.rkt}, @code{.ss}, @code{.scm}, @code{.sls}, or @code{.scrbl} and @code{racket -f ~s} is used if the file's suffix is @code{.rktl}.} - - @p{The command-line is always executed with a fresh empty current directory which is removed after the run. But all the files share the same home directory and X server, which are both removed after each push's testing is complete.} - - @p{When DrDr runs any command, it sets the @code{PLTDRDR} environment variable. You can use this to change the command's behavior. However, it is preferred that you change the command-line directly.} - - @h1{How many files are "tested" concurrently?} - @p{One per core, or @,(number->string (number-of-cpus)).} - - @p{However, all @code{gracket} files are serialized so that one runs at a time. This is because GUI programs may be sensitive to screen-specific state such as window focus and there is only one screen available to all GUI programs. Historicallly, the @code{gracket} difference was essential before the GUI code was ported to Racket; but currently that is irrelevant. Therefore, you should not mark things as using @code{gracket} unless you anticipate they will actually cause such conflicts; nor should you mark anything as using @code{gracket} if it just has a different kind of race.} - - @h1{How long may a file run?} - @p{The execution timeout is @,(number->string (current-subprocess-timeout-seconds)) seconds by default, but the @code{@,PROP:timeout} property is used if @code{string->number} returns a number on it.} - - @h1{May these settings be set on a per-directory basis?} - @p{Yes; if the property is set on any ancestor directory, then its value is used for its descendents when theirs is not set. - } - - @h1{What data is gathered during these runs?} - @p{When each file is run the following is recorded: the start time, the command-line, the STDERR and STDOUT output, the exit code (unless there is a timeout), and the end time. All this information is presented in the per-file DrDr report page.} - - @h1{How is the data analyzed?} - @p{From the data collected from the run, DrDr computes the total test time and whether output has "changed" since the last time the file was tested.} - - @h1{What output patterns constitute a "change"?} - @p{At the most basic level, if the bytes are different. However, there are a few subtleties. First, DrDr knows to ignore the result of @code{time}. Second, the standard output and standard error streams are compared independently. Finally, if the file has the @code{drdr:random} property, then changes do not affect any reporting DrDr would otherwise perform. The difference display pages present changed lines with a @span[([class "difference"])]{unique background}.} - - @h1{What do the green buttons do?} - @p{They switch between revisions where there was a change from the previous revision.} - - @p{For example, if there where seven revisions with three different outputs---1A 2A 3A 4B 5B 6C 7C---then the green buttons will go from 1 to 4 to 6 to 7. (1 and 7 are included because they are the last possible revisions and the search stops.)} - - @p{In other words, the green buttons go forwards and backwards to the nearest pushes that have the red 'This result of executing this file has changed' box on them.} - - @h1{How is this site organized?} - @p{Each file's test results are displayed on a separate page, with a link to the previous push on changes. All the files in a directory are collated and indexed recursively. On these pages each column is sortable and each row is clickable. The root of a push also includes the git commit messages with links to the test results of the modified files. The top DrDr page displays the summary information for all the tested pushes.} - - @h1{What is the difference between @code{Duration (Abs)} and @code{Duration (Sum)}?} - @p{@code{Duration (Abs)} is the difference between the earliest start time and the latest end time in the collection.} - @p{@code{Duration (Sum)} is the sum of each file's difference between the start time and end time.} - @p{The two are often different because of parallelism in the testing process. (Long absolute durations indicate DrDr bugs waiting to get fixed.)} - - @h1{What do the graphs mean?} - @p{There is a single graph for each file, i.e., graphs are not kept for old pushs.} - @p{The X-axis is the tested push. The Y-axis is the percentage of the time of the slowest push.} - @p{The gray, horizontal lines show where 0%, 25%, 50%, 75%, and 100% are in the graph.} - @p{The black line shows the times for overall running of the file. The colored lines show the results from @code{time}. For each color, the "real" time is the darkest version of it and the "cpu" and "gc" time are 50% and 25% of the darkness, respectively.} - @p{If the number of calls to @code{time} change from one push to the next, then there is a gray, vertical bar at that point. Also, the scaling to the slowest time is specific to each horizontal chunk.} - @p{The graph is split up into panes that each contain approximately 300 pushes. The green arrowheads to the left - and right of the image move between panes.} - @p{The legend at the bottom of the graph shows the current pane, as well as the push number and any timing information from that push.} - @p{Click on the graph to jump to the DrDr page for a specific push.} - - @h1{What is the timing data format?} - @p{The timing files are a list of S-expressions. Their grammar is: @code{(push duration ((cpu real gc) ...))} where @code{push} is an integer, @code{duration} is an inexact millisecond, and @code{cpu}, @code{real}, and @code{gc} are parsed from the @code{time-apply} function.} - - @h1{Why are some pushes missing?} - @p{Some pushes are missing because they only modify branches. Only pushes that change the @code{master} or @code{release} branch are tested.} - - @h1{How do I make the most use of DrDr?} - @p{So DrDr can be effective with all testing packages and untested code, it only pays attention to error output and non-zero exit codes. You can make the most of this strategy by ensuring that when your tests are run successfully they have no STDERR output and exit cleanly, but have both when they fail.} - - @h1{How do I fix the reporting of an error in my code?} - @p{If you know you code does not have a bug, but DrDr thinks it does, you can probably fix it by setting its properties: allow it to run longer with @code{@,PROP:timeout} (but be kind and perhaps change the program to support work load selection on the command-line) or make sure it is run with the right command-line using @code{@,PROP:command-line}.} - - @h1{How can I do the most for DrDr?} - @p{The most important thing you can do is eliminate false positives by configuring DrDr for your code and removing spurious error output.} - @p{The next thing is to structure your code so DrDr does not do the same work many times. For example, because DrDr will load every file if your test suite is broken up into different parts that execute when loaded @em{and} they are all loaded by some other file, then DrDr will load and run them twice. The recommended solution is to have DrDr ignore the combining file or change it so a command-line argument is needed to run everything but is not provided by DrDr, that way the combining code is compiled but the tests are run once.} - - } - ,(footer)))))) - -(define (take* l i) - (take l (min (length l) i))) - -(define (list-limit len offset l) - (take* (drop l offset) len)) - -(define (string-first-line s) - (define v - (with-input-from-string s read-line)) - (if (eof-object? v) - "" v)) - -(define log->committer+title - (match-lambda - [(struct git-push (num author commits)) - (define lines (append-map (λ (c) (if (git-merge? c) empty (git-commit-msg* c))) commits)) - (define title - (if (empty? lines) - "" - (first lines))) - (values author title)] - [(struct svn-rev-log (num author date msg changes)) - (define commit-msg (string-first-line msg)) - (define title - (format "~a - ~a" - (svn-date->nice-date date) - commit-msg)) - (values author title)])) - -(define (log->branches log) - (match-define (struct git-push (num author commits)) log) - (apply string-append - (add-between - (remove-duplicates - (for/list ([c (in-list commits)]) - (format "branch-~a" - (regexp-replace* - "/" - (if (git-commit*? c) - (git-commit*-branch c) - "refs/heads/master") - "-")))) - " "))) - -(require web-server/servlet-env - web-server/http - web-server/dispatch - "scm.rkt") -(define how-many-revs 45) -(define (show-revisions req) - (define builds-pth (plt-build-directory)) - (define offset - (match (bindings-assq #"offset" (request-bindings/raw req)) - [(struct binding:form (_ val)) - (string->number (bytes->string/utf-8 val))] - [_ - 0])) - (define future-revs - (map (curry cons 'future) - (sort (directory-list* (plt-future-build-directory)) - > - #:key (compose string->number path->string)))) - (define how-many-future-revs - (length future-revs)) - (define built-or-building-revs - (map (curry cons 'past) - (sort (directory-list* builds-pth) - > - #:key (compose string->number path->string)))) - (define all-revs - (append future-revs built-or-building-revs)) - (define how-many-total-revs - (length all-revs)) - (response/xexpr - `(html - (head (title "DrDr") - (link ([rel "stylesheet"] [type "text/css"] [href "/render.css"]))) - (body - (div ([class "dirlog, content"]) - ; XXX Use same function as above - (span ([class "breadcrumb"]) - (span ([class "this"]) - "DrDr")) - (table ([class "dirlist"]) - (thead - (tr (td "Push#") - (td "Duration (Abs)") - (td "Duration (Sum)") - (td "Timeout?") - (td "Unclean Exit?") - (td "STDERR Output") - (td "Changes") - (td "Pusher"))) - (tbody - ,@(map (match-lambda - [(cons 'future rev-pth) - (define name (path->string rev-pth)) - (define rev (string->number name)) - (define log (read-cache (future-record-path rev))) - (define-values (committer title) - (log->committer+title log)) - (define url (log->url log)) - `(tr ([class ,(format "dir ~a" - (log->branches log))] - [title ,title]) - (td (a ([href ,url]) ,name)) - (td ([class "building"] [colspan "6"]) - "") - (td ([class "author"]) ,committer))] - [(cons 'past rev-pth) - (define name (path->string rev-pth)) - (define url (format "~a/" name)) - (define rev (string->number name)) - (define log-pth (revision-commit-msg rev)) - (define log (read-cache log-pth)) - (define-values (committer title) - (log->committer+title log)) - (define (no-rendering-row) - (define mtime - (file-or-directory-modify-seconds log-pth)) - - `(tr ([class ,(format "dir ~a" - (log->branches log))] - [title ,title]) - (td (a ([href "#"]) ,name)) - (td ([class "building"] [colspan "6"]) - "Build in progress. Started " - ,(format-duration-m - (/ (- (current-seconds) mtime) 60)) - " ago.") - (td ([class "author"]) ,committer))) - (parameterize ([current-rev rev]) - (with-handlers - ([(lambda (x) - (regexp-match #rx"No cache available" (exn-message x))) - (lambda (x) - (no-rendering-row))]) - ; XXX One function to generate - (match (dir-rendering (revision-log-dir rev)) - [#f - (no-rendering-row)] - [(struct rendering - (start end dur timeout unclean - stderr responsible-party changes)) - (define abs-dur (- end start)) - - `(tr ([class ,(format "dir ~a" - (log->branches log))] - [title ,title] - [onclick ,(format "document.location = ~S" url)]) - (td (a ([href ,url]) ,name)) - (td ([sorttable_customkey ,(number->string abs-dur)]) - ,(format-duration-ms abs-dur)) - (td ([sorttable_customkey ,(number->string dur)]) - ,(format-duration-ms dur)) - ,@(map (lambda (vv) - (define v (lc->number vv)) - `(td ([sorttable_customkey ,(number->string v)]) - ,(number->string/zero v))) - (list timeout unclean stderr changes)) - (td ,responsible-party))])))]) - (list-limit - how-many-revs offset - all-revs)))) - (table ([id "revnav"] [width "100%"]) - (tr (td ([align "left"]) - (span ([class "revnav"]) - (a ([href ,(top-url show-revisions)]) - (img ([src "/images/skip-backward1.png"]))) - (a ([href ,(format "~a?offset=~a" - (top-url show-revisions) - (max 0 (- offset how-many-revs)))]) - (img ([src "/images/rewind.png"]))))) - (td ([align "right"]) - (span ([class "revnav"]) - (a ([href ,(format "~a?offset=~a" - (top-url show-revisions) - (min (- how-many-total-revs how-many-revs) - (+ offset how-many-revs)))]) - (img ([src "/images/fast-forward.png"]))) - (a ([href ,(format "~a?offset=~a" - (top-url show-revisions) - (- how-many-total-revs how-many-revs))]) - (img ([src "/images/skip-forward1.png"]))))))) - ,(footer)))))) - -(define (show-revision req rev) - (define log-dir (revision-log-dir rev)) - (parameterize ([current-rev rev] - [previous-rev (find-previous-rev rev)]) - (with-handlers ([(lambda (x) - (regexp-match #rx"No cache available" (exn-message x))) - (lambda (x) - (rev-not-found log-dir rev))]) - (render-logs/dir log-dir #:show-commit-msg? #t)))) - -(define (file-not-found file-pth) - (define-values (title breadcrumb) (path->breadcrumb file-pth #f)) - (response/xexpr - `(html - (head (title ,title " > Not Found") - (link ([rel "stylesheet"] [type "text/css"] [href "/render.css"]))) - (body - (div ([class "content"]) - ,breadcrumb - (div ([class "error"]) - "This file does not exist in push #" ,(number->string (current-rev)) " or has not been tested.") - ,(footer)))))) -(define (dir-not-found dir-pth) - (define-values (title breadcrumb) (path->breadcrumb dir-pth #t)) - (response/xexpr - `(html - (head (title ,title " > Not Found") - (link ([rel "stylesheet"] [type "text/css"] [href "/render.css"]))) - (body - (div ([class "content"]) - ,breadcrumb - (div ([class "error"]) - "This directory does not exist in push #" ,(number->string (current-rev)) " or has not been tested.") - ,(footer)))))) -(define (rev-not-found dir-pth path-to-file) - (define-values (title breadcrumb) (path->breadcrumb dir-pth #t)) - (response/xexpr - `(html - (head (title ,title " > Not Found") - (link ([rel "stylesheet"] [type "text/css"] [href "/render.css"]))) - (body - (div ([class "content"]) - ,breadcrumb - (div ([class "error"]) - "Push #" ,(number->string (current-rev)) " does not exist or has not been tested.") - ,(footer)))))) - -(define (find-previous-rev this-rev) - (if (zero? this-rev) - #f - (local [(define maybe (sub1 this-rev))] - (if (cached-directory-exists? (revision-log-dir maybe)) - maybe - (find-previous-rev maybe))))) - -(define (show-file/prev-change req rev path-to-file) - (show-file/change -1 rev path-to-file)) -(define (show-file/next-change req rev path-to-file) - (show-file/change +1 rev path-to-file)) -(define (show-file/change direction top-rev path-to-file) - (define the-rev - (let loop ([last-rev top-rev] - [this-rev (+ direction top-rev)]) - (parameterize ([current-rev this-rev] - [previous-rev (find-previous-rev this-rev)]) - (define log-dir (revision-log-dir this-rev)) - (define log-pth - (apply build-path log-dir path-to-file)) - (match - (with-handlers ([(lambda (x) - (regexp-match #rx"No cache available" (exn-message x))) - (lambda (x) - #f)]) - (log-rendering log-pth)) - [#f - last-rev] - [(and the-log-rendering (struct rendering (_ _ _ _ _ _ _ changed))) - (if (empty? changed) - (loop this-rev (+ direction this-rev)) - this-rev)])))) - (redirect-to - (top-url show-file the-rev path-to-file))) - -(define (show-file req rev path-to-file) - (define log-dir (revision-log-dir rev)) - (parameterize ([current-rev rev] - [previous-rev (find-previous-rev rev)]) - (if (member "" path-to-file) - (local [(define dir-pth - (apply build-path log-dir (all-but-last path-to-file)))] - (with-handlers ([(lambda (x) - (regexp-match #rx"No cache available" (exn-message x))) - (lambda (x) - (dir-not-found dir-pth))]) - (render-logs/dir dir-pth))) - (local [(define file-pth - (apply build-path log-dir path-to-file))] - (with-handlers ([(lambda (x) - (regexp-match #rx"No cache available" (exn-message x))) - (lambda (x) - (file-not-found file-pth))]) - (render-log file-pth)))))) - -(define (show-revision/current req) - (init-revisions!) - (redirect-to - (top-url show-revision (newest-completed-revision)))) -(define (show-file/current req . args) - (init-revisions!) - (redirect-to - (apply top-url show-file (newest-completed-revision) args))) - -(define (show-diff req r1 r2 f) - (define f1 (apply build-path (revision-log-dir r1) f)) - (with-handlers ([(lambda (x) - (regexp-match #rx"File is not cached" (exn-message x))) - (lambda (x) - ; XXX Make a little nicer - (parameterize ([current-rev r1]) - (file-not-found f1)))]) - (define l1 (status-output-log (read-cache f1))) - (define f2 (apply build-path (revision-log-dir r2) f)) - (with-handlers ([(lambda (x) - (regexp-match #rx"File is not cached" (exn-message x))) - (lambda (x) - ; XXX Make a little nicer - (parameterize ([current-rev r2]) - (file-not-found f2)))]) - (define l2 (status-output-log (read-cache f2))) - (define f-str (path->string (apply build-path f))) - (define title - (format "DrDr / File Difference / ~a (~a:~a)" - f-str r1 r2)) - - (response/xexpr - `(html (head (title ,title) - (link ([rel "stylesheet"] [type "text/css"] [href "/render.css"]))) - (body - (div ([class "log, content"]) - (span ([class "breadcrumb"]) - (a ([class "parent"] [href "/"]) - "DrDr") - " / " - (span ([class "this"]) - "File Difference")) - (table ([class "data"]) - (tr (td "First Push:") (td (a ([href ,(format "/~a/~a" r1 f-str)]) ,(number->string r1)))) - (tr (td "Second Push:") (td (a ([href ,(format "/~a/~a" r2 f-str)]) ,(number->string r2)))) - (tr (td "File:") (td "/" ,f-str))) - (div ([class "output"]) - (table ([class "diff"]) - ,@(for/list ([d (in-list (render-log-difference l1 l2))]) - (match d - [(struct difference (old new)) - `(tr ([class "difference"]) - (td ,(render-event old)) - (td ,(render-event new)))] - [(struct same-itude (e)) - `(tr (td ([colspan "2"]) ,(render-event e)))])))) - ,(footer)))))))) - -(define-values (top-dispatch top-url) - (dispatch-rules - [("help") show-help] - [("") show-revisions] - [("diff" (integer-arg) (integer-arg) (string-arg) ...) show-diff] - [("json" "timing" (string-arg) ...) json-timing] - [("previous-change" (integer-arg) (string-arg) ...) show-file/prev-change] - [("next-change" (integer-arg) (string-arg) ...) show-file/next-change] - [("current" "") show-revision/current] - [("current" (string-arg) ...) show-file/current] - [((integer-arg) "") show-revision] - [((integer-arg) (string-arg) ...) show-file])) - -(require (only-in net/url url->string)) -(define (log-dispatch req) - (define user-agent - (cond - [(headers-assq #"User-Agent" - (request-headers/raw req)) - => header-value] - [else - #"Unknown"])) - (cond - [(regexp-match #"Googlebot" user-agent) - (response/xexpr "Please, do not index.")] - [else - (printf "~a - ~a\n" - (url->string (request-uri req)) - user-agent) - (parameterize ([drdr-start-request (current-inexact-milliseconds)]) - (top-dispatch req))])) - -(date-display-format 'iso-8601) -(cache/file-mode 'no-cache) -(serve/servlet log-dispatch - #:port 9000 - #:listen-ip #f - #:quit? #f - #:launch-browser? #f - #:servlet-regexp #rx"" - #:servlet-path "/" - #:extra-files-paths (list static)) diff --git a/pkgs/plt-services/meta/drdr/rendering.rkt b/pkgs/plt-services/meta/drdr/rendering.rkt deleted file mode 100644 index 566a29788e..0000000000 --- a/pkgs/plt-services/meta/drdr/rendering.rkt +++ /dev/null @@ -1,18 +0,0 @@ -#lang racket -(require "list-count.rkt") - -(define-struct rendering (start end duration timeout? unclean-exit? stderr? responsible changed?) #:prefab) - -(define (rendering-responsibles r) - (regexp-split #rx"," (rendering-responsible r))) - -(provide/contract - [struct rendering ([start number?] - [end number?] - [duration number?] - [timeout? list/count] - [unclean-exit? list/count] - [stderr? list/count] - [responsible string?] - [changed? list/count])] - [rendering-responsibles (rendering? . -> . (listof string?))]) diff --git a/pkgs/plt-services/meta/drdr/replay-log.rkt b/pkgs/plt-services/meta/drdr/replay-log.rkt deleted file mode 100644 index a768857a6c..0000000000 --- a/pkgs/plt-services/meta/drdr/replay-log.rkt +++ /dev/null @@ -1,21 +0,0 @@ -#lang racket -(require "replay.rkt" - "cache.rkt" - "status.rkt") - -; XXX Rewrite to work with logs in dbm - -(define the-log-file - (command-line - #:program "replay-log" - #:args (filename) - filename)) - -(define the-log - (read-cache the-log-file)) - -(unless (status? the-log) - (error 'replay-log "Not an output log: ~e" the-log)) - -(replay-status the-log) -(replay-exit-code the-log) diff --git a/pkgs/plt-services/meta/drdr/replay.rkt b/pkgs/plt-services/meta/drdr/replay.rkt deleted file mode 100644 index c9364323dd..0000000000 --- a/pkgs/plt-services/meta/drdr/replay.rkt +++ /dev/null @@ -1,27 +0,0 @@ -#lang racket -(require (prefix-in racket: racket) - "formats.rkt" - "status.rkt") - -(define replay-event - (match-lambda - [(struct stdout (bs)) (printf "~a\n" bs)] - [(struct stderr (bs)) (eprintf "~a\n" bs)])) - -(define (replay-status s) - (for-each replay-event (status-output-log s)) - #;(when (timeout? s) - (eprintf "[replay-log] TIMEOUT!\n")) - #;(when (exit? s) - (eprintf "[replay-log] Exit code: ~a\n" (exit-code s))) - #;(printf "[replay-log] Took ~a\n" - (format-duration-ms (status-duration s))) - (replay-exit-code s)) - -(define (replay-exit-code s) - (when (exit? s) - (racket:exit (exit-code s)))) - -(provide/contract - [replay-exit-code (status? . -> . void)] - [replay-status (status? . -> . void)]) diff --git a/pkgs/plt-services/meta/drdr/retry.rkt b/pkgs/plt-services/meta/drdr/retry.rkt deleted file mode 100644 index 1dae04d695..0000000000 --- a/pkgs/plt-services/meta/drdr/retry.rkt +++ /dev/null @@ -1,16 +0,0 @@ -#lang racket -(require "notify.rkt") - -(define-syntax-rule (retry-until-success msg expr ...) - (retry-until-success* msg (lambda () expr ...))) - -(define (retry-until-success* msg thunk) - (notify! msg) - (thunk) - #;(with-handlers ([exn:fail? (lambda (x) - ((error-display-handler) (format "Error trying to: ~a: ~a" msg (exn-message x)) x) - (notify! "Retrying...") - (retry-until-success* msg thunk))]) - (thunk))) - -(provide retry-until-success) diff --git a/pkgs/plt-services/meta/drdr/rewriting.rkt b/pkgs/plt-services/meta/drdr/rewriting.rkt deleted file mode 100644 index 5bfc1f0887..0000000000 --- a/pkgs/plt-services/meta/drdr/rewriting.rkt +++ /dev/null @@ -1,31 +0,0 @@ -#lang racket -(require "status.rkt") - -(define (rewrite-status #:rewrite rewrite-string s) - (match s - [(struct exit (start end command-line output-log code)) - (make-exit start end - (rewrite-strings #:rewrite rewrite-string command-line) - (rewrite-events #:rewrite rewrite-string output-log) - code)] - [(struct timeout (start end command-line output-log)) - (make-timeout start end - (rewrite-strings #:rewrite rewrite-string command-line) - (rewrite-events #:rewrite rewrite-string output-log))])) - -(define (rewrite-strings #:rewrite rewrite-string los) - (map rewrite-string los)) -(define (rewrite-events #:rewrite rewrite-string loe) - (map (rewrite-event #:rewrite rewrite-string) loe)) -(define (rewrite-event #:rewrite rewrite-bytes) - (match-lambda - [(struct stdout (b)) (make-stdout (rewrite-bytes b))] - [(struct stderr (b)) (make-stderr (rewrite-bytes b))])) - - -(define rewrite-string/c - ((or/c string? bytes?) . -> . (or/c string? bytes?))) - -(provide/contract - [rewrite-string/c contract?] - [rewrite-status (#:rewrite rewrite-string/c status? . -> . status?)]) diff --git a/pkgs/plt-services/meta/drdr/run-collect.rkt b/pkgs/plt-services/meta/drdr/run-collect.rkt deleted file mode 100644 index 3d6d594385..0000000000 --- a/pkgs/plt-services/meta/drdr/run-collect.rkt +++ /dev/null @@ -1,163 +0,0 @@ -#lang racket -(require "status.rkt" - "notify.rkt" - "rewriting.rkt" - "dirstruct.rkt" - "cache.rkt") - -(define (command+args+env->command+args - #:env env - cmd args) - (values "/usr/bin/env" - (append (for/list ([(k v) (in-hash env)]) - (format "~a=~a" k v)) - (list* cmd - args)))) - -(define (run/collect/wait - #:env env - #:timeout timeout - command args) - (define start-time - (current-inexact-milliseconds)) - - ; Run the command - (define-values (new-command new-args) - (command+args+env->command+args - #:env env - command args)) - (define command-line - (list* command args)) - (define-values - (the-process stdout stdin stderr) - (parameterize ([subprocess-group-enabled #t]) - (apply subprocess - #f #f #f - new-command - new-args))) - - (notify! "Running: ~a ~S" command args) - - ; Run it without input - (close-output-port stdin) - - ; Wait for all the output and the process death or timeout - (local - [(define the-alarm - (alarm-evt (+ start-time (* 1000 timeout)))) - - (define line-ch (make-channel)) - (define (read-port-t make port) - (thread - (λ () - (let loop () - (define l (read-bytes-line port)) - (if (eof-object? l) - (channel-put line-ch l) - (begin (channel-put line-ch (make l)) - (loop))))))) - (define stdout-t (read-port-t make-stdout stdout)) - (define stderr-t (read-port-t make-stderr stderr)) - - (define final-status - (let loop ([open-ports 2] - [end-time #f] - [status #f] - [log empty]) - (define process-done? (and end-time #t)) - (define output-done? (zero? open-ports)) - (if (and output-done? process-done?) - (if status - (if (= status 2) - (make-timeout start-time end-time command-line (reverse log)) - (make-exit start-time end-time command-line (reverse log) status)) - (make-timeout start-time end-time command-line (reverse log))) - (sync (if process-done? - never-evt - (choice-evt - (handle-evt the-alarm - (λ (_) - (define end-time - (current-inexact-milliseconds)) - (subprocess-kill the-process #f) - ;; Sleep for 10% of the timeout - ;; before sending the death - ;; signal - (sleep (* timeout 0.1)) - (subprocess-kill the-process #t) - (loop open-ports end-time status log))) - (handle-evt the-process - (λ (_) - (define end-time - (current-inexact-milliseconds)) - (loop open-ports end-time (subprocess-status the-process) log))))) - (if output-done? - never-evt - (handle-evt line-ch - (match-lambda - [(? eof-object?) - (loop (sub1 open-ports) end-time status log)] - [l - (loop open-ports end-time status (list* l log))])))))))] - - (close-input-port stdout) - (close-input-port stderr) - - (notify! "Done: ~a ~S" command args) - - final-status)) - -(define-syntax regexp-replace** - (syntax-rules () - [(_ () s) s] - [(_ ([pat0 subst0] - [pat subst] - ...) - s) - (regexp-replace* (regexp-quote pat0) - (regexp-replace** ([pat subst] ...) s) - subst0)])) - -(define (run/collect/wait/log log-path command - #:timeout timeout - #:env env - args) - (define ran? #f) - (cache/file - log-path - (lambda () - (define rev (number->string (current-rev))) - (define home (hash-ref env "HOME")) - (define tmp (hash-ref env "TMPDIR")) - (define cwd (path->string (current-directory))) - (define (rewrite s) - (regexp-replace** ([rev ""] - [tmp ""] - [home ""] - [cwd ""]) - s)) - - (set! ran? #t) - (rewrite-status - #:rewrite rewrite - (run/collect/wait - #:timeout timeout - #:env env - command args)))) - ran?) - -(provide/contract - [command+args+env->command+args - (string? (listof string?) #:env (hash/c string? string?) . -> . (values string? (listof string?)))] - [run/collect/wait - (string? - #:env (hash/c string? string?) - #:timeout exact-nonnegative-integer? - (listof string?) - . -> . status?)] - [run/collect/wait/log - (path-string? string? - #:env (hash/c string? string?) - #:timeout exact-nonnegative-integer? - (listof string?) - . -> . boolean?)]) diff --git a/pkgs/plt-services/meta/drdr/scm.rkt b/pkgs/plt-services/meta/drdr/scm.rkt deleted file mode 100644 index 7b67291036..0000000000 --- a/pkgs/plt-services/meta/drdr/scm.rkt +++ /dev/null @@ -1,294 +0,0 @@ -#lang racket -(require "svn.rkt" - "path-utils.rkt" - "dirstruct.rkt" - net/url - racket/system) -(provide - (all-from-out "svn.rkt")) - -(define git-path (make-parameter "/opt/local/bin/git")) -(provide/contract - [git-path (parameter/c string?)]) - -(define git-url-base "http://git.racket-lang.org/plt.git") - -(provide/contract - [newest-push (-> number?)]) -(define (newest-push) - (string->number (port->string (get-pure-port (string->url (format "~a/push-counter" git-url-base)))))) - -(define (pad2zeros n) - (format "~a~a" - (if (n . < . 10) - "0" "") - (number->string n))) - -(define-struct push-data (who end-commit branches) #:prefab) - -(define (push-info push-n) - (define push-n100s (quotient push-n 100)) - (define push-nrem (pad2zeros (modulo push-n 100))) - (define ls - (port->lines - (get-pure-port - (string->url - (format "~a/pushes/~a/~a" git-url-base push-n100s push-nrem))))) - (match - ls - [(list (regexp #rx"^([^ ]+) +([0-9abcdef]+)$" (list _ who end-commit)) - (regexp #rx"^([0-9abcdef]+) +([0-9abcdef]+) +(.+)$" (list _ bstart bend branch))) - (make-push-data who bend - (make-immutable-hash - (list (cons branch (vector bstart bend)))))] - [(list (regexp #rx"^([^ ]+) +([0-9abcdef]+)$" (list _ who end-commit)) - (regexp #rx"^([0-9abcdef]+) +([0-9abcdef]+) +(.+)$" (list _ bstart bend branch)) - ...) - (make-push-data who end-commit - (make-immutable-hash - (map (lambda (b bs be) (cons b (vector bs be))) - branch bstart bend)))] - [_ - #f])) - -(define (pipe/proc cmds) - (if (null? (cdr cmds)) - ((car cmds)) - (let-values ([(i o) (make-pipe 4096)]) - (parameterize ([current-output-port o]) - (thread (lambda () ((car cmds)) (close-output-port o)))) - (parameterize ([current-input-port i]) - (pipe/proc (cdr cmds)))))) -(define-syntax-rule (pipe expr exprs ...) - (pipe/proc (list (lambda () expr) (lambda () exprs) ...))) - -(define (close-input-port* p) - (when p (close-input-port p))) -(define (close-output-port* p) - (when p (close-output-port p))) - -(define (system/output-port #:k k #:stdout [init-stdout #f] . as) - (define-values (sp stdout stdin stderr) - (apply subprocess init-stdout #f #f as)) - (begin0 (k stdout) - (subprocess-wait sp) - (subprocess-kill sp #t) - (close-input-port* stdout) - (close-output-port* stdin) - (close-input-port* stderr))) - -(define-struct git-push (num author commits) #:prefab) -(define-struct git-commit (hash author date msg) #:prefab) -(define-struct (git-diff git-commit) (mfiles) #:prefab) -(define-struct (git-merge git-commit) (from to) #:prefab) - -(define-struct git-commit* (branch hash author date msg) #:prefab) -(define-struct (git-diff* git-commit*) (mfiles) #:prefab) -(define-struct (git-merge* git-commit*) (from to) #:prefab) - -(define (read-until-empty-line in-p) - (let loop () - (let ([l (read-line in-p)]) - (cond - [(eof-object? l) - (close-input-port in-p) - empty] - [(string=? l "") - empty] - [else - (list* (regexp-replace #rx"^ +" l "") (loop))])))) - -(define (read-commit branch in-p) - (match (read-line in-p) - [(? eof-object?) - #f] - [(regexp #rx"^commit +(.+)$" (list _ hash)) - (match (read-line in-p) - [(regexp #rx"^Merge: +(.+) +(.+)$" (list _ from to)) - (match-define (regexp #rx"^Author: +(.+)$" (list _ author)) (read-line in-p)) - (match-define (regexp #rx"^Date: +(.+)$" (list _ date)) (read-line in-p)) - (define _1 (read-line in-p)) - (define msg (read-until-empty-line in-p)) - (make-git-merge* branch hash author date msg from to)] - [(regexp #rx"^Author: +(.+)$" (list _ author)) - (match-define (regexp #rx"^Date: +(.+)$" (list _ date)) (read-line in-p)) - (define _1 (read-line in-p)) - (define msg (read-until-empty-line in-p)) - (define mfiles (read-until-empty-line in-p)) - (make-git-diff* branch hash author date msg mfiles)])])) - -(define port-empty? port-closed?) - -(define (read-commits branch in-p) - (cond - [(port-empty? in-p) - empty] - [(read-commit branch in-p) - => (lambda (c) - (printf "~S\n" c) - (list* c (read-commits branch in-p)))] - [else - empty])) - -(define (get-scm-commit-msg rev repo) - (match-define (struct push-data (who _ branches)) (push-info rev)) - (make-git-push - rev who - (apply append - (for/list - ([(branch cs) branches]) - (match-define (vector start-commit end-commit) cs) - (parameterize - ([current-directory repo]) - (system/output-port - #:k (curry read-commits branch) - (git-path) - "--no-pager" "log" "--date=iso" "--name-only" "--no-merges" - (format "~a..~a" start-commit end-commit))))))) -(provide/contract - [struct git-push - ([num exact-nonnegative-integer?] - [author string?] - [commits (listof (or/c git-commit? git-commit*?))])] - [struct git-commit - ([hash string?] - [author string?] - [date string?] - [msg (listof string?)])] - [struct git-diff - ([hash string?] - [author string?] - [date string?] - [msg (listof string?)] - [mfiles (listof string?)])] - [struct git-merge - ([hash string?] - [author string?] - [date string?] - [msg (listof string?)] - [from string?] - [to string?])] - [struct git-commit* - ([branch string?] - [hash string?] - [author string?] - [date string?] - [msg (listof string?)])] - [struct git-diff* - ([branch string?] - [hash string?] - [author string?] - [date string?] - [msg (listof string?)] - [mfiles (listof string?)])] - [struct git-merge* - ([branch string?] - [hash string?] - [author string?] - [date string?] - [msg (listof string?)] - [from string?] - [to string?])] - [get-scm-commit-msg (exact-nonnegative-integer? path-string? . -> . git-push?)]) - -(define (git-commit-msg* gc) - (if (git-commit? gc) - (git-commit-msg gc) - (git-commit*-msg gc))) -(define (git-commit-hash* gc) - (if (git-commit? gc) - (git-commit-hash gc) - (git-commit*-hash gc))) - -(provide/contract - [git-commit-hash* (-> (or/c git-commit? git-commit*?) string?)] - [git-commit-msg* (-> (or/c git-commit? git-commit*?) (listof string?))]) - -(define (git-push-previous-commit gp) - (define start (git-push-start-commit gp)) - (parameterize ([current-directory (plt-repository)]) - (system/output-port - #:k (λ (port) (read-line port)) - (git-path) - "--no-pager" "log" "--format=format:%P" start "-1"))) -(define (git-push-start-commit gp) - (define cs (git-push-commits gp)) - (if (empty? cs) - "xxxxxxxxxxxxxxxxxxxxxxxxx" - (git-commit-hash* (last cs)))) -(define (git-push-end-commit gp) - (define cs (git-push-commits gp)) - (if (empty? cs) - "xxxxxxxxxxxxxxxxxxxxxxxxx" - (git-commit-hash* (first cs)))) -(provide/contract - [git-push-previous-commit (git-push? . -> . string?)] - [git-push-start-commit (git-push? . -> . string?)] - [git-push-end-commit (git-push? . -> . string?)]) - -(define scm-commit-author - (match-lambda - [(? git-push? gp) (git-push-author gp)] - [(? svn-rev-log? srl) (svn-rev-log-author srl)])) -(provide/contract - [scm-commit-author ((or/c git-push? svn-rev-log?) . -> . string?)]) - -(define (scm-export-file rev repo file dest) - (define commit - (push-data-end-commit (push-info rev))) - (call-with-output-file* - dest - #:exists 'truncate/replace - (lambda (file-port) - (parameterize ([current-directory repo]) - (system/output-port - #:k void - #:stdout file-port - (git-path) "--no-pager" "show" (format "~a:~a" commit file))))) - (void)) - -(define (scm-export-repo rev repo dest) - (define end (push-data-end-commit (push-info rev))) - (printf "Exporting ~v where end = ~a\n" - (list rev repo dest) - end) - (pipe - (parameterize ([current-directory repo]) - (system* - (git-path) "archive" - (format "--prefix=~a/" - (regexp-replace #rx"/+$" (path->string* dest) "")) - "--format=tar" - end)) - (system* (find-executable-path "tar") "xf" "-" "--absolute-names")) - (void)) - -(define (scm-update repo) - (parameterize ([current-directory repo]) - (system* (git-path) "fetch")) - (void)) - -(define master-branch "refs/heads/master") -(define release-branch "refs/heads/release") - -(define (contains-drdr-request? p) - (for*/or ([c (in-list (git-push-commits p))] - [m (in-list (git-commit-msg* c))]) - (regexp-match #rx"DrDr, test this push" m))) - -(define (scm-revisions-after cur-rev repo) - (define newest-rev (newest-push)) - (for/list ([rev (in-range (add1 cur-rev) (add1 newest-rev))] - #:when - (let ([info (push-info rev)]) - (and info - (or (hash-has-key? (push-data-branches info) master-branch) - (hash-has-key? (push-data-branches info) release-branch) - (contains-drdr-request? (get-scm-commit-msg rev repo)))))) - rev)) - -(provide/contract - [scm-update (path? . -> . void?)] - [scm-revisions-after (exact-nonnegative-integer? path-string? . -> . (listof exact-nonnegative-integer?))] - [scm-export-file (exact-nonnegative-integer? path-string? string? path-string? . -> . void?)] - [scm-export-repo (exact-nonnegative-integer? path-string? path-string? . -> . void?)]) diff --git a/pkgs/plt-services/meta/drdr/sema.rkt b/pkgs/plt-services/meta/drdr/sema.rkt deleted file mode 100644 index 91cf7cf67f..0000000000 --- a/pkgs/plt-services/meta/drdr/sema.rkt +++ /dev/null @@ -1,9 +0,0 @@ -#lang racket - -(define (semaphore-wait* sema how-many) - (unless (zero? how-many) - (semaphore-wait sema) - (semaphore-wait* sema (sub1 how-many)))) - -(provide/contract - [semaphore-wait* (semaphore? exact-nonnegative-integer? . -> . void)]) diff --git a/pkgs/plt-services/meta/drdr/set-browser.rkt b/pkgs/plt-services/meta/drdr/set-browser.rkt deleted file mode 100644 index 6729375486..0000000000 --- a/pkgs/plt-services/meta/drdr/set-browser.rkt +++ /dev/null @@ -1,8 +0,0 @@ -#lang racket - -(printf "Setting the default browser to something safe...\n") - -; XXX maybe have it call /quit -(put-preferences - '(external-browser) - '(("echo " . ""))) diff --git a/pkgs/plt-services/meta/drdr/static/chart.js b/pkgs/plt-services/meta/drdr/static/chart.js deleted file mode 100644 index c69c640a26..0000000000 --- a/pkgs/plt-services/meta/drdr/static/chart.js +++ /dev/null @@ -1,256 +0,0 @@ -var path = "" -var data = null; -var sub_times = []; -var overall_times = []; -var chart_data = []; -var show_hide = {} -var options = { selection: { mode: "xy" }, - legend: { backgroundOpacity: 0, - position: "sw", - show: true, - noColumns : 1, - labelFormatter : - function(label, series) { - if (show_hide[label] === undefined) - show_hide[label] = true; - var css = ''; - if (!show_hide[label]) { - css = 'style="font-style: italic"'; - } - var v = '
' + label + '
'; - return v;}}, - xaxes: [{min: null, max: null, label: 'push'}], - yaxes: [{min: null, max: null, label: "time"}, - {position: "right"}], - grid: { clickable: true, hoverable : true } - }; - -function addCommas(nStr) { - var rgx = /(\d+)(\d{3})/; - while (rgx.test(nStr)) { - nStr = nStr.replace(rgx, '$1' + ',' + '$2'); - } - return nStr; -} - -// Number -> String -function format_ms(ms) { - return addCommas(String(ms)) + " ms" -} - -// Number -> String -function format_time(ms) { - if (ms >= 300000) - return Number(ms/60000).toFixed(2) + " m " + "("+ format_ms(ms)+")"; - if (ms >= 10000) - return Number(ms/1000).toFixed(2) + " s" + "("+ format_ms(ms)+")"; - return format_ms(ms); -} - -function legend_click(l) { - show_hide[l] = !show_hide[l]; - show(); - serialize_opts(options); -} - -var placeholder = $("#_chart"); -var previousPoint = null; - -function showTooltip(x, y, contents) { - $('
' + contents + '
').css( { - position: 'absolute', - display: 'none', - top: y + 5, - left: x + 5, - border: '1px solid #fdd', - padding: '2px', - 'background-color': '#fee', - opacity: 0.80 - }).appendTo("body").fadeIn(200); -} - -function makeTooltip(item,path) { - var x = item.datapoint[0]; - var y = item.datapoint[1].toFixed(2); - showTooltip(item.pageX, item.pageY, - item.series.label + ' at push ' + x + ": " - + format_time(y)); -} -placeholder.bind("plotselected", handle_selection); - -// is the tooltip shown b/c of a click? -var tooltip_clicked = false; - -function remove_tooltip() { - tooltip_clicked = false; - $("#tooltip").remove(); -} - -function hover(event,pos,item) { - if (tooltip_clicked) return; - if (item) { - // don't re-show the same tool-tip that's already shown - if (previousPoint != item.dataIndex) { - previousPoint = item.dataIndex; - remove_tooltip(); - makeTooltip(item,path); - } - } - else { - remove_tooltip(); - previousPoint = null; - } -} - -function click(e,pos,item) { - if (tooltip_clicked) { - remove_tooltip(); - return; - } - if (!item) return; - tooltip_clicked = true; - // if we've already got the tooltip, just keep it around - if (previousPoint != item.dataIndex) { - $("#tooltip").remove(); - makeTooltip(item,path); - } -} - - -// sort chart data based on the order of a[0], b[0] -function sorter(a,b) { - if (a[0] < b[0]) return -1; - if (a[0] > b[0]) return 1; - return 0; -} - - - -function load_data(d) { - chart_data = []; - overall_times = []; - sub_times = []; - pdata = [] - data = d; - reset_chart(); - pdata = data && JSON.parse(data); - - var max_overall = 0; - var max_sub = 0; - - // build the timing data arrays - for (var i = 0; i < pdata.length; i++) { - overall_times.push([pdata[i][0], pdata[i][1]]); - max_overall = Math.max(max_overall, pdata[i][1]); - if (pdata[i][2].length != 0) { - for (var j = 0; j < pdata[i][2].length; j++) { - sub_times[j] = sub_times[j] || []; - sub_times[j].push([pdata[i][0],pdata[i][2][j][0]]); - max_sub = Math.max(max_sub, pdata[i][2][j][0]); - } - } - }; - - // is there a significant difference between the overall times - // and the internal timings? - - var ya = 1; - if ((max_overall > (5 * max_sub)) || ((max_overall * 5) < max_sub)) - ya = 2; - - // put the data into the chart format - chart_data.push({data: overall_times.sort(sorter), label: "Overall Time", color: "#804040"}); - for(var i = 0; i < sub_times.length; i++) { - var n = (sub_times[i].length/overall_times.length); - chart_data.push({data: sub_times[i].sort(sorter), label: "Timer "+ (i+1), - lines: { show: (.9").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},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(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i. -shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j -)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/pkgs/plt-services/meta/drdr/static/jquery.flot.js b/pkgs/plt-services/meta/drdr/static/jquery.flot.js deleted file mode 100644 index aabc544e9a..0000000000 --- a/pkgs/plt-services/meta/drdr/static/jquery.flot.js +++ /dev/null @@ -1,2599 +0,0 @@ -/*! Javascript plotting library for jQuery, v. 0.7. - * - * Released under the MIT license by IOLA, December 2007. - * - */ - -// first an inline dependency, jquery.colorhelpers.js, we inline it here -// for convenience - -/* Plugin for jQuery for working with colors. - * - * Version 1.1. - * - * Inspiration from jQuery color animation plugin by John Resig. - * - * Released under the MIT license by Ole Laursen, October 2009. - * - * Examples: - * - * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() - * var c = $.color.extract($("#mydiv"), 'background-color'); - * console.log(c.r, c.g, c.b, c.a); - * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" - * - * Note that .scale() and .add() return the same modified object - * instead of making a new one. - * - * V. 1.1: Fix error handling so e.g. parsing an empty string does - * produce a color rather than just crashing. - */ -(function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H=1){return"rgb("+[G.r,G.g,G.b].join(",")+")"}else{return"rgba("+[G.r,G.g,G.b,G.a].join(",")+")"}};G.normalize=function(){function H(J,K,I){return KI?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=""&&E!="transparent"){break}D=D.parent()}while(!B.nodeName(D.get(0),"body"));if(E=="rgba(0, 0, 0, 0)"){E="transparent"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D=="transparent"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery); - -// the actual Flot code -(function($) { - function Plot(placeholder, data_, options_, plugins) { - // data is on the form: - // [ series1, series2 ... ] - // where series is either just the data as [ [x1, y1], [x2, y2], ... ] - // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... } - - var series = [], - options = { - // the color theme used for graphs - colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"], - legend: { - show: true, - noColumns: 1, // number of colums in legend table - labelFormatter: null, // fn: string -> string - labelBoxBorderColor: "#ccc", // border color for the little label boxes - container: null, // container (as jQuery object) to put legend in, null means default on top of graph - position: "ne", // position of default legend container within plot - margin: 5, // distance from grid edge to default legend container within plot - backgroundColor: null, // null means auto-detect - backgroundOpacity: 0.85 // set to 0 to avoid background - }, - xaxis: { - show: null, // null = auto-detect, true = always, false = never - position: "bottom", // or "top" - mode: null, // null or "time" - color: null, // base color, labels, ticks - tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)" - transform: null, // null or f: number -> number to transform axis - inverseTransform: null, // if transform is set, this should be the inverse function - min: null, // min. value to show, null means set automatically - max: null, // max. value to show, null means set automatically - autoscaleMargin: null, // margin in % to add if auto-setting min/max - ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks - tickFormatter: null, // fn: number -> string - labelWidth: null, // size of tick labels in pixels - labelHeight: null, - reserveSpace: null, // whether to reserve space even if axis isn't shown - tickLength: null, // size in pixels of ticks, or "full" for whole line - alignTicksWithAxis: null, // axis number or null for no sync - - // mode specific options - tickDecimals: null, // no. of decimals, null means auto - tickSize: null, // number or [number, "unit"] - minTickSize: null, // number or [number, "unit"] - monthNames: null, // list of names of months - timeformat: null, // format string to use - twelveHourClock: false // 12 or 24 time in time mode - }, - yaxis: { - autoscaleMargin: 0.02, - position: "left" // or "right" - }, - xaxes: [], - yaxes: [], - series: { - points: { - show: false, - radius: 3, - lineWidth: 2, // in pixels - fill: true, - fillColor: "#ffffff", - symbol: "circle" // or callback - }, - lines: { - // we don't put in show: false so we can see - // whether lines were actively disabled - lineWidth: 2, // in pixels - fill: false, - fillColor: null, - steps: false - }, - bars: { - show: false, - lineWidth: 2, // in pixels - barWidth: 1, // in units of the x axis - fill: true, - fillColor: null, - align: "left", // or "center" - horizontal: false - }, - shadowSize: 3 - }, - grid: { - show: true, - aboveData: false, - color: "#545454", // primary color used for outline and labels - backgroundColor: null, // null for transparent, else color - borderColor: null, // set if different from the grid color - tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)" - labelMargin: 5, // in pixels - axisMargin: 8, // in pixels - borderWidth: 2, // in pixels - minBorderMargin: null, // in pixels, null means taken from points radius - markings: null, // array of ranges or fn: axes -> array of ranges - markingsColor: "#f4f4f4", - markingsLineWidth: 2, - // interactive stuff - clickable: false, - hoverable: false, - autoHighlight: true, // highlight in case mouse is near - mouseActiveRadius: 10 // how far the mouse can be away to activate an item - }, - hooks: {} - }, - canvas = null, // the canvas for the plot itself - overlay = null, // canvas for interactive stuff on top of plot - eventHolder = null, // jQuery object that events should be bound to - ctx = null, octx = null, - xaxes = [], yaxes = [], - plotOffset = { left: 0, right: 0, top: 0, bottom: 0}, - canvasWidth = 0, canvasHeight = 0, - plotWidth = 0, plotHeight = 0, - hooks = { - processOptions: [], - processRawData: [], - processDatapoints: [], - drawSeries: [], - draw: [], - bindEvents: [], - drawOverlay: [], - shutdown: [] - }, - plot = this; - - // public functions - plot.setData = setData; - plot.setupGrid = setupGrid; - plot.draw = draw; - plot.getPlaceholder = function() { return placeholder; }; - plot.getCanvas = function() { return canvas; }; - plot.getPlotOffset = function() { return plotOffset; }; - plot.width = function () { return plotWidth; }; - plot.height = function () { return plotHeight; }; - plot.offset = function () { - var o = eventHolder.offset(); - o.left += plotOffset.left; - o.top += plotOffset.top; - return o; - }; - plot.getData = function () { return series; }; - plot.getAxes = function () { - var res = {}, i; - $.each(xaxes.concat(yaxes), function (_, axis) { - if (axis) - res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis; - }); - return res; - }; - plot.getXAxes = function () { return xaxes; }; - plot.getYAxes = function () { return yaxes; }; - plot.c2p = canvasToAxisCoords; - plot.p2c = axisToCanvasCoords; - plot.getOptions = function () { return options; }; - plot.highlight = highlight; - plot.unhighlight = unhighlight; - plot.triggerRedrawOverlay = triggerRedrawOverlay; - plot.pointOffset = function(point) { - return { - left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left), - top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top) - }; - }; - plot.shutdown = shutdown; - plot.resize = function () { - getCanvasDimensions(); - resizeCanvas(canvas); - resizeCanvas(overlay); - }; - - // public attributes - plot.hooks = hooks; - - // initialize - initPlugins(plot); - parseOptions(options_); - setupCanvases(); - setData(data_); - setupGrid(); - draw(); - bindEvents(); - - - function executeHooks(hook, args) { - args = [plot].concat(args); - for (var i = 0; i < hook.length; ++i) - hook[i].apply(this, args); - } - - function initPlugins() { - for (var i = 0; i < plugins.length; ++i) { - var p = plugins[i]; - p.init(plot); - if (p.options) - $.extend(true, options, p.options); - } - } - - function parseOptions(opts) { - var i; - - $.extend(true, options, opts); - - if (options.xaxis.color == null) - options.xaxis.color = options.grid.color; - if (options.yaxis.color == null) - options.yaxis.color = options.grid.color; - - if (options.xaxis.tickColor == null) // backwards-compatibility - options.xaxis.tickColor = options.grid.tickColor; - if (options.yaxis.tickColor == null) // backwards-compatibility - options.yaxis.tickColor = options.grid.tickColor; - - if (options.grid.borderColor == null) - options.grid.borderColor = options.grid.color; - if (options.grid.tickColor == null) - options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString(); - - // fill in defaults in axes, copy at least always the - // first as the rest of the code assumes it'll be there - for (i = 0; i < Math.max(1, options.xaxes.length); ++i) - options.xaxes[i] = $.extend(true, {}, options.xaxis, options.xaxes[i]); - for (i = 0; i < Math.max(1, options.yaxes.length); ++i) - options.yaxes[i] = $.extend(true, {}, options.yaxis, options.yaxes[i]); - - // backwards compatibility, to be removed in future - if (options.xaxis.noTicks && options.xaxis.ticks == null) - options.xaxis.ticks = options.xaxis.noTicks; - if (options.yaxis.noTicks && options.yaxis.ticks == null) - options.yaxis.ticks = options.yaxis.noTicks; - if (options.x2axis) { - options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis); - options.xaxes[1].position = "top"; - } - if (options.y2axis) { - options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis); - options.yaxes[1].position = "right"; - } - if (options.grid.coloredAreas) - options.grid.markings = options.grid.coloredAreas; - if (options.grid.coloredAreasColor) - options.grid.markingsColor = options.grid.coloredAreasColor; - if (options.lines) - $.extend(true, options.series.lines, options.lines); - if (options.points) - $.extend(true, options.series.points, options.points); - if (options.bars) - $.extend(true, options.series.bars, options.bars); - if (options.shadowSize != null) - options.series.shadowSize = options.shadowSize; - - // save options on axes for future reference - for (i = 0; i < options.xaxes.length; ++i) - getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i]; - for (i = 0; i < options.yaxes.length; ++i) - getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i]; - - // add hooks from options - for (var n in hooks) - if (options.hooks[n] && options.hooks[n].length) - hooks[n] = hooks[n].concat(options.hooks[n]); - - executeHooks(hooks.processOptions, [options]); - } - - function setData(d) { - series = parseData(d); - fillInSeriesOptions(); - processData(); - } - - function parseData(d) { - var res = []; - for (var i = 0; i < d.length; ++i) { - var s = $.extend(true, {}, options.series); - - if (d[i].data != null) { - s.data = d[i].data; // move the data instead of deep-copy - delete d[i].data; - - $.extend(true, s, d[i]); - - d[i].data = s.data; - } - else - s.data = d[i]; - res.push(s); - } - - return res; - } - - function axisNumber(obj, coord) { - var a = obj[coord + "axis"]; - if (typeof a == "object") // if we got a real axis, extract number - a = a.n; - if (typeof a != "number") - a = 1; // default to first axis - return a; - } - - function allAxes() { - // return flat array without annoying null entries - return $.grep(xaxes.concat(yaxes), function (a) { return a; }); - } - - function canvasToAxisCoords(pos) { - // return an object with x/y corresponding to all used axes - var res = {}, i, axis; - for (i = 0; i < xaxes.length; ++i) { - axis = xaxes[i]; - if (axis && axis.used) - res["x" + axis.n] = axis.c2p(pos.left); - } - - for (i = 0; i < yaxes.length; ++i) { - axis = yaxes[i]; - if (axis && axis.used) - res["y" + axis.n] = axis.c2p(pos.top); - } - - if (res.x1 !== undefined) - res.x = res.x1; - if (res.y1 !== undefined) - res.y = res.y1; - - return res; - } - - function axisToCanvasCoords(pos) { - // get canvas coords from the first pair of x/y found in pos - var res = {}, i, axis, key; - - for (i = 0; i < xaxes.length; ++i) { - axis = xaxes[i]; - if (axis && axis.used) { - key = "x" + axis.n; - if (pos[key] == null && axis.n == 1) - key = "x"; - - if (pos[key] != null) { - res.left = axis.p2c(pos[key]); - break; - } - } - } - - for (i = 0; i < yaxes.length; ++i) { - axis = yaxes[i]; - if (axis && axis.used) { - key = "y" + axis.n; - if (pos[key] == null && axis.n == 1) - key = "y"; - - if (pos[key] != null) { - res.top = axis.p2c(pos[key]); - break; - } - } - } - - return res; - } - - function getOrCreateAxis(axes, number) { - if (!axes[number - 1]) - axes[number - 1] = { - n: number, // save the number for future reference - direction: axes == xaxes ? "x" : "y", - options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis) - }; - - return axes[number - 1]; - } - - function fillInSeriesOptions() { - var i; - - // collect what we already got of colors - var neededColors = series.length, - usedColors = [], - assignedColors = []; - for (i = 0; i < series.length; ++i) { - var sc = series[i].color; - if (sc != null) { - --neededColors; - if (typeof sc == "number") - assignedColors.push(sc); - else - usedColors.push($.color.parse(series[i].color)); - } - } - - // we might need to generate more colors if higher indices - // are assigned - for (i = 0; i < assignedColors.length; ++i) { - neededColors = Math.max(neededColors, assignedColors[i] + 1); - } - - // produce colors as needed - var colors = [], variation = 0; - i = 0; - while (colors.length < neededColors) { - var c; - if (options.colors.length == i) // check degenerate case - c = $.color.make(100, 100, 100); - else - c = $.color.parse(options.colors[i]); - - // vary color if needed - var sign = variation % 2 == 1 ? -1 : 1; - c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2) - - // FIXME: if we're getting to close to something else, - // we should probably skip this one - colors.push(c); - - ++i; - if (i >= options.colors.length) { - i = 0; - ++variation; - } - } - - // fill in the options - var colori = 0, s; - for (i = 0; i < series.length; ++i) { - s = series[i]; - - // assign colors - if (s.color == null) { - s.color = colors[colori].toString(); - ++colori; - } - else if (typeof s.color == "number") - s.color = colors[s.color].toString(); - - // turn on lines automatically in case nothing is set - if (s.lines.show == null) { - var v, show = true; - for (v in s) - if (s[v] && s[v].show) { - show = false; - break; - } - if (show) - s.lines.show = true; - } - - // setup axes - s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x")); - s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y")); - } - } - - function processData() { - var topSentry = Number.POSITIVE_INFINITY, - bottomSentry = Number.NEGATIVE_INFINITY, - fakeInfinity = Number.MAX_VALUE, - i, j, k, m, length, - s, points, ps, x, y, axis, val, f, p; - - function updateAxis(axis, min, max) { - if (min < axis.datamin && min != -fakeInfinity) - axis.datamin = min; - if (max > axis.datamax && max != fakeInfinity) - axis.datamax = max; - } - - $.each(allAxes(), function (_, axis) { - // init axis - axis.datamin = topSentry; - axis.datamax = bottomSentry; - axis.used = false; - }); - - for (i = 0; i < series.length; ++i) { - s = series[i]; - s.datapoints = { points: [] }; - - executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]); - } - - // first pass: clean and copy data - for (i = 0; i < series.length; ++i) { - s = series[i]; - - var data = s.data, format = s.datapoints.format; - - if (!format) { - format = []; - // find out how to copy - format.push({ x: true, number: true, required: true }); - format.push({ y: true, number: true, required: true }); - - if (s.bars.show || (s.lines.show && s.lines.fill)) { - format.push({ y: true, number: true, required: false, defaultValue: 0 }); - if (s.bars.horizontal) { - delete format[format.length - 1].y; - format[format.length - 1].x = true; - } - } - - s.datapoints.format = format; - } - - if (s.datapoints.pointsize != null) - continue; // already filled in - - s.datapoints.pointsize = format.length; - - ps = s.datapoints.pointsize; - points = s.datapoints.points; - - insertSteps = s.lines.show && s.lines.steps; - s.xaxis.used = s.yaxis.used = true; - - for (j = k = 0; j < data.length; ++j, k += ps) { - p = data[j]; - - var nullify = p == null; - if (!nullify) { - for (m = 0; m < ps; ++m) { - val = p[m]; - f = format[m]; - - if (f) { - if (f.number && val != null) { - val = +val; // convert to number - if (isNaN(val)) - val = null; - else if (val == Infinity) - val = fakeInfinity; - else if (val == -Infinity) - val = -fakeInfinity; - } - - if (val == null) { - if (f.required) - nullify = true; - - if (f.defaultValue != null) - val = f.defaultValue; - } - } - - points[k + m] = val; - } - } - - if (nullify) { - for (m = 0; m < ps; ++m) { - val = points[k + m]; - if (val != null) { - f = format[m]; - // extract min/max info - if (f.x) - updateAxis(s.xaxis, val, val); - if (f.y) - updateAxis(s.yaxis, val, val); - } - points[k + m] = null; - } - } - else { - // a little bit of line specific stuff that - // perhaps shouldn't be here, but lacking - // better means... - if (insertSteps && k > 0 - && points[k - ps] != null - && points[k - ps] != points[k] - && points[k - ps + 1] != points[k + 1]) { - // copy the point to make room for a middle point - for (m = 0; m < ps; ++m) - points[k + ps + m] = points[k + m]; - - // middle point has same y - points[k + 1] = points[k - ps + 1]; - - // we've added a point, better reflect that - k += ps; - } - } - } - } - - // give the hooks a chance to run - for (i = 0; i < series.length; ++i) { - s = series[i]; - - executeHooks(hooks.processDatapoints, [ s, s.datapoints]); - } - - // second pass: find datamax/datamin for auto-scaling - for (i = 0; i < series.length; ++i) { - s = series[i]; - points = s.datapoints.points, - ps = s.datapoints.pointsize; - - var xmin = topSentry, ymin = topSentry, - xmax = bottomSentry, ymax = bottomSentry; - - for (j = 0; j < points.length; j += ps) { - if (points[j] == null) - continue; - - for (m = 0; m < ps; ++m) { - val = points[j + m]; - f = format[m]; - if (!f || val == fakeInfinity || val == -fakeInfinity) - continue; - - if (f.x) { - if (val < xmin) - xmin = val; - if (val > xmax) - xmax = val; - } - if (f.y) { - if (val < ymin) - ymin = val; - if (val > ymax) - ymax = val; - } - } - } - - if (s.bars.show) { - // make sure we got room for the bar on the dancing floor - var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2; - if (s.bars.horizontal) { - ymin += delta; - ymax += delta + s.bars.barWidth; - } - else { - xmin += delta; - xmax += delta + s.bars.barWidth; - } - } - - updateAxis(s.xaxis, xmin, xmax); - updateAxis(s.yaxis, ymin, ymax); - } - - $.each(allAxes(), function (_, axis) { - if (axis.datamin == topSentry) - axis.datamin = null; - if (axis.datamax == bottomSentry) - axis.datamax = null; - }); - } - - function makeCanvas(skipPositioning, cls) { - var c = document.createElement('canvas'); - c.className = cls; - c.width = canvasWidth; - c.height = canvasHeight; - - if (!skipPositioning) - $(c).css({ position: 'absolute', left: 0, top: 0 }); - - $(c).appendTo(placeholder); - - if (!c.getContext) // excanvas hack - c = window.G_vmlCanvasManager.initElement(c); - - // used for resetting in case we get replotted - c.getContext("2d").save(); - - return c; - } - - function getCanvasDimensions() { - canvasWidth = placeholder.width(); - canvasHeight = placeholder.height(); - - if (canvasWidth <= 0 || canvasHeight <= 0) - throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight; - } - - function resizeCanvas(c) { - // resizing should reset the state (excanvas seems to be - // buggy though) - if (c.width != canvasWidth) - c.width = canvasWidth; - - if (c.height != canvasHeight) - c.height = canvasHeight; - - // so try to get back to the initial state (even if it's - // gone now, this should be safe according to the spec) - var cctx = c.getContext("2d"); - cctx.restore(); - - // and save again - cctx.save(); - } - - function setupCanvases() { - var reused, - existingCanvas = placeholder.children("canvas.base"), - existingOverlay = placeholder.children("canvas.overlay"); - - if (existingCanvas.length == 0 || existingOverlay == 0) { - // init everything - - placeholder.html(""); // make sure placeholder is clear - - placeholder.css({ padding: 0 }); // padding messes up the positioning - - if (placeholder.css("position") == 'static') - placeholder.css("position", "relative"); // for positioning labels and overlay - - getCanvasDimensions(); - - canvas = makeCanvas(true, "base"); - overlay = makeCanvas(false, "overlay"); // overlay canvas for interactive features - - reused = false; - } - else { - // reuse existing elements - - canvas = existingCanvas.get(0); - overlay = existingOverlay.get(0); - - reused = true; - } - - ctx = canvas.getContext("2d"); - octx = overlay.getContext("2d"); - - // we include the canvas in the event holder too, because IE 7 - // sometimes has trouble with the stacking order - eventHolder = $([overlay, canvas]); - - if (reused) { - // run shutdown in the old plot object - placeholder.data("plot").shutdown(); - - // reset reused canvases - plot.resize(); - - // make sure overlay pixels are cleared (canvas is cleared when we redraw) - octx.clearRect(0, 0, canvasWidth, canvasHeight); - - // then whack any remaining obvious garbage left - eventHolder.unbind(); - placeholder.children().not([canvas, overlay]).remove(); - } - - // save in case we get replotted - placeholder.data("plot", plot); - } - - function bindEvents() { - // bind events - if (options.grid.hoverable) { - eventHolder.mousemove(onMouseMove); - eventHolder.mouseleave(onMouseLeave); - } - - if (options.grid.clickable) - eventHolder.click(onClick); - - executeHooks(hooks.bindEvents, [eventHolder]); - } - - function shutdown() { - if (redrawTimeout) - clearTimeout(redrawTimeout); - - eventHolder.unbind("mousemove", onMouseMove); - eventHolder.unbind("mouseleave", onMouseLeave); - eventHolder.unbind("click", onClick); - - executeHooks(hooks.shutdown, [eventHolder]); - } - - function setTransformationHelpers(axis) { - // set helper functions on the axis, assumes plot area - // has been computed already - - function identity(x) { return x; } - - var s, m, t = axis.options.transform || identity, - it = axis.options.inverseTransform; - - // precompute how much the axis is scaling a point - // in canvas space - if (axis.direction == "x") { - s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min)); - m = Math.min(t(axis.max), t(axis.min)); - } - else { - s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min)); - s = -s; - m = Math.max(t(axis.max), t(axis.min)); - } - - // data point to canvas coordinate - if (t == identity) // slight optimization - axis.p2c = function (p) { return (p - m) * s; }; - else - axis.p2c = function (p) { return (t(p) - m) * s; }; - // canvas coordinate to data point - if (!it) - axis.c2p = function (c) { return m + c / s; }; - else - axis.c2p = function (c) { return it(m + c / s); }; - } - - function measureTickLabels(axis) { - var opts = axis.options, i, ticks = axis.ticks || [], labels = [], - l, w = opts.labelWidth, h = opts.labelHeight, dummyDiv; - - function makeDummyDiv(labels, width) { - return $('
' + - '
' - + labels.join("") + '
') - .appendTo(placeholder); - } - - if (axis.direction == "x") { - // to avoid measuring the widths of the labels (it's slow), we - // construct fixed-size boxes and put the labels inside - // them, we don't need the exact figures and the - // fixed-size box content is easy to center - if (w == null) - w = Math.floor(canvasWidth / (ticks.length > 0 ? ticks.length : 1)); - - // measure x label heights - if (h == null) { - labels = []; - for (i = 0; i < ticks.length; ++i) { - l = ticks[i].label; - if (l) - labels.push('
' + l + '
'); - } - - if (labels.length > 0) { - // stick them all in the same div and measure - // collective height - labels.push('
'); - dummyDiv = makeDummyDiv(labels, "width:10000px;"); - h = dummyDiv.height(); - dummyDiv.remove(); - } - } - } - else if (w == null || h == null) { - // calculate y label dimensions - for (i = 0; i < ticks.length; ++i) { - l = ticks[i].label; - if (l) - labels.push('
' + l + '
'); - } - - if (labels.length > 0) { - dummyDiv = makeDummyDiv(labels, ""); - if (w == null) - w = dummyDiv.children().width(); - if (h == null) - h = dummyDiv.find("div.tickLabel").height(); - dummyDiv.remove(); - } - } - - if (w == null) - w = 0; - if (h == null) - h = 0; - - axis.labelWidth = w; - axis.labelHeight = h; - } - - function allocateAxisBoxFirstPhase(axis) { - // find the bounding box of the axis by looking at label - // widths/heights and ticks, make room by diminishing the - // plotOffset - - var lw = axis.labelWidth, - lh = axis.labelHeight, - pos = axis.options.position, - tickLength = axis.options.tickLength, - axismargin = options.grid.axisMargin, - padding = options.grid.labelMargin, - all = axis.direction == "x" ? xaxes : yaxes, - index; - - // determine axis margin - var samePosition = $.grep(all, function (a) { - return a && a.options.position == pos && a.reserveSpace; - }); - if ($.inArray(axis, samePosition) == samePosition.length - 1) - axismargin = 0; // outermost - - // determine tick length - if we're innermost, we can use "full" - if (tickLength == null) - tickLength = "full"; - - var sameDirection = $.grep(all, function (a) { - return a && a.reserveSpace; - }); - - var innermost = $.inArray(axis, sameDirection) == 0; - if (!innermost && tickLength == "full") - tickLength = 5; - - if (!isNaN(+tickLength)) - padding += +tickLength; - - // compute box - if (axis.direction == "x") { - lh += padding; - - if (pos == "bottom") { - plotOffset.bottom += lh + axismargin; - axis.box = { top: canvasHeight - plotOffset.bottom, height: lh }; - } - else { - axis.box = { top: plotOffset.top + axismargin, height: lh }; - plotOffset.top += lh + axismargin; - } - } - else { - lw += padding; - - if (pos == "left") { - axis.box = { left: plotOffset.left + axismargin, width: lw }; - plotOffset.left += lw + axismargin; - } - else { - plotOffset.right += lw + axismargin; - axis.box = { left: canvasWidth - plotOffset.right, width: lw }; - } - } - - // save for future reference - axis.position = pos; - axis.tickLength = tickLength; - axis.box.padding = padding; - axis.innermost = innermost; - } - - function allocateAxisBoxSecondPhase(axis) { - // set remaining bounding box coordinates - if (axis.direction == "x") { - axis.box.left = plotOffset.left; - axis.box.width = plotWidth; - } - else { - axis.box.top = plotOffset.top; - axis.box.height = plotHeight; - } - } - - function setupGrid() { - var i, axes = allAxes(); - - // first calculate the plot and axis box dimensions - - $.each(axes, function (_, axis) { - axis.show = axis.options.show; - if (axis.show == null) - axis.show = axis.used; // by default an axis is visible if it's got data - - axis.reserveSpace = axis.show || axis.options.reserveSpace; - - setRange(axis); - }); - - allocatedAxes = $.grep(axes, function (axis) { return axis.reserveSpace; }); - - plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0; - if (options.grid.show) { - $.each(allocatedAxes, function (_, axis) { - // make the ticks - setupTickGeneration(axis); - setTicks(axis); - snapRangeToTicks(axis, axis.ticks); - - // find labelWidth/Height for axis - measureTickLabels(axis); - }); - - // with all dimensions in house, we can compute the - // axis boxes, start from the outside (reverse order) - for (i = allocatedAxes.length - 1; i >= 0; --i) - allocateAxisBoxFirstPhase(allocatedAxes[i]); - - // make sure we've got enough space for things that - // might stick out - var minMargin = options.grid.minBorderMargin; - if (minMargin == null) { - minMargin = 0; - for (i = 0; i < series.length; ++i) - minMargin = Math.max(minMargin, series[i].points.radius + series[i].points.lineWidth/2); - } - - for (var a in plotOffset) { - plotOffset[a] += options.grid.borderWidth; - plotOffset[a] = Math.max(minMargin, plotOffset[a]); - } - } - - plotWidth = canvasWidth - plotOffset.left - plotOffset.right; - plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top; - - // now we got the proper plotWidth/Height, we can compute the scaling - $.each(axes, function (_, axis) { - setTransformationHelpers(axis); - }); - - if (options.grid.show) { - $.each(allocatedAxes, function (_, axis) { - allocateAxisBoxSecondPhase(axis); - }); - - insertAxisLabels(); - } - - insertLegend(); - } - - function setRange(axis) { - var opts = axis.options, - min = +(opts.min != null ? opts.min : axis.datamin), - max = +(opts.max != null ? opts.max : axis.datamax), - delta = max - min; - - if (delta == 0.0) { - // degenerate case - var widen = max == 0 ? 1 : 0.01; - - if (opts.min == null) - min -= widen; - // always widen max if we couldn't widen min to ensure we - // don't fall into min == max which doesn't work - if (opts.max == null || opts.min != null) - max += widen; - } - else { - // consider autoscaling - var margin = opts.autoscaleMargin; - if (margin != null) { - if (opts.min == null) { - min -= delta * margin; - // make sure we don't go below zero if all values - // are positive - if (min < 0 && axis.datamin != null && axis.datamin >= 0) - min = 0; - } - if (opts.max == null) { - max += delta * margin; - if (max > 0 && axis.datamax != null && axis.datamax <= 0) - max = 0; - } - } - } - axis.min = min; - axis.max = max; - } - - function setupTickGeneration(axis) { - var opts = axis.options; - - // estimate number of ticks - var noTicks; - if (typeof opts.ticks == "number" && opts.ticks > 0) - noTicks = opts.ticks; - else - // heuristic based on the model a*sqrt(x) fitted to - // some data points that seemed reasonable - noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? canvasWidth : canvasHeight); - - var delta = (axis.max - axis.min) / noTicks, - size, generator, unit, formatter, i, magn, norm; - - if (opts.mode == "time") { - // pretty handling of time - - // map of app. size of time units in milliseconds - var timeUnitSize = { - "second": 1000, - "minute": 60 * 1000, - "hour": 60 * 60 * 1000, - "day": 24 * 60 * 60 * 1000, - "month": 30 * 24 * 60 * 60 * 1000, - "year": 365.2425 * 24 * 60 * 60 * 1000 - }; - - - // the allowed tick sizes, after 1 year we use - // an integer algorithm - var spec = [ - [1, "second"], [2, "second"], [5, "second"], [10, "second"], - [30, "second"], - [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], - [30, "minute"], - [1, "hour"], [2, "hour"], [4, "hour"], - [8, "hour"], [12, "hour"], - [1, "day"], [2, "day"], [3, "day"], - [0.25, "month"], [0.5, "month"], [1, "month"], - [2, "month"], [3, "month"], [6, "month"], - [1, "year"] - ]; - - var minSize = 0; - if (opts.minTickSize != null) { - if (typeof opts.tickSize == "number") - minSize = opts.tickSize; - else - minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]]; - } - - for (var i = 0; i < spec.length - 1; ++i) - if (delta < (spec[i][0] * timeUnitSize[spec[i][1]] - + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2 - && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) - break; - size = spec[i][0]; - unit = spec[i][1]; - - // special-case the possibility of several years - if (unit == "year") { - magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10)); - norm = (delta / timeUnitSize.year) / magn; - if (norm < 1.5) - size = 1; - else if (norm < 3) - size = 2; - else if (norm < 7.5) - size = 5; - else - size = 10; - - size *= magn; - } - - axis.tickSize = opts.tickSize || [size, unit]; - - generator = function(axis) { - var ticks = [], - tickSize = axis.tickSize[0], unit = axis.tickSize[1], - d = new Date(axis.min); - - var step = tickSize * timeUnitSize[unit]; - - if (unit == "second") - d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize)); - if (unit == "minute") - d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize)); - if (unit == "hour") - d.setUTCHours(floorInBase(d.getUTCHours(), tickSize)); - if (unit == "month") - d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize)); - if (unit == "year") - d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize)); - - // reset smaller components - d.setUTCMilliseconds(0); - if (step >= timeUnitSize.minute) - d.setUTCSeconds(0); - if (step >= timeUnitSize.hour) - d.setUTCMinutes(0); - if (step >= timeUnitSize.day) - d.setUTCHours(0); - if (step >= timeUnitSize.day * 4) - d.setUTCDate(1); - if (step >= timeUnitSize.year) - d.setUTCMonth(0); - - - var carry = 0, v = Number.NaN, prev; - do { - prev = v; - v = d.getTime(); - ticks.push(v); - if (unit == "month") { - if (tickSize < 1) { - // a bit complicated - we'll divide the month - // up but we need to take care of fractions - // so we don't end up in the middle of a day - d.setUTCDate(1); - var start = d.getTime(); - d.setUTCMonth(d.getUTCMonth() + 1); - var end = d.getTime(); - d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize); - carry = d.getUTCHours(); - d.setUTCHours(0); - } - else - d.setUTCMonth(d.getUTCMonth() + tickSize); - } - else if (unit == "year") { - d.setUTCFullYear(d.getUTCFullYear() + tickSize); - } - else - d.setTime(v + step); - } while (v < axis.max && v != prev); - - return ticks; - }; - - formatter = function (v, axis) { - var d = new Date(v); - - // first check global format - if (opts.timeformat != null) - return $.plot.formatDate(d, opts.timeformat, opts.monthNames); - - var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]]; - var span = axis.max - axis.min; - var suffix = (opts.twelveHourClock) ? " %p" : ""; - - if (t < timeUnitSize.minute) - fmt = "%h:%M:%S" + suffix; - else if (t < timeUnitSize.day) { - if (span < 2 * timeUnitSize.day) - fmt = "%h:%M" + suffix; - else - fmt = "%b %d %h:%M" + suffix; - } - else if (t < timeUnitSize.month) - fmt = "%b %d"; - else if (t < timeUnitSize.year) { - if (span < timeUnitSize.year) - fmt = "%b"; - else - fmt = "%b %y"; - } - else - fmt = "%y"; - - return $.plot.formatDate(d, fmt, opts.monthNames); - }; - } - else { - // pretty rounding of base-10 numbers - var maxDec = opts.tickDecimals; - var dec = -Math.floor(Math.log(delta) / Math.LN10); - if (maxDec != null && dec > maxDec) - dec = maxDec; - - magn = Math.pow(10, -dec); - norm = delta / magn; // norm is between 1.0 and 10.0 - - if (norm < 1.5) - size = 1; - else if (norm < 3) { - size = 2; - // special case for 2.5, requires an extra decimal - if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) { - size = 2.5; - ++dec; - } - } - else if (norm < 7.5) - size = 5; - else - size = 10; - - size *= magn; - - if (opts.minTickSize != null && size < opts.minTickSize) - size = opts.minTickSize; - - axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec); - axis.tickSize = opts.tickSize || size; - - generator = function (axis) { - var ticks = []; - - // spew out all possible ticks - var start = floorInBase(axis.min, axis.tickSize), - i = 0, v = Number.NaN, prev; - do { - prev = v; - v = start + i * axis.tickSize; - ticks.push(v); - ++i; - } while (v < axis.max && v != prev); - return ticks; - }; - - formatter = function (v, axis) { - return v.toFixed(axis.tickDecimals); - }; - } - - if (opts.alignTicksWithAxis != null) { - var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1]; - if (otherAxis && otherAxis.used && otherAxis != axis) { - // consider snapping min/max to outermost nice ticks - var niceTicks = generator(axis); - if (niceTicks.length > 0) { - if (opts.min == null) - axis.min = Math.min(axis.min, niceTicks[0]); - if (opts.max == null && niceTicks.length > 1) - axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]); - } - - generator = function (axis) { - // copy ticks, scaled to this axis - var ticks = [], v, i; - for (i = 0; i < otherAxis.ticks.length; ++i) { - v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min); - v = axis.min + v * (axis.max - axis.min); - ticks.push(v); - } - return ticks; - }; - - // we might need an extra decimal since forced - // ticks don't necessarily fit naturally - if (axis.mode != "time" && opts.tickDecimals == null) { - var extraDec = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1), - ts = generator(axis); - - // only proceed if the tick interval rounded - // with an extra decimal doesn't give us a - // zero at end - if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec)))) - axis.tickDecimals = extraDec; - } - } - } - - axis.tickGenerator = generator; - if ($.isFunction(opts.tickFormatter)) - axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); }; - else - axis.tickFormatter = formatter; - } - - function setTicks(axis) { - var oticks = axis.options.ticks, ticks = []; - if (oticks == null || (typeof oticks == "number" && oticks > 0)) - ticks = axis.tickGenerator(axis); - else if (oticks) { - if ($.isFunction(oticks)) - // generate the ticks - ticks = oticks({ min: axis.min, max: axis.max }); - else - ticks = oticks; - } - - // clean up/labelify the supplied ticks, copy them over - var i, v; - axis.ticks = []; - for (i = 0; i < ticks.length; ++i) { - var label = null; - var t = ticks[i]; - if (typeof t == "object") { - v = +t[0]; - if (t.length > 1) - label = t[1]; - } - else - v = +t; - if (label == null) - label = axis.tickFormatter(v, axis); - if (!isNaN(v)) - axis.ticks.push({ v: v, label: label }); - } - } - - function snapRangeToTicks(axis, ticks) { - if (axis.options.autoscaleMargin && ticks.length > 0) { - // snap to ticks - if (axis.options.min == null) - axis.min = Math.min(axis.min, ticks[0].v); - if (axis.options.max == null && ticks.length > 1) - axis.max = Math.max(axis.max, ticks[ticks.length - 1].v); - } - } - - function draw() { - ctx.clearRect(0, 0, canvasWidth, canvasHeight); - - var grid = options.grid; - - // draw background, if any - if (grid.show && grid.backgroundColor) - drawBackground(); - - if (grid.show && !grid.aboveData) - drawGrid(); - - for (var i = 0; i < series.length; ++i) { - executeHooks(hooks.drawSeries, [ctx, series[i]]); - drawSeries(series[i]); - } - - executeHooks(hooks.draw, [ctx]); - - if (grid.show && grid.aboveData) - drawGrid(); - } - - function extractRange(ranges, coord) { - var axis, from, to, key, axes = allAxes(); - - for (i = 0; i < axes.length; ++i) { - axis = axes[i]; - if (axis.direction == coord) { - key = coord + axis.n + "axis"; - if (!ranges[key] && axis.n == 1) - key = coord + "axis"; // support x1axis as xaxis - if (ranges[key]) { - from = ranges[key].from; - to = ranges[key].to; - break; - } - } - } - - // backwards-compat stuff - to be removed in future - if (!ranges[key]) { - axis = coord == "x" ? xaxes[0] : yaxes[0]; - from = ranges[coord + "1"]; - to = ranges[coord + "2"]; - } - - // auto-reverse as an added bonus - if (from != null && to != null && from > to) { - var tmp = from; - from = to; - to = tmp; - } - - return { from: from, to: to, axis: axis }; - } - - function drawBackground() { - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)"); - ctx.fillRect(0, 0, plotWidth, plotHeight); - ctx.restore(); - } - - function drawGrid() { - var i; - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - // draw markings - var markings = options.grid.markings; - if (markings) { - if ($.isFunction(markings)) { - var axes = plot.getAxes(); - // xmin etc. is backwards compatibility, to be - // removed in the future - axes.xmin = axes.xaxis.min; - axes.xmax = axes.xaxis.max; - axes.ymin = axes.yaxis.min; - axes.ymax = axes.yaxis.max; - - markings = markings(axes); - } - - for (i = 0; i < markings.length; ++i) { - var m = markings[i], - xrange = extractRange(m, "x"), - yrange = extractRange(m, "y"); - - // fill in missing - if (xrange.from == null) - xrange.from = xrange.axis.min; - if (xrange.to == null) - xrange.to = xrange.axis.max; - if (yrange.from == null) - yrange.from = yrange.axis.min; - if (yrange.to == null) - yrange.to = yrange.axis.max; - - // clip - if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max || - yrange.to < yrange.axis.min || yrange.from > yrange.axis.max) - continue; - - xrange.from = Math.max(xrange.from, xrange.axis.min); - xrange.to = Math.min(xrange.to, xrange.axis.max); - yrange.from = Math.max(yrange.from, yrange.axis.min); - yrange.to = Math.min(yrange.to, yrange.axis.max); - - if (xrange.from == xrange.to && yrange.from == yrange.to) - continue; - - // then draw - xrange.from = xrange.axis.p2c(xrange.from); - xrange.to = xrange.axis.p2c(xrange.to); - yrange.from = yrange.axis.p2c(yrange.from); - yrange.to = yrange.axis.p2c(yrange.to); - - if (xrange.from == xrange.to || yrange.from == yrange.to) { - // draw line - ctx.beginPath(); - ctx.strokeStyle = m.color || options.grid.markingsColor; - ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth; - ctx.moveTo(xrange.from, yrange.from); - ctx.lineTo(xrange.to, yrange.to); - ctx.stroke(); - } - else { - // fill area - ctx.fillStyle = m.color || options.grid.markingsColor; - ctx.fillRect(xrange.from, yrange.to, - xrange.to - xrange.from, - yrange.from - yrange.to); - } - } - } - - // draw the ticks - var axes = allAxes(), bw = options.grid.borderWidth; - - for (var j = 0; j < axes.length; ++j) { - var axis = axes[j], box = axis.box, - t = axis.tickLength, x, y, xoff, yoff; - if (!axis.show || axis.ticks.length == 0) - continue - - ctx.strokeStyle = axis.options.tickColor || $.color.parse(axis.options.color).scale('a', 0.22).toString(); - ctx.lineWidth = 1; - - // find the edges - if (axis.direction == "x") { - x = 0; - if (t == "full") - y = (axis.position == "top" ? 0 : plotHeight); - else - y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0); - } - else { - y = 0; - if (t == "full") - x = (axis.position == "left" ? 0 : plotWidth); - else - x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0); - } - - // draw tick bar - if (!axis.innermost) { - ctx.beginPath(); - xoff = yoff = 0; - if (axis.direction == "x") - xoff = plotWidth; - else - yoff = plotHeight; - - if (ctx.lineWidth == 1) { - x = Math.floor(x) + 0.5; - y = Math.floor(y) + 0.5; - } - - ctx.moveTo(x, y); - ctx.lineTo(x + xoff, y + yoff); - ctx.stroke(); - } - - // draw ticks - ctx.beginPath(); - for (i = 0; i < axis.ticks.length; ++i) { - var v = axis.ticks[i].v; - - xoff = yoff = 0; - - if (v < axis.min || v > axis.max - // skip those lying on the axes if we got a border - || (t == "full" && bw > 0 - && (v == axis.min || v == axis.max))) - continue; - - if (axis.direction == "x") { - x = axis.p2c(v); - yoff = t == "full" ? -plotHeight : t; - - if (axis.position == "top") - yoff = -yoff; - } - else { - y = axis.p2c(v); - xoff = t == "full" ? -plotWidth : t; - - if (axis.position == "left") - xoff = -xoff; - } - - if (ctx.lineWidth == 1) { - if (axis.direction == "x") - x = Math.floor(x) + 0.5; - else - y = Math.floor(y) + 0.5; - } - - ctx.moveTo(x, y); - ctx.lineTo(x + xoff, y + yoff); - } - - ctx.stroke(); - } - - - // draw border - if (bw) { - ctx.lineWidth = bw; - ctx.strokeStyle = options.grid.borderColor; - ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw); - } - - ctx.restore(); - } - - function insertAxisLabels() { - placeholder.find(".tickLabels").remove(); - - var html = ['
']; - - var axes = allAxes(); - for (var j = 0; j < axes.length; ++j) { - var axis = axes[j], box = axis.box; - if (!axis.show) - continue; - //debug: html.push('
') - html.push('
'); - for (var i = 0; i < axis.ticks.length; ++i) { - var tick = axis.ticks[i]; - if (!tick.label || tick.v < axis.min || tick.v > axis.max) - continue; - - var pos = {}, align; - - if (axis.direction == "x") { - align = "center"; - pos.left = Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2); - if (axis.position == "bottom") - pos.top = box.top + box.padding; - else - pos.bottom = canvasHeight - (box.top + box.height - box.padding); - } - else { - pos.top = Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2); - if (axis.position == "left") { - pos.right = canvasWidth - (box.left + box.width - box.padding) - align = "right"; - } - else { - pos.left = box.left + box.padding; - align = "left"; - } - } - - pos.width = axis.labelWidth; - - var style = ["position:absolute", "text-align:" + align ]; - for (var a in pos) - style.push(a + ":" + pos[a] + "px") - - html.push('
' + tick.label + '
'); - } - html.push('
'); - } - - html.push('
'); - - placeholder.append(html.join("")); - } - - function drawSeries(series) { - if (series.lines.show) - drawSeriesLines(series); - if (series.bars.show) - drawSeriesBars(series); - if (series.points.show) - drawSeriesPoints(series); - } - - function drawSeriesLines(series) { - function plotLine(datapoints, xoffset, yoffset, axisx, axisy) { - var points = datapoints.points, - ps = datapoints.pointsize, - prevx = null, prevy = null; - - ctx.beginPath(); - for (var i = ps; i < points.length; i += ps) { - var x1 = points[i - ps], y1 = points[i - ps + 1], - x2 = points[i], y2 = points[i + 1]; - - if (x1 == null || x2 == null) - continue; - - // clip with ymin - if (y1 <= y2 && y1 < axisy.min) { - if (y2 < axisy.min) - continue; // line segment is outside - // compute new intersection point - x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; - y1 = axisy.min; - } - else if (y2 <= y1 && y2 < axisy.min) { - if (y1 < axisy.min) - continue; - x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; - y2 = axisy.min; - } - - // clip with ymax - if (y1 >= y2 && y1 > axisy.max) { - if (y2 > axisy.max) - continue; - x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; - y1 = axisy.max; - } - else if (y2 >= y1 && y2 > axisy.max) { - if (y1 > axisy.max) - continue; - x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; - y2 = axisy.max; - } - - // clip with xmin - if (x1 <= x2 && x1 < axisx.min) { - if (x2 < axisx.min) - continue; - y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; - x1 = axisx.min; - } - else if (x2 <= x1 && x2 < axisx.min) { - if (x1 < axisx.min) - continue; - y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; - x2 = axisx.min; - } - - // clip with xmax - if (x1 >= x2 && x1 > axisx.max) { - if (x2 > axisx.max) - continue; - y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; - x1 = axisx.max; - } - else if (x2 >= x1 && x2 > axisx.max) { - if (x1 > axisx.max) - continue; - y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; - x2 = axisx.max; - } - - if (x1 != prevx || y1 != prevy) - ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset); - - prevx = x2; - prevy = y2; - ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset); - } - ctx.stroke(); - } - - function plotLineArea(datapoints, axisx, axisy) { - var points = datapoints.points, - ps = datapoints.pointsize, - bottom = Math.min(Math.max(0, axisy.min), axisy.max), - i = 0, top, areaOpen = false, - ypos = 1, segmentStart = 0, segmentEnd = 0; - - // we process each segment in two turns, first forward - // direction to sketch out top, then once we hit the - // end we go backwards to sketch the bottom - while (true) { - if (ps > 0 && i > points.length + ps) - break; - - i += ps; // ps is negative if going backwards - - var x1 = points[i - ps], - y1 = points[i - ps + ypos], - x2 = points[i], y2 = points[i + ypos]; - - if (areaOpen) { - if (ps > 0 && x1 != null && x2 == null) { - // at turning point - segmentEnd = i; - ps = -ps; - ypos = 2; - continue; - } - - if (ps < 0 && i == segmentStart + ps) { - // done with the reverse sweep - ctx.fill(); - areaOpen = false; - ps = -ps; - ypos = 1; - i = segmentStart = segmentEnd + ps; - continue; - } - } - - if (x1 == null || x2 == null) - continue; - - // clip x values - - // clip with xmin - if (x1 <= x2 && x1 < axisx.min) { - if (x2 < axisx.min) - continue; - y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; - x1 = axisx.min; - } - else if (x2 <= x1 && x2 < axisx.min) { - if (x1 < axisx.min) - continue; - y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; - x2 = axisx.min; - } - - // clip with xmax - if (x1 >= x2 && x1 > axisx.max) { - if (x2 > axisx.max) - continue; - y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; - x1 = axisx.max; - } - else if (x2 >= x1 && x2 > axisx.max) { - if (x1 > axisx.max) - continue; - y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; - x2 = axisx.max; - } - - if (!areaOpen) { - // open area - ctx.beginPath(); - ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom)); - areaOpen = true; - } - - // now first check the case where both is outside - if (y1 >= axisy.max && y2 >= axisy.max) { - ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max)); - ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max)); - continue; - } - else if (y1 <= axisy.min && y2 <= axisy.min) { - ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min)); - ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min)); - continue; - } - - // else it's a bit more complicated, there might - // be a flat maxed out rectangle first, then a - // triangular cutout or reverse; to find these - // keep track of the current x values - var x1old = x1, x2old = x2; - - // clip the y values, without shortcutting, we - // go through all cases in turn - - // clip with ymin - if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) { - x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; - y1 = axisy.min; - } - else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) { - x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; - y2 = axisy.min; - } - - // clip with ymax - if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) { - x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; - y1 = axisy.max; - } - else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) { - x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; - y2 = axisy.max; - } - - // if the x value was changed we got a rectangle - // to fill - if (x1 != x1old) { - ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1)); - // it goes to (x1, y1), but we fill that below - } - - // fill triangular section, this sometimes result - // in redundant points if (x1, y1) hasn't changed - // from previous line to, but we just ignore that - ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1)); - ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); - - // fill the other rectangle if it's there - if (x2 != x2old) { - ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); - ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2)); - } - } - } - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - ctx.lineJoin = "round"; - - var lw = series.lines.lineWidth, - sw = series.shadowSize; - // FIXME: consider another form of shadow when filling is turned on - if (lw > 0 && sw > 0) { - // draw shadow as a thick and thin line with transparency - ctx.lineWidth = sw; - ctx.strokeStyle = "rgba(0,0,0,0.1)"; - // position shadow at angle from the mid of line - var angle = Math.PI/18; - plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis); - ctx.lineWidth = sw/2; - plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis); - } - - ctx.lineWidth = lw; - ctx.strokeStyle = series.color; - var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight); - if (fillStyle) { - ctx.fillStyle = fillStyle; - plotLineArea(series.datapoints, series.xaxis, series.yaxis); - } - - if (lw > 0) - plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis); - ctx.restore(); - } - - function drawSeriesPoints(series) { - function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) { - var points = datapoints.points, ps = datapoints.pointsize; - - for (var i = 0; i < points.length; i += ps) { - var x = points[i], y = points[i + 1]; - if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) - continue; - - ctx.beginPath(); - x = axisx.p2c(x); - y = axisy.p2c(y) + offset; - if (symbol == "circle") - ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false); - else - symbol(ctx, x, y, radius, shadow); - ctx.closePath(); - - if (fillStyle) { - ctx.fillStyle = fillStyle; - ctx.fill(); - } - ctx.stroke(); - } - } - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - var lw = series.points.lineWidth, - sw = series.shadowSize, - radius = series.points.radius, - symbol = series.points.symbol; - if (lw > 0 && sw > 0) { - // draw shadow in two steps - var w = sw / 2; - ctx.lineWidth = w; - ctx.strokeStyle = "rgba(0,0,0,0.1)"; - plotPoints(series.datapoints, radius, null, w + w/2, true, - series.xaxis, series.yaxis, symbol); - - ctx.strokeStyle = "rgba(0,0,0,0.2)"; - plotPoints(series.datapoints, radius, null, w/2, true, - series.xaxis, series.yaxis, symbol); - } - - ctx.lineWidth = lw; - ctx.strokeStyle = series.color; - plotPoints(series.datapoints, radius, - getFillStyle(series.points, series.color), 0, false, - series.xaxis, series.yaxis, symbol); - ctx.restore(); - } - - function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) { - var left, right, bottom, top, - drawLeft, drawRight, drawTop, drawBottom, - tmp; - - // in horizontal mode, we start the bar from the left - // instead of from the bottom so it appears to be - // horizontal rather than vertical - if (horizontal) { - drawBottom = drawRight = drawTop = true; - drawLeft = false; - left = b; - right = x; - top = y + barLeft; - bottom = y + barRight; - - // account for negative bars - if (right < left) { - tmp = right; - right = left; - left = tmp; - drawLeft = true; - drawRight = false; - } - } - else { - drawLeft = drawRight = drawTop = true; - drawBottom = false; - left = x + barLeft; - right = x + barRight; - bottom = b; - top = y; - - // account for negative bars - if (top < bottom) { - tmp = top; - top = bottom; - bottom = tmp; - drawBottom = true; - drawTop = false; - } - } - - // clip - if (right < axisx.min || left > axisx.max || - top < axisy.min || bottom > axisy.max) - return; - - if (left < axisx.min) { - left = axisx.min; - drawLeft = false; - } - - if (right > axisx.max) { - right = axisx.max; - drawRight = false; - } - - if (bottom < axisy.min) { - bottom = axisy.min; - drawBottom = false; - } - - if (top > axisy.max) { - top = axisy.max; - drawTop = false; - } - - left = axisx.p2c(left); - bottom = axisy.p2c(bottom); - right = axisx.p2c(right); - top = axisy.p2c(top); - - // fill the bar - if (fillStyleCallback) { - c.beginPath(); - c.moveTo(left, bottom); - c.lineTo(left, top); - c.lineTo(right, top); - c.lineTo(right, bottom); - c.fillStyle = fillStyleCallback(bottom, top); - c.fill(); - } - - // draw outline - if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) { - c.beginPath(); - - // FIXME: inline moveTo is buggy with excanvas - c.moveTo(left, bottom + offset); - if (drawLeft) - c.lineTo(left, top + offset); - else - c.moveTo(left, top + offset); - if (drawTop) - c.lineTo(right, top + offset); - else - c.moveTo(right, top + offset); - if (drawRight) - c.lineTo(right, bottom + offset); - else - c.moveTo(right, bottom + offset); - if (drawBottom) - c.lineTo(left, bottom + offset); - else - c.moveTo(left, bottom + offset); - c.stroke(); - } - } - - function drawSeriesBars(series) { - function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) { - var points = datapoints.points, ps = datapoints.pointsize; - - for (var i = 0; i < points.length; i += ps) { - if (points[i] == null) - continue; - drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth); - } - } - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - // FIXME: figure out a way to add shadows (for instance along the right edge) - ctx.lineWidth = series.bars.lineWidth; - ctx.strokeStyle = series.color; - var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; - var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null; - plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis); - ctx.restore(); - } - - function getFillStyle(filloptions, seriesColor, bottom, top) { - var fill = filloptions.fill; - if (!fill) - return null; - - if (filloptions.fillColor) - return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor); - - var c = $.color.parse(seriesColor); - c.a = typeof fill == "number" ? fill : 0.4; - c.normalize(); - return c.toString(); - } - - function insertLegend() { - placeholder.find(".legend").remove(); - - if (!options.legend.show) - return; - - var fragments = [], rowStarted = false, - lf = options.legend.labelFormatter, s, label; - for (var i = 0; i < series.length; ++i) { - s = series[i]; - label = s.label; - if (!label) - continue; - - if (i % options.legend.noColumns == 0) { - if (rowStarted) - fragments.push(''); - fragments.push(''); - rowStarted = true; - } - - if (lf) - label = lf(label, s); - - fragments.push( - '
' + - '' + label + ''); - } - if (rowStarted) - fragments.push(''); - - if (fragments.length == 0) - return; - - var table = '' + fragments.join("") + '
'; - if (options.legend.container != null) - $(options.legend.container).html(table); - else { - var pos = "", - p = options.legend.position, - m = options.legend.margin; - if (m[0] == null) - m = [m, m]; - if (p.charAt(0) == "n") - pos += 'top:' + (m[1] + plotOffset.top) + 'px;'; - else if (p.charAt(0) == "s") - pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;'; - if (p.charAt(1) == "e") - pos += 'right:' + (m[0] + plotOffset.right) + 'px;'; - else if (p.charAt(1) == "w") - pos += 'left:' + (m[0] + plotOffset.left) + 'px;'; - var legend = $('
' + table.replace('style="', 'style="position:absolute;' + pos +';') + '
').appendTo(placeholder); - if (options.legend.backgroundOpacity != 0.0) { - // put in the transparent background - // separately to avoid blended labels and - // label boxes - var c = options.legend.backgroundColor; - if (c == null) { - c = options.grid.backgroundColor; - if (c && typeof c == "string") - c = $.color.parse(c); - else - c = $.color.extract(legend, 'background-color'); - c.a = 1; - c = c.toString(); - } - var div = legend.children(); - $('
').prependTo(legend).css('opacity', options.legend.backgroundOpacity); - } - } - } - - - // interactive features - - var highlights = [], - redrawTimeout = null; - - // returns the data item the mouse is over, or null if none is found - function findNearbyItem(mouseX, mouseY, seriesFilter) { - var maxDistance = options.grid.mouseActiveRadius, - smallestDistance = maxDistance * maxDistance + 1, - item = null, foundPoint = false, i, j; - - for (i = series.length - 1; i >= 0; --i) { - if (!seriesFilter(series[i])) - continue; - - var s = series[i], - axisx = s.xaxis, - axisy = s.yaxis, - points = s.datapoints.points, - ps = s.datapoints.pointsize, - mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster - my = axisy.c2p(mouseY), - maxx = maxDistance / axisx.scale, - maxy = maxDistance / axisy.scale; - - // with inverse transforms, we can't use the maxx/maxy - // optimization, sadly - if (axisx.options.inverseTransform) - maxx = Number.MAX_VALUE; - if (axisy.options.inverseTransform) - maxy = Number.MAX_VALUE; - - if (s.lines.show || s.points.show) { - for (j = 0; j < points.length; j += ps) { - var x = points[j], y = points[j + 1]; - if (x == null) - continue; - - // For points and lines, the cursor must be within a - // certain distance to the data point - if (x - mx > maxx || x - mx < -maxx || - y - my > maxy || y - my < -maxy) - continue; - - // We have to calculate distances in pixels, not in - // data units, because the scales of the axes may be different - var dx = Math.abs(axisx.p2c(x) - mouseX), - dy = Math.abs(axisy.p2c(y) - mouseY), - dist = dx * dx + dy * dy; // we save the sqrt - - // use <= to ensure last point takes precedence - // (last generally means on top of) - if (dist < smallestDistance) { - smallestDistance = dist; - item = [i, j / ps]; - } - } - } - - if (s.bars.show && !item) { // no other point can be nearby - var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2, - barRight = barLeft + s.bars.barWidth; - - for (j = 0; j < points.length; j += ps) { - var x = points[j], y = points[j + 1], b = points[j + 2]; - if (x == null) - continue; - - // for a bar graph, the cursor must be inside the bar - if (series[i].bars.horizontal ? - (mx <= Math.max(b, x) && mx >= Math.min(b, x) && - my >= y + barLeft && my <= y + barRight) : - (mx >= x + barLeft && mx <= x + barRight && - my >= Math.min(b, y) && my <= Math.max(b, y))) - item = [i, j / ps]; - } - } - } - - if (item) { - i = item[0]; - j = item[1]; - ps = series[i].datapoints.pointsize; - - return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps), - dataIndex: j, - series: series[i], - seriesIndex: i }; - } - - return null; - } - - function onMouseMove(e) { - if (options.grid.hoverable) - triggerClickHoverEvent("plothover", e, - function (s) { return s["hoverable"] != false; }); - } - - function onMouseLeave(e) { - if (options.grid.hoverable) - triggerClickHoverEvent("plothover", e, - function (s) { return false; }); - } - - function onClick(e) { - triggerClickHoverEvent("plotclick", e, - function (s) { return s["clickable"] != false; }); - } - - // trigger click or hover event (they send the same parameters - // so we share their code) - function triggerClickHoverEvent(eventname, event, seriesFilter) { - var offset = eventHolder.offset(), - canvasX = event.pageX - offset.left - plotOffset.left, - canvasY = event.pageY - offset.top - plotOffset.top, - pos = canvasToAxisCoords({ left: canvasX, top: canvasY }); - - pos.pageX = event.pageX; - pos.pageY = event.pageY; - - var item = findNearbyItem(canvasX, canvasY, seriesFilter); - - if (item) { - // fill in mouse pos for any listeners out there - item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left); - item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top); - } - - if (options.grid.autoHighlight) { - // clear auto-highlights - for (var i = 0; i < highlights.length; ++i) { - var h = highlights[i]; - if (h.auto == eventname && - !(item && h.series == item.series && - h.point[0] == item.datapoint[0] && - h.point[1] == item.datapoint[1])) - unhighlight(h.series, h.point); - } - - if (item) - highlight(item.series, item.datapoint, eventname); - } - - placeholder.trigger(eventname, [ pos, item ]); - } - - function triggerRedrawOverlay() { - if (!redrawTimeout) - redrawTimeout = setTimeout(drawOverlay, 30); - } - - function drawOverlay() { - redrawTimeout = null; - - // draw highlights - octx.save(); - octx.clearRect(0, 0, canvasWidth, canvasHeight); - octx.translate(plotOffset.left, plotOffset.top); - - var i, hi; - for (i = 0; i < highlights.length; ++i) { - hi = highlights[i]; - - if (hi.series.bars.show) - drawBarHighlight(hi.series, hi.point); - else - drawPointHighlight(hi.series, hi.point); - } - octx.restore(); - - executeHooks(hooks.drawOverlay, [octx]); - } - - function highlight(s, point, auto) { - if (typeof s == "number") - s = series[s]; - - if (typeof point == "number") { - var ps = s.datapoints.pointsize; - point = s.datapoints.points.slice(ps * point, ps * (point + 1)); - } - - var i = indexOfHighlight(s, point); - if (i == -1) { - highlights.push({ series: s, point: point, auto: auto }); - - triggerRedrawOverlay(); - } - else if (!auto) - highlights[i].auto = false; - } - - function unhighlight(s, point) { - if (s == null && point == null) { - highlights = []; - triggerRedrawOverlay(); - } - - if (typeof s == "number") - s = series[s]; - - if (typeof point == "number") - point = s.data[point]; - - var i = indexOfHighlight(s, point); - if (i != -1) { - highlights.splice(i, 1); - - triggerRedrawOverlay(); - } - } - - function indexOfHighlight(s, p) { - for (var i = 0; i < highlights.length; ++i) { - var h = highlights[i]; - if (h.series == s && h.point[0] == p[0] - && h.point[1] == p[1]) - return i; - } - return -1; - } - - function drawPointHighlight(series, point) { - var x = point[0], y = point[1], - axisx = series.xaxis, axisy = series.yaxis; - - if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) - return; - - var pointRadius = series.points.radius + series.points.lineWidth / 2; - octx.lineWidth = pointRadius; - octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString(); - var radius = 1.5 * pointRadius, - x = axisx.p2c(x), - y = axisy.p2c(y); - - octx.beginPath(); - if (series.points.symbol == "circle") - octx.arc(x, y, radius, 0, 2 * Math.PI, false); - else - series.points.symbol(octx, x, y, radius, false); - octx.closePath(); - octx.stroke(); - } - - function drawBarHighlight(series, point) { - octx.lineWidth = series.bars.lineWidth; - octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString(); - var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString(); - var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; - drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, - 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth); - } - - function getColorOrGradient(spec, bottom, top, defaultColor) { - if (typeof spec == "string") - return spec; - else { - // assume this is a gradient spec; IE currently only - // supports a simple vertical gradient properly, so that's - // what we support too - var gradient = ctx.createLinearGradient(0, top, 0, bottom); - - for (var i = 0, l = spec.colors.length; i < l; ++i) { - var c = spec.colors[i]; - if (typeof c != "string") { - var co = $.color.parse(defaultColor); - if (c.brightness != null) - co = co.scale('rgb', c.brightness) - if (c.opacity != null) - co.a *= c.opacity; - c = co.toString(); - } - gradient.addColorStop(i / (l - 1), c); - } - - return gradient; - } - } - } - - $.plot = function(placeholder, data, options) { - //var t0 = new Date(); - var plot = new Plot($(placeholder), data, options, $.plot.plugins); - //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime())); - return plot; - }; - - $.plot.version = "0.7"; - - $.plot.plugins = []; - - // returns a string with the date d formatted according to fmt - $.plot.formatDate = function(d, fmt, monthNames) { - var leftPad = function(n) { - n = "" + n; - return n.length == 1 ? "0" + n : n; - }; - - var r = []; - var escape = false, padNext = false; - var hours = d.getUTCHours(); - var isAM = hours < 12; - if (monthNames == null) - monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - - if (fmt.search(/%p|%P/) != -1) { - if (hours > 12) { - hours = hours - 12; - } else if (hours == 0) { - hours = 12; - } - } - for (var i = 0; i < fmt.length; ++i) { - var c = fmt.charAt(i); - - if (escape) { - switch (c) { - case 'h': c = "" + hours; break; - case 'H': c = leftPad(hours); break; - case 'M': c = leftPad(d.getUTCMinutes()); break; - case 'S': c = leftPad(d.getUTCSeconds()); break; - case 'd': c = "" + d.getUTCDate(); break; - case 'm': c = "" + (d.getUTCMonth() + 1); break; - case 'y': c = "" + d.getUTCFullYear(); break; - case 'b': c = "" + monthNames[d.getUTCMonth()]; break; - case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break; - case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break; - case '0': c = ""; padNext = true; break; - } - if (c && padNext) { - c = leftPad(c); - padNext = false; - } - r.push(c); - if (!padNext) - escape = false; - } - else { - if (c == "%") - escape = true; - else - r.push(c); - } - } - return r.join(""); - }; - - // round to nearby lower multiple of base - function floorInBase(n, base) { - return base * Math.floor(n / base); - } - -})(jQuery); diff --git a/pkgs/plt-services/meta/drdr/static/jquery.flot.selection.js b/pkgs/plt-services/meta/drdr/static/jquery.flot.selection.js deleted file mode 100644 index 7f7b32694b..0000000000 --- a/pkgs/plt-services/meta/drdr/static/jquery.flot.selection.js +++ /dev/null @@ -1,344 +0,0 @@ -/* -Flot plugin for selecting regions. - -The plugin defines the following options: - - selection: { - mode: null or "x" or "y" or "xy", - color: color - } - -Selection support is enabled by setting the mode to one of "x", "y" or -"xy". In "x" mode, the user will only be able to specify the x range, -similarly for "y" mode. For "xy", the selection becomes a rectangle -where both ranges can be specified. "color" is color of the selection -(if you need to change the color later on, you can get to it with -plot.getOptions().selection.color). - -When selection support is enabled, a "plotselected" event will be -emitted on the DOM element you passed into the plot function. The -event handler gets a parameter with the ranges selected on the axes, -like this: - - placeholder.bind("plotselected", function(event, ranges) { - alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to) - // similar for yaxis - with multiple axes, the extra ones are in - // x2axis, x3axis, ... - }); - -The "plotselected" event is only fired when the user has finished -making the selection. A "plotselecting" event is fired during the -process with the same parameters as the "plotselected" event, in case -you want to know what's happening while it's happening, - -A "plotunselected" event with no arguments is emitted when the user -clicks the mouse to remove the selection. - -The plugin allso adds the following methods to the plot object: - -- setSelection(ranges, preventEvent) - - Set the selection rectangle. The passed in ranges is on the same - form as returned in the "plotselected" event. If the selection mode - is "x", you should put in either an xaxis range, if the mode is "y" - you need to put in an yaxis range and both xaxis and yaxis if the - selection mode is "xy", like this: - - setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } }); - - setSelection will trigger the "plotselected" event when called. If - you don't want that to happen, e.g. if you're inside a - "plotselected" handler, pass true as the second parameter. If you - are using multiple axes, you can specify the ranges on any of those, - e.g. as x2axis/x3axis/... instead of xaxis, the plugin picks the - first one it sees. - -- clearSelection(preventEvent) - - Clear the selection rectangle. Pass in true to avoid getting a - "plotunselected" event. - -- getSelection() - - Returns the current selection in the same format as the - "plotselected" event. If there's currently no selection, the - function returns null. - -*/ - -(function ($) { - function init(plot) { - var selection = { - first: { x: -1, y: -1}, second: { x: -1, y: -1}, - show: false, - active: false - }; - - // FIXME: The drag handling implemented here should be - // abstracted out, there's some similar code from a library in - // the navigation plugin, this should be massaged a bit to fit - // the Flot cases here better and reused. Doing this would - // make this plugin much slimmer. - var savedhandlers = {}; - - var mouseUpHandler = null; - - function onMouseMove(e) { - if (selection.active) { - updateSelection(e); - - plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]); - } - } - - function onMouseDown(e) { - if (e.which != 1) // only accept left-click - return; - - // cancel out any text selections - document.body.focus(); - - // prevent text selection and drag in old-school browsers - if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) { - savedhandlers.onselectstart = document.onselectstart; - document.onselectstart = function () { return false; }; - } - if (document.ondrag !== undefined && savedhandlers.ondrag == null) { - savedhandlers.ondrag = document.ondrag; - document.ondrag = function () { return false; }; - } - - setSelectionPos(selection.first, e); - - selection.active = true; - - // this is a bit silly, but we have to use a closure to be - // able to whack the same handler again - mouseUpHandler = function (e) { onMouseUp(e); }; - - $(document).one("mouseup", mouseUpHandler); - } - - function onMouseUp(e) { - mouseUpHandler = null; - - // revert drag stuff for old-school browsers - if (document.onselectstart !== undefined) - document.onselectstart = savedhandlers.onselectstart; - if (document.ondrag !== undefined) - document.ondrag = savedhandlers.ondrag; - - // no more dragging - selection.active = false; - updateSelection(e); - - if (selectionIsSane()) - triggerSelectedEvent(); - else { - // this counts as a clear - plot.getPlaceholder().trigger("plotunselected", [ ]); - plot.getPlaceholder().trigger("plotselecting", [ null ]); - } - - return false; - } - - function getSelection() { - if (!selectionIsSane()) - return null; - - var r = {}, c1 = selection.first, c2 = selection.second; - $.each(plot.getAxes(), function (name, axis) { - if (axis.used) { - var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]); - r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) }; - } - }); - return r; - } - - function triggerSelectedEvent() { - var r = getSelection(); - - plot.getPlaceholder().trigger("plotselected", [ r ]); - - // backwards-compat stuff, to be removed in future - if (r.xaxis && r.yaxis) - plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]); - } - - function clamp(min, value, max) { - return value < min ? min: (value > max ? max: value); - } - - function setSelectionPos(pos, e) { - var o = plot.getOptions(); - var offset = plot.getPlaceholder().offset(); - var plotOffset = plot.getPlotOffset(); - pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width()); - pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height()); - - if (o.selection.mode == "y") - pos.x = pos == selection.first ? 0 : plot.width(); - - if (o.selection.mode == "x") - pos.y = pos == selection.first ? 0 : plot.height(); - } - - function updateSelection(pos) { - if (pos.pageX == null) - return; - - setSelectionPos(selection.second, pos); - if (selectionIsSane()) { - selection.show = true; - plot.triggerRedrawOverlay(); - } - else - clearSelection(true); - } - - function clearSelection(preventEvent) { - if (selection.show) { - selection.show = false; - plot.triggerRedrawOverlay(); - if (!preventEvent) - plot.getPlaceholder().trigger("plotunselected", [ ]); - } - } - - // function taken from markings support in Flot - function extractRange(ranges, coord) { - var axis, from, to, key, axes = plot.getAxes(); - - for (var k in axes) { - axis = axes[k]; - if (axis.direction == coord) { - key = coord + axis.n + "axis"; - if (!ranges[key] && axis.n == 1) - key = coord + "axis"; // support x1axis as xaxis - if (ranges[key]) { - from = ranges[key].from; - to = ranges[key].to; - break; - } - } - } - - // backwards-compat stuff - to be removed in future - if (!ranges[key]) { - axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0]; - from = ranges[coord + "1"]; - to = ranges[coord + "2"]; - } - - // auto-reverse as an added bonus - if (from != null && to != null && from > to) { - var tmp = from; - from = to; - to = tmp; - } - - return { from: from, to: to, axis: axis }; - } - - function setSelection(ranges, preventEvent) { - var axis, range, o = plot.getOptions(); - - if (o.selection.mode == "y") { - selection.first.x = 0; - selection.second.x = plot.width(); - } - else { - range = extractRange(ranges, "x"); - - selection.first.x = range.axis.p2c(range.from); - selection.second.x = range.axis.p2c(range.to); - } - - if (o.selection.mode == "x") { - selection.first.y = 0; - selection.second.y = plot.height(); - } - else { - range = extractRange(ranges, "y"); - - selection.first.y = range.axis.p2c(range.from); - selection.second.y = range.axis.p2c(range.to); - } - - selection.show = true; - plot.triggerRedrawOverlay(); - if (!preventEvent && selectionIsSane()) - triggerSelectedEvent(); - } - - function selectionIsSane() { - var minSize = 5; - return Math.abs(selection.second.x - selection.first.x) >= minSize && - Math.abs(selection.second.y - selection.first.y) >= minSize; - } - - plot.clearSelection = clearSelection; - plot.setSelection = setSelection; - plot.getSelection = getSelection; - - plot.hooks.bindEvents.push(function(plot, eventHolder) { - var o = plot.getOptions(); - if (o.selection.mode != null) { - eventHolder.mousemove(onMouseMove); - eventHolder.mousedown(onMouseDown); - } - }); - - - plot.hooks.drawOverlay.push(function (plot, ctx) { - // draw selection - if (selection.show && selectionIsSane()) { - var plotOffset = plot.getPlotOffset(); - var o = plot.getOptions(); - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - var c = $.color.parse(o.selection.color); - - ctx.strokeStyle = c.scale('a', 0.8).toString(); - ctx.lineWidth = 1; - ctx.lineJoin = "round"; - ctx.fillStyle = c.scale('a', 0.4).toString(); - - var x = Math.min(selection.first.x, selection.second.x), - y = Math.min(selection.first.y, selection.second.y), - w = Math.abs(selection.second.x - selection.first.x), - h = Math.abs(selection.second.y - selection.first.y); - - ctx.fillRect(x, y, w, h); - ctx.strokeRect(x, y, w, h); - - ctx.restore(); - } - }); - - plot.hooks.shutdown.push(function (plot, eventHolder) { - eventHolder.unbind("mousemove", onMouseMove); - eventHolder.unbind("mousedown", onMouseDown); - - if (mouseUpHandler) - $(document).unbind("mouseup", mouseUpHandler); - }); - - } - - $.plot.plugins.push({ - init: init, - options: { - selection: { - mode: null, // one of null, "x", "y" or "xy" - color: "#e8cfac" - } - }, - name: 'selection', - version: '1.1' - }); -})(jQuery); diff --git a/pkgs/plt-services/meta/drdr/static/render.css b/pkgs/plt-services/meta/drdr/static/render.css deleted file mode 100644 index dc8f389fce..0000000000 --- a/pkgs/plt-services/meta/drdr/static/render.css +++ /dev/null @@ -1,292 +0,0 @@ -html { - overflow-y: scroll; -} - -a img { - border: 0; -} - -body { - color: black; - background-color: white; - font-family: Optima, Arial, Verdana, Helvetica, sans-serif; - margin: 0px; - padding: 0px; -} - -.content { - margin-left: auto; - margin-right: auto; - width: 50em; -} - -#footer { - text-align: right; - width: 50em; - background: #F5F5DC; - margin-top: 2em; -} - -.help h1 { - background: #F5F5DC; - font-size: 130%; - width: 100%; -} - -.stderr { - color: red; -} -.stdout { - color: black; -} -.difference,.unprintable { - background: #00ffc8; -} - -.breadcrumb { - padding-left: 1em; - padding-right: 1em; - background: #FFCC66; - font-size: 120%; - font-weight: bold; -} - -.breadcrumb a.parent { - color: black; - text-decoration: none; - font-weight: normal; -} - -.breadcrumb a.parent:hover { - color: blue; - text-decoration: underline; -} - -div.error { - margin-top: 1em; - background-color: rgba(100%,0%,0%,0.5); - border: 1px solid black; - padding: 1em; -} - -span.revnav { - margin-left: 1em; - margin-right: 1em; - padding-left: 1em; - padding-right: 1em; - background: #FFCC66; - font-size: 120%; - font-weight: bold; -} - -span.revnav a { - margin-right: 5px; - color: black; - text-decoration: none; - font-weight: normal; -} - -span.revnav a:hover { - color: blue; - text-decoration: underline; -} - -span.filepath { - font-family: monospace; -} - -table.data { - margin-top: 1em; - width: 100%; - background-color: rgb(90%,90%,90%); - border: 1px solid black; - padding: 1em; -} - -table.data > tbody > tr > td:nth-child(1) > a { - color: black; - text-decoration: none; -} - -table.data > tbody > tr > td:nth-child(1) > a:hover { - color: blue; - text-decoration: underline; -} - -table.data > tbody > tr > td:nth-child(1) { - font-weight: bold; - width: 15%; - text-align: right; - vertical-align: top; - padding-right: 1em; -} - -pre { - overflow-x: auto; /* Use horizontal scroller if needed; for Firefox 2, not needed in Firefox 3 */ - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - /* width: 99%; */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ -} - -div.status { - margin-top: 1em; - background-color: rgb(90%,90%,90%); - border: 1px solid black; - padding: 1em; -} - -div.status ul { - list-style-type: none; -} - -div.status a { - color: black; - text-decoration: none; - font-weight: normal; -} - -div.status a:hover { - color: blue; - text-decoration: underline; -} - -.status .tag { - float: right; - color: rgb(50%,50%,50%); - font-size: 200%; - margin-top: -0.5em; - padding-top: 0px; -} - -.commandline { - font-family: monospace; - white-space: pre-wrap; -} -.commandline:before { content: "'"; } -.commandline:after { content: "'"; } - -tr.changes table tr td:nth-child(1) { - text-align: left; - padding-right: 0.5em; -} - -table.dirlist { - margin-top: 1em; - background-color: #F5F5DC; - width: 100%; -} - -p.output { - font-family: monospace; -} - -div.output { - margin-top: 1em; - background-color: #F5F5DC; - font-family: monospace; - width: 100%; - padding: 0.5em; - border: 1px solid black; -} - -div.output p { - margin: 0.5em; -} - -.dirlist thead tr td:nth-child(n+2) { - text-align: center; -} -.dirlist tbody tr td:nth-child(2) { - text-align: right; -} -.dirlist tbody tr td:nth-child(3) { - text-align: right; -} -.dirlist tbody tr td:nth-child(n+4) { - text-align: center; -} -.dirlist tfoot tr td:nth-child(2) { - text-align: right; -} -.dirlist tfoot tr td:nth-child(3) { - text-align: right; -} -.dirlist tfoot tr td:nth-child(n+4) { - text-align: center; -} - -.dirlist tbody tr td.building { - text-align: center; -} - -.dirlist tbody tr td.author { - text-align: center; -} - -.dir, .file { - cursor: pointer; - font-family: Courier New, Courier, monospace; -} - -.dir { - margin: 3px; - padding: 3px; - margin-left: 3em; - background: rgb(90%,90%,90%); -} - -.dir a { - text-decoration: none; - color: black; - font-weight: bold; -} - -.dir:hover { - margin: 3px; - padding: 3px; - margin-left: 3em; - background: rgb(100%,100%,80%); - /* border: 1px black solid; */ -} - -.branch-refs-heads-release { - background: rgb(90%,70%,90%); -} -.branch-refs-heads-release:hover { - background: rgb(100%,80%,100%); -} - -.file { - margin: 3px; - padding: 3px; - margin-left: 3em; - background: rgb(95%,95%,95%); -} - -.file a { - text-decoration: none; - color: black; -} - -.file:hover { - margin: 3px; - padding: 3px; - margin-left: 3em; - background: rgb(100%,100%,90%); -} - -div.timing img { - border: 0px; - width: 100%; -} -div.timing { - margin-top: 2em; - width: 50em; -} - -table.diff tr.difference td { - width: 48%; -} diff --git a/pkgs/plt-services/meta/drdr/static/robots.txt b/pkgs/plt-services/meta/drdr/static/robots.txt deleted file mode 100644 index 1a3761aa8b..0000000000 --- a/pkgs/plt-services/meta/drdr/static/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# go away -User-agent: * -Disallow: / diff --git a/pkgs/plt-services/meta/drdr/static/sorttable.js b/pkgs/plt-services/meta/drdr/static/sorttable.js deleted file mode 100644 index ec537e9ecf..0000000000 --- a/pkgs/plt-services/meta/drdr/static/sorttable.js +++ /dev/null @@ -1,502 +0,0 @@ -function TocviewToggle(glyphid, id) { - var glyph = document.getElementById(glyphid); - var s = document.getElementById(id).style; - var expand = s.display == "none"; - s.display = expand ? "block" : "none"; - glyph.innerHTML = expand ? "▼" : "►"; -} - -/* - SortTable - version 2 - 7th April 2007 - Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ - - Instructions: - Download this file - Add to your HTML - Add class="sortable" to any table you'd like to make sortable - Click on the headers to sort - - Thanks to many, many people for contributions and suggestions. - Licenced as X11: http://www.kryogenix.org/code/browser/licence.html - This basically means: do what you want with it. -*/ - - -var stIsIE = /*@cc_on!@*/false; - -sorttable = { - init: function() { - // quit if this function has already been called - if (arguments.callee.done) return; - // flag this function so we don't do the same thing twice - arguments.callee.done = true; - // kill the timer - if (_timer) clearInterval(_timer); - - if (!document.createElement || !document.getElementsByTagName) return; - - sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; - - forEach(document.getElementsByTagName('table'), function(table) { - if (table.className.search(/\bsortable\b/) != -1) { - sorttable.makeSortable(table); - } - }); - - }, - - makeSortable: function(table) { - if (table.getElementsByTagName('thead').length == 0) { - // table doesn't have a tHead. Since it should have, create one and - // put the first table row in it. - the = document.createElement('thead'); - the.appendChild(table.rows[0]); - table.insertBefore(the,table.firstChild); - } - // Safari doesn't support table.tHead, sigh - if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; - - if (table.tHead.rows.length != 1) return; // can't cope with two header rows - - // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as - // "total" rows, for example). This is B&R, since what you're supposed - // to do is put them in a tfoot. So, if there are sortbottom rows, - // for backwards compatibility, move them to tfoot (creating it if needed). - sortbottomrows = []; - for (var i=0; i5' : ' ▴'; - this.appendChild(sortrevind); - return; - } - if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { - // if we're already sorted by this column in reverse, just - // re-reverse the table, which is quicker - sorttable.reverse(this.sorttable_tbody); - this.className = this.className.replace('sorttable_sorted_reverse', - 'sorttable_sorted'); - this.removeChild(document.getElementById('sorttable_sortrevind')); - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; - this.appendChild(sortfwdind); - return; - } - - // remove sorttable_sorted classes - theadrow = this.parentNode; - forEach(theadrow.childNodes, function(cell) { - if (cell.nodeType == 1) { // an element - cell.className = cell.className.replace('sorttable_sorted_reverse',''); - cell.className = cell.className.replace('sorttable_sorted',''); - } - }); - sortfwdind = document.getElementById('sorttable_sortfwdind'); - if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } - sortrevind = document.getElementById('sorttable_sortrevind'); - if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } - - this.className += ' sorttable_sorted'; - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; - this.appendChild(sortfwdind); - - // build an array to sort. This is a Schwartzian transform thing, - // i.e., we "decorate" each row with the actual sort key, - // sort based on the sort keys, and then put the rows back in order - // which is a lot faster because you only do getInnerText once per row - row_array = []; - col = this.sorttable_columnindex; - rows = this.sorttable_tbody.rows; - for (var j=0; j 12) { - // definitely dd/mm - return sorttable.sort_ddmm; - } else if (second > 12) { - return sorttable.sort_mmdd; - } else { - // looks like a date, but we can't tell which, so assume - // that it's dd/mm (English imperialism!) and keep looking - sortfn = sorttable.sort_ddmm; - } - } - } - } - return sortfn; - }, - - getInnerText: function(node) { - // gets the text we want to use for sorting for a cell. - // strips leading and trailing whitespace. - // this is *not* a generic getInnerText function; it's special to sorttable. - // for example, you can override the cell text with a customkey attribute. - // it also gets .value for fields. - - hasInputs = (typeof node.getElementsByTagName == 'function') && - node.getElementsByTagName('input').length; - - if (node.getAttribute("sorttable_customkey") != null) { - return node.getAttribute("sorttable_customkey"); - } - else if (typeof node.textContent != 'undefined' && !hasInputs) { - return node.textContent.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.innerText != 'undefined' && !hasInputs) { - return node.innerText.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.text != 'undefined' && !hasInputs) { - return node.text.replace(/^\s+|\s+$/g, ''); - } - else { - switch (node.nodeType) { - case 3: - if (node.nodeName.toLowerCase() == 'input') { - return node.value.replace(/^\s+|\s+$/g, ''); - } - case 4: - return node.nodeValue.replace(/^\s+|\s+$/g, ''); - break; - case 1: - case 11: - var innerText = ''; - for (var i = 0; i < node.childNodes.length; i++) { - innerText += sorttable.getInnerText(node.childNodes[i]); - } - return innerText.replace(/^\s+|\s+$/g, ''); - break; - default: - return ''; - } - } - }, - - reverse: function(tbody) { - // reverse the rows in a tbody - newrows = []; - for (var i=0; i=0; i--) { - tbody.appendChild(newrows[i]); - } - delete newrows; - }, - - /* sort functions - each sort function takes two parameters, a and b - you are comparing a[0] and b[0] */ - sort_numeric: function(a,b) { - aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); - if (isNaN(aa)) aa = 0; - bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); - if (isNaN(bb)) bb = 0; - return aa-bb; - }, - sort_alpha: function(a,b) { - if (a[0]==b[0]) return 0; - if (a[0] 0 ) { - var q = list[i]; list[i] = list[i+1]; list[i+1] = q; - swap = true; - } - } // for - t--; - - if (!swap) break; - - for(var i = t; i > b; --i) { - if ( comp_func(list[i], list[i-1]) < 0 ) { - var q = list[i]; list[i] = list[i-1]; list[i-1] = q; - swap = true; - } - } // for - b++; - - } // while(swap) - } -} - -/* ****************************************************************** - Supporting functions: bundled here to avoid depending on a library - ****************************************************************** */ - -// Dean Edwards/Matthias Miller/John Resig - -/* for Mozilla/Opera9 */ -if (document.addEventListener) { - document.addEventListener("DOMContentLoaded", sorttable.init, false); -} - -/* for Internet Explorer */ -/*@cc_on @*/ -/*@if (@_win32) - document.write("