diff --git a/Dockerfile.moth b/Dockerfile.moth index 84330fa..23a16da 100644 --- a/Dockerfile.moth +++ b/Dockerfile.moth @@ -1,4 +1,4 @@ -FROM alpine AS builder +FROM alpine:3.8 AS builder RUN apk --no-cache add go libc-dev COPY src /src RUN go build -o /mothd /src/*.go diff --git a/Dockerfile.moth-devel b/Dockerfile.moth-devel index f6364e2..9a563dc 100644 --- a/Dockerfile.moth-devel +++ b/Dockerfile.moth-devel @@ -1,4 +1,4 @@ -FROM alpine:3.7 +FROM alpine:3.8 RUN apk --no-cache add \ gcc \ @@ -6,11 +6,12 @@ RUN apk --no-cache add \ python3 \ python3-dev \ py3-pillow \ - && \ - pip3 install aiohttp + && pip3 install aiohttp -COPY . /moth/ +COPY devel /app/ COPY example-puzzles /puzzles/ +COPY theme /theme/ WORKDIR /moth/ -ENTRYPOINT ["python3", "/moth/devel/devel-server.py", "--bind", ":8080", "--puzzles", "/puzzles"] +ENTRYPOINT [ "python3", "/app/devel-server.py" ] +CMD [ "--bind", "0.0.0.0:8080", "--puzzles", "/puzzles", "--theme", "/theme" ] diff --git a/README.md b/README.md index 2d73d75..f47399c 100644 --- a/README.md +++ b/README.md @@ -36,14 +36,14 @@ Click the `[mb]` link by a puzzle category to compile and download a mothball th Running a Production Server =========================== - docker run --rm -it -p 8080:8080 -v /path/to/moth:/moth dirtbags/moth + docker run --rm -it -p 8080:8080 -v /path/to/moth/state:/state -v /path/to/moth/balls:/mothballs:ro dirtbags/moth You can be more fine-grained about directories, if you like. Inside the container, you need the following paths: -* `/moth/state` (rw) Where state is stored. Read [the overview](docs/overview.md) to learn what's what in here. -* `/moth/mothballs` (ro) Mothballs (puzzle bundles) as provided by the development server. -* `/moth/resources` (ro) Overrides for built-in HTML/CSS resources. +* `/state` (rw) Where state is stored. Read [the overview](docs/overview.md) to learn what's what in here. +* `/mothballs` (ro) Mothballs (puzzle bundles) as provided by the development server. +* `/resources` (ro) Overrides for built-in HTML/CSS resources. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..c3c565f --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +3.0-rc4 diff --git a/build.sh b/build.sh index 6b32568..ac8d438 100755 --- a/build.sh +++ b/build.sh @@ -2,11 +2,13 @@ set -e -version=$(date +%Y%m%d%H%M) +read version < VERSION cd $(dirname $0) for img in moth moth-devel; do echo "==== $img" sudo docker build --build-arg http_proxy=$http_proxy --build-arg https_proxy=$https_proxy --tag dirtbags/$img --tag dirtbags/$img:$version -f Dockerfile.$img . - [ "$1" = "-push" ] && docker push dirtbags/$img:$version && docker push dirtbags/$img + [ "$1" = "-push" ] && docker push dirtbags/$img:$version && docker push dirtbags/$img:latest done + +exit 0 diff --git a/devel/devel-server.py b/devel/devel-server.py index 4db0b4a..af0679b 100755 --- a/devel/devel-server.py +++ b/devel/devel-server.py @@ -2,10 +2,10 @@ import asyncio import cgitb -import glob import html from aiohttp import web import io +import json import mimetypes import moth import logging @@ -20,158 +20,80 @@ import mothballer sys.dont_write_bytecode = True # Don't write .pyc files -def mkseed(): - return bytes(random.choice(b'abcdef0123456789') for i in range(40)).decode('ascii') -class Page: - def __init__(self, title, depth=0): - self.title = title - if depth: - self.base = "/".join([".."] * depth) - else: - self.base = "." - self.body = io.StringIO() - self.scripts = [] - - def add_script(self, path): - self.scripts.append(path) - - def write(self, s): - self.body.write(s) - - def text(self): - ret = io.StringIO() - ret.write("\n") - ret.write("\n") - ret.write(" \n") - ret.write(" {}\n".format(self.title)) - ret.write(" \n".format(self.base)) - for s in self.scripts: - ret.write(" {}\n".format(s)) - ret.write(" \n") - ret.write(" \n") - ret.write("

{}

\n".format(self.title)) - ret.write("
\n") - ret.write(self.body.getvalue()) - ret.write("
\n") - ret.write(" \n") - ret.write("\n") - return ret.getvalue() - - def response(self, request): - return web.Response(text=self.text(), content_type="text/html") +def get_seed(request): + seedstr = request.match_info.get("seed") + if seedstr == "random": + return random.getrandbits(32) + else: + return int(seedstr) -async def handle_front(request): - p = Page("Devel Server", 0) - p.write("

Yo, it's the front page!

") - p.write("") - p.write("

If you use this development server to run a contest, you are a fool.

") - return p.response(request) async def handle_puzzlelist(request): - seed = request.query.get("seed", mkseed()) - p = Page("Puzzle Categories", 1) - p.write("

seed = {}

".format(seed)) - p.write("
") - return p.response(request) + seed = get_seed(request) + puzzles = { + "__devel__": [[0, ""]], + } + for p in request.app["puzzles_dir"].glob("*"): + if not p.is_dir() or p.match(".*"): + continue + catName = p.parts[-1] + cat = moth.Category(p, seed) + puzzles[catName] = [[i, str(i)] for i in cat.pointvals()] + puzzles[catName].append([0, ""]) + if len(puzzles) <= 1: + logging.warning("No directories found matching {}/*".format(request.app["puzzles_dir"])) + return web.Response( + content_type="application/json", + body=json.dumps(puzzles), + ) -async def handle_category(request): - seed = request.query.get("seed", mkseed()) - category = request.match_info.get("category") - cat = moth.Category(os.path.join(request.app["puzzles_dir"], category), seed) - p = Page("Puzzles in category {}".format(category), 2) - p.write("") - return p.response(request) async def handle_puzzle(request): - seed = request.query.get("seed", mkseed()) + seed = get_seed(request) category = request.match_info.get("category") points = int(request.match_info.get("points")) - cat = moth.Category(os.path.join(request.app["puzzles_dir"], category), seed) + cat = moth.Category(request.app["puzzles_dir"].joinpath(category), seed) puzzle = cat.puzzle(points) - - p = Page("{} puzzle {}".format(category, points), 3) - for s in puzzle.scripts: - p.add_script(s) - p.write("

Body

") - p.write("
") - p.write(puzzle.html_body()) - p.write("
") - p.write("

Files

") - p.write("") - p.write("

Answers

") - p.write("

Input box (for scripts): ") - p.write("

") - p.write("

Authors

{}

".format(', '.join(puzzle.get_authors()))) - p.write("

Summary

{}

".format(puzzle.summary)) - if puzzle.logs: - p.write("

Debug Log

") - p.write('") - - return p.response(request) + + obj = puzzle.package() + obj["answers"] = puzzle.answers + obj["hint"] = puzzle.hint + obj["summary"] = puzzle.summary + obj["logs"] = puzzle.logs + + return web.Response( + content_type="application/json", + body=json.dumps(obj), + ) + async def handle_puzzlefile(request): - seed = request.query.get("seed", mkseed()).encode('ascii') + seed = get_seed(request) category = request.match_info.get("category") points = int(request.match_info.get("points")) filename = request.match_info.get("filename") - cat = moth.Category(os.path.join(request.app["puzzles_dir"], category), seed) + cat = moth.Category(request.app["puzzles_dir"].joinpath(category), seed) puzzle = cat.puzzle(points) try: file = puzzle.files[filename] except KeyError: return web.Response(status=404) - - resp = web.Response() - resp.content_type, _ = mimetypes.guess_type(file.name) - # This is the line where I decided Go was better than Python at multiprocessing - # You should be able to chain the puzzle file's output to the async output, - # without having to block. But if there's a way to do that, it certainly - # isn't documented anywhere. - resp.body = file.stream.read() - return resp + + content_type, _ = mimetypes.guess_type(file.name) + return web.Response( + body=file.stream.read(), # Is there no way to pipe this, must we slurp the whole thing into memory? + content_type=content_type, + ) + async def handle_mothballer(request): - seed = request.query.get("seed", mkseed()) + seed = get_seed(request) category = request.match_info.get("category") try: - catdir = os.path.join(request.app["puzzles_dir"], category) + catdir = request.app["puzzles_dir"].joinpath(category) mb = mothballer.package(category, catdir, seed) except: body = cgitb.html(sys.exc_info()) @@ -186,6 +108,47 @@ async def handle_mothballer(request): ) return resp + +async def handle_index(request): + seed = random.getrandbits(32) + body = """ + + Dev Server + +

Dev Server

+

+ You need to provide the contest seed in the URL. + If you don't have a contest seed in mind, + why not try {seed}? +

+

+ If you are chaotic, + you could even take your chances with a + random seed for every HTTP request. + This means generated files will get a different seed than the puzzle itself! +

+ + +""".format(seed=seed) + return web.Response( + content_type="text/html", + body=body, + ) + + +async def handle_static(request): + themes = request.app["theme_dir"] + fn = request.match_info.get("filename") + if not fn: + for fn in ("puzzle-list.html", "index.html"): + path = themes.joinpath(fn) + if path.exists(): + break + else: + path = themes.joinpath(fn) + return web.FileResponse(path) + + if __name__ == '__main__': import argparse @@ -194,6 +157,9 @@ if __name__ == '__main__': '--puzzles', default='puzzles', help="Directory containing your puzzles" ) + parser.add_argument( + '--theme', default='theme', + help="Directory containing theme files") parser.add_argument( '--bind', default="127.0.0.1:8080", help="Bind to ip:port" @@ -212,13 +178,13 @@ if __name__ == '__main__': mydir = os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0]))) app = web.Application() - app["puzzles_dir"] = args.puzzles app["base_url"] = args.base - app.router.add_route("GET", "/", handle_front) - app.router.add_route("GET", "/puzzles/", handle_puzzlelist) - app.router.add_route("GET", "/puzzles/{category}/", handle_category) - app.router.add_route("GET", "/puzzles/{category}/{points}/", handle_puzzle) - app.router.add_route("GET", "/puzzles/{category}/{points}/{filename}", handle_puzzlefile) - app.router.add_route("GET", "/mothballer/{category}", handle_mothballer) - app.router.add_static("/files/", mydir, show_index=True) + app["puzzles_dir"] = pathlib.Path(args.puzzles) + app["theme_dir"] = pathlib.Path(args.theme) + app.router.add_route("GET", "/", handle_index) + app.router.add_route("GET", "/{seed}/puzzles.json", handle_puzzlelist) + app.router.add_route("GET", "/{seed}/content/{category}/{points}/puzzle.json", handle_puzzle) + app.router.add_route("GET", "/{seed}/content/{category}/{points}/{filename}", handle_puzzlefile) + app.router.add_route("GET", "/{seed}/mothballer/{category}", handle_mothballer) + app.router.add_route("GET", "/{seed}/{filename:.*}", handle_static) web.run_app(app, host=addr, port=port) diff --git a/devel/moth.py b/devel/moth.py index bcd0e32..9820783 100644 --- a/devel/moth.py +++ b/devel/moth.py @@ -75,6 +75,7 @@ class Puzzle: self.authors = [] self.answers = [] self.scripts = [] + self.hint = None self.files = {} self.body = io.StringIO() self.logs = [] @@ -104,7 +105,7 @@ class Puzzle: elif key == 'answer': self.answers.append(val) elif key == 'hint': - pass + self.hint = val elif key == 'name': pass elif key == 'file': @@ -260,6 +261,18 @@ class Puzzle: def html_body(self): """Format and return the markdown for the puzzle body.""" return mistune.markdown(self.get_body(), escape=False) + + def package(self, answers=False): + """Return a dict packaging of the puzzle.""" + + files = [fn for fn,f in self.files.items() if f.visible] + return { + 'authors': self.authors, + 'hashes': self.hashes(), + 'files': files, + 'scripts': self.scripts, + 'body': self.html_body(), + } def hashes(self): "Return a list of answer hashes" diff --git a/devel/mothballer.py b/devel/mothballer.py index f0799b1..19bd46d 100755 --- a/devel/mothballer.py +++ b/devel/mothballer.py @@ -11,6 +11,7 @@ import os import shutil import tempfile import zipfile +import random SEEDFN = "SEED" @@ -37,62 +38,8 @@ def escape(s): return s.replace('&', '&').replace('<', '<').replace('>', '>') -def generate_html(ziphandle, puzzle, puzzledir, category, points, authors, files): - html_content = io.StringIO() - file_content = io.StringIO() - if files: - file_content.write( -'''
-

Associated files:

- -
-''') - scripts = [''.format(s) for s in puzzle.scripts] - - html_content.write( -''' - - - - - {category} {points} - - {scripts} - - -

{category} for {points} points

-
-{body}
-{file_content}
-
- - -
Team hash:
-
Answer:
- -
-
-
Puzzle by {authors}
- -'''.format( - category=category, - points=points, - body=puzzle.html_body(), - file_content=file_content.getvalue(), - authors=', '.join(authors), - scripts='\n'.join(scripts), - ) - ) - ziphandle.writestr(os.path.join(puzzledir, 'index.html'), html_content.getvalue()) - - def build_category(categorydir, outdir): - category_seed = binascii.b2a_hex(os.urandom(20)) + category_seed = random.getrandbits(32) categoryname = os.path.basename(categorydir.strip(os.sep)) zipfilename = os.path.join(outdir, "%s.mb" % categoryname) @@ -102,7 +49,7 @@ def build_category(categorydir, outdir): # open and gather some state existing = zipfile.ZipFile(zipfilename, 'r') try: - category_seed = existing.open(SEEDFN).read().strip() + category_seed = int(existing.open(SEEDFN).read().strip()) except Exception: pass existing.close() @@ -119,7 +66,7 @@ def build_category(categorydir, outdir): def package(categoryname, categorydir, seed): zfraw = io.BytesIO() zf = zipfile.ZipFile(zfraw, 'x') - zf.writestr("category_seed.txt", seed) + zf.writestr("category_seed.txt", str(seed)) cat = moth.Category(categorydir, seed) mapping = {} @@ -128,7 +75,7 @@ def package(categoryname, categorydir, seed): for puzzle in cat: logging.info("Processing point value {}".format(puzzle.points)) - hashmap = hashlib.sha1(seed.encode('utf-8')) + hashmap = hashlib.sha1(str(seed).encode('utf-8')) hashmap.update(str(puzzle.points).encode('utf-8')) puzzlehash = hashmap.hexdigest() @@ -136,23 +83,13 @@ def package(categoryname, categorydir, seed): answers[puzzle.points] = puzzle.answers summary[puzzle.points] = puzzle.summary - puzzledir = os.path.join('content', puzzlehash) - files = [] + puzzledir = os.path.join("content", puzzlehash) for fn, f in puzzle.files.items(): - if f.visible: - files.append(fn) payload = f.stream.read() zf.writestr(os.path.join(puzzledir, fn), payload) - puzzledict = { - 'authors': puzzle.authors, - 'hashes': puzzle.hashes(), - 'files': files, - 'body': puzzle.html_body(), - } - puzzlejson = json.dumps(puzzledict) - zf.writestr(os.path.join(puzzledir, 'puzzle.json'), puzzlejson) - generate_html(zf, puzzle, puzzledir, categoryname, puzzle.points, puzzle.get_authors(), files) + obj = puzzle.package() + zf.writestr(os.path.join(puzzledir, 'puzzle.json'), json.dumps(obj)) write_kv_pairs(zf, 'map.txt', mapping) write_kv_pairs(zf, 'answers.txt', answers) @@ -172,5 +109,7 @@ if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) + outdir = os.path.abspath(args.outdir) for categorydir in args.categorydirs: - build_category(categorydir, args.outdir) + categorydir = os.path.abspath(categorydir) + build_category(categorydir, outdir) diff --git a/docs/devel-server.md b/docs/devel-server.md index 7058596..bc05d3a 100644 --- a/docs/devel-server.md +++ b/docs/devel-server.md @@ -30,7 +30,7 @@ try this: apt install python3 git clone https://github.com/dirtbags/moth/ cd moth - ./devel-server.py --puzzles example-puzzles + python3 devel/devel-server.py --puzzles example-puzzles Installing New Puzzles diff --git a/docs/philosophy.md b/docs/philosophy.md new file mode 100644 index 0000000..5320580 --- /dev/null +++ b/docs/philosophy.md @@ -0,0 +1,32 @@ +Philosophy +========== + +This is just some scattered thoughts by the architect, Neale. + +People are going to try to break this thing. +It needs to be bulletproof. +This pretty much set the entire design: + +* As much as possible is done client-side + * Participants can attack their own web browsers as much as they feel like + * Also reduces server load + * We will help you create brute-force attacks! + * Your laptop is faster than our server + * We give you the carrot of hashed answers and the hashing function + * This removes one incentive to DoS the server +* Generate static content whenever possible + * Puzzles are statically compiled before the event even starts + * `points.json` and `puzzles.json` are generated and cached by a maintenance loop +* Minimize dynamic handling + * There are only two (2) dynamic handlers + * team registration + * answer validation + * You can disable team registration if you want, just remove `teamids.txt` + * I even removed token handling once I realized we replicate the user experience with the `answer` handler and some client-side JavaScript +* As much as possible is read-only + * The only rw directory is `state` +* Server code should be as tiny as possible + * Server should provide highly limited functionality + * It should be easy to remember in your head everything it does +* Server is also compiled + * Static type-checking helps assure no run-time errors diff --git a/src/handlers.go b/src/handlers.go index 5f4f524..3d3984b 100644 --- a/src/handlers.go +++ b/src/handlers.go @@ -75,6 +75,7 @@ func ShowHtml(w http.ResponseWriter, status Status, title string, body string) { } fmt.Fprintf(w, "") + fmt.Fprintf(w, "\n") fmt.Fprintf(w, "") fmt.Fprintf(w, "%s", title) fmt.Fprintf(w, "") @@ -173,70 +174,6 @@ func (ctx *Instance) registerHandler(w http.ResponseWriter, req *http.Request) { ) } -func (ctx *Instance) tokenHandler(w http.ResponseWriter, req *http.Request) { - teamid := req.FormValue("id") - token := req.FormValue("token") - - var category string - var points int - var fluff string - - stoken := strings.Replace(token, ":", " ", 2) - n, err := fmt.Sscanf(stoken, "%s %d %s", &category, &points, &fluff) - if err != nil || n != 3 { - respond( - w, req, Fail, - "Malformed token", - "That doesn't look like a token: %v.", err, - ) - return - } - - if (category == "") || (points <= 0) { - respond( - w, req, Fail, - "Weird token", - "That token doesn't make any sense.", - ) - return - } - - f, err := ctx.OpenCategoryFile(category, "tokens.txt") - if err != nil { - respond( - w, req, Fail, - "Cannot list valid tokens", - err.Error(), - ) - return - } - defer f.Close() - - // Make sure the token is in the list - if !hasLine(f, token) { - respond( - w, req, Fail, - "Unrecognized token", - "I don't recognize that token. Did you type in the whole thing?", - ) - return - } - - if err := ctx.AwardPoints(teamid, category, points); err != nil { - respond( - w, req, Fail, - "Error awarding points", - err.Error(), - ) - return - } - respond( - w, req, Success, - "Points awarded", - "%d points for %s!", points, teamid, - ) -} - func (ctx *Instance) answerHandler(w http.ResponseWriter, req *http.Request) { teamid := req.FormValue("id") category := req.FormValue("cat") @@ -367,7 +304,6 @@ func (ctx *Instance) staticHandler(w http.ResponseWriter, req *http.Request) { func (ctx *Instance) BindHandlers(mux *http.ServeMux) { mux.HandleFunc(ctx.Base+"/", ctx.staticHandler) mux.HandleFunc(ctx.Base+"/register", ctx.registerHandler) - mux.HandleFunc(ctx.Base+"/token", ctx.tokenHandler) mux.HandleFunc(ctx.Base+"/answer", ctx.answerHandler) mux.HandleFunc(ctx.Base+"/content/", ctx.contentHandler) mux.HandleFunc(ctx.Base+"/puzzles.json", ctx.puzzlesHandler) diff --git a/src/maintenance.go b/src/maintenance.go index 5f08fe6..136ba88 100644 --- a/src/maintenance.go +++ b/src/maintenance.go @@ -31,7 +31,7 @@ func (pm *PuzzleMap) MarshalJSON() ([]byte, error) { return []byte(ret), nil } -func (ctx *Instance) generatePuzzleList() error { +func (ctx *Instance) generatePuzzleList() { maxByCategory := map[string]int{} for _, a := range ctx.PointsLog() { if a.Points > maxByCategory[a.Category] { @@ -43,7 +43,8 @@ func (ctx *Instance) generatePuzzleList() error { for catName, mb := range ctx.Categories { mf, err := mb.Open("map.txt") if err != nil { - return err + // File isn't in there + continue } defer mf.Close() @@ -58,9 +59,11 @@ func (ctx *Instance) generatePuzzleList() error { n, err := fmt.Sscanf(line, "%d %s", &pointval, &dir) if err != nil { - return err + log.Printf("Parsing map for %s: %v", catName, err) + continue } else if n != 2 { - return fmt.Errorf("Parsing map for %s: short read", catName) + log.Printf("Parsing map for %s: short read", catName) + continue } pm = append(pm, PuzzleMap{pointval, dir}) @@ -78,13 +81,14 @@ func (ctx *Instance) generatePuzzleList() error { } jpl, err := json.Marshal(ret) - if err == nil { - ctx.jPuzzleList = jpl + if err != nil { + log.Printf("Marshalling puzzles.js: %v", err) + return } - return err + ctx.jPuzzleList = jpl } -func (ctx *Instance) generatePointsLog() error { +func (ctx *Instance) generatePointsLog() { var ret struct { Teams map[string]string `json:"teams"` Points []*Award `json:"points"` @@ -98,7 +102,7 @@ func (ctx *Instance) generatePointsLog() error { if !ok { teamName, err := ctx.TeamName(a.TeamId) if err != nil { - teamName = "[unregistered]" + teamName = "Rodney" // https://en.wikipedia.org/wiki/Rogue_(video_game)#Gameplay } teamNumber = nr teamNumbersById[a.TeamId] = teamNumber @@ -108,10 +112,11 @@ func (ctx *Instance) generatePointsLog() error { } jpl, err := json.Marshal(ret) - if err == nil { - ctx.jPointsLog = jpl + if err != nil { + log.Printf("Marshalling points.js: %v", err) + return } - return err + ctx.jPointsLog = jpl } // maintenance runs diff --git a/theme/basic.css b/theme/basic.css index 4e9bd88..2ee7b34 100644 --- a/theme/basic.css +++ b/theme/basic.css @@ -28,9 +28,10 @@ p { form, pre { margin: 1em; } -input { +input, select { padding: 0.6em; margin: 0.2em; + max-width: 30em; } nav { border: solid black 2px; @@ -77,3 +78,12 @@ img { .cat5, .cat13, .cat21 {background-color: #e31a1c; color: white;} .cat6, .cat14, .cat22 {background-color: #fdbf6f; color: black;} .cat7, .cat15, .cat23 {background-color: #ff7f00; color: black;} + + +#devel { + background-color: #c88; + color: black; +} +.kvpair { + border: solid black 2px; +} \ No newline at end of file diff --git a/theme/devel.js b/theme/devel.js new file mode 100644 index 0000000..6abe921 --- /dev/null +++ b/theme/devel.js @@ -0,0 +1,47 @@ +// Devel server addons + +// devel_addin drops a bunch of development extensions into element e. +// It will only modify stuff inside e. +function devel_addin(obj, e) { + let h = document.createElement("h2"); + e.appendChild(h); + h.textContent = "Development Options"; + + let g = document.createElement("p"); + e.appendChild(g); + g.innerText = "This section will not appear for participants." + + let keys = Object.keys(obj); + keys.sort(); + for (let key of keys) { + switch (key) { + case "body": + continue; + } + + let d = document.createElement("div"); + e.appendChild(d); + d.classList.add("kvpair"); + + let ktxt = document.createElement("span"); + d.appendChild(ktxt); + ktxt.textContent = key; + + let val = obj[key]; + if (Array.isArray(val)) { + let vi = document.createElement("select"); + d.appendChild(vi); + vi.multiple = true; + for (let a of val) { + let opt = document.createElement("option"); + vi.appendChild(opt); + opt.innerText = a; + } + } else { + let vi = document.createElement("input"); + d.appendChild(vi); + vi.value = val; + vi.disabled = true; + } + } +} \ No newline at end of file diff --git a/theme/index.html b/theme/index.html index 803cd7f..51ad704 100644 --- a/theme/index.html +++ b/theme/index.html @@ -4,8 +4,6 @@ Welcome -

Welcome

diff --git a/theme/points.json b/theme/points.json new file mode 100644 index 0000000..5440553 --- /dev/null +++ b/theme/points.json @@ -0,0 +1,9 @@ +{"__comment__": + " + This is some sample data from a Cyber Fire Puzzles event in 2018. + You don't need to include this file in any custom theme: + It's here to help debug scoreboard work. + The devel server will serve this up as static content; + MOTHd will ignore it. + ", +"teams":{"0":"PPP11","1":"Ashley King","103":"sparkles","10c":"OpsElite","11d":"ECU","11f":"hellokitty","127":"dirtbags","12f":"C","17c":"gouda","187":"student-d","19e":"Mit1306","1d0":"ssamson","1e":"Zen","1e0":"Moises Carrillo","1e2":"Cyber_Defender","1fb":"Carnivorous Robot","2":"NasarioS","20d":"Gnaneshwar","23":"CyberTia","24":"Cyberfighter","3":"csus2018","315":"TaterBots","344":"Starstruck Traveller","34e":"team202","35d":"Giga_mpact","38":"KTF","39":"#SINA","3f8":"cebcn","3f9":"WeAreGamers","410":"AWCTeam","42":"cyberfire","44e":"sam","4a":"rBurke","4d8":"Fiji","4e5":"Viet","5":"AART","517":"hazard.bay","52":"Prismriver","53":"Prajna","55":"Aggie1","577":"345keenan","5e":"App_U","64":"yau.marie","65":"cyberfight","673":"intel0pe","674":"ccat","6b":"Slackers đŸ¶","7":"hpu","73":"Haris","77":"tutuvous","81":"n0v","8d":"RemindMeMidtermOnMonday","9c":"Jest","a1":"pmcclanahan","a7":"Shadow03","ab":"TopTierMemeEngineer","af":"Tacere","b":"GREEN","b1":"Slackers 🐾","c":"SaengP","d0":"Penny1","d2":"Yashkumar Ukani","d5":"Unintended Consequences","d6":"JoelSwansonNYPD","da":"pmcclanahan","db":"worm","dd":"1","f9":"silversky"},"points":[[1538154043,"0","base",1],[1538154052,"1","base",1],[1538154090,"2","base",1],[1538154090,"3","base",1],[1538154118,"2","nocode",1],[1538154182,"5","nocode",1],[1538154199,"2","nocode",2],[1538154219,"7","base",1],[1538154243,"2","nocode",3],[1538154269,"3","base",2],[1538154274,"2","nocode",4],[1538154292,"b","base",1],[1538154318,"c","base",1],[1538154318,"b","nocode",1],[1538154329,"b","nocode",2],[1538154334,"2","nocode",10],[1538154348,"0","netarch",1],[1538154350,"5","nocode",3],[1538154355,"1","base",2],[1538154358,"0","nocode",1],[1538154362,"3","nocode",1],[1538154372,"0","nocode",2],[1538154386,"0","nocode",3],[1538154393,"b","nocode",4],[1538154395,"0","nocode",4],[1538154418,"b","nocode",10],[1538154428,"0","nocode",10],[1538154458,"7","netarch",1],[1538154498,"0","netarch",2],[1538154540,"7","netarch",2],[1538154581,"1e","base",1],[1538154632,"1","netarch",1],[1538154633,"2","netarch",1],[1538154694,"1e","base",2],[1538154754,"5","base",2],[1538154762,"23","base",1],[1538154796,"24","base",1],[1538154848,"23","nocode",1],[1538154857,"c","netarch",1],[1538154884,"23","nocode",2],[1538154886,"1e","netarch",1],[1538154908,"1","netarch",2],[1538154922,"1","nocode",1],[1538154927,"1e","netarch",2],[1538154933,"1","nocode",2],[1538154951,"1","nocode",3],[1538154962,"1","nocode",4],[1538154972,"5","nocode",2],[1538155005,"1","nocode",10],[1538155006,"7","base",2],[1538155016,"3","nocode",10],[1538155031,"5","nocode",4],[1538155059,"b","netarch",1],[1538155104,"7","nocode",1],[1538155132,"23","nocode",4],[1538155142,"7","nocode",2],[1538155149,"38","netarch",1],[1538155170,"39","base",1],[1538155219,"23","nocode",3],[1538155256,"38","netarch",2],[1538155281,"3","nocode",2],[1538155335,"1e","nocode",1],[1538155367,"7","nocode",4],[1538155384,"1e","nocode",2],[1538155429,"7","nocode",10],[1538155458,"1e","nocode",3],[1538155490,"42","base",1],[1538155509,"3","netarch",1],[1538155515,"1e","nocode",4],[1538155516,"38","nocode",10],[1538155551,"5","nocode",10],[1538155585,"39","netarch",1],[1538155600,"5","netarch",1],[1538155611,"39","nocode",1],[1538155615,"4a","nocode",1],[1538155626,"38","nocode",4],[1538155637,"4a","nocode",2],[1538155645,"38","nocode",3],[1538155650,"39","nocode",2],[1538155659,"38","nocode",2],[1538155661,"5","netarch",2],[1538155666,"38","nocode",1],[1538155687,"52","base",1],[1538155723,"53","netarch",1],[1538155745,"1e","nocode",10],[1538155779,"55","nocode",10],[1538155856,"55","base",1],[1538155893,"39","nocode",4],[1538155915,"3","nocode",4],[1538155916,"4a","nocode",3],[1538155934,"4a","nocode",4],[1538155978,"3","nocode",3],[1538155982,"4a","nocode",10],[1538156084,"52","base",2],[1538156161,"5e","base",1],[1538156229,"5e","nocode",1],[1538156261,"7","nocode",20],[1538156269,"4a","base",1],[1538156301,"5e","nocode",2],[1538156348,"7","nocode",3],[1538156537,"64","base",1],[1538156548,"65","base",1],[1538156608,"64","base",2],[1538156738,"39","nocode",10],[1538156823,"2","netarch",2],[1538157096,"3","netarch",2],[1538157358,"5e","nocode",3],[1538157404,"6b","base",1],[1538157417,"5e","nocode",4],[1538157422,"64","netarch",1],[1538157450,"5e","nocode",10],[1538157503,"64","netarch",2],[1538157587,"64","nocode",1],[1538157609,"64","nocode",2],[1538157684,"52","netarch",1],[1538157697,"73","base",1],[1538157700,"64","nocode",3],[1538157713,"64","nocode",4],[1538157792,"c","netarch",2],[1538157840,"77","base",1],[1538157886,"c","nocode",1],[1538157913,"c","nocode",2],[1538157926,"0","base",2],[1538157961,"6b","base",2],[1538157971,"c","nocode",3],[1538157989,"c","nocode",4],[1538158009,"38","base",1],[1538158082,"c","nocode",10],[1538158097,"0","base",3],[1538158118,"81","base",1],[1538158285,"0","base",4],[1538158354,"0","base",5],[1538158433,"0","base",6],[1538158470,"0","base",7],[1538158635,"6b","netarch",1],[1538158695,"3","base",4],[1538158715,"5","nocode",20],[1538158752,"6b","netarch",2],[1538158864,"3","nocode",20],[1538158874,"6b","nocode",1],[1538158890,"6b","nocode",2],[1538158939,"8d","base",1],[1538159105,"42","base",2],[1538159302,"42","nocode",2],[1538159579,"6b","nocode",3],[1538159714,"6b","nocode",4],[1538159801,"6b","nocode",10],[1538159920,"52","nocode",1],[1538159929,"52","nocode",2],[1538159987,"52","nocode",3],[1538159998,"52","nocode",4],[1538160019,"52","nocode",10],[1538160168,"8d","base",2],[1538160250,"8d","base",3],[1538160302,"8d","base",4],[1538160306,"4a","netarch",1],[1538160320,"9c","base",1],[1538160354,"8d","base",5],[1538160403,"8d","base",6],[1538160458,"8d","base",7],[1538160711,"52","base",4],[1538160886,"a1","netarch",1],[1538161028,"7","base",3],[1538161093,"5","base",1],[1538161171,"7","base",4],[1538161423,"7","base",5],[1538161534,"7","base",6],[1538161913,"a7","base",2],[1538161970,"3","base",5],[1538162163,"38","base",2],[1538162248,"55","base",2],[1538162423,"ab","base",1],[1538162486,"7","base",7],[1538162580,"ab","base",2],[1538162806,"73","nocode",1],[1538162926,"af","base",1],[1538162995,"3","base",6],[1538163002,"b1","base",1],[1538163024,"55","nocode",1],[1538163025,"b1","nocode",2],[1538163035,"1","base",3],[1538163036,"b1","nocode",3],[1538163054,"55","nocode",2],[1538163063,"b1","nocode",4],[1538163082,"b1","base",2],[1538163096,"b1","netarch",1],[1538163109,"b1","netarch",2],[1538163149,"b1","nocode",1],[1538163174,"55","netarch",1],[1538163179,"b1","nocode",10],[1538163275,"55","netarch",2],[1538163527,"a7","netarch",1],[1538163529,"3","base",7],[1538163553,"1","base",4],[1538163563,"55","nocode",3],[1538163629,"55","nocode",4],[1538163637,"a7","netarch",2],[1538163845,"55","nocode",20],[1538163865,"af","base",2],[1538163950,"a7","nocode",1],[1538164019,"a7","nocode",2],[1538164084,"7","base",8],[1538164125,"1","base",5],[1538164138,"5","nocode",30],[1538164213,"a7","nocode",3],[1538164246,"9c","base",2],[1538164246,"a7","nocode",4],[1538164311,"a7","nocode",10],[1538164593,"d0","base",1],[1538164674,"52","base",8],[1538164694,"d2","base",1],[1538164711,"d2","nocode",1],[1538164859,"d2","netarch",1],[1538165026,"d5","base",1],[1538165148,"d6","base",1],[1538165165,"52","nocode",20],[1538165199,"af","base",3],[1538165208,"73","base",2],[1538165212,"da","base",1],[1538165359,"db","base",1],[1538165387,"d6","base",2],[1538165394,"dd","base",1],[1538165398,"7","base",9],[1538165582,"dd","base",2],[1538165747,"db","base",2],[1538166077,"7","base",10],[1538166100,"3","base",3],[1538166106,"af","base",4],[1538166208,"d5","base",2],[1538166211,"8d","netarch",1],[1538166224,"d0","base",2],[1538166290,"af","base",5],[1538166328,"52","nocode",50],[1538166358,"af","base",6],[1538166495,"af","base",7],[1538166803,"7","nocode",50],[1538166910,"d0","base",10],[1538167306,"7","base",11],[1538167411,"8d","netarch",2],[1538167436,"d5","base",3],[1538167482,"55","nocode",80],[1538167511,"7","base",12],[1538167524,"d5","base",4],[1538167577,"d5","base",5],[1538167625,"d5","base",6],[1538167702,"55","nocode",90],[1538167807,"d5","base",7],[1538167974,"d0","netarch",1],[1538168034,"d0","netarch",2],[1538168066,"f9","nocode",1],[1538168086,"f9","nocode",2],[1538168101,"f9","nocode",3],[1538168111,"f9","nocode",4],[1538168226,"d6","base",3],[1538168238,"52","netarch",2],[1538168289,"f9","nocode",10],[1538168349,"d6","netarch",1],[1538168387,"af","base",9],[1538168469,"af","base",10],[1538168511,"103","netarch",1],[1538168538,"af","base",11],[1538168589,"d6","nocode",1],[1538168596,"5","nocode",90],[1538168635,"d6","nocode",2],[1538168664,"d6","nocode",3],[1538168683,"af","base",12],[1538168704,"d0","nocode",1],[1538168726,"d0","nocode",2],[1538168732,"10c","base",1],[1538168744,"d6","nocode",4],[1538168746,"d0","nocode",3],[1538168750,"af","base",13],[1538168768,"d0","nocode",4],[1538168841,"af","base",14],[1538168856,"d0","nocode",10],[1538168915,"af","base",15],[1538168936,"7","nocode",90],[1538168973,"af","base",16],[1538169126,"10c","base",2],[1538169149,"3","nocode",90],[1538169311,"af","netarch",1],[1538169499,"af","nocode",1],[1538169522,"af","nocode",2],[1538169543,"d6","nocode",90],[1538169651,"af","nocode",3],[1538169702,"11d","base",1],[1538169834,"d5","base",9],[1538169870,"11f","base",1],[1538169879,"d5","base",10],[1538169896,"9c","nocode",1],[1538169908,"11d","base",2],[1538169919,"d5","base",11],[1538169948,"9c","nocode",2],[1538169959,"d5","base",12],[1538169985,"af","nocode",4],[1538170018,"127","netarch",3],[1538170020,"d6","netarch",2],[1538170025,"d5","base",13],[1538170033,"af","nocode",10],[1538170043,"9c","nocode",4],[1538170069,"d5","base",14],[1538170110,"d5","base",15],[1538170111,"11f","base",2],[1538170117,"12f","base",1],[1538170182,"d5","base",16],[1538170223,"d5","base",17],[1538170325,"52","base",16],[1538170360,"3","netarch",4],[1538170361,"f9","netarch",1],[1538170435,"0","netarch",4],[1538170450,"2","base",2],[1538170515,"d5","netarch",1],[1538170770,"0","nocode",80],[1538170830,"0","base",9],[1538170880,"0","base",10],[1538170916,"0","base",11],[1538170929,"2","nocode",20],[1538170942,"103","nocode",1],[1538170964,"0","base",12],[1538170964,"103","nocode",2],[1538170995,"0","base",13],[1538170999,"103","nocode",3],[1538171026,"0","base",14],[1538171045,"103","nocode",4],[1538171055,"0","base",15],[1538171071,"103","nocode",10],[1538171085,"0","base",16],[1538171111,"0","base",17],[1538171136,"0","base",18],[1538171147,"103","nocode",20],[1538171165,"0","base",19],[1538171254,"0","base",20],[1538171276,"0","base",21],[1538171290,"12f","base",2],[1538171304,"0","base",22],[1538171328,"0","base",23],[1538171355,"0","base",24],[1538171380,"0","base",25],[1538171404,"0","base",26],[1538171430,"0","base",27],[1538171461,"0","base",28],[1538171484,"0","base",29],[1538171510,"0","base",30],[1538171541,"0","base",31],[1538171566,"7","netarch",4],[1538171614,"0","base",32],[1538171698,"12f","nocode",1],[1538172076,"0","base",33],[1538172186,"0","base",34],[1538172243,"0","base",35],[1538172258,"52","base",3],[1538172273,"0","base",36],[1538172308,"52","base",5],[1538172331,"52","base",6],[1538172354,"52","base",7],[1538172446,"52","base",9],[1538172468,"52","base",10],[1538172487,"52","base",11],[1538172507,"52","base",12],[1538172533,"52","base",13],[1538172545,"af","base",17],[1538172561,"12f","nocode",2],[1538172581,"52","base",14],[1538172603,"52","base",15],[1538172650,"12f","netarch",1],[1538172652,"52","base",17],[1538172672,"52","base",18],[1538172700,"52","base",19],[1538172710,"0","base",37],[1538172718,"52","base",20],[1538172735,"52","base",21],[1538172753,"52","base",22],[1538172771,"52","base",23],[1538172790,"52","base",24],[1538172806,"52","base",25],[1538172823,"52","base",26],[1538172840,"52","base",27],[1538172859,"52","base",28],[1538172867,"12f","nocode",3],[1538172878,"52","base",29],[1538172879,"17c","nocode",1],[1538172891,"17c","nocode",2],[1538172898,"52","base",30],[1538172917,"52","base",31],[1538172922,"12f","nocode",4],[1538172956,"17c","base",1],[1538172967,"12f","nocode",10],[1538172993,"17c","nocode",4],[1538173049,"52","nocode",90],[1538173049,"17c","nocode",10],[1538173116,"0","base",38],[1538173138,"187","base",1],[1538173167,"0","base",39],[1538173195,"0","base",40],[1538173306,"187","base",2],[1538173349,"103","nocode",90],[1538173393,"0","base",8],[1538173460,"12f","nocode",20],[1538173482,"d5","netarch",2],[1538173807,"0","base",41],[1538173831,"52","netarch",4],[1538173957,"0","base",42],[1538173976,"7","base",13],[1538173995,"0","base",43],[1538174032,"0","base",44],[1538174045,"7","base",14],[1538174079,"10c","netarch",1],[1538174089,"0","base",45],[1538174101,"7","base",15],[1538174127,"0","base",46],[1538174164,"0","base",47],[1538174197,"3","base",20],[1538174224,"7","base",16],[1538174247,"d5","nocode",1],[1538174253,"19e","base",1],[1538174264,"d5","nocode",2],[1538174327,"19e","netarch",1],[1538174343,"19e","nocode",1],[1538174350,"0","base",48],[1538174438,"0","base",49],[1538174459,"19e","nocode",2],[1538174499,"19e","nocode",10],[1538174556,"0","nocode",90],[1538174671,"11f","netarch",1],[1538174727,"7","base",32],[1538174737,"8d","base",9],[1538174756,"11f","netarch",2],[1538174757,"0","base",50],[1538174775,"8d","base",10],[1538174788,"db","nocode",1],[1538174800,"db","nocode",2],[1538174811,"8d","base",11],[1538174813,"11f","nocode",1],[1538174813,"db","nocode",3],[1538174826,"db","nocode",4],[1538174835,"11f","nocode",2],[1538174843,"8d","base",12],[1538174856,"11f","nocode",3],[1538174867,"11f","nocode",4],[1538174870,"db","nocode",10],[1538174875,"8d","base",13],[1538174893,"11f","nocode",10],[1538174907,"8d","base",14],[1538174940,"8d","base",15],[1538174987,"8d","base",16],[1538175021,"8d","base",17],[1538175040,"11f","nocode",90],[1538175055,"8d","base",18],[1538175121,"8d","base",28],[1538175137,"db","netarch",1],[1538175197,"8d","base",19],[1538175229,"8d","base",20],[1538175261,"8d","base",21],[1538175293,"8d","base",22],[1538175326,"8d","base",23],[1538175358,"8d","base",24],[1538175390,"8d","base",25],[1538175419,"8d","base",26],[1538175450,"8d","base",27],[1538175490,"8d","base",29],[1538175525,"8d","base",30],[1538175565,"8d","base",31],[1538175597,"db","netarch",2],[1538176001,"8d","netarch",4],[1538176052,"1d0","base",1],[1538176502,"db","netarch",4],[1538176516,"10c","netarch",2],[1538176523,"17c","nocode",3],[1538176639,"0","reverse",200],[1538176677,"1d0","nocode",1],[1538176694,"1d0","nocode",2],[1538176713,"38","nocode",90],[1538176715,"1d0","nocode",3],[1538176748,"1d0","nocode",4],[1538176768,"103","netarch",2],[1538176910,"1d0","nocode",10],[1538176982,"17c","nocode",20],[1538177189,"17c","nocode",90],[1538177408,"8d","netarch",5],[1538177507,"4a","base",2],[1538177526,"1e0","base",1],[1538177636,"1e0","nocode",1],[1538177789,"1e2","base",1],[1538177826,"0","netarch",5],[1538177879,"0","netarch",6],[1538178068,"0","netarch",7],[1538178085,"1e2","nocode",1],[1538178262,"8d","netarch",6],[1538178265,"10c","nocode",1],[1538178281,"10c","nocode",2],[1538178453,"10c","nocode",3],[1538178565,"10c","nocode",4],[1538178608,"10c","nocode",10],[1538178653,"64","nocode",10],[1538178837,"187","netarch",1],[1538178947,"103","netarch",7],[1538178964,"8d","netarch",7],[1538178968,"0","netarch",8],[1538179087,"0","netarch",10],[1538179177,"0","netarch",20],[1538179356,"64","base",16],[1538179376,"0","netarch",30],[1538179429,"7","netarch",10],[1538179455,"0","netarch",100],[1538179506,"0","netarch",200],[1538179581,"0","netarch",250],[1538179730,"0","netarch",300],[1538179738,"1fb","base",1],[1538179771,"187","netarch",2],[1538179848,"4a","nocode",90],[1538179915,"1fb","base",2],[1538180372,"4a","nocode",20],[1538180381,"8d","netarch",8],[1538180386,"b1","netarch",250],[1538180569,"81","base",2],[1538180674,"1fb","base",16],[1538180846,"64","base",3],[1538180864,"103","base",2],[1538181098,"1fb","base",32],[1538181237,"187","nocode",1],[1538181252,"8d","netarch",10],[1538181272,"187","nocode",2],[1538181272,"55","reverse",200],[1538181363,"8d","netarch",20],[1538181363,"187","nocode",3],[1538181380,"20d","base",1],[1538181422,"187","nocode",4],[1538181555,"20d","nocode",1],[1538181576,"17c","netarch",1],[1538182000,"3","nocode",50],[1538182028,"64","base",4],[1538182179,"81","nocode",1],[1538182199,"81","sequence",1],[1538182265,"4a","netarch",2],[1538182289,"3","sequence",1],[1538182324,"4a","network-fundamentals",1],[1538182328,"3","sequence",2],[1538182331,"81","network-fundamentals",1],[1538182358,"4a","sequence",1],[1538182360,"17c","sequence",1],[1538182361,"b1","nocode",90],[1538182374,"17c","sequence",2],[1538182378,"4a","sequence",2],[1538182382,"3","sequence",8],[1538182387,"7","sequence",1],[1538182403,"3","sequence",16],[1538182409,"81","network-fundamentals",10],[1538182410,"7","sequence",2],[1538182416,"4a","sequence",8],[1538182427,"81","network-fundamentals",11],[1538182434,"3","sequence",19],[1538182441,"81","network-fundamentals",12],[1538182443,"4a","sequence",16],[1538182444,"3","sequence",25],[1538182457,"4a","sequence",19],[1538182462,"3","sequence",35],[1538182467,"4a","sequence",25],[1538182482,"3","sequence",50],[1538182485,"4a","sequence",35],[1538182522,"81","network-fundamentals",13],[1538182560,"81","network-fundamentals",14],[1538182563,"17c","sequence",8],[1538182587,"5","sequence",1],[1538182627,"17c","sequence",16],[1538182653,"20d","netarch",2],[1538182657,"10c","nocode",90],[1538182684,"5","sequence",2],[1538182687,"17c","sequence",19],[1538182706,"17c","sequence",25],[1538182741,"17c","sequence",35],[1538182799,"7","network-fundamentals",10],[1538182811,"7","network-fundamentals",11],[1538182822,"7","network-fundamentals",12],[1538182825,"8d","netarch",100],[1538183054,"5","sequence",16],[1538183065,"7","sequence",19],[1538183073,"5","sequence",19],[1538183093,"5","sequence",25],[1538183098,"7","sequence",25],[1538183128,"5","sequence",35],[1538183131,"81","netarch",1],[1538183181,"7","sequence",35],[1538183190,"3","netarch",5],[1538183202,"0","sequence",1],[1538183212,"52","sequence",1],[1538183215,"0","sequence",2],[1538183216,"5","sequence",50],[1538183226,"52","sequence",2],[1538183230,"0","sequence",8],[1538183239,"52","sequence",8],[1538183242,"0","sequence",16],[1538183247,"64","network-fundamentals",1],[1538183253,"0","sequence",19],[1538183256,"52","sequence",16],[1538183263,"0","sequence",25],[1538183279,"0","sequence",35],[1538183280,"8d","netarch",250],[1538183382,"0","sequence",50],[1538183418,"52","sequence",25],[1538183423,"0","sequence",60],[1538183429,"52","sequence",35],[1538183458,"20d","network-fundamentals",1],[1538183463,"3","netarch",6],[1538183489,"5","sequence",60],[1538183514,"20d","sequence",1],[1538183550,"0","network-fundamentals",1],[1538183609,"0","network-fundamentals",10],[1538183617,"10c","network-fundamentals",1],[1538183629,"4a","sequence",100],[1538183631,"0","network-fundamentals",11],[1538183632,"64","sequence",1],[1538183639,"0","network-fundamentals",12],[1538183643,"3","sequence",60],[1538183651,"64","sequence",2],[1538183653,"0","network-fundamentals",13],[1538183732,"0","network-fundamentals",14],[1538183788,"7","network-fundamentals",13],[1538183789,"52","sequence",100],[1538183818,"5","network-fundamentals",1],[1538183832,"3","netarch",7],[1538183862,"52","network-fundamentals",1],[1538183879,"0","sequence",200],[1538183890,"2","sequence",1],[1538183944,"2","sequence",2],[1538183946,"17c","network-fundamentals",1],[1538183966,"3","sequence",100],[1538183970,"52","sequence",200],[1538184064,"2","sequence",8],[1538184065,"5","base",32],[1538184072,"20d","netarch",1],[1538184112,"2","sequence",16],[1538184165,"2","sequence",19],[1538184180,"2","sequence",25],[1538184202,"2","sequence",35],[1538184704,"b1","sequence",1],[1538184799,"17c","sequence",300],[1538184805,"4a","sequence",300],[1538184844,"b1","sequence",2],[1538185161,"5","netarch",200],[1538185263,"3","netarch",8],[1538185288,"b1","sequence",25],[1538185393,"3","netarch",10],[1538185440,"2","base",16],[1538185451,"b1","sequence",19],[1538185477,"10c","network-fundamentals",10],[1538185537,"10c","network-fundamentals",11],[1538185546,"b1","sequence",35],[1538185557,"10c","network-fundamentals",12],[1538185566,"d0","sequence",1],[1538185583,"d0","sequence",2],[1538185617,"0","sequence",400],[1538185638,"5","netarch",250],[1538185655,"10c","network-fundamentals",13],[1538185703,"5","network-fundamentals",12],[1538185780,"0","sequence",300],[1538185787,"d0","sequence",19],[1538185881,"0","sequence",100],[1538185961,"5","network-fundamentals",10],[1538186003,"0","sequence",500],[1538186020,"5","network-fundamentals",11],[1538186070,"5","network-fundamentals",13],[1538186122,"5","netarch",300],[1538186124,"b1","sequence",16],[1538186315,"5","sequence",100],[1538186352,"3","netarch",20],[1538186542,"9c","sequence",1],[1538186544,"17c","netarch",2],[1538186601,"d6","network-fundamentals",1],[1538186661,"9c","sequence",2],[1538186670,"1fb","nocode",1],[1538186730,"1fb","nocode",2],[1538186815,"d6","sequence",1],[1538186823,"d0","sequence",25],[1538186831,"d6","sequence",2],[1538186843,"d0","sequence",35],[1538186858,"d6","sequence",8],[1538186874,"d6","sequence",16],[1538186889,"d0","sequence",50],[1538186893,"d6","sequence",19],[1538186895,"1fb","nocode",3],[1538186922,"d6","sequence",25],[1538186935,"0","sequence",600],[1538186951,"d6","sequence",35],[1538187018,"1fb","nocode",4],[1538187074,"5","sequence",200],[1538187095,"2","network-fundamentals",1],[1538187099,"1fb","nocode",10],[1538187162,"b1","netarch",10],[1538187366,"f9","sequence",1],[1538187366,"0","reverse",500],[1538187379,"2","network-fundamentals",10],[1538187478,"d6","sequence",300],[1538187501,"81","sequence",2],[1538187547,"3","network-fundamentals",1],[1538187577,"2","network-fundamentals",11],[1538187601,"2","network-fundamentals",12],[1538187642,"3","network-fundamentals",10],[1538187695,"3","network-fundamentals",11],[1538187720,"10c","sequence",1],[1538187742,"81","nocode",2],[1538187769,"3","network-fundamentals",12],[1538187796,"3","network-fundamentals",13],[1538187803,"9c","sequence",8],[1538187817,"3","network-fundamentals",14],[1538187968,"3","network-fundamentals",15],[1538187983,"9c","sequence",16],[1538187988,"1fb","netarch",1],[1538188051,"3","network-fundamentals",16],[1538188147,"10c","sequence",19],[1538188245,"65","network-fundamentals",1],[1538188260,"10c","sequence",25],[1538188284,"65","nocode",1],[1538188306,"10c","sequence",35],[1538188311,"0","nocode",50],[1538188395,"2","network-fundamentals",14],[1538188402,"65","network-fundamentals",11],[1538188416,"2","network-fundamentals",15],[1538188431,"1fb","sequence",1],[1538188439,"2","network-fundamentals",16],[1538188462,"65","network-fundamentals",12],[1538188466,"1fb","sequence",2],[1538188503,"0","network-fundamentals",15],[1538188513,"0","network-fundamentals",16],[1538188514,"65","network-fundamentals",13],[1538188539,"0","network-fundamentals",30],[1538188588,"65","network-fundamentals",15],[1538188590,"1fb","sequence",8],[1538188611,"f9","nocode",90],[1538188611,"3","sequence",300],[1538188617,"65","network-fundamentals",16],[1538188629,"1fb","sequence",16],[1538188652,"65","network-fundamentals",30],[1538188881,"5","network-fundamentals",30],[1538189024,"0","base",51],[1538189032,"65","sequence",2],[1538189062,"0","base",52],[1538189114,"0","base",53],[1538189138,"53","base",1],[1538189193,"55","sequence",1],[1538189213,"55","sequence",2],[1538189238,"55","sequence",8],[1538189239,"3","sequence",400],[1538189251,"d0","sequence",60],[1538189252,"55","sequence",16],[1538189277,"10c","sequence",100],[1538189296,"53","base",2],[1538189351,"55","sequence",25],[1538189354,"0","base",54],[1538189369,"55","sequence",35],[1538189380,"0","base",55],[1538189391,"d0","sequence",100],[1538189409,"0","base",56],[1538189438,"3","sequence",500],[1538189439,"0","base",57],[1538189484,"55","network-fundamentals",1],[1538189548,"55","network-fundamentals",10],[1538189643,"10c","netarch",100],[1538190021,"3","sequence",600],[1538190258,"24","network-fundamentals",1],[1538190398,"5","base",3],[1538190563,"1fb","netarch",2],[1538190729,"b1","netarch",200],[1538190898,"b1","netarch",100],[1538191003,"9c","nocode",3],[1538191016,"9c","sequence",19],[1538191063,"10c","netarch",200],[1538191084,"5","base",4],[1538191100,"73","netarch",2],[1538191342,"1d0","sequence",1],[1538191371,"1d0","sequence",2],[1538191418,"5","base",5],[1538191515,"5","base",6],[1538191617,"1d0","sequence",8],[1538191625,"5","network-fundamentals",14],[1538191738,"5","base",7],[1538191790,"73","nocode",2],[1538191800,"1d0","sequence",16],[1538191819,"1d0","sequence",19],[1538191867,"1d0","sequence",25],[1538192020,"5","base",9],[1538192144,"5","base",10],[1538192214,"1d0","sequence",35],[1538192326,"73","sequence",1],[1538192450,"2","nocode",90],[1538192711,"3","sequence",200],[1538192726,"1d0","sequence",50],[1538192845,"5","network-fundamentals",16],[1538193142,"1","sequence",1],[1538193153,"1","sequence",2],[1538193201,"315","nocode",1],[1538193246,"315","base",1],[1538193250,"1","sequence",25],[1538193264,"1","sequence",35],[1538193285,"10c","base",4],[1538193288,"55","network-fundamentals",11],[1538193311,"55","network-fundamentals",12],[1538193368,"1d0","network-fundamentals",1],[1538193825,"3","netarch",30],[1538193930,"1","nocode",20],[1538194028,"9c","network-fundamentals",1],[1538194076,"9c","network-fundamentals",10],[1538194100,"9c","network-fundamentals",11],[1538194149,"9c","network-fundamentals",12],[1538194447,"9c","network-fundamentals",13],[1538194527,"5","netarch",20],[1538194610,"5","netarch",10],[1538194652,"9c","network-fundamentals",14],[1538194670,"1d0","network-fundamentals",12],[1538194712,"1d0","network-fundamentals",10],[1538194816,"9c","network-fundamentals",15],[1538194836,"9c","network-fundamentals",16],[1538195026,"5","netarch",400],[1538195039,"9c","netarch",100],[1538195501,"0","reverse",650],[1538195720,"5","sequence",8],[1538196349,"9c","netarch",1],[1538196784,"55","netarch",4],[1538196838,"52","netarch",7],[1538196892,"0","netarch",400],[1538196923,"9c","netarch",2],[1538197199,"53","network-fundamentals",1],[1538197267,"55","network-fundamentals",13],[1538197296,"55","network-fundamentals",14],[1538197320,"53","netarch",2],[1538197361,"55","network-fundamentals",15],[1538197400,"55","netarch",6],[1538197462,"55","network-fundamentals",16],[1538197607,"55","network-fundamentals",30],[1538197709,"53","network-fundamentals",11],[1538197775,"53","network-fundamentals",12],[1538197934,"55","sequence",50],[1538198026,"1fb","sequence",600],[1538198039,"53","network-fundamentals",13],[1538198122,"55","sequence",200],[1538198198,"55","sequence",300],[1538198296,"55","sequence",100],[1538198949,"344","base",1],[1538199218,"187","sequence",1],[1538199246,"187","sequence",2],[1538199519,"8d","base",32],[1538199628,"53","nocode",1],[1538199659,"53","nocode",2],[1538199725,"53","nocode",3],[1538199746,"53","nocode",4],[1538199761,"1fb","sequence",700],[1538199871,"53","nocode",10],[1538199979,"34e","base",1],[1538200015,"55","netarch",100],[1538200046,"55","netarch",200],[1538200101,"5","reverse",200],[1538200205,"34e","base",2],[1538200655,"0","sequence",740],[1538201242,"5","reverse",500],[1538201529,"42","sequence",1],[1538201540,"24","network-fundamentals",12],[1538201556,"42","sequence",2],[1538201595,"53","nocode",90],[1538201626,"42","sequence",25],[1538201648,"42","sequence",35],[1538201972,"42","sequence",19],[1538202003,"24","network-fundamentals",14],[1538203046,"35d","nocode",1],[1538203095,"35d","nocode",2],[1538203139,"35d","nocode",3],[1538203158,"35d","nocode",4],[1538203163,"f9","network-fundamentals",1],[1538203213,"35d","nocode",10],[1538203284,"53","sequence",1],[1538203330,"53","sequence",2],[1538203413,"35d","sequence",1],[1538203428,"35d","sequence",2],[1538203458,"53","sequence",8],[1538203514,"f9","sequence",2],[1538203546,"35d","sequence",16],[1538203566,"f9","sequence",8],[1538203575,"53","sequence",16],[1538203578,"35d","sequence",19],[1538203584,"f9","sequence",16],[1538203591,"35d","sequence",25],[1538203605,"f9","sequence",19],[1538203609,"35d","sequence",35],[1538203616,"f9","sequence",25],[1538203638,"f9","sequence",35],[1538203651,"53","sequence",19],[1538203679,"53","sequence",25],[1538203748,"53","sequence",35],[1538203752,"35d","base",1],[1538203902,"0","reverse",1000],[1538204061,"35d","network-fundamentals",1],[1538204277,"f9","sequence",50],[1538204423,"35d","network-fundamentals",10],[1538204468,"10c","netarch",5],[1538204604,"315","network-fundamentals",1],[1538204666,"f9","sequence",60],[1538204734,"10c","netarch",10],[1538204748,"35d","netarch",1],[1538204800,"315","network-fundamentals",11],[1538204821,"3","sequence",740],[1538204835,"315","network-fundamentals",12],[1538204866,"315","network-fundamentals",13],[1538204916,"315","network-fundamentals",14],[1538204934,"10c","netarch",20],[1538205088,"315","nocode",2],[1538205100,"53","sequence",100],[1538205130,"315","nocode",3],[1538205144,"315","nocode",4],[1538205190,"0","network-fundamentals",40],[1538205193,"f9","sequence",100],[1538205240,"0","network-fundamentals",41],[1538205266,"315","nocode",10],[1538205278,"0","network-fundamentals",42],[1538205306,"12f","base",3],[1538205322,"24","nocode",1],[1538205466,"f9","sequence",200],[1538205490,"0","network-fundamentals",43],[1538205496,"24","nocode",2],[1538205552,"1fb","base",3],[1538205602,"0","network-fundamentals",44],[1538205603,"1fb","base",4],[1538205608,"315","nocode",90],[1538205626,"24","nocode",3],[1538205632,"53","sequence",300],[1538205642,"1fb","base",5],[1538205660,"0","network-fundamentals",46],[1538205660,"24","nocode",4],[1538205688,"1fb","base",6],[1538205742,"1fb","base",7],[1538205813,"0","network-fundamentals",50],[1538205824,"315","netarch",2],[1538205902,"0","network-fundamentals",51],[1538205953,"1fb","base",9],[1538205992,"1fb","base",10],[1538206019,"81","netarch",2],[1538206025,"1fb","base",11],[1538206105,"0","network-fundamentals",52],[1538206105,"8d","base",33],[1538206124,"24","nocode",10],[1538206125,"1fb","base",12],[1538206153,"1fb","base",13],[1538206183,"0","network-fundamentals",53],[1538206185,"1fb","base",14],[1538206213,"1fb","base",15],[1538206274,"8d","base",34],[1538206282,"1fb","base",17],[1538206283,"0","network-fundamentals",54],[1538206358,"0","network-fundamentals",55],[1538206416,"315","sequence",1],[1538206432,"315","sequence",2],[1538206473,"315","sequence",8],[1538206490,"8d","base",35],[1538206503,"315","sequence",16],[1538206526,"315","sequence",19],[1538206559,"315","sequence",25],[1538206664,"1fb","base",18],[1538206695,"0","network-fundamentals",56],[1538206704,"1fb","base",19],[1538206730,"1fb","base",20],[1538206748,"8d","base",36],[1538206757,"1fb","base",21],[1538206788,"0","network-fundamentals",57],[1538206821,"1fb","base",22],[1538206834,"0","network-fundamentals",58],[1538206844,"1fb","base",23],[1538206899,"1fb","base",24],[1538206926,"0","network-fundamentals",59],[1538206928,"1fb","base",25],[1538206955,"1fb","base",26],[1538206986,"1fb","base",27],[1538207017,"0","network-fundamentals",60],[1538207018,"1fb","base",28],[1538207057,"1fb","base",29],[1538207059,"0","network-fundamentals",61],[1538207092,"1fb","base",30],[1538207112,"12f","base",4],[1538207127,"1fb","base",31],[1538207145,"0","network-fundamentals",62],[1538207188,"315","sequence",400],[1538207212,"0","network-fundamentals",63],[1538207250,"0","network-fundamentals",64],[1538207265,"0","network-fundamentals",70],[1538207275,"0","network-fundamentals",71],[1538207278,"12f","base",5],[1538207296,"0","network-fundamentals",72],[1538207406,"12f","base",6],[1538207467,"0","network-fundamentals",200],[1538207587,"12f","base",7],[1538207631,"f9","sequence",300],[1538208185,"1fb","network-fundamentals",1],[1538208564,"81","network-fundamentals",200],[1538208581,"1fb","sequence",19],[1538208685,"1fb","sequence",25],[1538208944,"3","nocode",80],[1538209362,"24","netarch",1],[1538209605,"1fb","sequence",35],[1538209672,"3","netarch",100],[1538209925,"1fb","sequence",50],[1538210291,"12f","base",9],[1538210534,"12f","base",10],[1538210647,"f9","network-fundamentals",12],[1538210676,"f9","network-fundamentals",13],[1538210738,"24","sequence",1],[1538210792,"24","sequence",2],[1538211005,"3","netarch",200],[1538211035,"24","sequence",8],[1538211081,"24","sequence",16],[1538211154,"12f","sequence",1],[1538211160,"1fb","sequence",100],[1538211217,"12f","sequence",2],[1538211491,"1fb","sequence",300],[1538211533,"24","sequence",19],[1538211568,"24","sequence",25],[1538212107,"3","netarch",250],[1538212117,"81","netarch",250],[1538212155,"24","sequence",35],[1538212335,"24","sequence",50],[1538212545,"1fb","sequence",400],[1538212935,"3f8","netarch",1],[1538213499,"3f9","nocode",1],[1538214048,"24","sequence",100],[1538214537,"24","network-fundamentals",72],[1538214657,"3f8","netarch",2],[1538214819,"24","network-fundamentals",70],[1538214898,"24","network-fundamentals",71],[1538216910,"1fb","sequence",740],[1538217532,"3f8","netarch",4],[1538217991,"1fb","network-fundamentals",72],[1538219894,"3f8","netarch",5],[1538232378,"f9","network-fundamentals",10],[1538232631,"f9","network-fundamentals",11],[1538233724,"8d","netarch",300],[1538234792,"42","network-fundamentals",10],[1538234809,"42","network-fundamentals",11],[1538234821,"42","network-fundamentals",12],[1538235061,"42","network-fundamentals",13],[1538235137,"0","nocode",20],[1538235206,"42","nocode",1],[1538236318,"7","sequence",50],[1538237155,"8d","netarch",400],[1538237600,"7","base",17],[1538237945,"55","sequence",19],[1538237981,"410","base",1],[1538238252,"42","codebreaking",1],[1538238344,"55","codebreaking",1],[1538238435,"55","codebreaking",2],[1538238462,"55","network-fundamentals",72],[1538238505,"7","codebreaking",1],[1538238532,"315","network-fundamentals",10],[1538238658,"7","codebreaking",2],[1538238815,"315","network-fundamentals",15],[1538238878,"8d","netarch",700],[1538238940,"5","codebreaking",1],[1538239044,"0","codebreaking",1],[1538239155,"81","codebreaking",1],[1538239291,"55","codebreaking",4],[1538239310,"315","sequence",35],[1538239338,"55","netarch",250],[1538239449,"5","codebreaking",4],[1538239523,"5","codebreaking",2],[1538239555,"315","sequence",100],[1538239589,"410","nocode",1],[1538239607,"410","nocode",2],[1538239674,"410","base",16],[1538239817,"410","base",2],[1538239845,"55","codebreaking",5],[1538239927,"410","nocode",3],[1538239967,"315","codebreaking",1],[1538240094,"315","codebreaking",2],[1538240253,"410","nocode",4],[1538240391,"410","nocode",10],[1538240457,"410","codebreaking",2],[1538240472,"410","codebreaking",1],[1538240555,"410","nocode",20],[1538240579,"d0","codebreaking",1],[1538240633,"410","codebreaking",4],[1538240746,"53","base",4],[1538240799,"5","sequence",740],[1538241016,"410","base",10],[1538241071,"d0","codebreaking",2],[1538241096,"410","sequence",1],[1538241097,"53","base",3],[1538241143,"53","base",5],[1538241150,"410","sequence",2],[1538241188,"53","base",6],[1538241237,"53","base",7],[1538241370,"7","codebreaking",4],[1538241370,"55","netarch",300],[1538241503,"53","base",9],[1538241545,"0","codebreaking",2],[1538241549,"53","base",10],[1538241564,"0","codebreaking",4],[1538241576,"7","codebreaking",5],[1538241591,"53","base",11],[1538241636,"53","base",12],[1538241652,"5","network-fundamentals",61],[1538242188,"410","netarch",1],[1538242237,"0","codebreaking",5],[1538242554,"410","sequence",16],[1538242592,"0","codebreaking",6],[1538242720,"0","codebreaking",7],[1538242908,"7","codebreaking",6],[1538243063,"a7","network-fundamentals",1],[1538243067,"8d","netarch",800],[1538243190,"44e","base",1],[1538243272,"410","sequence",25],[1538243276,"5","sequence",300],[1538243371,"a7","network-fundamentals",10],[1538243424,"44e","codebreaking",1],[1538243445,"410","sequence",35],[1538243527,"a7","network-fundamentals",11],[1538243581,"a7","network-fundamentals",12],[1538243623,"44e","netarch",1],[1538243646,"a7","network-fundamentals",13],[1538243675,"44e","network-fundamentals",1],[1538243689,"44e","nocode",1],[1538243799,"44e","sequence",1],[1538243818,"44e","sequence",2],[1538243863,"0","netarch",800],[1538243976,"a7","network-fundamentals",30],[1538244036,"410","base",32],[1538244145,"44e","sequence",16],[1538244173,"44e","sequence",25],[1538244201,"44e","sequence",35],[1538244418,"44e","sequence",50],[1538244447,"8d","network-fundamentals",1],[1538244481,"44e","sequence",60],[1538244518,"410","sequence",100],[1538244692,"44e","sequence",200],[1538244743,"53","base",13],[1538244800,"53","base",14],[1538244861,"53","base",15],[1538244914,"53","base",16],[1538244960,"8d","network-fundamentals",10],[1538244968,"53","base",17],[1538244974,"8d","network-fundamentals",11],[1538244979,"44e","sequence",300],[1538244987,"8d","network-fundamentals",12],[1538245130,"53","base",18],[1538245194,"53","base",19],[1538245234,"53","base",20],[1538245280,"53","base",21],[1538245294,"44e","nocode",2],[1538245322,"53","base",22],[1538245361,"53","base",23],[1538245368,"8d","network-fundamentals",13],[1538245401,"a7","network-fundamentals",72],[1538245401,"53","base",24],[1538245403,"2","codebreaking",1],[1538245485,"44e","nocode",4],[1538245509,"44e","nocode",3],[1538245537,"44e","nocode",10],[1538245564,"f9","network-fundamentals",14],[1538245654,"53","base",25],[1538245657,"410","nocode",90],[1538245708,"53","base",26],[1538245761,"53","base",27],[1538245766,"f9","network-fundamentals",15],[1538245826,"53","base",28],[1538245863,"410","network-fundamentals",1],[1538245945,"410","network-fundamentals",10],[1538245954,"53","base",29],[1538245986,"410","network-fundamentals",11],[1538246000,"53","base",30],[1538246000,"410","network-fundamentals",12],[1538246021,"410","network-fundamentals",13],[1538246036,"410","network-fundamentals",14],[1538246050,"53","base",31],[1538246099,"52","codebreaking",1],[1538246115,"8d","network-fundamentals",14],[1538246159,"44e","codebreaking",2],[1538246198,"8d","network-fundamentals",15],[1538246224,"8d","network-fundamentals",16],[1538246262,"2","codebreaking",2],[1538246272,"53","codebreaking",1],[1538246306,"f9","codebreaking",1],[1538246349,"52","codebreaking",2],[1538246404,"2","codebreaking",4],[1538246502,"53","codebreaking",2],[1538246566,"53","codebreaking",4],[1538246659,"24","codebreaking",1],[1538246671,"5","network-fundamentals",72],[1538246952,"410","sequence",400],[1538246991,"f9","network-fundamentals",16],[1538247200,"53","codebreaking",7],[1538247216,"f9","codebreaking",2],[1538247304,"f9","codebreaking",5],[1538247461,"5","network-fundamentals",71],[1538247530,"5","network-fundamentals",70],[1538247550,"7","base",18],[1538247745,"f9","codebreaking",4],[1538247773,"f9","base",1],[1538247812,"8d","codebreaking",1],[1538247951,"7","base",19],[1538248006,"7","base",20],[1538248036,"7","base",21],[1538248084,"7","base",22],[1538248127,"7","base",23],[1538248161,"7","base",24],[1538248186,"8d","codebreaking",2],[1538248205,"7","base",26],[1538248239,"7","base",25],[1538248278,"7","base",27],[1538248365,"7","base",28],[1538248400,"7","base",29],[1538248435,"7","base",30],[1538248464,"a7","base",32],[1538248470,"8d","codebreaking",4],[1538248585,"f9","base",2],[1538248745,"8d","codebreaking",5],[1538248952,"a7","base",16],[1538248982,"44e","codebreaking",4],[1538249105,"1fb","codebreaking",1],[1538249153,"1fb","codebreaking",2],[1538249178,"7","base",31],[1538249197,"81","codebreaking",5],[1538249267,"315","base",2],[1538249286,"7","sequence",200],[1538249389,"53","netarch",4],[1538249417,"7","sequence",300],[1538249477,"f9","network-fundamentals",61],[1538249552,"1fb","codebreaking",4],[1538249594,"410","network-fundamentals",200],[1538249630,"44e","codebreaking",5],[1538249962,"315","base",16],[1538250003,"53","netarch",5],[1538250037,"4a","codebreaking",1],[1538250101,"4a","codebreaking",2],[1538250491,"53","netarch",10],[1538250524,"44e","codebreaking",6],[1538250530,"4a","codebreaking",4],[1538250561,"81","network-fundamentals",72],[1538250744,"315","codebreaking",4],[1538250817,"7","network-fundamentals",14],[1538250913,"1fb","netarch",4],[1538251155,"7","network-fundamentals",72],[1538251456,"53","netarch",200],[1538251472,"44e","codebreaking",7],[1538251960,"7","netarch",250],[1538252500,"315","codebreaking",5],[1538253409,"a7","netarch",250],[1538253591,"7","sequence",700],[1538253711,"4d8","codebreaking",1],[1538253761,"4d8","base",1],[1538254573,"7","sequence",740],[1538254577,"5","codebreaking",8],[1538254686,"5","codebreaking",7],[1538254702,"1fb","netarch",5],[1538255622,"a7","sequence",19],[1538255694,"4d8","netarch",1],[1538255745,"4d8","nocode",1],[1538255757,"1fb","netarch",6],[1538255940,"f9","network-fundamentals",70],[1538256054,"1fb","netarch",7],[1538256186,"5","codebreaking",5],[1538256197,"4e5","base",1],[1538256299,"f9","network-fundamentals",72],[1538256305,"4d8","sequence",1],[1538256560,"4d8","network-fundamentals",1],[1538256789,"315","sequence",600],[1538256971,"4e5","base",2],[1538257007,"4d8","sequence",2],[1538257412,"4e5","codebreaking",1],[1538257439,"3","nocode",30],[1538257730,"4e5","netarch",1],[1538257755,"4e5","nocode",1],[1538257884,"4e5","sequence",1],[1538257952,"4e5","sequence",2],[1538257984,"315","sequence",740],[1538258021,"4e5","sequence",8],[1538258134,"4e5","sequence",16],[1538258161,"4e5","sequence",19],[1538258180,"4e5","sequence",25],[1538258238,"4e5","sequence",35],[1538258294,"4e5","sequence",50],[1538258597,"af","codebreaking",1],[1538258660,"55","base",16],[1538258802,"af","codebreaking",2],[1538258856,"b1","codebreaking",1],[1538259414,"af","codebreaking",4],[1538259458,"8d","codebreaking",15],[1538259621,"4e5","nocode",2],[1538259634,"4e5","nocode",3],[1538259645,"4e5","nocode",4],[1538259676,"4e5","nocode",10],[1538259787,"af","codebreaking",5],[1538260383,"0","codebreaking",50],[1538260397,"8d","codebreaking",50],[1538260415,"3","codebreaking",1],[1538260521,"4e5","base",3],[1538260553,"4e5","base",4],[1538260579,"4e5","base",5],[1538260609,"4e5","base",6],[1538260611,"3","codebreaking",2],[1538260646,"af","codebreaking",7],[1538260653,"4e5","base",7],[1538260902,"af","codebreaking",8],[1538261403,"3","codebreaking",4],[1538261903,"d0","codebreaking",5],[1538261905,"0","codebreaking",15],[1538262527,"b1","codebreaking",2],[1538262558,"3","codebreaking",50],[1538262594,"b1","sequence",8],[1538262706,"b1","sequence",50],[1538262841,"4e5","nocode",20],[1538263279,"517","network-fundamentals",10],[1538263458,"4e5","sequence",60],[1538263947,"517","network-fundamentals",1],[1538264147,"af","codebreaking",50],[1538264152,"5","base",11],[1538264243,"5","base",12],[1538264246,"3","codebreaking",5],[1538264303,"5","base",13],[1538264385,"5","base",14],[1538264417,"af","network-fundamentals",1],[1538264444,"5","base",15],[1538264572,"1fb","netarch",100],[1538264575,"5","base",16],[1538264649,"5","base",17],[1538264662,"1fb","netarch",200],[1538264693,"517","netarch",1],[1538264694,"5","base",18],[1538264749,"5","base",19],[1538264832,"5","base",20],[1538264873,"5","base",21],[1538264895,"4e5","sequence",100],[1538264919,"5","base",22],[1538264953,"af","sequence",1],[1538264961,"5","base",23],[1538264982,"af","sequence",2],[1538264985,"1fb","netarch",250],[1538265008,"af","sequence",8],[1538265057,"af","sequence",16],[1538265064,"5","base",24],[1538265075,"8d","network-fundamentals",72],[1538265079,"af","sequence",19],[1538265092,"af","sequence",25],[1538265102,"5","base",25],[1538265104,"af","sequence",35],[1538265133,"5","base",26],[1538265163,"5","base",27],[1538265194,"5","base",28],[1538265236,"5","base",29],[1538265267,"5","base",30],[1538265300,"5","base",31],[1538265302,"c","sequence",1],[1538265338,"c","sequence",2],[1538265446,"c","codebreaking",1],[1538265576,"4e5","sequence",200],[1538265778,"0","sequence",700],[1538265804,"c","nocode",90],[1538265872,"4e5","sequence",300],[1538266214,"af","sequence",100],[1538266233,"4e5","base",9],[1538266267,"4e5","base",10],[1538266325,"af","sequence",200],[1538266408,"c","sequence",35],[1538266472,"c","sequence",19],[1538266489,"c","sequence",25],[1538266607,"c","sequence",50],[1538266687,"af","sequence",300],[1538266972,"af","sequence",400],[1538267151,"4e5","base",11],[1538267206,"4e5","base",12],[1538267228,"4e5","base",13],[1538267251,"4e5","base",14],[1538267271,"4e5","base",15],[1538267300,"4e5","base",16],[1538267317,"4e5","base",17],[1538267332,"4e5","base",18],[1538267349,"4e5","base",19],[1538267371,"4e5","base",20],[1538267390,"4e5","base",21],[1538267407,"4e5","base",22],[1538267430,"4e5","base",23],[1538267453,"4e5","base",24],[1538267633,"4e5","network-fundamentals",1],[1538267683,"c","network-fundamentals",1],[1538268334,"f9","network-fundamentals",64],[1538268453,"517","nocode",1],[1538268488,"517","nocode",2],[1538269087,"1fb","netarch",300],[1538269319,"4e5","netarch",2],[1538269898,"4e5","nocode",90],[1538269993,"10c","netarch",250],[1538270313,"10c","codebreaking",1],[1538270435,"4e5","sequence",400],[1538271128,"517","nocode",4],[1538271165,"9c","codebreaking",1],[1538271210,"9c","codebreaking",2],[1538271274,"517","nocode",10],[1538271661,"103","sequence",1],[1538271682,"103","sequence",2],[1538271904,"103","sequence",16],[1538271966,"103","sequence",19],[1538271981,"103","sequence",25],[1538272000,"103","sequence",35],[1538272454,"11d","network-fundamentals",10],[1538272465,"11d","network-fundamentals",11],[1538272477,"11d","network-fundamentals",12],[1538272791,"3","codebreaking",100],[1538272822,"577","nocode",1],[1538272859,"577","nocode",2],[1538273535,"577","sequence",1],[1538273622,"3","codebreaking",200],[1538273638,"577","sequence",2],[1538275224,"5","codebreaking",50],[1538275475,"b1","reverse",200],[1538275574,"0","codebreaking",500],[1538275592,"103","codebreaking",1],[1538275666,"0","codebreaking",600],[1538275952,"0","codebreaking",200],[1538276189,"1fb","network-fundamentals",10],[1538276374,"1fb","network-fundamentals",11],[1538276452,"1fb","network-fundamentals",12],[1538276465,"103","sequence",200],[1538276491,"1fb","network-fundamentals",13],[1538276600,"1fb","network-fundamentals",14],[1538276629,"1fb","network-fundamentals",15],[1538276645,"1fb","network-fundamentals",16],[1538277168,"5","codebreaking",200],[1538277335,"1fb","network-fundamentals",50],[1538277500,"1fb","network-fundamentals",51],[1538277807,"b1","reverse",500],[1538278030,"5","network-fundamentals",60],[1538278056,"4e5","codebreaking",2],[1538278219,"d0","codebreaking",4],[1538278319,"5","network-fundamentals",50],[1538278624,"5","network-fundamentals",51],[1538278864,"3","base",16],[1538279109,"65","codebreaking",1],[1538279140,"4e5","codebreaking",5],[1538279307,"65","netarch",1],[1538279422,"5","netarch",4],[1538279458,"4e5","codebreaking",4],[1538279890,"5","network-fundamentals",64],[1538280038,"5","network-fundamentals",63],[1538280054,"b1","codebreaking",4],[1538280430,"b1","codebreaking",5],[1538280525,"5","network-fundamentals",59],[1538280603,"5","network-fundamentals",58],[1538280810,"b1","sequence",100],[1538281149,"b1","sequence",300],[1538282318,"5","network-fundamentals",55],[1538282477,"52","netarch",10],[1538282716,"5","network-fundamentals",54],[1538282956,"3","base",30],[1538283110,"3","base",29],[1538283217,"3","base",28],[1538283340,"3","base",27],[1538283420,"3","base",26],[1538283512,"3","base",25],[1538283567,"3","base",24],[1538283585,"44e","nocode",90],[1538283612,"b1","base",16],[1538283618,"3","base",23],[1538283675,"3","base",22],[1538283756,"3","base",21],[1538283819,"3","base",19],[1538284032,"3","base",18],[1538284066,"5","network-fundamentals",62],[1538284088,"3","base",17],[1538284194,"3","base",15],[1538284327,"3","base",14],[1538284389,"3","base",13],[1538284446,"3","base",12],[1538284497,"3","base",11],[1538284555,"3","base",10],[1538284614,"52","network-fundamentals",72],[1538284656,"3","base",9],[1538284786,"52","network-fundamentals",63],[1538284903,"52","network-fundamentals",50],[1538285292,"52","network-fundamentals",55],[1538285373,"3","base",31],[1538285476,"52","network-fundamentals",58],[1538285547,"52","network-fundamentals",59],[1538285643,"3","base",32],[1538285652,"52","network-fundamentals",60],[1538285685,"52","network-fundamentals",61],[1538285947,"52","network-fundamentals",62],[1538286138,"52","network-fundamentals",64],[1538286331,"0","base",58],[1538286745,"0","base",59],[1538286778,"0","base",60],[1538286828,"0","base",61],[1538286859,"0","base",62],[1538287004,"0","base",63],[1538287019,"3","base",33],[1538287065,"0","base",64],[1538287093,"3","base",64],[1538287097,"0","base",65],[1538287127,"0","base",66],[1538287210,"0","base",67],[1538287211,"44e","nocode",20],[1538287311,"0","base",68],[1538287333,"0","base",69],[1538287356,"0","base",70],[1538287377,"0","base",71],[1538287396,"0","base",72],[1538287421,"0","base",73],[1538287469,"0","base",74],[1538287490,"0","base",75],[1538287527,"0","base",76],[1538287548,"0","base",77],[1538287606,"0","base",78],[1538287634,"0","base",79],[1538287657,"0","base",80],[1538287680,"3","base",34],[1538287687,"0","base",81],[1538287723,"0","base",82],[1538287743,"0","base",83],[1538287757,"3","base",35],[1538287782,"0","base",84],[1538287799,"0","base",85],[1538287819,"0","base",86],[1538287834,"3","base",36],[1538287839,"0","base",87],[1538287858,"0","base",88],[1538287879,"0","base",89],[1538287900,"0","base",90],[1538287924,"0","base",91],[1538287943,"0","base",92],[1538287962,"0","base",93],[1538287987,"0","base",94],[1538288133,"1fb","netarch",800],[1538288618,"1fb","nocode",90],[1538288622,"0","base",117],[1538288869,"b1","base",64],[1538289075,"0","base",121],[1538289223,"1fb","nocode",20],[1538290920,"1fb","sequence",500],[1538291036,"3","base",37],[1538291205,"3","base",38],[1538291259,"3","base",39],[1538291347,"3","base",40],[1538291478,"3","base",41],[1538291529,"3","base",42],[1538291575,"3","base",43],[1538291652,"3","base",44],[1538291793,"3","base",45],[1538291840,"3","base",46],[1538291890,"3","base",47],[1538291934,"3","base",48],[1538292306,"1fb","sequence",200],[1538292692,"3","base",49],[1538292983,"3","base",50],[1538293048,"3","base",51],[1538293080,"3","base",52],[1538293160,"3","base",53],[1538293188,"3","base",54],[1538293215,"3","base",55],[1538293240,"3","base",56],[1538293267,"3","base",57],[1538293421,"1fb","codebreaking",50],[1538294553,"3","reverse",200],[1538295876,"3","base",59],[1538295923,"3","base",60],[1538295948,"3","base",61],[1538295978,"3","base",62],[1538295994,"577","sequence",8],[1538296031,"3","base",63],[1538296052,"577","sequence",16],[1538296127,"3","base",65],[1538298562,"3","base",66],[1538298614,"3","base",67],[1538298670,"3","base",68],[1538298723,"3","base",69],[1538298764,"3","base",70],[1538298806,"3","base",71],[1538298968,"3","base",72],[1538299022,"3","base",73],[1538299063,"3","base",74],[1538299104,"3","base",75],[1538299295,"3","base",76],[1538299364,"3","base",77],[1538299425,"3","base",78],[1538299465,"3","base",79],[1538299583,"3","base",80],[1538299649,"3","base",81],[1538299739,"3","base",82],[1538299907,"3","base",83],[1538299966,"3","base",84],[1538300036,"3","base",85],[1538300082,"3","base",86],[1538300133,"3","base",87],[1538300184,"3","base",88],[1538300223,"3","base",89],[1538300269,"3","base",90],[1538300307,"3","base",91],[1538300345,"3","base",92],[1538300412,"3","base",93],[1538300452,"3","base",94],[1538301325,"3","base",117],[1538316409,"81","codebreaking",6],[1538319490,"81","codebreaking",2],[1538319604,"81","base",64],[1538319732,"81","base",32],[1538320290,"81","sequence",25],[1538320325,"81","sequence",35],[1538320912,"3","reverse",500],[1538321166,"315","codebreaking",50],[1538321568,"315","codebreaking",200],[1538322484,"0","js",1],[1538322485,"52","base",64],[1538322549,"0","js",2],[1538323119,"52","base",32],[1538323940,"f9","js",2],[1538324682,"52","sequence",50],[1538325511,"52","netarch",100],[1538328017,"7","js",1],[1538328082,"7","js",2],[1538328296,"3","js",2],[1538328828,"4e5","network-fundamentals",10],[1538328845,"4e5","network-fundamentals",11],[1538328880,"4e5","network-fundamentals",12],[1538328902,"5","js",1],[1538329418,"5","js",2],[1538329436,"3","js",1],[1538329683,"5","js",3],[1538329837,"4e5","network-fundamentals",13],[1538329838,"d0","js",1],[1538329859,"d0","js",2],[1538330249,"5","js",10],[1538330676,"5","js",50],[1538330771,"8d","js",10],[1538331774,"3","js",3],[1538331935,"24","js",1],[1538332032,"24","js",2],[1538332034,"3","js",10],[1538333410,"4a","shadow",100],[1538333914,"4a","shadow",200],[1538334490,"52","network-fundamentals",10],[1538334499,"3","js",50],[1538334775,"5","base",64],[1538334794,"4e5","netarch",100],[1538334864,"81","network-fundamentals",71],[1538334894,"81","network-fundamentals",70],[1538334921,"4e5","netarch",200],[1538335361,"4e5","network-fundamentals",14],[1538335809,"24","network-fundamentals",11],[1538335909,"0","js",3],[1538335948,"0","js",10],[1538335977,"0","js",50],[1538336012,"b1","js",1],[1538336091,"1d0","codebreaking",1],[1538336134,"b1","js",2],[1538336189,"24","network-fundamentals",10],[1538336247,"4a","js",1],[1538336268,"8d","js",300],[1538336292,"4a","js",2],[1538336365,"b1","js",3],[1538336418,"24","network-fundamentals",13],[1538336469,"b1","js",10],[1538336512,"673","base",1],[1538336524,"674","base",1],[1538336544,"674","codebreaking",1],[1538336556,"b1","js",50],[1538336578,"674","nocode",1],[1538336592,"673","base",2],[1538336599,"674","sequence",1],[1538336646,"65","nocode",10],[1538336739,"d0","js",10],[1538336756,"7","js",10],[1538336832,"7","js",50],[1538336869,"65","nocode",4],[1538336900,"5","js",300],[1538337031,"4e5","codebreaking",15],[1538337036,"7","netarch",100],[1538337113,"673","nocode",1],[1538337134,"673","nocode",2],[1538337274,"7","netarch",200],[1538337393,"24","network-fundamentals",15],[1538337457,"24","network-fundamentals",16],[1538337501,"7","base",64],[1538337766,"7","netarch",800],[1538338047,"55","base",3],[1538338204,"24","network-fundamentals",40],[1538338291,"103","sequence",8],[1538338330,"d0","js",3],[1538338359,"65","netarch",250],[1538338369,"d0","js",50],[1538338371,"103","sequence",50],[1538338447,"3f9","base",1],[1538338511,"65","netarch",200],[1538338550,"3f9","codebreaking",1],[1538338641,"65","base",64],[1538338643,"55","base",4],[1538338694,"3f9","nocode",2],[1538338731,"81","network-fundamentals",61],[1538338764,"3f9","nocode",3],[1538338805,"3f9","nocode",4],[1538338884,"103","sequence",100],[1538339277,"8d","js",500],[1538339303,"0","js",300],[1538339305,"673","codebreaking",1],[1538339384,"673","codebreaking",2],[1538339486,"24","js",50],[1538339552,"65","base",32],[1538339639,"103","sequence",300],[1538339662,"55","base",5],[1538339698,"0","js",500],[1538339733,"55","base",6],[1538339741,"673","network-fundamentals",13],[1538339767,"673","network-fundamentals",14],[1538339800,"24","js",10],[1538339808,"55","base",7],[1538340352,"53","base",64],[1538340460,"55","base",10],[1538340550,"55","base",64]]} diff --git a/theme/puzzle-list.html b/theme/puzzle-list.html index d841bb7..af42db5 100644 --- a/theme/puzzle-list.html +++ b/theme/puzzle-list.html @@ -4,20 +4,21 @@ Open Puzzles - - + diff --git a/theme/puzzle.html b/theme/puzzle.html index 70130f3..5aa19b9 100644 --- a/theme/puzzle.html +++ b/theme/puzzle.html @@ -4,8 +4,8 @@ Puzzle - - + + @@ -80,14 +88,14 @@ document.addEventListener("DOMContentLoaded", init); Team ID:
- Answer:
+ Answer:
+
diff --git a/theme/scoreboard.html b/theme/scoreboard.html index 1cff569..db6531a 100644 --- a/theme/scoreboard.html +++ b/theme/scoreboard.html @@ -4,133 +4,121 @@ Scoreboard - - diff --git a/theme/token.html b/theme/token.html new file mode 100644 index 0000000..44d845a --- /dev/null +++ b/theme/token.html @@ -0,0 +1,43 @@ + + + + Redeem Token + + + + + +

Redeem Token

+
+ + + + Team ID:
+ Token:
+ +
+ + + diff --git a/www/credits.html b/www/credits.html deleted file mode 100644 index a0f6af8..0000000 --- a/www/credits.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - The Credits - - - - - -

Credits

- -
-

Created By

- - - -

- Should your name be here? Please remind me! -

-
- -
-

Inspiration

- -
- -
-

Thanks

-

- This contest would not exist were it not for hundreds of - thousands of lines of code from free software authors around the - world, including: -

- -
- -
- - - - - -
- - diff --git a/www/d3.js b/www/d3.js deleted file mode 100644 index 5c59e8c..0000000 --- a/www/d3.js +++ /dev/null @@ -1,17020 +0,0 @@ -// https://d3js.org Version 4.11.0. Copyright 2017 Mike Bostock. -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.d3 = global.d3 || {}))); -}(this, (function (exports) { 'use strict'; - -var version = "4.11.0"; - -var ascending = function(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; -}; - -var bisector = function(compare) { - if (compare.length === 1) compare = ascendingComparator(compare); - return { - left: function(a, x, lo, hi) { - if (lo == null) lo = 0; - if (hi == null) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) < 0) lo = mid + 1; - else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (lo == null) lo = 0; - if (hi == null) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) > 0) hi = mid; - else lo = mid + 1; - } - return lo; - } - }; -}; - -function ascendingComparator(f) { - return function(d, x) { - return ascending(f(d), x); - }; -} - -var ascendingBisect = bisector(ascending); -var bisectRight = ascendingBisect.right; -var bisectLeft = ascendingBisect.left; - -var pairs = function(array, f) { - if (f == null) f = pair; - var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); - while (i < n) pairs[i] = f(p, p = array[++i]); - return pairs; -}; - -function pair(a, b) { - return [a, b]; -} - -var cross = function(values0, values1, reduce) { - var n0 = values0.length, - n1 = values1.length, - values = new Array(n0 * n1), - i0, - i1, - i, - value0; - - if (reduce == null) reduce = pair; - - for (i0 = i = 0; i0 < n0; ++i0) { - for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { - values[i] = reduce(value0, values1[i1]); - } - } - - return values; -}; - -var descending = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; -}; - -var number = function(x) { - return x === null ? NaN : +x; -}; - -var variance = function(values, valueof) { - var n = values.length, - m = 0, - i = -1, - mean = 0, - value, - delta, - sum = 0; - - if (valueof == null) { - while (++i < n) { - if (!isNaN(value = number(values[i]))) { - delta = value - mean; - mean += delta / ++m; - sum += delta * (value - mean); - } - } - } - - else { - while (++i < n) { - if (!isNaN(value = number(valueof(values[i], i, values)))) { - delta = value - mean; - mean += delta / ++m; - sum += delta * (value - mean); - } - } - } - - if (m > 1) return sum / (m - 1); -}; - -var deviation = function(array, f) { - var v = variance(array, f); - return v ? Math.sqrt(v) : v; -}; - -var extent = function(values, valueof) { - var n = values.length, - i = -1, - value, - min, - max; - - if (valueof == null) { - while (++i < n) { // Find the first comparable value. - if ((value = values[i]) != null && value >= value) { - min = max = value; - while (++i < n) { // Compare the remaining values. - if ((value = values[i]) != null) { - if (min > value) min = value; - if (max < value) max = value; - } - } - } - } - } - - else { - while (++i < n) { // Find the first comparable value. - if ((value = valueof(values[i], i, values)) != null && value >= value) { - min = max = value; - while (++i < n) { // Compare the remaining values. - if ((value = valueof(values[i], i, values)) != null) { - if (min > value) min = value; - if (max < value) max = value; - } - } - } - } - } - - return [min, max]; -}; - -var array = Array.prototype; - -var slice = array.slice; -var map = array.map; - -var constant = function(x) { - return function() { - return x; - }; -}; - -var identity = function(x) { - return x; -}; - -var sequence = function(start, stop, step) { - start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; - - var i = -1, - n = Math.max(0, Math.ceil((stop - start) / step)) | 0, - range = new Array(n); - - while (++i < n) { - range[i] = start + i * step; - } - - return range; -}; - -var e10 = Math.sqrt(50); -var e5 = Math.sqrt(10); -var e2 = Math.sqrt(2); - -var ticks = function(start, stop, count) { - var reverse, - i = -1, - n, - ticks, - step; - - stop = +stop, start = +start, count = +count; - if (start === stop && count > 0) return [start]; - if (reverse = stop < start) n = start, start = stop, stop = n; - if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; - - if (step > 0) { - start = Math.ceil(start / step); - stop = Math.floor(stop / step); - ticks = new Array(n = Math.ceil(stop - start + 1)); - while (++i < n) ticks[i] = (start + i) * step; - } else { - start = Math.floor(start * step); - stop = Math.ceil(stop * step); - ticks = new Array(n = Math.ceil(start - stop + 1)); - while (++i < n) ticks[i] = (start - i) / step; - } - - if (reverse) ticks.reverse(); - - return ticks; -}; - -function tickIncrement(start, stop, count) { - var step = (stop - start) / Math.max(0, count), - power = Math.floor(Math.log(step) / Math.LN10), - error = step / Math.pow(10, power); - return power >= 0 - ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) - : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); -} - -function tickStep(start, stop, count) { - var step0 = Math.abs(stop - start) / Math.max(0, count), - step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), - error = step0 / step1; - if (error >= e10) step1 *= 10; - else if (error >= e5) step1 *= 5; - else if (error >= e2) step1 *= 2; - return stop < start ? -step1 : step1; -} - -var sturges = function(values) { - return Math.ceil(Math.log(values.length) / Math.LN2) + 1; -}; - -var histogram = function() { - var value = identity, - domain = extent, - threshold = sturges; - - function histogram(data) { - var i, - n = data.length, - x, - values = new Array(n); - - for (i = 0; i < n; ++i) { - values[i] = value(data[i], i, data); - } - - var xz = domain(values), - x0 = xz[0], - x1 = xz[1], - tz = threshold(values, x0, x1); - - // Convert number of thresholds into uniform thresholds. - if (!Array.isArray(tz)) { - tz = tickStep(x0, x1, tz); - tz = sequence(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive - } - - // Remove any thresholds outside the domain. - var m = tz.length; - while (tz[0] <= x0) tz.shift(), --m; - while (tz[m - 1] > x1) tz.pop(), --m; - - var bins = new Array(m + 1), - bin; - - // Initialize bins. - for (i = 0; i <= m; ++i) { - bin = bins[i] = []; - bin.x0 = i > 0 ? tz[i - 1] : x0; - bin.x1 = i < m ? tz[i] : x1; - } - - // Assign data to bins by value, ignoring any outside the domain. - for (i = 0; i < n; ++i) { - x = values[i]; - if (x0 <= x && x <= x1) { - bins[bisectRight(tz, x, 0, m)].push(data[i]); - } - } - - return bins; - } - - histogram.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; - }; - - histogram.domain = function(_) { - return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; - }; - - histogram.thresholds = function(_) { - return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; - }; - - return histogram; -}; - -var threshold = function(values, p, valueof) { - if (valueof == null) valueof = number; - if (!(n = values.length)) return; - if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); - if (p >= 1) return +valueof(values[n - 1], n - 1, values); - var n, - i = (n - 1) * p, - i0 = Math.floor(i), - value0 = +valueof(values[i0], i0, values), - value1 = +valueof(values[i0 + 1], i0 + 1, values); - return value0 + (value1 - value0) * (i - i0); -}; - -var freedmanDiaconis = function(values, min, max) { - values = map.call(values, number).sort(ascending); - return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3))); -}; - -var scott = function(values, min, max) { - return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); -}; - -var max = function(values, valueof) { - var n = values.length, - i = -1, - value, - max; - - if (valueof == null) { - while (++i < n) { // Find the first comparable value. - if ((value = values[i]) != null && value >= value) { - max = value; - while (++i < n) { // Compare the remaining values. - if ((value = values[i]) != null && value > max) { - max = value; - } - } - } - } - } - - else { - while (++i < n) { // Find the first comparable value. - if ((value = valueof(values[i], i, values)) != null && value >= value) { - max = value; - while (++i < n) { // Compare the remaining values. - if ((value = valueof(values[i], i, values)) != null && value > max) { - max = value; - } - } - } - } - } - - return max; -}; - -var mean = function(values, valueof) { - var n = values.length, - m = n, - i = -1, - value, - sum = 0; - - if (valueof == null) { - while (++i < n) { - if (!isNaN(value = number(values[i]))) sum += value; - else --m; - } - } - - else { - while (++i < n) { - if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value; - else --m; - } - } - - if (m) return sum / m; -}; - -var median = function(values, valueof) { - var n = values.length, - i = -1, - value, - numbers = []; - - if (valueof == null) { - while (++i < n) { - if (!isNaN(value = number(values[i]))) { - numbers.push(value); - } - } - } - - else { - while (++i < n) { - if (!isNaN(value = number(valueof(values[i], i, values)))) { - numbers.push(value); - } - } - } - - return threshold(numbers.sort(ascending), 0.5); -}; - -var merge = function(arrays) { - var n = arrays.length, - m, - i = -1, - j = 0, - merged, - array; - - while (++i < n) j += arrays[i].length; - merged = new Array(j); - - while (--n >= 0) { - array = arrays[n]; - m = array.length; - while (--m >= 0) { - merged[--j] = array[m]; - } - } - - return merged; -}; - -var min = function(values, valueof) { - var n = values.length, - i = -1, - value, - min; - - if (valueof == null) { - while (++i < n) { // Find the first comparable value. - if ((value = values[i]) != null && value >= value) { - min = value; - while (++i < n) { // Compare the remaining values. - if ((value = values[i]) != null && min > value) { - min = value; - } - } - } - } - } - - else { - while (++i < n) { // Find the first comparable value. - if ((value = valueof(values[i], i, values)) != null && value >= value) { - min = value; - while (++i < n) { // Compare the remaining values. - if ((value = valueof(values[i], i, values)) != null && min > value) { - min = value; - } - } - } - } - } - - return min; -}; - -var permute = function(array, indexes) { - var i = indexes.length, permutes = new Array(i); - while (i--) permutes[i] = array[indexes[i]]; - return permutes; -}; - -var scan = function(values, compare) { - if (!(n = values.length)) return; - var n, - i = 0, - j = 0, - xi, - xj = values[j]; - - if (compare == null) compare = ascending; - - while (++i < n) { - if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { - xj = xi, j = i; - } - } - - if (compare(xj, xj) === 0) return j; -}; - -var shuffle = function(array, i0, i1) { - var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), - t, - i; - - while (m) { - i = Math.random() * m-- | 0; - t = array[m + i0]; - array[m + i0] = array[i + i0]; - array[i + i0] = t; - } - - return array; -}; - -var sum = function(values, valueof) { - var n = values.length, - i = -1, - value, - sum = 0; - - if (valueof == null) { - while (++i < n) { - if (value = +values[i]) sum += value; // Note: zero and null are equivalent. - } - } - - else { - while (++i < n) { - if (value = +valueof(values[i], i, values)) sum += value; - } - } - - return sum; -}; - -var transpose = function(matrix) { - if (!(n = matrix.length)) return []; - for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { - for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { - row[j] = matrix[j][i]; - } - } - return transpose; -}; - -function length(d) { - return d.length; -} - -var zip = function() { - return transpose(arguments); -}; - -var slice$1 = Array.prototype.slice; - -var identity$1 = function(x) { - return x; -}; - -var top = 1; -var right = 2; -var bottom = 3; -var left = 4; -var epsilon = 1e-6; - -function translateX(x) { - return "translate(" + (x + 0.5) + ",0)"; -} - -function translateY(y) { - return "translate(0," + (y + 0.5) + ")"; -} - -function number$1(scale) { - return function(d) { - return +scale(d); - }; -} - -function center(scale) { - var offset = Math.max(0, scale.bandwidth() - 1) / 2; // Adjust for 0.5px offset. - if (scale.round()) offset = Math.round(offset); - return function(d) { - return +scale(d) + offset; - }; -} - -function entering() { - return !this.__axis; -} - -function axis(orient, scale) { - var tickArguments = [], - tickValues = null, - tickFormat = null, - tickSizeInner = 6, - tickSizeOuter = 6, - tickPadding = 3, - k = orient === top || orient === left ? -1 : 1, - x = orient === left || orient === right ? "x" : "y", - transform = orient === top || orient === bottom ? translateX : translateY; - - function axis(context) { - var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues, - format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$1) : tickFormat, - spacing = Math.max(tickSizeInner, 0) + tickPadding, - range = scale.range(), - range0 = +range[0] + 0.5, - range1 = +range[range.length - 1] + 0.5, - position = (scale.bandwidth ? center : number$1)(scale.copy()), - selection = context.selection ? context.selection() : context, - path = selection.selectAll(".domain").data([null]), - tick = selection.selectAll(".tick").data(values, scale).order(), - tickExit = tick.exit(), - tickEnter = tick.enter().append("g").attr("class", "tick"), - line = tick.select("line"), - text = tick.select("text"); - - path = path.merge(path.enter().insert("path", ".tick") - .attr("class", "domain") - .attr("stroke", "#000")); - - tick = tick.merge(tickEnter); - - line = line.merge(tickEnter.append("line") - .attr("stroke", "#000") - .attr(x + "2", k * tickSizeInner)); - - text = text.merge(tickEnter.append("text") - .attr("fill", "#000") - .attr(x, k * spacing) - .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em")); - - if (context !== selection) { - path = path.transition(context); - tick = tick.transition(context); - line = line.transition(context); - text = text.transition(context); - - tickExit = tickExit.transition(context) - .attr("opacity", epsilon) - .attr("transform", function(d) { return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); }); - - tickEnter - .attr("opacity", epsilon) - .attr("transform", function(d) { var p = this.parentNode.__axis; return transform(p && isFinite(p = p(d)) ? p : position(d)); }); - } - - tickExit.remove(); - - path - .attr("d", orient === left || orient == right - ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter - : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter); - - tick - .attr("opacity", 1) - .attr("transform", function(d) { return transform(position(d)); }); - - line - .attr(x + "2", k * tickSizeInner); - - text - .attr(x, k * spacing) - .text(format); - - selection.filter(entering) - .attr("fill", "none") - .attr("font-size", 10) - .attr("font-family", "sans-serif") - .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); - - selection - .each(function() { this.__axis = position; }); - } - - axis.scale = function(_) { - return arguments.length ? (scale = _, axis) : scale; - }; - - axis.ticks = function() { - return tickArguments = slice$1.call(arguments), axis; - }; - - axis.tickArguments = function(_) { - return arguments.length ? (tickArguments = _ == null ? [] : slice$1.call(_), axis) : tickArguments.slice(); - }; - - axis.tickValues = function(_) { - return arguments.length ? (tickValues = _ == null ? null : slice$1.call(_), axis) : tickValues && tickValues.slice(); - }; - - axis.tickFormat = function(_) { - return arguments.length ? (tickFormat = _, axis) : tickFormat; - }; - - axis.tickSize = function(_) { - return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; - }; - - axis.tickSizeInner = function(_) { - return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; - }; - - axis.tickSizeOuter = function(_) { - return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; - }; - - axis.tickPadding = function(_) { - return arguments.length ? (tickPadding = +_, axis) : tickPadding; - }; - - return axis; -} - -function axisTop(scale) { - return axis(top, scale); -} - -function axisRight(scale) { - return axis(right, scale); -} - -function axisBottom(scale) { - return axis(bottom, scale); -} - -function axisLeft(scale) { - return axis(left, scale); -} - -var noop = {value: function() {}}; - -function dispatch() { - for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { - if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); - _[t] = []; - } - return new Dispatch(_); -} - -function Dispatch(_) { - this._ = _; -} - -function parseTypenames(typenames, types) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); - return {type: t, name: name}; - }); -} - -Dispatch.prototype = dispatch.prototype = { - constructor: Dispatch, - on: function(typename, callback) { - var _ = this._, - T = parseTypenames(typename + "", _), - t, - i = -1, - n = T.length; - - // If no callback was specified, return the callback of the given type and name. - if (arguments.length < 2) { - while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; - return; - } - - // If a type was specified, set the callback for the given type and name. - // Otherwise, if a null callback was specified, remove callbacks of the given name. - if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); - while (++i < n) { - if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback); - else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null); - } - - return this; - }, - copy: function() { - var copy = {}, _ = this._; - for (var t in _) copy[t] = _[t].slice(); - return new Dispatch(copy); - }, - call: function(type, that) { - if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - }, - apply: function(type, that, args) { - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - } -}; - -function get(type, name) { - for (var i = 0, n = type.length, c; i < n; ++i) { - if ((c = type[i]).name === name) { - return c.value; - } - } -} - -function set(type, name, callback) { - for (var i = 0, n = type.length; i < n; ++i) { - if (type[i].name === name) { - type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); - break; - } - } - if (callback != null) type.push({name: name, value: callback}); - return type; -} - -var xhtml = "http://www.w3.org/1999/xhtml"; - -var namespaces = { - svg: "http://www.w3.org/2000/svg", - xhtml: xhtml, - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" -}; - -var namespace = function(name) { - var prefix = name += "", i = prefix.indexOf(":"); - if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); - return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; -}; - -function creatorInherit(name) { - return function() { - var document = this.ownerDocument, - uri = this.namespaceURI; - return uri === xhtml && document.documentElement.namespaceURI === xhtml - ? document.createElement(name) - : document.createElementNS(uri, name); - }; -} - -function creatorFixed(fullname) { - return function() { - return this.ownerDocument.createElementNS(fullname.space, fullname.local); - }; -} - -var creator = function(name) { - var fullname = namespace(name); - return (fullname.local - ? creatorFixed - : creatorInherit)(fullname); -}; - -var nextId = 0; - -function local$1() { - return new Local; -} - -function Local() { - this._ = "@" + (++nextId).toString(36); -} - -Local.prototype = local$1.prototype = { - constructor: Local, - get: function(node) { - var id = this._; - while (!(id in node)) if (!(node = node.parentNode)) return; - return node[id]; - }, - set: function(node, value) { - return node[this._] = value; - }, - remove: function(node) { - return this._ in node && delete node[this._]; - }, - toString: function() { - return this._; - } -}; - -var matcher = function(selector) { - return function() { - return this.matches(selector); - }; -}; - -if (typeof document !== "undefined") { - var element = document.documentElement; - if (!element.matches) { - var vendorMatches = element.webkitMatchesSelector - || element.msMatchesSelector - || element.mozMatchesSelector - || element.oMatchesSelector; - matcher = function(selector) { - return function() { - return vendorMatches.call(this, selector); - }; - }; - } -} - -var matcher$1 = matcher; - -var filterEvents = {}; - -exports.event = null; - -if (typeof document !== "undefined") { - var element$1 = document.documentElement; - if (!("onmouseenter" in element$1)) { - filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; - } -} - -function filterContextListener(listener, index, group) { - listener = contextListener(listener, index, group); - return function(event) { - var related = event.relatedTarget; - if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { - listener.call(this, event); - } - }; -} - -function contextListener(listener, index, group) { - return function(event1) { - var event0 = exports.event; // Events can be reentrant (e.g., focus). - exports.event = event1; - try { - listener.call(this, this.__data__, index, group); - } finally { - exports.event = event0; - } - }; -} - -function parseTypenames$1(typenames) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - return {type: t, name: name}; - }); -} - -function onRemove(typename) { - return function() { - var on = this.__on; - if (!on) return; - for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { - if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { - this.removeEventListener(o.type, o.listener, o.capture); - } else { - on[++i] = o; - } - } - if (++i) on.length = i; - else delete this.__on; - }; -} - -function onAdd(typename, value, capture) { - var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; - return function(d, i, group) { - var on = this.__on, o, listener = wrap(value, i, group); - if (on) for (var j = 0, m = on.length; j < m; ++j) { - if ((o = on[j]).type === typename.type && o.name === typename.name) { - this.removeEventListener(o.type, o.listener, o.capture); - this.addEventListener(o.type, o.listener = listener, o.capture = capture); - o.value = value; - return; - } - } - this.addEventListener(typename.type, listener, capture); - o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; - if (!on) this.__on = [o]; - else on.push(o); - }; -} - -var selection_on = function(typename, value, capture) { - var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t; - - if (arguments.length < 2) { - var on = this.node().__on; - if (on) for (var j = 0, m = on.length, o; j < m; ++j) { - for (i = 0, o = on[j]; i < n; ++i) { - if ((t = typenames[i]).type === o.type && t.name === o.name) { - return o.value; - } - } - } - return; - } - - on = value ? onAdd : onRemove; - if (capture == null) capture = false; - for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); - return this; -}; - -function customEvent(event1, listener, that, args) { - var event0 = exports.event; - event1.sourceEvent = exports.event; - exports.event = event1; - try { - return listener.apply(that, args); - } finally { - exports.event = event0; - } -} - -var sourceEvent = function() { - var current = exports.event, source; - while (source = current.sourceEvent) current = source; - return current; -}; - -var point = function(node, event) { - var svg = node.ownerSVGElement || node; - - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - point.x = event.clientX, point.y = event.clientY; - point = point.matrixTransform(node.getScreenCTM().inverse()); - return [point.x, point.y]; - } - - var rect = node.getBoundingClientRect(); - return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; -}; - -var mouse = function(node) { - var event = sourceEvent(); - if (event.changedTouches) event = event.changedTouches[0]; - return point(node, event); -}; - -function none() {} - -var selector = function(selector) { - return selector == null ? none : function() { - return this.querySelector(selector); - }; -}; - -var selection_select = function(select) { - if (typeof select !== "function") select = selector(select); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { - if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - subgroup[i] = subnode; - } - } - } - - return new Selection(subgroups, this._parents); -}; - -function empty$1() { - return []; -} - -var selectorAll = function(selector) { - return selector == null ? empty$1 : function() { - return this.querySelectorAll(selector); - }; -}; - -var selection_selectAll = function(select) { - if (typeof select !== "function") select = selectorAll(select); - - for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - subgroups.push(select.call(node, node.__data__, i, group)); - parents.push(node); - } - } - } - - return new Selection(subgroups, parents); -}; - -var selection_filter = function(match) { - if (typeof match !== "function") match = matcher$1(match); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { - if ((node = group[i]) && match.call(node, node.__data__, i, group)) { - subgroup.push(node); - } - } - } - - return new Selection(subgroups, this._parents); -}; - -var sparse = function(update) { - return new Array(update.length); -}; - -var selection_enter = function() { - return new Selection(this._enter || this._groups.map(sparse), this._parents); -}; - -function EnterNode(parent, datum) { - this.ownerDocument = parent.ownerDocument; - this.namespaceURI = parent.namespaceURI; - this._next = null; - this._parent = parent; - this.__data__ = datum; -} - -EnterNode.prototype = { - constructor: EnterNode, - appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, - insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, - querySelector: function(selector) { return this._parent.querySelector(selector); }, - querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } -}; - -var constant$1 = function(x) { - return function() { - return x; - }; -}; - -var keyPrefix = "$"; // Protect against keys like “__proto__”. - -function bindIndex(parent, group, enter, update, exit, data) { - var i = 0, - node, - groupLength = group.length, - dataLength = data.length; - - // Put any non-null nodes that fit into update. - // Put any null nodes into enter. - // Put any remaining data into enter. - for (; i < dataLength; ++i) { - if (node = group[i]) { - node.__data__ = data[i]; - update[i] = node; - } else { - enter[i] = new EnterNode(parent, data[i]); - } - } - - // Put any non-null nodes that don’t fit into exit. - for (; i < groupLength; ++i) { - if (node = group[i]) { - exit[i] = node; - } - } -} - -function bindKey(parent, group, enter, update, exit, data, key) { - var i, - node, - nodeByKeyValue = {}, - groupLength = group.length, - dataLength = data.length, - keyValues = new Array(groupLength), - keyValue; - - // Compute the key for each node. - // If multiple nodes have the same key, the duplicates are added to exit. - for (i = 0; i < groupLength; ++i) { - if (node = group[i]) { - keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); - if (keyValue in nodeByKeyValue) { - exit[i] = node; - } else { - nodeByKeyValue[keyValue] = node; - } - } - } - - // Compute the key for each datum. - // If there a node associated with this key, join and add it to update. - // If there is not (or the key is a duplicate), add it to enter. - for (i = 0; i < dataLength; ++i) { - keyValue = keyPrefix + key.call(parent, data[i], i, data); - if (node = nodeByKeyValue[keyValue]) { - update[i] = node; - node.__data__ = data[i]; - nodeByKeyValue[keyValue] = null; - } else { - enter[i] = new EnterNode(parent, data[i]); - } - } - - // Add any remaining nodes that were not bound to data to exit. - for (i = 0; i < groupLength; ++i) { - if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { - exit[i] = node; - } - } -} - -var selection_data = function(value, key) { - if (!value) { - data = new Array(this.size()), j = -1; - this.each(function(d) { data[++j] = d; }); - return data; - } - - var bind = key ? bindKey : bindIndex, - parents = this._parents, - groups = this._groups; - - if (typeof value !== "function") value = constant$1(value); - - for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { - var parent = parents[j], - group = groups[j], - groupLength = group.length, - data = value.call(parent, parent && parent.__data__, j, parents), - dataLength = data.length, - enterGroup = enter[j] = new Array(dataLength), - updateGroup = update[j] = new Array(dataLength), - exitGroup = exit[j] = new Array(groupLength); - - bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); - - // Now connect the enter nodes to their following update node, such that - // appendChild can insert the materialized enter node before this node, - // rather than at the end of the parent node. - for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { - if (previous = enterGroup[i0]) { - if (i0 >= i1) i1 = i0 + 1; - while (!(next = updateGroup[i1]) && ++i1 < dataLength); - previous._next = next || null; - } - } - } - - update = new Selection(update, parents); - update._enter = enter; - update._exit = exit; - return update; -}; - -var selection_exit = function() { - return new Selection(this._exit || this._groups.map(sparse), this._parents); -}; - -var selection_merge = function(selection$$1) { - - for (var groups0 = this._groups, groups1 = selection$$1._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { - for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group0[i] || group1[i]) { - merge[i] = node; - } - } - } - - for (; j < m0; ++j) { - merges[j] = groups0[j]; - } - - return new Selection(merges, this._parents); -}; - -var selection_order = function() { - - for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { - for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) { - if (node = group[i]) { - if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - - return this; -}; - -var selection_sort = function(compare) { - if (!compare) compare = ascending$1; - - function compareNode(a, b) { - return a && b ? compare(a.__data__, b.__data__) : !a - !b; - } - - for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group[i]) { - sortgroup[i] = node; - } - } - sortgroup.sort(compareNode); - } - - return new Selection(sortgroups, this._parents).order(); -}; - -function ascending$1(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; -} - -var selection_call = function() { - var callback = arguments[0]; - arguments[0] = this; - callback.apply(null, arguments); - return this; -}; - -var selection_nodes = function() { - var nodes = new Array(this.size()), i = -1; - this.each(function() { nodes[++i] = this; }); - return nodes; -}; - -var selection_node = function() { - - for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { - for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { - var node = group[i]; - if (node) return node; - } - } - - return null; -}; - -var selection_size = function() { - var size = 0; - this.each(function() { ++size; }); - return size; -}; - -var selection_empty = function() { - return !this.node(); -}; - -var selection_each = function(callback) { - - for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { - if (node = group[i]) callback.call(node, node.__data__, i, group); - } - } - - return this; -}; - -function attrRemove(name) { - return function() { - this.removeAttribute(name); - }; -} - -function attrRemoveNS(fullname) { - return function() { - this.removeAttributeNS(fullname.space, fullname.local); - }; -} - -function attrConstant(name, value) { - return function() { - this.setAttribute(name, value); - }; -} - -function attrConstantNS(fullname, value) { - return function() { - this.setAttributeNS(fullname.space, fullname.local, value); - }; -} - -function attrFunction(name, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.removeAttribute(name); - else this.setAttribute(name, v); - }; -} - -function attrFunctionNS(fullname, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.removeAttributeNS(fullname.space, fullname.local); - else this.setAttributeNS(fullname.space, fullname.local, v); - }; -} - -var selection_attr = function(name, value) { - var fullname = namespace(name); - - if (arguments.length < 2) { - var node = this.node(); - return fullname.local - ? node.getAttributeNS(fullname.space, fullname.local) - : node.getAttribute(fullname); - } - - return this.each((value == null - ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" - ? (fullname.local ? attrFunctionNS : attrFunction) - : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); -}; - -var defaultView = function(node) { - return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node - || (node.document && node) // node is a Window - || node.defaultView; // node is a Document -}; - -function styleRemove(name) { - return function() { - this.style.removeProperty(name); - }; -} - -function styleConstant(name, value, priority) { - return function() { - this.style.setProperty(name, value, priority); - }; -} - -function styleFunction(name, value, priority) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.style.removeProperty(name); - else this.style.setProperty(name, v, priority); - }; -} - -var selection_style = function(name, value, priority) { - return arguments.length > 1 - ? this.each((value == null - ? styleRemove : typeof value === "function" - ? styleFunction - : styleConstant)(name, value, priority == null ? "" : priority)) - : styleValue(this.node(), name); -}; - -function styleValue(node, name) { - return node.style.getPropertyValue(name) - || defaultView(node).getComputedStyle(node, null).getPropertyValue(name); -} - -function propertyRemove(name) { - return function() { - delete this[name]; - }; -} - -function propertyConstant(name, value) { - return function() { - this[name] = value; - }; -} - -function propertyFunction(name, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) delete this[name]; - else this[name] = v; - }; -} - -var selection_property = function(name, value) { - return arguments.length > 1 - ? this.each((value == null - ? propertyRemove : typeof value === "function" - ? propertyFunction - : propertyConstant)(name, value)) - : this.node()[name]; -}; - -function classArray(string) { - return string.trim().split(/^|\s+/); -} - -function classList(node) { - return node.classList || new ClassList(node); -} - -function ClassList(node) { - this._node = node; - this._names = classArray(node.getAttribute("class") || ""); -} - -ClassList.prototype = { - add: function(name) { - var i = this._names.indexOf(name); - if (i < 0) { - this._names.push(name); - this._node.setAttribute("class", this._names.join(" ")); - } - }, - remove: function(name) { - var i = this._names.indexOf(name); - if (i >= 0) { - this._names.splice(i, 1); - this._node.setAttribute("class", this._names.join(" ")); - } - }, - contains: function(name) { - return this._names.indexOf(name) >= 0; - } -}; - -function classedAdd(node, names) { - var list = classList(node), i = -1, n = names.length; - while (++i < n) list.add(names[i]); -} - -function classedRemove(node, names) { - var list = classList(node), i = -1, n = names.length; - while (++i < n) list.remove(names[i]); -} - -function classedTrue(names) { - return function() { - classedAdd(this, names); - }; -} - -function classedFalse(names) { - return function() { - classedRemove(this, names); - }; -} - -function classedFunction(names, value) { - return function() { - (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); - }; -} - -var selection_classed = function(name, value) { - var names = classArray(name + ""); - - if (arguments.length < 2) { - var list = classList(this.node()), i = -1, n = names.length; - while (++i < n) if (!list.contains(names[i])) return false; - return true; - } - - return this.each((typeof value === "function" - ? classedFunction : value - ? classedTrue - : classedFalse)(names, value)); -}; - -function textRemove() { - this.textContent = ""; -} - -function textConstant(value) { - return function() { - this.textContent = value; - }; -} - -function textFunction(value) { - return function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - }; -} - -var selection_text = function(value) { - return arguments.length - ? this.each(value == null - ? textRemove : (typeof value === "function" - ? textFunction - : textConstant)(value)) - : this.node().textContent; -}; - -function htmlRemove() { - this.innerHTML = ""; -} - -function htmlConstant(value) { - return function() { - this.innerHTML = value; - }; -} - -function htmlFunction(value) { - return function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - }; -} - -var selection_html = function(value) { - return arguments.length - ? this.each(value == null - ? htmlRemove : (typeof value === "function" - ? htmlFunction - : htmlConstant)(value)) - : this.node().innerHTML; -}; - -function raise() { - if (this.nextSibling) this.parentNode.appendChild(this); -} - -var selection_raise = function() { - return this.each(raise); -}; - -function lower() { - if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); -} - -var selection_lower = function() { - return this.each(lower); -}; - -var selection_append = function(name) { - var create = typeof name === "function" ? name : creator(name); - return this.select(function() { - return this.appendChild(create.apply(this, arguments)); - }); -}; - -function constantNull() { - return null; -} - -var selection_insert = function(name, before) { - var create = typeof name === "function" ? name : creator(name), - select = before == null ? constantNull : typeof before === "function" ? before : selector(before); - return this.select(function() { - return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); - }); -}; - -function remove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); -} - -var selection_remove = function() { - return this.each(remove); -}; - -var selection_datum = function(value) { - return arguments.length - ? this.property("__data__", value) - : this.node().__data__; -}; - -function dispatchEvent(node, type, params) { - var window = defaultView(node), - event = window.CustomEvent; - - if (typeof event === "function") { - event = new event(type, params); - } else { - event = window.document.createEvent("Event"); - if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; - else event.initEvent(type, false, false); - } - - node.dispatchEvent(event); -} - -function dispatchConstant(type, params) { - return function() { - return dispatchEvent(this, type, params); - }; -} - -function dispatchFunction(type, params) { - return function() { - return dispatchEvent(this, type, params.apply(this, arguments)); - }; -} - -var selection_dispatch = function(type, params) { - return this.each((typeof params === "function" - ? dispatchFunction - : dispatchConstant)(type, params)); -}; - -var root = [null]; - -function Selection(groups, parents) { - this._groups = groups; - this._parents = parents; -} - -function selection() { - return new Selection([[document.documentElement]], root); -} - -Selection.prototype = selection.prototype = { - constructor: Selection, - select: selection_select, - selectAll: selection_selectAll, - filter: selection_filter, - data: selection_data, - enter: selection_enter, - exit: selection_exit, - merge: selection_merge, - order: selection_order, - sort: selection_sort, - call: selection_call, - nodes: selection_nodes, - node: selection_node, - size: selection_size, - empty: selection_empty, - each: selection_each, - attr: selection_attr, - style: selection_style, - property: selection_property, - classed: selection_classed, - text: selection_text, - html: selection_html, - raise: selection_raise, - lower: selection_lower, - append: selection_append, - insert: selection_insert, - remove: selection_remove, - datum: selection_datum, - on: selection_on, - dispatch: selection_dispatch -}; - -var select = function(selector) { - return typeof selector === "string" - ? new Selection([[document.querySelector(selector)]], [document.documentElement]) - : new Selection([[selector]], root); -}; - -var selectAll = function(selector) { - return typeof selector === "string" - ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) - : new Selection([selector == null ? [] : selector], root); -}; - -var touch = function(node, touches, identifier) { - if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches; - - for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { - if ((touch = touches[i]).identifier === identifier) { - return point(node, touch); - } - } - - return null; -}; - -var touches = function(node, touches) { - if (touches == null) touches = sourceEvent().touches; - - for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) { - points[i] = point(node, touches[i]); - } - - return points; -}; - -function nopropagation() { - exports.event.stopImmediatePropagation(); -} - -var noevent = function() { - exports.event.preventDefault(); - exports.event.stopImmediatePropagation(); -}; - -var dragDisable = function(view) { - var root = view.document.documentElement, - selection = select(view).on("dragstart.drag", noevent, true); - if ("onselectstart" in root) { - selection.on("selectstart.drag", noevent, true); - } else { - root.__noselect = root.style.MozUserSelect; - root.style.MozUserSelect = "none"; - } -}; - -function yesdrag(view, noclick) { - var root = view.document.documentElement, - selection = select(view).on("dragstart.drag", null); - if (noclick) { - selection.on("click.drag", noevent, true); - setTimeout(function() { selection.on("click.drag", null); }, 0); - } - if ("onselectstart" in root) { - selection.on("selectstart.drag", null); - } else { - root.style.MozUserSelect = root.__noselect; - delete root.__noselect; - } -} - -var constant$2 = function(x) { - return function() { - return x; - }; -}; - -function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) { - this.target = target; - this.type = type; - this.subject = subject; - this.identifier = id; - this.active = active; - this.x = x; - this.y = y; - this.dx = dx; - this.dy = dy; - this._ = dispatch; -} - -DragEvent.prototype.on = function() { - var value = this._.on.apply(this._, arguments); - return value === this._ ? this : value; -}; - -// Ignore right-click, since that should open the context menu. -function defaultFilter$1() { - return !exports.event.button; -} - -function defaultContainer() { - return this.parentNode; -} - -function defaultSubject(d) { - return d == null ? {x: exports.event.x, y: exports.event.y} : d; -} - -function defaultTouchable() { - return "ontouchstart" in this; -} - -var drag = function() { - var filter = defaultFilter$1, - container = defaultContainer, - subject = defaultSubject, - touchable = defaultTouchable, - gestures = {}, - listeners = dispatch("start", "drag", "end"), - active = 0, - mousedownx, - mousedowny, - mousemoving, - touchending, - clickDistance2 = 0; - - function drag(selection) { - selection - .on("mousedown.drag", mousedowned) - .filter(touchable) - .on("touchstart.drag", touchstarted) - .on("touchmove.drag", touchmoved) - .on("touchend.drag touchcancel.drag", touchended) - .style("touch-action", "none") - .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); - } - - function mousedowned() { - if (touchending || !filter.apply(this, arguments)) return; - var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments); - if (!gesture) return; - select(exports.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); - dragDisable(exports.event.view); - nopropagation(); - mousemoving = false; - mousedownx = exports.event.clientX; - mousedowny = exports.event.clientY; - gesture("start"); - } - - function mousemoved() { - noevent(); - if (!mousemoving) { - var dx = exports.event.clientX - mousedownx, dy = exports.event.clientY - mousedowny; - mousemoving = dx * dx + dy * dy > clickDistance2; - } - gestures.mouse("drag"); - } - - function mouseupped() { - select(exports.event.view).on("mousemove.drag mouseup.drag", null); - yesdrag(exports.event.view, mousemoving); - noevent(); - gestures.mouse("end"); - } - - function touchstarted() { - if (!filter.apply(this, arguments)) return; - var touches = exports.event.changedTouches, - c = container.apply(this, arguments), - n = touches.length, i, gesture; - - for (i = 0; i < n; ++i) { - if (gesture = beforestart(touches[i].identifier, c, touch, this, arguments)) { - nopropagation(); - gesture("start"); - } - } - } - - function touchmoved() { - var touches = exports.event.changedTouches, - n = touches.length, i, gesture; - - for (i = 0; i < n; ++i) { - if (gesture = gestures[touches[i].identifier]) { - noevent(); - gesture("drag"); - } - } - } - - function touchended() { - var touches = exports.event.changedTouches, - n = touches.length, i, gesture; - - if (touchending) clearTimeout(touchending); - touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! - for (i = 0; i < n; ++i) { - if (gesture = gestures[touches[i].identifier]) { - nopropagation(); - gesture("end"); - } - } - } - - function beforestart(id, container, point, that, args) { - var p = point(container, id), s, dx, dy, - sublisteners = listeners.copy(); - - if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() { - if ((exports.event.subject = s = subject.apply(that, args)) == null) return false; - dx = s.x - p[0] || 0; - dy = s.y - p[1] || 0; - return true; - })) return; - - return function gesture(type) { - var p0 = p, n; - switch (type) { - case "start": gestures[id] = gesture, n = active++; break; - case "end": delete gestures[id], --active; // nobreak - case "drag": p = point(container, id), n = active; break; - } - customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); - }; - } - - drag.filter = function(_) { - return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter; - }; - - drag.container = function(_) { - return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container; - }; - - drag.subject = function(_) { - return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject; - }; - - drag.touchable = function(_) { - return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$2(!!_), drag) : touchable; - }; - - drag.on = function() { - var value = listeners.on.apply(listeners, arguments); - return value === listeners ? drag : value; - }; - - drag.clickDistance = function(_) { - return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); - }; - - return drag; -}; - -var define = function(constructor, factory, prototype) { - constructor.prototype = factory.prototype = prototype; - prototype.constructor = constructor; -}; - -function extend(parent, definition) { - var prototype = Object.create(parent.prototype); - for (var key in definition) prototype[key] = definition[key]; - return prototype; -} - -function Color() {} - -var darker = 0.7; -var brighter = 1 / darker; - -var reI = "\\s*([+-]?\\d+)\\s*"; -var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*"; -var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*"; -var reHex3 = /^#([0-9a-f]{3})$/; -var reHex6 = /^#([0-9a-f]{6})$/; -var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"); -var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"); -var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"); -var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"); -var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"); -var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); - -var named = { - aliceblue: 0xf0f8ff, - antiquewhite: 0xfaebd7, - aqua: 0x00ffff, - aquamarine: 0x7fffd4, - azure: 0xf0ffff, - beige: 0xf5f5dc, - bisque: 0xffe4c4, - black: 0x000000, - blanchedalmond: 0xffebcd, - blue: 0x0000ff, - blueviolet: 0x8a2be2, - brown: 0xa52a2a, - burlywood: 0xdeb887, - cadetblue: 0x5f9ea0, - chartreuse: 0x7fff00, - chocolate: 0xd2691e, - coral: 0xff7f50, - cornflowerblue: 0x6495ed, - cornsilk: 0xfff8dc, - crimson: 0xdc143c, - cyan: 0x00ffff, - darkblue: 0x00008b, - darkcyan: 0x008b8b, - darkgoldenrod: 0xb8860b, - darkgray: 0xa9a9a9, - darkgreen: 0x006400, - darkgrey: 0xa9a9a9, - darkkhaki: 0xbdb76b, - darkmagenta: 0x8b008b, - darkolivegreen: 0x556b2f, - darkorange: 0xff8c00, - darkorchid: 0x9932cc, - darkred: 0x8b0000, - darksalmon: 0xe9967a, - darkseagreen: 0x8fbc8f, - darkslateblue: 0x483d8b, - darkslategray: 0x2f4f4f, - darkslategrey: 0x2f4f4f, - darkturquoise: 0x00ced1, - darkviolet: 0x9400d3, - deeppink: 0xff1493, - deepskyblue: 0x00bfff, - dimgray: 0x696969, - dimgrey: 0x696969, - dodgerblue: 0x1e90ff, - firebrick: 0xb22222, - floralwhite: 0xfffaf0, - forestgreen: 0x228b22, - fuchsia: 0xff00ff, - gainsboro: 0xdcdcdc, - ghostwhite: 0xf8f8ff, - gold: 0xffd700, - goldenrod: 0xdaa520, - gray: 0x808080, - green: 0x008000, - greenyellow: 0xadff2f, - grey: 0x808080, - honeydew: 0xf0fff0, - hotpink: 0xff69b4, - indianred: 0xcd5c5c, - indigo: 0x4b0082, - ivory: 0xfffff0, - khaki: 0xf0e68c, - lavender: 0xe6e6fa, - lavenderblush: 0xfff0f5, - lawngreen: 0x7cfc00, - lemonchiffon: 0xfffacd, - lightblue: 0xadd8e6, - lightcoral: 0xf08080, - lightcyan: 0xe0ffff, - lightgoldenrodyellow: 0xfafad2, - lightgray: 0xd3d3d3, - lightgreen: 0x90ee90, - lightgrey: 0xd3d3d3, - lightpink: 0xffb6c1, - lightsalmon: 0xffa07a, - lightseagreen: 0x20b2aa, - lightskyblue: 0x87cefa, - lightslategray: 0x778899, - lightslategrey: 0x778899, - lightsteelblue: 0xb0c4de, - lightyellow: 0xffffe0, - lime: 0x00ff00, - limegreen: 0x32cd32, - linen: 0xfaf0e6, - magenta: 0xff00ff, - maroon: 0x800000, - mediumaquamarine: 0x66cdaa, - mediumblue: 0x0000cd, - mediumorchid: 0xba55d3, - mediumpurple: 0x9370db, - mediumseagreen: 0x3cb371, - mediumslateblue: 0x7b68ee, - mediumspringgreen: 0x00fa9a, - mediumturquoise: 0x48d1cc, - mediumvioletred: 0xc71585, - midnightblue: 0x191970, - mintcream: 0xf5fffa, - mistyrose: 0xffe4e1, - moccasin: 0xffe4b5, - navajowhite: 0xffdead, - navy: 0x000080, - oldlace: 0xfdf5e6, - olive: 0x808000, - olivedrab: 0x6b8e23, - orange: 0xffa500, - orangered: 0xff4500, - orchid: 0xda70d6, - palegoldenrod: 0xeee8aa, - palegreen: 0x98fb98, - paleturquoise: 0xafeeee, - palevioletred: 0xdb7093, - papayawhip: 0xffefd5, - peachpuff: 0xffdab9, - peru: 0xcd853f, - pink: 0xffc0cb, - plum: 0xdda0dd, - powderblue: 0xb0e0e6, - purple: 0x800080, - rebeccapurple: 0x663399, - red: 0xff0000, - rosybrown: 0xbc8f8f, - royalblue: 0x4169e1, - saddlebrown: 0x8b4513, - salmon: 0xfa8072, - sandybrown: 0xf4a460, - seagreen: 0x2e8b57, - seashell: 0xfff5ee, - sienna: 0xa0522d, - silver: 0xc0c0c0, - skyblue: 0x87ceeb, - slateblue: 0x6a5acd, - slategray: 0x708090, - slategrey: 0x708090, - snow: 0xfffafa, - springgreen: 0x00ff7f, - steelblue: 0x4682b4, - tan: 0xd2b48c, - teal: 0x008080, - thistle: 0xd8bfd8, - tomato: 0xff6347, - turquoise: 0x40e0d0, - violet: 0xee82ee, - wheat: 0xf5deb3, - white: 0xffffff, - whitesmoke: 0xf5f5f5, - yellow: 0xffff00, - yellowgreen: 0x9acd32 -}; - -define(Color, color, { - displayable: function() { - return this.rgb().displayable(); - }, - toString: function() { - return this.rgb() + ""; - } -}); - -function color(format) { - var m; - format = (format + "").trim().toLowerCase(); - return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 - : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 - : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) - : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) - : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) - : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) - : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) - : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) - : named.hasOwnProperty(format) ? rgbn(named[format]) - : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) - : null; -} - -function rgbn(n) { - return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); -} - -function rgba(r, g, b, a) { - if (a <= 0) r = g = b = NaN; - return new Rgb(r, g, b, a); -} - -function rgbConvert(o) { - if (!(o instanceof Color)) o = color(o); - if (!o) return new Rgb; - o = o.rgb(); - return new Rgb(o.r, o.g, o.b, o.opacity); -} - -function rgb(r, g, b, opacity) { - return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); -} - -function Rgb(r, g, b, opacity) { - this.r = +r; - this.g = +g; - this.b = +b; - this.opacity = +opacity; -} - -define(Rgb, rgb, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - rgb: function() { - return this; - }, - displayable: function() { - return (0 <= this.r && this.r <= 255) - && (0 <= this.g && this.g <= 255) - && (0 <= this.b && this.b <= 255) - && (0 <= this.opacity && this.opacity <= 1); - }, - toString: function() { - var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); - return (a === 1 ? "rgb(" : "rgba(") - + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " - + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " - + Math.max(0, Math.min(255, Math.round(this.b) || 0)) - + (a === 1 ? ")" : ", " + a + ")"); - } -})); - -function hsla(h, s, l, a) { - if (a <= 0) h = s = l = NaN; - else if (l <= 0 || l >= 1) h = s = NaN; - else if (s <= 0) h = NaN; - return new Hsl(h, s, l, a); -} - -function hslConvert(o) { - if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Color)) o = color(o); - if (!o) return new Hsl; - if (o instanceof Hsl) return o; - o = o.rgb(); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - h = NaN, - s = max - min, - l = (max + min) / 2; - if (s) { - if (r === max) h = (g - b) / s + (g < b) * 6; - else if (g === max) h = (b - r) / s + 2; - else h = (r - g) / s + 4; - s /= l < 0.5 ? max + min : 2 - max - min; - h *= 60; - } else { - s = l > 0 && l < 1 ? 0 : h; - } - return new Hsl(h, s, l, o.opacity); -} - -function hsl(h, s, l, opacity) { - return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); -} - -function Hsl(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; -} - -define(Hsl, hsl, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - rgb: function() { - var h = this.h % 360 + (this.h < 0) * 360, - s = isNaN(h) || isNaN(this.s) ? 0 : this.s, - l = this.l, - m2 = l + (l < 0.5 ? l : 1 - l) * s, - m1 = 2 * l - m2; - return new Rgb( - hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), - hsl2rgb(h, m1, m2), - hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), - this.opacity - ); - }, - displayable: function() { - return (0 <= this.s && this.s <= 1 || isNaN(this.s)) - && (0 <= this.l && this.l <= 1) - && (0 <= this.opacity && this.opacity <= 1); - } -})); - -/* From FvD 13.37, CSS Color Module Level 3 */ -function hsl2rgb(h, m1, m2) { - return (h < 60 ? m1 + (m2 - m1) * h / 60 - : h < 180 ? m2 - : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 - : m1) * 255; -} - -var deg2rad = Math.PI / 180; -var rad2deg = 180 / Math.PI; - -var Kn = 18; -var Xn = 0.950470; -var Yn = 1; -var Zn = 1.088830; -var t0 = 4 / 29; -var t1 = 6 / 29; -var t2 = 3 * t1 * t1; -var t3 = t1 * t1 * t1; - -function labConvert(o) { - if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); - if (o instanceof Hcl) { - var h = o.h * deg2rad; - return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); - } - if (!(o instanceof Rgb)) o = rgbConvert(o); - var b = rgb2xyz(o.r), - a = rgb2xyz(o.g), - l = rgb2xyz(o.b), - x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), - y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), - z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn); - return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); -} - -function lab(l, a, b, opacity) { - return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); -} - -function Lab(l, a, b, opacity) { - this.l = +l; - this.a = +a; - this.b = +b; - this.opacity = +opacity; -} - -define(Lab, lab, extend(Color, { - brighter: function(k) { - return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); - }, - darker: function(k) { - return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); - }, - rgb: function() { - var y = (this.l + 16) / 116, - x = isNaN(this.a) ? y : y + this.a / 500, - z = isNaN(this.b) ? y : y - this.b / 200; - y = Yn * lab2xyz(y); - x = Xn * lab2xyz(x); - z = Zn * lab2xyz(z); - return new Rgb( - xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB - xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), - xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z), - this.opacity - ); - } -})); - -function xyz2lab(t) { - return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; -} - -function lab2xyz(t) { - return t > t1 ? t * t * t : t2 * (t - t0); -} - -function xyz2rgb(x) { - return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); -} - -function rgb2xyz(x) { - return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); -} - -function hclConvert(o) { - if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); - if (!(o instanceof Lab)) o = labConvert(o); - var h = Math.atan2(o.b, o.a) * rad2deg; - return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); -} - -function hcl(h, c, l, opacity) { - return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); -} - -function Hcl(h, c, l, opacity) { - this.h = +h; - this.c = +c; - this.l = +l; - this.opacity = +opacity; -} - -define(Hcl, hcl, extend(Color, { - brighter: function(k) { - return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity); - }, - darker: function(k) { - return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity); - }, - rgb: function() { - return labConvert(this).rgb(); - } -})); - -var A = -0.14861; -var B = +1.78277; -var C = -0.29227; -var D = -0.90649; -var E = +1.97294; -var ED = E * D; -var EB = E * B; -var BC_DA = B * C - D * A; - -function cubehelixConvert(o) { - if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Rgb)) o = rgbConvert(o); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), - bl = b - l, - k = (E * (g - l) - C * bl) / D, - s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 - h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; - return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); -} - -function cubehelix(h, s, l, opacity) { - return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); -} - -function Cubehelix(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; -} - -define(Cubehelix, cubehelix, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Cubehelix(this.h, this.s, this.l * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Cubehelix(this.h, this.s, this.l * k, this.opacity); - }, - rgb: function() { - var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, - l = +this.l, - a = isNaN(this.s) ? 0 : this.s * l * (1 - l), - cosh = Math.cos(h), - sinh = Math.sin(h); - return new Rgb( - 255 * (l + a * (A * cosh + B * sinh)), - 255 * (l + a * (C * cosh + D * sinh)), - 255 * (l + a * (E * cosh)), - this.opacity - ); - } -})); - -function basis(t1, v0, v1, v2, v3) { - var t2 = t1 * t1, t3 = t2 * t1; - return ((1 - 3 * t1 + 3 * t2 - t3) * v0 - + (4 - 6 * t2 + 3 * t3) * v1 - + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 - + t3 * v3) / 6; -} - -var basis$1 = function(values) { - var n = values.length - 1; - return function(t) { - var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), - v1 = values[i], - v2 = values[i + 1], - v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, - v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; - return basis((t - i / n) * n, v0, v1, v2, v3); - }; -}; - -var basisClosed = function(values) { - var n = values.length; - return function(t) { - var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), - v0 = values[(i + n - 1) % n], - v1 = values[i % n], - v2 = values[(i + 1) % n], - v3 = values[(i + 2) % n]; - return basis((t - i / n) * n, v0, v1, v2, v3); - }; -}; - -var constant$3 = function(x) { - return function() { - return x; - }; -}; - -function linear(a, d) { - return function(t) { - return a + t * d; - }; -} - -function exponential(a, b, y) { - return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { - return Math.pow(a + t * b, y); - }; -} - -function hue(a, b) { - var d = b - a; - return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a); -} - -function gamma(y) { - return (y = +y) === 1 ? nogamma : function(a, b) { - return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a); - }; -} - -function nogamma(a, b) { - var d = b - a; - return d ? linear(a, d) : constant$3(isNaN(a) ? b : a); -} - -var interpolateRgb = (function rgbGamma(y) { - var color$$1 = gamma(y); - - function rgb$$1(start, end) { - var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r), - g = color$$1(start.g, end.g), - b = color$$1(start.b, end.b), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.r = r(t); - start.g = g(t); - start.b = b(t); - start.opacity = opacity(t); - return start + ""; - }; - } - - rgb$$1.gamma = rgbGamma; - - return rgb$$1; -})(1); - -function rgbSpline(spline) { - return function(colors) { - var n = colors.length, - r = new Array(n), - g = new Array(n), - b = new Array(n), - i, color$$1; - for (i = 0; i < n; ++i) { - color$$1 = rgb(colors[i]); - r[i] = color$$1.r || 0; - g[i] = color$$1.g || 0; - b[i] = color$$1.b || 0; - } - r = spline(r); - g = spline(g); - b = spline(b); - color$$1.opacity = 1; - return function(t) { - color$$1.r = r(t); - color$$1.g = g(t); - color$$1.b = b(t); - return color$$1 + ""; - }; - }; -} - -var rgbBasis = rgbSpline(basis$1); -var rgbBasisClosed = rgbSpline(basisClosed); - -var array$1 = function(a, b) { - var nb = b ? b.length : 0, - na = a ? Math.min(nb, a.length) : 0, - x = new Array(nb), - c = new Array(nb), - i; - - for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]); - for (; i < nb; ++i) c[i] = b[i]; - - return function(t) { - for (i = 0; i < na; ++i) c[i] = x[i](t); - return c; - }; -}; - -var date = function(a, b) { - var d = new Date; - return a = +a, b -= a, function(t) { - return d.setTime(a + b * t), d; - }; -}; - -var reinterpolate = function(a, b) { - return a = +a, b -= a, function(t) { - return a + b * t; - }; -}; - -var object = function(a, b) { - var i = {}, - c = {}, - k; - - if (a === null || typeof a !== "object") a = {}; - if (b === null || typeof b !== "object") b = {}; - - for (k in b) { - if (k in a) { - i[k] = interpolateValue(a[k], b[k]); - } else { - c[k] = b[k]; - } - } - - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; -}; - -var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; -var reB = new RegExp(reA.source, "g"); - -function zero(b) { - return function() { - return b; - }; -} - -function one(b) { - return function(t) { - return b(t) + ""; - }; -} - -var interpolateString = function(a, b) { - var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b - am, // current match in a - bm, // current match in b - bs, // string preceding current number in b, if any - i = -1, // index in s - s = [], // string constants and placeholders - q = []; // number interpolators - - // Coerce inputs to strings. - a = a + "", b = b + ""; - - // Interpolate pairs of numbers in a & b. - while ((am = reA.exec(a)) - && (bm = reB.exec(b))) { - if ((bs = bm.index) > bi) { // a string precedes the next number in b - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match - if (s[i]) s[i] += bm; // coalesce with previous string - else s[++i] = bm; - } else { // interpolate non-matching numbers - s[++i] = null; - q.push({i: i, x: reinterpolate(am, bm)}); - } - bi = reB.lastIndex; - } - - // Add remains of b. - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - - // Special optimization for only a single match. - // Otherwise, interpolate each of the numbers and rejoin the string. - return s.length < 2 ? (q[0] - ? one(q[0].x) - : zero(b)) - : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); -}; - -var interpolateValue = function(a, b) { - var t = typeof b, c; - return b == null || t === "boolean" ? constant$3(b) - : (t === "number" ? reinterpolate - : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString) - : b instanceof color ? interpolateRgb - : b instanceof Date ? date - : Array.isArray(b) ? array$1 - : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object - : reinterpolate)(a, b); -}; - -var interpolateRound = function(a, b) { - return a = +a, b -= a, function(t) { - return Math.round(a + b * t); - }; -}; - -var degrees = 180 / Math.PI; - -var identity$2 = { - translateX: 0, - translateY: 0, - rotate: 0, - skewX: 0, - scaleX: 1, - scaleY: 1 -}; - -var decompose = function(a, b, c, d, e, f) { - var scaleX, scaleY, skewX; - if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; - if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; - if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; - if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; - return { - translateX: e, - translateY: f, - rotate: Math.atan2(b, a) * degrees, - skewX: Math.atan(skewX) * degrees, - scaleX: scaleX, - scaleY: scaleY - }; -}; - -var cssNode; -var cssRoot; -var cssView; -var svgNode; - -function parseCss(value) { - if (value === "none") return identity$2; - if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; - cssNode.style.transform = value; - value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); - cssRoot.removeChild(cssNode); - value = value.slice(7, -1).split(","); - return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); -} - -function parseSvg(value) { - if (value == null) return identity$2; - if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); - svgNode.setAttribute("transform", value); - if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2; - value = value.matrix; - return decompose(value.a, value.b, value.c, value.d, value.e, value.f); -} - -function interpolateTransform(parse, pxComma, pxParen, degParen) { - - function pop(s) { - return s.length ? s.pop() + " " : ""; - } - - function translate(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push("translate(", null, pxComma, null, pxParen); - q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)}); - } else if (xb || yb) { - s.push("translate(" + xb + pxComma + yb + pxParen); - } - } - - function rotate(a, b, s, q) { - if (a !== b) { - if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path - q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: reinterpolate(a, b)}); - } else if (b) { - s.push(pop(s) + "rotate(" + b + degParen); - } - } - - function skewX(a, b, s, q) { - if (a !== b) { - q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: reinterpolate(a, b)}); - } else if (b) { - s.push(pop(s) + "skewX(" + b + degParen); - } - } - - function scale(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push(pop(s) + "scale(", null, ",", null, ")"); - q.push({i: i - 4, x: reinterpolate(xa, xb)}, {i: i - 2, x: reinterpolate(ya, yb)}); - } else if (xb !== 1 || yb !== 1) { - s.push(pop(s) + "scale(" + xb + "," + yb + ")"); - } - } - - return function(a, b) { - var s = [], // string constants and placeholders - q = []; // number interpolators - a = parse(a), b = parse(b); - translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); - rotate(a.rotate, b.rotate, s, q); - skewX(a.skewX, b.skewX, s, q); - scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); - a = b = null; // gc - return function(t) { - var i = -1, n = q.length, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - }; -} - -var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); -var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); - -var rho = Math.SQRT2; -var rho2 = 2; -var rho4 = 4; -var epsilon2 = 1e-12; - -function cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; -} - -function sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; -} - -function tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); -} - -// p0 = [ux0, uy0, w0] -// p1 = [ux1, uy1, w1] -var interpolateZoom = function(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], - ux1 = p1[0], uy1 = p1[1], w1 = p1[2], - dx = ux1 - ux0, - dy = uy1 - uy0, - d2 = dx * dx + dy * dy, - i, - S; - - // Special case for u0 ≅ u1. - if (d2 < epsilon2) { - S = Math.log(w1 / w0) / rho; - i = function(t) { - return [ - ux0 + t * dx, - uy0 + t * dy, - w0 * Math.exp(rho * t * S) - ]; - }; - } - - // General case. - else { - var d1 = Math.sqrt(d2), - b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), - b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), - r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), - r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); - S = (r1 - r0) / rho; - i = function(t) { - var s = t * S, - coshr0 = cosh(r0), - u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); - return [ - ux0 + u * dx, - uy0 + u * dy, - w0 * coshr0 / cosh(rho * s + r0) - ]; - }; - } - - i.duration = S * 1000; - - return i; -}; - -function hsl$1(hue$$1) { - return function(start, end) { - var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h), - s = nogamma(start.s, end.s), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.s = s(t); - start.l = l(t); - start.opacity = opacity(t); - return start + ""; - }; - } -} - -var hsl$2 = hsl$1(hue); -var hslLong = hsl$1(nogamma); - -function lab$1(start, end) { - var l = nogamma((start = lab(start)).l, (end = lab(end)).l), - a = nogamma(start.a, end.a), - b = nogamma(start.b, end.b), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.l = l(t); - start.a = a(t); - start.b = b(t); - start.opacity = opacity(t); - return start + ""; - }; -} - -function hcl$1(hue$$1) { - return function(start, end) { - var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h), - c = nogamma(start.c, end.c), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.c = c(t); - start.l = l(t); - start.opacity = opacity(t); - return start + ""; - }; - } -} - -var hcl$2 = hcl$1(hue); -var hclLong = hcl$1(nogamma); - -function cubehelix$1(hue$$1) { - return (function cubehelixGamma(y) { - y = +y; - - function cubehelix$$1(start, end) { - var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h), - s = nogamma(start.s, end.s), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.s = s(t); - start.l = l(Math.pow(t, y)); - start.opacity = opacity(t); - return start + ""; - }; - } - - cubehelix$$1.gamma = cubehelixGamma; - - return cubehelix$$1; - })(1); -} - -var cubehelix$2 = cubehelix$1(hue); -var cubehelixLong = cubehelix$1(nogamma); - -var quantize = function(interpolator, n) { - var samples = new Array(n); - for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); - return samples; -}; - -var frame = 0; -var timeout = 0; -var interval = 0; -var pokeDelay = 1000; -var taskHead; -var taskTail; -var clockLast = 0; -var clockNow = 0; -var clockSkew = 0; -var clock = typeof performance === "object" && performance.now ? performance : Date; -var setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); }; - -function now() { - return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); -} - -function clearNow() { - clockNow = 0; -} - -function Timer() { - this._call = - this._time = - this._next = null; -} - -Timer.prototype = timer.prototype = { - constructor: Timer, - restart: function(callback, delay, time) { - if (typeof callback !== "function") throw new TypeError("callback is not a function"); - time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); - if (!this._next && taskTail !== this) { - if (taskTail) taskTail._next = this; - else taskHead = this; - taskTail = this; - } - this._call = callback; - this._time = time; - sleep(); - }, - stop: function() { - if (this._call) { - this._call = null; - this._time = Infinity; - sleep(); - } - } -}; - -function timer(callback, delay, time) { - var t = new Timer; - t.restart(callback, delay, time); - return t; -} - -function timerFlush() { - now(); // Get the current time, if not already set. - ++frame; // Pretend we’ve set an alarm, if we haven’t already. - var t = taskHead, e; - while (t) { - if ((e = clockNow - t._time) >= 0) t._call.call(null, e); - t = t._next; - } - --frame; -} - -function wake() { - clockNow = (clockLast = clock.now()) + clockSkew; - frame = timeout = 0; - try { - timerFlush(); - } finally { - frame = 0; - nap(); - clockNow = 0; - } -} - -function poke() { - var now = clock.now(), delay = now - clockLast; - if (delay > pokeDelay) clockSkew -= delay, clockLast = now; -} - -function nap() { - var t0, t1 = taskHead, t2, time = Infinity; - while (t1) { - if (t1._call) { - if (time > t1._time) time = t1._time; - t0 = t1, t1 = t1._next; - } else { - t2 = t1._next, t1._next = null; - t1 = t0 ? t0._next = t2 : taskHead = t2; - } - } - taskTail = t0; - sleep(time); -} - -function sleep(time) { - if (frame) return; // Soonest alarm already set, or will be. - if (timeout) timeout = clearTimeout(timeout); - var delay = time - clockNow; // Strictly less than if we recomputed clockNow. - if (delay > 24) { - if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew); - if (interval) interval = clearInterval(interval); - } else { - if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); - frame = 1, setFrame(wake); - } -} - -var timeout$1 = function(callback, delay, time) { - var t = new Timer; - delay = delay == null ? 0 : +delay; - t.restart(function(elapsed) { - t.stop(); - callback(elapsed + delay); - }, delay, time); - return t; -}; - -var interval$1 = function(callback, delay, time) { - var t = new Timer, total = delay; - if (delay == null) return t.restart(callback, delay, time), t; - delay = +delay, time = time == null ? now() : +time; - t.restart(function tick(elapsed) { - elapsed += total; - t.restart(tick, total += delay, time); - callback(elapsed); - }, delay, time); - return t; -}; - -var emptyOn = dispatch("start", "end", "interrupt"); -var emptyTween = []; - -var CREATED = 0; -var SCHEDULED = 1; -var STARTING = 2; -var STARTED = 3; -var RUNNING = 4; -var ENDING = 5; -var ENDED = 6; - -var schedule = function(node, name, id, index, group, timing) { - var schedules = node.__transition; - if (!schedules) node.__transition = {}; - else if (id in schedules) return; - create(node, id, { - name: name, - index: index, // For context during callback. - group: group, // For context during callback. - on: emptyOn, - tween: emptyTween, - time: timing.time, - delay: timing.delay, - duration: timing.duration, - ease: timing.ease, - timer: null, - state: CREATED - }); -}; - -function init(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late"); - return schedule; -} - -function set$1(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late"); - return schedule; -} - -function get$1(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id])) throw new Error("too late"); - return schedule; -} - -function create(node, id, self) { - var schedules = node.__transition, - tween; - - // Initialize the self timer when the transition is created. - // Note the actual delay is not known until the first callback! - schedules[id] = self; - self.timer = timer(schedule, 0, self.time); - - function schedule(elapsed) { - self.state = SCHEDULED; - self.timer.restart(start, self.delay, self.time); - - // If the elapsed delay is less than our first sleep, start immediately. - if (self.delay <= elapsed) start(elapsed - self.delay); - } - - function start(elapsed) { - var i, j, n, o; - - // If the state is not SCHEDULED, then we previously errored on start. - if (self.state !== SCHEDULED) return stop(); - - for (i in schedules) { - o = schedules[i]; - if (o.name !== self.name) continue; - - // While this element already has a starting transition during this frame, - // defer starting an interrupting transition until that transition has a - // chance to tick (and possibly end); see d3/d3-transition#54! - if (o.state === STARTED) return timeout$1(start); - - // Interrupt the active transition, if any. - // Dispatch the interrupt event. - if (o.state === RUNNING) { - o.state = ENDED; - o.timer.stop(); - o.on.call("interrupt", node, node.__data__, o.index, o.group); - delete schedules[i]; - } - - // Cancel any pre-empted transitions. No interrupt event is dispatched - // because the cancelled transitions never started. Note that this also - // removes this transition from the pending list! - else if (+i < id) { - o.state = ENDED; - o.timer.stop(); - delete schedules[i]; - } - } - - // Defer the first tick to end of the current frame; see d3/d3#1576. - // Note the transition may be canceled after start and before the first tick! - // Note this must be scheduled before the start event; see d3/d3-transition#16! - // Assuming this is successful, subsequent callbacks go straight to tick. - timeout$1(function() { - if (self.state === STARTED) { - self.state = RUNNING; - self.timer.restart(tick, self.delay, self.time); - tick(elapsed); - } - }); - - // Dispatch the start event. - // Note this must be done before the tween are initialized. - self.state = STARTING; - self.on.call("start", node, node.__data__, self.index, self.group); - if (self.state !== STARTING) return; // interrupted - self.state = STARTED; - - // Initialize the tween, deleting null tween. - tween = new Array(n = self.tween.length); - for (i = 0, j = -1; i < n; ++i) { - if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { - tween[++j] = o; - } - } - tween.length = j + 1; - } - - function tick(elapsed) { - var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), - i = -1, - n = tween.length; - - while (++i < n) { - tween[i].call(null, t); - } - - // Dispatch the end event. - if (self.state === ENDING) { - self.on.call("end", node, node.__data__, self.index, self.group); - stop(); - } - } - - function stop() { - self.state = ENDED; - self.timer.stop(); - delete schedules[id]; - for (var i in schedules) return; // eslint-disable-line no-unused-vars - delete node.__transition; - } -} - -var interrupt = function(node, name) { - var schedules = node.__transition, - schedule$$1, - active, - empty = true, - i; - - if (!schedules) return; - - name = name == null ? null : name + ""; - - for (i in schedules) { - if ((schedule$$1 = schedules[i]).name !== name) { empty = false; continue; } - active = schedule$$1.state > STARTING && schedule$$1.state < ENDING; - schedule$$1.state = ENDED; - schedule$$1.timer.stop(); - if (active) schedule$$1.on.call("interrupt", node, node.__data__, schedule$$1.index, schedule$$1.group); - delete schedules[i]; - } - - if (empty) delete node.__transition; -}; - -var selection_interrupt = function(name) { - return this.each(function() { - interrupt(this, name); - }); -}; - -function tweenRemove(id, name) { - var tween0, tween1; - return function() { - var schedule$$1 = set$1(this, id), - tween = schedule$$1.tween; - - // If this node shared tween with the previous node, - // just assign the updated shared tween and we’re done! - // Otherwise, copy-on-write. - if (tween !== tween0) { - tween1 = tween0 = tween; - for (var i = 0, n = tween1.length; i < n; ++i) { - if (tween1[i].name === name) { - tween1 = tween1.slice(); - tween1.splice(i, 1); - break; - } - } - } - - schedule$$1.tween = tween1; - }; -} - -function tweenFunction(id, name, value) { - var tween0, tween1; - if (typeof value !== "function") throw new Error; - return function() { - var schedule$$1 = set$1(this, id), - tween = schedule$$1.tween; - - // If this node shared tween with the previous node, - // just assign the updated shared tween and we’re done! - // Otherwise, copy-on-write. - if (tween !== tween0) { - tween1 = (tween0 = tween).slice(); - for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { - if (tween1[i].name === name) { - tween1[i] = t; - break; - } - } - if (i === n) tween1.push(t); - } - - schedule$$1.tween = tween1; - }; -} - -var transition_tween = function(name, value) { - var id = this._id; - - name += ""; - - if (arguments.length < 2) { - var tween = get$1(this.node(), id).tween; - for (var i = 0, n = tween.length, t; i < n; ++i) { - if ((t = tween[i]).name === name) { - return t.value; - } - } - return null; - } - - return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); -}; - -function tweenValue(transition, name, value) { - var id = transition._id; - - transition.each(function() { - var schedule$$1 = set$1(this, id); - (schedule$$1.value || (schedule$$1.value = {}))[name] = value.apply(this, arguments); - }); - - return function(node) { - return get$1(node, id).value[name]; - }; -} - -var interpolate = function(a, b) { - var c; - return (typeof b === "number" ? reinterpolate - : b instanceof color ? interpolateRgb - : (c = color(b)) ? (b = c, interpolateRgb) - : interpolateString)(a, b); -}; - -function attrRemove$1(name) { - return function() { - this.removeAttribute(name); - }; -} - -function attrRemoveNS$1(fullname) { - return function() { - this.removeAttributeNS(fullname.space, fullname.local); - }; -} - -function attrConstant$1(name, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = this.getAttribute(name); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); - }; -} - -function attrConstantNS$1(fullname, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = this.getAttributeNS(fullname.space, fullname.local); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); - }; -} - -function attrFunction$1(name, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var value0, value1 = value(this); - if (value1 == null) return void this.removeAttribute(name); - value0 = this.getAttribute(name); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; -} - -function attrFunctionNS$1(fullname, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var value0, value1 = value(this); - if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); - value0 = this.getAttributeNS(fullname.space, fullname.local); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; -} - -var transition_attr = function(name, value) { - var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate; - return this.attrTween(name, typeof value === "function" - ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value)) - : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname) - : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value + "")); -}; - -function attrTweenNS(fullname, value) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.setAttributeNS(fullname.space, fullname.local, i(t)); - }; - } - tween._value = value; - return tween; -} - -function attrTween(name, value) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.setAttribute(name, i(t)); - }; - } - tween._value = value; - return tween; -} - -var transition_attrTween = function(name, value) { - var key = "attr." + name; - if (arguments.length < 2) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - var fullname = namespace(name); - return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); -}; - -function delayFunction(id, value) { - return function() { - init(this, id).delay = +value.apply(this, arguments); - }; -} - -function delayConstant(id, value) { - return value = +value, function() { - init(this, id).delay = value; - }; -} - -var transition_delay = function(value) { - var id = this._id; - - return arguments.length - ? this.each((typeof value === "function" - ? delayFunction - : delayConstant)(id, value)) - : get$1(this.node(), id).delay; -}; - -function durationFunction(id, value) { - return function() { - set$1(this, id).duration = +value.apply(this, arguments); - }; -} - -function durationConstant(id, value) { - return value = +value, function() { - set$1(this, id).duration = value; - }; -} - -var transition_duration = function(value) { - var id = this._id; - - return arguments.length - ? this.each((typeof value === "function" - ? durationFunction - : durationConstant)(id, value)) - : get$1(this.node(), id).duration; -}; - -function easeConstant(id, value) { - if (typeof value !== "function") throw new Error; - return function() { - set$1(this, id).ease = value; - }; -} - -var transition_ease = function(value) { - var id = this._id; - - return arguments.length - ? this.each(easeConstant(id, value)) - : get$1(this.node(), id).ease; -}; - -var transition_filter = function(match) { - if (typeof match !== "function") match = matcher$1(match); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { - if ((node = group[i]) && match.call(node, node.__data__, i, group)) { - subgroup.push(node); - } - } - } - - return new Transition(subgroups, this._parents, this._name, this._id); -}; - -var transition_merge = function(transition$$1) { - if (transition$$1._id !== this._id) throw new Error; - - for (var groups0 = this._groups, groups1 = transition$$1._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { - for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group0[i] || group1[i]) { - merge[i] = node; - } - } - } - - for (; j < m0; ++j) { - merges[j] = groups0[j]; - } - - return new Transition(merges, this._parents, this._name, this._id); -}; - -function start(name) { - return (name + "").trim().split(/^|\s+/).every(function(t) { - var i = t.indexOf("."); - if (i >= 0) t = t.slice(0, i); - return !t || t === "start"; - }); -} - -function onFunction(id, name, listener) { - var on0, on1, sit = start(name) ? init : set$1; - return function() { - var schedule$$1 = sit(this, id), - on = schedule$$1.on; - - // If this node shared a dispatch with the previous node, - // just assign the updated shared dispatch and we’re done! - // Otherwise, copy-on-write. - if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); - - schedule$$1.on = on1; - }; -} - -var transition_on = function(name, listener) { - var id = this._id; - - return arguments.length < 2 - ? get$1(this.node(), id).on.on(name) - : this.each(onFunction(id, name, listener)); -}; - -function removeFunction(id) { - return function() { - var parent = this.parentNode; - for (var i in this.__transition) if (+i !== id) return; - if (parent) parent.removeChild(this); - }; -} - -var transition_remove = function() { - return this.on("end.remove", removeFunction(this._id)); -}; - -var transition_select = function(select) { - var name = this._name, - id = this._id; - - if (typeof select !== "function") select = selector(select); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { - if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - subgroup[i] = subnode; - schedule(subgroup[i], name, id, i, subgroup, get$1(node, id)); - } - } - } - - return new Transition(subgroups, this._parents, name, id); -}; - -var transition_selectAll = function(select) { - var name = this._name, - id = this._id; - - if (typeof select !== "function") select = selectorAll(select); - - for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - for (var children = select.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) { - if (child = children[k]) { - schedule(child, name, id, k, children, inherit); - } - } - subgroups.push(children); - parents.push(node); - } - } - } - - return new Transition(subgroups, parents, name, id); -}; - -var Selection$1 = selection.prototype.constructor; - -var transition_selection = function() { - return new Selection$1(this._groups, this._parents); -}; - -function styleRemove$1(name, interpolate$$1) { - var value00, - value10, - interpolate0; - return function() { - var value0 = styleValue(this, name), - value1 = (this.style.removeProperty(name), styleValue(this, name)); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; -} - -function styleRemoveEnd(name) { - return function() { - this.style.removeProperty(name); - }; -} - -function styleConstant$1(name, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = styleValue(this, name); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); - }; -} - -function styleFunction$1(name, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var value0 = styleValue(this, name), - value1 = value(this); - if (value1 == null) value1 = (this.style.removeProperty(name), styleValue(this, name)); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; -} - -var transition_style = function(name, value, priority) { - var i = (name += "") === "transform" ? interpolateTransformCss : interpolate; - return value == null ? this - .styleTween(name, styleRemove$1(name, i)) - .on("end.style." + name, styleRemoveEnd(name)) - : this.styleTween(name, typeof value === "function" - ? styleFunction$1(name, i, tweenValue(this, "style." + name, value)) - : styleConstant$1(name, i, value + ""), priority); -}; - -function styleTween(name, value, priority) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.style.setProperty(name, i(t), priority); - }; - } - tween._value = value; - return tween; -} - -var transition_styleTween = function(name, value, priority) { - var key = "style." + (name += ""); - if (arguments.length < 2) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); -}; - -function textConstant$1(value) { - return function() { - this.textContent = value; - }; -} - -function textFunction$1(value) { - return function() { - var value1 = value(this); - this.textContent = value1 == null ? "" : value1; - }; -} - -var transition_text = function(value) { - return this.tween("text", typeof value === "function" - ? textFunction$1(tweenValue(this, "text", value)) - : textConstant$1(value == null ? "" : value + "")); -}; - -var transition_transition = function() { - var name = this._name, - id0 = this._id, - id1 = newId(); - - for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - var inherit = get$1(node, id0); - schedule(node, name, id1, i, group, { - time: inherit.time + inherit.delay + inherit.duration, - delay: 0, - duration: inherit.duration, - ease: inherit.ease - }); - } - } - } - - return new Transition(groups, this._parents, name, id1); -}; - -var id = 0; - -function Transition(groups, parents, name, id) { - this._groups = groups; - this._parents = parents; - this._name = name; - this._id = id; -} - -function transition(name) { - return selection().transition(name); -} - -function newId() { - return ++id; -} - -var selection_prototype = selection.prototype; - -Transition.prototype = transition.prototype = { - constructor: Transition, - select: transition_select, - selectAll: transition_selectAll, - filter: transition_filter, - merge: transition_merge, - selection: transition_selection, - transition: transition_transition, - call: selection_prototype.call, - nodes: selection_prototype.nodes, - node: selection_prototype.node, - size: selection_prototype.size, - empty: selection_prototype.empty, - each: selection_prototype.each, - on: transition_on, - attr: transition_attr, - attrTween: transition_attrTween, - style: transition_style, - styleTween: transition_styleTween, - text: transition_text, - remove: transition_remove, - tween: transition_tween, - delay: transition_delay, - duration: transition_duration, - ease: transition_ease -}; - -function linear$1(t) { - return +t; -} - -function quadIn(t) { - return t * t; -} - -function quadOut(t) { - return t * (2 - t); -} - -function quadInOut(t) { - return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; -} - -function cubicIn(t) { - return t * t * t; -} - -function cubicOut(t) { - return --t * t * t + 1; -} - -function cubicInOut(t) { - return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; -} - -var exponent = 3; - -var polyIn = (function custom(e) { - e = +e; - - function polyIn(t) { - return Math.pow(t, e); - } - - polyIn.exponent = custom; - - return polyIn; -})(exponent); - -var polyOut = (function custom(e) { - e = +e; - - function polyOut(t) { - return 1 - Math.pow(1 - t, e); - } - - polyOut.exponent = custom; - - return polyOut; -})(exponent); - -var polyInOut = (function custom(e) { - e = +e; - - function polyInOut(t) { - return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2; - } - - polyInOut.exponent = custom; - - return polyInOut; -})(exponent); - -var pi = Math.PI; -var halfPi = pi / 2; - -function sinIn(t) { - return 1 - Math.cos(t * halfPi); -} - -function sinOut(t) { - return Math.sin(t * halfPi); -} - -function sinInOut(t) { - return (1 - Math.cos(pi * t)) / 2; -} - -function expIn(t) { - return Math.pow(2, 10 * t - 10); -} - -function expOut(t) { - return 1 - Math.pow(2, -10 * t); -} - -function expInOut(t) { - return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2; -} - -function circleIn(t) { - return 1 - Math.sqrt(1 - t * t); -} - -function circleOut(t) { - return Math.sqrt(1 - --t * t); -} - -function circleInOut(t) { - return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2; -} - -var b1 = 4 / 11; -var b2 = 6 / 11; -var b3 = 8 / 11; -var b4 = 3 / 4; -var b5 = 9 / 11; -var b6 = 10 / 11; -var b7 = 15 / 16; -var b8 = 21 / 22; -var b9 = 63 / 64; -var b0 = 1 / b1 / b1; - -function bounceIn(t) { - return 1 - bounceOut(1 - t); -} - -function bounceOut(t) { - return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9; -} - -function bounceInOut(t) { - return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2; -} - -var overshoot = 1.70158; - -var backIn = (function custom(s) { - s = +s; - - function backIn(t) { - return t * t * ((s + 1) * t - s); - } - - backIn.overshoot = custom; - - return backIn; -})(overshoot); - -var backOut = (function custom(s) { - s = +s; - - function backOut(t) { - return --t * t * ((s + 1) * t + s) + 1; - } - - backOut.overshoot = custom; - - return backOut; -})(overshoot); - -var backInOut = (function custom(s) { - s = +s; - - function backInOut(t) { - return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2; - } - - backInOut.overshoot = custom; - - return backInOut; -})(overshoot); - -var tau = 2 * Math.PI; -var amplitude = 1; -var period = 0.3; - -var elasticIn = (function custom(a, p) { - var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); - - function elasticIn(t) { - return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p); - } - - elasticIn.amplitude = function(a) { return custom(a, p * tau); }; - elasticIn.period = function(p) { return custom(a, p); }; - - return elasticIn; -})(amplitude, period); - -var elasticOut = (function custom(a, p) { - var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); - - function elasticOut(t) { - return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p); - } - - elasticOut.amplitude = function(a) { return custom(a, p * tau); }; - elasticOut.period = function(p) { return custom(a, p); }; - - return elasticOut; -})(amplitude, period); - -var elasticInOut = (function custom(a, p) { - var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); - - function elasticInOut(t) { - return ((t = t * 2 - 1) < 0 - ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p) - : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2; - } - - elasticInOut.amplitude = function(a) { return custom(a, p * tau); }; - elasticInOut.period = function(p) { return custom(a, p); }; - - return elasticInOut; -})(amplitude, period); - -var defaultTiming = { - time: null, // Set on use. - delay: 0, - duration: 250, - ease: cubicInOut -}; - -function inherit(node, id) { - var timing; - while (!(timing = node.__transition) || !(timing = timing[id])) { - if (!(node = node.parentNode)) { - return defaultTiming.time = now(), defaultTiming; - } - } - return timing; -} - -var selection_transition = function(name) { - var id, - timing; - - if (name instanceof Transition) { - id = name._id, name = name._name; - } else { - id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; - } - - for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - schedule(node, name, id, i, group, timing || inherit(node, id)); - } - } - } - - return new Transition(groups, this._parents, name, id); -}; - -selection.prototype.interrupt = selection_interrupt; -selection.prototype.transition = selection_transition; - -var root$1 = [null]; - -var active = function(node, name) { - var schedules = node.__transition, - schedule$$1, - i; - - if (schedules) { - name = name == null ? null : name + ""; - for (i in schedules) { - if ((schedule$$1 = schedules[i]).state > SCHEDULED && schedule$$1.name === name) { - return new Transition([[node]], root$1, name, +i); - } - } - } - - return null; -}; - -var constant$4 = function(x) { - return function() { - return x; - }; -}; - -var BrushEvent = function(target, type, selection) { - this.target = target; - this.type = type; - this.selection = selection; -}; - -function nopropagation$1() { - exports.event.stopImmediatePropagation(); -} - -var noevent$1 = function() { - exports.event.preventDefault(); - exports.event.stopImmediatePropagation(); -}; - -var MODE_DRAG = {name: "drag"}; -var MODE_SPACE = {name: "space"}; -var MODE_HANDLE = {name: "handle"}; -var MODE_CENTER = {name: "center"}; - -var X = { - name: "x", - handles: ["e", "w"].map(type), - input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; }, - output: function(xy) { return xy && [xy[0][0], xy[1][0]]; } -}; - -var Y = { - name: "y", - handles: ["n", "s"].map(type), - input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; }, - output: function(xy) { return xy && [xy[0][1], xy[1][1]]; } -}; - -var XY = { - name: "xy", - handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type), - input: function(xy) { return xy; }, - output: function(xy) { return xy; } -}; - -var cursors = { - overlay: "crosshair", - selection: "move", - n: "ns-resize", - e: "ew-resize", - s: "ns-resize", - w: "ew-resize", - nw: "nwse-resize", - ne: "nesw-resize", - se: "nwse-resize", - sw: "nesw-resize" -}; - -var flipX = { - e: "w", - w: "e", - nw: "ne", - ne: "nw", - se: "sw", - sw: "se" -}; - -var flipY = { - n: "s", - s: "n", - nw: "sw", - ne: "se", - se: "ne", - sw: "nw" -}; - -var signsX = { - overlay: +1, - selection: +1, - n: null, - e: +1, - s: null, - w: -1, - nw: -1, - ne: +1, - se: +1, - sw: -1 -}; - -var signsY = { - overlay: +1, - selection: +1, - n: -1, - e: null, - s: +1, - w: null, - nw: -1, - ne: -1, - se: +1, - sw: +1 -}; - -function type(t) { - return {type: t}; -} - -// Ignore right-click, since that should open the context menu. -function defaultFilter() { - return !exports.event.button; -} - -function defaultExtent() { - var svg = this.ownerSVGElement || this; - return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]]; -} - -// Like d3.local, but with the name “__brush” rather than auto-generated. -function local(node) { - while (!node.__brush) if (!(node = node.parentNode)) return; - return node.__brush; -} - -function empty(extent) { - return extent[0][0] === extent[1][0] - || extent[0][1] === extent[1][1]; -} - -function brushSelection(node) { - var state = node.__brush; - return state ? state.dim.output(state.selection) : null; -} - -function brushX() { - return brush$1(X); -} - -function brushY() { - return brush$1(Y); -} - -var brush = function() { - return brush$1(XY); -}; - -function brush$1(dim) { - var extent = defaultExtent, - filter = defaultFilter, - listeners = dispatch(brush, "start", "brush", "end"), - handleSize = 6, - touchending; - - function brush(group) { - var overlay = group - .property("__brush", initialize) - .selectAll(".overlay") - .data([type("overlay")]); - - overlay.enter().append("rect") - .attr("class", "overlay") - .attr("pointer-events", "all") - .attr("cursor", cursors.overlay) - .merge(overlay) - .each(function() { - var extent = local(this).extent; - select(this) - .attr("x", extent[0][0]) - .attr("y", extent[0][1]) - .attr("width", extent[1][0] - extent[0][0]) - .attr("height", extent[1][1] - extent[0][1]); - }); - - group.selectAll(".selection") - .data([type("selection")]) - .enter().append("rect") - .attr("class", "selection") - .attr("cursor", cursors.selection) - .attr("fill", "#777") - .attr("fill-opacity", 0.3) - .attr("stroke", "#fff") - .attr("shape-rendering", "crispEdges"); - - var handle = group.selectAll(".handle") - .data(dim.handles, function(d) { return d.type; }); - - handle.exit().remove(); - - handle.enter().append("rect") - .attr("class", function(d) { return "handle handle--" + d.type; }) - .attr("cursor", function(d) { return cursors[d.type]; }); - - group - .each(redraw) - .attr("fill", "none") - .attr("pointer-events", "all") - .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") - .on("mousedown.brush touchstart.brush", started); - } - - brush.move = function(group, selection) { - if (group.selection) { - group - .on("start.brush", function() { emitter(this, arguments).beforestart().start(); }) - .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); }) - .tween("brush", function() { - var that = this, - state = that.__brush, - emit = emitter(that, arguments), - selection0 = state.selection, - selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent), - i = interpolateValue(selection0, selection1); - - function tween(t) { - state.selection = t === 1 && empty(selection1) ? null : i(t); - redraw.call(that); - emit.brush(); - } - - return selection0 && selection1 ? tween : tween(1); - }); - } else { - group - .each(function() { - var that = this, - args = arguments, - state = that.__brush, - selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent), - emit = emitter(that, args).beforestart(); - - interrupt(that); - state.selection = selection1 == null || empty(selection1) ? null : selection1; - redraw.call(that); - emit.start().brush().end(); - }); - } - }; - - function redraw() { - var group = select(this), - selection = local(this).selection; - - if (selection) { - group.selectAll(".selection") - .style("display", null) - .attr("x", selection[0][0]) - .attr("y", selection[0][1]) - .attr("width", selection[1][0] - selection[0][0]) - .attr("height", selection[1][1] - selection[0][1]); - - group.selectAll(".handle") - .style("display", null) - .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; }) - .attr("y", function(d) { return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; }) - .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; }) - .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; }); - } - - else { - group.selectAll(".selection,.handle") - .style("display", "none") - .attr("x", null) - .attr("y", null) - .attr("width", null) - .attr("height", null); - } - } - - function emitter(that, args) { - return that.__brush.emitter || new Emitter(that, args); - } - - function Emitter(that, args) { - this.that = that; - this.args = args; - this.state = that.__brush; - this.active = 0; - } - - Emitter.prototype = { - beforestart: function() { - if (++this.active === 1) this.state.emitter = this, this.starting = true; - return this; - }, - start: function() { - if (this.starting) this.starting = false, this.emit("start"); - return this; - }, - brush: function() { - this.emit("brush"); - return this; - }, - end: function() { - if (--this.active === 0) delete this.state.emitter, this.emit("end"); - return this; - }, - emit: function(type) { - customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]); - } - }; - - function started() { - if (exports.event.touches) { if (exports.event.changedTouches.length < exports.event.touches.length) return noevent$1(); } - else if (touchending) return; - if (!filter.apply(this, arguments)) return; - - var that = this, - type = exports.event.target.__data__.type, - mode = (exports.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (exports.event.altKey ? MODE_CENTER : MODE_HANDLE), - signX = dim === Y ? null : signsX[type], - signY = dim === X ? null : signsY[type], - state = local(that), - extent = state.extent, - selection = state.selection, - W = extent[0][0], w0, w1, - N = extent[0][1], n0, n1, - E = extent[1][0], e0, e1, - S = extent[1][1], s0, s1, - dx, - dy, - moving, - shifting = signX && signY && exports.event.shiftKey, - lockX, - lockY, - point0 = mouse(that), - point = point0, - emit = emitter(that, arguments).beforestart(); - - if (type === "overlay") { - state.selection = selection = [ - [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], - [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0] - ]; - } else { - w0 = selection[0][0]; - n0 = selection[0][1]; - e0 = selection[1][0]; - s0 = selection[1][1]; - } - - w1 = w0; - n1 = n0; - e1 = e0; - s1 = s0; - - var group = select(that) - .attr("pointer-events", "none"); - - var overlay = group.selectAll(".overlay") - .attr("cursor", cursors[type]); - - if (exports.event.touches) { - group - .on("touchmove.brush", moved, true) - .on("touchend.brush touchcancel.brush", ended, true); - } else { - var view = select(exports.event.view) - .on("keydown.brush", keydowned, true) - .on("keyup.brush", keyupped, true) - .on("mousemove.brush", moved, true) - .on("mouseup.brush", ended, true); - - dragDisable(exports.event.view); - } - - nopropagation$1(); - interrupt(that); - redraw.call(that); - emit.start(); - - function moved() { - var point1 = mouse(that); - if (shifting && !lockX && !lockY) { - if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true; - else lockX = true; - } - point = point1; - moving = true; - noevent$1(); - move(); - } - - function move() { - var t; - - dx = point[0] - point0[0]; - dy = point[1] - point0[1]; - - switch (mode) { - case MODE_SPACE: - case MODE_DRAG: { - if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx; - if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy; - break; - } - case MODE_HANDLE: { - if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0; - else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx; - if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0; - else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy; - break; - } - case MODE_CENTER: { - if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX)); - if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY)); - break; - } - } - - if (e1 < w1) { - signX *= -1; - t = w0, w0 = e0, e0 = t; - t = w1, w1 = e1, e1 = t; - if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]); - } - - if (s1 < n1) { - signY *= -1; - t = n0, n0 = s0, s0 = t; - t = n1, n1 = s1, s1 = t; - if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]); - } - - if (state.selection) selection = state.selection; // May be set by brush.move! - if (lockX) w1 = selection[0][0], e1 = selection[1][0]; - if (lockY) n1 = selection[0][1], s1 = selection[1][1]; - - if (selection[0][0] !== w1 - || selection[0][1] !== n1 - || selection[1][0] !== e1 - || selection[1][1] !== s1) { - state.selection = [[w1, n1], [e1, s1]]; - redraw.call(that); - emit.brush(); - } - } - - function ended() { - nopropagation$1(); - if (exports.event.touches) { - if (exports.event.touches.length) return; - if (touchending) clearTimeout(touchending); - touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! - group.on("touchmove.brush touchend.brush touchcancel.brush", null); - } else { - yesdrag(exports.event.view, moving); - view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null); - } - group.attr("pointer-events", "all"); - overlay.attr("cursor", cursors.overlay); - if (state.selection) selection = state.selection; // May be set by brush.move (on start)! - if (empty(selection)) state.selection = null, redraw.call(that); - emit.end(); - } - - function keydowned() { - switch (exports.event.keyCode) { - case 16: { // SHIFT - shifting = signX && signY; - break; - } - case 18: { // ALT - if (mode === MODE_HANDLE) { - if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; - if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; - mode = MODE_CENTER; - move(); - } - break; - } - case 32: { // SPACE; takes priority over ALT - if (mode === MODE_HANDLE || mode === MODE_CENTER) { - if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx; - if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy; - mode = MODE_SPACE; - overlay.attr("cursor", cursors.selection); - move(); - } - break; - } - default: return; - } - noevent$1(); - } - - function keyupped() { - switch (exports.event.keyCode) { - case 16: { // SHIFT - if (shifting) { - lockX = lockY = shifting = false; - move(); - } - break; - } - case 18: { // ALT - if (mode === MODE_CENTER) { - if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; - if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; - mode = MODE_HANDLE; - move(); - } - break; - } - case 32: { // SPACE - if (mode === MODE_SPACE) { - if (exports.event.altKey) { - if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; - if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; - mode = MODE_CENTER; - } else { - if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; - if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; - mode = MODE_HANDLE; - } - overlay.attr("cursor", cursors[type]); - move(); - } - break; - } - default: return; - } - noevent$1(); - } - } - - function initialize() { - var state = this.__brush || {selection: null}; - state.extent = extent.apply(this, arguments); - state.dim = dim; - return state; - } - - brush.extent = function(_) { - return arguments.length ? (extent = typeof _ === "function" ? _ : constant$4([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent; - }; - - brush.filter = function(_) { - return arguments.length ? (filter = typeof _ === "function" ? _ : constant$4(!!_), brush) : filter; - }; - - brush.handleSize = function(_) { - return arguments.length ? (handleSize = +_, brush) : handleSize; - }; - - brush.on = function() { - var value = listeners.on.apply(listeners, arguments); - return value === listeners ? brush : value; - }; - - return brush; -} - -var cos = Math.cos; -var sin = Math.sin; -var pi$1 = Math.PI; -var halfPi$1 = pi$1 / 2; -var tau$1 = pi$1 * 2; -var max$1 = Math.max; - -function compareValue(compare) { - return function(a, b) { - return compare( - a.source.value + a.target.value, - b.source.value + b.target.value - ); - }; -} - -var chord = function() { - var padAngle = 0, - sortGroups = null, - sortSubgroups = null, - sortChords = null; - - function chord(matrix) { - var n = matrix.length, - groupSums = [], - groupIndex = sequence(n), - subgroupIndex = [], - chords = [], - groups = chords.groups = new Array(n), - subgroups = new Array(n * n), - k, - x, - x0, - dx, - i, - j; - - // Compute the sum. - k = 0, i = -1; while (++i < n) { - x = 0, j = -1; while (++j < n) { - x += matrix[i][j]; - } - groupSums.push(x); - subgroupIndex.push(sequence(n)); - k += x; - } - - // Sort groups
 - if (sortGroups) groupIndex.sort(function(a, b) { - return sortGroups(groupSums[a], groupSums[b]); - }); - - // Sort subgroups
 - if (sortSubgroups) subgroupIndex.forEach(function(d, i) { - d.sort(function(a, b) { - return sortSubgroups(matrix[i][a], matrix[i][b]); - }); - }); - - // Convert the sum to scaling factor for [0, 2pi]. - // TODO Allow start and end angle to be specified? - // TODO Allow padding to be specified as percentage? - k = max$1(0, tau$1 - padAngle * n) / k; - dx = k ? padAngle : tau$1 / n; - - // Compute the start and end angle for each group and subgroup. - // Note: Opera has a bug reordering object literal properties! - x = 0, i = -1; while (++i < n) { - x0 = x, j = -1; while (++j < n) { - var di = groupIndex[i], - dj = subgroupIndex[di][j], - v = matrix[di][dj], - a0 = x, - a1 = x += v * k; - subgroups[dj * n + di] = { - index: di, - subindex: dj, - startAngle: a0, - endAngle: a1, - value: v - }; - } - groups[di] = { - index: di, - startAngle: x0, - endAngle: x, - value: groupSums[di] - }; - x += dx; - } - - // Generate chords for each (non-empty) subgroup-subgroup link. - i = -1; while (++i < n) { - j = i - 1; while (++j < n) { - var source = subgroups[j * n + i], - target = subgroups[i * n + j]; - if (source.value || target.value) { - chords.push(source.value < target.value - ? {source: target, target: source} - : {source: source, target: target}); - } - } - } - - return sortChords ? chords.sort(sortChords) : chords; - } - - chord.padAngle = function(_) { - return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle; - }; - - chord.sortGroups = function(_) { - return arguments.length ? (sortGroups = _, chord) : sortGroups; - }; - - chord.sortSubgroups = function(_) { - return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups; - }; - - chord.sortChords = function(_) { - return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._; - }; - - return chord; -}; - -var slice$2 = Array.prototype.slice; - -var constant$5 = function(x) { - return function() { - return x; - }; -}; - -var pi$2 = Math.PI; -var tau$2 = 2 * pi$2; -var epsilon$1 = 1e-6; -var tauEpsilon = tau$2 - epsilon$1; - -function Path() { - this._x0 = this._y0 = // start of current subpath - this._x1 = this._y1 = null; // end of current subpath - this._ = ""; -} - -function path() { - return new Path; -} - -Path.prototype = path.prototype = { - constructor: Path, - moveTo: function(x, y) { - this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); - }, - closePath: function() { - if (this._x1 !== null) { - this._x1 = this._x0, this._y1 = this._y0; - this._ += "Z"; - } - }, - lineTo: function(x, y) { - this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); - }, - quadraticCurveTo: function(x1, y1, x, y) { - this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y); - }, - bezierCurveTo: function(x1, y1, x2, y2, x, y) { - this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y); - }, - arcTo: function(x1, y1, x2, y2, r) { - x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; - var x0 = this._x1, - y0 = this._y1, - x21 = x2 - x1, - y21 = y2 - y1, - x01 = x0 - x1, - y01 = y0 - y1, - l01_2 = x01 * x01 + y01 * y01; - - // Is the radius negative? Error. - if (r < 0) throw new Error("negative radius: " + r); - - // Is this path empty? Move to (x1,y1). - if (this._x1 === null) { - this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1); - } - - // Or, is (x1,y1) coincident with (x0,y0)? Do nothing. - else if (!(l01_2 > epsilon$1)) {} - - // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? - // Equivalently, is (x1,y1) coincident with (x2,y2)? - // Or, is the radius zero? Line to (x1,y1). - else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon$1) || !r) { - this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1); - } - - // Otherwise, draw an arc! - else { - var x20 = x2 - x0, - y20 = y2 - y0, - l21_2 = x21 * x21 + y21 * y21, - l20_2 = x20 * x20 + y20 * y20, - l21 = Math.sqrt(l21_2), - l01 = Math.sqrt(l01_2), - l = r * Math.tan((pi$2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), - t01 = l / l01, - t21 = l / l21; - - // If the start tangent is not coincident with (x0,y0), line to. - if (Math.abs(t01 - 1) > epsilon$1) { - this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01); - } - - this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21); - } - }, - arc: function(x, y, r, a0, a1, ccw) { - x = +x, y = +y, r = +r; - var dx = r * Math.cos(a0), - dy = r * Math.sin(a0), - x0 = x + dx, - y0 = y + dy, - cw = 1 ^ ccw, - da = ccw ? a0 - a1 : a1 - a0; - - // Is the radius negative? Error. - if (r < 0) throw new Error("negative radius: " + r); - - // Is this path empty? Move to (x0,y0). - if (this._x1 === null) { - this._ += "M" + x0 + "," + y0; - } - - // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). - else if (Math.abs(this._x1 - x0) > epsilon$1 || Math.abs(this._y1 - y0) > epsilon$1) { - this._ += "L" + x0 + "," + y0; - } - - // Is this arc empty? We’re done. - if (!r) return; - - // Does the angle go the wrong way? Flip the direction. - if (da < 0) da = da % tau$2 + tau$2; - - // Is this a complete circle? Draw two arcs to complete the circle. - if (da > tauEpsilon) { - this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0); - } - - // Is this arc non-empty? Draw an arc! - else if (da > epsilon$1) { - this._ += "A" + r + "," + r + ",0," + (+(da >= pi$2)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1)); - } - }, - rect: function(x, y, w, h) { - this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z"; - }, - toString: function() { - return this._; - } -}; - -function defaultSource(d) { - return d.source; -} - -function defaultTarget(d) { - return d.target; -} - -function defaultRadius(d) { - return d.radius; -} - -function defaultStartAngle(d) { - return d.startAngle; -} - -function defaultEndAngle(d) { - return d.endAngle; -} - -var ribbon = function() { - var source = defaultSource, - target = defaultTarget, - radius = defaultRadius, - startAngle = defaultStartAngle, - endAngle = defaultEndAngle, - context = null; - - function ribbon() { - var buffer, - argv = slice$2.call(arguments), - s = source.apply(this, argv), - t = target.apply(this, argv), - sr = +radius.apply(this, (argv[0] = s, argv)), - sa0 = startAngle.apply(this, argv) - halfPi$1, - sa1 = endAngle.apply(this, argv) - halfPi$1, - sx0 = sr * cos(sa0), - sy0 = sr * sin(sa0), - tr = +radius.apply(this, (argv[0] = t, argv)), - ta0 = startAngle.apply(this, argv) - halfPi$1, - ta1 = endAngle.apply(this, argv) - halfPi$1; - - if (!context) context = buffer = path(); - - context.moveTo(sx0, sy0); - context.arc(0, 0, sr, sa0, sa1); - if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr? - context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0)); - context.arc(0, 0, tr, ta0, ta1); - } - context.quadraticCurveTo(0, 0, sx0, sy0); - context.closePath(); - - if (buffer) return context = null, buffer + "" || null; - } - - ribbon.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant$5(+_), ribbon) : radius; - }; - - ribbon.startAngle = function(_) { - return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : startAngle; - }; - - ribbon.endAngle = function(_) { - return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : endAngle; - }; - - ribbon.source = function(_) { - return arguments.length ? (source = _, ribbon) : source; - }; - - ribbon.target = function(_) { - return arguments.length ? (target = _, ribbon) : target; - }; - - ribbon.context = function(_) { - return arguments.length ? ((context = _ == null ? null : _), ribbon) : context; - }; - - return ribbon; -}; - -var prefix = "$"; - -function Map() {} - -Map.prototype = map$1.prototype = { - constructor: Map, - has: function(key) { - return (prefix + key) in this; - }, - get: function(key) { - return this[prefix + key]; - }, - set: function(key, value) { - this[prefix + key] = value; - return this; - }, - remove: function(key) { - var property = prefix + key; - return property in this && delete this[property]; - }, - clear: function() { - for (var property in this) if (property[0] === prefix) delete this[property]; - }, - keys: function() { - var keys = []; - for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); - return keys; - }, - values: function() { - var values = []; - for (var property in this) if (property[0] === prefix) values.push(this[property]); - return values; - }, - entries: function() { - var entries = []; - for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); - return entries; - }, - size: function() { - var size = 0; - for (var property in this) if (property[0] === prefix) ++size; - return size; - }, - empty: function() { - for (var property in this) if (property[0] === prefix) return false; - return true; - }, - each: function(f) { - for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); - } -}; - -function map$1(object, f) { - var map = new Map; - - // Copy constructor. - if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); - - // Index array by numeric index or specified key function. - else if (Array.isArray(object)) { - var i = -1, - n = object.length, - o; - - if (f == null) while (++i < n) map.set(i, object[i]); - else while (++i < n) map.set(f(o = object[i], i, object), o); - } - - // Convert object to map. - else if (object) for (var key in object) map.set(key, object[key]); - - return map; -} - -var nest = function() { - var keys = [], - sortKeys = [], - sortValues, - rollup, - nest; - - function apply(array, depth, createResult, setResult) { - if (depth >= keys.length) { - if (sortValues != null) array.sort(sortValues); - return rollup != null ? rollup(array) : array; - } - - var i = -1, - n = array.length, - key = keys[depth++], - keyValue, - value, - valuesByKey = map$1(), - values, - result = createResult(); - - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { - values.push(value); - } else { - valuesByKey.set(keyValue, [value]); - } - } - - valuesByKey.each(function(values, key) { - setResult(result, key, apply(values, depth, createResult, setResult)); - }); - - return result; - } - - function entries(map, depth) { - if (++depth > keys.length) return map; - var array, sortKey = sortKeys[depth - 1]; - if (rollup != null && depth >= keys.length) array = map.entries(); - else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); - return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; - } - - return nest = { - object: function(array) { return apply(array, 0, createObject, setObject); }, - map: function(array) { return apply(array, 0, createMap, setMap); }, - entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, - key: function(d) { keys.push(d); return nest; }, - sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, - sortValues: function(order) { sortValues = order; return nest; }, - rollup: function(f) { rollup = f; return nest; } - }; -}; - -function createObject() { - return {}; -} - -function setObject(object, key, value) { - object[key] = value; -} - -function createMap() { - return map$1(); -} - -function setMap(map, key, value) { - map.set(key, value); -} - -function Set() {} - -var proto = map$1.prototype; - -Set.prototype = set$2.prototype = { - constructor: Set, - has: proto.has, - add: function(value) { - value += ""; - this[prefix + value] = value; - return this; - }, - remove: proto.remove, - clear: proto.clear, - values: proto.keys, - size: proto.size, - empty: proto.empty, - each: proto.each -}; - -function set$2(object, f) { - var set = new Set; - - // Copy constructor. - if (object instanceof Set) object.each(function(value) { set.add(value); }); - - // Otherwise, assume it’s an array. - else if (object) { - var i = -1, n = object.length; - if (f == null) while (++i < n) set.add(object[i]); - else while (++i < n) set.add(f(object[i], i, object)); - } - - return set; -} - -var keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; -}; - -var values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; -}; - -var entries = function(map) { - var entries = []; - for (var key in map) entries.push({key: key, value: map[key]}); - return entries; -}; - -var EOL = {}; -var EOF = {}; -var QUOTE = 34; -var NEWLINE = 10; -var RETURN = 13; - -function objectConverter(columns) { - return new Function("d", "return {" + columns.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); -} - -function customConverter(columns, f) { - var object = objectConverter(columns); - return function(row, i) { - return f(object(row), i, columns); - }; -} - -// Compute unique columns in order of discovery. -function inferColumns(rows) { - var columnSet = Object.create(null), - columns = []; - - rows.forEach(function(row) { - for (var column in row) { - if (!(column in columnSet)) { - columns.push(columnSet[column] = column); - } - } - }); - - return columns; -} - -var dsv = function(delimiter) { - var reFormat = new RegExp("[\"" + delimiter + "\n\r]"), - DELIMITER = delimiter.charCodeAt(0); - - function parse(text, f) { - var convert, columns, rows = parseRows(text, function(row, i) { - if (convert) return convert(row, i - 1); - columns = row, convert = f ? customConverter(row, f) : objectConverter(row); - }); - rows.columns = columns; - return rows; - } - - function parseRows(text, f) { - var rows = [], // output rows - N = text.length, - I = 0, // current character index - n = 0, // current line number - t, // current token - eof = N <= 0, // current token followed by EOF? - eol = false; // current token followed by EOL? - - // Strip the trailing newline. - if (text.charCodeAt(N - 1) === NEWLINE) --N; - if (text.charCodeAt(N - 1) === RETURN) --N; - - function token() { - if (eof) return EOF; - if (eol) return eol = false, EOL; - - // Unescape quotes. - var i, j = I, c; - if (text.charCodeAt(j) === QUOTE) { - while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE); - if ((i = I) >= N) eof = true; - else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true; - else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } - return text.slice(j + 1, i - 1).replace(/""/g, "\""); - } - - // Find next delimiter or newline. - while (I < N) { - if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true; - else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } - else if (c !== DELIMITER) continue; - return text.slice(j, i); - } - - // Return last token before EOF. - return eof = true, text.slice(j, N); - } - - while ((t = token()) !== EOF) { - var row = []; - while (t !== EOL && t !== EOF) row.push(t), t = token(); - if (f && (row = f(row, n++)) == null) continue; - rows.push(row); - } - - return rows; - } - - function format(rows, columns) { - if (columns == null) columns = inferColumns(rows); - return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { - return columns.map(function(column) { - return formatValue(row[column]); - }).join(delimiter); - })).join("\n"); - } - - function formatRows(rows) { - return rows.map(formatRow).join("\n"); - } - - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } - - function formatValue(text) { - return text == null ? "" - : reFormat.test(text += "") ? "\"" + text.replace(/"/g, "\"\"") + "\"" - : text; - } - - return { - parse: parse, - parseRows: parseRows, - format: format, - formatRows: formatRows - }; -}; - -var csv = dsv(","); - -var csvParse = csv.parse; -var csvParseRows = csv.parseRows; -var csvFormat = csv.format; -var csvFormatRows = csv.formatRows; - -var tsv = dsv("\t"); - -var tsvParse = tsv.parse; -var tsvParseRows = tsv.parseRows; -var tsvFormat = tsv.format; -var tsvFormatRows = tsv.formatRows; - -var center$1 = function(x, y) { - var nodes; - - if (x == null) x = 0; - if (y == null) y = 0; - - function force() { - var i, - n = nodes.length, - node, - sx = 0, - sy = 0; - - for (i = 0; i < n; ++i) { - node = nodes[i], sx += node.x, sy += node.y; - } - - for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { - node = nodes[i], node.x -= sx, node.y -= sy; - } - } - - force.initialize = function(_) { - nodes = _; - }; - - force.x = function(_) { - return arguments.length ? (x = +_, force) : x; - }; - - force.y = function(_) { - return arguments.length ? (y = +_, force) : y; - }; - - return force; -}; - -var constant$6 = function(x) { - return function() { - return x; - }; -}; - -var jiggle = function() { - return (Math.random() - 0.5) * 1e-6; -}; - -var tree_add = function(d) { - var x = +this._x.call(null, d), - y = +this._y.call(null, d); - return add(this.cover(x, y), x, y, d); -}; - -function add(tree, x, y, d) { - if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points - - var parent, - node = tree._root, - leaf = {data: d}, - x0 = tree._x0, - y0 = tree._y0, - x1 = tree._x1, - y1 = tree._y1, - xm, - ym, - xp, - yp, - right, - bottom, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return tree._root = leaf, tree; - - // Find the existing leaf for the new point, or add it. - while (node.length) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; - } - - // Is the new point is exactly coincident with the existing point? - xp = +tree._x.call(null, node.data); - yp = +tree._y.call(null, node.data); - if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; - - // Otherwise, split the leaf node until the old and new point are separated. - do { - parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); - return parent[j] = node, parent[i] = leaf, tree; -} - -function addAll(data) { - var d, i, n = data.length, - x, - y, - xz = new Array(n), - yz = new Array(n), - x0 = Infinity, - y0 = Infinity, - x1 = -Infinity, - y1 = -Infinity; - - // Compute the points and their extent. - for (i = 0; i < n; ++i) { - if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; - xz[i] = x; - yz[i] = y; - if (x < x0) x0 = x; - if (x > x1) x1 = x; - if (y < y0) y0 = y; - if (y > y1) y1 = y; - } - - // If there were no (valid) points, inherit the existing extent. - if (x1 < x0) x0 = this._x0, x1 = this._x1; - if (y1 < y0) y0 = this._y0, y1 = this._y1; - - // Expand the tree to cover the new points. - this.cover(x0, y0).cover(x1, y1); - - // Add the new points. - for (i = 0; i < n; ++i) { - add(this, xz[i], yz[i], data[i]); - } - - return this; -} - -var tree_cover = function(x, y) { - if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points - - var x0 = this._x0, - y0 = this._y0, - x1 = this._x1, - y1 = this._y1; - - // If the quadtree has no extent, initialize them. - // Integer extent are necessary so that if we later double the extent, - // the existing quadrant boundaries don’t change due to floating point error! - if (isNaN(x0)) { - x1 = (x0 = Math.floor(x)) + 1; - y1 = (y0 = Math.floor(y)) + 1; - } - - // Otherwise, double repeatedly to cover. - else if (x0 > x || x > x1 || y0 > y || y > y1) { - var z = x1 - x0, - node = this._root, - parent, - i; - - switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) { - case 0: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1); - break; - } - case 1: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1); - break; - } - case 2: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y); - break; - } - case 3: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y); - break; - } - } - - if (this._root && this._root.length) this._root = node; - } - - // If the quadtree covers the point already, just return. - else return this; - - this._x0 = x0; - this._y0 = y0; - this._x1 = x1; - this._y1 = y1; - return this; -}; - -var tree_data = function() { - var data = []; - this.visit(function(node) { - if (!node.length) do data.push(node.data); while (node = node.next) - }); - return data; -}; - -var tree_extent = function(_) { - return arguments.length - ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) - : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; -}; - -var Quad = function(node, x0, y0, x1, y1) { - this.node = node; - this.x0 = x0; - this.y0 = y0; - this.x1 = x1; - this.y1 = y1; -}; - -var tree_find = function(x, y, radius) { - var data, - x0 = this._x0, - y0 = this._y0, - x1, - y1, - x2, - y2, - x3 = this._x1, - y3 = this._y1, - quads = [], - node = this._root, - q, - i; - - if (node) quads.push(new Quad(node, x0, y0, x3, y3)); - if (radius == null) radius = Infinity; - else { - x0 = x - radius, y0 = y - radius; - x3 = x + radius, y3 = y + radius; - radius *= radius; - } - - while (q = quads.pop()) { - - // Stop searching if this quadrant can’t contain a closer node. - if (!(node = q.node) - || (x1 = q.x0) > x3 - || (y1 = q.y0) > y3 - || (x2 = q.x1) < x0 - || (y2 = q.y1) < y0) continue; - - // Bisect the current quadrant. - if (node.length) { - var xm = (x1 + x2) / 2, - ym = (y1 + y2) / 2; - - quads.push( - new Quad(node[3], xm, ym, x2, y2), - new Quad(node[2], x1, ym, xm, y2), - new Quad(node[1], xm, y1, x2, ym), - new Quad(node[0], x1, y1, xm, ym) - ); - - // Visit the closest quadrant first. - if (i = (y >= ym) << 1 | (x >= xm)) { - q = quads[quads.length - 1]; - quads[quads.length - 1] = quads[quads.length - 1 - i]; - quads[quads.length - 1 - i] = q; - } - } - - // Visit this point. (Visiting coincident points isn’t necessary!) - else { - var dx = x - +this._x.call(null, node.data), - dy = y - +this._y.call(null, node.data), - d2 = dx * dx + dy * dy; - if (d2 < radius) { - var d = Math.sqrt(radius = d2); - x0 = x - d, y0 = y - d; - x3 = x + d, y3 = y + d; - data = node.data; - } - } - } - - return data; -}; - -var tree_remove = function(d) { - if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points - - var parent, - node = this._root, - retainer, - previous, - next, - x0 = this._x0, - y0 = this._y0, - x1 = this._x1, - y1 = this._y1, - x, - y, - xm, - ym, - right, - bottom, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return this; - - // Find the leaf node for the point. - // While descending, also retain the deepest parent with a non-removed sibling. - if (node.length) while (true) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (!(parent = node, node = node[i = bottom << 1 | right])) return this; - if (!node.length) break; - if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; - } - - // Find the point to remove. - while (node.data !== d) if (!(previous = node, node = node.next)) return this; - if (next = node.next) delete node.next; - - // If there are multiple coincident points, remove just the point. - if (previous) return (next ? previous.next = next : delete previous.next), this; - - // If this is the root point, remove it. - if (!parent) return this._root = next, this; - - // Remove this leaf. - next ? parent[i] = next : delete parent[i]; - - // If the parent now contains exactly one leaf, collapse superfluous parents. - if ((node = parent[0] || parent[1] || parent[2] || parent[3]) - && node === (parent[3] || parent[2] || parent[1] || parent[0]) - && !node.length) { - if (retainer) retainer[j] = node; - else this._root = node; - } - - return this; -}; - -function removeAll(data) { - for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); - return this; -} - -var tree_root = function() { - return this._root; -}; - -var tree_size = function() { - var size = 0; - this.visit(function(node) { - if (!node.length) do ++size; while (node = node.next) - }); - return size; -}; - -var tree_visit = function(callback) { - var quads = [], q, node = this._root, child, x0, y0, x1, y1; - if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); - while (q = quads.pop()) { - if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { - var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; - if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); - if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); - if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); - if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); - } - } - return this; -}; - -var tree_visitAfter = function(callback) { - var quads = [], next = [], q; - if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); - while (q = quads.pop()) { - var node = q.node; - if (node.length) { - var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; - if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); - if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); - if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); - if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); - } - next.push(q); - } - while (q = next.pop()) { - callback(q.node, q.x0, q.y0, q.x1, q.y1); - } - return this; -}; - -function defaultX(d) { - return d[0]; -} - -var tree_x = function(_) { - return arguments.length ? (this._x = _, this) : this._x; -}; - -function defaultY(d) { - return d[1]; -} - -var tree_y = function(_) { - return arguments.length ? (this._y = _, this) : this._y; -}; - -function quadtree(nodes, x, y) { - var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN); - return nodes == null ? tree : tree.addAll(nodes); -} - -function Quadtree(x, y, x0, y0, x1, y1) { - this._x = x; - this._y = y; - this._x0 = x0; - this._y0 = y0; - this._x1 = x1; - this._y1 = y1; - this._root = undefined; -} - -function leaf_copy(leaf) { - var copy = {data: leaf.data}, next = copy; - while (leaf = leaf.next) next = next.next = {data: leaf.data}; - return copy; -} - -var treeProto = quadtree.prototype = Quadtree.prototype; - -treeProto.copy = function() { - var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), - node = this._root, - nodes, - child; - - if (!node) return copy; - - if (!node.length) return copy._root = leaf_copy(node), copy; - - nodes = [{source: node, target: copy._root = new Array(4)}]; - while (node = nodes.pop()) { - for (var i = 0; i < 4; ++i) { - if (child = node.source[i]) { - if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); - else node.target[i] = leaf_copy(child); - } - } - } - - return copy; -}; - -treeProto.add = tree_add; -treeProto.addAll = addAll; -treeProto.cover = tree_cover; -treeProto.data = tree_data; -treeProto.extent = tree_extent; -treeProto.find = tree_find; -treeProto.remove = tree_remove; -treeProto.removeAll = removeAll; -treeProto.root = tree_root; -treeProto.size = tree_size; -treeProto.visit = tree_visit; -treeProto.visitAfter = tree_visitAfter; -treeProto.x = tree_x; -treeProto.y = tree_y; - -function x(d) { - return d.x + d.vx; -} - -function y(d) { - return d.y + d.vy; -} - -var collide = function(radius) { - var nodes, - radii, - strength = 1, - iterations = 1; - - if (typeof radius !== "function") radius = constant$6(radius == null ? 1 : +radius); - - function force() { - var i, n = nodes.length, - tree, - node, - xi, - yi, - ri, - ri2; - - for (var k = 0; k < iterations; ++k) { - tree = quadtree(nodes, x, y).visitAfter(prepare); - for (i = 0; i < n; ++i) { - node = nodes[i]; - ri = radii[node.index], ri2 = ri * ri; - xi = node.x + node.vx; - yi = node.y + node.vy; - tree.visit(apply); - } - } - - function apply(quad, x0, y0, x1, y1) { - var data = quad.data, rj = quad.r, r = ri + rj; - if (data) { - if (data.index > node.index) { - var x = xi - data.x - data.vx, - y = yi - data.y - data.vy, - l = x * x + y * y; - if (l < r * r) { - if (x === 0) x = jiggle(), l += x * x; - if (y === 0) y = jiggle(), l += y * y; - l = (r - (l = Math.sqrt(l))) / l * strength; - node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); - node.vy += (y *= l) * r; - data.vx -= x * (r = 1 - r); - data.vy -= y * r; - } - } - return; - } - return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; - } - } - - function prepare(quad) { - if (quad.data) return quad.r = radii[quad.data.index]; - for (var i = quad.r = 0; i < 4; ++i) { - if (quad[i] && quad[i].r > quad.r) { - quad.r = quad[i].r; - } - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length, node; - radii = new Array(n); - for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes); - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.iterations = function(_) { - return arguments.length ? (iterations = +_, force) : iterations; - }; - - force.strength = function(_) { - return arguments.length ? (strength = +_, force) : strength; - }; - - force.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : radius; - }; - - return force; -}; - -function index(d) { - return d.index; -} - -function find(nodeById, nodeId) { - var node = nodeById.get(nodeId); - if (!node) throw new Error("missing: " + nodeId); - return node; -} - -var link = function(links) { - var id = index, - strength = defaultStrength, - strengths, - distance = constant$6(30), - distances, - nodes, - count, - bias, - iterations = 1; - - if (links == null) links = []; - - function defaultStrength(link) { - return 1 / Math.min(count[link.source.index], count[link.target.index]); - } - - function force(alpha) { - for (var k = 0, n = links.length; k < iterations; ++k) { - for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { - link = links[i], source = link.source, target = link.target; - x = target.x + target.vx - source.x - source.vx || jiggle(); - y = target.y + target.vy - source.y - source.vy || jiggle(); - l = Math.sqrt(x * x + y * y); - l = (l - distances[i]) / l * alpha * strengths[i]; - x *= l, y *= l; - target.vx -= x * (b = bias[i]); - target.vy -= y * b; - source.vx += x * (b = 1 - b); - source.vy += y * b; - } - } - } - - function initialize() { - if (!nodes) return; - - var i, - n = nodes.length, - m = links.length, - nodeById = map$1(nodes, id), - link; - - for (i = 0, count = new Array(n); i < m; ++i) { - link = links[i], link.index = i; - if (typeof link.source !== "object") link.source = find(nodeById, link.source); - if (typeof link.target !== "object") link.target = find(nodeById, link.target); - count[link.source.index] = (count[link.source.index] || 0) + 1; - count[link.target.index] = (count[link.target.index] || 0) + 1; - } - - for (i = 0, bias = new Array(m); i < m; ++i) { - link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); - } - - strengths = new Array(m), initializeStrength(); - distances = new Array(m), initializeDistance(); - } - - function initializeStrength() { - if (!nodes) return; - - for (var i = 0, n = links.length; i < n; ++i) { - strengths[i] = +strength(links[i], i, links); - } - } - - function initializeDistance() { - if (!nodes) return; - - for (var i = 0, n = links.length; i < n; ++i) { - distances[i] = +distance(links[i], i, links); - } - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.links = function(_) { - return arguments.length ? (links = _, initialize(), force) : links; - }; - - force.id = function(_) { - return arguments.length ? (id = _, force) : id; - }; - - force.iterations = function(_) { - return arguments.length ? (iterations = +_, force) : iterations; - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initializeStrength(), force) : strength; - }; - - force.distance = function(_) { - return arguments.length ? (distance = typeof _ === "function" ? _ : constant$6(+_), initializeDistance(), force) : distance; - }; - - return force; -}; - -function x$1(d) { - return d.x; -} - -function y$1(d) { - return d.y; -} - -var initialRadius = 10; -var initialAngle = Math.PI * (3 - Math.sqrt(5)); - -var simulation = function(nodes) { - var simulation, - alpha = 1, - alphaMin = 0.001, - alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), - alphaTarget = 0, - velocityDecay = 0.6, - forces = map$1(), - stepper = timer(step), - event = dispatch("tick", "end"); - - if (nodes == null) nodes = []; - - function step() { - tick(); - event.call("tick", simulation); - if (alpha < alphaMin) { - stepper.stop(); - event.call("end", simulation); - } - } - - function tick() { - var i, n = nodes.length, node; - - alpha += (alphaTarget - alpha) * alphaDecay; - - forces.each(function(force) { - force(alpha); - }); - - for (i = 0; i < n; ++i) { - node = nodes[i]; - if (node.fx == null) node.x += node.vx *= velocityDecay; - else node.x = node.fx, node.vx = 0; - if (node.fy == null) node.y += node.vy *= velocityDecay; - else node.y = node.fy, node.vy = 0; - } - } - - function initializeNodes() { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.index = i; - if (isNaN(node.x) || isNaN(node.y)) { - var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; - node.x = radius * Math.cos(angle); - node.y = radius * Math.sin(angle); - } - if (isNaN(node.vx) || isNaN(node.vy)) { - node.vx = node.vy = 0; - } - } - } - - function initializeForce(force) { - if (force.initialize) force.initialize(nodes); - return force; - } - - initializeNodes(); - - return simulation = { - tick: tick, - - restart: function() { - return stepper.restart(step), simulation; - }, - - stop: function() { - return stepper.stop(), simulation; - }, - - nodes: function(_) { - return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; - }, - - alpha: function(_) { - return arguments.length ? (alpha = +_, simulation) : alpha; - }, - - alphaMin: function(_) { - return arguments.length ? (alphaMin = +_, simulation) : alphaMin; - }, - - alphaDecay: function(_) { - return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; - }, - - alphaTarget: function(_) { - return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; - }, - - velocityDecay: function(_) { - return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; - }, - - force: function(name, _) { - return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); - }, - - find: function(x, y, radius) { - var i = 0, - n = nodes.length, - dx, - dy, - d2, - node, - closest; - - if (radius == null) radius = Infinity; - else radius *= radius; - - for (i = 0; i < n; ++i) { - node = nodes[i]; - dx = x - node.x; - dy = y - node.y; - d2 = dx * dx + dy * dy; - if (d2 < radius) closest = node, radius = d2; - } - - return closest; - }, - - on: function(name, _) { - return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); - } - }; -}; - -var manyBody = function() { - var nodes, - node, - alpha, - strength = constant$6(-30), - strengths, - distanceMin2 = 1, - distanceMax2 = Infinity, - theta2 = 0.81; - - function force(_) { - var i, n = nodes.length, tree = quadtree(nodes, x$1, y$1).visitAfter(accumulate); - for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length, node; - strengths = new Array(n); - for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); - } - - function accumulate(quad) { - var strength = 0, q, c, weight = 0, x, y, i; - - // For internal nodes, accumulate forces from child quadrants. - if (quad.length) { - for (x = y = i = 0; i < 4; ++i) { - if ((q = quad[i]) && (c = Math.abs(q.value))) { - strength += q.value, weight += c, x += c * q.x, y += c * q.y; - } - } - quad.x = x / weight; - quad.y = y / weight; - } - - // For leaf nodes, accumulate forces from coincident quadrants. - else { - q = quad; - q.x = q.data.x; - q.y = q.data.y; - do strength += strengths[q.data.index]; - while (q = q.next); - } - - quad.value = strength; - } - - function apply(quad, x1, _, x2) { - if (!quad.value) return true; - - var x = quad.x - node.x, - y = quad.y - node.y, - w = x2 - x1, - l = x * x + y * y; - - // Apply the Barnes-Hut approximation if possible. - // Limit forces for very close nodes; randomize direction if coincident. - if (w * w / theta2 < l) { - if (l < distanceMax2) { - if (x === 0) x = jiggle(), l += x * x; - if (y === 0) y = jiggle(), l += y * y; - if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); - node.vx += x * quad.value * alpha / l; - node.vy += y * quad.value * alpha / l; - } - return true; - } - - // Otherwise, process points directly. - else if (quad.length || l >= distanceMax2) return; - - // Limit forces for very close nodes; randomize direction if coincident. - if (quad.data !== node || quad.next) { - if (x === 0) x = jiggle(), l += x * x; - if (y === 0) y = jiggle(), l += y * y; - if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); - } - - do if (quad.data !== node) { - w = strengths[quad.data.index] * alpha / l; - node.vx += x * w; - node.vy += y * w; - } while (quad = quad.next); - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; - }; - - force.distanceMin = function(_) { - return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); - }; - - force.distanceMax = function(_) { - return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); - }; - - force.theta = function(_) { - return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); - }; - - return force; -}; - -var radial = function(radius, x, y) { - var nodes, - strength = constant$6(0.1), - strengths, - radiuses; - - if (typeof radius !== "function") radius = constant$6(+radius); - if (x == null) x = 0; - if (y == null) y = 0; - - function force(alpha) { - for (var i = 0, n = nodes.length; i < n; ++i) { - var node = nodes[i], - dx = node.x - x || 1e-6, - dy = node.y - y || 1e-6, - r = Math.sqrt(dx * dx + dy * dy), - k = (radiuses[i] - r) * strengths[i] * alpha / r; - node.vx += dx * k; - node.vy += dy * k; - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - radiuses = new Array(n); - for (i = 0; i < n; ++i) { - radiuses[i] = +radius(nodes[i], i, nodes); - strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); - } - } - - force.initialize = function(_) { - nodes = _, initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; - }; - - force.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : radius; - }; - - force.x = function(_) { - return arguments.length ? (x = +_, force) : x; - }; - - force.y = function(_) { - return arguments.length ? (y = +_, force) : y; - }; - - return force; -}; - -var x$2 = function(x) { - var strength = constant$6(0.1), - nodes, - strengths, - xz; - - if (typeof x !== "function") x = constant$6(x == null ? 0 : +x); - - function force(alpha) { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - xz = new Array(n); - for (i = 0; i < n; ++i) { - strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); - } - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; - }; - - force.x = function(_) { - return arguments.length ? (x = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : x; - }; - - return force; -}; - -var y$2 = function(y) { - var strength = constant$6(0.1), - nodes, - strengths, - yz; - - if (typeof y !== "function") y = constant$6(y == null ? 0 : +y); - - function force(alpha) { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - yz = new Array(n); - for (i = 0; i < n; ++i) { - strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); - } - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : strength; - }; - - force.y = function(_) { - return arguments.length ? (y = typeof _ === "function" ? _ : constant$6(+_), initialize(), force) : y; - }; - - return force; -}; - -// Computes the decimal coefficient and exponent of the specified number x with -// significant digits p, where x is positive and p is in [1, 21] or undefined. -// For example, formatDecimal(1.23) returns ["123", 0]. -var formatDecimal = function(x, p) { - if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity - var i, coefficient = x.slice(0, i); - - // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ - // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). - return [ - coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, - +x.slice(i + 1) - ]; -}; - -var exponent$1 = function(x) { - return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; -}; - -var formatGroup = function(grouping, thousands) { - return function(value, width) { - var i = value.length, - t = [], - j = 0, - g = grouping[0], - length = 0; - - while (i > 0 && g > 0) { - if (length + g + 1 > width) g = Math.max(1, width - length); - t.push(value.substring(i -= g, i + g)); - if ((length += g + 1) > width) break; - g = grouping[j = (j + 1) % grouping.length]; - } - - return t.reverse().join(thousands); - }; -}; - -var formatNumerals = function(numerals) { - return function(value) { - return value.replace(/[0-9]/g, function(i) { - return numerals[+i]; - }); - }; -}; - -var formatDefault = function(x, p) { - x = x.toPrecision(p); - - out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { - switch (x[i]) { - case ".": i0 = i1 = i; break; - case "0": if (i0 === 0) i0 = i; i1 = i; break; - case "e": break out; - default: if (i0 > 0) i0 = 0; break; - } - } - - return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; -}; - -var prefixExponent; - -var formatPrefixAuto = function(x, p) { - var d = formatDecimal(x, p); - if (!d) return x + ""; - var coefficient = d[0], - exponent = d[1], - i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, - n = coefficient.length; - return i === n ? coefficient - : i > n ? coefficient + new Array(i - n + 1).join("0") - : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) - : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! -}; - -var formatRounded = function(x, p) { - var d = formatDecimal(x, p); - if (!d) return x + ""; - var coefficient = d[0], - exponent = d[1]; - return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient - : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) - : coefficient + new Array(exponent - coefficient.length + 2).join("0"); -}; - -var formatTypes = { - "": formatDefault, - "%": function(x, p) { return (x * 100).toFixed(p); }, - "b": function(x) { return Math.round(x).toString(2); }, - "c": function(x) { return x + ""; }, - "d": function(x) { return Math.round(x).toString(10); }, - "e": function(x, p) { return x.toExponential(p); }, - "f": function(x, p) { return x.toFixed(p); }, - "g": function(x, p) { return x.toPrecision(p); }, - "o": function(x) { return Math.round(x).toString(8); }, - "p": function(x, p) { return formatRounded(x * 100, p); }, - "r": formatRounded, - "s": formatPrefixAuto, - "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, - "x": function(x) { return Math.round(x).toString(16); } -}; - -// [[fill]align][sign][symbol][0][width][,][.precision][type] -var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; - -function formatSpecifier(specifier) { - return new FormatSpecifier(specifier); -} - -formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof - -function FormatSpecifier(specifier) { - if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); - - var match, - fill = match[1] || " ", - align = match[2] || ">", - sign = match[3] || "-", - symbol = match[4] || "", - zero = !!match[5], - width = match[6] && +match[6], - comma = !!match[7], - precision = match[8] && +match[8].slice(1), - type = match[9] || ""; - - // The "n" type is an alias for ",g". - if (type === "n") comma = true, type = "g"; - - // Map invalid types to the default format. - else if (!formatTypes[type]) type = ""; - - // If zero fill is specified, padding goes after sign and before digits. - if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; - - this.fill = fill; - this.align = align; - this.sign = sign; - this.symbol = symbol; - this.zero = zero; - this.width = width; - this.comma = comma; - this.precision = precision; - this.type = type; -} - -FormatSpecifier.prototype.toString = function() { - return this.fill - + this.align - + this.sign - + this.symbol - + (this.zero ? "0" : "") - + (this.width == null ? "" : Math.max(1, this.width | 0)) - + (this.comma ? "," : "") - + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) - + this.type; -}; - -var identity$3 = function(x) { - return x; -}; - -var prefixes = ["y","z","a","f","p","n","\xB5","m","","k","M","G","T","P","E","Z","Y"]; - -var formatLocale = function(locale) { - var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3, - currency = locale.currency, - decimal = locale.decimal, - numerals = locale.numerals ? formatNumerals(locale.numerals) : identity$3, - percent = locale.percent || "%"; - - function newFormat(specifier) { - specifier = formatSpecifier(specifier); - - var fill = specifier.fill, - align = specifier.align, - sign = specifier.sign, - symbol = specifier.symbol, - zero = specifier.zero, - width = specifier.width, - comma = specifier.comma, - precision = specifier.precision, - type = specifier.type; - - // Compute the prefix and suffix. - // For SI-prefix, the suffix is lazily computed. - var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", - suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : ""; - - // What format function should we use? - // Is this an integer type? - // Can this type generate exponential notation? - var formatType = formatTypes[type], - maybeSuffix = !type || /[defgprs%]/.test(type); - - // Set the default precision if not specified, - // or clamp the specified precision to the supported range. - // For significant precision, it must be in [1, 21]. - // For fixed precision, it must be in [0, 20]. - precision = precision == null ? (type ? 6 : 12) - : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) - : Math.max(0, Math.min(20, precision)); - - function format(value) { - var valuePrefix = prefix, - valueSuffix = suffix, - i, n, c; - - if (type === "c") { - valueSuffix = formatType(value) + valueSuffix; - value = ""; - } else { - value = +value; - - // Perform the initial formatting. - var valueNegative = value < 0; - value = formatType(Math.abs(value), precision); - - // If a negative value rounds to zero during formatting, treat as positive. - if (valueNegative && +value === 0) valueNegative = false; - - // Compute the prefix and suffix. - valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; - valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); - - // Break the formatted value into the integer “value” part that can be - // grouped, and fractional or exponential “suffix” part that is not. - if (maybeSuffix) { - i = -1, n = value.length; - while (++i < n) { - if (c = value.charCodeAt(i), 48 > c || c > 57) { - valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; - value = value.slice(0, i); - break; - } - } - } - } - - // If the fill character is not "0", grouping is applied before padding. - if (comma && !zero) value = group(value, Infinity); - - // Compute the padding. - var length = valuePrefix.length + value.length + valueSuffix.length, - padding = length < width ? new Array(width - length + 1).join(fill) : ""; - - // If the fill character is "0", grouping is applied after padding. - if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; - - // Reconstruct the final output based on the desired alignment. - switch (align) { - case "<": value = valuePrefix + value + valueSuffix + padding; break; - case "=": value = valuePrefix + padding + value + valueSuffix; break; - case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break; - default: value = padding + valuePrefix + value + valueSuffix; break; - } - - return numerals(value); - } - - format.toString = function() { - return specifier + ""; - }; - - return format; - } - - function formatPrefix(specifier, value) { - var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), - e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3, - k = Math.pow(10, -e), - prefix = prefixes[8 + e / 3]; - return function(value) { - return f(k * value) + prefix; - }; - } - - return { - format: newFormat, - formatPrefix: formatPrefix - }; -}; - -var locale; - - - -defaultLocale({ - decimal: ".", - thousands: ",", - grouping: [3], - currency: ["$", ""] -}); - -function defaultLocale(definition) { - locale = formatLocale(definition); - exports.format = locale.format; - exports.formatPrefix = locale.formatPrefix; - return locale; -} - -var precisionFixed = function(step) { - return Math.max(0, -exponent$1(Math.abs(step))); -}; - -var precisionPrefix = function(step, value) { - return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step))); -}; - -var precisionRound = function(step, max) { - step = Math.abs(step), max = Math.abs(max) - step; - return Math.max(0, exponent$1(max) - exponent$1(step)) + 1; -}; - -// Adds floating point numbers with twice the normal precision. -// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and -// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) -// 305–363 (1997). -// Code adapted from GeographicLib by Charles F. F. Karney, -// http://geographiclib.sourceforge.net/ - -var adder = function() { - return new Adder; -}; - -function Adder() { - this.reset(); -} - -Adder.prototype = { - constructor: Adder, - reset: function() { - this.s = // rounded value - this.t = 0; // exact error - }, - add: function(y) { - add$1(temp, y, this.t); - add$1(this, temp.s, this.s); - if (this.s) this.t += temp.t; - else this.s = temp.t; - }, - valueOf: function() { - return this.s; - } -}; - -var temp = new Adder; - -function add$1(adder, a, b) { - var x = adder.s = a + b, - bv = x - a, - av = x - bv; - adder.t = (a - av) + (b - bv); -} - -var epsilon$2 = 1e-6; -var epsilon2$1 = 1e-12; -var pi$3 = Math.PI; -var halfPi$2 = pi$3 / 2; -var quarterPi = pi$3 / 4; -var tau$3 = pi$3 * 2; - -var degrees$1 = 180 / pi$3; -var radians = pi$3 / 180; - -var abs = Math.abs; -var atan = Math.atan; -var atan2 = Math.atan2; -var cos$1 = Math.cos; -var ceil = Math.ceil; -var exp = Math.exp; - -var log = Math.log; -var pow = Math.pow; -var sin$1 = Math.sin; -var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }; -var sqrt = Math.sqrt; -var tan = Math.tan; - -function acos(x) { - return x > 1 ? 0 : x < -1 ? pi$3 : Math.acos(x); -} - -function asin(x) { - return x > 1 ? halfPi$2 : x < -1 ? -halfPi$2 : Math.asin(x); -} - -function haversin(x) { - return (x = sin$1(x / 2)) * x; -} - -function noop$1() {} - -function streamGeometry(geometry, stream) { - if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { - streamGeometryType[geometry.type](geometry, stream); - } -} - -var streamObjectType = { - Feature: function(object, stream) { - streamGeometry(object.geometry, stream); - }, - FeatureCollection: function(object, stream) { - var features = object.features, i = -1, n = features.length; - while (++i < n) streamGeometry(features[i].geometry, stream); - } -}; - -var streamGeometryType = { - Sphere: function(object, stream) { - stream.sphere(); - }, - Point: function(object, stream) { - object = object.coordinates; - stream.point(object[0], object[1], object[2]); - }, - MultiPoint: function(object, stream) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]); - }, - LineString: function(object, stream) { - streamLine(object.coordinates, stream, 0); - }, - MultiLineString: function(object, stream) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) streamLine(coordinates[i], stream, 0); - }, - Polygon: function(object, stream) { - streamPolygon(object.coordinates, stream); - }, - MultiPolygon: function(object, stream) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) streamPolygon(coordinates[i], stream); - }, - GeometryCollection: function(object, stream) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) streamGeometry(geometries[i], stream); - } -}; - -function streamLine(coordinates, stream, closed) { - var i = -1, n = coordinates.length - closed, coordinate; - stream.lineStart(); - while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); - stream.lineEnd(); -} - -function streamPolygon(coordinates, stream) { - var i = -1, n = coordinates.length; - stream.polygonStart(); - while (++i < n) streamLine(coordinates[i], stream, 1); - stream.polygonEnd(); -} - -var geoStream = function(object, stream) { - if (object && streamObjectType.hasOwnProperty(object.type)) { - streamObjectType[object.type](object, stream); - } else { - streamGeometry(object, stream); - } -}; - -var areaRingSum = adder(); - -var areaSum = adder(); -var lambda00; -var phi00; -var lambda0; -var cosPhi0; -var sinPhi0; - -var areaStream = { - point: noop$1, - lineStart: noop$1, - lineEnd: noop$1, - polygonStart: function() { - areaRingSum.reset(); - areaStream.lineStart = areaRingStart; - areaStream.lineEnd = areaRingEnd; - }, - polygonEnd: function() { - var areaRing = +areaRingSum; - areaSum.add(areaRing < 0 ? tau$3 + areaRing : areaRing); - this.lineStart = this.lineEnd = this.point = noop$1; - }, - sphere: function() { - areaSum.add(tau$3); - } -}; - -function areaRingStart() { - areaStream.point = areaPointFirst; -} - -function areaRingEnd() { - areaPoint(lambda00, phi00); -} - -function areaPointFirst(lambda, phi) { - areaStream.point = areaPoint; - lambda00 = lambda, phi00 = phi; - lambda *= radians, phi *= radians; - lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi); -} - -function areaPoint(lambda, phi) { - lambda *= radians, phi *= radians; - phi = phi / 2 + quarterPi; // half the angular distance from south pole - - // Spherical excess E for a spherical triangle with vertices: south pole, - // previous point, current point. Uses a formula derived from Cagnoli’s - // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). - var dLambda = lambda - lambda0, - sdLambda = dLambda >= 0 ? 1 : -1, - adLambda = sdLambda * dLambda, - cosPhi = cos$1(phi), - sinPhi = sin$1(phi), - k = sinPhi0 * sinPhi, - u = cosPhi0 * cosPhi + k * cos$1(adLambda), - v = k * sdLambda * sin$1(adLambda); - areaRingSum.add(atan2(v, u)); - - // Advance the previous points. - lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; -} - -var area = function(object) { - areaSum.reset(); - geoStream(object, areaStream); - return areaSum * 2; -}; - -function spherical(cartesian) { - return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])]; -} - -function cartesian(spherical) { - var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi); - return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)]; -} - -function cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; -} - -function cartesianCross(a, b) { - return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]; -} - -// TODO return a -function cartesianAddInPlace(a, b) { - a[0] += b[0], a[1] += b[1], a[2] += b[2]; -} - -function cartesianScale(vector, k) { - return [vector[0] * k, vector[1] * k, vector[2] * k]; -} - -// TODO return d -function cartesianNormalizeInPlace(d) { - var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); - d[0] /= l, d[1] /= l, d[2] /= l; -} - -var lambda0$1; -var phi0; -var lambda1; -var phi1; -var lambda2; -var lambda00$1; -var phi00$1; -var p0; -var deltaSum = adder(); -var ranges; -var range; - -var boundsStream = { - point: boundsPoint, - lineStart: boundsLineStart, - lineEnd: boundsLineEnd, - polygonStart: function() { - boundsStream.point = boundsRingPoint; - boundsStream.lineStart = boundsRingStart; - boundsStream.lineEnd = boundsRingEnd; - deltaSum.reset(); - areaStream.polygonStart(); - }, - polygonEnd: function() { - areaStream.polygonEnd(); - boundsStream.point = boundsPoint; - boundsStream.lineStart = boundsLineStart; - boundsStream.lineEnd = boundsLineEnd; - if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); - else if (deltaSum > epsilon$2) phi1 = 90; - else if (deltaSum < -epsilon$2) phi0 = -90; - range[0] = lambda0$1, range[1] = lambda1; - } -}; - -function boundsPoint(lambda, phi) { - ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]); - if (phi < phi0) phi0 = phi; - if (phi > phi1) phi1 = phi; -} - -function linePoint(lambda, phi) { - var p = cartesian([lambda * radians, phi * radians]); - if (p0) { - var normal = cartesianCross(p0, p), - equatorial = [normal[1], -normal[0], 0], - inflection = cartesianCross(equatorial, normal); - cartesianNormalizeInPlace(inflection); - inflection = spherical(inflection); - var delta = lambda - lambda2, - sign$$1 = delta > 0 ? 1 : -1, - lambdai = inflection[0] * degrees$1 * sign$$1, - phii, - antimeridian = abs(delta) > 180; - if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { - phii = inflection[1] * degrees$1; - if (phii > phi1) phi1 = phii; - } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { - phii = -inflection[1] * degrees$1; - if (phii < phi0) phi0 = phii; - } else { - if (phi < phi0) phi0 = phi; - if (phi > phi1) phi1 = phi; - } - if (antimeridian) { - if (lambda < lambda2) { - if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; - } else { - if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; - } - } else { - if (lambda1 >= lambda0$1) { - if (lambda < lambda0$1) lambda0$1 = lambda; - if (lambda > lambda1) lambda1 = lambda; - } else { - if (lambda > lambda2) { - if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; - } else { - if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; - } - } - } - } else { - ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]); - } - if (phi < phi0) phi0 = phi; - if (phi > phi1) phi1 = phi; - p0 = p, lambda2 = lambda; -} - -function boundsLineStart() { - boundsStream.point = linePoint; -} - -function boundsLineEnd() { - range[0] = lambda0$1, range[1] = lambda1; - boundsStream.point = boundsPoint; - p0 = null; -} - -function boundsRingPoint(lambda, phi) { - if (p0) { - var delta = lambda - lambda2; - deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); - } else { - lambda00$1 = lambda, phi00$1 = phi; - } - areaStream.point(lambda, phi); - linePoint(lambda, phi); -} - -function boundsRingStart() { - areaStream.lineStart(); -} - -function boundsRingEnd() { - boundsRingPoint(lambda00$1, phi00$1); - areaStream.lineEnd(); - if (abs(deltaSum) > epsilon$2) lambda0$1 = -(lambda1 = 180); - range[0] = lambda0$1, range[1] = lambda1; - p0 = null; -} - -// Finds the left-right distance between two longitudes. -// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want -// the distance between ±180° to be 360°. -function angle(lambda0, lambda1) { - return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; -} - -function rangeCompare(a, b) { - return a[0] - b[0]; -} - -function rangeContains(range, x) { - return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; -} - -var bounds = function(feature) { - var i, n, a, b, merged, deltaMax, delta; - - phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity); - ranges = []; - geoStream(feature, boundsStream); - - // First, sort ranges by their minimum longitudes. - if (n = ranges.length) { - ranges.sort(rangeCompare); - - // Then, merge any ranges that overlap. - for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { - b = ranges[i]; - if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { - if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; - if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; - } else { - merged.push(a = b); - } - } - - // Finally, find the largest gap between the merged ranges. - // The final bounding box will be the inverse of this gap. - for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { - b = merged[i]; - if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1]; - } - } - - ranges = range = null; - - return lambda0$1 === Infinity || phi0 === Infinity - ? [[NaN, NaN], [NaN, NaN]] - : [[lambda0$1, phi0], [lambda1, phi1]]; -}; - -var W0; -var W1; -var X0; -var Y0; -var Z0; -var X1; -var Y1; -var Z1; -var X2; -var Y2; -var Z2; -var lambda00$2; -var phi00$2; -var x0; -var y0; -var z0; // previous point - -var centroidStream = { - sphere: noop$1, - point: centroidPoint, - lineStart: centroidLineStart, - lineEnd: centroidLineEnd, - polygonStart: function() { - centroidStream.lineStart = centroidRingStart; - centroidStream.lineEnd = centroidRingEnd; - }, - polygonEnd: function() { - centroidStream.lineStart = centroidLineStart; - centroidStream.lineEnd = centroidLineEnd; - } -}; - -// Arithmetic mean of Cartesian vectors. -function centroidPoint(lambda, phi) { - lambda *= radians, phi *= radians; - var cosPhi = cos$1(phi); - centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)); -} - -function centroidPointCartesian(x, y, z) { - ++W0; - X0 += (x - X0) / W0; - Y0 += (y - Y0) / W0; - Z0 += (z - Z0) / W0; -} - -function centroidLineStart() { - centroidStream.point = centroidLinePointFirst; -} - -function centroidLinePointFirst(lambda, phi) { - lambda *= radians, phi *= radians; - var cosPhi = cos$1(phi); - x0 = cosPhi * cos$1(lambda); - y0 = cosPhi * sin$1(lambda); - z0 = sin$1(phi); - centroidStream.point = centroidLinePoint; - centroidPointCartesian(x0, y0, z0); -} - -function centroidLinePoint(lambda, phi) { - lambda *= radians, phi *= radians; - var cosPhi = cos$1(phi), - x = cosPhi * cos$1(lambda), - y = cosPhi * sin$1(lambda), - z = sin$1(phi), - w = atan2(sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); - W1 += w; - X1 += w * (x0 + (x0 = x)); - Y1 += w * (y0 + (y0 = y)); - Z1 += w * (z0 + (z0 = z)); - centroidPointCartesian(x0, y0, z0); -} - -function centroidLineEnd() { - centroidStream.point = centroidPoint; -} - -// See J. E. Brock, The Inertia Tensor for a Spherical Triangle, -// J. Applied Mechanics 42, 239 (1975). -function centroidRingStart() { - centroidStream.point = centroidRingPointFirst; -} - -function centroidRingEnd() { - centroidRingPoint(lambda00$2, phi00$2); - centroidStream.point = centroidPoint; -} - -function centroidRingPointFirst(lambda, phi) { - lambda00$2 = lambda, phi00$2 = phi; - lambda *= radians, phi *= radians; - centroidStream.point = centroidRingPoint; - var cosPhi = cos$1(phi); - x0 = cosPhi * cos$1(lambda); - y0 = cosPhi * sin$1(lambda); - z0 = sin$1(phi); - centroidPointCartesian(x0, y0, z0); -} - -function centroidRingPoint(lambda, phi) { - lambda *= radians, phi *= radians; - var cosPhi = cos$1(phi), - x = cosPhi * cos$1(lambda), - y = cosPhi * sin$1(lambda), - z = sin$1(phi), - cx = y0 * z - z0 * y, - cy = z0 * x - x0 * z, - cz = x0 * y - y0 * x, - m = sqrt(cx * cx + cy * cy + cz * cz), - w = asin(m), // line weight = angle - v = m && -w / m; // area weight multiplier - X2 += v * cx; - Y2 += v * cy; - Z2 += v * cz; - W1 += w; - X1 += w * (x0 + (x0 = x)); - Y1 += w * (y0 + (y0 = y)); - Z1 += w * (z0 + (z0 = z)); - centroidPointCartesian(x0, y0, z0); -} - -var centroid = function(object) { - W0 = W1 = - X0 = Y0 = Z0 = - X1 = Y1 = Z1 = - X2 = Y2 = Z2 = 0; - geoStream(object, centroidStream); - - var x = X2, - y = Y2, - z = Z2, - m = x * x + y * y + z * z; - - // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid. - if (m < epsilon2$1) { - x = X1, y = Y1, z = Z1; - // If the feature has zero length, fall back to arithmetic mean of point vectors. - if (W1 < epsilon$2) x = X0, y = Y0, z = Z0; - m = x * x + y * y + z * z; - // If the feature still has an undefined ccentroid, then return. - if (m < epsilon2$1) return [NaN, NaN]; - } - - return [atan2(y, x) * degrees$1, asin(z / sqrt(m)) * degrees$1]; -}; - -var constant$7 = function(x) { - return function() { - return x; - }; -}; - -var compose = function(a, b) { - - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); - } - - if (a.invert && b.invert) compose.invert = function(x, y) { - return x = b.invert(x, y), x && a.invert(x[0], x[1]); - }; - - return compose; -}; - -function rotationIdentity(lambda, phi) { - return [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi]; -} - -rotationIdentity.invert = rotationIdentity; - -function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { - return (deltaLambda %= tau$3) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) - : rotationLambda(deltaLambda)) - : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) - : rotationIdentity); -} - -function forwardRotationLambda(deltaLambda) { - return function(lambda, phi) { - return lambda += deltaLambda, [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi]; - }; -} - -function rotationLambda(deltaLambda) { - var rotation = forwardRotationLambda(deltaLambda); - rotation.invert = forwardRotationLambda(-deltaLambda); - return rotation; -} - -function rotationPhiGamma(deltaPhi, deltaGamma) { - var cosDeltaPhi = cos$1(deltaPhi), - sinDeltaPhi = sin$1(deltaPhi), - cosDeltaGamma = cos$1(deltaGamma), - sinDeltaGamma = sin$1(deltaGamma); - - function rotation(lambda, phi) { - var cosPhi = cos$1(phi), - x = cos$1(lambda) * cosPhi, - y = sin$1(lambda) * cosPhi, - z = sin$1(phi), - k = z * cosDeltaPhi + x * sinDeltaPhi; - return [ - atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), - asin(k * cosDeltaGamma + y * sinDeltaGamma) - ]; - } - - rotation.invert = function(lambda, phi) { - var cosPhi = cos$1(phi), - x = cos$1(lambda) * cosPhi, - y = sin$1(lambda) * cosPhi, - z = sin$1(phi), - k = z * cosDeltaGamma - y * sinDeltaGamma; - return [ - atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), - asin(k * cosDeltaPhi - x * sinDeltaPhi) - ]; - }; - - return rotation; -} - -var rotation = function(rotate) { - rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0); - - function forward(coordinates) { - coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians); - return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; - } - - forward.invert = function(coordinates) { - coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); - return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; - }; - - return forward; -}; - -// Generates a circle centered at [0°, 0°], with a given radius and precision. -function circleStream(stream, radius, delta, direction, t0, t1) { - if (!delta) return; - var cosRadius = cos$1(radius), - sinRadius = sin$1(radius), - step = direction * delta; - if (t0 == null) { - t0 = radius + direction * tau$3; - t1 = radius - step / 2; - } else { - t0 = circleRadius(cosRadius, t0); - t1 = circleRadius(cosRadius, t1); - if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$3; - } - for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { - point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]); - stream.point(point[0], point[1]); - } -} - -// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. -function circleRadius(cosRadius, point) { - point = cartesian(point), point[0] -= cosRadius; - cartesianNormalizeInPlace(point); - var radius = acos(-point[1]); - return ((-point[2] < 0 ? -radius : radius) + tau$3 - epsilon$2) % tau$3; -} - -var circle = function() { - var center = constant$7([0, 0]), - radius = constant$7(90), - precision = constant$7(6), - ring, - rotate, - stream = {point: point}; - - function point(x, y) { - ring.push(x = rotate(x, y)); - x[0] *= degrees$1, x[1] *= degrees$1; - } - - function circle() { - var c = center.apply(this, arguments), - r = radius.apply(this, arguments) * radians, - p = precision.apply(this, arguments) * radians; - ring = []; - rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; - circleStream(stream, r, p, 1); - c = {type: "Polygon", coordinates: [ring]}; - ring = rotate = null; - return c; - } - - circle.center = function(_) { - return arguments.length ? (center = typeof _ === "function" ? _ : constant$7([+_[0], +_[1]]), circle) : center; - }; - - circle.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), circle) : radius; - }; - - circle.precision = function(_) { - return arguments.length ? (precision = typeof _ === "function" ? _ : constant$7(+_), circle) : precision; - }; - - return circle; -}; - -var clipBuffer = function() { - var lines = [], - line; - return { - point: function(x, y) { - line.push([x, y]); - }, - lineStart: function() { - lines.push(line = []); - }, - lineEnd: noop$1, - rejoin: function() { - if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); - }, - result: function() { - var result = lines; - lines = []; - line = null; - return result; - } - }; -}; - -var pointEqual = function(a, b) { - return abs(a[0] - b[0]) < epsilon$2 && abs(a[1] - b[1]) < epsilon$2; -}; - -function Intersection(point, points, other, entry) { - this.x = point; - this.z = points; - this.o = other; // another intersection - this.e = entry; // is an entry? - this.v = false; // visited - this.n = this.p = null; // next & previous -} - -// A generalized polygon clipping algorithm: given a polygon that has been cut -// into its visible line segments, and rejoins the segments by interpolating -// along the clip edge. -var clipRejoin = function(segments, compareIntersection, startInside, interpolate, stream) { - var subject = [], - clip = [], - i, - n; - - segments.forEach(function(segment) { - if ((n = segment.length - 1) <= 0) return; - var n, p0 = segment[0], p1 = segment[n], x; - - // If the first and last points of a segment are coincident, then treat as a - // closed ring. TODO if all rings are closed, then the winding order of the - // exterior ring should be checked. - if (pointEqual(p0, p1)) { - stream.lineStart(); - for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); - stream.lineEnd(); - return; - } - - subject.push(x = new Intersection(p0, segment, null, true)); - clip.push(x.o = new Intersection(p0, null, x, false)); - subject.push(x = new Intersection(p1, segment, null, false)); - clip.push(x.o = new Intersection(p1, null, x, true)); - }); - - if (!subject.length) return; - - clip.sort(compareIntersection); - link$1(subject); - link$1(clip); - - for (i = 0, n = clip.length; i < n; ++i) { - clip[i].e = startInside = !startInside; - } - - var start = subject[0], - points, - point; - - while (1) { - // Find first unvisited intersection. - var current = start, - isSubject = true; - while (current.v) if ((current = current.n) === start) return; - points = current.z; - stream.lineStart(); - do { - current.v = current.o.v = true; - if (current.e) { - if (isSubject) { - for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.n.x, 1, stream); - } - current = current.n; - } else { - if (isSubject) { - points = current.p.z; - for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.p.x, -1, stream); - } - current = current.p; - } - current = current.o; - points = current.z; - isSubject = !isSubject; - } while (!current.v); - stream.lineEnd(); - } -}; - -function link$1(array) { - if (!(n = array.length)) return; - var n, - i = 0, - a = array[0], - b; - while (++i < n) { - a.n = b = array[i]; - b.p = a; - a = b; - } - a.n = b = array[0]; - b.p = a; -} - -var sum$1 = adder(); - -var polygonContains = function(polygon, point) { - var lambda = point[0], - phi = point[1], - normal = [sin$1(lambda), -cos$1(lambda), 0], - angle = 0, - winding = 0; - - sum$1.reset(); - - for (var i = 0, n = polygon.length; i < n; ++i) { - if (!(m = (ring = polygon[i]).length)) continue; - var ring, - m, - point0 = ring[m - 1], - lambda0 = point0[0], - phi0 = point0[1] / 2 + quarterPi, - sinPhi0 = sin$1(phi0), - cosPhi0 = cos$1(phi0); - - for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { - var point1 = ring[j], - lambda1 = point1[0], - phi1 = point1[1] / 2 + quarterPi, - sinPhi1 = sin$1(phi1), - cosPhi1 = cos$1(phi1), - delta = lambda1 - lambda0, - sign$$1 = delta >= 0 ? 1 : -1, - absDelta = sign$$1 * delta, - antimeridian = absDelta > pi$3, - k = sinPhi0 * sinPhi1; - - sum$1.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta))); - angle += antimeridian ? delta + sign$$1 * tau$3 : delta; - - // Are the longitudes either side of the point’s meridian (lambda), - // and are the latitudes smaller than the parallel (phi)? - if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { - var arc = cartesianCross(cartesian(point0), cartesian(point1)); - cartesianNormalizeInPlace(arc); - var intersection = cartesianCross(normal, arc); - cartesianNormalizeInPlace(intersection); - var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]); - if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { - winding += antimeridian ^ delta >= 0 ? 1 : -1; - } - } - } - } - - // First, determine whether the South pole is inside or outside: - // - // It is inside if: - // * the polygon winds around it in a clockwise direction. - // * the polygon does not (cumulatively) wind around it, but has a negative - // (counter-clockwise) area. - // - // Second, count the (signed) number of times a segment crosses a lambda - // from the point to the South pole. If it is zero, then the point is the - // same side as the South pole. - - return (angle < -epsilon$2 || angle < epsilon$2 && sum$1 < -epsilon$2) ^ (winding & 1); -}; - -var clip = function(pointVisible, clipLine, interpolate, start) { - return function(sink) { - var line = clipLine(sink), - ringBuffer = clipBuffer(), - ringSink = clipLine(ringBuffer), - polygonStarted = false, - polygon, - segments, - ring; - - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - clip.point = pointRing; - clip.lineStart = ringStart; - clip.lineEnd = ringEnd; - segments = []; - polygon = []; - }, - polygonEnd: function() { - clip.point = point; - clip.lineStart = lineStart; - clip.lineEnd = lineEnd; - segments = merge(segments); - var startInside = polygonContains(polygon, start); - if (segments.length) { - if (!polygonStarted) sink.polygonStart(), polygonStarted = true; - clipRejoin(segments, compareIntersection, startInside, interpolate, sink); - } else if (startInside) { - if (!polygonStarted) sink.polygonStart(), polygonStarted = true; - sink.lineStart(); - interpolate(null, null, 1, sink); - sink.lineEnd(); - } - if (polygonStarted) sink.polygonEnd(), polygonStarted = false; - segments = polygon = null; - }, - sphere: function() { - sink.polygonStart(); - sink.lineStart(); - interpolate(null, null, 1, sink); - sink.lineEnd(); - sink.polygonEnd(); - } - }; - - function point(lambda, phi) { - if (pointVisible(lambda, phi)) sink.point(lambda, phi); - } - - function pointLine(lambda, phi) { - line.point(lambda, phi); - } - - function lineStart() { - clip.point = pointLine; - line.lineStart(); - } - - function lineEnd() { - clip.point = point; - line.lineEnd(); - } - - function pointRing(lambda, phi) { - ring.push([lambda, phi]); - ringSink.point(lambda, phi); - } - - function ringStart() { - ringSink.lineStart(); - ring = []; - } - - function ringEnd() { - pointRing(ring[0][0], ring[0][1]); - ringSink.lineEnd(); - - var clean = ringSink.clean(), - ringSegments = ringBuffer.result(), - i, n = ringSegments.length, m, - segment, - point; - - ring.pop(); - polygon.push(ring); - ring = null; - - if (!n) return; - - // No intersections. - if (clean & 1) { - segment = ringSegments[0]; - if ((m = segment.length - 1) > 0) { - if (!polygonStarted) sink.polygonStart(), polygonStarted = true; - sink.lineStart(); - for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]); - sink.lineEnd(); - } - return; - } - - // Rejoin connected segments. - // TODO reuse ringBuffer.rejoin()? - if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); - - segments.push(ringSegments.filter(validSegment)); - } - - return clip; - }; -}; - -function validSegment(segment) { - return segment.length > 1; -} - -// Intersections are sorted along the clip edge. For both antimeridian cutting -// and circle clipping, the same comparison is used. -function compareIntersection(a, b) { - return ((a = a.x)[0] < 0 ? a[1] - halfPi$2 - epsilon$2 : halfPi$2 - a[1]) - - ((b = b.x)[0] < 0 ? b[1] - halfPi$2 - epsilon$2 : halfPi$2 - b[1]); -} - -var clipAntimeridian = clip( - function() { return true; }, - clipAntimeridianLine, - clipAntimeridianInterpolate, - [-pi$3, -halfPi$2] -); - -// Takes a line and cuts into visible segments. Return values: 0 - there were -// intersections or the line was empty; 1 - no intersections; 2 - there were -// intersections, and the first and last segments should be rejoined. -function clipAntimeridianLine(stream) { - var lambda0 = NaN, - phi0 = NaN, - sign0 = NaN, - clean; // no intersections - - return { - lineStart: function() { - stream.lineStart(); - clean = 1; - }, - point: function(lambda1, phi1) { - var sign1 = lambda1 > 0 ? pi$3 : -pi$3, - delta = abs(lambda1 - lambda0); - if (abs(delta - pi$3) < epsilon$2) { // line crosses a pole - stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$2 : -halfPi$2); - stream.point(sign0, phi0); - stream.lineEnd(); - stream.lineStart(); - stream.point(sign1, phi0); - stream.point(lambda1, phi0); - clean = 0; - } else if (sign0 !== sign1 && delta >= pi$3) { // line crosses antimeridian - if (abs(lambda0 - sign0) < epsilon$2) lambda0 -= sign0 * epsilon$2; // handle degeneracies - if (abs(lambda1 - sign1) < epsilon$2) lambda1 -= sign1 * epsilon$2; - phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); - stream.point(sign0, phi0); - stream.lineEnd(); - stream.lineStart(); - stream.point(sign1, phi0); - clean = 0; - } - stream.point(lambda0 = lambda1, phi0 = phi1); - sign0 = sign1; - }, - lineEnd: function() { - stream.lineEnd(); - lambda0 = phi0 = NaN; - }, - clean: function() { - return 2 - clean; // if intersections, rejoin first and last segments - } - }; -} - -function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { - var cosPhi0, - cosPhi1, - sinLambda0Lambda1 = sin$1(lambda0 - lambda1); - return abs(sinLambda0Lambda1) > epsilon$2 - ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1) - - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0)) - / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) - : (phi0 + phi1) / 2; -} - -function clipAntimeridianInterpolate(from, to, direction, stream) { - var phi; - if (from == null) { - phi = direction * halfPi$2; - stream.point(-pi$3, phi); - stream.point(0, phi); - stream.point(pi$3, phi); - stream.point(pi$3, 0); - stream.point(pi$3, -phi); - stream.point(0, -phi); - stream.point(-pi$3, -phi); - stream.point(-pi$3, 0); - stream.point(-pi$3, phi); - } else if (abs(from[0] - to[0]) > epsilon$2) { - var lambda = from[0] < to[0] ? pi$3 : -pi$3; - phi = direction * lambda / 2; - stream.point(-lambda, phi); - stream.point(0, phi); - stream.point(lambda, phi); - } else { - stream.point(to[0], to[1]); - } -} - -var clipCircle = function(radius) { - var cr = cos$1(radius), - delta = 6 * radians, - smallRadius = cr > 0, - notHemisphere = abs(cr) > epsilon$2; // TODO optimise for this common case - - function interpolate(from, to, direction, stream) { - circleStream(stream, radius, delta, direction, from, to); - } - - function visible(lambda, phi) { - return cos$1(lambda) * cos$1(phi) > cr; - } - - // Takes a line and cuts into visible segments. Return values used for polygon - // clipping: 0 - there were intersections or the line was empty; 1 - no - // intersections 2 - there were intersections, and the first and last segments - // should be rejoined. - function clipLine(stream) { - var point0, // previous point - c0, // code for previous point - v0, // visibility of previous point - v00, // visibility of first point - clean; // no intersections - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(lambda, phi) { - var point1 = [lambda, phi], - point2, - v = visible(lambda, phi), - c = smallRadius - ? v ? 0 : code(lambda, phi) - : v ? code(lambda + (lambda < 0 ? pi$3 : -pi$3), phi) : 0; - if (!point0 && (v00 = v0 = v)) stream.lineStart(); - // Handle degeneracies. - // TODO ignore if not clipping polygons. - if (v !== v0) { - point2 = intersect(point0, point1); - if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) { - point1[0] += epsilon$2; - point1[1] += epsilon$2; - v = visible(point1[0], point1[1]); - } - } - if (v !== v0) { - clean = 0; - if (v) { - // outside going in - stream.lineStart(); - point2 = intersect(point1, point0); - stream.point(point2[0], point2[1]); - } else { - // inside going out - point2 = intersect(point0, point1); - stream.point(point2[0], point2[1]); - stream.lineEnd(); - } - point0 = point2; - } else if (notHemisphere && point0 && smallRadius ^ v) { - var t; - // If the codes for two points are different, or are both zero, - // and there this segment intersects with the small circle. - if (!(c & c0) && (t = intersect(point1, point0, true))) { - clean = 0; - if (smallRadius) { - stream.lineStart(); - stream.point(t[0][0], t[0][1]); - stream.point(t[1][0], t[1][1]); - stream.lineEnd(); - } else { - stream.point(t[1][0], t[1][1]); - stream.lineEnd(); - stream.lineStart(); - stream.point(t[0][0], t[0][1]); - } - } - } - if (v && (!point0 || !pointEqual(point0, point1))) { - stream.point(point1[0], point1[1]); - } - point0 = point1, v0 = v, c0 = c; - }, - lineEnd: function() { - if (v0) stream.lineEnd(); - point0 = null; - }, - // Rejoin first and last segments if there were intersections and the first - // and last points were visible. - clean: function() { - return clean | ((v00 && v0) << 1); - } - }; - } - - // Intersects the great circle between a and b with the clip circle. - function intersect(a, b, two) { - var pa = cartesian(a), - pb = cartesian(b); - - // We have two planes, n1.p = d1 and n2.p = d2. - // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⚯ n2). - var n1 = [1, 0, 0], // normal - n2 = cartesianCross(pa, pb), - n2n2 = cartesianDot(n2, n2), - n1n2 = n2[0], // cartesianDot(n1, n2), - determinant = n2n2 - n1n2 * n1n2; - - // Two polar points. - if (!determinant) return !two && a; - - var c1 = cr * n2n2 / determinant, - c2 = -cr * n1n2 / determinant, - n1xn2 = cartesianCross(n1, n2), - A = cartesianScale(n1, c1), - B = cartesianScale(n2, c2); - cartesianAddInPlace(A, B); - - // Solve |p(t)|^2 = 1. - var u = n1xn2, - w = cartesianDot(A, u), - uu = cartesianDot(u, u), - t2 = w * w - uu * (cartesianDot(A, A) - 1); - - if (t2 < 0) return; - - var t = sqrt(t2), - q = cartesianScale(u, (-w - t) / uu); - cartesianAddInPlace(q, A); - q = spherical(q); - - if (!two) return q; - - // Two intersection points. - var lambda0 = a[0], - lambda1 = b[0], - phi0 = a[1], - phi1 = b[1], - z; - - if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z; - - var delta = lambda1 - lambda0, - polar = abs(delta - pi$3) < epsilon$2, - meridian = polar || delta < epsilon$2; - - if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; - - // Check that the first point is between a and b. - if (meridian - ? polar - ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$2 ? phi0 : phi1) - : phi0 <= q[1] && q[1] <= phi1 - : delta > pi$3 ^ (lambda0 <= q[0] && q[0] <= lambda1)) { - var q1 = cartesianScale(u, (-w + t) / uu); - cartesianAddInPlace(q1, A); - return [q, spherical(q1)]; - } - } - - // Generates a 4-bit vector representing the location of a point relative to - // the small circle's bounding box. - function code(lambda, phi) { - var r = smallRadius ? radius : pi$3 - radius, - code = 0; - if (lambda < -r) code |= 1; // left - else if (lambda > r) code |= 2; // right - if (phi < -r) code |= 4; // below - else if (phi > r) code |= 8; // above - return code; - } - - return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$3, radius - pi$3]); -}; - -var clipLine = function(a, b, x0, y0, x1, y1) { - var ax = a[0], - ay = a[1], - bx = b[0], - by = b[1], - t0 = 0, - t1 = 1, - dx = bx - ax, - dy = by - ay, - r; - - r = x0 - ax; - if (!dx && r > 0) return; - r /= dx; - if (dx < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dx > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - - r = x1 - ax; - if (!dx && r < 0) return; - r /= dx; - if (dx < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dx > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - - r = y0 - ay; - if (!dy && r > 0) return; - r /= dy; - if (dy < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dy > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - - r = y1 - ay; - if (!dy && r < 0) return; - r /= dy; - if (dy < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dy > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - - if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy; - if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy; - return true; -}; - -var clipMax = 1e9; -var clipMin = -clipMax; - -// TODO Use d3-polygon’s polygonContains here for the ring check? -// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? - -function clipRectangle(x0, y0, x1, y1) { - - function visible(x, y) { - return x0 <= x && x <= x1 && y0 <= y && y <= y1; - } - - function interpolate(from, to, direction, stream) { - var a = 0, a1 = 0; - if (from == null - || (a = corner(from, direction)) !== (a1 = corner(to, direction)) - || comparePoint(from, to) < 0 ^ direction > 0) { - do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); - while ((a = (a + direction + 4) % 4) !== a1); - } else { - stream.point(to[0], to[1]); - } - } - - function corner(p, direction) { - return abs(p[0] - x0) < epsilon$2 ? direction > 0 ? 0 : 3 - : abs(p[0] - x1) < epsilon$2 ? direction > 0 ? 2 : 1 - : abs(p[1] - y0) < epsilon$2 ? direction > 0 ? 1 : 0 - : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon - } - - function compareIntersection(a, b) { - return comparePoint(a.x, b.x); - } - - function comparePoint(a, b) { - var ca = corner(a, 1), - cb = corner(b, 1); - return ca !== cb ? ca - cb - : ca === 0 ? b[1] - a[1] - : ca === 1 ? a[0] - b[0] - : ca === 2 ? a[1] - b[1] - : b[0] - a[0]; - } - - return function(stream) { - var activeStream = stream, - bufferStream = clipBuffer(), - segments, - polygon, - ring, - x__, y__, v__, // first point - x_, y_, v_, // previous point - first, - clean; - - var clipStream = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: polygonStart, - polygonEnd: polygonEnd - }; - - function point(x, y) { - if (visible(x, y)) activeStream.point(x, y); - } - - function polygonInside() { - var winding = 0; - - for (var i = 0, n = polygon.length; i < n; ++i) { - for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { - a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; - if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; } - else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; } - } - } - - return winding; - } - - // Buffer geometry within a polygon and then clip it en masse. - function polygonStart() { - activeStream = bufferStream, segments = [], polygon = [], clean = true; - } - - function polygonEnd() { - var startInside = polygonInside(), - cleanInside = clean && startInside, - visible = (segments = merge(segments)).length; - if (cleanInside || visible) { - stream.polygonStart(); - if (cleanInside) { - stream.lineStart(); - interpolate(null, null, 1, stream); - stream.lineEnd(); - } - if (visible) { - clipRejoin(segments, compareIntersection, startInside, interpolate, stream); - } - stream.polygonEnd(); - } - activeStream = stream, segments = polygon = ring = null; - } - - function lineStart() { - clipStream.point = linePoint; - if (polygon) polygon.push(ring = []); - first = true; - v_ = false; - x_ = y_ = NaN; - } - - // TODO rather than special-case polygons, simply handle them separately. - // Ideally, coincident intersection points should be jittered to avoid - // clipping issues. - function lineEnd() { - if (segments) { - linePoint(x__, y__); - if (v__ && v_) bufferStream.rejoin(); - segments.push(bufferStream.result()); - } - clipStream.point = point; - if (v_) activeStream.lineEnd(); - } - - function linePoint(x, y) { - var v = visible(x, y); - if (polygon) ring.push([x, y]); - if (first) { - x__ = x, y__ = y, v__ = v; - first = false; - if (v) { - activeStream.lineStart(); - activeStream.point(x, y); - } - } else { - if (v && v_) activeStream.point(x, y); - else { - var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], - b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; - if (clipLine(a, b, x0, y0, x1, y1)) { - if (!v_) { - activeStream.lineStart(); - activeStream.point(a[0], a[1]); - } - activeStream.point(b[0], b[1]); - if (!v) activeStream.lineEnd(); - clean = false; - } else if (v) { - activeStream.lineStart(); - activeStream.point(x, y); - clean = false; - } - } - } - x_ = x, y_ = y, v_ = v; - } - - return clipStream; - }; -} - -var extent$1 = function() { - var x0 = 0, - y0 = 0, - x1 = 960, - y1 = 500, - cache, - cacheStream, - clip; - - return clip = { - stream: function(stream) { - return cache && cacheStream === stream ? cache : cache = clipRectangle(x0, y0, x1, y1)(cacheStream = stream); - }, - extent: function(_) { - return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]]; - } - }; -}; - -var lengthSum = adder(); -var lambda0$2; -var sinPhi0$1; -var cosPhi0$1; - -var lengthStream = { - sphere: noop$1, - point: noop$1, - lineStart: lengthLineStart, - lineEnd: noop$1, - polygonStart: noop$1, - polygonEnd: noop$1 -}; - -function lengthLineStart() { - lengthStream.point = lengthPointFirst; - lengthStream.lineEnd = lengthLineEnd; -} - -function lengthLineEnd() { - lengthStream.point = lengthStream.lineEnd = noop$1; -} - -function lengthPointFirst(lambda, phi) { - lambda *= radians, phi *= radians; - lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi); - lengthStream.point = lengthPoint; -} - -function lengthPoint(lambda, phi) { - lambda *= radians, phi *= radians; - var sinPhi = sin$1(phi), - cosPhi = cos$1(phi), - delta = abs(lambda - lambda0$2), - cosDelta = cos$1(delta), - sinDelta = sin$1(delta), - x = cosPhi * sinDelta, - y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta, - z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta; - lengthSum.add(atan2(sqrt(x * x + y * y), z)); - lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi; -} - -var length$1 = function(object) { - lengthSum.reset(); - geoStream(object, lengthStream); - return +lengthSum; -}; - -var coordinates = [null, null]; -var object$1 = {type: "LineString", coordinates: coordinates}; - -var distance = function(a, b) { - coordinates[0] = a; - coordinates[1] = b; - return length$1(object$1); -}; - -var containsObjectType = { - Feature: function(object, point) { - return containsGeometry(object.geometry, point); - }, - FeatureCollection: function(object, point) { - var features = object.features, i = -1, n = features.length; - while (++i < n) if (containsGeometry(features[i].geometry, point)) return true; - return false; - } -}; - -var containsGeometryType = { - Sphere: function() { - return true; - }, - Point: function(object, point) { - return containsPoint(object.coordinates, point); - }, - MultiPoint: function(object, point) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) if (containsPoint(coordinates[i], point)) return true; - return false; - }, - LineString: function(object, point) { - return containsLine(object.coordinates, point); - }, - MultiLineString: function(object, point) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) if (containsLine(coordinates[i], point)) return true; - return false; - }, - Polygon: function(object, point) { - return containsPolygon(object.coordinates, point); - }, - MultiPolygon: function(object, point) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) if (containsPolygon(coordinates[i], point)) return true; - return false; - }, - GeometryCollection: function(object, point) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) if (containsGeometry(geometries[i], point)) return true; - return false; - } -}; - -function containsGeometry(geometry, point) { - return geometry && containsGeometryType.hasOwnProperty(geometry.type) - ? containsGeometryType[geometry.type](geometry, point) - : false; -} - -function containsPoint(coordinates, point) { - return distance(coordinates, point) === 0; -} - -function containsLine(coordinates, point) { - var ab = distance(coordinates[0], coordinates[1]), - ao = distance(coordinates[0], point), - ob = distance(point, coordinates[1]); - return ao + ob <= ab + epsilon$2; -} - -function containsPolygon(coordinates, point) { - return !!polygonContains(coordinates.map(ringRadians), pointRadians(point)); -} - -function ringRadians(ring) { - return ring = ring.map(pointRadians), ring.pop(), ring; -} - -function pointRadians(point) { - return [point[0] * radians, point[1] * radians]; -} - -var contains = function(object, point) { - return (object && containsObjectType.hasOwnProperty(object.type) - ? containsObjectType[object.type] - : containsGeometry)(object, point); -}; - -function graticuleX(y0, y1, dy) { - var y = sequence(y0, y1 - epsilon$2, dy).concat(y1); - return function(x) { return y.map(function(y) { return [x, y]; }); }; -} - -function graticuleY(x0, x1, dx) { - var x = sequence(x0, x1 - epsilon$2, dx).concat(x1); - return function(y) { return x.map(function(x) { return [x, y]; }); }; -} - -function graticule() { - var x1, x0, X1, X0, - y1, y0, Y1, Y0, - dx = 10, dy = dx, DX = 90, DY = 360, - x, y, X, Y, - precision = 2.5; - - function graticule() { - return {type: "MultiLineString", coordinates: lines()}; - } - - function lines() { - return sequence(ceil(X0 / DX) * DX, X1, DX).map(X) - .concat(sequence(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) - .concat(sequence(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$2; }).map(x)) - .concat(sequence(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$2; }).map(y)); - } - - graticule.lines = function() { - return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; }); - }; - - graticule.outline = function() { - return { - type: "Polygon", - coordinates: [ - X(X0).concat( - Y(Y1).slice(1), - X(X1).reverse().slice(1), - Y(Y0).reverse().slice(1)) - ] - }; - }; - - graticule.extent = function(_) { - if (!arguments.length) return graticule.extentMinor(); - return graticule.extentMajor(_).extentMinor(_); - }; - - graticule.extentMajor = function(_) { - if (!arguments.length) return [[X0, Y0], [X1, Y1]]; - X0 = +_[0][0], X1 = +_[1][0]; - Y0 = +_[0][1], Y1 = +_[1][1]; - if (X0 > X1) _ = X0, X0 = X1, X1 = _; - if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; - return graticule.precision(precision); - }; - - graticule.extentMinor = function(_) { - if (!arguments.length) return [[x0, y0], [x1, y1]]; - x0 = +_[0][0], x1 = +_[1][0]; - y0 = +_[0][1], y1 = +_[1][1]; - if (x0 > x1) _ = x0, x0 = x1, x1 = _; - if (y0 > y1) _ = y0, y0 = y1, y1 = _; - return graticule.precision(precision); - }; - - graticule.step = function(_) { - if (!arguments.length) return graticule.stepMinor(); - return graticule.stepMajor(_).stepMinor(_); - }; - - graticule.stepMajor = function(_) { - if (!arguments.length) return [DX, DY]; - DX = +_[0], DY = +_[1]; - return graticule; - }; - - graticule.stepMinor = function(_) { - if (!arguments.length) return [dx, dy]; - dx = +_[0], dy = +_[1]; - return graticule; - }; - - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = graticuleX(y0, y1, 90); - y = graticuleY(x0, x1, precision); - X = graticuleX(Y0, Y1, 90); - Y = graticuleY(X0, X1, precision); - return graticule; - }; - - return graticule - .extentMajor([[-180, -90 + epsilon$2], [180, 90 - epsilon$2]]) - .extentMinor([[-180, -80 - epsilon$2], [180, 80 + epsilon$2]]); -} - -function graticule10() { - return graticule()(); -} - -var interpolate$1 = function(a, b) { - var x0 = a[0] * radians, - y0 = a[1] * radians, - x1 = b[0] * radians, - y1 = b[1] * radians, - cy0 = cos$1(y0), - sy0 = sin$1(y0), - cy1 = cos$1(y1), - sy1 = sin$1(y1), - kx0 = cy0 * cos$1(x0), - ky0 = cy0 * sin$1(x0), - kx1 = cy1 * cos$1(x1), - ky1 = cy1 * sin$1(x1), - d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), - k = sin$1(d); - - var interpolate = d ? function(t) { - var B = sin$1(t *= d) / k, - A = sin$1(d - t) / k, - x = A * kx0 + B * kx1, - y = A * ky0 + B * ky1, - z = A * sy0 + B * sy1; - return [ - atan2(y, x) * degrees$1, - atan2(z, sqrt(x * x + y * y)) * degrees$1 - ]; - } : function() { - return [x0 * degrees$1, y0 * degrees$1]; - }; - - interpolate.distance = d; - - return interpolate; -}; - -var identity$4 = function(x) { - return x; -}; - -var areaSum$1 = adder(); -var areaRingSum$1 = adder(); -var x00; -var y00; -var x0$1; -var y0$1; - -var areaStream$1 = { - point: noop$1, - lineStart: noop$1, - lineEnd: noop$1, - polygonStart: function() { - areaStream$1.lineStart = areaRingStart$1; - areaStream$1.lineEnd = areaRingEnd$1; - }, - polygonEnd: function() { - areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$1; - areaSum$1.add(abs(areaRingSum$1)); - areaRingSum$1.reset(); - }, - result: function() { - var area = areaSum$1 / 2; - areaSum$1.reset(); - return area; - } -}; - -function areaRingStart$1() { - areaStream$1.point = areaPointFirst$1; -} - -function areaPointFirst$1(x, y) { - areaStream$1.point = areaPoint$1; - x00 = x0$1 = x, y00 = y0$1 = y; -} - -function areaPoint$1(x, y) { - areaRingSum$1.add(y0$1 * x - x0$1 * y); - x0$1 = x, y0$1 = y; -} - -function areaRingEnd$1() { - areaPoint$1(x00, y00); -} - -var x0$2 = Infinity; -var y0$2 = x0$2; -var x1 = -x0$2; -var y1 = x1; - -var boundsStream$1 = { - point: boundsPoint$1, - lineStart: noop$1, - lineEnd: noop$1, - polygonStart: noop$1, - polygonEnd: noop$1, - result: function() { - var bounds = [[x0$2, y0$2], [x1, y1]]; - x1 = y1 = -(y0$2 = x0$2 = Infinity); - return bounds; - } -}; - -function boundsPoint$1(x, y) { - if (x < x0$2) x0$2 = x; - if (x > x1) x1 = x; - if (y < y0$2) y0$2 = y; - if (y > y1) y1 = y; -} - -// TODO Enforce positive area for exterior, negative area for interior? - -var X0$1 = 0; -var Y0$1 = 0; -var Z0$1 = 0; -var X1$1 = 0; -var Y1$1 = 0; -var Z1$1 = 0; -var X2$1 = 0; -var Y2$1 = 0; -var Z2$1 = 0; -var x00$1; -var y00$1; -var x0$3; -var y0$3; - -var centroidStream$1 = { - point: centroidPoint$1, - lineStart: centroidLineStart$1, - lineEnd: centroidLineEnd$1, - polygonStart: function() { - centroidStream$1.lineStart = centroidRingStart$1; - centroidStream$1.lineEnd = centroidRingEnd$1; - }, - polygonEnd: function() { - centroidStream$1.point = centroidPoint$1; - centroidStream$1.lineStart = centroidLineStart$1; - centroidStream$1.lineEnd = centroidLineEnd$1; - }, - result: function() { - var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1] - : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1] - : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1] - : [NaN, NaN]; - X0$1 = Y0$1 = Z0$1 = - X1$1 = Y1$1 = Z1$1 = - X2$1 = Y2$1 = Z2$1 = 0; - return centroid; - } -}; - -function centroidPoint$1(x, y) { - X0$1 += x; - Y0$1 += y; - ++Z0$1; -} - -function centroidLineStart$1() { - centroidStream$1.point = centroidPointFirstLine; -} - -function centroidPointFirstLine(x, y) { - centroidStream$1.point = centroidPointLine; - centroidPoint$1(x0$3 = x, y0$3 = y); -} - -function centroidPointLine(x, y) { - var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy); - X1$1 += z * (x0$3 + x) / 2; - Y1$1 += z * (y0$3 + y) / 2; - Z1$1 += z; - centroidPoint$1(x0$3 = x, y0$3 = y); -} - -function centroidLineEnd$1() { - centroidStream$1.point = centroidPoint$1; -} - -function centroidRingStart$1() { - centroidStream$1.point = centroidPointFirstRing; -} - -function centroidRingEnd$1() { - centroidPointRing(x00$1, y00$1); -} - -function centroidPointFirstRing(x, y) { - centroidStream$1.point = centroidPointRing; - centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y); -} - -function centroidPointRing(x, y) { - var dx = x - x0$3, - dy = y - y0$3, - z = sqrt(dx * dx + dy * dy); - - X1$1 += z * (x0$3 + x) / 2; - Y1$1 += z * (y0$3 + y) / 2; - Z1$1 += z; - - z = y0$3 * x - x0$3 * y; - X2$1 += z * (x0$3 + x); - Y2$1 += z * (y0$3 + y); - Z2$1 += z * 3; - centroidPoint$1(x0$3 = x, y0$3 = y); -} - -function PathContext(context) { - this._context = context; -} - -PathContext.prototype = { - _radius: 4.5, - pointRadius: function(_) { - return this._radius = _, this; - }, - polygonStart: function() { - this._line = 0; - }, - polygonEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._point = 0; - }, - lineEnd: function() { - if (this._line === 0) this._context.closePath(); - this._point = NaN; - }, - point: function(x, y) { - switch (this._point) { - case 0: { - this._context.moveTo(x, y); - this._point = 1; - break; - } - case 1: { - this._context.lineTo(x, y); - break; - } - default: { - this._context.moveTo(x + this._radius, y); - this._context.arc(x, y, this._radius, 0, tau$3); - break; - } - } - }, - result: noop$1 -}; - -var lengthSum$1 = adder(); -var lengthRing; -var x00$2; -var y00$2; -var x0$4; -var y0$4; - -var lengthStream$1 = { - point: noop$1, - lineStart: function() { - lengthStream$1.point = lengthPointFirst$1; - }, - lineEnd: function() { - if (lengthRing) lengthPoint$1(x00$2, y00$2); - lengthStream$1.point = noop$1; - }, - polygonStart: function() { - lengthRing = true; - }, - polygonEnd: function() { - lengthRing = null; - }, - result: function() { - var length = +lengthSum$1; - lengthSum$1.reset(); - return length; - } -}; - -function lengthPointFirst$1(x, y) { - lengthStream$1.point = lengthPoint$1; - x00$2 = x0$4 = x, y00$2 = y0$4 = y; -} - -function lengthPoint$1(x, y) { - x0$4 -= x, y0$4 -= y; - lengthSum$1.add(sqrt(x0$4 * x0$4 + y0$4 * y0$4)); - x0$4 = x, y0$4 = y; -} - -function PathString() { - this._string = []; -} - -PathString.prototype = { - _radius: 4.5, - _circle: circle$1(4.5), - pointRadius: function(_) { - if ((_ = +_) !== this._radius) this._radius = _, this._circle = null; - return this; - }, - polygonStart: function() { - this._line = 0; - }, - polygonEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._point = 0; - }, - lineEnd: function() { - if (this._line === 0) this._string.push("Z"); - this._point = NaN; - }, - point: function(x, y) { - switch (this._point) { - case 0: { - this._string.push("M", x, ",", y); - this._point = 1; - break; - } - case 1: { - this._string.push("L", x, ",", y); - break; - } - default: { - if (this._circle == null) this._circle = circle$1(this._radius); - this._string.push("M", x, ",", y, this._circle); - break; - } - } - }, - result: function() { - if (this._string.length) { - var result = this._string.join(""); - this._string = []; - return result; - } else { - return null; - } - } -}; - -function circle$1(radius) { - return "m0," + radius - + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius - + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius - + "z"; -} - -var index$1 = function(projection, context) { - var pointRadius = 4.5, - projectionStream, - contextStream; - - function path(object) { - if (object) { - if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); - geoStream(object, projectionStream(contextStream)); - } - return contextStream.result(); - } - - path.area = function(object) { - geoStream(object, projectionStream(areaStream$1)); - return areaStream$1.result(); - }; - - path.measure = function(object) { - geoStream(object, projectionStream(lengthStream$1)); - return lengthStream$1.result(); - }; - - path.bounds = function(object) { - geoStream(object, projectionStream(boundsStream$1)); - return boundsStream$1.result(); - }; - - path.centroid = function(object) { - geoStream(object, projectionStream(centroidStream$1)); - return centroidStream$1.result(); - }; - - path.projection = function(_) { - return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection; - }; - - path.context = function(_) { - if (!arguments.length) return context; - contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _); - if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); - return path; - }; - - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); - return path; - }; - - return path.projection(projection).context(context); -}; - -var transform = function(methods) { - return { - stream: transformer(methods) - }; -}; - -function transformer(methods) { - return function(stream) { - var s = new TransformStream; - for (var key in methods) s[key] = methods[key]; - s.stream = stream; - return s; - }; -} - -function TransformStream() {} - -TransformStream.prototype = { - constructor: TransformStream, - point: function(x, y) { this.stream.point(x, y); }, - sphere: function() { this.stream.sphere(); }, - lineStart: function() { this.stream.lineStart(); }, - lineEnd: function() { this.stream.lineEnd(); }, - polygonStart: function() { this.stream.polygonStart(); }, - polygonEnd: function() { this.stream.polygonEnd(); } -}; - -function fitExtent(projection, extent, object) { - var w = extent[1][0] - extent[0][0], - h = extent[1][1] - extent[0][1], - clip = projection.clipExtent && projection.clipExtent(); - - projection - .scale(150) - .translate([0, 0]); - - if (clip != null) projection.clipExtent(null); - - geoStream(object, projection.stream(boundsStream$1)); - - var b = boundsStream$1.result(), - k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), - x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, - y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; - - if (clip != null) projection.clipExtent(clip); - - return projection - .scale(k * 150) - .translate([x, y]); -} - -function fitSize(projection, size, object) { - return fitExtent(projection, [[0, 0], size], object); -} - -var maxDepth = 16; -var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance) - -var resample = function(project, delta2) { - return +delta2 ? resample$1(project, delta2) : resampleNone(project); -}; - -function resampleNone(project) { - return transformer({ - point: function(x, y) { - x = project(x, y); - this.stream.point(x[0], x[1]); - } - }); -} - -function resample$1(project, delta2) { - - function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { - var dx = x1 - x0, - dy = y1 - y0, - d2 = dx * dx + dy * dy; - if (d2 > 4 * delta2 && depth--) { - var a = a0 + a1, - b = b0 + b1, - c = c0 + c1, - m = sqrt(a * a + b * b + c * c), - phi2 = asin(c /= m), - lambda2 = abs(abs(c) - 1) < epsilon$2 || abs(lambda0 - lambda1) < epsilon$2 ? (lambda0 + lambda1) / 2 : atan2(b, a), - p = project(lambda2, phi2), - x2 = p[0], - y2 = p[1], - dx2 = x2 - x0, - dy2 = y2 - y0, - dz = dy * dx2 - dx * dy2; - if (dz * dz / d2 > delta2 // perpendicular projected distance - || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end - || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance - resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream); - stream.point(x2, y2); - resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream); - } - } - } - return function(stream) { - var lambda00, x00, y00, a00, b00, c00, // first point - lambda0, x0, y0, a0, b0, c0; // previous point - - var resampleStream = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; }, - polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; } - }; - - function point(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - } - - function lineStart() { - x0 = NaN; - resampleStream.point = linePoint; - stream.lineStart(); - } - - function linePoint(lambda, phi) { - var c = cartesian([lambda, phi]), p = project(lambda, phi); - resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); - stream.point(x0, y0); - } - - function lineEnd() { - resampleStream.point = point; - stream.lineEnd(); - } - - function ringStart() { - lineStart(); - resampleStream.point = ringPoint; - resampleStream.lineEnd = ringEnd; - } - - function ringPoint(lambda, phi) { - linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resampleStream.point = linePoint; - } - - function ringEnd() { - resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream); - resampleStream.lineEnd = lineEnd; - lineEnd(); - } - - return resampleStream; - }; -} - -var transformRadians = transformer({ - point: function(x, y) { - this.stream.point(x * radians, y * radians); - } -}); - -function transformRotate(rotate) { - return transformer({ - point: function(x, y) { - var r = rotate(x, y); - return this.stream.point(r[0], r[1]); - } - }); -} - -function projection(project) { - return projectionMutator(function() { return project; })(); -} - -function projectionMutator(projectAt) { - var project, - k = 150, // scale - x = 480, y = 250, // translate - dx, dy, lambda = 0, phi = 0, // center - deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate - theta = null, preclip = clipAntimeridian, // clip angle - x0 = null, y0, x1, y1, postclip = identity$4, // clip extent - delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision - cache, - cacheStream; - - function projection(point) { - point = projectRotate(point[0] * radians, point[1] * radians); - return [point[0] * k + dx, dy - point[1] * k]; - } - - function invert(point) { - point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k); - return point && [point[0] * degrees$1, point[1] * degrees$1]; - } - - function projectTransform(x, y) { - return x = project(x, y), [x[0] * k + dx, dy - x[1] * k]; - } - - projection.stream = function(stream) { - return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream))))); - }; - - projection.preclip = function(_) { - return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip; - }; - - projection.postclip = function(_) { - return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip; - }; - - projection.clipAngle = function(_) { - return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1; - }; - - projection.clipExtent = function(_) { - return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; - }; - - projection.scale = function(_) { - return arguments.length ? (k = +_, recenter()) : k; - }; - - projection.translate = function(_) { - return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; - }; - - projection.center = function(_) { - return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1]; - }; - - projection.rotate = function(_) { - return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1]; - }; - - projection.precision = function(_) { - return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2); - }; - - projection.fitExtent = function(extent, object) { - return fitExtent(projection, extent, object); - }; - - projection.fitSize = function(size, object) { - return fitSize(projection, size, object); - }; - - function recenter() { - projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project); - var center = project(lambda, phi); - dx = x - center[0] * k; - dy = y + center[1] * k; - return reset(); - } - - function reset() { - cache = cacheStream = null; - return projection; - } - - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return recenter(); - }; -} - -function conicProjection(projectAt) { - var phi0 = 0, - phi1 = pi$3 / 3, - m = projectionMutator(projectAt), - p = m(phi0, phi1); - - p.parallels = function(_) { - return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1]; - }; - - return p; -} - -function cylindricalEqualAreaRaw(phi0) { - var cosPhi0 = cos$1(phi0); - - function forward(lambda, phi) { - return [lambda * cosPhi0, sin$1(phi) / cosPhi0]; - } - - forward.invert = function(x, y) { - return [x / cosPhi0, asin(y * cosPhi0)]; - }; - - return forward; -} - -function conicEqualAreaRaw(y0, y1) { - var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2; - - // Are the parallels symmetrical around the Equator? - if (abs(n) < epsilon$2) return cylindricalEqualAreaRaw(y0); - - var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n; - - function project(x, y) { - var r = sqrt(c - 2 * n * sin$1(y)) / n; - return [r * sin$1(x *= n), r0 - r * cos$1(x)]; - } - - project.invert = function(x, y) { - var r0y = r0 - y; - return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; - }; - - return project; -} - -var conicEqualArea = function() { - return conicProjection(conicEqualAreaRaw) - .scale(155.424) - .center([0, 33.6442]); -}; - -var albers = function() { - return conicEqualArea() - .parallels([29.5, 45.5]) - .scale(1070) - .translate([480, 250]) - .rotate([96, 0]) - .center([-0.6, 38.7]); -}; - -// The projections must have mutually exclusive clip regions on the sphere, -// as this will avoid emitting interleaving lines and polygons. -function multiplex(streams) { - var n = streams.length; - return { - point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); }, - sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); }, - lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); }, - lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); }, - polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); }, - polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); } - }; -} - -// A composite projection for the United States, configured by default for -// 960×500. The projection also works quite well at 960×600 if you change the -// scale to 1285 and adjust the translate accordingly. The set of standard -// parallels for each region comes from USGS, which is published here: -// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers -var albersUsa = function() { - var cache, - cacheStream, - lower48 = albers(), lower48Point, - alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 - hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 - point, pointStream = {point: function(x, y) { point = [x, y]; }}; - - function albersUsa(coordinates) { - var x = coordinates[0], y = coordinates[1]; - return point = null, - (lower48Point.point(x, y), point) - || (alaskaPoint.point(x, y), point) - || (hawaiiPoint.point(x, y), point); - } - - albersUsa.invert = function(coordinates) { - var k = lower48.scale(), - t = lower48.translate(), - x = (coordinates[0] - t[0]) / k, - y = (coordinates[1] - t[1]) / k; - return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska - : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii - : lower48).invert(coordinates); - }; - - albersUsa.stream = function(stream) { - return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]); - }; - - albersUsa.precision = function(_) { - if (!arguments.length) return lower48.precision(); - lower48.precision(_), alaska.precision(_), hawaii.precision(_); - return reset(); - }; - - albersUsa.scale = function(_) { - if (!arguments.length) return lower48.scale(); - lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_); - return albersUsa.translate(lower48.translate()); - }; - - albersUsa.translate = function(_) { - if (!arguments.length) return lower48.translate(); - var k = lower48.scale(), x = +_[0], y = +_[1]; - - lower48Point = lower48 - .translate(_) - .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]]) - .stream(pointStream); - - alaskaPoint = alaska - .translate([x - 0.307 * k, y + 0.201 * k]) - .clipExtent([[x - 0.425 * k + epsilon$2, y + 0.120 * k + epsilon$2], [x - 0.214 * k - epsilon$2, y + 0.234 * k - epsilon$2]]) - .stream(pointStream); - - hawaiiPoint = hawaii - .translate([x - 0.205 * k, y + 0.212 * k]) - .clipExtent([[x - 0.214 * k + epsilon$2, y + 0.166 * k + epsilon$2], [x - 0.115 * k - epsilon$2, y + 0.234 * k - epsilon$2]]) - .stream(pointStream); - - return reset(); - }; - - albersUsa.fitExtent = function(extent, object) { - return fitExtent(albersUsa, extent, object); - }; - - albersUsa.fitSize = function(size, object) { - return fitSize(albersUsa, size, object); - }; - - function reset() { - cache = cacheStream = null; - return albersUsa; - } - - return albersUsa.scale(1070); -}; - -function azimuthalRaw(scale) { - return function(x, y) { - var cx = cos$1(x), - cy = cos$1(y), - k = scale(cx * cy); - return [ - k * cy * sin$1(x), - k * sin$1(y) - ]; - } -} - -function azimuthalInvert(angle) { - return function(x, y) { - var z = sqrt(x * x + y * y), - c = angle(z), - sc = sin$1(c), - cc = cos$1(c); - return [ - atan2(x * sc, z * cc), - asin(z && y * sc / z) - ]; - } -} - -var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { - return sqrt(2 / (1 + cxcy)); -}); - -azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { - return 2 * asin(z / 2); -}); - -var azimuthalEqualArea = function() { - return projection(azimuthalEqualAreaRaw) - .scale(124.75) - .clipAngle(180 - 1e-3); -}; - -var azimuthalEquidistantRaw = azimuthalRaw(function(c) { - return (c = acos(c)) && c / sin$1(c); -}); - -azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) { - return z; -}); - -var azimuthalEquidistant = function() { - return projection(azimuthalEquidistantRaw) - .scale(79.4188) - .clipAngle(180 - 1e-3); -}; - -function mercatorRaw(lambda, phi) { - return [lambda, log(tan((halfPi$2 + phi) / 2))]; -} - -mercatorRaw.invert = function(x, y) { - return [x, 2 * atan(exp(y)) - halfPi$2]; -}; - -var mercator = function() { - return mercatorProjection(mercatorRaw) - .scale(961 / tau$3); -}; - -function mercatorProjection(project) { - var m = projection(project), - center = m.center, - scale = m.scale, - translate = m.translate, - clipExtent = m.clipExtent, - x0 = null, y0, x1, y1; // clip extent - - m.scale = function(_) { - return arguments.length ? (scale(_), reclip()) : scale(); - }; - - m.translate = function(_) { - return arguments.length ? (translate(_), reclip()) : translate(); - }; - - m.center = function(_) { - return arguments.length ? (center(_), reclip()) : center(); - }; - - m.clipExtent = function(_) { - return arguments.length ? ((_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1])), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]]; - }; - - function reclip() { - var k = pi$3 * scale(), - t = m(rotation(m.rotate()).invert([0, 0])); - return clipExtent(x0 == null - ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw - ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]] - : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]); - } - - return reclip(); -} - -function tany(y) { - return tan((halfPi$2 + y) / 2); -} - -function conicConformalRaw(y0, y1) { - var cy0 = cos$1(y0), - n = y0 === y1 ? sin$1(y0) : log(cy0 / cos$1(y1)) / log(tany(y1) / tany(y0)), - f = cy0 * pow(tany(y0), n) / n; - - if (!n) return mercatorRaw; - - function project(x, y) { - if (f > 0) { if (y < -halfPi$2 + epsilon$2) y = -halfPi$2 + epsilon$2; } - else { if (y > halfPi$2 - epsilon$2) y = halfPi$2 - epsilon$2; } - var r = f / pow(tany(y), n); - return [r * sin$1(n * x), f - r * cos$1(n * x)]; - } - - project.invert = function(x, y) { - var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy); - return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi$2]; - }; - - return project; -} - -var conicConformal = function() { - return conicProjection(conicConformalRaw) - .scale(109.5) - .parallels([30, 30]); -}; - -function equirectangularRaw(lambda, phi) { - return [lambda, phi]; -} - -equirectangularRaw.invert = equirectangularRaw; - -var equirectangular = function() { - return projection(equirectangularRaw) - .scale(152.63); -}; - -function conicEquidistantRaw(y0, y1) { - var cy0 = cos$1(y0), - n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0), - g = cy0 / n + y0; - - if (abs(n) < epsilon$2) return equirectangularRaw; - - function project(x, y) { - var gy = g - y, nx = n * x; - return [gy * sin$1(nx), g - gy * cos$1(nx)]; - } - - project.invert = function(x, y) { - var gy = g - y; - return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)]; - }; - - return project; -} - -var conicEquidistant = function() { - return conicProjection(conicEquidistantRaw) - .scale(131.154) - .center([0, 13.9389]); -}; - -function gnomonicRaw(x, y) { - var cy = cos$1(y), k = cos$1(x) * cy; - return [cy * sin$1(x) / k, sin$1(y) / k]; -} - -gnomonicRaw.invert = azimuthalInvert(atan); - -var gnomonic = function() { - return projection(gnomonicRaw) - .scale(144.049) - .clipAngle(60); -}; - -function scaleTranslate(kx, ky, tx, ty) { - return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity$4 : transformer({ - point: function(x, y) { - this.stream.point(x * kx + tx, y * ky + ty); - } - }); -} - -var identity$5 = function() { - var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform$$1 = identity$4, // scale, translate and reflect - x0 = null, y0, x1, y1, // clip extent - postclip = identity$4, - cache, - cacheStream, - projection; - - function reset() { - cache = cacheStream = null; - return projection; - } - - return projection = { - stream: function(stream) { - return cache && cacheStream === stream ? cache : cache = transform$$1(postclip(cacheStream = stream)); - }, - postclip: function(_) { - return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip; - }, - clipExtent: function(_) { - return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; - }, - scale: function(_) { - return arguments.length ? (transform$$1 = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k; - }, - translate: function(_) { - return arguments.length ? (transform$$1 = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty]; - }, - reflectX: function(_) { - return arguments.length ? (transform$$1 = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0; - }, - reflectY: function(_) { - return arguments.length ? (transform$$1 = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0; - }, - fitExtent: function(extent, object) { - return fitExtent(projection, extent, object); - }, - fitSize: function(size, object) { - return fitSize(projection, size, object); - } - }; -}; - -function naturalEarth1Raw(lambda, phi) { - var phi2 = phi * phi, phi4 = phi2 * phi2; - return [ - lambda * (0.8707 - 0.131979 * phi2 + phi4 * (-0.013791 + phi4 * (0.003971 * phi2 - 0.001529 * phi4))), - phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) - ]; -} - -naturalEarth1Raw.invert = function(x, y) { - var phi = y, i = 25, delta; - do { - var phi2 = phi * phi, phi4 = phi2 * phi2; - phi -= delta = (phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) - y) / - (1.007226 + phi2 * (0.015085 * 3 + phi4 * (-0.044475 * 7 + 0.028874 * 9 * phi2 - 0.005916 * 11 * phi4))); - } while (abs(delta) > epsilon$2 && --i > 0); - return [ - x / (0.8707 + (phi2 = phi * phi) * (-0.131979 + phi2 * (-0.013791 + phi2 * phi2 * phi2 * (0.003971 - 0.001529 * phi2)))), - phi - ]; -}; - -var naturalEarth1 = function() { - return projection(naturalEarth1Raw) - .scale(175.295); -}; - -function orthographicRaw(x, y) { - return [cos$1(y) * sin$1(x), sin$1(y)]; -} - -orthographicRaw.invert = azimuthalInvert(asin); - -var orthographic = function() { - return projection(orthographicRaw) - .scale(249.5) - .clipAngle(90 + epsilon$2); -}; - -function stereographicRaw(x, y) { - var cy = cos$1(y), k = 1 + cos$1(x) * cy; - return [cy * sin$1(x) / k, sin$1(y) / k]; -} - -stereographicRaw.invert = azimuthalInvert(function(z) { - return 2 * atan(z); -}); - -var stereographic = function() { - return projection(stereographicRaw) - .scale(250) - .clipAngle(142); -}; - -function transverseMercatorRaw(lambda, phi) { - return [log(tan((halfPi$2 + phi) / 2)), -lambda]; -} - -transverseMercatorRaw.invert = function(x, y) { - return [-y, 2 * atan(exp(x)) - halfPi$2]; -}; - -var transverseMercator = function() { - var m = mercatorProjection(transverseMercatorRaw), - center = m.center, - rotate = m.rotate; - - m.center = function(_) { - return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]); - }; - - m.rotate = function(_) { - return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]); - }; - - return rotate([0, 0, 90]) - .scale(159.155); -}; - -function defaultSeparation(a, b) { - return a.parent === b.parent ? 1 : 2; -} - -function meanX(children) { - return children.reduce(meanXReduce, 0) / children.length; -} - -function meanXReduce(x, c) { - return x + c.x; -} - -function maxY(children) { - return 1 + children.reduce(maxYReduce, 0); -} - -function maxYReduce(y, c) { - return Math.max(y, c.y); -} - -function leafLeft(node) { - var children; - while (children = node.children) node = children[0]; - return node; -} - -function leafRight(node) { - var children; - while (children = node.children) node = children[children.length - 1]; - return node; -} - -var cluster = function() { - var separation = defaultSeparation, - dx = 1, - dy = 1, - nodeSize = false; - - function cluster(root) { - var previousNode, - x = 0; - - // First walk, computing the initial x & y values. - root.eachAfter(function(node) { - var children = node.children; - if (children) { - node.x = meanX(children); - node.y = maxY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } - }); - - var left = leafLeft(root), - right = leafRight(root), - x0 = left.x - separation(left, right) / 2, - x1 = right.x + separation(right, left) / 2; - - // Second walk, normalizing x & y to the desired size. - return root.eachAfter(nodeSize ? function(node) { - node.x = (node.x - root.x) * dx; - node.y = (root.y - node.y) * dy; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * dx; - node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; - }); - } - - cluster.separation = function(x) { - return arguments.length ? (separation = x, cluster) : separation; - }; - - cluster.size = function(x) { - return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); - }; - - cluster.nodeSize = function(x) { - return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); - }; - - return cluster; -}; - -function count(node) { - var sum = 0, - children = node.children, - i = children && children.length; - if (!i) sum = 1; - else while (--i >= 0) sum += children[i].value; - node.value = sum; -} - -var node_count = function() { - return this.eachAfter(count); -}; - -var node_each = function(callback) { - var node = this, current, next = [node], children, i, n; - do { - current = next.reverse(), next = []; - while (node = current.pop()) { - callback(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - next.push(children[i]); - } - } - } while (next.length); - return this; -}; - -var node_eachBefore = function(callback) { - var node = this, nodes = [node], children, i; - while (node = nodes.pop()) { - callback(node), children = node.children; - if (children) for (i = children.length - 1; i >= 0; --i) { - nodes.push(children[i]); - } - } - return this; -}; - -var node_eachAfter = function(callback) { - var node = this, nodes = [node], next = [], children, i, n; - while (node = nodes.pop()) { - next.push(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - nodes.push(children[i]); - } - } - while (node = next.pop()) { - callback(node); - } - return this; -}; - -var node_sum = function(value) { - return this.eachAfter(function(node) { - var sum = +value(node.data) || 0, - children = node.children, - i = children && children.length; - while (--i >= 0) sum += children[i].value; - node.value = sum; - }); -}; - -var node_sort = function(compare) { - return this.eachBefore(function(node) { - if (node.children) { - node.children.sort(compare); - } - }); -}; - -var node_path = function(end) { - var start = this, - ancestor = leastCommonAncestor(start, end), - nodes = [start]; - while (start !== ancestor) { - start = start.parent; - nodes.push(start); - } - var k = nodes.length; - while (end !== ancestor) { - nodes.splice(k, 0, end); - end = end.parent; - } - return nodes; -}; - -function leastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = a.ancestors(), - bNodes = b.ancestors(), - c = null; - a = aNodes.pop(); - b = bNodes.pop(); - while (a === b) { - c = a; - a = aNodes.pop(); - b = bNodes.pop(); - } - return c; -} - -var node_ancestors = function() { - var node = this, nodes = [node]; - while (node = node.parent) { - nodes.push(node); - } - return nodes; -}; - -var node_descendants = function() { - var nodes = []; - this.each(function(node) { - nodes.push(node); - }); - return nodes; -}; - -var node_leaves = function() { - var leaves = []; - this.eachBefore(function(node) { - if (!node.children) { - leaves.push(node); - } - }); - return leaves; -}; - -var node_links = function() { - var root = this, links = []; - root.each(function(node) { - if (node !== root) { // Don’t include the root’s parent, if any. - links.push({source: node.parent, target: node}); - } - }); - return links; -}; - -function hierarchy(data, children) { - var root = new Node(data), - valued = +data.value && (root.value = data.value), - node, - nodes = [root], - child, - childs, - i, - n; - - if (children == null) children = defaultChildren; - - while (node = nodes.pop()) { - if (valued) node.value = +node.data.value; - if ((childs = children(node.data)) && (n = childs.length)) { - node.children = new Array(n); - for (i = n - 1; i >= 0; --i) { - nodes.push(child = node.children[i] = new Node(childs[i])); - child.parent = node; - child.depth = node.depth + 1; - } - } - } - - return root.eachBefore(computeHeight); -} - -function node_copy() { - return hierarchy(this).eachBefore(copyData); -} - -function defaultChildren(d) { - return d.children; -} - -function copyData(node) { - node.data = node.data.data; -} - -function computeHeight(node) { - var height = 0; - do node.height = height; - while ((node = node.parent) && (node.height < ++height)); -} - -function Node(data) { - this.data = data; - this.depth = - this.height = 0; - this.parent = null; -} - -Node.prototype = hierarchy.prototype = { - constructor: Node, - count: node_count, - each: node_each, - eachAfter: node_eachAfter, - eachBefore: node_eachBefore, - sum: node_sum, - sort: node_sort, - path: node_path, - ancestors: node_ancestors, - descendants: node_descendants, - leaves: node_leaves, - links: node_links, - copy: node_copy -}; - -var slice$3 = Array.prototype.slice; - -function shuffle$1(array) { - var m = array.length, - t, - i; - - while (m) { - i = Math.random() * m-- | 0; - t = array[m]; - array[m] = array[i]; - array[i] = t; - } - - return array; -} - -var enclose = function(circles) { - var i = 0, n = (circles = shuffle$1(slice$3.call(circles))).length, B = [], p, e; - - while (i < n) { - p = circles[i]; - if (e && enclosesWeak(e, p)) ++i; - else e = encloseBasis(B = extendBasis(B, p)), i = 0; - } - - return e; -}; - -function extendBasis(B, p) { - var i, j; - - if (enclosesWeakAll(p, B)) return [p]; - - // If we get here then B must have at least one element. - for (i = 0; i < B.length; ++i) { - if (enclosesNot(p, B[i]) - && enclosesWeakAll(encloseBasis2(B[i], p), B)) { - return [B[i], p]; - } - } - - // If we get here then B must have at least two elements. - for (i = 0; i < B.length - 1; ++i) { - for (j = i + 1; j < B.length; ++j) { - if (enclosesNot(encloseBasis2(B[i], B[j]), p) - && enclosesNot(encloseBasis2(B[i], p), B[j]) - && enclosesNot(encloseBasis2(B[j], p), B[i]) - && enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) { - return [B[i], B[j], p]; - } - } - } - - // If we get here then something is very wrong. - throw new Error; -} - -function enclosesNot(a, b) { - var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y; - return dr < 0 || dr * dr < dx * dx + dy * dy; -} - -function enclosesWeak(a, b) { - var dr = a.r - b.r + 1e-6, dx = b.x - a.x, dy = b.y - a.y; - return dr > 0 && dr * dr > dx * dx + dy * dy; -} - -function enclosesWeakAll(a, B) { - for (var i = 0; i < B.length; ++i) { - if (!enclosesWeak(a, B[i])) { - return false; - } - } - return true; -} - -function encloseBasis(B) { - switch (B.length) { - case 1: return encloseBasis1(B[0]); - case 2: return encloseBasis2(B[0], B[1]); - case 3: return encloseBasis3(B[0], B[1], B[2]); - } -} - -function encloseBasis1(a) { - return { - x: a.x, - y: a.y, - r: a.r - }; -} - -function encloseBasis2(a, b) { - var x1 = a.x, y1 = a.y, r1 = a.r, - x2 = b.x, y2 = b.y, r2 = b.r, - x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, - l = Math.sqrt(x21 * x21 + y21 * y21); - return { - x: (x1 + x2 + x21 / l * r21) / 2, - y: (y1 + y2 + y21 / l * r21) / 2, - r: (l + r1 + r2) / 2 - }; -} - -function encloseBasis3(a, b, c) { - var x1 = a.x, y1 = a.y, r1 = a.r, - x2 = b.x, y2 = b.y, r2 = b.r, - x3 = c.x, y3 = c.y, r3 = c.r, - a2 = x1 - x2, - a3 = x1 - x3, - b2 = y1 - y2, - b3 = y1 - y3, - c2 = r2 - r1, - c3 = r3 - r1, - d1 = x1 * x1 + y1 * y1 - r1 * r1, - d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2, - d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3, - ab = a3 * b2 - a2 * b3, - xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1, - xb = (b3 * c2 - b2 * c3) / ab, - ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1, - yb = (a2 * c3 - a3 * c2) / ab, - A = xb * xb + yb * yb - 1, - B = 2 * (r1 + xa * xb + ya * yb), - C = xa * xa + ya * ya - r1 * r1, - r = -(A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B); - return { - x: x1 + xa + xb * r, - y: y1 + ya + yb * r, - r: r - }; -} - -function place(a, b, c) { - var ax = a.x, - ay = a.y, - da = b.r + c.r, - db = a.r + c.r, - dx = b.x - ax, - dy = b.y - ay, - dc = dx * dx + dy * dy; - if (dc) { - var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc), - y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); - c.x = ax + x * dx + y * dy; - c.y = ay + x * dy - y * dx; - } else { - c.x = ax + db; - c.y = ay; - } -} - -function intersects(a, b) { - var dx = b.x - a.x, - dy = b.y - a.y, - dr = a.r + b.r; - return dr * dr - 1e-6 > dx * dx + dy * dy; -} - -function score(node) { - var a = node._, - b = node.next._, - ab = a.r + b.r, - dx = (a.x * b.r + b.x * a.r) / ab, - dy = (a.y * b.r + b.y * a.r) / ab; - return dx * dx + dy * dy; -} - -function Node$1(circle) { - this._ = circle; - this.next = null; - this.previous = null; -} - -function packEnclose(circles) { - if (!(n = circles.length)) return 0; - - var a, b, c, n, aa, ca, i, j, k, sj, sk; - - // Place the first circle. - a = circles[0], a.x = 0, a.y = 0; - if (!(n > 1)) return a.r; - - // Place the second circle. - b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; - if (!(n > 2)) return a.r + b.r; - - // Place the third circle. - place(b, a, c = circles[2]); - - // Initialize the front-chain using the first three circles a, b and c. - a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); - a.next = c.previous = b; - b.next = a.previous = c; - c.next = b.previous = a; - - // Attempt to place each remaining circle
 - pack: for (i = 3; i < n; ++i) { - place(a._, b._, c = circles[i]), c = new Node$1(c); - - // Find the closest intersecting circle on the front-chain, if any. - // “Closeness” is determined by linear distance along the front-chain. - // “Ahead” or “behind” is likewise determined by linear distance. - j = b.next, k = a.previous, sj = b._.r, sk = a._.r; - do { - if (sj <= sk) { - if (intersects(j._, c._)) { - b = j, a.next = b, b.previous = a, --i; - continue pack; - } - sj += j._.r, j = j.next; - } else { - if (intersects(k._, c._)) { - a = k, a.next = b, b.previous = a, --i; - continue pack; - } - sk += k._.r, k = k.previous; - } - } while (j !== k.next); - - // Success! Insert the new circle c between a and b. - c.previous = a, c.next = b, a.next = b.previous = b = c; - - // Compute the new closest circle pair to the centroid. - aa = score(a); - while ((c = c.next) !== b) { - if ((ca = score(c)) < aa) { - a = c, aa = ca; - } - } - b = a.next; - } - - // Compute the enclosing circle of the front chain. - a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a); - - // Translate the circles to put the enclosing circle around the origin. - for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; - - return c.r; -} - -var siblings = function(circles) { - packEnclose(circles); - return circles; -}; - -function optional(f) { - return f == null ? null : required(f); -} - -function required(f) { - if (typeof f !== "function") throw new Error; - return f; -} - -function constantZero() { - return 0; -} - -var constant$8 = function(x) { - return function() { - return x; - }; -}; - -function defaultRadius$1(d) { - return Math.sqrt(d.value); -} - -var index$2 = function() { - var radius = null, - dx = 1, - dy = 1, - padding = constantZero; - - function pack(root) { - root.x = dx / 2, root.y = dy / 2; - if (radius) { - root.eachBefore(radiusLeaf(radius)) - .eachAfter(packChildren(padding, 0.5)) - .eachBefore(translateChild(1)); - } else { - root.eachBefore(radiusLeaf(defaultRadius$1)) - .eachAfter(packChildren(constantZero, 1)) - .eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) - .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); - } - return root; - } - - pack.radius = function(x) { - return arguments.length ? (radius = optional(x), pack) : radius; - }; - - pack.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; - }; - - pack.padding = function(x) { - return arguments.length ? (padding = typeof x === "function" ? x : constant$8(+x), pack) : padding; - }; - - return pack; -}; - -function radiusLeaf(radius) { - return function(node) { - if (!node.children) { - node.r = Math.max(0, +radius(node) || 0); - } - }; -} - -function packChildren(padding, k) { - return function(node) { - if (children = node.children) { - var children, - i, - n = children.length, - r = padding(node) * k || 0, - e; - - if (r) for (i = 0; i < n; ++i) children[i].r += r; - e = packEnclose(children); - if (r) for (i = 0; i < n; ++i) children[i].r -= r; - node.r = e + r; - } - }; -} - -function translateChild(k) { - return function(node) { - var parent = node.parent; - node.r *= k; - if (parent) { - node.x = parent.x + k * node.x; - node.y = parent.y + k * node.y; - } - }; -} - -var roundNode = function(node) { - node.x0 = Math.round(node.x0); - node.y0 = Math.round(node.y0); - node.x1 = Math.round(node.x1); - node.y1 = Math.round(node.y1); -}; - -var treemapDice = function(parent, x0, y0, x1, y1) { - var nodes = parent.children, - node, - i = -1, - n = nodes.length, - k = parent.value && (x1 - x0) / parent.value; - - while (++i < n) { - node = nodes[i], node.y0 = y0, node.y1 = y1; - node.x0 = x0, node.x1 = x0 += node.value * k; - } -}; - -var partition = function() { - var dx = 1, - dy = 1, - padding = 0, - round = false; - - function partition(root) { - var n = root.height + 1; - root.x0 = - root.y0 = padding; - root.x1 = dx; - root.y1 = dy / n; - root.eachBefore(positionNode(dy, n)); - if (round) root.eachBefore(roundNode); - return root; - } - - function positionNode(dy, n) { - return function(node) { - if (node.children) { - treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); - } - var x0 = node.x0, - y0 = node.y0, - x1 = node.x1 - padding, - y1 = node.y1 - padding; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - node.x0 = x0; - node.y0 = y0; - node.x1 = x1; - node.y1 = y1; - }; - } - - partition.round = function(x) { - return arguments.length ? (round = !!x, partition) : round; - }; - - partition.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; - }; - - partition.padding = function(x) { - return arguments.length ? (padding = +x, partition) : padding; - }; - - return partition; -}; - -var keyPrefix$1 = "$"; -var preroot = {depth: -1}; -var ambiguous = {}; - -function defaultId(d) { - return d.id; -} - -function defaultParentId(d) { - return d.parentId; -} - -var stratify = function() { - var id = defaultId, - parentId = defaultParentId; - - function stratify(data) { - var d, - i, - n = data.length, - root, - parent, - node, - nodes = new Array(n), - nodeId, - nodeKey, - nodeByKey = {}; - - for (i = 0; i < n; ++i) { - d = data[i], node = nodes[i] = new Node(d); - if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { - nodeKey = keyPrefix$1 + (node.id = nodeId); - nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; - } - } - - for (i = 0; i < n; ++i) { - node = nodes[i], nodeId = parentId(data[i], i, data); - if (nodeId == null || !(nodeId += "")) { - if (root) throw new Error("multiple roots"); - root = node; - } else { - parent = nodeByKey[keyPrefix$1 + nodeId]; - if (!parent) throw new Error("missing: " + nodeId); - if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); - if (parent.children) parent.children.push(node); - else parent.children = [node]; - node.parent = parent; - } - } - - if (!root) throw new Error("no root"); - root.parent = preroot; - root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); - root.parent = null; - if (n > 0) throw new Error("cycle"); - - return root; - } - - stratify.id = function(x) { - return arguments.length ? (id = required(x), stratify) : id; - }; - - stratify.parentId = function(x) { - return arguments.length ? (parentId = required(x), stratify) : parentId; - }; - - return stratify; -}; - -function defaultSeparation$1(a, b) { - return a.parent === b.parent ? 1 : 2; -} - -// function radialSeparation(a, b) { -// return (a.parent === b.parent ? 1 : 2) / a.depth; -// } - -// This function is used to traverse the left contour of a subtree (or -// subforest). It returns the successor of v on this contour. This successor is -// either given by the leftmost child of v or by the thread of v. The function -// returns null if and only if v is on the highest level of its subtree. -function nextLeft(v) { - var children = v.children; - return children ? children[0] : v.t; -} - -// This function works analogously to nextLeft. -function nextRight(v) { - var children = v.children; - return children ? children[children.length - 1] : v.t; -} - -// Shifts the current subtree rooted at w+. This is done by increasing -// prelim(w+) and mod(w+) by shift. -function moveSubtree(wm, wp, shift) { - var change = shift / (wp.i - wm.i); - wp.c -= change; - wp.s += shift; - wm.c += change; - wp.z += shift; - wp.m += shift; -} - -// All other shifts, applied to the smaller subtrees between w- and w+, are -// performed by this function. To prepare the shifts, we have to adjust -// change(w+), shift(w+), and change(w-). -function executeShifts(v) { - var shift = 0, - change = 0, - children = v.children, - i = children.length, - w; - while (--i >= 0) { - w = children[i]; - w.z += shift; - w.m += shift; - shift += w.s + (change += w.c); - } -} - -// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, -// returns the specified (default) ancestor. -function nextAncestor(vim, v, ancestor) { - return vim.a.parent === v.parent ? vim.a : ancestor; -} - -function TreeNode(node, i) { - this._ = node; - this.parent = null; - this.children = null; - this.A = null; // default ancestor - this.a = this; // ancestor - this.z = 0; // prelim - this.m = 0; // mod - this.c = 0; // change - this.s = 0; // shift - this.t = null; // thread - this.i = i; // number -} - -TreeNode.prototype = Object.create(Node.prototype); - -function treeRoot(root) { - var tree = new TreeNode(root, 0), - node, - nodes = [tree], - child, - children, - i, - n; - - while (node = nodes.pop()) { - if (children = node._.children) { - node.children = new Array(n = children.length); - for (i = n - 1; i >= 0; --i) { - nodes.push(child = node.children[i] = new TreeNode(children[i], i)); - child.parent = node; - } - } - } - - (tree.parent = new TreeNode(null, 0)).children = [tree]; - return tree; -} - -// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm -var tree = function() { - var separation = defaultSeparation$1, - dx = 1, - dy = 1, - nodeSize = null; - - function tree(root) { - var t = treeRoot(root); - - // Compute the layout using Buchheim et al.’s algorithm. - t.eachAfter(firstWalk), t.parent.m = -t.z; - t.eachBefore(secondWalk); - - // If a fixed node size is specified, scale x and y. - if (nodeSize) root.eachBefore(sizeNode); - - // If a fixed tree size is specified, scale x and y based on the extent. - // Compute the left-most, right-most, and depth-most nodes for extents. - else { - var left = root, - right = root, - bottom = root; - root.eachBefore(function(node) { - if (node.x < left.x) left = node; - if (node.x > right.x) right = node; - if (node.depth > bottom.depth) bottom = node; - }); - var s = left === right ? 1 : separation(left, right) / 2, - tx = s - left.x, - kx = dx / (right.x + s + tx), - ky = dy / (bottom.depth || 1); - root.eachBefore(function(node) { - node.x = (node.x + tx) * kx; - node.y = node.depth * ky; - }); - } - - return root; - } - - // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is - // applied recursively to the children of v, as well as the function - // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the - // node v is placed to the midpoint of its outermost children. - function firstWalk(v) { - var children = v.children, - siblings = v.parent.children, - w = v.i ? siblings[v.i - 1] : null; - if (children) { - executeShifts(v); - var midpoint = (children[0].z + children[children.length - 1].z) / 2; - if (w) { - v.z = w.z + separation(v._, w._); - v.m = v.z - midpoint; - } else { - v.z = midpoint; - } - } else if (w) { - v.z = w.z + separation(v._, w._); - } - v.parent.A = apportion(v, w, v.parent.A || siblings[0]); - } - - // Computes all real x-coordinates by summing up the modifiers recursively. - function secondWalk(v) { - v._.x = v.z + v.parent.m; - v.m += v.parent.m; - } - - // The core of the algorithm. Here, a new subtree is combined with the - // previous subtrees. Threads are used to traverse the inside and outside - // contours of the left and right subtree up to the highest common level. The - // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the - // superscript o means outside and i means inside, the subscript - means left - // subtree and + means right subtree. For summing up the modifiers along the - // contour, we use respective variables si+, si-, so-, and so+. Whenever two - // nodes of the inside contours conflict, we compute the left one of the - // greatest uncommon ancestors using the function ANCESTOR and call MOVE - // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. - // Finally, we add a new thread (if necessary). - function apportion(v, w, ancestor) { - if (w) { - var vip = v, - vop = v, - vim = w, - vom = vip.parent.children[0], - sip = vip.m, - sop = vop.m, - sim = vim.m, - som = vom.m, - shift; - while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) { - vom = nextLeft(vom); - vop = nextRight(vop); - vop.a = v; - shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); - if (shift > 0) { - moveSubtree(nextAncestor(vim, v, ancestor), v, shift); - sip += shift; - sop += shift; - } - sim += vim.m; - sip += vip.m; - som += vom.m; - sop += vop.m; - } - if (vim && !nextRight(vop)) { - vop.t = vim; - vop.m += sim - sop; - } - if (vip && !nextLeft(vom)) { - vom.t = vip; - vom.m += sip - som; - ancestor = v; - } - } - return ancestor; - } - - function sizeNode(node) { - node.x *= dx; - node.y = node.depth * dy; - } - - tree.separation = function(x) { - return arguments.length ? (separation = x, tree) : separation; - }; - - tree.size = function(x) { - return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); - }; - - tree.nodeSize = function(x) { - return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); - }; - - return tree; -}; - -var treemapSlice = function(parent, x0, y0, x1, y1) { - var nodes = parent.children, - node, - i = -1, - n = nodes.length, - k = parent.value && (y1 - y0) / parent.value; - - while (++i < n) { - node = nodes[i], node.x0 = x0, node.x1 = x1; - node.y0 = y0, node.y1 = y0 += node.value * k; - } -}; - -var phi = (1 + Math.sqrt(5)) / 2; - -function squarifyRatio(ratio, parent, x0, y0, x1, y1) { - var rows = [], - nodes = parent.children, - row, - nodeValue, - i0 = 0, - i1 = 0, - n = nodes.length, - dx, dy, - value = parent.value, - sumValue, - minValue, - maxValue, - newRatio, - minRatio, - alpha, - beta; - - while (i0 < n) { - dx = x1 - x0, dy = y1 - y0; - - // Find the next non-empty node. - do sumValue = nodes[i1++].value; while (!sumValue && i1 < n); - minValue = maxValue = sumValue; - alpha = Math.max(dy / dx, dx / dy) / (value * ratio); - beta = sumValue * sumValue * alpha; - minRatio = Math.max(maxValue / beta, beta / minValue); - - // Keep adding nodes while the aspect ratio maintains or improves. - for (; i1 < n; ++i1) { - sumValue += nodeValue = nodes[i1].value; - if (nodeValue < minValue) minValue = nodeValue; - if (nodeValue > maxValue) maxValue = nodeValue; - beta = sumValue * sumValue * alpha; - newRatio = Math.max(maxValue / beta, beta / minValue); - if (newRatio > minRatio) { sumValue -= nodeValue; break; } - minRatio = newRatio; - } - - // Position and record the row orientation. - rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); - if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); - else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); - value -= sumValue, i0 = i1; - } - - return rows; -} - -var squarify = (function custom(ratio) { - - function squarify(parent, x0, y0, x1, y1) { - squarifyRatio(ratio, parent, x0, y0, x1, y1); - } - - squarify.ratio = function(x) { - return custom((x = +x) > 1 ? x : 1); - }; - - return squarify; -})(phi); - -var index$3 = function() { - var tile = squarify, - round = false, - dx = 1, - dy = 1, - paddingStack = [0], - paddingInner = constantZero, - paddingTop = constantZero, - paddingRight = constantZero, - paddingBottom = constantZero, - paddingLeft = constantZero; - - function treemap(root) { - root.x0 = - root.y0 = 0; - root.x1 = dx; - root.y1 = dy; - root.eachBefore(positionNode); - paddingStack = [0]; - if (round) root.eachBefore(roundNode); - return root; - } - - function positionNode(node) { - var p = paddingStack[node.depth], - x0 = node.x0 + p, - y0 = node.y0 + p, - x1 = node.x1 - p, - y1 = node.y1 - p; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - node.x0 = x0; - node.y0 = y0; - node.x1 = x1; - node.y1 = y1; - if (node.children) { - p = paddingStack[node.depth + 1] = paddingInner(node) / 2; - x0 += paddingLeft(node) - p; - y0 += paddingTop(node) - p; - x1 -= paddingRight(node) - p; - y1 -= paddingBottom(node) - p; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - tile(node, x0, y0, x1, y1); - } - } - - treemap.round = function(x) { - return arguments.length ? (round = !!x, treemap) : round; - }; - - treemap.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; - }; - - treemap.tile = function(x) { - return arguments.length ? (tile = required(x), treemap) : tile; - }; - - treemap.padding = function(x) { - return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); - }; - - treemap.paddingInner = function(x) { - return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$8(+x), treemap) : paddingInner; - }; - - treemap.paddingOuter = function(x) { - return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); - }; - - treemap.paddingTop = function(x) { - return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$8(+x), treemap) : paddingTop; - }; - - treemap.paddingRight = function(x) { - return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$8(+x), treemap) : paddingRight; - }; - - treemap.paddingBottom = function(x) { - return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$8(+x), treemap) : paddingBottom; - }; - - treemap.paddingLeft = function(x) { - return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$8(+x), treemap) : paddingLeft; - }; - - return treemap; -}; - -var binary = function(parent, x0, y0, x1, y1) { - var nodes = parent.children, - i, n = nodes.length, - sum, sums = new Array(n + 1); - - for (sums[0] = sum = i = 0; i < n; ++i) { - sums[i + 1] = sum += nodes[i].value; - } - - partition(0, n, parent.value, x0, y0, x1, y1); - - function partition(i, j, value, x0, y0, x1, y1) { - if (i >= j - 1) { - var node = nodes[i]; - node.x0 = x0, node.y0 = y0; - node.x1 = x1, node.y1 = y1; - return; - } - - var valueOffset = sums[i], - valueTarget = (value / 2) + valueOffset, - k = i + 1, - hi = j - 1; - - while (k < hi) { - var mid = k + hi >>> 1; - if (sums[mid] < valueTarget) k = mid + 1; - else hi = mid; - } - - if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k; - - var valueLeft = sums[k] - valueOffset, - valueRight = value - valueLeft; - - if ((x1 - x0) > (y1 - y0)) { - var xk = (x0 * valueRight + x1 * valueLeft) / value; - partition(i, k, valueLeft, x0, y0, xk, y1); - partition(k, j, valueRight, xk, y0, x1, y1); - } else { - var yk = (y0 * valueRight + y1 * valueLeft) / value; - partition(i, k, valueLeft, x0, y0, x1, yk); - partition(k, j, valueRight, x0, yk, x1, y1); - } - } -}; - -var sliceDice = function(parent, x0, y0, x1, y1) { - (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); -}; - -var resquarify = (function custom(ratio) { - - function resquarify(parent, x0, y0, x1, y1) { - if ((rows = parent._squarify) && (rows.ratio === ratio)) { - var rows, - row, - nodes, - i, - j = -1, - n, - m = rows.length, - value = parent.value; - - while (++j < m) { - row = rows[j], nodes = row.children; - for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value; - if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); - else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); - value -= row.value; - } - } else { - parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); - rows.ratio = ratio; - } - } - - resquarify.ratio = function(x) { - return custom((x = +x) > 1 ? x : 1); - }; - - return resquarify; -})(phi); - -var area$1 = function(polygon) { - var i = -1, - n = polygon.length, - a, - b = polygon[n - 1], - area = 0; - - while (++i < n) { - a = b; - b = polygon[i]; - area += a[1] * b[0] - a[0] * b[1]; - } - - return area / 2; -}; - -var centroid$1 = function(polygon) { - var i = -1, - n = polygon.length, - x = 0, - y = 0, - a, - b = polygon[n - 1], - c, - k = 0; - - while (++i < n) { - a = b; - b = polygon[i]; - k += c = a[0] * b[1] - b[0] * a[1]; - x += (a[0] + b[0]) * c; - y += (a[1] + b[1]) * c; - } - - return k *= 3, [x / k, y / k]; -}; - -// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of -// the 3D cross product in a quadrant I Cartesian coordinate system (+x is -// right, +y is up). Returns a positive value if ABC is counter-clockwise, -// negative if clockwise, and zero if the points are collinear. -var cross$1 = function(a, b, c) { - return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); -}; - -function lexicographicOrder(a, b) { - return a[0] - b[0] || a[1] - b[1]; -} - -// Computes the upper convex hull per the monotone chain algorithm. -// Assumes points.length >= 3, is sorted by x, unique in y. -// Returns an array of indices into points in left-to-right order. -function computeUpperHullIndexes(points) { - var n = points.length, - indexes = [0, 1], - size = 2; - - for (var i = 2; i < n; ++i) { - while (size > 1 && cross$1(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size; - indexes[size++] = i; - } - - return indexes.slice(0, size); // remove popped points -} - -var hull = function(points) { - if ((n = points.length) < 3) return null; - - var i, - n, - sortedPoints = new Array(n), - flippedPoints = new Array(n); - - for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i]; - sortedPoints.sort(lexicographicOrder); - for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]; - - var upperIndexes = computeUpperHullIndexes(sortedPoints), - lowerIndexes = computeUpperHullIndexes(flippedPoints); - - // Construct the hull polygon, removing possible duplicate endpoints. - var skipLeft = lowerIndexes[0] === upperIndexes[0], - skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1], - hull = []; - - // Add upper hull in right-to-l order. - // Then add lower hull in left-to-right order. - for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]); - for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]); - - return hull; -}; - -var contains$1 = function(polygon, point) { - var n = polygon.length, - p = polygon[n - 1], - x = point[0], y = point[1], - x0 = p[0], y0 = p[1], - x1, y1, - inside = false; - - for (var i = 0; i < n; ++i) { - p = polygon[i], x1 = p[0], y1 = p[1]; - if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside; - x0 = x1, y0 = y1; - } - - return inside; -}; - -var length$2 = function(polygon) { - var i = -1, - n = polygon.length, - b = polygon[n - 1], - xa, - ya, - xb = b[0], - yb = b[1], - perimeter = 0; - - while (++i < n) { - xa = xb; - ya = yb; - b = polygon[i]; - xb = b[0]; - yb = b[1]; - xa -= xb; - ya -= yb; - perimeter += Math.sqrt(xa * xa + ya * ya); - } - - return perimeter; -}; - -var slice$4 = [].slice; - -var noabort = {}; - -function Queue(size) { - this._size = size; - this._call = - this._error = null; - this._tasks = []; - this._data = []; - this._waiting = - this._active = - this._ended = - this._start = 0; // inside a synchronous task callback? -} - -Queue.prototype = queue.prototype = { - constructor: Queue, - defer: function(callback) { - if (typeof callback !== "function") throw new Error("invalid callback"); - if (this._call) throw new Error("defer after await"); - if (this._error != null) return this; - var t = slice$4.call(arguments, 1); - t.push(callback); - ++this._waiting, this._tasks.push(t); - poke$1(this); - return this; - }, - abort: function() { - if (this._error == null) abort(this, new Error("abort")); - return this; - }, - await: function(callback) { - if (typeof callback !== "function") throw new Error("invalid callback"); - if (this._call) throw new Error("multiple await"); - this._call = function(error, results) { callback.apply(null, [error].concat(results)); }; - maybeNotify(this); - return this; - }, - awaitAll: function(callback) { - if (typeof callback !== "function") throw new Error("invalid callback"); - if (this._call) throw new Error("multiple await"); - this._call = callback; - maybeNotify(this); - return this; - } -}; - -function poke$1(q) { - if (!q._start) { - try { start$1(q); } // let the current task complete - catch (e) { - if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously - else if (!q._data) throw e; // await callback errored synchronously - } - } -} - -function start$1(q) { - while (q._start = q._waiting && q._active < q._size) { - var i = q._ended + q._active, - t = q._tasks[i], - j = t.length - 1, - c = t[j]; - t[j] = end(q, i); - --q._waiting, ++q._active; - t = c.apply(null, t); - if (!q._tasks[i]) continue; // task finished synchronously - q._tasks[i] = t || noabort; - } -} - -function end(q, i) { - return function(e, r) { - if (!q._tasks[i]) return; // ignore multiple callbacks - --q._active, ++q._ended; - q._tasks[i] = null; - if (q._error != null) return; // ignore secondary errors - if (e != null) { - abort(q, e); - } else { - q._data[i] = r; - if (q._waiting) poke$1(q); - else maybeNotify(q); - } - }; -} - -function abort(q, e) { - var i = q._tasks.length, t; - q._error = e; // ignore active callbacks - q._data = undefined; // allow gc - q._waiting = NaN; // prevent starting - - while (--i >= 0) { - if (t = q._tasks[i]) { - q._tasks[i] = null; - if (t.abort) { - try { t.abort(); } - catch (e) { /* ignore */ } - } - } - } - - q._active = NaN; // allow notification - maybeNotify(q); -} - -function maybeNotify(q) { - if (!q._active && q._call) { - var d = q._data; - q._data = undefined; // allow gc - q._call(q._error, d); - } -} - -function queue(concurrency) { - if (concurrency == null) concurrency = Infinity; - else if (!((concurrency = +concurrency) >= 1)) throw new Error("invalid concurrency"); - return new Queue(concurrency); -} - -var defaultSource$1 = function() { - return Math.random(); -}; - -var uniform = (function sourceRandomUniform(source) { - function randomUniform(min, max) { - min = min == null ? 0 : +min; - max = max == null ? 1 : +max; - if (arguments.length === 1) max = min, min = 0; - else max -= min; - return function() { - return source() * max + min; - }; - } - - randomUniform.source = sourceRandomUniform; - - return randomUniform; -})(defaultSource$1); - -var normal = (function sourceRandomNormal(source) { - function randomNormal(mu, sigma) { - var x, r; - mu = mu == null ? 0 : +mu; - sigma = sigma == null ? 1 : +sigma; - return function() { - var y; - - // If available, use the second previously-generated uniform random. - if (x != null) y = x, x = null; - - // Otherwise, generate a new x and y. - else do { - x = source() * 2 - 1; - y = source() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); - - return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); - }; - } - - randomNormal.source = sourceRandomNormal; - - return randomNormal; -})(defaultSource$1); - -var logNormal = (function sourceRandomLogNormal(source) { - function randomLogNormal() { - var randomNormal = normal.source(source).apply(this, arguments); - return function() { - return Math.exp(randomNormal()); - }; - } - - randomLogNormal.source = sourceRandomLogNormal; - - return randomLogNormal; -})(defaultSource$1); - -var irwinHall = (function sourceRandomIrwinHall(source) { - function randomIrwinHall(n) { - return function() { - for (var sum = 0, i = 0; i < n; ++i) sum += source(); - return sum; - }; - } - - randomIrwinHall.source = sourceRandomIrwinHall; - - return randomIrwinHall; -})(defaultSource$1); - -var bates = (function sourceRandomBates(source) { - function randomBates(n) { - var randomIrwinHall = irwinHall.source(source)(n); - return function() { - return randomIrwinHall() / n; - }; - } - - randomBates.source = sourceRandomBates; - - return randomBates; -})(defaultSource$1); - -var exponential$1 = (function sourceRandomExponential(source) { - function randomExponential(lambda) { - return function() { - return -Math.log(1 - source()) / lambda; - }; - } - - randomExponential.source = sourceRandomExponential; - - return randomExponential; -})(defaultSource$1); - -var request = function(url, callback) { - var request, - event = dispatch("beforesend", "progress", "load", "error"), - mimeType, - headers = map$1(), - xhr = new XMLHttpRequest, - user = null, - password = null, - response, - responseType, - timeout = 0; - - // If IE does not support CORS, use XDomainRequest. - if (typeof XDomainRequest !== "undefined" - && !("withCredentials" in xhr) - && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; - - "onload" in xhr - ? xhr.onload = xhr.onerror = xhr.ontimeout = respond - : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; - - function respond(o) { - var status = xhr.status, result; - if (!status && hasResponse(xhr) - || status >= 200 && status < 300 - || status === 304) { - if (response) { - try { - result = response.call(request, xhr); - } catch (e) { - event.call("error", request, e); - return; - } - } else { - result = xhr; - } - event.call("load", request, result); - } else { - event.call("error", request, o); - } - } - - xhr.onprogress = function(e) { - event.call("progress", request, e); - }; - - request = { - header: function(name, value) { - name = (name + "").toLowerCase(); - if (arguments.length < 2) return headers.get(name); - if (value == null) headers.remove(name); - else headers.set(name, value + ""); - return request; - }, - - // If mimeType is non-null and no Accept header is set, a default is used. - mimeType: function(value) { - if (!arguments.length) return mimeType; - mimeType = value == null ? null : value + ""; - return request; - }, - - // Specifies what type the response value should take; - // for instance, arraybuffer, blob, document, or text. - responseType: function(value) { - if (!arguments.length) return responseType; - responseType = value; - return request; - }, - - timeout: function(value) { - if (!arguments.length) return timeout; - timeout = +value; - return request; - }, - - user: function(value) { - return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); - }, - - password: function(value) { - return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); - }, - - // Specify how to convert the response content to a specific type; - // changes the callback value on "load" events. - response: function(value) { - response = value; - return request; - }, - - // Alias for send("GET", 
). - get: function(data, callback) { - return request.send("GET", data, callback); - }, - - // Alias for send("POST", 
). - post: function(data, callback) { - return request.send("POST", data, callback); - }, - - // If callback is non-null, it will be used for error and load events. - send: function(method, data, callback) { - xhr.open(method, url, true, user, password); - if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); - if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); - if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); - if (responseType != null) xhr.responseType = responseType; - if (timeout > 0) xhr.timeout = timeout; - if (callback == null && typeof data === "function") callback = data, data = null; - if (callback != null && callback.length === 1) callback = fixCallback(callback); - if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); - event.call("beforesend", request, xhr); - xhr.send(data == null ? null : data); - return request; - }, - - abort: function() { - xhr.abort(); - return request; - }, - - on: function() { - var value = event.on.apply(event, arguments); - return value === event ? request : value; - } - }; - - if (callback != null) { - if (typeof callback !== "function") throw new Error("invalid callback: " + callback); - return request.get(callback); - } - - return request; -}; - -function fixCallback(callback) { - return function(error, xhr) { - callback(error == null ? xhr : null); - }; -} - -function hasResponse(xhr) { - var type = xhr.responseType; - return type && type !== "text" - ? xhr.response // null on error - : xhr.responseText; // "" on error -} - -var type$1 = function(defaultMimeType, response) { - return function(url, callback) { - var r = request(url).mimeType(defaultMimeType).response(response); - if (callback != null) { - if (typeof callback !== "function") throw new Error("invalid callback: " + callback); - return r.get(callback); - } - return r; - }; -}; - -var html = type$1("text/html", function(xhr) { - return document.createRange().createContextualFragment(xhr.responseText); -}); - -var json = type$1("application/json", function(xhr) { - return JSON.parse(xhr.responseText); -}); - -var text = type$1("text/plain", function(xhr) { - return xhr.responseText; -}); - -var xml = type$1("application/xml", function(xhr) { - var xml = xhr.responseXML; - if (!xml) throw new Error("parse error"); - return xml; -}); - -var dsv$1 = function(defaultMimeType, parse) { - return function(url, row, callback) { - if (arguments.length < 3) callback = row, row = null; - var r = request(url).mimeType(defaultMimeType); - r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; - r.row(row); - return callback ? r.get(callback) : r; - }; -}; - -function responseOf(parse, row) { - return function(request$$1) { - return parse(request$$1.responseText, row); - }; -} - -var csv$1 = dsv$1("text/csv", csvParse); - -var tsv$1 = dsv$1("text/tab-separated-values", tsvParse); - -var array$2 = Array.prototype; - -var map$3 = array$2.map; -var slice$5 = array$2.slice; - -var implicit = {name: "implicit"}; - -function ordinal(range) { - var index = map$1(), - domain = [], - unknown = implicit; - - range = range == null ? [] : slice$5.call(range); - - function scale(d) { - var key = d + "", i = index.get(key); - if (!i) { - if (unknown !== implicit) return unknown; - index.set(key, i = domain.push(d)); - } - return range[(i - 1) % range.length]; - } - - scale.domain = function(_) { - if (!arguments.length) return domain.slice(); - domain = [], index = map$1(); - var i = -1, n = _.length, d, key; - while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d)); - return scale; - }; - - scale.range = function(_) { - return arguments.length ? (range = slice$5.call(_), scale) : range.slice(); - }; - - scale.unknown = function(_) { - return arguments.length ? (unknown = _, scale) : unknown; - }; - - scale.copy = function() { - return ordinal() - .domain(domain) - .range(range) - .unknown(unknown); - }; - - return scale; -} - -function band() { - var scale = ordinal().unknown(undefined), - domain = scale.domain, - ordinalRange = scale.range, - range$$1 = [0, 1], - step, - bandwidth, - round = false, - paddingInner = 0, - paddingOuter = 0, - align = 0.5; - - delete scale.unknown; - - function rescale() { - var n = domain().length, - reverse = range$$1[1] < range$$1[0], - start = range$$1[reverse - 0], - stop = range$$1[1 - reverse]; - step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); - if (round) step = Math.floor(step); - start += (stop - start - step * (n - paddingInner)) * align; - bandwidth = step * (1 - paddingInner); - if (round) start = Math.round(start), bandwidth = Math.round(bandwidth); - var values = sequence(n).map(function(i) { return start + step * i; }); - return ordinalRange(reverse ? values.reverse() : values); - } - - scale.domain = function(_) { - return arguments.length ? (domain(_), rescale()) : domain(); - }; - - scale.range = function(_) { - return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice(); - }; - - scale.rangeRound = function(_) { - return range$$1 = [+_[0], +_[1]], round = true, rescale(); - }; - - scale.bandwidth = function() { - return bandwidth; - }; - - scale.step = function() { - return step; - }; - - scale.round = function(_) { - return arguments.length ? (round = !!_, rescale()) : round; - }; - - scale.padding = function(_) { - return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; - }; - - scale.paddingInner = function(_) { - return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; - }; - - scale.paddingOuter = function(_) { - return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter; - }; - - scale.align = function(_) { - return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align; - }; - - scale.copy = function() { - return band() - .domain(domain()) - .range(range$$1) - .round(round) - .paddingInner(paddingInner) - .paddingOuter(paddingOuter) - .align(align); - }; - - return rescale(); -} - -function pointish(scale) { - var copy = scale.copy; - - scale.padding = scale.paddingOuter; - delete scale.paddingInner; - delete scale.paddingOuter; - - scale.copy = function() { - return pointish(copy()); - }; - - return scale; -} - -function point$1() { - return pointish(band().paddingInner(1)); -} - -var constant$9 = function(x) { - return function() { - return x; - }; -}; - -var number$2 = function(x) { - return +x; -}; - -var unit = [0, 1]; - -function deinterpolateLinear(a, b) { - return (b -= (a = +a)) - ? function(x) { return (x - a) / b; } - : constant$9(b); -} - -function deinterpolateClamp(deinterpolate) { - return function(a, b) { - var d = deinterpolate(a = +a, b = +b); - return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; - }; -} - -function reinterpolateClamp(reinterpolate) { - return function(a, b) { - var r = reinterpolate(a = +a, b = +b); - return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; - }; -} - -function bimap(domain, range, deinterpolate, reinterpolate) { - var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1]; - if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); - else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); - return function(x) { return r0(d0(x)); }; -} - -function polymap(domain, range, deinterpolate, reinterpolate) { - var j = Math.min(domain.length, range.length) - 1, - d = new Array(j), - r = new Array(j), - i = -1; - - // Reverse descending domains. - if (domain[j] < domain[0]) { - domain = domain.slice().reverse(); - range = range.slice().reverse(); - } - - while (++i < j) { - d[i] = deinterpolate(domain[i], domain[i + 1]); - r[i] = reinterpolate(range[i], range[i + 1]); - } - - return function(x) { - var i = bisectRight(domain, x, 1, j) - 1; - return r[i](d[i](x)); - }; -} - -function copy(source, target) { - return target - .domain(source.domain()) - .range(source.range()) - .interpolate(source.interpolate()) - .clamp(source.clamp()); -} - -// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. -// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. -function continuous(deinterpolate, reinterpolate) { - var domain = unit, - range = unit, - interpolate$$1 = interpolateValue, - clamp = false, - piecewise, - output, - input; - - function rescale() { - piecewise = Math.min(domain.length, range.length) > 2 ? polymap : bimap; - output = input = null; - return scale; - } - - function scale(x) { - return (output || (output = piecewise(domain, range, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x); - } - - scale.invert = function(y) { - return (input || (input = piecewise(range, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); - }; - - scale.domain = function(_) { - return arguments.length ? (domain = map$3.call(_, number$2), rescale()) : domain.slice(); - }; - - scale.range = function(_) { - return arguments.length ? (range = slice$5.call(_), rescale()) : range.slice(); - }; - - scale.rangeRound = function(_) { - return range = slice$5.call(_), interpolate$$1 = interpolateRound, rescale(); - }; - - scale.clamp = function(_) { - return arguments.length ? (clamp = !!_, rescale()) : clamp; - }; - - scale.interpolate = function(_) { - return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1; - }; - - return rescale(); -} - -var tickFormat = function(domain, count, specifier) { - var start = domain[0], - stop = domain[domain.length - 1], - step = tickStep(start, stop, count == null ? 10 : count), - precision; - specifier = formatSpecifier(specifier == null ? ",f" : specifier); - switch (specifier.type) { - case "s": { - var value = Math.max(Math.abs(start), Math.abs(stop)); - if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision; - return exports.formatPrefix(specifier, value); - } - case "": - case "e": - case "g": - case "p": - case "r": { - if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e"); - break; - } - case "f": - case "%": { - if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2; - break; - } - } - return exports.format(specifier); -}; - -function linearish(scale) { - var domain = scale.domain; - - scale.ticks = function(count) { - var d = domain(); - return ticks(d[0], d[d.length - 1], count == null ? 10 : count); - }; - - scale.tickFormat = function(count, specifier) { - return tickFormat(domain(), count, specifier); - }; - - scale.nice = function(count) { - if (count == null) count = 10; - - var d = domain(), - i0 = 0, - i1 = d.length - 1, - start = d[i0], - stop = d[i1], - step; - - if (stop < start) { - step = start, start = stop, stop = step; - step = i0, i0 = i1, i1 = step; - } - - step = tickIncrement(start, stop, count); - - if (step > 0) { - start = Math.floor(start / step) * step; - stop = Math.ceil(stop / step) * step; - step = tickIncrement(start, stop, count); - } else if (step < 0) { - start = Math.ceil(start * step) / step; - stop = Math.floor(stop * step) / step; - step = tickIncrement(start, stop, count); - } - - if (step > 0) { - d[i0] = Math.floor(start / step) * step; - d[i1] = Math.ceil(stop / step) * step; - domain(d); - } else if (step < 0) { - d[i0] = Math.ceil(start * step) / step; - d[i1] = Math.floor(stop * step) / step; - domain(d); - } - - return scale; - }; - - return scale; -} - -function linear$2() { - var scale = continuous(deinterpolateLinear, reinterpolate); - - scale.copy = function() { - return copy(scale, linear$2()); - }; - - return linearish(scale); -} - -function identity$6() { - var domain = [0, 1]; - - function scale(x) { - return +x; - } - - scale.invert = scale; - - scale.domain = scale.range = function(_) { - return arguments.length ? (domain = map$3.call(_, number$2), scale) : domain.slice(); - }; - - scale.copy = function() { - return identity$6().domain(domain); - }; - - return linearish(scale); -} - -var nice = function(domain, interval) { - domain = domain.slice(); - - var i0 = 0, - i1 = domain.length - 1, - x0 = domain[i0], - x1 = domain[i1], - t; - - if (x1 < x0) { - t = i0, i0 = i1, i1 = t; - t = x0, x0 = x1, x1 = t; - } - - domain[i0] = interval.floor(x0); - domain[i1] = interval.ceil(x1); - return domain; -}; - -function deinterpolate(a, b) { - return (b = Math.log(b / a)) - ? function(x) { return Math.log(x / a) / b; } - : constant$9(b); -} - -function reinterpolate$1(a, b) { - return a < 0 - ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); } - : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); }; -} - -function pow10(x) { - return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; -} - -function powp(base) { - return base === 10 ? pow10 - : base === Math.E ? Math.exp - : function(x) { return Math.pow(base, x); }; -} - -function logp(base) { - return base === Math.E ? Math.log - : base === 10 && Math.log10 - || base === 2 && Math.log2 - || (base = Math.log(base), function(x) { return Math.log(x) / base; }); -} - -function reflect(f) { - return function(x) { - return -f(-x); - }; -} - -function log$1() { - var scale = continuous(deinterpolate, reinterpolate$1).domain([1, 10]), - domain = scale.domain, - base = 10, - logs = logp(10), - pows = powp(10); - - function rescale() { - logs = logp(base), pows = powp(base); - if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows); - return scale; - } - - scale.base = function(_) { - return arguments.length ? (base = +_, rescale()) : base; - }; - - scale.domain = function(_) { - return arguments.length ? (domain(_), rescale()) : domain(); - }; - - scale.ticks = function(count) { - var d = domain(), - u = d[0], - v = d[d.length - 1], - r; - - if (r = v < u) i = u, u = v, v = i; - - var i = logs(u), - j = logs(v), - p, - k, - t, - n = count == null ? 10 : +count, - z = []; - - if (!(base % 1) && j - i < n) { - i = Math.round(i) - 1, j = Math.round(j) + 1; - if (u > 0) for (; i < j; ++i) { - for (k = 1, p = pows(i); k < base; ++k) { - t = p * k; - if (t < u) continue; - if (t > v) break; - z.push(t); - } - } else for (; i < j; ++i) { - for (k = base - 1, p = pows(i); k >= 1; --k) { - t = p * k; - if (t < u) continue; - if (t > v) break; - z.push(t); - } - } - } else { - z = ticks(i, j, Math.min(j - i, n)).map(pows); - } - - return r ? z.reverse() : z; - }; - - scale.tickFormat = function(count, specifier) { - if (specifier == null) specifier = base === 10 ? ".0e" : ","; - if (typeof specifier !== "function") specifier = exports.format(specifier); - if (count === Infinity) return specifier; - if (count == null) count = 10; - var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate? - return function(d) { - var i = d / pows(Math.round(logs(d))); - if (i * base < base - 0.5) i *= base; - return i <= k ? specifier(d) : ""; - }; - }; - - scale.nice = function() { - return domain(nice(domain(), { - floor: function(x) { return pows(Math.floor(logs(x))); }, - ceil: function(x) { return pows(Math.ceil(logs(x))); } - })); - }; - - scale.copy = function() { - return copy(scale, log$1().base(base)); - }; - - return scale; -} - -function raise$1(x, exponent) { - return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); -} - -function pow$1() { - var exponent = 1, - scale = continuous(deinterpolate, reinterpolate), - domain = scale.domain; - - function deinterpolate(a, b) { - return (b = raise$1(b, exponent) - (a = raise$1(a, exponent))) - ? function(x) { return (raise$1(x, exponent) - a) / b; } - : constant$9(b); - } - - function reinterpolate(a, b) { - b = raise$1(b, exponent) - (a = raise$1(a, exponent)); - return function(t) { return raise$1(a + b * t, 1 / exponent); }; - } - - scale.exponent = function(_) { - return arguments.length ? (exponent = +_, domain(domain())) : exponent; - }; - - scale.copy = function() { - return copy(scale, pow$1().exponent(exponent)); - }; - - return linearish(scale); -} - -function sqrt$1() { - return pow$1().exponent(0.5); -} - -function quantile$$1() { - var domain = [], - range = [], - thresholds = []; - - function rescale() { - var i = 0, n = Math.max(1, range.length); - thresholds = new Array(n - 1); - while (++i < n) thresholds[i - 1] = threshold(domain, i / n); - return scale; - } - - function scale(x) { - if (!isNaN(x = +x)) return range[bisectRight(thresholds, x)]; - } - - scale.invertExtent = function(y) { - var i = range.indexOf(y); - return i < 0 ? [NaN, NaN] : [ - i > 0 ? thresholds[i - 1] : domain[0], - i < thresholds.length ? thresholds[i] : domain[domain.length - 1] - ]; - }; - - scale.domain = function(_) { - if (!arguments.length) return domain.slice(); - domain = []; - for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d); - domain.sort(ascending); - return rescale(); - }; - - scale.range = function(_) { - return arguments.length ? (range = slice$5.call(_), rescale()) : range.slice(); - }; - - scale.quantiles = function() { - return thresholds.slice(); - }; - - scale.copy = function() { - return quantile$$1() - .domain(domain) - .range(range); - }; - - return scale; -} - -function quantize$1() { - var x0 = 0, - x1 = 1, - n = 1, - domain = [0.5], - range = [0, 1]; - - function scale(x) { - if (x <= x) return range[bisectRight(domain, x, 0, n)]; - } - - function rescale() { - var i = -1; - domain = new Array(n); - while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1); - return scale; - } - - scale.domain = function(_) { - return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1]; - }; - - scale.range = function(_) { - return arguments.length ? (n = (range = slice$5.call(_)).length - 1, rescale()) : range.slice(); - }; - - scale.invertExtent = function(y) { - var i = range.indexOf(y); - return i < 0 ? [NaN, NaN] - : i < 1 ? [x0, domain[0]] - : i >= n ? [domain[n - 1], x1] - : [domain[i - 1], domain[i]]; - }; - - scale.copy = function() { - return quantize$1() - .domain([x0, x1]) - .range(range); - }; - - return linearish(scale); -} - -function threshold$1() { - var domain = [0.5], - range = [0, 1], - n = 1; - - function scale(x) { - if (x <= x) return range[bisectRight(domain, x, 0, n)]; - } - - scale.domain = function(_) { - return arguments.length ? (domain = slice$5.call(_), n = Math.min(domain.length, range.length - 1), scale) : domain.slice(); - }; - - scale.range = function(_) { - return arguments.length ? (range = slice$5.call(_), n = Math.min(domain.length, range.length - 1), scale) : range.slice(); - }; - - scale.invertExtent = function(y) { - var i = range.indexOf(y); - return [domain[i - 1], domain[i]]; - }; - - scale.copy = function() { - return threshold$1() - .domain(domain) - .range(range); - }; - - return scale; -} - -var t0$1 = new Date; -var t1$1 = new Date; - -function newInterval(floori, offseti, count, field) { - - function interval(date) { - return floori(date = new Date(+date)), date; - } - - interval.floor = interval; - - interval.ceil = function(date) { - return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; - }; - - interval.round = function(date) { - var d0 = interval(date), - d1 = interval.ceil(date); - return date - d0 < d1 - date ? d0 : d1; - }; - - interval.offset = function(date, step) { - return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; - }; - - interval.range = function(start, stop, step) { - var range = []; - start = interval.ceil(start); - step = step == null ? 1 : Math.floor(step); - if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date - do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop) - return range; - }; - - interval.filter = function(test) { - return newInterval(function(date) { - if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); - }, function(date, step) { - if (date >= date) { - if (step < 0) while (++step <= 0) { - while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty - } else while (--step >= 0) { - while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty - } - } - }); - }; - - if (count) { - interval.count = function(start, end) { - t0$1.setTime(+start), t1$1.setTime(+end); - floori(t0$1), floori(t1$1); - return Math.floor(count(t0$1, t1$1)); - }; - - interval.every = function(step) { - step = Math.floor(step); - return !isFinite(step) || !(step > 0) ? null - : !(step > 1) ? interval - : interval.filter(field - ? function(d) { return field(d) % step === 0; } - : function(d) { return interval.count(0, d) % step === 0; }); - }; - } - - return interval; -} - -var millisecond = newInterval(function() { - // noop -}, function(date, step) { - date.setTime(+date + step); -}, function(start, end) { - return end - start; -}); - -// An optimized implementation for this simple case. -millisecond.every = function(k) { - k = Math.floor(k); - if (!isFinite(k) || !(k > 0)) return null; - if (!(k > 1)) return millisecond; - return newInterval(function(date) { - date.setTime(Math.floor(date / k) * k); - }, function(date, step) { - date.setTime(+date + step * k); - }, function(start, end) { - return (end - start) / k; - }); -}; - -var milliseconds = millisecond.range; - -var durationSecond$1 = 1e3; -var durationMinute$1 = 6e4; -var durationHour$1 = 36e5; -var durationDay$1 = 864e5; -var durationWeek$1 = 6048e5; - -var second = newInterval(function(date) { - date.setTime(Math.floor(date / durationSecond$1) * durationSecond$1); -}, function(date, step) { - date.setTime(+date + step * durationSecond$1); -}, function(start, end) { - return (end - start) / durationSecond$1; -}, function(date) { - return date.getUTCSeconds(); -}); - -var seconds = second.range; - -var minute = newInterval(function(date) { - date.setTime(Math.floor(date / durationMinute$1) * durationMinute$1); -}, function(date, step) { - date.setTime(+date + step * durationMinute$1); -}, function(start, end) { - return (end - start) / durationMinute$1; -}, function(date) { - return date.getMinutes(); -}); - -var minutes = minute.range; - -var hour = newInterval(function(date) { - var offset = date.getTimezoneOffset() * durationMinute$1 % durationHour$1; - if (offset < 0) offset += durationHour$1; - date.setTime(Math.floor((+date - offset) / durationHour$1) * durationHour$1 + offset); -}, function(date, step) { - date.setTime(+date + step * durationHour$1); -}, function(start, end) { - return (end - start) / durationHour$1; -}, function(date) { - return date.getHours(); -}); - -var hours = hour.range; - -var day = newInterval(function(date) { - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setDate(date.getDate() + step); -}, function(start, end) { - return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationDay$1; -}, function(date) { - return date.getDate() - 1; -}); - -var days = day.range; - -function weekday(i) { - return newInterval(function(date) { - date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); - date.setHours(0, 0, 0, 0); - }, function(date, step) { - date.setDate(date.getDate() + step * 7); - }, function(start, end) { - return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationWeek$1; - }); -} - -var sunday = weekday(0); -var monday = weekday(1); -var tuesday = weekday(2); -var wednesday = weekday(3); -var thursday = weekday(4); -var friday = weekday(5); -var saturday = weekday(6); - -var sundays = sunday.range; -var mondays = monday.range; -var tuesdays = tuesday.range; -var wednesdays = wednesday.range; -var thursdays = thursday.range; -var fridays = friday.range; -var saturdays = saturday.range; - -var month = newInterval(function(date) { - date.setDate(1); - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setMonth(date.getMonth() + step); -}, function(start, end) { - return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; -}, function(date) { - return date.getMonth(); -}); - -var months = month.range; - -var year = newInterval(function(date) { - date.setMonth(0, 1); - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setFullYear(date.getFullYear() + step); -}, function(start, end) { - return end.getFullYear() - start.getFullYear(); -}, function(date) { - return date.getFullYear(); -}); - -// An optimized implementation for this simple case. -year.every = function(k) { - return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { - date.setFullYear(Math.floor(date.getFullYear() / k) * k); - date.setMonth(0, 1); - date.setHours(0, 0, 0, 0); - }, function(date, step) { - date.setFullYear(date.getFullYear() + step * k); - }); -}; - -var years = year.range; - -var utcMinute = newInterval(function(date) { - date.setUTCSeconds(0, 0); -}, function(date, step) { - date.setTime(+date + step * durationMinute$1); -}, function(start, end) { - return (end - start) / durationMinute$1; -}, function(date) { - return date.getUTCMinutes(); -}); - -var utcMinutes = utcMinute.range; - -var utcHour = newInterval(function(date) { - date.setUTCMinutes(0, 0, 0); -}, function(date, step) { - date.setTime(+date + step * durationHour$1); -}, function(start, end) { - return (end - start) / durationHour$1; -}, function(date) { - return date.getUTCHours(); -}); - -var utcHours = utcHour.range; - -var utcDay = newInterval(function(date) { - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCDate(date.getUTCDate() + step); -}, function(start, end) { - return (end - start) / durationDay$1; -}, function(date) { - return date.getUTCDate() - 1; -}); - -var utcDays = utcDay.range; - -function utcWeekday(i) { - return newInterval(function(date) { - date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); - date.setUTCHours(0, 0, 0, 0); - }, function(date, step) { - date.setUTCDate(date.getUTCDate() + step * 7); - }, function(start, end) { - return (end - start) / durationWeek$1; - }); -} - -var utcSunday = utcWeekday(0); -var utcMonday = utcWeekday(1); -var utcTuesday = utcWeekday(2); -var utcWednesday = utcWeekday(3); -var utcThursday = utcWeekday(4); -var utcFriday = utcWeekday(5); -var utcSaturday = utcWeekday(6); - -var utcSundays = utcSunday.range; -var utcMondays = utcMonday.range; -var utcTuesdays = utcTuesday.range; -var utcWednesdays = utcWednesday.range; -var utcThursdays = utcThursday.range; -var utcFridays = utcFriday.range; -var utcSaturdays = utcSaturday.range; - -var utcMonth = newInterval(function(date) { - date.setUTCDate(1); - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCMonth(date.getUTCMonth() + step); -}, function(start, end) { - return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; -}, function(date) { - return date.getUTCMonth(); -}); - -var utcMonths = utcMonth.range; - -var utcYear = newInterval(function(date) { - date.setUTCMonth(0, 1); - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCFullYear(date.getUTCFullYear() + step); -}, function(start, end) { - return end.getUTCFullYear() - start.getUTCFullYear(); -}, function(date) { - return date.getUTCFullYear(); -}); - -// An optimized implementation for this simple case. -utcYear.every = function(k) { - return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { - date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); - date.setUTCMonth(0, 1); - date.setUTCHours(0, 0, 0, 0); - }, function(date, step) { - date.setUTCFullYear(date.getUTCFullYear() + step * k); - }); -}; - -var utcYears = utcYear.range; - -function localDate(d) { - if (0 <= d.y && d.y < 100) { - var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); - date.setFullYear(d.y); - return date; - } - return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); -} - -function utcDate(d) { - if (0 <= d.y && d.y < 100) { - var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); - date.setUTCFullYear(d.y); - return date; - } - return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); -} - -function newYear(y) { - return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; -} - -function formatLocale$1(locale) { - var locale_dateTime = locale.dateTime, - locale_date = locale.date, - locale_time = locale.time, - locale_periods = locale.periods, - locale_weekdays = locale.days, - locale_shortWeekdays = locale.shortDays, - locale_months = locale.months, - locale_shortMonths = locale.shortMonths; - - var periodRe = formatRe(locale_periods), - periodLookup = formatLookup(locale_periods), - weekdayRe = formatRe(locale_weekdays), - weekdayLookup = formatLookup(locale_weekdays), - shortWeekdayRe = formatRe(locale_shortWeekdays), - shortWeekdayLookup = formatLookup(locale_shortWeekdays), - monthRe = formatRe(locale_months), - monthLookup = formatLookup(locale_months), - shortMonthRe = formatRe(locale_shortMonths), - shortMonthLookup = formatLookup(locale_shortMonths); - - var formats = { - "a": formatShortWeekday, - "A": formatWeekday, - "b": formatShortMonth, - "B": formatMonth, - "c": null, - "d": formatDayOfMonth, - "e": formatDayOfMonth, - "H": formatHour24, - "I": formatHour12, - "j": formatDayOfYear, - "L": formatMilliseconds, - "m": formatMonthNumber, - "M": formatMinutes, - "p": formatPeriod, - "S": formatSeconds, - "U": formatWeekNumberSunday, - "w": formatWeekdayNumber, - "W": formatWeekNumberMonday, - "x": null, - "X": null, - "y": formatYear, - "Y": formatFullYear, - "Z": formatZone, - "%": formatLiteralPercent - }; - - var utcFormats = { - "a": formatUTCShortWeekday, - "A": formatUTCWeekday, - "b": formatUTCShortMonth, - "B": formatUTCMonth, - "c": null, - "d": formatUTCDayOfMonth, - "e": formatUTCDayOfMonth, - "H": formatUTCHour24, - "I": formatUTCHour12, - "j": formatUTCDayOfYear, - "L": formatUTCMilliseconds, - "m": formatUTCMonthNumber, - "M": formatUTCMinutes, - "p": formatUTCPeriod, - "S": formatUTCSeconds, - "U": formatUTCWeekNumberSunday, - "w": formatUTCWeekdayNumber, - "W": formatUTCWeekNumberMonday, - "x": null, - "X": null, - "y": formatUTCYear, - "Y": formatUTCFullYear, - "Z": formatUTCZone, - "%": formatLiteralPercent - }; - - var parses = { - "a": parseShortWeekday, - "A": parseWeekday, - "b": parseShortMonth, - "B": parseMonth, - "c": parseLocaleDateTime, - "d": parseDayOfMonth, - "e": parseDayOfMonth, - "H": parseHour24, - "I": parseHour24, - "j": parseDayOfYear, - "L": parseMilliseconds, - "m": parseMonthNumber, - "M": parseMinutes, - "p": parsePeriod, - "S": parseSeconds, - "U": parseWeekNumberSunday, - "w": parseWeekdayNumber, - "W": parseWeekNumberMonday, - "x": parseLocaleDate, - "X": parseLocaleTime, - "y": parseYear, - "Y": parseFullYear, - "Z": parseZone, - "%": parseLiteralPercent - }; - - // These recursive directive definitions must be deferred. - formats.x = newFormat(locale_date, formats); - formats.X = newFormat(locale_time, formats); - formats.c = newFormat(locale_dateTime, formats); - utcFormats.x = newFormat(locale_date, utcFormats); - utcFormats.X = newFormat(locale_time, utcFormats); - utcFormats.c = newFormat(locale_dateTime, utcFormats); - - function newFormat(specifier, formats) { - return function(date) { - var string = [], - i = -1, - j = 0, - n = specifier.length, - c, - pad, - format; - - if (!(date instanceof Date)) date = new Date(+date); - - while (++i < n) { - if (specifier.charCodeAt(i) === 37) { - string.push(specifier.slice(j, i)); - if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); - else pad = c === "e" ? " " : "0"; - if (format = formats[c]) c = format(date, pad); - string.push(c); - j = i + 1; - } - } - - string.push(specifier.slice(j, i)); - return string.join(""); - }; - } - - function newParse(specifier, newDate) { - return function(string) { - var d = newYear(1900), - i = parseSpecifier(d, specifier, string += "", 0); - if (i != string.length) return null; - - // The am-pm flag is 0 for AM, and 1 for PM. - if ("p" in d) d.H = d.H % 12 + d.p * 12; - - // Convert day-of-week and week-of-year to day-of-year. - if ("W" in d || "U" in d) { - if (!("w" in d)) d.w = "W" in d ? 1 : 0; - var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); - d.m = 0; - d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$$1 + 5) % 7 : d.w + d.U * 7 - (day$$1 + 6) % 7; - } - - // If a time zone is specified, all fields are interpreted as UTC and then - // offset according to the specified time zone. - if ("Z" in d) { - d.H += d.Z / 100 | 0; - d.M += d.Z % 100; - return utcDate(d); - } - - // Otherwise, all fields are in local time. - return newDate(d); - }; - } - - function parseSpecifier(d, specifier, string, j) { - var i = 0, - n = specifier.length, - m = string.length, - c, - parse; - - while (i < n) { - if (j >= m) return -1; - c = specifier.charCodeAt(i++); - if (c === 37) { - c = specifier.charAt(i++); - parse = parses[c in pads ? specifier.charAt(i++) : c]; - if (!parse || ((j = parse(d, string, j)) < 0)) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } - } - - return j; - } - - function parsePeriod(d, string, i) { - var n = periodRe.exec(string.slice(i)); - return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseShortWeekday(d, string, i) { - var n = shortWeekdayRe.exec(string.slice(i)); - return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseWeekday(d, string, i) { - var n = weekdayRe.exec(string.slice(i)); - return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseShortMonth(d, string, i) { - var n = shortMonthRe.exec(string.slice(i)); - return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseMonth(d, string, i) { - var n = monthRe.exec(string.slice(i)); - return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseLocaleDateTime(d, string, i) { - return parseSpecifier(d, locale_dateTime, string, i); - } - - function parseLocaleDate(d, string, i) { - return parseSpecifier(d, locale_date, string, i); - } - - function parseLocaleTime(d, string, i) { - return parseSpecifier(d, locale_time, string, i); - } - - function formatShortWeekday(d) { - return locale_shortWeekdays[d.getDay()]; - } - - function formatWeekday(d) { - return locale_weekdays[d.getDay()]; - } - - function formatShortMonth(d) { - return locale_shortMonths[d.getMonth()]; - } - - function formatMonth(d) { - return locale_months[d.getMonth()]; - } - - function formatPeriod(d) { - return locale_periods[+(d.getHours() >= 12)]; - } - - function formatUTCShortWeekday(d) { - return locale_shortWeekdays[d.getUTCDay()]; - } - - function formatUTCWeekday(d) { - return locale_weekdays[d.getUTCDay()]; - } - - function formatUTCShortMonth(d) { - return locale_shortMonths[d.getUTCMonth()]; - } - - function formatUTCMonth(d) { - return locale_months[d.getUTCMonth()]; - } - - function formatUTCPeriod(d) { - return locale_periods[+(d.getUTCHours() >= 12)]; - } - - return { - format: function(specifier) { - var f = newFormat(specifier += "", formats); - f.toString = function() { return specifier; }; - return f; - }, - parse: function(specifier) { - var p = newParse(specifier += "", localDate); - p.toString = function() { return specifier; }; - return p; - }, - utcFormat: function(specifier) { - var f = newFormat(specifier += "", utcFormats); - f.toString = function() { return specifier; }; - return f; - }, - utcParse: function(specifier) { - var p = newParse(specifier, utcDate); - p.toString = function() { return specifier; }; - return p; - } - }; -} - -var pads = {"-": "", "_": " ", "0": "0"}; -var numberRe = /^\s*\d+/; -var percentRe = /^%/; -var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - -function pad(value, fill, width) { - var sign = value < 0 ? "-" : "", - string = (sign ? -value : value) + "", - length = string.length; - return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); -} - -function requote(s) { - return s.replace(requoteRe, "\\$&"); -} - -function formatRe(names) { - return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); -} - -function formatLookup(names) { - var map = {}, i = -1, n = names.length; - while (++i < n) map[names[i].toLowerCase()] = i; - return map; -} - -function parseWeekdayNumber(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 1)); - return n ? (d.w = +n[0], i + n[0].length) : -1; -} - -function parseWeekNumberSunday(d, string, i) { - var n = numberRe.exec(string.slice(i)); - return n ? (d.U = +n[0], i + n[0].length) : -1; -} - -function parseWeekNumberMonday(d, string, i) { - var n = numberRe.exec(string.slice(i)); - return n ? (d.W = +n[0], i + n[0].length) : -1; -} - -function parseFullYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 4)); - return n ? (d.y = +n[0], i + n[0].length) : -1; -} - -function parseYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; -} - -function parseZone(d, string, i) { - var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6)); - return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; -} - -function parseMonthNumber(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.m = n[0] - 1, i + n[0].length) : -1; -} - -function parseDayOfMonth(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.d = +n[0], i + n[0].length) : -1; -} - -function parseDayOfYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 3)); - return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; -} - -function parseHour24(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.H = +n[0], i + n[0].length) : -1; -} - -function parseMinutes(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.M = +n[0], i + n[0].length) : -1; -} - -function parseSeconds(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.S = +n[0], i + n[0].length) : -1; -} - -function parseMilliseconds(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 3)); - return n ? (d.L = +n[0], i + n[0].length) : -1; -} - -function parseLiteralPercent(d, string, i) { - var n = percentRe.exec(string.slice(i, i + 1)); - return n ? i + n[0].length : -1; -} - -function formatDayOfMonth(d, p) { - return pad(d.getDate(), p, 2); -} - -function formatHour24(d, p) { - return pad(d.getHours(), p, 2); -} - -function formatHour12(d, p) { - return pad(d.getHours() % 12 || 12, p, 2); -} - -function formatDayOfYear(d, p) { - return pad(1 + day.count(year(d), d), p, 3); -} - -function formatMilliseconds(d, p) { - return pad(d.getMilliseconds(), p, 3); -} - -function formatMonthNumber(d, p) { - return pad(d.getMonth() + 1, p, 2); -} - -function formatMinutes(d, p) { - return pad(d.getMinutes(), p, 2); -} - -function formatSeconds(d, p) { - return pad(d.getSeconds(), p, 2); -} - -function formatWeekNumberSunday(d, p) { - return pad(sunday.count(year(d), d), p, 2); -} - -function formatWeekdayNumber(d) { - return d.getDay(); -} - -function formatWeekNumberMonday(d, p) { - return pad(monday.count(year(d), d), p, 2); -} - -function formatYear(d, p) { - return pad(d.getFullYear() % 100, p, 2); -} - -function formatFullYear(d, p) { - return pad(d.getFullYear() % 10000, p, 4); -} - -function formatZone(d) { - var z = d.getTimezoneOffset(); - return (z > 0 ? "-" : (z *= -1, "+")) - + pad(z / 60 | 0, "0", 2) - + pad(z % 60, "0", 2); -} - -function formatUTCDayOfMonth(d, p) { - return pad(d.getUTCDate(), p, 2); -} - -function formatUTCHour24(d, p) { - return pad(d.getUTCHours(), p, 2); -} - -function formatUTCHour12(d, p) { - return pad(d.getUTCHours() % 12 || 12, p, 2); -} - -function formatUTCDayOfYear(d, p) { - return pad(1 + utcDay.count(utcYear(d), d), p, 3); -} - -function formatUTCMilliseconds(d, p) { - return pad(d.getUTCMilliseconds(), p, 3); -} - -function formatUTCMonthNumber(d, p) { - return pad(d.getUTCMonth() + 1, p, 2); -} - -function formatUTCMinutes(d, p) { - return pad(d.getUTCMinutes(), p, 2); -} - -function formatUTCSeconds(d, p) { - return pad(d.getUTCSeconds(), p, 2); -} - -function formatUTCWeekNumberSunday(d, p) { - return pad(utcSunday.count(utcYear(d), d), p, 2); -} - -function formatUTCWeekdayNumber(d) { - return d.getUTCDay(); -} - -function formatUTCWeekNumberMonday(d, p) { - return pad(utcMonday.count(utcYear(d), d), p, 2); -} - -function formatUTCYear(d, p) { - return pad(d.getUTCFullYear() % 100, p, 2); -} - -function formatUTCFullYear(d, p) { - return pad(d.getUTCFullYear() % 10000, p, 4); -} - -function formatUTCZone() { - return "+0000"; -} - -function formatLiteralPercent() { - return "%"; -} - -var locale$1; - - - - - -defaultLocale$1({ - dateTime: "%x, %X", - date: "%-m/%-d/%Y", - time: "%-I:%M:%S %p", - periods: ["AM", "PM"], - days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], - shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], - months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] -}); - -function defaultLocale$1(definition) { - locale$1 = formatLocale$1(definition); - exports.timeFormat = locale$1.format; - exports.timeParse = locale$1.parse; - exports.utcFormat = locale$1.utcFormat; - exports.utcParse = locale$1.utcParse; - return locale$1; -} - -var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; - -function formatIsoNative(date) { - return date.toISOString(); -} - -var formatIso = Date.prototype.toISOString - ? formatIsoNative - : exports.utcFormat(isoSpecifier); - -function parseIsoNative(string) { - var date = new Date(string); - return isNaN(date) ? null : date; -} - -var parseIso = +new Date("2000-01-01T00:00:00.000Z") - ? parseIsoNative - : exports.utcParse(isoSpecifier); - -var durationSecond = 1000; -var durationMinute = durationSecond * 60; -var durationHour = durationMinute * 60; -var durationDay = durationHour * 24; -var durationWeek = durationDay * 7; -var durationMonth = durationDay * 30; -var durationYear = durationDay * 365; - -function date$1(t) { - return new Date(t); -} - -function number$3(t) { - return t instanceof Date ? +t : +new Date(+t); -} - -function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) { - var scale = continuous(deinterpolateLinear, reinterpolate), - invert = scale.invert, - domain = scale.domain; - - var formatMillisecond = format(".%L"), - formatSecond = format(":%S"), - formatMinute = format("%I:%M"), - formatHour = format("%I %p"), - formatDay = format("%a %d"), - formatWeek = format("%b %d"), - formatMonth = format("%B"), - formatYear = format("%Y"); - - var tickIntervals = [ - [second$$1, 1, durationSecond], - [second$$1, 5, 5 * durationSecond], - [second$$1, 15, 15 * durationSecond], - [second$$1, 30, 30 * durationSecond], - [minute$$1, 1, durationMinute], - [minute$$1, 5, 5 * durationMinute], - [minute$$1, 15, 15 * durationMinute], - [minute$$1, 30, 30 * durationMinute], - [ hour$$1, 1, durationHour ], - [ hour$$1, 3, 3 * durationHour ], - [ hour$$1, 6, 6 * durationHour ], - [ hour$$1, 12, 12 * durationHour ], - [ day$$1, 1, durationDay ], - [ day$$1, 2, 2 * durationDay ], - [ week, 1, durationWeek ], - [ month$$1, 1, durationMonth ], - [ month$$1, 3, 3 * durationMonth ], - [ year$$1, 1, durationYear ] - ]; - - function tickFormat(date) { - return (second$$1(date) < date ? formatMillisecond - : minute$$1(date) < date ? formatSecond - : hour$$1(date) < date ? formatMinute - : day$$1(date) < date ? formatHour - : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek) - : year$$1(date) < date ? formatMonth - : formatYear)(date); - } - - function tickInterval(interval, start, stop, step) { - if (interval == null) interval = 10; - - // If a desired tick count is specified, pick a reasonable tick interval - // based on the extent of the domain and a rough estimate of tick size. - // Otherwise, assume interval is already a time interval and use it. - if (typeof interval === "number") { - var target = Math.abs(stop - start) / interval, - i = bisector(function(i) { return i[2]; }).right(tickIntervals, target); - if (i === tickIntervals.length) { - step = tickStep(start / durationYear, stop / durationYear, interval); - interval = year$$1; - } else if (i) { - i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; - step = i[1]; - interval = i[0]; - } else { - step = tickStep(start, stop, interval); - interval = millisecond$$1; - } - } - - return step == null ? interval : interval.every(step); - } - - scale.invert = function(y) { - return new Date(invert(y)); - }; - - scale.domain = function(_) { - return arguments.length ? domain(map$3.call(_, number$3)) : domain().map(date$1); - }; - - scale.ticks = function(interval, step) { - var d = domain(), - t0 = d[0], - t1 = d[d.length - 1], - r = t1 < t0, - t; - if (r) t = t0, t0 = t1, t1 = t; - t = tickInterval(interval, t0, t1, step); - t = t ? t.range(t0, t1 + 1) : []; // inclusive stop - return r ? t.reverse() : t; - }; - - scale.tickFormat = function(count, specifier) { - return specifier == null ? tickFormat : format(specifier); - }; - - scale.nice = function(interval, step) { - var d = domain(); - return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) - ? domain(nice(d, interval)) - : scale; - }; - - scale.copy = function() { - return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format)); - }; - - return scale; -} - -var time = function() { - return calendar(year, month, sunday, day, hour, minute, second, millisecond, exports.timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); -}; - -var utcTime = function() { - return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, exports.utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]); -}; - -var colors = function(s) { - return s.match(/.{6}/g).map(function(x) { - return "#" + x; - }); -}; - -var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); - -var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"); - -var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"); - -var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"); - -var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0)); - -var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); - -var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); - -var rainbow = cubehelix(); - -var rainbow$1 = function(t) { - if (t < 0 || t > 1) t -= Math.floor(t); - var ts = Math.abs(t - 0.5); - rainbow.h = 360 * t - 100; - rainbow.s = 1.5 - 1.5 * ts; - rainbow.l = 0.8 - 0.9 * ts; - return rainbow + ""; -}; - -function ramp(range) { - var n = range.length; - return function(t) { - return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; - }; -} - -var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); - -var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); - -var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); - -var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); - -function sequential(interpolator) { - var x0 = 0, - x1 = 1, - clamp = false; - - function scale(x) { - var t = (x - x0) / (x1 - x0); - return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t); - } - - scale.domain = function(_) { - return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1]; - }; - - scale.clamp = function(_) { - return arguments.length ? (clamp = !!_, scale) : clamp; - }; - - scale.interpolator = function(_) { - return arguments.length ? (interpolator = _, scale) : interpolator; - }; - - scale.copy = function() { - return sequential(interpolator).domain([x0, x1]).clamp(clamp); - }; - - return linearish(scale); -} - -var constant$10 = function(x) { - return function constant() { - return x; - }; -}; - -var abs$1 = Math.abs; -var atan2$1 = Math.atan2; -var cos$2 = Math.cos; -var max$2 = Math.max; -var min$1 = Math.min; -var sin$2 = Math.sin; -var sqrt$2 = Math.sqrt; - -var epsilon$3 = 1e-12; -var pi$4 = Math.PI; -var halfPi$3 = pi$4 / 2; -var tau$4 = 2 * pi$4; - -function acos$1(x) { - return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x); -} - -function asin$1(x) { - return x >= 1 ? halfPi$3 : x <= -1 ? -halfPi$3 : Math.asin(x); -} - -function arcInnerRadius(d) { - return d.innerRadius; -} - -function arcOuterRadius(d) { - return d.outerRadius; -} - -function arcStartAngle(d) { - return d.startAngle; -} - -function arcEndAngle(d) { - return d.endAngle; -} - -function arcPadAngle(d) { - return d && d.padAngle; // Note: optional! -} - -function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { - var x10 = x1 - x0, y10 = y1 - y0, - x32 = x3 - x2, y32 = y3 - y2, - t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); - return [x0 + t * x10, y0 + t * y10]; -} - -// Compute perpendicular offset line of length rc. -// http://mathworld.wolfram.com/Circle-LineIntersection.html -function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { - var x01 = x0 - x1, - y01 = y0 - y1, - lo = (cw ? rc : -rc) / sqrt$2(x01 * x01 + y01 * y01), - ox = lo * y01, - oy = -lo * x01, - x11 = x0 + ox, - y11 = y0 + oy, - x10 = x1 + ox, - y10 = y1 + oy, - x00 = (x11 + x10) / 2, - y00 = (y11 + y10) / 2, - dx = x10 - x11, - dy = y10 - y11, - d2 = dx * dx + dy * dy, - r = r1 - rc, - D = x11 * y10 - x10 * y11, - d = (dy < 0 ? -1 : 1) * sqrt$2(max$2(0, r * r * d2 - D * D)), - cx0 = (D * dy - dx * d) / d2, - cy0 = (-D * dx - dy * d) / d2, - cx1 = (D * dy + dx * d) / d2, - cy1 = (-D * dx + dy * d) / d2, - dx0 = cx0 - x00, - dy0 = cy0 - y00, - dx1 = cx1 - x00, - dy1 = cy1 - y00; - - // Pick the closer of the two intersection points. - // TODO Is there a faster way to determine which intersection to use? - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; - - return { - cx: cx0, - cy: cy0, - x01: -ox, - y01: -oy, - x11: cx0 * (r1 / r - 1), - y11: cy0 * (r1 / r - 1) - }; -} - -var arc = function() { - var innerRadius = arcInnerRadius, - outerRadius = arcOuterRadius, - cornerRadius = constant$10(0), - padRadius = null, - startAngle = arcStartAngle, - endAngle = arcEndAngle, - padAngle = arcPadAngle, - context = null; - - function arc() { - var buffer, - r, - r0 = +innerRadius.apply(this, arguments), - r1 = +outerRadius.apply(this, arguments), - a0 = startAngle.apply(this, arguments) - halfPi$3, - a1 = endAngle.apply(this, arguments) - halfPi$3, - da = abs$1(a1 - a0), - cw = a1 > a0; - - if (!context) context = buffer = path(); - - // Ensure that the outer radius is always larger than the inner radius. - if (r1 < r0) r = r1, r1 = r0, r0 = r; - - // Is it a point? - if (!(r1 > epsilon$3)) context.moveTo(0, 0); - - // Or is it a circle or annulus? - else if (da > tau$4 - epsilon$3) { - context.moveTo(r1 * cos$2(a0), r1 * sin$2(a0)); - context.arc(0, 0, r1, a0, a1, !cw); - if (r0 > epsilon$3) { - context.moveTo(r0 * cos$2(a1), r0 * sin$2(a1)); - context.arc(0, 0, r0, a1, a0, cw); - } - } - - // Or is it a circular or annular sector? - else { - var a01 = a0, - a11 = a1, - a00 = a0, - a10 = a1, - da0 = da, - da1 = da, - ap = padAngle.apply(this, arguments) / 2, - rp = (ap > epsilon$3) && (padRadius ? +padRadius.apply(this, arguments) : sqrt$2(r0 * r0 + r1 * r1)), - rc = min$1(abs$1(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), - rc0 = rc, - rc1 = rc, - t0, - t1; - - // Apply padding? Note that since r1 ≄ r0, da1 ≄ da0. - if (rp > epsilon$3) { - var p0 = asin$1(rp / r0 * sin$2(ap)), - p1 = asin$1(rp / r1 * sin$2(ap)); - if ((da0 -= p0 * 2) > epsilon$3) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; - else da0 = 0, a00 = a10 = (a0 + a1) / 2; - if ((da1 -= p1 * 2) > epsilon$3) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; - else da1 = 0, a01 = a11 = (a0 + a1) / 2; - } - - var x01 = r1 * cos$2(a01), - y01 = r1 * sin$2(a01), - x10 = r0 * cos$2(a10), - y10 = r0 * sin$2(a10); - - // Apply rounded corners? - if (rc > epsilon$3) { - var x11 = r1 * cos$2(a11), - y11 = r1 * sin$2(a11), - x00 = r0 * cos$2(a00), - y00 = r0 * sin$2(a00); - - // Restrict the corner radius according to the sector angle. - if (da < pi$4) { - var oc = da0 > epsilon$3 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], - ax = x01 - oc[0], - ay = y01 - oc[1], - bx = x11 - oc[0], - by = y11 - oc[1], - kc = 1 / sin$2(acos$1((ax * bx + ay * by) / (sqrt$2(ax * ax + ay * ay) * sqrt$2(bx * bx + by * by))) / 2), - lc = sqrt$2(oc[0] * oc[0] + oc[1] * oc[1]); - rc0 = min$1(rc, (r0 - lc) / (kc - 1)); - rc1 = min$1(rc, (r1 - lc) / (kc + 1)); - } - } - - // Is the sector collapsed to a line? - if (!(da1 > epsilon$3)) context.moveTo(x01, y01); - - // Does the sector’s outer ring have rounded corners? - else if (rc1 > epsilon$3) { - t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); - t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); - - context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); - - // Have the corners merged? - if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw); - - // Otherwise, draw the two corners and the ring. - else { - context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw); - context.arc(0, 0, r1, atan2$1(t0.cy + t0.y11, t0.cx + t0.x11), atan2$1(t1.cy + t1.y11, t1.cx + t1.x11), !cw); - context.arc(t1.cx, t1.cy, rc1, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw); - } - } - - // Or is the outer ring just a circular arc? - else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); - - // Is there no inner ring, and it’s a circular sector? - // Or perhaps it’s an annular sector collapsed due to padding? - if (!(r0 > epsilon$3) || !(da0 > epsilon$3)) context.lineTo(x10, y10); - - // Does the sector’s inner ring (or point) have rounded corners? - else if (rc0 > epsilon$3) { - t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); - t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); - - context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); - - // Have the corners merged? - if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw); - - // Otherwise, draw the two corners and the ring. - else { - context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw); - context.arc(0, 0, r0, atan2$1(t0.cy + t0.y11, t0.cx + t0.x11), atan2$1(t1.cy + t1.y11, t1.cx + t1.x11), cw); - context.arc(t1.cx, t1.cy, rc0, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw); - } - } - - // Or is the inner ring just a circular arc? - else context.arc(0, 0, r0, a10, a00, cw); - } - - context.closePath(); - - if (buffer) return context = null, buffer + "" || null; - } - - arc.centroid = function() { - var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, - a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$4 / 2; - return [cos$2(a) * r, sin$2(a) * r]; - }; - - arc.innerRadius = function(_) { - return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : innerRadius; - }; - - arc.outerRadius = function(_) { - return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : outerRadius; - }; - - arc.cornerRadius = function(_) { - return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$10(+_), arc) : cornerRadius; - }; - - arc.padRadius = function(_) { - return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), arc) : padRadius; - }; - - arc.startAngle = function(_) { - return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : startAngle; - }; - - arc.endAngle = function(_) { - return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : endAngle; - }; - - arc.padAngle = function(_) { - return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), arc) : padAngle; - }; - - arc.context = function(_) { - return arguments.length ? ((context = _ == null ? null : _), arc) : context; - }; - - return arc; -}; - -function Linear(context) { - this._context = context; -} - -Linear.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; // proceed - default: this._context.lineTo(x, y); break; - } - } -}; - -var curveLinear = function(context) { - return new Linear(context); -}; - -function x$3(p) { - return p[0]; -} - -function y$3(p) { - return p[1]; -} - -var line = function() { - var x$$1 = x$3, - y$$1 = y$3, - defined = constant$10(true), - context = null, - curve = curveLinear, - output = null; - - function line(data) { - var i, - n = data.length, - d, - defined0 = false, - buffer; - - if (context == null) output = curve(buffer = path()); - - for (i = 0; i <= n; ++i) { - if (!(i < n && defined(d = data[i], i, data)) === defined0) { - if (defined0 = !defined0) output.lineStart(); - else output.lineEnd(); - } - if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); - } - - if (buffer) return output = null, buffer + "" || null; - } - - line.x = function(_) { - return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : x$$1; - }; - - line.y = function(_) { - return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : y$$1; - }; - - line.defined = function(_) { - return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), line) : defined; - }; - - line.curve = function(_) { - return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; - }; - - line.context = function(_) { - return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; - }; - - return line; -}; - -var area$2 = function() { - var x0 = x$3, - x1 = null, - y0 = constant$10(0), - y1 = y$3, - defined = constant$10(true), - context = null, - curve = curveLinear, - output = null; - - function area(data) { - var i, - j, - k, - n = data.length, - d, - defined0 = false, - buffer, - x0z = new Array(n), - y0z = new Array(n); - - if (context == null) output = curve(buffer = path()); - - for (i = 0; i <= n; ++i) { - if (!(i < n && defined(d = data[i], i, data)) === defined0) { - if (defined0 = !defined0) { - j = i; - output.areaStart(); - output.lineStart(); - } else { - output.lineEnd(); - output.lineStart(); - for (k = i - 1; k >= j; --k) { - output.point(x0z[k], y0z[k]); - } - output.lineEnd(); - output.areaEnd(); - } - } - if (defined0) { - x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); - output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); - } - } - - if (buffer) return output = null, buffer + "" || null; - } - - function arealine() { - return line().defined(defined).curve(curve).context(context); - } - - area.x = function(_) { - return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), x1 = null, area) : x0; - }; - - area.x0 = function(_) { - return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$10(+_), area) : x0; - }; - - area.x1 = function(_) { - return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : x1; - }; - - area.y = function(_) { - return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), y1 = null, area) : y0; - }; - - area.y0 = function(_) { - return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$10(+_), area) : y0; - }; - - area.y1 = function(_) { - return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$10(+_), area) : y1; - }; - - area.lineX0 = - area.lineY0 = function() { - return arealine().x(x0).y(y0); - }; - - area.lineY1 = function() { - return arealine().x(x0).y(y1); - }; - - area.lineX1 = function() { - return arealine().x(x1).y(y0); - }; - - area.defined = function(_) { - return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), area) : defined; - }; - - area.curve = function(_) { - return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; - }; - - area.context = function(_) { - return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; - }; - - return area; -}; - -var descending$1 = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; -}; - -var identity$7 = function(d) { - return d; -}; - -var pie = function() { - var value = identity$7, - sortValues = descending$1, - sort = null, - startAngle = constant$10(0), - endAngle = constant$10(tau$4), - padAngle = constant$10(0); - - function pie(data) { - var i, - n = data.length, - j, - k, - sum = 0, - index = new Array(n), - arcs = new Array(n), - a0 = +startAngle.apply(this, arguments), - da = Math.min(tau$4, Math.max(-tau$4, endAngle.apply(this, arguments) - a0)), - a1, - p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), - pa = p * (da < 0 ? -1 : 1), - v; - - for (i = 0; i < n; ++i) { - if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { - sum += v; - } - } - - // Optionally sort the arcs by previously-computed values or by data. - if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); - else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); - - // Compute the arcs! They are stored in the original data's order. - for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { - j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { - data: data[j], - index: i, - value: v, - startAngle: a0, - endAngle: a1, - padAngle: p - }; - } - - return arcs; - } - - pie.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), pie) : value; - }; - - pie.sortValues = function(_) { - return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; - }; - - pie.sort = function(_) { - return arguments.length ? (sort = _, sortValues = null, pie) : sort; - }; - - pie.startAngle = function(_) { - return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : startAngle; - }; - - pie.endAngle = function(_) { - return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : endAngle; - }; - - pie.padAngle = function(_) { - return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$10(+_), pie) : padAngle; - }; - - return pie; -}; - -var curveRadialLinear = curveRadial(curveLinear); - -function Radial(curve) { - this._curve = curve; -} - -Radial.prototype = { - areaStart: function() { - this._curve.areaStart(); - }, - areaEnd: function() { - this._curve.areaEnd(); - }, - lineStart: function() { - this._curve.lineStart(); - }, - lineEnd: function() { - this._curve.lineEnd(); - }, - point: function(a, r) { - this._curve.point(r * Math.sin(a), r * -Math.cos(a)); - } -}; - -function curveRadial(curve) { - - function radial(context) { - return new Radial(curve(context)); - } - - radial._curve = curve; - - return radial; -} - -function lineRadial(l) { - var c = l.curve; - - l.angle = l.x, delete l.x; - l.radius = l.y, delete l.y; - - l.curve = function(_) { - return arguments.length ? c(curveRadial(_)) : c()._curve; - }; - - return l; -} - -var lineRadial$1 = function() { - return lineRadial(line().curve(curveRadialLinear)); -}; - -var areaRadial = function() { - var a = area$2().curve(curveRadialLinear), - c = a.curve, - x0 = a.lineX0, - x1 = a.lineX1, - y0 = a.lineY0, - y1 = a.lineY1; - - a.angle = a.x, delete a.x; - a.startAngle = a.x0, delete a.x0; - a.endAngle = a.x1, delete a.x1; - a.radius = a.y, delete a.y; - a.innerRadius = a.y0, delete a.y0; - a.outerRadius = a.y1, delete a.y1; - a.lineStartAngle = function() { return lineRadial(x0()); }, delete a.lineX0; - a.lineEndAngle = function() { return lineRadial(x1()); }, delete a.lineX1; - a.lineInnerRadius = function() { return lineRadial(y0()); }, delete a.lineY0; - a.lineOuterRadius = function() { return lineRadial(y1()); }, delete a.lineY1; - - a.curve = function(_) { - return arguments.length ? c(curveRadial(_)) : c()._curve; - }; - - return a; -}; - -var pointRadial = function(x, y) { - return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)]; -}; - -var slice$6 = Array.prototype.slice; - -function linkSource(d) { - return d.source; -} - -function linkTarget(d) { - return d.target; -} - -function link$2(curve) { - var source = linkSource, - target = linkTarget, - x$$1 = x$3, - y$$1 = y$3, - context = null; - - function link() { - var buffer, argv = slice$6.call(arguments), s = source.apply(this, argv), t = target.apply(this, argv); - if (!context) context = buffer = path(); - curve(context, +x$$1.apply(this, (argv[0] = s, argv)), +y$$1.apply(this, argv), +x$$1.apply(this, (argv[0] = t, argv)), +y$$1.apply(this, argv)); - if (buffer) return context = null, buffer + "" || null; - } - - link.source = function(_) { - return arguments.length ? (source = _, link) : source; - }; - - link.target = function(_) { - return arguments.length ? (target = _, link) : target; - }; - - link.x = function(_) { - return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$10(+_), link) : x$$1; - }; - - link.y = function(_) { - return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$10(+_), link) : y$$1; - }; - - link.context = function(_) { - return arguments.length ? ((context = _ == null ? null : _), link) : context; - }; - - return link; -} - -function curveHorizontal(context, x0, y0, x1, y1) { - context.moveTo(x0, y0); - context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1); -} - -function curveVertical(context, x0, y0, x1, y1) { - context.moveTo(x0, y0); - context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1); -} - -function curveRadial$1(context, x0, y0, x1, y1) { - var p0 = pointRadial(x0, y0), - p1 = pointRadial(x0, y0 = (y0 + y1) / 2), - p2 = pointRadial(x1, y0), - p3 = pointRadial(x1, y1); - context.moveTo(p0[0], p0[1]); - context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); -} - -function linkHorizontal() { - return link$2(curveHorizontal); -} - -function linkVertical() { - return link$2(curveVertical); -} - -function linkRadial() { - var l = link$2(curveRadial$1); - l.angle = l.x, delete l.x; - l.radius = l.y, delete l.y; - return l; -} - -var circle$2 = { - draw: function(context, size) { - var r = Math.sqrt(size / pi$4); - context.moveTo(r, 0); - context.arc(0, 0, r, 0, tau$4); - } -}; - -var cross$2 = { - draw: function(context, size) { - var r = Math.sqrt(size / 5) / 2; - context.moveTo(-3 * r, -r); - context.lineTo(-r, -r); - context.lineTo(-r, -3 * r); - context.lineTo(r, -3 * r); - context.lineTo(r, -r); - context.lineTo(3 * r, -r); - context.lineTo(3 * r, r); - context.lineTo(r, r); - context.lineTo(r, 3 * r); - context.lineTo(-r, 3 * r); - context.lineTo(-r, r); - context.lineTo(-3 * r, r); - context.closePath(); - } -}; - -var tan30 = Math.sqrt(1 / 3); -var tan30_2 = tan30 * 2; - -var diamond = { - draw: function(context, size) { - var y = Math.sqrt(size / tan30_2), - x = y * tan30; - context.moveTo(0, -y); - context.lineTo(x, 0); - context.lineTo(0, y); - context.lineTo(-x, 0); - context.closePath(); - } -}; - -var ka = 0.89081309152928522810; -var kr = Math.sin(pi$4 / 10) / Math.sin(7 * pi$4 / 10); -var kx = Math.sin(tau$4 / 10) * kr; -var ky = -Math.cos(tau$4 / 10) * kr; - -var star = { - draw: function(context, size) { - var r = Math.sqrt(size * ka), - x = kx * r, - y = ky * r; - context.moveTo(0, -r); - context.lineTo(x, y); - for (var i = 1; i < 5; ++i) { - var a = tau$4 * i / 5, - c = Math.cos(a), - s = Math.sin(a); - context.lineTo(s * r, -c * r); - context.lineTo(c * x - s * y, s * x + c * y); - } - context.closePath(); - } -}; - -var square = { - draw: function(context, size) { - var w = Math.sqrt(size), - x = -w / 2; - context.rect(x, x, w, w); - } -}; - -var sqrt3 = Math.sqrt(3); - -var triangle = { - draw: function(context, size) { - var y = -Math.sqrt(size / (sqrt3 * 3)); - context.moveTo(0, y * 2); - context.lineTo(-sqrt3 * y, -y); - context.lineTo(sqrt3 * y, -y); - context.closePath(); - } -}; - -var c = -0.5; -var s = Math.sqrt(3) / 2; -var k = 1 / Math.sqrt(12); -var a = (k / 2 + 1) * 3; - -var wye = { - draw: function(context, size) { - var r = Math.sqrt(size / a), - x0 = r / 2, - y0 = r * k, - x1 = x0, - y1 = r * k + r, - x2 = -x1, - y2 = y1; - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - context.lineTo(c * x0 - s * y0, s * x0 + c * y0); - context.lineTo(c * x1 - s * y1, s * x1 + c * y1); - context.lineTo(c * x2 - s * y2, s * x2 + c * y2); - context.lineTo(c * x0 + s * y0, c * y0 - s * x0); - context.lineTo(c * x1 + s * y1, c * y1 - s * x1); - context.lineTo(c * x2 + s * y2, c * y2 - s * x2); - context.closePath(); - } -}; - -var symbols = [ - circle$2, - cross$2, - diamond, - square, - star, - triangle, - wye -]; - -var symbol = function() { - var type = constant$10(circle$2), - size = constant$10(64), - context = null; - - function symbol() { - var buffer; - if (!context) context = buffer = path(); - type.apply(this, arguments).draw(context, +size.apply(this, arguments)); - if (buffer) return context = null, buffer + "" || null; - } - - symbol.type = function(_) { - return arguments.length ? (type = typeof _ === "function" ? _ : constant$10(_), symbol) : type; - }; - - symbol.size = function(_) { - return arguments.length ? (size = typeof _ === "function" ? _ : constant$10(+_), symbol) : size; - }; - - symbol.context = function(_) { - return arguments.length ? (context = _ == null ? null : _, symbol) : context; - }; - - return symbol; -}; - -var noop$2 = function() {}; - -function point$2(that, x, y) { - that._context.bezierCurveTo( - (2 * that._x0 + that._x1) / 3, - (2 * that._y0 + that._y1) / 3, - (that._x0 + 2 * that._x1) / 3, - (that._y0 + 2 * that._y1) / 3, - (that._x0 + 4 * that._x1 + x) / 6, - (that._y0 + 4 * that._y1 + y) / 6 - ); -} - -function Basis(context) { - this._context = context; -} - -Basis.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 3: point$2(this, this._x1, this._y1); // proceed - case 2: this._context.lineTo(this._x1, this._y1); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed - default: point$2(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -var basis$2 = function(context) { - return new Basis(context); -}; - -function BasisClosed(context) { - this._context = context; -} - -BasisClosed.prototype = { - areaStart: noop$2, - areaEnd: noop$2, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x2, this._y2); - this._context.closePath(); - break; - } - case 2: { - this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); - this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x2, this._y2); - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - break; - } - } - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._x2 = x, this._y2 = y; break; - case 1: this._point = 2; this._x3 = x, this._y3 = y; break; - case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; - default: point$2(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -var basisClosed$1 = function(context) { - return new BasisClosed(context); -}; - -function BasisOpen(context) { - this._context = context; -} - -BasisOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = NaN; - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; - case 3: this._point = 4; // proceed - default: point$2(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -var basisOpen = function(context) { - return new BasisOpen(context); -}; - -function Bundle(context, beta) { - this._basis = new Basis(context); - this._beta = beta; -} - -Bundle.prototype = { - lineStart: function() { - this._x = []; - this._y = []; - this._basis.lineStart(); - }, - lineEnd: function() { - var x = this._x, - y = this._y, - j = x.length - 1; - - if (j > 0) { - var x0 = x[0], - y0 = y[0], - dx = x[j] - x0, - dy = y[j] - y0, - i = -1, - t; - - while (++i <= j) { - t = i / j; - this._basis.point( - this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), - this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) - ); - } - } - - this._x = this._y = null; - this._basis.lineEnd(); - }, - point: function(x, y) { - this._x.push(+x); - this._y.push(+y); - } -}; - -var bundle = (function custom(beta) { - - function bundle(context) { - return beta === 1 ? new Basis(context) : new Bundle(context, beta); - } - - bundle.beta = function(beta) { - return custom(+beta); - }; - - return bundle; -})(0.85); - -function point$3(that, x, y) { - that._context.bezierCurveTo( - that._x1 + that._k * (that._x2 - that._x0), - that._y1 + that._k * (that._y2 - that._y0), - that._x2 + that._k * (that._x1 - x), - that._y2 + that._k * (that._y1 - y), - that._x2, - that._y2 - ); -} - -function Cardinal(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -Cardinal.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x2, this._y2); break; - case 3: point$3(this, this._x1, this._y1); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; this._x1 = x, this._y1 = y; break; - case 2: this._point = 3; // proceed - default: point$3(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var cardinal = (function custom(tension) { - - function cardinal(context) { - return new Cardinal(context, tension); - } - - cardinal.tension = function(tension) { - return custom(+tension); - }; - - return cardinal; -})(0); - -function CardinalClosed(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -CardinalClosed.prototype = { - areaStart: noop$2, - areaEnd: noop$2, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 2: { - this._context.lineTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - this.point(this._x5, this._y5); - break; - } - } - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._x3 = x, this._y3 = y; break; - case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; - case 2: this._point = 3; this._x5 = x, this._y5 = y; break; - default: point$3(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var cardinalClosed = (function custom(tension) { - - function cardinal$$1(context) { - return new CardinalClosed(context, tension); - } - - cardinal$$1.tension = function(tension) { - return custom(+tension); - }; - - return cardinal$$1; -})(0); - -function CardinalOpen(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -CardinalOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; - case 3: this._point = 4; // proceed - default: point$3(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var cardinalOpen = (function custom(tension) { - - function cardinal$$1(context) { - return new CardinalOpen(context, tension); - } - - cardinal$$1.tension = function(tension) { - return custom(+tension); - }; - - return cardinal$$1; -})(0); - -function point$4(that, x, y) { - var x1 = that._x1, - y1 = that._y1, - x2 = that._x2, - y2 = that._y2; - - if (that._l01_a > epsilon$3) { - var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, - n = 3 * that._l01_a * (that._l01_a + that._l12_a); - x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; - y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; - } - - if (that._l23_a > epsilon$3) { - var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, - m = 3 * that._l23_a * (that._l23_a + that._l12_a); - x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; - y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; - } - - that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); -} - -function CatmullRom(context, alpha) { - this._context = context; - this._alpha = alpha; -} - -CatmullRom.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x2, this._y2); break; - case 3: this.point(this._x2, this._y2); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } - - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; // proceed - default: point$4(this, x, y); break; - } - - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var catmullRom = (function custom(alpha) { - - function catmullRom(context) { - return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); - } - - catmullRom.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom; -})(0.5); - -function CatmullRomClosed(context, alpha) { - this._context = context; - this._alpha = alpha; -} - -CatmullRomClosed.prototype = { - areaStart: noop$2, - areaEnd: noop$2, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 2: { - this._context.lineTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - this.point(this._x5, this._y5); - break; - } - } - }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } - - switch (this._point) { - case 0: this._point = 1; this._x3 = x, this._y3 = y; break; - case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; - case 2: this._point = 3; this._x5 = x, this._y5 = y; break; - default: point$4(this, x, y); break; - } - - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var catmullRomClosed = (function custom(alpha) { - - function catmullRom$$1(context) { - return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); - } - - catmullRom$$1.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom$$1; -})(0.5); - -function CatmullRomOpen(context, alpha) { - this._context = context; - this._alpha = alpha; -} - -CatmullRomOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } - - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; - case 3: this._point = 4; // proceed - default: point$4(this, x, y); break; - } - - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var catmullRomOpen = (function custom(alpha) { - - function catmullRom$$1(context) { - return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); - } - - catmullRom$$1.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom$$1; -})(0.5); - -function LinearClosed(context) { - this._context = context; -} - -LinearClosed.prototype = { - areaStart: noop$2, - areaEnd: noop$2, - lineStart: function() { - this._point = 0; - }, - lineEnd: function() { - if (this._point) this._context.closePath(); - }, - point: function(x, y) { - x = +x, y = +y; - if (this._point) this._context.lineTo(x, y); - else this._point = 1, this._context.moveTo(x, y); - } -}; - -var linearClosed = function(context) { - return new LinearClosed(context); -}; - -function sign$1(x) { - return x < 0 ? -1 : 1; -} - -// Calculate the slopes of the tangents (Hermite-type interpolation) based on -// the following paper: Steffen, M. 1990. A Simple Method for Monotonic -// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. -// NOV(II), P. 443, 1990. -function slope3(that, x2, y2) { - var h0 = that._x1 - that._x0, - h1 = x2 - that._x1, - s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), - s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), - p = (s0 * h1 + s1 * h0) / (h0 + h1); - return (sign$1(s0) + sign$1(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; -} - -// Calculate a one-sided slope. -function slope2(that, t) { - var h = that._x1 - that._x0; - return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; -} - -// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations -// "you can express cubic Hermite interpolation in terms of cubic BĂ©zier curves -// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". -function point$5(that, t0, t1) { - var x0 = that._x0, - y0 = that._y0, - x1 = that._x1, - y1 = that._y1, - dx = (x1 - x0) / 3; - that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); -} - -function MonotoneX(context) { - this._context = context; -} - -MonotoneX.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = - this._t0 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x1, this._y1); break; - case 3: point$5(this, this._t0, slope2(this, this._t0)); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - var t1 = NaN; - - x = +x, y = +y; - if (x === this._x1 && y === this._y1) return; // Ignore coincident points. - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); break; - default: point$5(this, this._t0, t1 = slope3(this, x, y)); break; - } - - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - this._t0 = t1; - } -}; - -function MonotoneY(context) { - this._context = new ReflectContext(context); -} - -(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { - MonotoneX.prototype.point.call(this, y, x); -}; - -function ReflectContext(context) { - this._context = context; -} - -ReflectContext.prototype = { - moveTo: function(x, y) { this._context.moveTo(y, x); }, - closePath: function() { this._context.closePath(); }, - lineTo: function(x, y) { this._context.lineTo(y, x); }, - bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } -}; - -function monotoneX(context) { - return new MonotoneX(context); -} - -function monotoneY(context) { - return new MonotoneY(context); -} - -function Natural(context) { - this._context = context; -} - -Natural.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x = []; - this._y = []; - }, - lineEnd: function() { - var x = this._x, - y = this._y, - n = x.length; - - if (n) { - this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); - if (n === 2) { - this._context.lineTo(x[1], y[1]); - } else { - var px = controlPoints(x), - py = controlPoints(y); - for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { - this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); - } - } - } - - if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); - this._line = 1 - this._line; - this._x = this._y = null; - }, - point: function(x, y) { - this._x.push(+x); - this._y.push(+y); - } -}; - -// See https://www.particleincell.com/2012/bezier-splines/ for derivation. -function controlPoints(x) { - var i, - n = x.length - 1, - m, - a = new Array(n), - b = new Array(n), - r = new Array(n); - a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; - for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; - a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; - for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; - a[n - 1] = r[n - 1] / b[n - 1]; - for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; - b[n - 1] = (x[n] + a[n - 1]) / 2; - for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; - return [a, b]; -} - -var natural = function(context) { - return new Natural(context); -}; - -function Step(context, t) { - this._context = context; - this._t = t; -} - -Step.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x = this._y = NaN; - this._point = 0; - }, - lineEnd: function() { - if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; // proceed - default: { - if (this._t <= 0) { - this._context.lineTo(this._x, y); - this._context.lineTo(x, y); - } else { - var x1 = this._x * (1 - this._t) + x * this._t; - this._context.lineTo(x1, this._y); - this._context.lineTo(x1, y); - } - break; - } - } - this._x = x, this._y = y; - } -}; - -var step = function(context) { - return new Step(context, 0.5); -}; - -function stepBefore(context) { - return new Step(context, 0); -} - -function stepAfter(context) { - return new Step(context, 1); -} - -var none$1 = function(series, order) { - if (!((n = series.length) > 1)) return; - for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { - s0 = s1, s1 = series[order[i]]; - for (j = 0; j < m; ++j) { - s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; - } - } -}; - -var none$2 = function(series) { - var n = series.length, o = new Array(n); - while (--n >= 0) o[n] = n; - return o; -}; - -function stackValue(d, key) { - return d[key]; -} - -var stack = function() { - var keys = constant$10([]), - order = none$2, - offset = none$1, - value = stackValue; - - function stack(data) { - var kz = keys.apply(this, arguments), - i, - m = data.length, - n = kz.length, - sz = new Array(n), - oz; - - for (i = 0; i < n; ++i) { - for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { - si[j] = sij = [0, +value(data[j], ki, j, data)]; - sij.data = data[j]; - } - si.key = ki; - } - - for (i = 0, oz = order(sz); i < n; ++i) { - sz[oz[i]].index = i; - } - - offset(sz, oz); - return sz; - } - - stack.keys = function(_) { - return arguments.length ? (keys = typeof _ === "function" ? _ : constant$10(slice$6.call(_)), stack) : keys; - }; - - stack.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant$10(+_), stack) : value; - }; - - stack.order = function(_) { - return arguments.length ? (order = _ == null ? none$2 : typeof _ === "function" ? _ : constant$10(slice$6.call(_)), stack) : order; - }; - - stack.offset = function(_) { - return arguments.length ? (offset = _ == null ? none$1 : _, stack) : offset; - }; - - return stack; -}; - -var expand = function(series, order) { - if (!((n = series.length) > 0)) return; - for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { - for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; - if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; - } - none$1(series, order); -}; - -var diverging = function(series, order) { - if (!((n = series.length) > 1)) return; - for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) { - for (yp = yn = 0, i = 0; i < n; ++i) { - if ((dy = (d = series[order[i]][j])[1] - d[0]) >= 0) { - d[0] = yp, d[1] = yp += dy; - } else if (dy < 0) { - d[1] = yn, d[0] = yn += dy; - } else { - d[0] = yp; - } - } - } -}; - -var silhouette = function(series, order) { - if (!((n = series.length) > 0)) return; - for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { - for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; - s0[j][1] += s0[j][0] = -y / 2; - } - none$1(series, order); -}; - -var wiggle = function(series, order) { - if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; - for (var y = 0, j = 1, s0, m, n; j < m; ++j) { - for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { - var si = series[order[i]], - sij0 = si[j][1] || 0, - sij1 = si[j - 1][1] || 0, - s3 = (sij0 - sij1) / 2; - for (var k = 0; k < i; ++k) { - var sk = series[order[k]], - skj0 = sk[j][1] || 0, - skj1 = sk[j - 1][1] || 0; - s3 += skj0 - skj1; - } - s1 += sij0, s2 += s3 * sij0; - } - s0[j - 1][1] += s0[j - 1][0] = y; - if (s1) y -= s2 / s1; - } - s0[j - 1][1] += s0[j - 1][0] = y; - none$1(series, order); -}; - -var ascending$2 = function(series) { - var sums = series.map(sum$2); - return none$2(series).sort(function(a, b) { return sums[a] - sums[b]; }); -}; - -function sum$2(series) { - var s = 0, i = -1, n = series.length, v; - while (++i < n) if (v = +series[i][1]) s += v; - return s; -} - -var descending$2 = function(series) { - return ascending$2(series).reverse(); -}; - -var insideOut = function(series) { - var n = series.length, - i, - j, - sums = series.map(sum$2), - order = none$2(series).sort(function(a, b) { return sums[b] - sums[a]; }), - top = 0, - bottom = 0, - tops = [], - bottoms = []; - - for (i = 0; i < n; ++i) { - j = order[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); - } - } - - return bottoms.reverse().concat(tops); -}; - -var reverse = function(series) { - return none$2(series).reverse(); -}; - -var constant$11 = function(x) { - return function() { - return x; - }; -}; - -function x$4(d) { - return d[0]; -} - -function y$4(d) { - return d[1]; -} - -function RedBlackTree() { - this._ = null; // root node -} - -function RedBlackNode(node) { - node.U = // parent node - node.C = // color - true for red, false for black - node.L = // left node - node.R = // right node - node.P = // previous node - node.N = null; // next node -} - -RedBlackTree.prototype = { - constructor: RedBlackTree, - - insert: function(after, node) { - var parent, grandpa, uncle; - - if (after) { - node.P = after; - node.N = after.N; - if (after.N) after.N.P = node; - after.N = node; - if (after.R) { - after = after.R; - while (after.L) after = after.L; - after.L = node; - } else { - after.R = node; - } - parent = after; - } else if (this._) { - after = RedBlackFirst(this._); - node.P = null; - node.N = after; - after.P = after.L = node; - parent = after; - } else { - node.P = node.N = null; - this._ = node; - parent = null; - } - node.L = node.R = null; - node.U = parent; - node.C = true; - - after = node; - while (parent && parent.C) { - grandpa = parent.U; - if (parent === grandpa.L) { - uncle = grandpa.R; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.R) { - RedBlackRotateLeft(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - RedBlackRotateRight(this, grandpa); - } - } else { - uncle = grandpa.L; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.L) { - RedBlackRotateRight(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - RedBlackRotateLeft(this, grandpa); - } - } - parent = after.U; - } - this._.C = false; - }, - - remove: function(node) { - if (node.N) node.N.P = node.P; - if (node.P) node.P.N = node.N; - node.N = node.P = null; - - var parent = node.U, - sibling, - left = node.L, - right = node.R, - next, - red; - - if (!left) next = right; - else if (!right) next = left; - else next = RedBlackFirst(right); - - if (parent) { - if (parent.L === node) parent.L = next; - else parent.R = next; - } else { - this._ = next; - } - - if (left && right) { - red = next.C; - next.C = node.C; - next.L = left; - left.U = next; - if (next !== right) { - parent = next.U; - next.U = node.U; - node = next.R; - parent.L = node; - next.R = right; - right.U = next; - } else { - next.U = parent; - parent = next; - node = next.R; - } - } else { - red = node.C; - node = next; - } - - if (node) node.U = parent; - if (red) return; - if (node && node.C) { node.C = false; return; } - - do { - if (node === this._) break; - if (node === parent.L) { - sibling = parent.R; - if (sibling.C) { - sibling.C = false; - parent.C = true; - RedBlackRotateLeft(this, parent); - sibling = parent.R; - } - if ((sibling.L && sibling.L.C) - || (sibling.R && sibling.R.C)) { - if (!sibling.R || !sibling.R.C) { - sibling.L.C = false; - sibling.C = true; - RedBlackRotateRight(this, sibling); - sibling = parent.R; - } - sibling.C = parent.C; - parent.C = sibling.R.C = false; - RedBlackRotateLeft(this, parent); - node = this._; - break; - } - } else { - sibling = parent.L; - if (sibling.C) { - sibling.C = false; - parent.C = true; - RedBlackRotateRight(this, parent); - sibling = parent.L; - } - if ((sibling.L && sibling.L.C) - || (sibling.R && sibling.R.C)) { - if (!sibling.L || !sibling.L.C) { - sibling.R.C = false; - sibling.C = true; - RedBlackRotateLeft(this, sibling); - sibling = parent.L; - } - sibling.C = parent.C; - parent.C = sibling.L.C = false; - RedBlackRotateRight(this, parent); - node = this._; - break; - } - } - sibling.C = true; - node = parent; - parent = parent.U; - } while (!node.C); - - if (node) node.C = false; - } -}; - -function RedBlackRotateLeft(tree, node) { - var p = node, - q = node.R, - parent = p.U; - - if (parent) { - if (parent.L === p) parent.L = q; - else parent.R = q; - } else { - tree._ = q; - } - - q.U = parent; - p.U = q; - p.R = q.L; - if (p.R) p.R.U = p; - q.L = p; -} - -function RedBlackRotateRight(tree, node) { - var p = node, - q = node.L, - parent = p.U; - - if (parent) { - if (parent.L === p) parent.L = q; - else parent.R = q; - } else { - tree._ = q; - } - - q.U = parent; - p.U = q; - p.L = q.R; - if (p.L) p.L.U = p; - q.R = p; -} - -function RedBlackFirst(node) { - while (node.L) node = node.L; - return node; -} - -function createEdge(left, right, v0, v1) { - var edge = [null, null], - index = edges.push(edge) - 1; - edge.left = left; - edge.right = right; - if (v0) setEdgeEnd(edge, left, right, v0); - if (v1) setEdgeEnd(edge, right, left, v1); - cells[left.index].halfedges.push(index); - cells[right.index].halfedges.push(index); - return edge; -} - -function createBorderEdge(left, v0, v1) { - var edge = [v0, v1]; - edge.left = left; - return edge; -} - -function setEdgeEnd(edge, left, right, vertex) { - if (!edge[0] && !edge[1]) { - edge[0] = vertex; - edge.left = left; - edge.right = right; - } else if (edge.left === right) { - edge[1] = vertex; - } else { - edge[0] = vertex; - } -} - -// Liang–Barsky line clipping. -function clipEdge(edge, x0, y0, x1, y1) { - var a = edge[0], - b = edge[1], - ax = a[0], - ay = a[1], - bx = b[0], - by = b[1], - t0 = 0, - t1 = 1, - dx = bx - ax, - dy = by - ay, - r; - - r = x0 - ax; - if (!dx && r > 0) return; - r /= dx; - if (dx < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dx > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - - r = x1 - ax; - if (!dx && r < 0) return; - r /= dx; - if (dx < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dx > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - - r = y0 - ay; - if (!dy && r > 0) return; - r /= dy; - if (dy < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dy > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - - r = y1 - ay; - if (!dy && r < 0) return; - r /= dy; - if (dy < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dy > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - - if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check? - - if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy]; - if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy]; - return true; -} - -function connectEdge(edge, x0, y0, x1, y1) { - var v1 = edge[1]; - if (v1) return true; - - var v0 = edge[0], - left = edge.left, - right = edge.right, - lx = left[0], - ly = left[1], - rx = right[0], - ry = right[1], - fx = (lx + rx) / 2, - fy = (ly + ry) / 2, - fm, - fb; - - if (ry === ly) { - if (fx < x0 || fx >= x1) return; - if (lx > rx) { - if (!v0) v0 = [fx, y0]; - else if (v0[1] >= y1) return; - v1 = [fx, y1]; - } else { - if (!v0) v0 = [fx, y1]; - else if (v0[1] < y0) return; - v1 = [fx, y0]; - } - } else { - fm = (lx - rx) / (ry - ly); - fb = fy - fm * fx; - if (fm < -1 || fm > 1) { - if (lx > rx) { - if (!v0) v0 = [(y0 - fb) / fm, y0]; - else if (v0[1] >= y1) return; - v1 = [(y1 - fb) / fm, y1]; - } else { - if (!v0) v0 = [(y1 - fb) / fm, y1]; - else if (v0[1] < y0) return; - v1 = [(y0 - fb) / fm, y0]; - } - } else { - if (ly < ry) { - if (!v0) v0 = [x0, fm * x0 + fb]; - else if (v0[0] >= x1) return; - v1 = [x1, fm * x1 + fb]; - } else { - if (!v0) v0 = [x1, fm * x1 + fb]; - else if (v0[0] < x0) return; - v1 = [x0, fm * x0 + fb]; - } - } - } - - edge[0] = v0; - edge[1] = v1; - return true; -} - -function clipEdges(x0, y0, x1, y1) { - var i = edges.length, - edge; - - while (i--) { - if (!connectEdge(edge = edges[i], x0, y0, x1, y1) - || !clipEdge(edge, x0, y0, x1, y1) - || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$4 - || Math.abs(edge[0][1] - edge[1][1]) > epsilon$4)) { - delete edges[i]; - } - } -} - -function createCell(site) { - return cells[site.index] = { - site: site, - halfedges: [] - }; -} - -function cellHalfedgeAngle(cell, edge) { - var site = cell.site, - va = edge.left, - vb = edge.right; - if (site === vb) vb = va, va = site; - if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]); - if (site === va) va = edge[1], vb = edge[0]; - else va = edge[0], vb = edge[1]; - return Math.atan2(va[0] - vb[0], vb[1] - va[1]); -} - -function cellHalfedgeStart(cell, edge) { - return edge[+(edge.left !== cell.site)]; -} - -function cellHalfedgeEnd(cell, edge) { - return edge[+(edge.left === cell.site)]; -} - -function sortCellHalfedges() { - for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) { - if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) { - var index = new Array(m), - array = new Array(m); - for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]); - index.sort(function(i, j) { return array[j] - array[i]; }); - for (j = 0; j < m; ++j) array[j] = halfedges[index[j]]; - for (j = 0; j < m; ++j) halfedges[j] = array[j]; - } - } -} - -function clipCells(x0, y0, x1, y1) { - var nCells = cells.length, - iCell, - cell, - site, - iHalfedge, - halfedges, - nHalfedges, - start, - startX, - startY, - end, - endX, - endY, - cover = true; - - for (iCell = 0; iCell < nCells; ++iCell) { - if (cell = cells[iCell]) { - site = cell.site; - halfedges = cell.halfedges; - iHalfedge = halfedges.length; - - // Remove any dangling clipped edges. - while (iHalfedge--) { - if (!edges[halfedges[iHalfedge]]) { - halfedges.splice(iHalfedge, 1); - } - } - - // Insert any border edges as necessary. - iHalfedge = 0, nHalfedges = halfedges.length; - while (iHalfedge < nHalfedges) { - end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1]; - start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1]; - if (Math.abs(endX - startX) > epsilon$4 || Math.abs(endY - startY) > epsilon$4) { - halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end, - Math.abs(endX - x0) < epsilon$4 && y1 - endY > epsilon$4 ? [x0, Math.abs(startX - x0) < epsilon$4 ? startY : y1] - : Math.abs(endY - y1) < epsilon$4 && x1 - endX > epsilon$4 ? [Math.abs(startY - y1) < epsilon$4 ? startX : x1, y1] - : Math.abs(endX - x1) < epsilon$4 && endY - y0 > epsilon$4 ? [x1, Math.abs(startX - x1) < epsilon$4 ? startY : y0] - : Math.abs(endY - y0) < epsilon$4 && endX - x0 > epsilon$4 ? [Math.abs(startY - y0) < epsilon$4 ? startX : x0, y0] - : null)) - 1); - ++nHalfedges; - } - } - - if (nHalfedges) cover = false; - } - } - - // If there weren’t any edges, have the closest site cover the extent. - // It doesn’t matter which corner of the extent we measure! - if (cover) { - var dx, dy, d2, dc = Infinity; - - for (iCell = 0, cover = null; iCell < nCells; ++iCell) { - if (cell = cells[iCell]) { - site = cell.site; - dx = site[0] - x0; - dy = site[1] - y0; - d2 = dx * dx + dy * dy; - if (d2 < dc) dc = d2, cover = cell; - } - } - - if (cover) { - var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0]; - cover.halfedges.push( - edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1, - edges.push(createBorderEdge(site, v01, v11)) - 1, - edges.push(createBorderEdge(site, v11, v10)) - 1, - edges.push(createBorderEdge(site, v10, v00)) - 1 - ); - } - } - - // Lastly delete any cells with no edges; these were entirely clipped. - for (iCell = 0; iCell < nCells; ++iCell) { - if (cell = cells[iCell]) { - if (!cell.halfedges.length) { - delete cells[iCell]; - } - } - } -} - -var circlePool = []; - -var firstCircle; - -function Circle() { - RedBlackNode(this); - this.x = - this.y = - this.arc = - this.site = - this.cy = null; -} - -function attachCircle(arc) { - var lArc = arc.P, - rArc = arc.N; - - if (!lArc || !rArc) return; - - var lSite = lArc.site, - cSite = arc.site, - rSite = rArc.site; - - if (lSite === rSite) return; - - var bx = cSite[0], - by = cSite[1], - ax = lSite[0] - bx, - ay = lSite[1] - by, - cx = rSite[0] - bx, - cy = rSite[1] - by; - - var d = 2 * (ax * cy - ay * cx); - if (d >= -epsilon2$2) return; - - var ha = ax * ax + ay * ay, - hc = cx * cx + cy * cy, - x = (cy * ha - ay * hc) / d, - y = (ax * hc - cx * ha) / d; - - var circle = circlePool.pop() || new Circle; - circle.arc = arc; - circle.site = cSite; - circle.x = x + bx; - circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom - - arc.circle = circle; - - var before = null, - node = circles._; - - while (node) { - if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) { - if (node.L) node = node.L; - else { before = node.P; break; } - } else { - if (node.R) node = node.R; - else { before = node; break; } - } - } - - circles.insert(before, circle); - if (!before) firstCircle = circle; -} - -function detachCircle(arc) { - var circle = arc.circle; - if (circle) { - if (!circle.P) firstCircle = circle.N; - circles.remove(circle); - circlePool.push(circle); - RedBlackNode(circle); - arc.circle = null; - } -} - -var beachPool = []; - -function Beach() { - RedBlackNode(this); - this.edge = - this.site = - this.circle = null; -} - -function createBeach(site) { - var beach = beachPool.pop() || new Beach; - beach.site = site; - return beach; -} - -function detachBeach(beach) { - detachCircle(beach); - beaches.remove(beach); - beachPool.push(beach); - RedBlackNode(beach); -} - -function removeBeach(beach) { - var circle = beach.circle, - x = circle.x, - y = circle.cy, - vertex = [x, y], - previous = beach.P, - next = beach.N, - disappearing = [beach]; - - detachBeach(beach); - - var lArc = previous; - while (lArc.circle - && Math.abs(x - lArc.circle.x) < epsilon$4 - && Math.abs(y - lArc.circle.cy) < epsilon$4) { - previous = lArc.P; - disappearing.unshift(lArc); - detachBeach(lArc); - lArc = previous; - } - - disappearing.unshift(lArc); - detachCircle(lArc); - - var rArc = next; - while (rArc.circle - && Math.abs(x - rArc.circle.x) < epsilon$4 - && Math.abs(y - rArc.circle.cy) < epsilon$4) { - next = rArc.N; - disappearing.push(rArc); - detachBeach(rArc); - rArc = next; - } - - disappearing.push(rArc); - detachCircle(rArc); - - var nArcs = disappearing.length, - iArc; - for (iArc = 1; iArc < nArcs; ++iArc) { - rArc = disappearing[iArc]; - lArc = disappearing[iArc - 1]; - setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); - } - - lArc = disappearing[0]; - rArc = disappearing[nArcs - 1]; - rArc.edge = createEdge(lArc.site, rArc.site, null, vertex); - - attachCircle(lArc); - attachCircle(rArc); -} - -function addBeach(site) { - var x = site[0], - directrix = site[1], - lArc, - rArc, - dxl, - dxr, - node = beaches._; - - while (node) { - dxl = leftBreakPoint(node, directrix) - x; - if (dxl > epsilon$4) node = node.L; else { - dxr = x - rightBreakPoint(node, directrix); - if (dxr > epsilon$4) { - if (!node.R) { - lArc = node; - break; - } - node = node.R; - } else { - if (dxl > -epsilon$4) { - lArc = node.P; - rArc = node; - } else if (dxr > -epsilon$4) { - lArc = node; - rArc = node.N; - } else { - lArc = rArc = node; - } - break; - } - } - } - - createCell(site); - var newArc = createBeach(site); - beaches.insert(lArc, newArc); - - if (!lArc && !rArc) return; - - if (lArc === rArc) { - detachCircle(lArc); - rArc = createBeach(lArc.site); - beaches.insert(newArc, rArc); - newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site); - attachCircle(lArc); - attachCircle(rArc); - return; - } - - if (!rArc) { // && lArc - newArc.edge = createEdge(lArc.site, newArc.site); - return; - } - - // else lArc !== rArc - detachCircle(lArc); - detachCircle(rArc); - - var lSite = lArc.site, - ax = lSite[0], - ay = lSite[1], - bx = site[0] - ax, - by = site[1] - ay, - rSite = rArc.site, - cx = rSite[0] - ax, - cy = rSite[1] - ay, - d = 2 * (bx * cy - by * cx), - hb = bx * bx + by * by, - hc = cx * cx + cy * cy, - vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay]; - - setEdgeEnd(rArc.edge, lSite, rSite, vertex); - newArc.edge = createEdge(lSite, site, null, vertex); - rArc.edge = createEdge(site, rSite, null, vertex); - attachCircle(lArc); - attachCircle(rArc); -} - -function leftBreakPoint(arc, directrix) { - var site = arc.site, - rfocx = site[0], - rfocy = site[1], - pby2 = rfocy - directrix; - - if (!pby2) return rfocx; - - var lArc = arc.P; - if (!lArc) return -Infinity; - - site = lArc.site; - var lfocx = site[0], - lfocy = site[1], - plby2 = lfocy - directrix; - - if (!plby2) return lfocx; - - var hl = lfocx - rfocx, - aby2 = 1 / pby2 - 1 / plby2, - b = hl / plby2; - - if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; - - return (rfocx + lfocx) / 2; -} - -function rightBreakPoint(arc, directrix) { - var rArc = arc.N; - if (rArc) return leftBreakPoint(rArc, directrix); - var site = arc.site; - return site[1] === directrix ? site[0] : Infinity; -} - -var epsilon$4 = 1e-6; -var epsilon2$2 = 1e-12; -var beaches; -var cells; -var circles; -var edges; - -function triangleArea(a, b, c) { - return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]); -} - -function lexicographic(a, b) { - return b[1] - a[1] - || b[0] - a[0]; -} - -function Diagram(sites, extent) { - var site = sites.sort(lexicographic).pop(), - x, - y, - circle; - - edges = []; - cells = new Array(sites.length); - beaches = new RedBlackTree; - circles = new RedBlackTree; - - while (true) { - circle = firstCircle; - if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { - if (site[0] !== x || site[1] !== y) { - addBeach(site); - x = site[0], y = site[1]; - } - site = sites.pop(); - } else if (circle) { - removeBeach(circle.arc); - } else { - break; - } - } - - sortCellHalfedges(); - - if (extent) { - var x0 = +extent[0][0], - y0 = +extent[0][1], - x1 = +extent[1][0], - y1 = +extent[1][1]; - clipEdges(x0, y0, x1, y1); - clipCells(x0, y0, x1, y1); - } - - this.edges = edges; - this.cells = cells; - - beaches = - circles = - edges = - cells = null; -} - -Diagram.prototype = { - constructor: Diagram, - - polygons: function() { - var edges = this.edges; - - return this.cells.map(function(cell) { - var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); }); - polygon.data = cell.site.data; - return polygon; - }); - }, - - triangles: function() { - var triangles = [], - edges = this.edges; - - this.cells.forEach(function(cell, i) { - if (!(m = (halfedges = cell.halfedges).length)) return; - var site = cell.site, - halfedges, - j = -1, - m, - s0, - e1 = edges[halfedges[m - 1]], - s1 = e1.left === site ? e1.right : e1.left; - - while (++j < m) { - s0 = s1; - e1 = edges[halfedges[j]]; - s1 = e1.left === site ? e1.right : e1.left; - if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { - triangles.push([site.data, s0.data, s1.data]); - } - } - }); - - return triangles; - }, - - links: function() { - return this.edges.filter(function(edge) { - return edge.right; - }).map(function(edge) { - return { - source: edge.left.data, - target: edge.right.data - }; - }); - }, - - find: function(x, y, radius) { - var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell; - - // Use the previously-found cell, or start with an arbitrary one. - while (!(cell = that.cells[i1])) if (++i1 >= n) return null; - var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy; - - // Traverse the half-edges to find a closer cell, if any. - do { - cell = that.cells[i0 = i1], i1 = null; - cell.halfedges.forEach(function(e) { - var edge = that.edges[e], v = edge.left; - if ((v === cell.site || !v) && !(v = edge.right)) return; - var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy; - if (v2 < d2) d2 = v2, i1 = v.index; - }); - } while (i1 !== null); - - that._found = i0; - - return radius == null || d2 <= radius * radius ? cell.site : null; - } -}; - -var voronoi = function() { - var x$$1 = x$4, - y$$1 = y$4, - extent = null; - - function voronoi(data) { - return new Diagram(data.map(function(d, i) { - var s = [Math.round(x$$1(d, i, data) / epsilon$4) * epsilon$4, Math.round(y$$1(d, i, data) / epsilon$4) * epsilon$4]; - s.index = i; - s.data = d; - return s; - }), extent); - } - - voronoi.polygons = function(data) { - return voronoi(data).polygons(); - }; - - voronoi.links = function(data) { - return voronoi(data).links(); - }; - - voronoi.triangles = function(data) { - return voronoi(data).triangles(); - }; - - voronoi.x = function(_) { - return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : x$$1; - }; - - voronoi.y = function(_) { - return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$11(+_), voronoi) : y$$1; - }; - - voronoi.extent = function(_) { - return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]]; - }; - - voronoi.size = function(_) { - return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]]; - }; - - return voronoi; -}; - -var constant$12 = function(x) { - return function() { - return x; - }; -}; - -function ZoomEvent(target, type, transform) { - this.target = target; - this.type = type; - this.transform = transform; -} - -function Transform(k, x, y) { - this.k = k; - this.x = x; - this.y = y; -} - -Transform.prototype = { - constructor: Transform, - scale: function(k) { - return k === 1 ? this : new Transform(this.k * k, this.x, this.y); - }, - translate: function(x, y) { - return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); - }, - apply: function(point) { - return [point[0] * this.k + this.x, point[1] * this.k + this.y]; - }, - applyX: function(x) { - return x * this.k + this.x; - }, - applyY: function(y) { - return y * this.k + this.y; - }, - invert: function(location) { - return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; - }, - invertX: function(x) { - return (x - this.x) / this.k; - }, - invertY: function(y) { - return (y - this.y) / this.k; - }, - rescaleX: function(x) { - return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); - }, - rescaleY: function(y) { - return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); - }, - toString: function() { - return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; - } -}; - -var identity$8 = new Transform(1, 0, 0); - -transform$1.prototype = Transform.prototype; - -function transform$1(node) { - return node.__zoom || identity$8; -} - -function nopropagation$2() { - exports.event.stopImmediatePropagation(); -} - -var noevent$2 = function() { - exports.event.preventDefault(); - exports.event.stopImmediatePropagation(); -}; - -// Ignore right-click, since that should open the context menu. -function defaultFilter$2() { - return !exports.event.button; -} - -function defaultExtent$1() { - var e = this, w, h; - if (e instanceof SVGElement) { - e = e.ownerSVGElement || e; - w = e.width.baseVal.value; - h = e.height.baseVal.value; - } else { - w = e.clientWidth; - h = e.clientHeight; - } - return [[0, 0], [w, h]]; -} - -function defaultTransform() { - return this.__zoom || identity$8; -} - -function defaultWheelDelta() { - return -exports.event.deltaY * (exports.event.deltaMode ? 120 : 1) / 500; -} - -function defaultTouchable$1() { - return "ontouchstart" in this; -} - -var zoom = function() { - var filter = defaultFilter$2, - extent = defaultExtent$1, - wheelDelta = defaultWheelDelta, - touchable = defaultTouchable$1, - k0 = 0, - k1 = Infinity, - x0 = -k1, - x1 = k1, - y0 = x0, - y1 = x1, - duration = 250, - interpolate = interpolateZoom, - gestures = [], - listeners = dispatch("start", "zoom", "end"), - touchstarting, - touchending, - touchDelay = 500, - wheelDelay = 150, - clickDistance2 = 0; - - function zoom(selection) { - selection - .property("__zoom", defaultTransform) - .on("wheel.zoom", wheeled) - .on("mousedown.zoom", mousedowned) - .on("dblclick.zoom", dblclicked) - .filter(touchable) - .on("touchstart.zoom", touchstarted) - .on("touchmove.zoom", touchmoved) - .on("touchend.zoom touchcancel.zoom", touchended) - .style("touch-action", "none") - .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); - } - - zoom.transform = function(collection, transform$$1) { - var selection = collection.selection ? collection.selection() : collection; - selection.property("__zoom", defaultTransform); - if (collection !== selection) { - schedule(collection, transform$$1); - } else { - selection.interrupt().each(function() { - gesture(this, arguments) - .start() - .zoom(null, typeof transform$$1 === "function" ? transform$$1.apply(this, arguments) : transform$$1) - .end(); - }); - } - }; - - zoom.scaleBy = function(selection, k) { - zoom.scaleTo(selection, function() { - var k0 = this.__zoom.k, - k1 = typeof k === "function" ? k.apply(this, arguments) : k; - return k0 * k1; - }); - }; - - zoom.scaleTo = function(selection, k) { - zoom.transform(selection, function() { - var e = extent.apply(this, arguments), - t0 = this.__zoom, - p0 = centroid(e), - p1 = t0.invert(p0), - k1 = typeof k === "function" ? k.apply(this, arguments) : k; - return constrain(translate(scale(t0, k1), p0, p1), e); - }); - }; - - zoom.translateBy = function(selection, x, y) { - zoom.transform(selection, function() { - return constrain(this.__zoom.translate( - typeof x === "function" ? x.apply(this, arguments) : x, - typeof y === "function" ? y.apply(this, arguments) : y - ), extent.apply(this, arguments)); - }); - }; - - zoom.translateTo = function(selection, x, y) { - zoom.transform(selection, function() { - var e = extent.apply(this, arguments), - t = this.__zoom, - p = centroid(e); - return constrain(identity$8.translate(p[0], p[1]).scale(t.k).translate( - typeof x === "function" ? -x.apply(this, arguments) : -x, - typeof y === "function" ? -y.apply(this, arguments) : -y - ), e); - }); - }; - - function scale(transform$$1, k) { - k = Math.max(k0, Math.min(k1, k)); - return k === transform$$1.k ? transform$$1 : new Transform(k, transform$$1.x, transform$$1.y); - } - - function translate(transform$$1, p0, p1) { - var x = p0[0] - p1[0] * transform$$1.k, y = p0[1] - p1[1] * transform$$1.k; - return x === transform$$1.x && y === transform$$1.y ? transform$$1 : new Transform(transform$$1.k, x, y); - } - - function constrain(transform$$1, extent) { - var dx0 = transform$$1.invertX(extent[0][0]) - x0, - dx1 = transform$$1.invertX(extent[1][0]) - x1, - dy0 = transform$$1.invertY(extent[0][1]) - y0, - dy1 = transform$$1.invertY(extent[1][1]) - y1; - return transform$$1.translate( - dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), - dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1) - ); - } - - function centroid(extent) { - return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; - } - - function schedule(transition, transform$$1, center) { - transition - .on("start.zoom", function() { gesture(this, arguments).start(); }) - .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); }) - .tween("zoom", function() { - var that = this, - args = arguments, - g = gesture(that, args), - e = extent.apply(that, args), - p = center || centroid(e), - w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), - a = that.__zoom, - b = typeof transform$$1 === "function" ? transform$$1.apply(that, args) : transform$$1, - i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); - return function(t) { - if (t === 1) t = b; // Avoid rounding error on end. - else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } - g.zoom(null, t); - }; - }); - } - - function gesture(that, args) { - for (var i = 0, n = gestures.length, g; i < n; ++i) { - if ((g = gestures[i]).that === that) { - return g; - } - } - return new Gesture(that, args); - } - - function Gesture(that, args) { - this.that = that; - this.args = args; - this.index = -1; - this.active = 0; - this.extent = extent.apply(that, args); - } - - Gesture.prototype = { - start: function() { - if (++this.active === 1) { - this.index = gestures.push(this) - 1; - this.emit("start"); - } - return this; - }, - zoom: function(key, transform$$1) { - if (this.mouse && key !== "mouse") this.mouse[1] = transform$$1.invert(this.mouse[0]); - if (this.touch0 && key !== "touch") this.touch0[1] = transform$$1.invert(this.touch0[0]); - if (this.touch1 && key !== "touch") this.touch1[1] = transform$$1.invert(this.touch1[0]); - this.that.__zoom = transform$$1; - this.emit("zoom"); - return this; - }, - end: function() { - if (--this.active === 0) { - gestures.splice(this.index, 1); - this.index = -1; - this.emit("end"); - } - return this; - }, - emit: function(type) { - customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]); - } - }; - - function wheeled() { - if (!filter.apply(this, arguments)) return; - var g = gesture(this, arguments), - t = this.__zoom, - k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), - p = mouse(this); - - // If the mouse is in the same location as before, reuse it. - // If there were recent wheel events, reset the wheel idle timeout. - if (g.wheel) { - if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { - g.mouse[1] = t.invert(g.mouse[0] = p); - } - clearTimeout(g.wheel); - } - - // If this wheel event won’t trigger a transform change, ignore it. - else if (t.k === k) return; - - // Otherwise, capture the mouse point and location at the start. - else { - g.mouse = [p, t.invert(p)]; - interrupt(this); - g.start(); - } - - noevent$2(); - g.wheel = setTimeout(wheelidled, wheelDelay); - g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent)); - - function wheelidled() { - g.wheel = null; - g.end(); - } - } - - function mousedowned() { - if (touchending || !filter.apply(this, arguments)) return; - var g = gesture(this, arguments), - v = select(exports.event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), - p = mouse(this), - x0 = exports.event.clientX, - y0 = exports.event.clientY; - - dragDisable(exports.event.view); - nopropagation$2(); - g.mouse = [p, this.__zoom.invert(p)]; - interrupt(this); - g.start(); - - function mousemoved() { - noevent$2(); - if (!g.moved) { - var dx = exports.event.clientX - x0, dy = exports.event.clientY - y0; - g.moved = dx * dx + dy * dy > clickDistance2; - } - g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent)); - } - - function mouseupped() { - v.on("mousemove.zoom mouseup.zoom", null); - yesdrag(exports.event.view, g.moved); - noevent$2(); - g.end(); - } - } - - function dblclicked() { - if (!filter.apply(this, arguments)) return; - var t0 = this.__zoom, - p0 = mouse(this), - p1 = t0.invert(p0), - k1 = t0.k * (exports.event.shiftKey ? 0.5 : 2), - t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments)); - - noevent$2(); - if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0); - else select(this).call(zoom.transform, t1); - } - - function touchstarted() { - if (!filter.apply(this, arguments)) return; - var g = gesture(this, arguments), - touches = exports.event.changedTouches, - started, - n = touches.length, i, t, p; - - nopropagation$2(); - for (i = 0; i < n; ++i) { - t = touches[i], p = touch(this, touches, t.identifier); - p = [p, this.__zoom.invert(p), t.identifier]; - if (!g.touch0) g.touch0 = p, started = true; - else if (!g.touch1) g.touch1 = p; - } - - // If this is a dbltap, reroute to the (optional) dblclick.zoom handler. - if (touchstarting) { - touchstarting = clearTimeout(touchstarting); - if (!g.touch1) { - g.end(); - p = select(this).on("dblclick.zoom"); - if (p) p.apply(this, arguments); - return; - } - } - - if (started) { - touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); - interrupt(this); - g.start(); - } - } - - function touchmoved() { - var g = gesture(this, arguments), - touches = exports.event.changedTouches, - n = touches.length, i, t, p, l; - - noevent$2(); - if (touchstarting) touchstarting = clearTimeout(touchstarting); - for (i = 0; i < n; ++i) { - t = touches[i], p = touch(this, touches, t.identifier); - if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; - else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; - } - t = g.that.__zoom; - if (g.touch1) { - var p0 = g.touch0[0], l0 = g.touch0[1], - p1 = g.touch1[0], l1 = g.touch1[1], - dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, - dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; - t = scale(t, Math.sqrt(dp / dl)); - p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; - l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; - } - else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; - else return; - g.zoom("touch", constrain(translate(t, p, l), g.extent)); - } - - function touchended() { - var g = gesture(this, arguments), - touches = exports.event.changedTouches, - n = touches.length, i, t; - - nopropagation$2(); - if (touchending) clearTimeout(touchending); - touchending = setTimeout(function() { touchending = null; }, touchDelay); - for (i = 0; i < n; ++i) { - t = touches[i]; - if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; - else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; - } - if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; - if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]); - else g.end(); - } - - zoom.wheelDelta = function(_) { - return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant$12(+_), zoom) : wheelDelta; - }; - - zoom.filter = function(_) { - return arguments.length ? (filter = typeof _ === "function" ? _ : constant$12(!!_), zoom) : filter; - }; - - zoom.touchable = function(_) { - return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$12(!!_), zoom) : touchable; - }; - - zoom.extent = function(_) { - return arguments.length ? (extent = typeof _ === "function" ? _ : constant$12([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; - }; - - zoom.scaleExtent = function(_) { - return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1]; - }; - - zoom.translateExtent = function(_) { - return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]]; - }; - - zoom.duration = function(_) { - return arguments.length ? (duration = +_, zoom) : duration; - }; - - zoom.interpolate = function(_) { - return arguments.length ? (interpolate = _, zoom) : interpolate; - }; - - zoom.on = function() { - var value = listeners.on.apply(listeners, arguments); - return value === listeners ? zoom : value; - }; - - zoom.clickDistance = function(_) { - return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2); - }; - - return zoom; -}; - -exports.version = version; -exports.bisect = bisectRight; -exports.bisectRight = bisectRight; -exports.bisectLeft = bisectLeft; -exports.ascending = ascending; -exports.bisector = bisector; -exports.cross = cross; -exports.descending = descending; -exports.deviation = deviation; -exports.extent = extent; -exports.histogram = histogram; -exports.thresholdFreedmanDiaconis = freedmanDiaconis; -exports.thresholdScott = scott; -exports.thresholdSturges = sturges; -exports.max = max; -exports.mean = mean; -exports.median = median; -exports.merge = merge; -exports.min = min; -exports.pairs = pairs; -exports.permute = permute; -exports.quantile = threshold; -exports.range = sequence; -exports.scan = scan; -exports.shuffle = shuffle; -exports.sum = sum; -exports.ticks = ticks; -exports.tickIncrement = tickIncrement; -exports.tickStep = tickStep; -exports.transpose = transpose; -exports.variance = variance; -exports.zip = zip; -exports.axisTop = axisTop; -exports.axisRight = axisRight; -exports.axisBottom = axisBottom; -exports.axisLeft = axisLeft; -exports.brush = brush; -exports.brushX = brushX; -exports.brushY = brushY; -exports.brushSelection = brushSelection; -exports.chord = chord; -exports.ribbon = ribbon; -exports.nest = nest; -exports.set = set$2; -exports.map = map$1; -exports.keys = keys; -exports.values = values; -exports.entries = entries; -exports.color = color; -exports.rgb = rgb; -exports.hsl = hsl; -exports.lab = lab; -exports.hcl = hcl; -exports.cubehelix = cubehelix; -exports.dispatch = dispatch; -exports.drag = drag; -exports.dragDisable = dragDisable; -exports.dragEnable = yesdrag; -exports.dsvFormat = dsv; -exports.csvParse = csvParse; -exports.csvParseRows = csvParseRows; -exports.csvFormat = csvFormat; -exports.csvFormatRows = csvFormatRows; -exports.tsvParse = tsvParse; -exports.tsvParseRows = tsvParseRows; -exports.tsvFormat = tsvFormat; -exports.tsvFormatRows = tsvFormatRows; -exports.easeLinear = linear$1; -exports.easeQuad = quadInOut; -exports.easeQuadIn = quadIn; -exports.easeQuadOut = quadOut; -exports.easeQuadInOut = quadInOut; -exports.easeCubic = cubicInOut; -exports.easeCubicIn = cubicIn; -exports.easeCubicOut = cubicOut; -exports.easeCubicInOut = cubicInOut; -exports.easePoly = polyInOut; -exports.easePolyIn = polyIn; -exports.easePolyOut = polyOut; -exports.easePolyInOut = polyInOut; -exports.easeSin = sinInOut; -exports.easeSinIn = sinIn; -exports.easeSinOut = sinOut; -exports.easeSinInOut = sinInOut; -exports.easeExp = expInOut; -exports.easeExpIn = expIn; -exports.easeExpOut = expOut; -exports.easeExpInOut = expInOut; -exports.easeCircle = circleInOut; -exports.easeCircleIn = circleIn; -exports.easeCircleOut = circleOut; -exports.easeCircleInOut = circleInOut; -exports.easeBounce = bounceOut; -exports.easeBounceIn = bounceIn; -exports.easeBounceOut = bounceOut; -exports.easeBounceInOut = bounceInOut; -exports.easeBack = backInOut; -exports.easeBackIn = backIn; -exports.easeBackOut = backOut; -exports.easeBackInOut = backInOut; -exports.easeElastic = elasticOut; -exports.easeElasticIn = elasticIn; -exports.easeElasticOut = elasticOut; -exports.easeElasticInOut = elasticInOut; -exports.forceCenter = center$1; -exports.forceCollide = collide; -exports.forceLink = link; -exports.forceManyBody = manyBody; -exports.forceRadial = radial; -exports.forceSimulation = simulation; -exports.forceX = x$2; -exports.forceY = y$2; -exports.formatDefaultLocale = defaultLocale; -exports.formatLocale = formatLocale; -exports.formatSpecifier = formatSpecifier; -exports.precisionFixed = precisionFixed; -exports.precisionPrefix = precisionPrefix; -exports.precisionRound = precisionRound; -exports.geoArea = area; -exports.geoBounds = bounds; -exports.geoCentroid = centroid; -exports.geoCircle = circle; -exports.geoClipAntimeridian = clipAntimeridian; -exports.geoClipCircle = clipCircle; -exports.geoClipExtent = extent$1; -exports.geoClipRectangle = clipRectangle; -exports.geoContains = contains; -exports.geoDistance = distance; -exports.geoGraticule = graticule; -exports.geoGraticule10 = graticule10; -exports.geoInterpolate = interpolate$1; -exports.geoLength = length$1; -exports.geoPath = index$1; -exports.geoAlbers = albers; -exports.geoAlbersUsa = albersUsa; -exports.geoAzimuthalEqualArea = azimuthalEqualArea; -exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw; -exports.geoAzimuthalEquidistant = azimuthalEquidistant; -exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw; -exports.geoConicConformal = conicConformal; -exports.geoConicConformalRaw = conicConformalRaw; -exports.geoConicEqualArea = conicEqualArea; -exports.geoConicEqualAreaRaw = conicEqualAreaRaw; -exports.geoConicEquidistant = conicEquidistant; -exports.geoConicEquidistantRaw = conicEquidistantRaw; -exports.geoEquirectangular = equirectangular; -exports.geoEquirectangularRaw = equirectangularRaw; -exports.geoGnomonic = gnomonic; -exports.geoGnomonicRaw = gnomonicRaw; -exports.geoIdentity = identity$5; -exports.geoProjection = projection; -exports.geoProjectionMutator = projectionMutator; -exports.geoMercator = mercator; -exports.geoMercatorRaw = mercatorRaw; -exports.geoNaturalEarth1 = naturalEarth1; -exports.geoNaturalEarth1Raw = naturalEarth1Raw; -exports.geoOrthographic = orthographic; -exports.geoOrthographicRaw = orthographicRaw; -exports.geoStereographic = stereographic; -exports.geoStereographicRaw = stereographicRaw; -exports.geoTransverseMercator = transverseMercator; -exports.geoTransverseMercatorRaw = transverseMercatorRaw; -exports.geoRotation = rotation; -exports.geoStream = geoStream; -exports.geoTransform = transform; -exports.cluster = cluster; -exports.hierarchy = hierarchy; -exports.pack = index$2; -exports.packSiblings = siblings; -exports.packEnclose = enclose; -exports.partition = partition; -exports.stratify = stratify; -exports.tree = tree; -exports.treemap = index$3; -exports.treemapBinary = binary; -exports.treemapDice = treemapDice; -exports.treemapSlice = treemapSlice; -exports.treemapSliceDice = sliceDice; -exports.treemapSquarify = squarify; -exports.treemapResquarify = resquarify; -exports.interpolate = interpolateValue; -exports.interpolateArray = array$1; -exports.interpolateBasis = basis$1; -exports.interpolateBasisClosed = basisClosed; -exports.interpolateDate = date; -exports.interpolateNumber = reinterpolate; -exports.interpolateObject = object; -exports.interpolateRound = interpolateRound; -exports.interpolateString = interpolateString; -exports.interpolateTransformCss = interpolateTransformCss; -exports.interpolateTransformSvg = interpolateTransformSvg; -exports.interpolateZoom = interpolateZoom; -exports.interpolateRgb = interpolateRgb; -exports.interpolateRgbBasis = rgbBasis; -exports.interpolateRgbBasisClosed = rgbBasisClosed; -exports.interpolateHsl = hsl$2; -exports.interpolateHslLong = hslLong; -exports.interpolateLab = lab$1; -exports.interpolateHcl = hcl$2; -exports.interpolateHclLong = hclLong; -exports.interpolateCubehelix = cubehelix$2; -exports.interpolateCubehelixLong = cubehelixLong; -exports.quantize = quantize; -exports.path = path; -exports.polygonArea = area$1; -exports.polygonCentroid = centroid$1; -exports.polygonHull = hull; -exports.polygonContains = contains$1; -exports.polygonLength = length$2; -exports.quadtree = quadtree; -exports.queue = queue; -exports.randomUniform = uniform; -exports.randomNormal = normal; -exports.randomLogNormal = logNormal; -exports.randomBates = bates; -exports.randomIrwinHall = irwinHall; -exports.randomExponential = exponential$1; -exports.request = request; -exports.html = html; -exports.json = json; -exports.text = text; -exports.xml = xml; -exports.csv = csv$1; -exports.tsv = tsv$1; -exports.scaleBand = band; -exports.scalePoint = point$1; -exports.scaleIdentity = identity$6; -exports.scaleLinear = linear$2; -exports.scaleLog = log$1; -exports.scaleOrdinal = ordinal; -exports.scaleImplicit = implicit; -exports.scalePow = pow$1; -exports.scaleSqrt = sqrt$1; -exports.scaleQuantile = quantile$$1; -exports.scaleQuantize = quantize$1; -exports.scaleThreshold = threshold$1; -exports.scaleTime = time; -exports.scaleUtc = utcTime; -exports.schemeCategory10 = category10; -exports.schemeCategory20b = category20b; -exports.schemeCategory20c = category20c; -exports.schemeCategory20 = category20; -exports.interpolateCubehelixDefault = cubehelix$3; -exports.interpolateRainbow = rainbow$1; -exports.interpolateWarm = warm; -exports.interpolateCool = cool; -exports.interpolateViridis = viridis; -exports.interpolateMagma = magma; -exports.interpolateInferno = inferno; -exports.interpolatePlasma = plasma; -exports.scaleSequential = sequential; -exports.creator = creator; -exports.local = local$1; -exports.matcher = matcher$1; -exports.mouse = mouse; -exports.namespace = namespace; -exports.namespaces = namespaces; -exports.select = select; -exports.selectAll = selectAll; -exports.selection = selection; -exports.selector = selector; -exports.selectorAll = selectorAll; -exports.style = styleValue; -exports.touch = touch; -exports.touches = touches; -exports.window = defaultView; -exports.customEvent = customEvent; -exports.arc = arc; -exports.area = area$2; -exports.line = line; -exports.pie = pie; -exports.areaRadial = areaRadial; -exports.radialArea = areaRadial; -exports.lineRadial = lineRadial$1; -exports.radialLine = lineRadial$1; -exports.pointRadial = pointRadial; -exports.linkHorizontal = linkHorizontal; -exports.linkVertical = linkVertical; -exports.linkRadial = linkRadial; -exports.symbol = symbol; -exports.symbols = symbols; -exports.symbolCircle = circle$2; -exports.symbolCross = cross$2; -exports.symbolDiamond = diamond; -exports.symbolSquare = square; -exports.symbolStar = star; -exports.symbolTriangle = triangle; -exports.symbolWye = wye; -exports.curveBasisClosed = basisClosed$1; -exports.curveBasisOpen = basisOpen; -exports.curveBasis = basis$2; -exports.curveBundle = bundle; -exports.curveCardinalClosed = cardinalClosed; -exports.curveCardinalOpen = cardinalOpen; -exports.curveCardinal = cardinal; -exports.curveCatmullRomClosed = catmullRomClosed; -exports.curveCatmullRomOpen = catmullRomOpen; -exports.curveCatmullRom = catmullRom; -exports.curveLinearClosed = linearClosed; -exports.curveLinear = curveLinear; -exports.curveMonotoneX = monotoneX; -exports.curveMonotoneY = monotoneY; -exports.curveNatural = natural; -exports.curveStep = step; -exports.curveStepAfter = stepAfter; -exports.curveStepBefore = stepBefore; -exports.stack = stack; -exports.stackOffsetExpand = expand; -exports.stackOffsetDiverging = diverging; -exports.stackOffsetNone = none$1; -exports.stackOffsetSilhouette = silhouette; -exports.stackOffsetWiggle = wiggle; -exports.stackOrderAscending = ascending$2; -exports.stackOrderDescending = descending$2; -exports.stackOrderInsideOut = insideOut; -exports.stackOrderNone = none$2; -exports.stackOrderReverse = reverse; -exports.timeInterval = newInterval; -exports.timeMillisecond = millisecond; -exports.timeMilliseconds = milliseconds; -exports.utcMillisecond = millisecond; -exports.utcMilliseconds = milliseconds; -exports.timeSecond = second; -exports.timeSeconds = seconds; -exports.utcSecond = second; -exports.utcSeconds = seconds; -exports.timeMinute = minute; -exports.timeMinutes = minutes; -exports.timeHour = hour; -exports.timeHours = hours; -exports.timeDay = day; -exports.timeDays = days; -exports.timeWeek = sunday; -exports.timeWeeks = sundays; -exports.timeSunday = sunday; -exports.timeSundays = sundays; -exports.timeMonday = monday; -exports.timeMondays = mondays; -exports.timeTuesday = tuesday; -exports.timeTuesdays = tuesdays; -exports.timeWednesday = wednesday; -exports.timeWednesdays = wednesdays; -exports.timeThursday = thursday; -exports.timeThursdays = thursdays; -exports.timeFriday = friday; -exports.timeFridays = fridays; -exports.timeSaturday = saturday; -exports.timeSaturdays = saturdays; -exports.timeMonth = month; -exports.timeMonths = months; -exports.timeYear = year; -exports.timeYears = years; -exports.utcMinute = utcMinute; -exports.utcMinutes = utcMinutes; -exports.utcHour = utcHour; -exports.utcHours = utcHours; -exports.utcDay = utcDay; -exports.utcDays = utcDays; -exports.utcWeek = utcSunday; -exports.utcWeeks = utcSundays; -exports.utcSunday = utcSunday; -exports.utcSundays = utcSundays; -exports.utcMonday = utcMonday; -exports.utcMondays = utcMondays; -exports.utcTuesday = utcTuesday; -exports.utcTuesdays = utcTuesdays; -exports.utcWednesday = utcWednesday; -exports.utcWednesdays = utcWednesdays; -exports.utcThursday = utcThursday; -exports.utcThursdays = utcThursdays; -exports.utcFriday = utcFriday; -exports.utcFridays = utcFridays; -exports.utcSaturday = utcSaturday; -exports.utcSaturdays = utcSaturdays; -exports.utcMonth = utcMonth; -exports.utcMonths = utcMonths; -exports.utcYear = utcYear; -exports.utcYears = utcYears; -exports.timeFormatDefaultLocale = defaultLocale$1; -exports.timeFormatLocale = formatLocale$1; -exports.isoFormat = formatIso; -exports.isoParse = parseIso; -exports.now = now; -exports.timer = timer; -exports.timerFlush = timerFlush; -exports.timeout = timeout$1; -exports.interval = interval$1; -exports.transition = transition; -exports.active = active; -exports.interrupt = interrupt; -exports.voronoi = voronoi; -exports.zoom = zoom; -exports.zoomTransform = transform$1; -exports.zoomIdentity = identity$8; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); diff --git a/www/fancypants.html b/www/fancypants.html deleted file mode 100644 index b88a8c2..0000000 --- a/www/fancypants.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - MOTH Dashboard - - -
-

Monarch Of The Hill

-

Brought to you by dirtbags.net

-
-
- If you turn on JavaScript this will look a lot cooler. -
-
- 🌼 🌼 🌼 🌼 🌼 🌼 🌼 🌼 -
-
-
- - diff --git a/www/fonts/MicroFLF-Bold.ttf b/www/fonts/MicroFLF-Bold.ttf deleted file mode 100644 index 6702790..0000000 Binary files a/www/fonts/MicroFLF-Bold.ttf and /dev/null differ diff --git a/www/fonts/MicroFLF-BoldItalic.ttf b/www/fonts/MicroFLF-BoldItalic.ttf deleted file mode 100644 index 0929959..0000000 Binary files a/www/fonts/MicroFLF-BoldItalic.ttf and /dev/null differ diff --git a/www/fonts/MicroFLF-Italic.ttf b/www/fonts/MicroFLF-Italic.ttf deleted file mode 100644 index ca219b9..0000000 Binary files a/www/fonts/MicroFLF-Italic.ttf and /dev/null differ diff --git a/www/fonts/MicroFLF.css b/www/fonts/MicroFLF.css deleted file mode 100644 index 103f9b8..0000000 --- a/www/fonts/MicroFLF.css +++ /dev/null @@ -1,14 +0,0 @@ -@font-face { - font-family: 'MicroFLF'; - src: url('MicroFLF.ttf'); - font-weight: 500; - font-style: normal; - -} - -@font-face { - font-family: 'MicroFLF'; - src: url('MicroFLF-Bold.ttf'); - font-weight: 700; - font-style: normal; -} diff --git a/www/fonts/MicroFLF.ttf b/www/fonts/MicroFLF.ttf deleted file mode 100644 index c6e3f92..0000000 Binary files a/www/fonts/MicroFLF.ttf and /dev/null differ diff --git a/www/fonts/maven_pro.css b/www/fonts/maven_pro.css deleted file mode 100755 index b55184e..0000000 --- a/www/fonts/maven_pro.css +++ /dev/null @@ -1,48 +0,0 @@ -@font-face { - font-family: 'Maven Pro'; - src: url('maven_pro_black-webfont.eot'); - src: url('maven_pro_black-webfont.eot?#iefix') format('eot'), - url('maven_pro_black-webfont.woff') format('woff'), - url('maven_pro_black-webfont.ttf') format('truetype'), - url('maven_pro_black-webfont.svg#webfontXhB2DgBK') format('svg'); - font-weight: 900; - font-style: normal; - -} - -@font-face { - font-family: 'Maven Pro'; - src: url('maven_pro_medium-webfont.eot'); - src: url('maven_pro_medium-webfont.eot?#iefix') format('eot'), - url('maven_pro_medium-webfont.woff') format('woff'), - url('maven_pro_medium-webfont.ttf') format('truetype'), - url('maven_pro_medium-webfont.svg#webfontNj5iy4Dl') format('svg'); - font-weight: 500; - font-style: normal; - -} - -@font-face { - font-family: 'Maven Pro'; - src: url('maven_pro_bold-webfont.eot'); - src: url('maven_pro_bold-webfont.eot?#iefix') format('eot'), - url('maven_pro_bold-webfont.woff') format('woff'), - url('maven_pro_bold-webfont.ttf') format('truetype'), - url('maven_pro_bold-webfont.svg#webfontNOU7iUTL') format('svg'); - font-weight: 700; - font-style: normal; - -} - -@font-face { - font-family: 'Maven Pro'; - src: url('maven_pro_regular-webfont.eot'); - src: url('maven_pro_regular-webfont.eot?#iefix') format('eot'), - url('maven_pro_regular-webfont.woff') format('woff'), - url('maven_pro_regular-webfont.ttf') format('truetype'), - url('maven_pro_regular-webfont.svg#webfontOM8fITNz') format('svg'); - font-weight: 400; - font-style: normal; - -} - diff --git a/www/fonts/maven_pro_black-webfont.eot b/www/fonts/maven_pro_black-webfont.eot deleted file mode 100755 index c7091c1..0000000 Binary files a/www/fonts/maven_pro_black-webfont.eot and /dev/null differ diff --git a/www/fonts/maven_pro_black-webfont.svg b/www/fonts/maven_pro_black-webfont.svg deleted file mode 100755 index 456f336..0000000 --- a/www/fonts/maven_pro_black-webfont.svg +++ /dev/null @@ -1,245 +0,0 @@ - - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Copyright c 2011 by Vissol Ltd All rights reserved -Designer : Joe Prince -Foundry : Joe Prince - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/www/fonts/maven_pro_black-webfont.ttf b/www/fonts/maven_pro_black-webfont.ttf deleted file mode 100755 index 22cebdf..0000000 Binary files a/www/fonts/maven_pro_black-webfont.ttf and /dev/null differ diff --git a/www/fonts/maven_pro_black-webfont.woff b/www/fonts/maven_pro_black-webfont.woff deleted file mode 100755 index ae8fba0..0000000 Binary files a/www/fonts/maven_pro_black-webfont.woff and /dev/null differ diff --git a/www/fonts/maven_pro_bold-webfont.eot b/www/fonts/maven_pro_bold-webfont.eot deleted file mode 100755 index 6f4a488..0000000 Binary files a/www/fonts/maven_pro_bold-webfont.eot and /dev/null differ diff --git a/www/fonts/maven_pro_bold-webfont.svg b/www/fonts/maven_pro_bold-webfont.svg deleted file mode 100755 index 7f24bdb..0000000 --- a/www/fonts/maven_pro_bold-webfont.svg +++ /dev/null @@ -1,245 +0,0 @@ - - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Copyright c 2011 by Vissol Ltd All rights reserved -Designer : Joe Prince -Foundry : Joe Prince - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/www/fonts/maven_pro_bold-webfont.ttf b/www/fonts/maven_pro_bold-webfont.ttf deleted file mode 100755 index 7682e5b..0000000 Binary files a/www/fonts/maven_pro_bold-webfont.ttf and /dev/null differ diff --git a/www/fonts/maven_pro_bold-webfont.woff b/www/fonts/maven_pro_bold-webfont.woff deleted file mode 100755 index 3eea8ae..0000000 Binary files a/www/fonts/maven_pro_bold-webfont.woff and /dev/null differ diff --git a/www/fonts/maven_pro_medium-webfont.eot b/www/fonts/maven_pro_medium-webfont.eot deleted file mode 100755 index 0eb177c..0000000 Binary files a/www/fonts/maven_pro_medium-webfont.eot and /dev/null differ diff --git a/www/fonts/maven_pro_medium-webfont.svg b/www/fonts/maven_pro_medium-webfont.svg deleted file mode 100755 index 532bf53..0000000 --- a/www/fonts/maven_pro_medium-webfont.svg +++ /dev/null @@ -1,245 +0,0 @@ - - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Copyright c 2011 by Vissol Ltd All rights reserved -Designer : Joe Prince -Foundry : Joe Prince - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/www/fonts/maven_pro_medium-webfont.ttf b/www/fonts/maven_pro_medium-webfont.ttf deleted file mode 100755 index a930700..0000000 Binary files a/www/fonts/maven_pro_medium-webfont.ttf and /dev/null differ diff --git a/www/fonts/maven_pro_medium-webfont.woff b/www/fonts/maven_pro_medium-webfont.woff deleted file mode 100755 index a2737c3..0000000 Binary files a/www/fonts/maven_pro_medium-webfont.woff and /dev/null differ diff --git a/www/fonts/maven_pro_regular-webfont.eot b/www/fonts/maven_pro_regular-webfont.eot deleted file mode 100755 index a9b38de..0000000 Binary files a/www/fonts/maven_pro_regular-webfont.eot and /dev/null differ diff --git a/www/fonts/maven_pro_regular-webfont.svg b/www/fonts/maven_pro_regular-webfont.svg deleted file mode 100755 index 6f5deb3..0000000 --- a/www/fonts/maven_pro_regular-webfont.svg +++ /dev/null @@ -1,245 +0,0 @@ - - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Copyright c 2011 by Vissol Ltd All rights reserved -Designer : Joe Prince -Foundry : Joe Prince - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/www/fonts/maven_pro_regular-webfont.ttf b/www/fonts/maven_pro_regular-webfont.ttf deleted file mode 100755 index fae9c6a..0000000 Binary files a/www/fonts/maven_pro_regular-webfont.ttf and /dev/null differ diff --git a/www/fonts/maven_pro_regular-webfont.woff b/www/fonts/maven_pro_regular-webfont.woff deleted file mode 100755 index 3c27f73..0000000 Binary files a/www/fonts/maven_pro_regular-webfont.woff and /dev/null differ diff --git a/www/images/background.png b/www/images/background.png deleted file mode 100644 index 004e817..0000000 Binary files a/www/images/background.png and /dev/null differ diff --git a/www/images/logo0.png b/www/images/logo0.png deleted file mode 100644 index 0c4add8..0000000 Binary files a/www/images/logo0.png and /dev/null differ diff --git a/www/images/logo1.png b/www/images/logo1.png deleted file mode 100644 index 0c4add8..0000000 Binary files a/www/images/logo1.png and /dev/null differ diff --git a/www/images/logo2.png b/www/images/logo2.png deleted file mode 100644 index 0c4add8..0000000 Binary files a/www/images/logo2.png and /dev/null differ diff --git a/www/images/logo3.png b/www/images/logo3.png deleted file mode 100644 index 0c4add8..0000000 Binary files a/www/images/logo3.png and /dev/null differ diff --git a/www/images/logo4.png b/www/images/logo4.png deleted file mode 100644 index 0c4add8..0000000 Binary files a/www/images/logo4.png and /dev/null differ diff --git a/www/index.html b/www/index.html deleted file mode 100644 index ad9f3db..0000000 --- a/www/index.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - Welcome - - - -

MOTH

- - - -
-

Getting Started

- -

- Here is what you need to do: -

- -
    -
  1. - Register your team. - This only needs to happen once per team, - so if somebody else on your team has already done it, - you don't need to. -
  2. - -
  3. - Get an overview of puzzles, - and start working on something. - The list of open puzzles changes over time, - you need to reload the page to get the current version! -
  4. - -
  5. - Check the scoreboard - in another tab, - to see how your team is doing. -
  6. -
-
- -
-

Reading Material

- -

- Stuck? Taking a break? - Here are some things to read. -

- - -
- -
- - - - - -
- - diff --git a/www/projections.json b/www/projections.json deleted file mode 100644 index 133ffe4..0000000 --- a/www/projections.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - "scoreboard.html" -] diff --git a/www/projector.html b/www/projector.html deleted file mode 100644 index 7366521..0000000 --- a/www/projector.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - Scoreboard - - - - - - - - - diff --git a/www/puzzles-notoken.html b/www/puzzles-notoken.html deleted file mode 100644 index f273602..0000000 --- a/www/puzzles-notoken.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - Open Puzzles - - - - - - - - - - - -

Open Puzzles

-
-
-
- - diff --git a/www/puzzles-tokens.html b/www/puzzles-tokens.html deleted file mode 100644 index a4971b0..0000000 --- a/www/puzzles-tokens.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - Open Puzzles - - - - - - - - - - - -

Open Puzzles

-
-
-
-
-
External Token: -

Example: category:5:xylep-radar-nanox

-
- Team Hash:
- Token: -
-
-
- - diff --git a/www/puzzles.html b/www/puzzles.html deleted file mode 120000 index 7fa7119..0000000 --- a/www/puzzles.html +++ /dev/null @@ -1 +0,0 @@ -puzzles-notoken.html \ No newline at end of file diff --git a/www/register.html b/www/register.html deleted file mode 100644 index 07fe93a..0000000 --- a/www/register.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - Team Registration - - - - -

Team Registration

- -
-

Register Your Team

- -

- Before you can use a team hash, - you must name your team. - You can only do this once, - so make sure it's the team name you actually want. - Staff are unable to make changes to team names. -

- -

- If somebody on your team has already registered your hash, - you don't need to do it again. -

- -
- - -
- - -
- -
-
- -
- - - - - -
- - diff --git a/www/res/Inconsolata-Bold.ttf b/www/res/Inconsolata-Bold.ttf deleted file mode 100644 index 035d579..0000000 Binary files a/www/res/Inconsolata-Bold.ttf and /dev/null differ diff --git a/www/res/Inconsolata-Regular.ttf b/www/res/Inconsolata-Regular.ttf deleted file mode 100644 index bbc9647..0000000 Binary files a/www/res/Inconsolata-Regular.ttf and /dev/null differ diff --git a/www/res/Lato-Black.ttf b/www/res/Lato-Black.ttf deleted file mode 100644 index 6848db0..0000000 Binary files a/www/res/Lato-Black.ttf and /dev/null differ diff --git a/www/res/Lato-BlackItalic.ttf b/www/res/Lato-BlackItalic.ttf deleted file mode 100644 index 5decf12..0000000 Binary files a/www/res/Lato-BlackItalic.ttf and /dev/null differ diff --git a/www/res/Lato-Bold.ttf b/www/res/Lato-Bold.ttf deleted file mode 100644 index 7434369..0000000 Binary files a/www/res/Lato-Bold.ttf and /dev/null differ diff --git a/www/res/Lato-BoldItalic.ttf b/www/res/Lato-BoldItalic.ttf deleted file mode 100644 index 684aacf..0000000 Binary files a/www/res/Lato-BoldItalic.ttf and /dev/null differ diff --git a/www/res/Lato-Hairline.ttf b/www/res/Lato-Hairline.ttf deleted file mode 100644 index 288be29..0000000 Binary files a/www/res/Lato-Hairline.ttf and /dev/null differ diff --git a/www/res/Lato-HairlineItalic.ttf b/www/res/Lato-HairlineItalic.ttf deleted file mode 100644 index c2bfd33..0000000 Binary files a/www/res/Lato-HairlineItalic.ttf and /dev/null differ diff --git a/www/res/Lato-Italic.ttf b/www/res/Lato-Italic.ttf deleted file mode 100644 index 3d3b7a2..0000000 Binary files a/www/res/Lato-Italic.ttf and /dev/null differ diff --git a/www/res/Lato-Light.ttf b/www/res/Lato-Light.ttf deleted file mode 100644 index a958067..0000000 Binary files a/www/res/Lato-Light.ttf and /dev/null differ diff --git a/www/res/Lato-LightItalic.ttf b/www/res/Lato-LightItalic.ttf deleted file mode 100644 index 5e45ad9..0000000 Binary files a/www/res/Lato-LightItalic.ttf and /dev/null differ diff --git a/www/res/Lato-Regular.ttf b/www/res/Lato-Regular.ttf deleted file mode 100644 index 04ea8ef..0000000 Binary files a/www/res/Lato-Regular.ttf and /dev/null differ diff --git a/www/res/Lato.css b/www/res/Lato.css deleted file mode 100644 index da5b5db..0000000 --- a/www/res/Lato.css +++ /dev/null @@ -1,18 +0,0 @@ -@font-face { - font-family: 'Lato'; - font-style: normal; - font-weight: 400; - src: local('Lato Regular'), local('Lato-Regular'), url(Lato-Regular.ttf) format('truetype'); -} -@font-face { - font-family: 'Lato'; - font-style: normal; - font-weight: 700; - src: local('Lato Bold'), local('Lato-Bold'), url(Lato-Bold.ttf) format('truetype'); -} -@font-face { - font-family: 'Lato'; - font-style: italic; - font-weight: 400; - src: local('Lato Italic'), local('Lato-Italic'), url(Lato-Italic.ttf) format('truetype'); -} diff --git a/www/res/brown-lines.jpg b/www/res/brown-lines.jpg deleted file mode 100644 index 63d30ac..0000000 Binary files a/www/res/brown-lines.jpg and /dev/null differ diff --git a/www/res/common.js b/www/res/common.js deleted file mode 100644 index 500dd14..0000000 --- a/www/res/common.js +++ /dev/null @@ -1,50 +0,0 @@ -function loadJSON(url, callback) { - function loaded(e) { - callback(e.target.response); - } - var xhr = new XMLHttpRequest() - xhr.onload = loaded; - xhr.open("GET", url, true); - xhr.responseType = "json"; - xhr.send(); -} - -function createElement(tagName) { - return document.createElement(tagName); -} - -function djb2hash(str) { - var hash = 5381; - - for (var i = 0; i < str.length; i += 1) { - var c = str.charCodeAt(i); - hash = ((hash * 33) + c) & 0xffffffff; - } - return hash; -} - -// Make code readable by providing Function.prototype.bind in older JS environments -if (!Function.prototype.bind) { - Function.prototype.bind = function(oThis) { - if (typeof this !== 'function') { - // closest thing possible to the ECMAScript 5 - // internal IsCallable function - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - - var aArgs = Array.prototype.slice.call(arguments, 1), - fToBind = this, - fNOP = function() {}, - fBound = function() { - return fToBind.apply(this instanceof fNOP && oThis - ? this - : oThis, - aArgs.concat(Array.prototype.slice.call(arguments))); - }; - - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - - return fBound; - }; -} diff --git a/www/res/luna-moth.png b/www/res/luna-moth.png deleted file mode 100644 index 0e34114..0000000 Binary files a/www/res/luna-moth.png and /dev/null differ diff --git a/www/res/luna-moth.svg b/www/res/luna-moth.svg deleted file mode 100644 index 337ce04..0000000 --- a/www/res/luna-moth.svg +++ /dev/null @@ -1,274 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - Openclipart - - - - 2012-05-15T03:53:14 - luna moth, moon, night, butterfly - https://openclipart.org/detail/170025/papillon-lune-by-presquesage - - - presquesage - - - - - butterfly - luna moth - lune - moon - night - nuit - papillon - - - - - - - - - - - diff --git a/www/res/main.js b/www/res/main.js deleted file mode 100644 index 8299d94..0000000 --- a/www/res/main.js +++ /dev/null @@ -1,26 +0,0 @@ -var main_terminal; - -function Main(element) { - var term = new Terminal(element); - - function start() { - term.clear(); - term.par("Main terminal.") - term.par("This is the main terminal. In this terminal you will get your puzzle content and someplace to enter in possible answers. It's probably just going to pull the old URL, steal the body element, and submit it to a new Terminal method for slow-despooling of the content of text nodes.") - term.par("One side-effect of the method I'm considering to slow-despool pre-written HTML is that inline images will load before the text. While not exactly what I had in mind for the feel of the thing, it may still be an interesting effect. I mean, if anything, text should render the *quickest*, so if we're going to turn everything on its head, why not make images pull in quicker than text."); - term.par("Anyway."); - term.par("Hopefully this demo illustrates how things are going to look."); - } - - term.clear(); - term.par("Loading
"); - - setTimeout(start, 2500); -} - - -function main_start() { - main_terminal = new Main(document.getElementById("main")); -} - -window.addEventListener("load", main_start); diff --git a/www/res/md5.min.js b/www/res/md5.min.js deleted file mode 100644 index 3399bf4..0000000 --- a/www/res/md5.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;et;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;tt;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); -//# sourceMappingURL=md5.min.js.map diff --git a/www/res/messages.js b/www/res/messages.js deleted file mode 100644 index 172599b..0000000 --- a/www/res/messages.js +++ /dev/null @@ -1,22 +0,0 @@ -var messages_terminal; - -function Messages(element) { - var term = new Terminal(element); - - function start() { - term.clear(); - term.par("Messages terminal"); - term.par("I've long wanted a way to communicate things to participants, like «yes, we're aware that JS 12 is broken, we are working on it», or «tanks category is now open!». This might have updates about people scoring points, or provide a chat service (although that has not historically been well-utilized)."); - } - - term.clear(); - term.par("Loading
"); - setTimeout(start, 500); -} - - -function messages_start() { - messages_terminal = new Messages(document.getElementById("messages")); -} - -window.addEventListener("load", messages_start); diff --git a/www/res/overview.js b/www/res/overview.js deleted file mode 100644 index ce6f817..0000000 --- a/www/res/overview.js +++ /dev/null @@ -1,19 +0,0 @@ -var overview_proc; - -function Overview(element) { - var term = new Terminal(element); - - this.start = function() { - term.clear(); - term.par("Overview terminal"); - term.par("Here you will find something resembling a scoreboard, maybe your team name.") - } -} - - -function overview_start() { - overview_proc = new Overview(document.getElementById("overview")); - setTimeout(overview_proc.start, 4000); -} - -window.addEventListener("load", overview_start); diff --git a/www/res/preview.png b/www/res/preview.png deleted file mode 100644 index 396a9c8..0000000 Binary files a/www/res/preview.png and /dev/null differ diff --git a/www/res/puzzles.js b/www/res/puzzles.js deleted file mode 100644 index e201559..0000000 --- a/www/res/puzzles.js +++ /dev/null @@ -1,67 +0,0 @@ -var puzzlesTerminal; -var puzzlesJsonUrl = "puzzles.json"; - -function loadPuzzle(cat, id, points) { - console.log("Requested " + cat + "/" + id + "(" + points + ")"); -} - -function puzzlesRefresh(term, obj) { - term.clear(); - - let cats = []; - for (let cat in obj) { - cats.push(cat); - } - cats.sort(); - - for (let cat of cats) { - let puzzles = obj[cat]; - - let pdiv = createElement('div'); - pdiv.className = 'category'; - - let h = createElement('h2'); - pdiv.appendChild(h); - h.textContent = cat; - - let l = createElement('ul'); - pdiv.appendChild(l); - - for (var puzzle of puzzles) { - var points = puzzle[0]; - var id = puzzle[1]; - - var i = createElement('li'); - l.appendChild(i); - - if (points === 0) { - i.textContent = "‡"; - } else { - var a = createElement('a'); - i.appendChild(a); - a.className = "link"; - a.textContent = points; - a.href = cat + "/" + id + "/index.html"; - // a.addEventListener("click", loadPuzzle.bind(undefined, cat, id, points)); - } - } - - term.appendShallow(pdiv); - } -} - -function puzzles_start() { - var element = document.getElementById("puzzles"); - var puzzlesTerminal = new Terminal(element); - var refreshInterval = 40 * 1000; - - var refreshCallback = puzzlesRefresh.bind(undefined, puzzlesTerminal); - var refreshFunction = loadJSON.bind(undefined, puzzlesJsonUrl + '?_=' + new Date().getTime(), refreshCallback); - - puzzlesTerminal.clear(); - puzzlesTerminal.par("Loading..."); - refreshFunction(); - setInterval(refreshFunction, refreshInterval); -} - -window.addEventListener("load", puzzles_start); diff --git a/www/res/scoreboard.js b/www/res/scoreboard.js deleted file mode 100644 index 76486f0..0000000 --- a/www/res/scoreboard.js +++ /dev/null @@ -1,116 +0,0 @@ -function loadJSON(url, callback) { - function loaded(e) { - callback(e.target.response); - } - var xhr = new XMLHttpRequest() - xhr.onload = loaded; - xhr.open("GET", url, true); - xhr.responseType = "json"; - xhr.send(); -} - -function scoreboard(element, continuous) { - function update(state) { - var teamnames = state["teams"]; - var pointslog = state["points"]; - var pointshistory = JSON.parse(localStorage.getItem("pointshistory")) || []; - if (pointshistory.length >= 20){ - pointshistory.shift(); - } - pointshistory.push(pointslog); - localStorage.setItem("pointshistory", JSON.stringify(pointshistory)); - var highscore = {}; - var teams = {}; - - // Dole out points - for (var i in pointslog) { - var entry = pointslog[i]; - var timestamp = entry[0]; - var teamhash = entry[1]; - var category = entry[2]; - var points = entry[3]; - - var team = teams[teamhash] || {__hash__: teamhash}; - - // Add points to team's points for that category - team[category] = (team[category] || 0) + points; - - // Record highest score in a category - highscore[category] = Math.max(highscore[category] || 0, team[category]); - - teams[teamhash] = team; - } - - // Sort by team score - function teamScore(t) { - var score = 0; - - for (var category in highscore) { - score += (t[category] || 0) / highscore[category]; - } - // XXX: This function really shouldn't have side effects. - t.__score__ = score; - return score; - } - function teamCompare(a, b) { - return teamScore(a) - teamScore(b); - } - - var winners = []; - for (var i in teams) { - winners.push(teams[i]); - } - if (winners.length == 0) { - // No teams! - return; - } - winners.sort(teamCompare); - winners.reverse(); - - // Clear out the element we're about to populate - while (element.lastChild) { - element.removeChild(element.lastChild); - } - - // Populate! - var topActualScore = winners[0].__score__; - - // (100 / ncats) * (ncats / topActualScore); - var maxWidth = 100 / topActualScore; - for (var i in winners) { - var team = winners[i]; - var row = document.createElement("div"); - var ncat = 0; - for (var category in highscore) { - var catHigh = highscore[category]; - var catTeam = team[category] || 0; - var catPct = catTeam / catHigh; - var width = maxWidth * catPct; - - var bar = document.createElement("span"); - bar.classList.add("cat" + ncat); - bar.style.width = width + "%"; - bar.textContent = category + ": " + catTeam; - bar.title = bar.textContent; - - row.appendChild(bar); - ncat += 1; - } - - var te = document.createElement("span"); - te.classList.add("teamname"); - te.textContent = teamnames[team.__hash__]; - row.appendChild(te); - - element.appendChild(row); - } - } - - function once() { - loadJSON("points.json", update); - } - if (continuous) { - setInterval(once, 60000); - } - once(); -} diff --git a/www/res/style.css b/www/res/style.css deleted file mode 100644 index 14f11e9..0000000 --- a/www/res/style.css +++ /dev/null @@ -1,139 +0,0 @@ -@font-face { - font-family: 'Lato'; - font-style: normal; - font-weight: 400; - src: local('Lato Regular'), local('Lato-Regular'), url(Lato-Regular.ttf) format('truetype'); -} -@font-face { - font-family: 'Lato'; - font-style: normal; - font-weight: 700; - src: local('Lato Bold'), local('Lato-Bold'), url(Lato-Bold.ttf) format('truetype'); -} -@font-face { - font-family: 'Lato'; - font-style: italic; - font-weight: 400; - src: local('Lato Italic'), local('Lato-Italic'), url(Lato-Italic.ttf) format('truetype'); -} -@font-face { - font-family: 'Inconsolata'; - font-style: normal; - font-weight: 400; - src: local('Inconsolata Regular'), local('Inconsolata-Regular'), url(Inconsolata-Regular.ttf) format('truetype'); -} - - -html { - background: rgba(61, 50, 44, 0) url(brown-lines.jpg) no-repeat center center fixed; - background-size: cover; - color: #ccb; - height: 100%; - font-family: Lato, sans-serif; -} - -body { - margin: 0; - height: 100% -} - -pre, tt { - font-family: Inconsolata, monospace; - background-color: rgba(0, 0, 0, 0.3); -} - -.terminal { - background: rgba(80, 70, 60, 0.96); - display: inline-block; - margin: 1%; - border: solid black 0.2em; - border-radius: 1em 1em 0.5em 1em; - overflow: auto; -} - -.terminal p { - padding: 0.25em 0.5em; -} - -#preview { - background-image: url(preview.png); - background-size: contain; - max-width: 40em; - display: block; - margin: 1% auto; -} - -#overview, #messages { - width: 47%; - height: 20%; -} - -#puzzles { - width: 24%; - height: 70%; -} - -#main { - width: 70%; - height: 70%; -} - -.download { - background: #080; - color: white; - display: inline-block; -} -.download:link { - color: inherit; - text-decoration: inherit; -} - -h1 { - text-align: center; - font-size: 120%; -} - -a:link, .link { - color: #13a5de; - cursor: pointer; -} - -a:visited { - color: #999999; -} - -.category h2 { - margin: 0; - font-size: 100%; -} -.category ul { - margin: 0; - padding-left: 1em; - font-size: 90%; -} -.category li { - display: inline; -} -.category li + li:before { - content: " "; -} - -@media (max-width: 52em) { - #overview, #messages, #puzzles, #main { - width: 96%; - } -} - -::-webkit-scrollbar { - width: 0.7em; -} - -::-webkit-scrollbar-track { - /* -webkit-box-shadow: inset 0 0 0.5em rgba(200, 200, 200, 0.3); */ - background: rgba(0, 0, 0, 0.2); -} - -::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, 0.2); - border-radius: 1em; -} diff --git a/www/res/terminal.js b/www/res/terminal.js deleted file mode 100644 index f49df38..0000000 --- a/www/res/terminal.js +++ /dev/null @@ -1,160 +0,0 @@ -// A class to turn an element into a cybersteampunk terminal. -// Runs at 1200 baud by default, but unlike an actual modem, -// will despool in parallel. This looks pretty cool. - -// XXX: Hack for chrome not supporting an iterator method on HTMLCollection -HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; -NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; - -function Terminal(target, bps) { - bps = bps || 9600; - - var outq = []; - var outTimer; - - // Heavy lifting happens here. - // At first I had it auto-scrolling to the bottom, like xterm (1987). - // But that was actually kind of annoying, since this is meant to be read. - // So now it leaves the scrollbar in place, and the user has to scroll. - // This is how the Plan 9 terminal (1991) works. - function tx(pairs, bps, scroll) { - var drawTimer; - - // Looks like EMCAScript 6 has a yield statement. - // That would make this mess a lot easier to understand. - - var pairIndex = 0; - var pair = pairs[0]; - - var textIndex = 0; - var text = ""; - - function draw() { - var node = pair[0]; - var src = pair[1]; - var c = src[textIndex]; - - text += c; - node.textContent = text; - - textIndex += 1; - if (textIndex == src.length) { - textIndex = 0; - text = ""; - - pairIndex += 1; - if (pairIndex == pairs.length) { - clearInterval(drawTimer); - return; - } - pair = pairs[pairIndex]; - } - - if (scroll) { - node.scrollIntoView(); - } - } - - // N81 uses 1 stop bit, and 1 parity bit. - // That works out to exactly 10 bits per byte. - msec = 10000 / bps; - - drawTimer = setInterval(draw, msec); - draw(); - } - - - function start() { - if (! outTimer) { - outTimer = setInterval(drawElement, 25); - } - } - - - function stop() { - if (outTimer) { - clearInterval(outTimer); - outTimer = null; - } - } - - - function drawElement() { - var pairs = outq.shift(); - - if (! pairs) { - stop(); - return; - } - - tx(pairs, bps); - } - - - function prepare(element) { - var pairs = []; - - walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT); - while (walker.nextNode()) { - var node = walker.currentNode; - var text = node.textContent; - - node.textContent = ""; - pairs.push([node, text]); - } - - return pairs; - } - - - // The main entry point: works like appendChild - this.append = function(element) { - pairs = prepare(element); - target.appendChild(element); - outq.push(pairs); - start(); - } - - - // A cool effect where it despools children in parallel - this.appendShallow = function(element) { - for (var child of element.childNodes) { - pairs = prepare(child); - outq.push(pairs); - } - target.appendChild(element); - start(); - } - - - this.clear = function() { - stop(); - outq = []; - while (target.firstChild) { - target.removeChild(target.firstChild); - } - } - - - this.par = function(txt) { - var e = document.createElement("p"); - e.textContent = txt; - this.append(e); - } - - - this.pre = function(txt) { - var e = document.createElement("pre"); - e.textContent = txt; - this.append(e); - } -} - -// -// Usage: -// -// var e = Terminal(document.getElementById("output")); -// e.output("This is a paragraph. It has sentences."); -// e.output("This is a second paragraph."); -// - diff --git a/www/restore.html b/www/restore.html deleted file mode 100644 index 361e0c1..0000000 --- a/www/restore.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - Points History - - - -
- - diff --git a/www/scoreboard-all.html b/www/scoreboard-all.html deleted file mode 100644 index e975d0e..0000000 --- a/www/scoreboard-all.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - Scoreboard - - - - - - - -

Scoreboard

-
- - - diff --git a/www/scoreboard-animated.js b/www/scoreboard-animated.js deleted file mode 100644 index 3f56646..0000000 --- a/www/scoreboard-animated.js +++ /dev/null @@ -1,164 +0,0 @@ -function loadJSON(url, callback) { - function loaded(e) { - callback(e.target.response); - } - var xhr = new XMLHttpRequest() - xhr.onload = loaded; - xhr.open("GET", url, true); - xhr.responseType = "json"; - xhr.send(); -} - -function scoreboardHistoryPush(pointslog) { - let pointsHistory = JSON.parse(localStorage.getItem("pointsHistory")) || []; - if (pointsHistory.length >= 20) { - pointsHistory.shift(); - } - pointsHistory.push(pointslog); - localStorage.setItem("pointsHistory", JSON.stringify(pointsHistory)); -} - -function scoreboard(element, continuous) { - function update(state) { - let teamNames = state["teams"]; - let pointsLog = state["points"]; - - // Establish scores, calculate category maximums - let categories = {}; - let maxPointsByCategory = {}; - let totalPointsByTeamByCategory = {}; - for (let entry of pointsLog) { - let entryTimeStamp = entry[0]; - let entryTeamHash = entry[1]; - let entryCategory = entry[2]; - let entryPoints = entry[3]; - - // Populate list of all categories - categories[entryCategory] = entryCategory; - - // Add points to team's points for that category - let points = totalPointsByTeamByCategory[entryTeamHash] || {}; - let categoryPoints = points[entryCategory] || 0; - categoryPoints += entryPoints; - points[entryCategory] = categoryPoints; - totalPointsByTeamByCategory[entryTeamHash] = points; - - // Calculate maximum points scored in each category - let m = maxPointsByCategory[entryCategory] || 0; - maxPointsByCategory[entryCategory] = Math.max(m, categoryPoints); - } - - // Calculate overall scores - let overallScore = {}; - let orderedOverallScores = []; - for (let teamHash in teamNames) { - var score = 0; - for (let cat in categories) { - var catPoints = totalPointsByTeamByCategory[teamHash][cat] || 0; - if (catPoints > 0) { - score += catPoints / maxPointsByCategory[cat]; - } - } - overallScore[teamHash] = score; - orderedOverallScores.push([score, teamHash]); - } - orderedOverallScores.sort(); - orderedOverallScores.reverse(); - - // Clear out the element we're about to populate - while (element.lastChild) { - element.removeChild(element.lastChild); - } - - // Set up scoreboard structure - let spansByTeamByCategory = {}; - for (let pair of orderedOverallScores) { - let teamHash = pair[1]; - let teamName = teamNames[teamHash]; - let teamRow = document.createElement("div"); - let ncat = 0; - spansByTeamByCategory[teamHash] = {}; - for (let cat in categories) { - let catSpan = document.createElement("span"); - catSpan.classList.add("cat" + ncat); - catSpan.style.width = "0%"; - catSpan.textContent = cat + ": 0"; - - spansByTeamByCategory[teamHash][cat] = catSpan; - - teamRow.appendChild(catSpan); - ncat += 1; - } - - var te = document.createElement("span"); - te.classList.add("teamname"); - te.textContent = teamName; - teamRow.appendChild(te); - - element.appendChild(teamRow); - } - - // How many categories are there? - var numCategories = 0; - for (var cat in categories) { - numCategories += 1; - } - - // Replay points log, displaying scoreboard at each step - let replayTimer = null; - let replayIndex = 0; - function replayStep(event) { - if (replayIndex > pointsLog.length) { - clearInterval(replayTimer); - return; - } - - // Replay log up until replayIndex - let totalPointsByTeamByCategory = {}; - for (let index = 0; index < replayIndex; index += 1) { - let entry = pointsLog[index]; - let entryTimeStamp = entry[0]; - let entryTeamHash = entry[1]; - let entryCategory = entry[2]; - let entryPoints = entry[3]; - - // Add points to team's points for that category - let points = totalPointsByTeamByCategory[entryTeamHash] || {}; - let categoryPoints = points[entryCategory] || 0; - categoryPoints += entryPoints; - points[entryCategory] = categoryPoints; - totalPointsByTeamByCategory[entryTeamHash] = points; - } - - // Figure out everybody's score - for (let teamHash in teamNames) { - for (let cat in categories) { - let totalPointsByCategory = totalPointsByTeamByCategory[teamHash] || {}; - let points = totalPointsByCategory[cat] || 0; - if (points > 0) { - let score = points / maxPointsByCategory[cat]; - let span = spansByTeamByCategory[teamHash][cat]; - let width = (100.0 / numCategories) * score; - - span.style.width = width + "%"; - span.textContent = cat + ": " + points; - span.title = span.textContent; - } - } - } - - replayIndex += 1; - } - replayStep(); - replayTimer = setInterval(replayStep, 20); - } - - function once() { - loadJSON("points.json", update); - } - if (continuous) { - setInterval(once, 60000); - } - once(); -} - diff --git a/www/scoreboard-proj.html b/www/scoreboard-proj.html deleted file mode 100644 index 2d5cf97..0000000 --- a/www/scoreboard-proj.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - Scoreboard - - -
- -
- - - diff --git a/www/scoreboard-timeline.html b/www/scoreboard-timeline.html deleted file mode 100644 index bc1da93..0000000 --- a/www/scoreboard-timeline.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - Scoreboard - - - - - - - -

Scoreboard

-
- - diff --git a/www/scoreboard.html b/www/scoreboard.html deleted file mode 100644 index 0289d9c..0000000 --- a/www/scoreboard.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - Scoreboard - - - - - -

Scoreboard

-
- - - diff --git a/www/scoreboard.js b/www/scoreboard.js deleted file mode 100644 index 7546522..0000000 --- a/www/scoreboard.js +++ /dev/null @@ -1,528 +0,0 @@ -function loadJSON(url, callback) { - function loaded(e) { - callback(e.target.response); - } - var xhr = new XMLHttpRequest() - xhr.onload = loaded; - xhr.open("GET", url, true); - xhr.responseType = "json"; - xhr.send(); -} - -function toObject(arr) { - var rv = {}; - for (var i = 0; i < arr.length; ++i) - if (arr[i] !== undefined) rv[i] = arr[i]; - return rv; -} - -var updateInterval; - -function scoreboard(element, continuous, mode, interval) { - if(updateInterval) { - clearInterval(updateInterval); - } - function update(state) { - //console.log("Updating"); - var teamnames = state["teams"]; - var pointslog = state["points"]; - var highscore = {}; - var teams = {}; - - function pointsCompare(a, b) { - return a[0] - b[0]; - } - pointslog.sort(pointsCompare); - var minTime = pointslog[0][0]; - var maxTime = pointslog[pointslog.length - 1][0]; - - var allQuestions = {}; - - for (var i in pointslog) { - var entry = pointslog[i]; - var timestamp = entry[0]; - var teamhash = entry[1]; - var category = entry[2]; - var points = entry[3]; - - var catPoints = {}; - if(category in allQuestions) { - catPoints = allQuestions[category]; - } else { - catPoints["total"] = 0; - } - - if(!(points in catPoints)) { - catPoints[points] = 1; - catPoints["total"] = catPoints["total"] + points; - } else { - catPoints[points] = catPoints[points] + 1; - } - - allQuestions[category] = catPoints; - } - - // Dole out points - for (var i in pointslog) { - var entry = pointslog[i]; - var timestamp = entry[0]; - var teamhash = entry[1]; - var category = entry[2]; - var points = entry[3]; - - var team = teams[teamhash] || {__hash__: teamhash}; - - // Add points to team's points for that category - team[category] = (team[category] || 0) + points; - - // Record highest score in a category - highscore[category] = Math.max(highscore[category] || 0, team[category]); - - teams[teamhash] = team; - } - - // Sort by team score - function teamScore(t) { - var score = 0; - - for (var category in highscore) { - score += (t[category] || 0) / highscore[category]; - } - // XXX: This function really shouldn't have side effects. - t.__score__ = score; - return score; - } - function pointScore(points, category) { - return points / highscore[category] - } - function teamCompare(a, b) { - return teamScore(a) - teamScore(b); - } - - var winners = []; - for (var i in teams) { - winners.push(teams[i]); - } - if (winners.length == 0) { - // No teams! - return; - } - winners.sort(teamCompare); - winners.reverse(); - - // Clear out the element we're about to populate - while (element.lastChild) { - element.removeChild(element.lastChild); - } - - // Populate! - var topActualScore = winners[0].__score__; - - - if(mode == "time") { - var colorScale = d3.schemeCategory20; - - var teamLines = {}; - var reverseTeam = {}; - for(var i in pointslog) { - var entry = pointslog[i]; - var timestamp = entry[0]; - var teamhash = entry[1]; - var category = entry[2]; - var points = entry[3]; - var teamname = teamnames[teamhash]; - reverseTeam[teamname] = teamhash; - points = pointScore(points, category); - - if(!(teamname in teamLines)) { - var teamHistory = [[timestamp, points, category, entry[3], [minTime, 0, category, 0]]]; - teamLines[teamname] = teamHistory; - } else { - var teamHistory = teamLines[teamname]; - teamHistory.push([timestamp, points + teamHistory[teamHistory.length - 1][1], category, entry[3], teamHistory[teamHistory.length - 1]]); - } - } - - //console.log(teamLines); - - var graph = document.createElement("svg"); - graph.id = "graph"; - graph.style.width="100%"; - graph.style.height = "100vh"; - var titleHeight = document.getElementById("title").clientHeight; - titleHeight += document.getElementById("title").offsetTop * 2; - graph.style.backgroundColor = "white"; - graph.style.display = "table"; - var holdingDiv = document.createElement("div"); - holdingDiv.align="center"; - holdingDiv.id="holding"; - holdingDiv.style.height = "100%"; - element.style.height = "100%"; - element.appendChild(holdingDiv); - holdingDiv.appendChild(graph); - - var margins = 40; - var marginsX = 120; - - var width = graph.offsetWidth; - var height = graph.offsetHeight; - height = height - titleHeight - margins; - - //var xScale = d3.scaleLinear().range([minTime, maxTime]); - //var yScale = d3.scaleLinear().range([0, topActualScore]); - var originTime = (maxTime - minTime) / 60; - var xScale = d3.scaleLinear().range([marginsX, width - margins]); - xScale.domain([0, originTime]); - var yScale = d3.scaleLinear().range([height - margins, margins]); - yScale.domain([0, topActualScore]); - - graph = d3.select("#graph"); - graph.remove(); - graph = d3.select("#holding").append("svg") - .attr("width", width) - .attr("height", height); - //.attr("style", "background: white"); - - - //graph.append("g") - // .attr("transform", "translate(" + margins + ", 0)") - // .call(d3.axisLeft(yScale)) - // .style("stroke", "white");; - - var maxNumEntry = 10; - //var curEntry = 0; - var winningTeams = []; - for(entry in winners) { - var curEntry = entry; - if(curEntry >= maxNumEntry) { - break; - } - entry = teamnames[winners[entry].__hash__]; - winningTeams.push(entry); - //console.log(curEntry); - //console.log(entry); - - //var isTop = false; - //for(var x=0; x < maxNumEntry; x++) - //{ - // var teamhash = reverseTeam[entry]; - // if(winners[x].__hash__ == teamhash) - // { - // curEntry = x; - // isTop = true; - // break; - // } - //} - //if(!isTop) - //{ - // continue; - //} - - var curTeam = teamLines[entry]; - var lastEntry = curTeam[curTeam.length - 1]; - //curTeam.append() - curTeam.push([maxTime, lastEntry[1], lastEntry[2], lastEntry[3], lastEntry]); - var curLayer = graph.append("g"); - curLayer.selectAll("line") - .data(curTeam) - .enter() - .append("line") - .style("stroke", colorScale[curEntry * 2]) - .attr("stroke-width", 4) - .attr("class", "team_" + entry) - .style("z-index", maxNumEntry - curEntry) - .attr("x1", - function(d) { - return xScale((d[4][0] - minTime) / 60); - }) - .attr("x2", - function(d) { - return xScale((d[0] - minTime) / 60); - }) - .attr("y1", - function(d) { - return yScale(d[4][1]); - }) - .attr("y2", - function(d) { - return yScale(d[1]); - }) - .on("mouseover", handleMouseover) - .on("mouseout", handleMouseout); - - curLayer.selectAll("circle") - .data(curTeam) - .enter() - .append("circle") - .style("fill", colorScale[curEntry * 2]) - .style("z-index", maxNumEntry - curEntry) - .attr("class", "team_" + entry) - .attr("r", 5) - .attr("cx", - function(d) { - return xScale((d[0] - minTime) / 60); - }) - .attr("cy", - function(d) { - return yScale(d[1]); - }) - .on("mouseover", handleMouseoverCircle) - .on("mouseout", handleMouseoutCircle); - - curEntry++; - } - - var axisG = graph.append("g"); - axisG - .attr("transform", "translate(0," + (height - margins) + ")") - .call(d3.axisBottom(xScale)); - //.style("stroke", "white"); - axisG.selectAll("path").style("stroke", "white"); - axisG.selectAll("line").style("stroke", "white"); - axisG.selectAll("text").style("fill", "white"); - - graph.append("text") - .attr("text-anchor", "middle") - .attr("transform", "translate(" + (width / 2) + ", " + (height - margins / 8) + ")") - .style("fill", "white") - .text("Time (minutes)"); - - var legend = graph.append("g"); - var legendRowHeight = (height - margins) / 10; - legend.selectAll("rect") - .data(winningTeams) - .enter() - .append("rect") - .attr("class", function(d){ return "team_" + d; }) - .attr("fill", function(d, i){ return colorScale[i * 2]; }) - .style("z-index", function(d, i){ return i; }) - .attr("x", 0) - .attr("y", function(d, i){ return legendRowHeight * i; }) - .attr("height", legendRowHeight) - .attr("width", marginsX) - .on("mouseover", handleMouseoverLegend) - .on("mouseout", handleMouseoutLegend); - - legend.selectAll("text") - .data(winningTeams) - .enter() - .append("text") - //.attr("class", function(d){ return "team_" + d; }) - .attr("fill", "black") - .style("z-index", function(d, i){ return i; }) - .attr("dx", 0) - .attr("dy", function(d, i){ return legendRowHeight * (i + .5); }) - .text(function(d, i){ return i + ": " + d; }) - .attr("dominant-baseline", "central") - .style("pointer-events", "none"); - - //legend.append("g").selectAll("text") - // .data(winningTeams) - // .enter() - // .append("text") - // .attr("class", function(d){ return "team_" + d; }) - // .attr("fill", function(d, i){ return colorScale[i]; }) - // .style("z-index", function(d, i){ return i; }) - // .attr("dx", margins) - // .attr("dy", function(d, i){ return margins + legendRowHeight * (i); }) - // .text(function(d){ return d; }); - //.attr("dominant-baseline", "central"); - //.style("pointer-events", "none"); - - - function handleMouseover(d, i) { - d3.select("body").selectAll(".tooltip").remove(); - var curClass = d3.select(this).attr("class"); - d3.select("body").selectAll("." + curClass) - .style("stroke", "white") - .style("fill", "white"); - d3.select("body").selectAll("text") - .style("stroke-width", 0); - } - - function handleMouseout(d, i) { - d3.select("body").selectAll(".tooltip").remove(); - var curClass = d3.select(this).attr("class"); - var zIndex = d3.select(this).style("z-index"); - d3.select("body").selectAll("." + curClass) - .style("stroke", colorScale[(maxNumEntry - zIndex) * 2]) - .style("fill", colorScale[(maxNumEntry - zIndex) * 2]); - legend.selectAll("." + curClass) - .style("stroke", colorScale[(maxNumEntry - zIndex) * 2]) - .style("fill", colorScale[(maxNumEntry - zIndex) * 2]); - d3.select("body").selectAll("text") - .style("stroke-width", 0); - } - - var tooltipPadding = 10; - function handleMouseoverCircle(d, i) { - d3.select("body").selectAll(".tooltip").remove(); - var curClass = d3.select(this).attr("class"); - d3.select("body").selectAll("." + curClass) - .style("stroke", "white") - .style("fill", "white"); - d3.select("body").selectAll("text") - .style("stroke-width", 0); - - graph.append("g").append("text") - .attr("class", "tooltip") - .attr("text-anchor", "middle") - .style("fill", "red") - .style("stroke-width", -4) - .style("stroke", "black") - .style("font-weight", "bolder") - .style("font-size", "large") - .attr("dx", - function() { - return xScale((d[0] - minTime) / 60); - }) - .attr("dy", - function() { - return yScale(d[1]) - tooltipPadding; - }) - .text(function(){ return d[2] + " " + d[3]; }) - .style("pointer-events", "none"); - - } - - function handleMouseoutCircle(d, i) { - d3.select("body").selectAll(".tooltip").remove(); - var curClass = d3.select(this).attr("class"); - var zIndex = d3.select(this).style("z-index"); - d3.select("body").selectAll("." + curClass) - .style("stroke", colorScale[(maxNumEntry - zIndex) * 2]) - .style("fill", colorScale[(maxNumEntry - zIndex) * 2]); - legend.selectAll("." + curClass) - .style("stroke", colorScale[(maxNumEntry - zIndex) * 2]) - .style("fill", colorScale[(maxNumEntry - zIndex) * 2]); - d3.select("body").selectAll("text") - .style("stroke-width", 0); - } - - function handleMouseoverLegend(d, i) { - d3.select("body").selectAll(".tooltip").remove(); - var curClass = d3.select(this).attr("class"); - d3.select("body").selectAll("." + curClass) - .style("stroke", "white") - .style("fill", "white"); - d3.select("body").selectAll("text") - .style("stroke-width", 0); - } - - function handleMouseoutLegend(d, i) { - d3.select("body").selectAll(".tooltip").remove(); - var curClass = d3.select(this).attr("class"); - var zIndex = d3.select(this).style("z-index"); - d3.select("body").selectAll("." + curClass) - .style("stroke", colorScale[zIndex * 2]) - .style("fill", colorScale[zIndex * 2]); - legend.selectAll("." + curClass) - .style("stroke", colorScale[(zIndex) * 2]) - .style("fill", colorScale[(zIndex) * 2]); - d3.select("body").selectAll("text") - .style("stroke-width", 0); - } - - - } else if(mode == "original") { - // (100 / ncats) * (ncats / topActualScore); - var maxWidth = 100 / topActualScore; - for (var i in winners) { - var team = winners[i]; - var row = document.createElement("div"); - var ncat = 0; - for (var category in highscore) { - var catHigh = highscore[category]; - var catTeam = team[category] || 0; - var catPct = catTeam / catHigh; - var width = maxWidth * catPct; - - var bar = document.createElement("span"); - bar.classList.add("cat" + ncat); - bar.style.width = width + "%"; - bar.textContent = category + ": " + catTeam; - bar.title = bar.textContent; - - row.appendChild(bar); - ncat += 1; - } - - var te = document.createElement("span"); - te.classList.add("teamname"); - te.textContent = teamnames[team.__hash__]; - row.appendChild(te); - - element.appendChild(row); - } - } - if(mode == "total") { - var colorScale = d3.schemeCategory20; - - var numCats = 0; - for(entry in allQuestions) { - numCats++; - } - var maxWidth = Math.floor(100 / (0.0 + numCats)); - //console.log(maxWidth); - - for (var i in winners) { - var team = winners[i]; - var row = document.createElement("div"); - var ncat = 0; - for (var category in allQuestions) { - var catHigh = highscore[category]; - var catTeam = team[category] || 0; - var catPct = 0; - if (catHigh > 30000) { - catPct = (0.0 + Math.log(1+catTeam)) / (0.0 + Math.log(1+catHigh)); - } else { - catPct = (0.0 + catTeam) / (0.0 + catHigh); - } - var width = maxWidth * catPct; - var bar = document.createElement("span"); - - var numLeft = catHigh - catTeam; - - //bar.classList.add("cat" + ncat); - bar.style.backgroundColor = colorScale[ncat % 20]; - bar.style.color = "white"; - bar.style.width = width + "%"; - bar.textContent = category + ": " + catTeam; - bar.title = bar.textContent; - - row.appendChild(bar); - - ncat++; - - width = maxWidth * (1 - catPct); - if(width > 0) { - var noBar = document.createElement("span"); - //noBar.classList.add("cat" + ncat); - noBar.style.backgroundColor = colorScale[ncat % 20]; - noBar.style.width = width + "%"; - noBar.textContent = numLeft; - noBar.title = bar.textContent; - - row.appendChild(noBar); - } - ncat += 1; - } - - var te = document.createElement("span"); - te.classList.add("teamname"); - te.textContent = teamnames[team.__hash__]; - row.appendChild(te); - - element.appendChild(row); - } - } - } - - function once() { - loadJSON("points.json", update); - } - if (continuous) { - updateInterval = setInterval(once, interval); - } - once(); -} diff --git a/www/scoring.html b/www/scoring.html deleted file mode 100644 index e85dea4..0000000 --- a/www/scoring.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - About scoring - - - - - -

About scoring

- -
-

How we compute scores

- -

- The contest is made up of multiple categories. - Each category is worth one point toward the total score; - your team's score in a category is the fraction of the total points unlocked so far in that category. -

- -

- The team that has 30% of the points - in each of five categories has 1.5 points, whereas the team that - has 80% of the points in only one category has 0.8 points. It is - typically better to have a few points in many categories, than - many points in a few categories. -

- -

- When points are unlocked in a category, - every other team's score in that category goes down until they too score that point. - Unlike previous years, however, - unlocking points is the only way to reduce another team's score. -

- -

- There are two main ways to make points: puzzles - and tokens. Your contest may have other ways to make - points: these will either be automatic, or explained elsewhere. -

-
- - -
-

Puzzles

-

- Many of the categories are in the form of - multiple puzzles: for each puzzle presented, a - case-sensitive answer must be found to receive the amount of - points that puzzle is worth. Any team may answer any puzzle - question at any time. A new puzzle is revealed when a team - correctly answers the highest-valued puzzle in that category. -

-
- - -
-

Tokens

-

- Tokens are strings redeemable once for points. They take on - two forms: a single or multipoint token. A single point - token for the "example" category might look like this: -

- -
example:xylep-radar-nanox
- -

- A 42 point - token for the "example" category might look like this: -

- -
example:42:xihyp-ropar-nanix
- -

- Tokens are typically associated with "live" categories, such as a - network-based service or a treasure hunt. Tokens can be submitted - with the form on the welcome page, or you - can write your own script to automate token submission. -

- -

- Some tokens change periodically, typically once a minute. If you - find a token, it's worth looking in the same place again later to - see if the token changes. -

-
- - -
-

About time

-

- Many Capture The Flag contests attempt to reward teams who answer - quickly, by adding a "quick answer" bonus or by decaying point - values over time. Our contest doesn't work this way. -

-

- We want to focus on rewarding technical proficiency, allowing - skilled contestants to prove their worth independent of their - ability to hit F5 quickly. It is our hope that by providing - enough things to work on, quick-moving teams will emerge with more - points by solving lots of puzzles, while novice teams get a solid - benchmark against which to judge their technical skill level: you - don't have to make allowances for reaction time in comparing - scores. In addition, when the game infrastructure goes down—which - seems to happen a lot in anybody's CTF—there's no losing points - while the organizers struggle to get things back up. -

-
- -
- - - - - -
- - diff --git a/www/style.css b/www/style.css deleted file mode 100644 index d820e35..0000000 --- a/www/style.css +++ /dev/null @@ -1,261 +0,0 @@ -/* -Light blue: #96d1e3 -Off-white blue: #b9e0ef -Dark brown: #35170c -Light brown: #432115 -Tan: #e1caa5 -*/ - -@import "fonts/maven_pro.css"; - -html { - background: #35170c url(images/background.png) no-repeat center center fixed; - -webkit-background-size: cover; - -moz-background-size: cover; - -o-background-size: cover; - background-size: cover; -/* min-height: 100%;*/ - font-family: "Maven Pro", Ubuntu, sans-serif; - overflow-y: auto; -} - -h1, h2, h3 { - color: #AD6F15; - font-family: "Maven Pro", Ubuntu, sans-serif; - font-weight: bold; -} - -body > h1:first-child { - color: #96d1e3; - font-size: 3em; - border-radius: 0.2em; - padding: 0 0.3em; - text-align: center; - max-width: 66%; - margin: 0.5em auto; -} - -body > h1:first-child img { - max-width: 66%; -} - -.readme, pre { - background-color: #FFDAA3; - border-radius: 0.5em; -} - - - - - - -input { - font-family: "Maven Pro", Ubuntu, sans-serif; -} - -a { - color: #432115; - text-decoration: underline; -} - -a:hover { - color: #9E1336; -} - -a img { - border: 0px; -} - -pre { - border: solid #ddc 2px; - padding: 0.25em; - font-family: "Ubuntu Mono", monospace; - overflow: auto; -} - -code, kbd, samp { - font-family: "Ubuntu Mono", monospace; -} - - -th { - vertical-align: top; - text-align: center; -} -td { - vertical-align: top; - text-align: left; -} - -dt { - font-weight: bold; -} - -p { - line-height: 1.4em; - margin-bottom: 20px; -} - -hr { - border: 1px solid #ddc; -} - -#prompt { - color: #0E7450; - border-radius: 0.2em; -} - -#cli { - background: rgba(14, 116, 80, 0.2); - color: #00120C; - width: 100%; - border: 0px; - padding: 0.1em 0.1em; -} - -#readme img { - max-width: 100%; - transition: all .2s ease; -} - -#readme img:hover { - transform: scale(1.5); -} - -/**** Section ****/ - -section, nav, address { - color: #35170c; - max-width: 35em; - border-radius: 0.6em; - margin: 1em auto; - padding: 0.5em; -} - -section, address { - background: #e1caa5; -} - -/*** navigation bar ***/ - -nav { - background: #b9e0ef; -} - -nav h2 { - display: none; -} - -nav ul { - list-style: none; - text-align: center; - padding: 0; -} - -nav li { - display: inline; -} - -nav li a { - text-transform: lowercase; - font-size: 0.9em; -} - -nav li + li:before { - content: " | "; -} - -#sponsors { - background: #b9e0ef; - text-align: center; - opacity: 0.8; -} - -#sponsors img { - max-width: 20%; - max-height: 5em; -} - - -/**** Terminal ****/ - -#terminal { - padding: 10px; - max-width: 35em; - margin: 1em auto; - border-radius: 1em; - -} - -#terminal #output { - max-height: 20em; - overflow-y: scroll; -} - -#terminal #output::-webkit-scrollbar -{ - width: 0.7em; -} - -#terminal #output::-webkit-scrollbar-track -{ - border-radius: 0.7em; - background-color: rgba(173, 111, 21, 0.4); -} - -#terminal #output::-webkit-scrollbar-thumb -{ - border-radius: 0.7em; - background-color: #FFDAA3; - border: solid rgba(173, 111, 21, 0.4) 1px; -} - -/**** Scoreboard ****/ - -#scoreboard { - width: 100%; - clear: both; - background: rgba(25, 0, 6, 0.8); - border-radius: 2em; -} - -#scoreboard span { - font-size: 75%; - display: inline-block; - margin: 0; - border: 0; - overflow: hidden; - height: 2.2em; -} - -#scoreboard .teamname { - font-size: 133%; - color: white; - text-shadow: 0 0 0.2em black; - opacity: 0.8; - position: absolute; - right: 1em; - height: 1.1em; -} - -#scoreboard div * {white-space: nowrap;} -.cat0, .cat8, .cat16 {background-color: #a6cee3; color: black;} -.cat1, .cat9, .cat17 {background-color: #1f78b4; color: white;} -.cat2, .cat10, .cat18 {background-color: #b2df8a; color: black;} -.cat3, .cat11, .cat19 {background-color: #33a02c; color: white;} -.cat4, .cat12, .cat20 {background-color: #fb9a99; color: black;} -.cat5, .cat13, .cat21 {background-color: #e31a1c; color: white;} -.cat6, .cat14, .cat22 {background-color: #fdbf6f; color: black;} -.cat7, .cat15, .cat23 {background-color: #ff7f00; color: black;} - - -.wide { - max-width: inherit; -} - -.figure { - margin: 0.5em 1em; - float: right; - font-size: small; - text-align: center; -} diff --git a/www/terminal.js b/www/terminal.js deleted file mode 100644 index 12c5d37..0000000 --- a/www/terminal.js +++ /dev/null @@ -1,54 +0,0 @@ -var baud = 1200; - -function tx(element, text, baud_) { - var drawTimer; - baud_ = baud_ || baud; - - var sp = false; - function draw() { - c = text[0]; - if ((c == " ") || (c == "\n")) { - sp = true; - c = " "; - } else if (sp) { - c = " " + c; - sp = false; - } - element.textContent += c; - text = text.substr(1); - if (text == "") { - clearInterval(drawTimer); - return; - } - } - - // N81 uses 1 stop bit, and 1 parity bit. - // That works out to exactly 10 bits per byte. - msec = 10000 / baud_; - - drawTimer = setInterval(draw, msec); - draw(); -} - - -var outq = []; -var outTimer; - -function drawPar() { - oute = document.getElementById("output"); - outp = document.createElement("p"); - - oute.appendChild(outp); - tx(outp, outq.shift()); - if (outq.length == 0) { - clearInterval(outTimer); - } -} - -function output(par) { - outq = outq.concat(par); - if (! outTimer) { - outTimer = setInterval(drawPar, 150); - } -} -