├── README.md
├── static
├── favicon.ico
├── bundle
│ ├── ._jquery.min.js
│ ├── bundle.bemjson.js
│ ├── bundle.bemdecl.js
│ ├── bundle.html
│ └── bundle.deps.js
├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
├── bundle.html
├── js
│ ├── angular-rickshaw.coffee
│ ├── ws.coffee
│ ├── angular-rickshaw.js
│ ├── ws.js
│ └── vendor
│ │ ├── cubism.min.js
│ │ └── bootstrap.min.js
└── css
│ ├── rickshaw.css
│ ├── custom.css
│ ├── bootstrap-theme.min.css
│ ├── bootstrap-theme.css.map
│ └── bootstrap-theme.css
├── t.py
├── events.py
├── qrcode_emitter.py
├── rps.py
├── tank.py
├── users.py
├── midi_emitter.py
├── templates
└── index.jade
├── top.py
├── server.py
├── start.py
└── LICENSE.txt
/README.md:
--------------------------------------------------------------------------------
1 | There is a treasure hidden elsewhere
2 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex/opensourcestand/master/static/favicon.ico
--------------------------------------------------------------------------------
/t.py:
--------------------------------------------------------------------------------
1 | import zmq
2 |
3 | ctx = zmq.Context()
4 | s = ctx.socket(zmq.PUSH)
5 | s.bind('tcp://127.0.0.1:43000')
6 |
--------------------------------------------------------------------------------
/static/bundle/._jquery.min.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex/opensourcestand/master/static/bundle/._jquery.min.js
--------------------------------------------------------------------------------
/static/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex/opensourcestand/master/static/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/static/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex/opensourcestand/master/static/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/static/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex/opensourcestand/master/static/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/static/bundle/bundle.bemjson.js:
--------------------------------------------------------------------------------
1 | ({
2 | block: 'page',
3 | js: true,
4 | styles: [
5 | { elem: 'css', url: 'bundle/bundle.min.css' }
6 | ],
7 | scripts: [
8 | { elem: 'js', url: 'bundle/bundle.min.js' }
9 | ]
10 | })
11 |
--------------------------------------------------------------------------------
/static/bundle/bundle.bemdecl.js:
--------------------------------------------------------------------------------
1 | exports.blocks = [
2 | {
3 | "name": "page"
4 | },
5 | {
6 | "name": "page",
7 | "elems": [
8 | {
9 | "name": "css"
10 | }
11 | ]
12 | },
13 | {
14 | "name": "page",
15 | "elems": [
16 | {
17 | "name": "js"
18 | }
19 | ]
20 | }
21 | ];
22 |
--------------------------------------------------------------------------------
/static/bundle.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/bundle/bundle.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/events.py:
--------------------------------------------------------------------------------
1 |
2 | class Event(object):
3 | pass
4 |
5 | class MidiEvent(Event):
6 | def __init__(self, drum, url):
7 | self.drum = drum
8 | self.url = url
9 |
10 | def __str__(self):
11 | return '' % (self.drum, self.url)
12 |
13 | class QRCodeEvent(Event):
14 | def __init__(self, text):
15 | self.text = text
16 |
17 | def __str__(self):
18 | return '' % (self.text)
19 |
--------------------------------------------------------------------------------
/qrcode_emitter.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import serial
3 | import events
4 | import tornado
5 | import logging
6 |
7 | class Emitter(object):
8 | def __init__(self, state, ioloop):
9 | self.state = state
10 | self.ioloop = ioloop
11 | self.data = ''
12 |
13 | def on_data(self, fd, evs):
14 | char = self.scanner.read(1)
15 |
16 | if char == '\r':
17 | return
18 |
19 | if char == '\n':
20 | # http://yaconf.yandex.net/?1281377701
21 | userid = self.data.split('?')[1]
22 | ev = events.QRCodeEvent(userid)
23 | self.state.post_event(ev)
24 | self.data = ''
25 | return
26 |
27 | self.data += char
28 |
29 | def run(self, port, baudrate=9600):
30 | self.scanner = serial.Serial(port, baudrate)
31 | self.ioloop.add_handler(self.scanner.fileno(), self.on_data, tornado.ioloop.IOLoop.READ)
32 |
33 |
--------------------------------------------------------------------------------
/rps.py:
--------------------------------------------------------------------------------
1 | class RPSCounter(object):
2 | H4X0R = ['tom1', 'tom2', 'floor_tom', 'tom2', 'tom2', 'floor_tom', 'ride_edge']
3 |
4 | def __init__(self):
5 | self.hresult = False
6 | self.cleanup()
7 |
8 | def cleanup(self):
9 | self.counter = 0
10 | self.lsl = []
11 | self.h4x0r_list = []
12 |
13 | def update(self, ts):
14 | if self.lsl:
15 | while self.lsl and ts - self.lsl[0][0] > 1:
16 | self.lsl.pop(0)
17 |
18 | def add_event(self, ts, event):
19 | self.counter += 1
20 | self.lsl.append((ts, event))
21 | self.update(ts)
22 |
23 | self.h4x0r_list.append(event.drum)
24 | diff = len(self.h4x0r_list) - len(RPSCounter.H4X0R)
25 | if diff > 0:
26 | del self.h4x0r_list[:diff]
27 |
28 | if self.h4x0r_list == RPSCounter.H4X0R and not self.hresult:
29 | raise Exception("H4X0R")
30 |
31 | def current_rps(self, ts):
32 | self.update(ts)
33 | return len(self.lsl)
34 |
--------------------------------------------------------------------------------
/tank.py:
--------------------------------------------------------------------------------
1 | import os
2 | import zmq
3 | import logging
4 |
5 | class Tank(object):
6 | def __init__(self, host, port):
7 | self.host = host
8 | self.port = port
9 |
10 | def run(self):
11 | self.context = zmq.Context()
12 | self.sock = self.context.socket(zmq.PUSH)
13 | logging.info('binding to \'tcp://0.0.0.0:%s\'' % (self.port, ))
14 | self.sock.bind('tcp://0.0.0.0:%s' % (self.port, ))
15 |
16 | def start(self):
17 | logging.info('Starting tank')
18 | os.system("ssh %s /bin/bash -c ~/start_tank.sh" % (self.host, ))
19 |
20 | def check(self):
21 | logging.info('Checking tank')
22 | if not self.sock.poll(100, zmq.POLLOUT):
23 | raise Exception('Tank is not ready')
24 | #self.sock.send_json((0,), zmq.NOBLOCK)
25 |
26 | def stop(self):
27 | logging.info('Stopping tank')
28 | try:
29 | self.sock.send_json(('stop', ), zmq.NOBLOCK)
30 | except:
31 | logging.error('Tank is not responding')
32 |
33 | def fire(self, url, drum):
34 | logging.debug('Firing with drum %s to url %s' % (drum, url))
35 | self.sock.send_json([0, url, drum], zmq.NOBLOCK)
36 |
37 |
--------------------------------------------------------------------------------
/users.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | class User(object):
4 | def __init__(self, id, name):
5 | self.id = id
6 | self.name = name
7 | self.points = 0
8 | self.improvement = False
9 |
10 | def __str__(self):
11 | return '' % (self.id, self.name)
12 |
13 | class Userlist(object):
14 | def __init__(self):
15 | self.db = sqlite3.connect('users.db')
16 |
17 | def get_user(self, id):
18 | c = self.db.cursor()
19 | row = c.execute('SELECT id, name FROM users WHERE id = ?', (id, )).fetchone()
20 |
21 | if row:
22 | return User(row[0], row[1])
23 |
24 | raise KeyError('Unknown user')
25 |
26 | if __name__ == '__main__':
27 | users = Userlist()
28 | c = users.db.cursor()
29 |
30 | try:
31 | c.execute('CREATE TABLE users (id text PRIMARY KEY, name text, email text)')
32 | except:
33 | pass
34 |
35 | def cleanup():
36 | c.execute('DELETE FROM users')
37 | #cleanup()
38 | #for i in range(100):
39 | # c.execute('INSERT INTO users VALUES (?, ?, ?)', ('testuser%d' % i, 'Test User %d' %i, 'test email'))
40 | #users.db.commit()
41 |
42 | #print users.get_user('testuser1')
43 |
--------------------------------------------------------------------------------
/midi_emitter.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import midi
3 | import midi.sequencer as sequencer
4 | import threading
5 | import logging
6 | import events
7 |
8 | drums_mapping = {
9 | 48: 'tom1',
10 | 45: 'tom2',
11 | 43: 'floor_tom',
12 | 38: 'snare',
13 | 40: 'snare_rim',
14 | 46: 'hat',
15 | 26: 'hat_edge',
16 | 42: 'hat_closed',
17 | 22: 'hat_closed_edge',
18 | 54: 'crash',
19 | 55: 'crash_edge',
20 | 51: 'ride',
21 | 53: 'ride_edge',
22 | 36: 'bass',
23 | }
24 |
25 | #44: 'hat_pedal',
26 | urls_mapping = {
27 | 'tom1': '/',
28 | 'tom2': '/',
29 | 'floor_tom': '/',
30 | 'snare': '/cpu_burn',
31 | 'snare_rim': '/',
32 | 'hat': '/',
33 | 'hat_edge': '/',
34 | 'hat_closed': '/',
35 | 'hat_closed_edge': '/',
36 | 'hat_pedal': '/',
37 | 'crash': '/',
38 | 'crash_edge': '/',
39 | 'ride': '/',
40 | 'ride_edge': '/',
41 | 'bass': '/heavy',
42 | }
43 |
44 | class Emitter(object):
45 | def __init__(self, state):
46 | self.state = state
47 |
48 | def run(self, client, port):
49 | self.seq = sequencer.SequencerRead(sequencer_resolution=120)
50 | self.seq.subscribe_port(client, port)
51 |
52 | self.th = threading.Thread(target=Emitter.event_reader, args=(self,))
53 | self.th.daemon = True
54 | self.th.start()
55 |
56 | def event_reader(self):
57 | self.seq.start_sequencer()
58 | while True:
59 | event = self.seq.event_read()
60 | if isinstance(event, midi.NoteOnEvent):
61 | try:
62 | logging.debug('MIDI ALSA event: %s' % event)
63 | drum = drums_mapping[event.data[0]]
64 | ev = events.MidiEvent(drum, urls_mapping[drum])
65 | logging.debug('MIDI event: %s' % ev)
66 | self.state.post_event(ev)
67 | except:
68 | pass
69 |
70 |
--------------------------------------------------------------------------------
/templates/index.jade:
--------------------------------------------------------------------------------
1 | !!! 5
2 | html(lang="en")
3 | head
4 | meta(charset="utf-8")
5 | meta(http-equiv="X-UA-Compatible", content="IE=edge")
6 | meta(name="viewport", content="width=device-width, initial-scale=1")
7 | title Yandex.Tank online report
8 | link(rel="shortcut icon", href="static/favicon.ico", type="image/x-icon")
9 | link(rel="icon", href="static/favicon.ico", type="image/x-icon")
10 | link(rel="stylesheet", href="static/css/bootstrap.min.css")
11 | link(rel="stylesheet", href="static/css/bootstrap-theme.min.css")
12 | link(rel="stylesheet", href="static/css/rickshaw.css")
13 | link(rel="stylesheet", href="static/css/custom.css")
14 | script(src="static/js/vendor/socket.io.min.js")
15 | script(src="static/js/vendor/jquery.min.js")
16 | script(src="static/js/vendor/angular.min.js")
17 | script(src="static/js/vendor/bootstrap.min.js")
18 | script(src="static/js/vendor/d3.min.js")
19 | script(src="static/js/vendor/rickshaw.min.js")
20 | script(src="static/js/angular-rickshaw.js")
21 | script(src="static/js/ws.js")
22 | script(type="text/javascript")
23 | document.cached_data = {{cached_data}};
24 | body
25 | .app.container(ng-app="ng-tank-report", ng-controller="TankReport")
26 | h1.page-header Yandex.Tank online report
27 | #status {{!status}}
28 | #timings
29 | .panel.panel-default
30 | .panel-heading
31 | h3.panel-title {{!quantiles.name}}
32 | .panel-body
33 | rickshaw.panel-body(
34 | rickshaw-series="quantiles.series",
35 | rickshaw-options="quantiles.options",
36 | rickshaw-features="quantiles.features"
37 | )
38 | .panel.panel-default
39 | .panel-heading
40 | h3.panel-title {{!rps.name}}
41 | .panel-body
42 | rickshaw(
43 | rickshaw-series="rps.series",
44 | rickshaw-options="rps.options",
45 | rickshaw-features="rps.features"
46 | )
47 | #monitoring
48 | .host(ng-repeat="host in monitoringData")
49 | h3 {{!host.hostname}}
50 | .panel.panel-default(ng-repeat="group in host.groups")
51 | .panel-heading
52 | h3.panel-title {{!group.name}}
53 | .panel-body
54 | rickshaw(
55 | rickshaw-series="group.series",
56 | rickshaw-options="group.options",
57 | rickshaw-features="group.features"
58 | )
59 |
--------------------------------------------------------------------------------
/top.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | class Top(object):
4 | def __init__(self):
5 | self.db = sqlite3.connect('top.db')
6 |
7 | def add_result(self, user, points):
8 | user.points = points
9 | user.improvement = True
10 | c = self.db.cursor()
11 |
12 | c.execute('INSERT INTO attempts VALUES(datetime("now"), ?, ?)', (user.id, points))
13 |
14 | row = c.execute('SELECT userid, points FROM rating WHERE userid = ?', (user.id, )).fetchone()
15 | if not row or row[1] < points:
16 | c.execute('INSERT OR REPLACE INTO rating VALUES (datetime("now"), ?, ?, ?)', (user.id, user.name, points))
17 | elif row:
18 | user.points = row[1]
19 | user.improvement = False
20 |
21 | self.db.commit()
22 |
23 | def add_hresult(self, user):
24 | c = self.db.cursor()
25 | row = c.execute('SELECT * from hrating').fetchone()
26 | if row:
27 | return row
28 | c.execute('INSERT INTO hrating VALUES (datetime("now"), ?)', (user.id,))
29 | self.db.commit()
30 | return None
31 |
32 | def get_hresults(self):
33 | c = self.db.cursor()
34 | return c.execute('SELECT * from hrating').fetchone()
35 |
36 | def get_results(self, user):
37 | c = self.db.cursor()
38 |
39 | rating = []
40 | place = 0
41 | found = False
42 |
43 | for row in c.execute('SELECT date, userid, username, points FROM rating ORDER BY points DESC'):
44 | place += 1
45 | rec = dict(zip(('date', 'userid', 'user', 'points'), row))
46 |
47 | if place > 10:
48 | if found or user is None:
49 | break
50 |
51 | if rec['userid'] != user.id:
52 | continue
53 |
54 | rec['place'] = place
55 | rec['current'] = False
56 |
57 | if user and rec['userid'] == user.id:
58 | rec['current'] = True
59 | rec['improvement'] = user.improvement
60 | found = True
61 |
62 | rating.append(rec)
63 |
64 | return rating
65 |
66 |
67 | if __name__ == '__main__':
68 | top = Top()
69 | c = top.db.cursor()
70 |
71 | try:
72 | c.execute('CREATE TABLE rating (date text, userid text PRIMARY KEY, username text, points integer)')
73 | except:
74 | pass
75 |
76 | try:
77 | c.execute('CREATE TABLE hrating (date text, userid text)')
78 | except:
79 | pass
80 |
81 | try:
82 | c.execute('CREATE TABLE attempts (date text, userid test, points integer)')
83 | except:
84 | pass
85 |
86 |
87 | def cleanup():
88 | c.execute('DELETE FROM rating')
89 | c.execute('DELETE FROM hrating')
90 | c.execute('DELETE FROM attempts')
91 | #cleanup()
92 | #for i in range(100):
93 | # top.add_result('testuser%d' % i, 'Test User %d' %i, 100 * i)
94 |
95 | #from pprint import pprint
96 | #pprint(top.get_results('testuser'))
97 |
98 | #c.execute('DELETE FROM hrating')
99 | #print c.execute('SELECT * from hrating').fetchone()
100 | #top.db.commit()
101 | #print top.add_hresult('testuser')
102 |
--------------------------------------------------------------------------------
/static/js/angular-rickshaw.coffee:
--------------------------------------------------------------------------------
1 | ###*
2 | Based on https://github.com/ngyewch/angular-rickshaw
3 | ###
4 | "use strict"
5 |
6 | angular.module("angular-rickshaw", []).directive "rickshaw", ($compile) ->
7 | restrict: "EA"
8 | scope:
9 | options: "=rickshawOptions"
10 | series: "=rickshawSeries"
11 | features: "=rickshawFeatures"
12 |
13 |
14 | # replace: true,
15 | link: (scope, element, attrs) ->
16 | getSettings = (el) ->
17 | settings = angular.copy(scope.options)
18 | settings.element = el
19 | settings.series = scope.series
20 | settings
21 | update = ->
22 | mainEl = angular.element(element)
23 | mainEl.append graphEl
24 | mainEl.empty()
25 | graphEl = $compile("
")(scope)
26 | mainEl.append graphEl
27 | settings = getSettings(graphEl[0])
28 | scope.graph = new Rickshaw.Graph(settings)
29 | if scope.features and scope.features.hover
30 | hoverConfig = graph: scope.graph
31 | hoverConfig.xFormatter = scope.features.hover.xFormatter
32 | hoverConfig.yFormatter = scope.features.hover.yFormatter
33 | hoverConfig.formatter = scope.features.hover.formatter
34 | hoverDetail = new Rickshaw.Graph.HoverDetail(hoverConfig)
35 | if scope.features and scope.features.palette
36 | palette = new Rickshaw.Color.Palette(scheme: scope.features.palette)
37 | i = 0
38 |
39 | while i < settings.series.length
40 | settings.series[i].color = palette.color()
41 | i++
42 | scope.graph.render()
43 | if scope.features and scope.features.xAxis
44 | xAxisConfig = graph: scope.graph
45 | if scope.features.xAxis.timeUnit
46 | time = new Rickshaw.Fixtures.Time()
47 | xAxisConfig.timeUnit = time.unit(scope.features.xAxis.timeUnit)
48 | xAxis = new Rickshaw.Graph.Axis.Time(xAxisConfig)
49 | xAxis.render()
50 | if scope.features and scope.features.yAxis
51 | yAxisConfig = graph: scope.graph
52 | yAxisConfig.tickFormat = Rickshaw.Fixtures.Number[scope.features.yAxis.tickFormat] if scope.features.yAxis.tickFormat
53 | yAxis = new Rickshaw.Graph.Axis.Y(yAxisConfig)
54 | yAxis.render()
55 | if scope.features and scope.features.legend
56 | legendEl = $compile("
")(scope)
57 | mainEl.append legendEl
58 | legend = new Rickshaw.Graph.Legend(
59 | graph: scope.graph
60 | element: legendEl[0]
61 | )
62 | if scope.features.legend.toggle
63 | shelving = new Rickshaw.Graph.Behavior.Series.Toggle(
64 | graph: scope.graph
65 | legend: legend
66 | )
67 | if scope.features.legend.highlight
68 | highlighter = new Rickshaw.Graph.Behavior.Series.Highlight(
69 | graph: scope.graph
70 | legend: legend
71 | )
72 | return
73 | scope.graph = undefined
74 | scope.$watch "options", (newValue, oldValue) ->
75 | update() unless angular.equals(newValue, oldValue)
76 | return
77 |
78 | scope.$watch "series", (newValue, oldValue) ->
79 | update() unless angular.equals(newValue, oldValue)
80 | return
81 |
82 | scope.$watch "features", (newValue, oldValue) ->
83 | update() unless angular.equals(newValue, oldValue)
84 | return
85 |
86 | scope.$on "DataUpdated", () ->
87 | scope.graph.update()
88 |
89 | update()
90 |
91 | controller: ($scope, $element, $attrs) ->
92 |
--------------------------------------------------------------------------------
/static/bundle/bundle.deps.js:
--------------------------------------------------------------------------------
1 | exports.deps = [
2 | {
3 | "block": "i-bem"
4 | },
5 | {
6 | "block": "i-bem",
7 | "elem": "internal"
8 | },
9 | {
10 | "block": "inherit"
11 | },
12 | {
13 | "block": "identify"
14 | },
15 | {
16 | "block": "next-tick"
17 | },
18 | {
19 | "block": "objects"
20 | },
21 | {
22 | "block": "functions"
23 | },
24 | {
25 | "block": "events"
26 | },
27 | {
28 | "block": "i-bem",
29 | "mod": "init"
30 | },
31 | {
32 | "block": "socket"
33 | },
34 | {
35 | "block": "i-bem",
36 | "elem": "dom"
37 | },
38 | {
39 | "block": "jquery"
40 | },
41 | {
42 | "block": "loader"
43 | },
44 | {
45 | "block": "loader",
46 | "mod": "type"
47 | },
48 | {
49 | "block": "jquery",
50 | "elem": "config"
51 | },
52 | {
53 | "block": "ua"
54 | },
55 | {
56 | "block": "dom"
57 | },
58 | {
59 | "block": "i-bem",
60 | "elem": "dom",
61 | "mod": "init"
62 | },
63 | {
64 | "block": "page",
65 | "elem": "css"
66 | },
67 | {
68 | "block": "page",
69 | "elem": "js"
70 | },
71 | {
72 | "block": "chart"
73 | },
74 | {
75 | "block": "user"
76 | },
77 | {
78 | "block": "user",
79 | "mod": "active"
80 | },
81 | {
82 | "block": "user",
83 | "elem": "info"
84 | },
85 | {
86 | "block": "user",
87 | "elem": "level"
88 | },
89 | {
90 | "block": "user",
91 | "elem": "level-star"
92 | },
93 | {
94 | "block": "user",
95 | "elem": "name"
96 | },
97 | {
98 | "block": "user",
99 | "elem": "place"
100 | },
101 | {
102 | "block": "welcome"
103 | },
104 | {
105 | "block": "welcome",
106 | "mod": "countdown"
107 | },
108 | {
109 | "block": "welcome",
110 | "elem": "call-to-action"
111 | },
112 | {
113 | "block": "welcome",
114 | "elem": "image"
115 | },
116 | {
117 | "block": "image"
118 | },
119 | {
120 | "block": "welcome",
121 | "elem": "text"
122 | },
123 | {
124 | "block": "welcome",
125 | "elem": "time-to-ready"
126 | },
127 | {
128 | "block": "shooting"
129 | },
130 | {
131 | "block": "shooting",
132 | "elem": "bullets"
133 | },
134 | {
135 | "block": "shooting",
136 | "elem": "scores"
137 | },
138 | {
139 | "block": "shooting",
140 | "elem": "timer"
141 | },
142 | {
143 | "block": "page",
144 | "elem": "wrap"
145 | },
146 | {
147 | "block": "i-bem",
148 | "mod": "init",
149 | "val": "auto"
150 | },
151 | {
152 | "block": "i-bem",
153 | "elem": "dom",
154 | "mod": "init",
155 | "val": "auto"
156 | },
157 | {
158 | "block": "loader",
159 | "mod": "type",
160 | "val": "js"
161 | },
162 | {
163 | "block": "user",
164 | "mod": "active",
165 | "val": true
166 | },
167 | {
168 | "block": "welcome",
169 | "mod": "countdown",
170 | "val": true
171 | },
172 | {
173 | "block": "page"
174 | }
175 | ];
176 |
--------------------------------------------------------------------------------
/static/js/ws.coffee:
--------------------------------------------------------------------------------
1 | app = angular.module("ng-tank-report", ["angular-rickshaw"])
2 |
3 | collect_subtree = (storage, subtree, ts) ->
4 | for key, node of subtree
5 | if typeof node is 'number' or typeof node is 'array'
6 | storage[key].push
7 | x: ts
8 | y: node
9 | else
10 | collect_subtree(storage[key], node, ts)
11 |
12 | app.controller "TankReport", ($scope, $element) ->
13 | $scope.status = "Disconnected"
14 | $scope.data = document.cached_data.data
15 | $scope.uuid = document.cached_data.uuid
16 | $scope.updateData = (tankData) ->
17 | for ts, storages of tankData
18 | for storage, data of storages
19 | collect_subtree $scope.data[storage], data, +ts
20 | $scope.$broadcast 'DataUpdated'
21 | $scope.buildSeries = () ->
22 | if $scope.data.responses and $scope.data.responses.overall
23 | overallData = $scope.data.responses.overall
24 | else
25 | overallData = {}
26 | setTimeout((() -> location.reload(true)), 3000)
27 | areaGraphs = ['CPU', 'Memory']
28 | $scope.monitoringData = (
29 | ({
30 | hostname: hostname
31 | groups: ({
32 | name: groupName
33 | features:
34 | palette: 'spectrum14'
35 | hover: {}
36 | xAxis: {}
37 | yAxis: {}
38 | legend:
39 | toggle: true
40 | highlight: true
41 | options:
42 | renderer: if groupName in areaGraphs then 'area' else 'line'
43 | series: ({
44 | name: name
45 | data: data
46 | } for name, data of series)
47 | } for groupName, series of groups)
48 | } for hostname, groups of $scope.data.monitoring)
49 | )
50 | $scope.quantiles =
51 | name: "Response time quantiles"
52 | features:
53 | palette: 'classic9'
54 | hover: {}
55 | xAxis: {}
56 | yAxis: {}
57 | legend:
58 | toggle: true
59 | highlight: true
60 | options:
61 | renderer: 'area'
62 | stack: false
63 | height: $element[0].offsetHeight - 45 - 62
64 | series: ({
65 | name: name
66 | data: data
67 | } for name, data of overallData.quantiles).sort (a, b) ->
68 | return if parseFloat(a.name) <= parseFloat(b.name) then 1 else -1
69 | $scope.rps =
70 | name: "Responses per second"
71 | features:
72 | palette: 'spectrum14'
73 | hover: {}
74 | xAxis: {}
75 | yAxis: {}
76 | legend:
77 | toggle: true
78 | highlight: true
79 | options:
80 | renderer: 'line'
81 | series: [
82 | name: 'RPS'
83 | data: overallData.RPS
84 | ]
85 |
86 | $scope.buildSeries()
87 |
88 | conn = new io.connect("http://#{window.location.host}",
89 | 'reconnection limit' : 1000
90 | 'max reconnection attempts' : 'Infinity'
91 | )
92 | setInterval((
93 | () ->conn.emit('heartbeat')
94 | ), 3000)
95 | conn.on 'connect', () =>
96 | console.log("Connection opened...")
97 | $scope.status = "Connected"
98 |
99 | $scope.$apply()
100 |
101 | conn.on 'disconnect', () =>
102 | console.log("Connection closed...")
103 | $scope.status = "Disonnected"
104 | $scope.$apply()
105 | conn.on 'reload', () =>
106 | location.reload(true)
107 | conn.on 'message', (msg) =>
108 | tankData = JSON.parse msg
109 | if tankData.uuid and $scope.uuid != tankData.uuid
110 | location.reload(true)
111 | else
112 | $scope.updateData(tankData.data)
113 |
--------------------------------------------------------------------------------
/server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import logging
4 | import tornado.ioloop
5 | import tornado.web
6 | import os.path
7 | import json
8 | import uuid
9 | from tornado import template
10 | from pyjade.ext.tornado import patch_tornado
11 | patch_tornado()
12 |
13 | from tornadio2 import SocketConnection, TornadioRouter, SocketServer, event
14 |
15 | from threading import Thread
16 |
17 |
18 | class Client(SocketConnection):
19 | CONNECTIONS = set()
20 |
21 | def on_open(self, info):
22 | #print 'Client connected'
23 | self.CONNECTIONS.add(self)
24 | self.emit('event', {'data': {'state': 0}})
25 |
26 | def on_message(self, msg):
27 | print 'Got', msg
28 |
29 | def on_close(self):
30 | #print 'Client disconnected'
31 | self.CONNECTIONS.remove(self)
32 |
33 | @event('heartbeat')
34 | def on_heartbeat(self):
35 | pass
36 |
37 | class MainHandler(tornado.web.RequestHandler):
38 | def initialize(self, template, reportUUID, state):
39 | self.template = template
40 | self.reportUUID = reportUUID
41 | self.state = state
42 |
43 | def get(self):
44 | if self.state is not None:
45 | cached_data = {
46 | 'data': self.state.get_current_state(),
47 | 'uuid': self.reportUUID,
48 | }
49 | else:
50 | cached_data = {
51 | 'data':{},
52 | 'uuid': self.reportUUID,
53 | }
54 | self.render(self.template, cached_data=json.dumps(cached_data))
55 |
56 | class JsonHandler(tornado.web.RequestHandler):
57 | def initialize(self, reportUUID, state):
58 | self.reportUUID = reportUUID
59 | self.state = state
60 |
61 | def get(self):
62 | if self.state is not None:
63 | cached_data = {
64 | 'data': self.get_data(),
65 | 'uuid': self.reportUUID,
66 | }
67 | else:
68 | cached_data = {
69 | 'data':{},
70 | 'uuid': self.reportUUID,
71 | }
72 | self.set_status(200)
73 | self.set_header("Content-type", "application/json")
74 | self.finish(json.dumps(cached_data))
75 |
76 | def get_data(self):
77 | raise Exception('Not implemented')
78 |
79 | class DataHandler(JsonHandler):
80 | def get_data(self):
81 | return self.state.get_current_state()
82 |
83 | class ResultsHandler(JsonHandler):
84 | def get_data(self):
85 | return self.state.get_results()
86 |
87 |
88 | class TopServer(object):
89 | def __init__(self, state):
90 | router = TornadioRouter(Client)
91 | self.reportUUID = uuid.uuid4().hex
92 | self.app = tornado.web.Application(
93 | router.apply_routes([
94 | (r"/", MainHandler, dict(template='index.jade', reportUUID=self.reportUUID, state=state)),
95 | (r"/data\.json$", DataHandler, dict(reportUUID=self.reportUUID, state=state)),
96 | (r"/toplist\.json$", ResultsHandler, dict(reportUUID=self.reportUUID, state=state)),
97 | ]),
98 | template_path=os.path.join(os.path.dirname(__file__), "templates"),
99 | static_path=os.path.join(os.path.dirname(__file__), "static"),
100 | debug=True,
101 | )
102 |
103 | def run(self, ioloop):
104 | self.server = SocketServer(self.app, io_loop=ioloop, auto_start=False)
105 |
106 | def send(self, data):
107 | for connection in Client.CONNECTIONS:
108 | ev = {}
109 | ev['uuid'] = self.reportUUID
110 | ev['data'] = data
111 | #print "Sending data to client ", connection
112 | connection.emit('event', ev)
113 |
114 | def reload(self):
115 | for connection in Client.CONNECTIONS:
116 | connection.emit('reload')
117 |
--------------------------------------------------------------------------------
/static/js/angular-rickshaw.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | Based on https://github.com/ngyewch/angular-rickshaw
4 | */
5 |
6 | (function() {
7 | "use strict";
8 | angular.module("angular-rickshaw", []).directive("rickshaw", function($compile) {
9 | return {
10 | restrict: "EA",
11 | scope: {
12 | options: "=rickshawOptions",
13 | series: "=rickshawSeries",
14 | features: "=rickshawFeatures"
15 | },
16 | link: function(scope, element, attrs) {
17 | var getSettings, update;
18 | getSettings = function(el) {
19 | var settings;
20 | settings = angular.copy(scope.options);
21 | settings.element = el;
22 | settings.series = scope.series;
23 | return settings;
24 | };
25 | update = function() {
26 | var graphEl, highlighter, hoverConfig, hoverDetail, i, legend, legendEl, mainEl, palette, settings, shelving, time, xAxis, xAxisConfig, yAxis, yAxisConfig;
27 | mainEl = angular.element(element);
28 | mainEl.append(graphEl);
29 | mainEl.empty();
30 | graphEl = $compile("
")(scope);
31 | mainEl.append(graphEl);
32 | settings = getSettings(graphEl[0]);
33 | scope.graph = new Rickshaw.Graph(settings);
34 | if (scope.features && scope.features.hover) {
35 | hoverConfig = {
36 | graph: scope.graph
37 | };
38 | hoverConfig.xFormatter = scope.features.hover.xFormatter;
39 | hoverConfig.yFormatter = scope.features.hover.yFormatter;
40 | hoverConfig.formatter = scope.features.hover.formatter;
41 | hoverDetail = new Rickshaw.Graph.HoverDetail(hoverConfig);
42 | }
43 | if (scope.features && scope.features.palette) {
44 | palette = new Rickshaw.Color.Palette({
45 | scheme: scope.features.palette
46 | });
47 | i = 0;
48 | while (i < settings.series.length) {
49 | settings.series[i].color = palette.color();
50 | i++;
51 | }
52 | }
53 | scope.graph.render();
54 | if (scope.features && scope.features.xAxis) {
55 | xAxisConfig = {
56 | graph: scope.graph
57 | };
58 | if (scope.features.xAxis.timeUnit) {
59 | time = new Rickshaw.Fixtures.Time();
60 | xAxisConfig.timeUnit = time.unit(scope.features.xAxis.timeUnit);
61 | }
62 | xAxis = new Rickshaw.Graph.Axis.Time(xAxisConfig);
63 | xAxis.render();
64 | }
65 | if (scope.features && scope.features.yAxis) {
66 | yAxisConfig = {
67 | graph: scope.graph
68 | };
69 | if (scope.features.yAxis.tickFormat) {
70 | yAxisConfig.tickFormat = Rickshaw.Fixtures.Number[scope.features.yAxis.tickFormat];
71 | }
72 | yAxis = new Rickshaw.Graph.Axis.Y(yAxisConfig);
73 | yAxis.render();
74 | }
75 | if (scope.features && scope.features.legend) {
76 | legendEl = $compile("
")(scope);
77 | mainEl.append(legendEl);
78 | legend = new Rickshaw.Graph.Legend({
79 | graph: scope.graph,
80 | element: legendEl[0]
81 | });
82 | if (scope.features.legend.toggle) {
83 | shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
84 | graph: scope.graph,
85 | legend: legend
86 | });
87 | }
88 | if (scope.features.legend.highlight) {
89 | highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
90 | graph: scope.graph,
91 | legend: legend
92 | });
93 | }
94 | }
95 | };
96 | scope.graph = void 0;
97 | scope.$watch("options", function(newValue, oldValue) {
98 | if (!angular.equals(newValue, oldValue)) {
99 | update();
100 | }
101 | });
102 | scope.$watch("series", function(newValue, oldValue) {
103 | if (!angular.equals(newValue, oldValue)) {
104 | update();
105 | }
106 | });
107 | scope.$watch("features", function(newValue, oldValue) {
108 | if (!angular.equals(newValue, oldValue)) {
109 | update();
110 | }
111 | });
112 | scope.$on("DataUpdated", function() {
113 | return scope.graph.update();
114 | });
115 | return update();
116 | },
117 | controller: function($scope, $element, $attrs) {}
118 | };
119 | });
120 |
121 | }).call(this);
122 |
--------------------------------------------------------------------------------
/static/js/ws.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var app, collect_subtree,
3 | __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
4 |
5 | app = angular.module("ng-tank-report", ["angular-rickshaw"]);
6 |
7 | collect_subtree = function(storage, subtree, ts) {
8 | var key, node, _results;
9 | _results = [];
10 | for (key in subtree) {
11 | node = subtree[key];
12 | if (typeof node === 'number' || typeof node === 'array') {
13 | _results.push(storage[key].push({
14 | x: ts,
15 | y: node
16 | }));
17 | } else {
18 | _results.push(collect_subtree(storage[key], node, ts));
19 | }
20 | }
21 | return _results;
22 | };
23 |
24 | app.controller("TankReport", function($scope, $element) {
25 | var conn;
26 | $scope.status = "Disconnected";
27 | $scope.data = document.cached_data.data;
28 | $scope.uuid = document.cached_data.uuid;
29 | $scope.updateData = function(tankData) {
30 | var data, storage, storages, ts;
31 | for (ts in tankData) {
32 | storages = tankData[ts];
33 | for (storage in storages) {
34 | data = storages[storage];
35 | collect_subtree($scope.data[storage], data, +ts);
36 | }
37 | }
38 | return $scope.$broadcast('DataUpdated');
39 | };
40 | $scope.buildSeries = function() {
41 | var areaGraphs, data, groupName, groups, hostname, name, overallData, series;
42 | if ($scope.data.responses && $scope.data.responses.overall) {
43 | overallData = $scope.data.responses.overall;
44 | } else {
45 | overallData = {};
46 | setTimeout((function() {
47 | return location.reload(true);
48 | }), 3000);
49 | }
50 | areaGraphs = ['CPU', 'Memory'];
51 | $scope.monitoringData = (function() {
52 | var _ref, _results;
53 | _ref = $scope.data.monitoring;
54 | _results = [];
55 | for (hostname in _ref) {
56 | groups = _ref[hostname];
57 | _results.push({
58 | hostname: hostname,
59 | groups: (function() {
60 | var _results1;
61 | _results1 = [];
62 | for (groupName in groups) {
63 | series = groups[groupName];
64 | _results1.push({
65 | name: groupName,
66 | features: {
67 | palette: 'spectrum14',
68 | hover: {},
69 | xAxis: {},
70 | yAxis: {},
71 | legend: {
72 | toggle: true,
73 | highlight: true
74 | }
75 | },
76 | options: {
77 | renderer: __indexOf.call(areaGraphs, groupName) >= 0 ? 'area' : 'line'
78 | },
79 | series: (function() {
80 | var _results2;
81 | _results2 = [];
82 | for (name in series) {
83 | data = series[name];
84 | _results2.push({
85 | name: name,
86 | data: data
87 | });
88 | }
89 | return _results2;
90 | })()
91 | });
92 | }
93 | return _results1;
94 | })()
95 | });
96 | }
97 | return _results;
98 | })();
99 | $scope.quantiles = {
100 | name: "Response time quantiles",
101 | features: {
102 | palette: 'classic9',
103 | hover: {},
104 | xAxis: {},
105 | yAxis: {},
106 | legend: {
107 | toggle: true,
108 | highlight: true
109 | }
110 | },
111 | options: {
112 | renderer: 'area',
113 | stack: false,
114 | height: $element[0].offsetHeight - 45 - 62
115 | },
116 | series: ((function() {
117 | var _ref, _results;
118 | _ref = overallData.quantiles;
119 | _results = [];
120 | for (name in _ref) {
121 | data = _ref[name];
122 | _results.push({
123 | name: name,
124 | data: data
125 | });
126 | }
127 | return _results;
128 | })()).sort(function(a, b) {
129 | if (parseFloat(a.name) <= parseFloat(b.name)) {
130 | return 1;
131 | } else {
132 | return -1;
133 | }
134 | })
135 | };
136 | return $scope.rps = {
137 | name: "Responses per second",
138 | features: {
139 | palette: 'spectrum14',
140 | hover: {},
141 | xAxis: {},
142 | yAxis: {},
143 | legend: {
144 | toggle: true,
145 | highlight: true
146 | }
147 | },
148 | options: {
149 | renderer: 'line'
150 | },
151 | series: [
152 | {
153 | name: 'RPS',
154 | data: overallData.RPS
155 | }
156 | ]
157 | };
158 | };
159 | $scope.buildSeries();
160 | conn = new io.connect("http://" + window.location.host, {
161 | 'reconnection limit': 1000,
162 | 'max reconnection attempts': 'Infinity'
163 | });
164 | setInterval((function() {
165 | return conn.emit('heartbeat');
166 | }), 3000);
167 | conn.on('connect', (function(_this) {
168 | return function() {
169 | console.log("Connection opened...");
170 | $scope.status = "Connected";
171 | return $scope.$apply();
172 | };
173 | })(this));
174 | conn.on('disconnect', (function(_this) {
175 | return function() {
176 | console.log("Connection closed...");
177 | $scope.status = "Disonnected";
178 | return $scope.$apply();
179 | };
180 | })(this));
181 | conn.on('reload', (function(_this) {
182 | return function() {
183 | return location.reload(true);
184 | };
185 | })(this));
186 | return conn.on('message', (function(_this) {
187 | return function(msg) {
188 | var tankData;
189 | tankData = JSON.parse(msg);
190 | if (tankData.uuid && $scope.uuid !== tankData.uuid) {
191 | return location.reload(true);
192 | } else {
193 | return $scope.updateData(tankData.data);
194 | }
195 | };
196 | })(this));
197 | });
198 |
199 | }).call(this);
200 |
--------------------------------------------------------------------------------
/start.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | import os
4 | import server
5 | import tornado
6 | import events
7 | import rps
8 | import top
9 | import tank
10 | import users
11 | import midi_emitter
12 | import qrcode_emitter
13 | from tornado import ioloop
14 | from tornado import options
15 | import logging
16 |
17 |
18 | class State(object):
19 | RESULTS=0
20 | GREETINGS=1
21 | COUNTDOWN=2
22 | ACTION=3
23 | HRESULTS=4
24 |
25 | COUNTDOWN_TIME = 3
26 | ACTION_TIME = 60
27 |
28 |
29 | def __init__(self, ioloop):
30 | self.ioloop = ioloop
31 | self.serv = server.TopServer(self)
32 | #self.tank = tank.Tank(options.options.tank, 43000)
33 | self.tank = tank.Tank('192.168.1.2', 43000)
34 | self.state = State.RESULTS
35 | self.user = None
36 | self.rps = rps.RPSCounter()
37 | self.top = top.Top()
38 | self.users = users.Userlist()
39 |
40 | self.timer_counter = None
41 | self.timer_fn = None
42 | self.timer_cb = tornado.ioloop.PeriodicCallback(self.timer, 1000, self.ioloop)
43 |
44 |
45 | def get_current_state(self):
46 | return {'state': self.state,
47 | 'user': self.user.name if self.user else None,
48 | 'timer': self.timer_counter,
49 | 'rps': self.rps.current_rps(self.ioloop.time()),
50 | 'points': self.rps.counter}
51 |
52 |
53 | def get_results(self):
54 | return self.top.get_results(self.user)
55 |
56 | def run(self):
57 | self.timer_cb.start()
58 | self.serv.run(self.ioloop)
59 | self.tank.run()
60 | self.rps.hresult = self.top.get_hresults()
61 | self.ioloop.start()
62 |
63 |
64 | def greetings(self, event):
65 | if (self.state != State.RESULTS):
66 | raise Exception('Incorrect state transcision!')
67 |
68 | # TODO: get user name from QRCode text
69 | self.user = self.users.get_user(event.text)
70 | self.state = State.GREETINGS
71 | logging.info('Hello, %s' % self.user)
72 | self.serv.send(self.get_current_state())
73 | self.rps.cleanup()
74 |
75 |
76 | def countdown(self):
77 | if (self.state != State.GREETINGS):
78 | raise Exception('Incorrect state transcision!')
79 |
80 | self.state = State.COUNTDOWN
81 | logging.info('Prepare, %s' % self.user)
82 | self.serv.send(self.get_current_state())
83 | self.timer_counter = State.COUNTDOWN_TIME
84 | self.timer_fn = State.tank_check
85 | self.tank.start()
86 |
87 |
88 | def tank_check(self):
89 | logging.info('Tank check')
90 | try:
91 | self.tank.check()
92 | self.action()
93 | except:
94 | logging.info('Tank check failed')
95 | self.timer_counter = 1
96 | self.timer_fn = State.tank_check
97 |
98 |
99 | def action(self):
100 | if (self.state != State.COUNTDOWN):
101 | raise Exception('Incorrect state transcision!')
102 |
103 | self.state = State.ACTION
104 | logging.info('Go, %s' % self.user)
105 | self.serv.send(self.get_current_state())
106 | self.timer_counter = State.ACTION_TIME
107 | self.timer_fn = State.results
108 |
109 |
110 | def results(self):
111 | if (self.state != State.ACTION) and (self.state != state.HRESULTS):
112 | raise Exception('Incorrect state transcision!')
113 |
114 | self.tank.stop()
115 | self.state = State.RESULTS
116 | self.serv.send(self.get_current_state())
117 | logging.info('Resuts for %s' % self.user)
118 | logging.info('Points earned: %d' % self.rps.counter)
119 | self.top.add_result(self.user, self.rps.counter)
120 | logging.info('Stored results: %d, improved: %s' % (self.user.points, self.user.improvement))
121 |
122 |
123 | def fire(self, event):
124 | try:
125 | self.tank.fire(event.url, event.drum)
126 | self.rps.add_event(self.ioloop.time(), event)
127 | self.serv.send(self.get_current_state())
128 | except Exception as e:
129 | if e.message and e.message[0] == 'H':
130 | self.hresults()
131 |
132 |
133 | def hresults(self):
134 | if (self.state != State.ACTION):
135 | raise Exception('Incorrect state transcision!')
136 |
137 | logging.info('Pre-hack for %s' % self.user)
138 | if not self.top.add_hresult(self.user):
139 | self.rps.hresult = True
140 | logging.info('Hacked!!')
141 | self.state = State.HRESULTS
142 | self.timer_counter = State.COUNTDOWN_TIME * 5
143 | self.timer_fn = State.results
144 |
145 |
146 | def timer(self):
147 | if self.timer_counter is None:
148 | return
149 |
150 | logging.debug('timer %d' % self.timer_counter)
151 | self.serv.send(self.get_current_state())
152 | if self.timer_counter > 0:
153 | self.timer_counter -= 1;
154 |
155 | if self.timer_counter == 0:
156 | self.timer_counter = None
157 | self.timer_fn(self)
158 |
159 |
160 | def post_event(self, event):
161 | self.ioloop.add_callback(State.process_event, self, event)
162 |
163 | def process_event(self, event):
164 | logging.debug('Processing event %s, state: %d' % (event, self.state))
165 | if self.state == State.RESULTS:
166 | if isinstance(event, events.QRCodeEvent):
167 | self.greetings(event)
168 | return
169 |
170 | if isinstance(event, events.MidiEvent):
171 | if (self.state == State.GREETINGS):
172 | self.countdown()
173 | return
174 |
175 | if (self.state == State.ACTION):
176 | self.fire(event)
177 | return
178 |
179 |
180 | options.define('config', type=str, help='Path to config file',
181 | callback=lambda path: options.parse_config_file(path, final=False))
182 | options.define('tank', type=str, help='Tank host\'s ip address', default='127.0.0.1')
183 | options.define('midi_device', type=int, help='Midi device number', default=24)
184 | options.define('midi_port', type=int, help='Midi port number', default=0)
185 | options.define('qrscanner_port', type=str, help='QRCode scanner port', default='/dev/ttyUSB0')
186 |
187 | options.parse_command_line()
188 | ioloop = ioloop.IOLoop.instance()
189 |
190 | state = State(ioloop)
191 |
192 | MidiE = midi_emitter.Emitter(state)
193 | MidiE.run(options.options.midi_device, options.options.midi_port)
194 |
195 | QRE = qrcode_emitter.Emitter(state, ioloop)
196 | QRE.run(options.options.qrscanner_port)
197 |
198 | state.run()
199 |
200 |
--------------------------------------------------------------------------------
/static/css/rickshaw.css:
--------------------------------------------------------------------------------
1 | .rickshaw_graph .detail {
2 | pointer-events: none;
3 | position: absolute;
4 | top: 0;
5 | z-index: 2;
6 | background: rgba(0, 0, 0, 0.1);
7 | bottom: 0;
8 | width: 1px;
9 | transition: opacity 0.25s linear;
10 | -moz-transition: opacity 0.25s linear;
11 | -o-transition: opacity 0.25s linear;
12 | -webkit-transition: opacity 0.25s linear;
13 | }
14 | .rickshaw_graph .detail.inactive {
15 | opacity: 0;
16 | }
17 | .rickshaw_graph .detail .item.active {
18 | opacity: 1;
19 | }
20 | .rickshaw_graph .detail .x_label {
21 | font-family: Arial, sans-serif;
22 | border-radius: 3px;
23 | padding: 6px;
24 | opacity: 0.5;
25 | border: 1px solid #e0e0e0;
26 | font-size: 12px;
27 | position: absolute;
28 | background: white;
29 | white-space: nowrap;
30 | }
31 | .rickshaw_graph .detail .x_label.left {
32 | left: 0;
33 | }
34 | .rickshaw_graph .detail .x_label.right {
35 | right: 0;
36 | }
37 | .rickshaw_graph .detail .item {
38 | position: absolute;
39 | z-index: 2;
40 | border-radius: 3px;
41 | padding: 0.25em;
42 | font-size: 12px;
43 | font-family: Arial, sans-serif;
44 | opacity: 0;
45 | background: rgba(0, 0, 0, 0.4);
46 | color: white;
47 | border: 1px solid rgba(0, 0, 0, 0.4);
48 | margin-left: 1em;
49 | margin-right: 1em;
50 | margin-top: -1em;
51 | white-space: nowrap;
52 | }
53 | .rickshaw_graph .detail .item.left {
54 | left: 0;
55 | }
56 | .rickshaw_graph .detail .item.right {
57 | right: 0;
58 | }
59 | .rickshaw_graph .detail .item.active {
60 | opacity: 1;
61 | background: rgba(0, 0, 0, 0.8);
62 | }
63 | .rickshaw_graph .detail .item:after {
64 | position: absolute;
65 | display: block;
66 | width: 0;
67 | height: 0;
68 |
69 | content: "";
70 |
71 | border: 5px solid transparent;
72 | }
73 | .rickshaw_graph .detail .item.left:after {
74 | top: 1em;
75 | left: -5px;
76 | margin-top: -5px;
77 | border-right-color: rgba(0, 0, 0, 0.8);
78 | border-left-width: 0;
79 | }
80 | .rickshaw_graph .detail .item.right:after {
81 | top: 1em;
82 | right: -5px;
83 | margin-top: -5px;
84 | border-left-color: rgba(0, 0, 0, 0.8);
85 | border-right-width: 0;
86 | }
87 | .rickshaw_graph .detail .dot {
88 | width: 4px;
89 | height: 4px;
90 | margin-left: -3px;
91 | margin-top: -3.5px;
92 | border-radius: 5px;
93 | position: absolute;
94 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
95 | box-sizing: content-box;
96 | -moz-box-sizing: content-box;
97 | background: white;
98 | border-width: 2px;
99 | border-style: solid;
100 | display: none;
101 | background-clip: padding-box;
102 | }
103 | .rickshaw_graph .detail .dot.active {
104 | display: block;
105 | }
106 | /* graph */
107 |
108 | .rickshaw_graph {
109 | position: relative;
110 | }
111 | .rickshaw_graph svg {
112 | display: block;
113 | overflow: hidden;
114 | }
115 |
116 | /* ticks */
117 |
118 | .rickshaw_graph .x_tick {
119 | position: absolute;
120 | top: 0;
121 | bottom: 0;
122 | width: 0px;
123 | border-left: 1px dotted rgba(0, 0, 0, 0.2);
124 | pointer-events: none;
125 | }
126 | .rickshaw_graph .x_tick .title {
127 | position: absolute;
128 | font-size: 12px;
129 | font-family: Arial, sans-serif;
130 | opacity: 0.5;
131 | white-space: nowrap;
132 | margin-left: 3px;
133 | bottom: 1px;
134 | }
135 |
136 | /* annotations */
137 |
138 | .rickshaw_annotation_timeline {
139 | height: 1px;
140 | border-top: 1px solid #e0e0e0;
141 | margin-top: 10px;
142 | position: relative;
143 | }
144 | .rickshaw_annotation_timeline .annotation {
145 | position: absolute;
146 | height: 6px;
147 | width: 6px;
148 | margin-left: -2px;
149 | top: -3px;
150 | border-radius: 5px;
151 | background-color: rgba(0, 0, 0, 0.25);
152 | }
153 | .rickshaw_graph .annotation_line {
154 | position: absolute;
155 | top: 0;
156 | bottom: -6px;
157 | width: 0px;
158 | border-left: 2px solid rgba(0, 0, 0, 0.3);
159 | display: none;
160 | }
161 | .rickshaw_graph .annotation_line.active {
162 | display: block;
163 | }
164 |
165 | .rickshaw_graph .annotation_range {
166 | background: rgba(0, 0, 0, 0.1);
167 | display: none;
168 | position: absolute;
169 | top: 0;
170 | bottom: -6px;
171 | }
172 | .rickshaw_graph .annotation_range.active {
173 | display: block;
174 | }
175 | .rickshaw_graph .annotation_range.active.offscreen {
176 | display: none;
177 | }
178 |
179 | .rickshaw_annotation_timeline .annotation .content {
180 | background: white;
181 | color: black;
182 | opacity: 0.9;
183 | padding: 5px 5px;
184 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
185 | border-radius: 3px;
186 | position: relative;
187 | z-index: 20;
188 | font-size: 12px;
189 | padding: 6px 8px 8px;
190 | top: 18px;
191 | left: -11px;
192 | width: 160px;
193 | display: none;
194 | cursor: pointer;
195 | }
196 | .rickshaw_annotation_timeline .annotation .content:before {
197 | content: "\25b2";
198 | position: absolute;
199 | top: -11px;
200 | color: white;
201 | text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.8);
202 | }
203 | .rickshaw_annotation_timeline .annotation.active,
204 | .rickshaw_annotation_timeline .annotation:hover {
205 | background-color: rgba(0, 0, 0, 0.8);
206 | cursor: none;
207 | }
208 | .rickshaw_annotation_timeline .annotation .content:hover {
209 | z-index: 50;
210 | }
211 | .rickshaw_annotation_timeline .annotation.active .content {
212 | display: block;
213 | }
214 | .rickshaw_annotation_timeline .annotation:hover .content {
215 | display: block;
216 | z-index: 50;
217 | }
218 | .rickshaw_graph .y_axis,
219 | .rickshaw_graph .x_axis_d3 {
220 | fill: none;
221 | }
222 | .rickshaw_graph .y_ticks .tick line,
223 | .rickshaw_graph .x_ticks_d3 .tick {
224 | stroke: rgba(0, 0, 0, 0.16);
225 | stroke-width: 2px;
226 | shape-rendering: crisp-edges;
227 | pointer-events: none;
228 | }
229 | .rickshaw_graph .y_grid .tick,
230 | .rickshaw_graph .x_grid_d3 .tick {
231 | z-index: -1;
232 | stroke: rgba(0, 0, 0, 0.20);
233 | stroke-width: 1px;
234 | stroke-dasharray: 1 1;
235 | }
236 | .rickshaw_graph .y_grid .tick[data-y-value="0"] {
237 | stroke-dasharray: 1 0;
238 | }
239 | .rickshaw_graph .y_grid path,
240 | .rickshaw_graph .x_grid_d3 path {
241 | fill: none;
242 | stroke: none;
243 | }
244 | .rickshaw_graph .y_ticks path,
245 | .rickshaw_graph .x_ticks_d3 path {
246 | fill: none;
247 | stroke: #808080;
248 | }
249 | .rickshaw_graph .y_ticks text,
250 | .rickshaw_graph .x_ticks_d3 text {
251 | opacity: 0.5;
252 | font-size: 12px;
253 | pointer-events: none;
254 | }
255 | .rickshaw_graph .x_tick.glow .title,
256 | .rickshaw_graph .y_ticks.glow text {
257 | fill: black;
258 | color: black;
259 | text-shadow:
260 | -1px 1px 0 rgba(255, 255, 255, 0.1),
261 | 1px -1px 0 rgba(255, 255, 255, 0.1),
262 | 1px 1px 0 rgba(255, 255, 255, 0.1),
263 | 0px 1px 0 rgba(255, 255, 255, 0.1),
264 | 0px -1px 0 rgba(255, 255, 255, 0.1),
265 | 1px 0px 0 rgba(255, 255, 255, 0.1),
266 | -1px 0px 0 rgba(255, 255, 255, 0.1),
267 | -1px -1px 0 rgba(255, 255, 255, 0.1);
268 | }
269 | .rickshaw_graph .x_tick.inverse .title,
270 | .rickshaw_graph .y_ticks.inverse text {
271 | fill: white;
272 | color: white;
273 | text-shadow:
274 | -1px 1px 0 rgba(0, 0, 0, 0.8),
275 | 1px -1px 0 rgba(0, 0, 0, 0.8),
276 | 1px 1px 0 rgba(0, 0, 0, 0.8),
277 | 0px 1px 0 rgba(0, 0, 0, 0.8),
278 | 0px -1px 0 rgba(0, 0, 0, 0.8),
279 | 1px 0px 0 rgba(0, 0, 0, 0.8),
280 | -1px 0px 0 rgba(0, 0, 0, 0.8),
281 | -1px -1px 0 rgba(0, 0, 0, 0.8);
282 | }
283 | .rickshaw_legend {
284 | font-family: Arial;
285 | font-size: 12px;
286 | color: white;
287 | background: #404040;
288 | display: inline-block;
289 | padding: 12px 5px;
290 | border-radius: 2px;
291 | position: relative;
292 | }
293 | .rickshaw_legend:hover {
294 | z-index: 10;
295 | }
296 | .rickshaw_legend .swatch {
297 | width: 10px;
298 | height: 10px;
299 | border: 1px solid rgba(0, 0, 0, 0.2);
300 | }
301 | .rickshaw_legend .line {
302 | clear: both;
303 | line-height: 140%;
304 | padding-right: 15px;
305 | }
306 | .rickshaw_legend .line .swatch {
307 | display: inline-block;
308 | margin-right: 3px;
309 | border-radius: 2px;
310 | }
311 | .rickshaw_legend .label {
312 | margin: 0;
313 | white-space: nowrap;
314 | display: inline;
315 | font-size: inherit;
316 | background-color: transparent;
317 | color: inherit;
318 | font-weight: normal;
319 | line-height: normal;
320 | padding: 0px;
321 | text-shadow: none;
322 | }
323 | .rickshaw_legend .action:hover {
324 | opacity: 0.6;
325 | }
326 | .rickshaw_legend .action {
327 | margin-right: 0.2em;
328 | font-size: 10px;
329 | opacity: 0.2;
330 | cursor: pointer;
331 | font-size: 14px;
332 | }
333 | .rickshaw_legend .line.disabled {
334 | opacity: 0.4;
335 | }
336 | .rickshaw_legend ul {
337 | list-style-type: none;
338 | margin: 0;
339 | padding: 0;
340 | margin: 2px;
341 | cursor: pointer;
342 | }
343 | .rickshaw_legend li {
344 | display: inline-block;
345 | padding: 0 0 0 2px;
346 | min-width: 80px;
347 | white-space: nowrap;
348 | }
349 | .rickshaw_legend li:hover {
350 | background: rgba(255, 255, 255, 0.08);
351 | border-radius: 3px;
352 | }
353 | .rickshaw_legend li:active {
354 | background: rgba(255, 255, 255, 0.2);
355 | border-radius: 3px;
356 | }
357 |
--------------------------------------------------------------------------------
/static/css/custom.css:
--------------------------------------------------------------------------------
1 | .fs {
2 | height: 100vh;
3 | }
4 |
5 |
6 | .rickshaw_graph .detail {
7 | pointer-events: none;
8 | position: absolute;
9 | top: 0;
10 | z-index: 2;
11 | background: rgba(0, 0, 0, 0.1);
12 | bottom: 0;
13 | width: 1px;
14 | transition: opacity 0.25s linear;
15 | -moz-transition: opacity 0.25s linear;
16 | -o-transition: opacity 0.25s linear;
17 | -webkit-transition: opacity 0.25s linear;
18 | }
19 | .rickshaw_graph .detail.inactive {
20 | opacity: 0;
21 | }
22 | .rickshaw_graph .detail .item.active {
23 | opacity: 1;
24 | }
25 | .rickshaw_graph .detail .x_label {
26 | font-family: Arial, sans-serif;
27 | border-radius: 3px;
28 | padding: 6px;
29 | opacity: 0.5;
30 | border: 1px solid #e0e0e0;
31 | font-size: 12px;
32 | position: absolute;
33 | background: white;
34 | white-space: nowrap;
35 | }
36 | .rickshaw_graph .detail .x_label.left {
37 | left: 0;
38 | }
39 | .rickshaw_graph .detail .x_label.right {
40 | right: 0;
41 | }
42 | .rickshaw_graph .detail .item {
43 | position: absolute;
44 | z-index: 2;
45 | border-radius: 3px;
46 | padding: 0.25em;
47 | font-size: 12px;
48 | font-family: Arial, sans-serif;
49 | opacity: 0;
50 | background: rgba(0, 0, 0, 0.4);
51 | color: white;
52 | border: 1px solid rgba(0, 0, 0, 0.4);
53 | margin-left: 1em;
54 | margin-right: 1em;
55 | margin-top: -1em;
56 | white-space: nowrap;
57 | }
58 | .rickshaw_graph .detail .item.left {
59 | left: 0;
60 | }
61 | .rickshaw_graph .detail .item.right {
62 | right: 0;
63 | }
64 | .rickshaw_graph .detail .item.active {
65 | opacity: 1;
66 | background: rgba(0, 0, 0, 0.8);
67 | }
68 | .rickshaw_graph .detail .item:after {
69 | position: absolute;
70 | display: block;
71 | width: 0;
72 | height: 0;
73 |
74 | content: "";
75 |
76 | border: 5px solid transparent;
77 | }
78 | .rickshaw_graph .detail .item.left:after {
79 | top: 1em;
80 | left: -5px;
81 | margin-top: -5px;
82 | border-right-color: rgba(0, 0, 0, 0.8);
83 | border-left-width: 0;
84 | }
85 | .rickshaw_graph .detail .item.right:after {
86 | top: 1em;
87 | right: -5px;
88 | margin-top: -5px;
89 | border-left-color: rgba(0, 0, 0, 0.8);
90 | border-right-width: 0;
91 | }
92 | .rickshaw_graph .detail .dot {
93 | width: 4px;
94 | height: 4px;
95 | margin-left: -3px;
96 | margin-top: -3.5px;
97 | border-radius: 5px;
98 | position: absolute;
99 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
100 | box-sizing: content-box;
101 | -moz-box-sizing: content-box;
102 | background: white;
103 | border-width: 2px;
104 | border-style: solid;
105 | display: none;
106 | background-clip: padding-box;
107 | }
108 | .rickshaw_graph .detail .dot.active {
109 | display: block;
110 | }
111 | /* graph */
112 |
113 | .rickshaw_graph {
114 | position: relative;
115 | }
116 | .rickshaw_graph svg {
117 | display: block;
118 | overflow: hidden;
119 | }
120 |
121 | /* ticks */
122 |
123 | .rickshaw_graph .x_tick {
124 | position: absolute;
125 | top: 0;
126 | bottom: 0;
127 | width: 0px;
128 | border-left: 1px dotted rgba(0, 0, 0, 0.2);
129 | pointer-events: none;
130 | }
131 | .rickshaw_graph .x_tick .title {
132 | position: absolute;
133 | font-size: 12px;
134 | font-family: Arial, sans-serif;
135 | opacity: 0.5;
136 | white-space: nowrap;
137 | margin-left: 3px;
138 | bottom: 1px;
139 | }
140 |
141 | /* annotations */
142 |
143 | .rickshaw_annotation_timeline {
144 | height: 1px;
145 | border-top: 1px solid #e0e0e0;
146 | margin-top: 10px;
147 | position: relative;
148 | }
149 | .rickshaw_annotation_timeline .annotation {
150 | position: absolute;
151 | height: 6px;
152 | width: 6px;
153 | margin-left: -2px;
154 | top: -3px;
155 | border-radius: 5px;
156 | background-color: rgba(0, 0, 0, 0.25);
157 | }
158 | .rickshaw_graph .annotation_line {
159 | position: absolute;
160 | top: 0;
161 | bottom: -6px;
162 | width: 0px;
163 | border-left: 2px solid rgba(0, 0, 0, 0.3);
164 | display: none;
165 | }
166 | .rickshaw_graph .annotation_line.active {
167 | display: block;
168 | }
169 |
170 | .rickshaw_graph .annotation_range {
171 | background: rgba(0, 0, 0, 0.1);
172 | display: none;
173 | position: absolute;
174 | top: 0;
175 | bottom: -6px;
176 | }
177 | .rickshaw_graph .annotation_range.active {
178 | display: block;
179 | }
180 | .rickshaw_graph .annotation_range.active.offscreen {
181 | display: none;
182 | }
183 |
184 | .rickshaw_annotation_timeline .annotation .content {
185 | background: white;
186 | color: black;
187 | opacity: 0.9;
188 | padding: 5px 5px;
189 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
190 | border-radius: 3px;
191 | position: relative;
192 | z-index: 20;
193 | font-size: 12px;
194 | padding: 6px 8px 8px;
195 | top: 18px;
196 | left: -11px;
197 | width: 160px;
198 | display: none;
199 | cursor: pointer;
200 | }
201 | .rickshaw_annotation_timeline .annotation .content:before {
202 | content: "\25b2";
203 | position: absolute;
204 | top: -11px;
205 | color: white;
206 | text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.8);
207 | }
208 | .rickshaw_annotation_timeline .annotation.active,
209 | .rickshaw_annotation_timeline .annotation:hover {
210 | background-color: rgba(0, 0, 0, 0.8);
211 | cursor: none;
212 | }
213 | .rickshaw_annotation_timeline .annotation .content:hover {
214 | z-index: 50;
215 | }
216 | .rickshaw_annotation_timeline .annotation.active .content {
217 | display: block;
218 | }
219 | .rickshaw_annotation_timeline .annotation:hover .content {
220 | display: block;
221 | z-index: 50;
222 | }
223 | .rickshaw_graph .y_axis,
224 | .rickshaw_graph .x_axis_d3 {
225 | fill: none;
226 | }
227 | .rickshaw_graph .y_ticks .tick line,
228 | .rickshaw_graph .x_ticks_d3 .tick {
229 | stroke: rgba(0, 0, 0, 0.16);
230 | stroke-width: 2px;
231 | shape-rendering: crisp-edges;
232 | pointer-events: none;
233 | }
234 | .rickshaw_graph .y_grid .tick,
235 | .rickshaw_graph .x_grid_d3 .tick {
236 | z-index: -1;
237 | stroke: rgba(0, 0, 0, 0.20);
238 | stroke-width: 1px;
239 | stroke-dasharray: 1 1;
240 | }
241 | .rickshaw_graph .y_grid .tick[data-y-value="0"] {
242 | stroke-dasharray: 1 0;
243 | }
244 | .rickshaw_graph .y_grid path,
245 | .rickshaw_graph .x_grid_d3 path {
246 | fill: none;
247 | stroke: none;
248 | }
249 | .rickshaw_graph .y_ticks path,
250 | .rickshaw_graph .x_ticks_d3 path {
251 | fill: none;
252 | stroke: #808080;
253 | }
254 | .rickshaw_graph .y_ticks text,
255 | .rickshaw_graph .x_ticks_d3 text {
256 | opacity: 0.5;
257 | font-size: 12px;
258 | pointer-events: none;
259 | }
260 | .rickshaw_graph .x_tick.glow .title,
261 | .rickshaw_graph .y_ticks.glow text {
262 | fill: black;
263 | color: black;
264 | text-shadow:
265 | -1px 1px 0 rgba(255, 255, 255, 0.1),
266 | 1px -1px 0 rgba(255, 255, 255, 0.1),
267 | 1px 1px 0 rgba(255, 255, 255, 0.1),
268 | 0px 1px 0 rgba(255, 255, 255, 0.1),
269 | 0px -1px 0 rgba(255, 255, 255, 0.1),
270 | 1px 0px 0 rgba(255, 255, 255, 0.1),
271 | -1px 0px 0 rgba(255, 255, 255, 0.1),
272 | -1px -1px 0 rgba(255, 255, 255, 0.1);
273 | }
274 | .rickshaw_graph .x_tick.inverse .title,
275 | .rickshaw_graph .y_ticks.inverse text {
276 | fill: white;
277 | color: white;
278 | text-shadow:
279 | -1px 1px 0 rgba(0, 0, 0, 0.8),
280 | 1px -1px 0 rgba(0, 0, 0, 0.8),
281 | 1px 1px 0 rgba(0, 0, 0, 0.8),
282 | 0px 1px 0 rgba(0, 0, 0, 0.8),
283 | 0px -1px 0 rgba(0, 0, 0, 0.8),
284 | 1px 0px 0 rgba(0, 0, 0, 0.8),
285 | -1px 0px 0 rgba(0, 0, 0, 0.8),
286 | -1px -1px 0 rgba(0, 0, 0, 0.8);
287 | }
288 | .rickshaw_legend {
289 | font-family: Arial;
290 | font-size: 12px;
291 | color: white;
292 | background: #404040;
293 | display: inline-block;
294 | padding: 12px 5px;
295 | border-radius: 2px;
296 | position: relative;
297 | }
298 | .rickshaw_legend:hover {
299 | z-index: 10;
300 | }
301 | .rickshaw_legend .swatch {
302 | width: 10px;
303 | height: 10px;
304 | border: 1px solid rgba(0, 0, 0, 0.2);
305 | }
306 | .rickshaw_legend .line {
307 | clear: both;
308 | line-height: 140%;
309 | padding-right: 15px;
310 | }
311 | .rickshaw_legend .line .swatch {
312 | display: inline-block;
313 | margin-right: 3px;
314 | border-radius: 2px;
315 | }
316 | .rickshaw_legend .label {
317 | margin: 0;
318 | white-space: nowrap;
319 | display: inline;
320 | font-size: inherit;
321 | background-color: transparent;
322 | color: inherit;
323 | font-weight: normal;
324 | line-height: normal;
325 | padding: 0px;
326 | text-shadow: none;
327 | }
328 | .rickshaw_legend .action:hover {
329 | opacity: 0.6;
330 | }
331 | .rickshaw_legend .action {
332 | margin-right: 0.2em;
333 | font-size: 10px;
334 | opacity: 0.2;
335 | cursor: pointer;
336 | font-size: 14px;
337 | }
338 | .rickshaw_legend .line.disabled {
339 | opacity: 0.4;
340 | }
341 | .rickshaw_legend ul {
342 | list-style-type: none;
343 | margin: 0;
344 | padding: 0;
345 | margin: 2px;
346 | cursor: pointer;
347 | }
348 | .rickshaw_legend li {
349 | display: inline-block;
350 | padding: 0 0 0 2px;
351 | min-width: 80px;
352 | white-space: nowrap;
353 | }
354 | .rickshaw_legend li:hover {
355 | background: rgba(255, 255, 255, 0.08);
356 | border-radius: 3px;
357 | }
358 | .rickshaw_legend li:active {
359 | background: rgba(255, 255, 255, 0.2);
360 | border-radius: 3px;
361 | }
--------------------------------------------------------------------------------
/static/js/vendor/cubism.min.js:
--------------------------------------------------------------------------------
1 | (function(a){function d(a){return a}function e(){}function j(a){return Math.floor(a/1e3)}function k(a){var b=a.indexOf("|"),c=a.substring(0,b),d=c.lastIndexOf(","),e=c.lastIndexOf(",",d-1),f=c.lastIndexOf(",",e-1),g=c.substring(f+1,e)*1e3,h=c.substring(d+1)*1e3;return a.substring(b+1).split(",").slice(1).map(function(a){return+a})}function l(a){if(!(a instanceof e))throw new Error("invalid context");this.context=a}function o(a,b){return function(c,d,e,f){a(new Date(+c+b),new Date(+d+b),e,f)}}function p(a,b){l.call(this,a),b=+b;var c=b+"";this.valueOf=function(){return b},this.toString=function(){return c}}function r(a,b){function c(b,c){if(c instanceof l){if(b.context!==c.context)throw new Error("mismatch context")}else c=new p(b.context,c);l.call(this,b.context),this.left=b,this.right=c,this.toString=function(){return b+" "+a+" "+c}}var d=c.prototype=Object.create(l.prototype);return d.valueAt=function(a){return b(this.left.valueAt(a),this.right.valueAt(a))},d.shift=function(a){return new c(this.left.shift(a),this.right.shift(a))},d.on=function(a,b){return arguments.length<2?this.left.on(a):(this.left.on(a,b),this.right.on(a,b),this)},function(a){return new c(this,a)}}function u(a){return a&16777214}function v(a){return(a+1&16777214)-1}function z(a){a.style("position","absolute").style("top",0).style("bottom",0).style("width","1px").style("pointer-events","none")}function A(a){return a+"px"}var b=a.cubism={version:"1.6.0"},c=0;b.option=function(a,c){var d=b.options(a);return d.length?d[0]:c},b.options=function(a,b){var c=location.search.substring(1).split("&"),d=[],e=-1,f=c.length,g;while(++e0&&a.focus(--o);break;case 39:o==null&&(o=d-2),o=c)return c;if(a<=b)return b;var d,e,f;for(f=a;f<=c;f++){d=avail_rsts.indexOf(f);if(d>-1){e=avail_rsts[d];break}}var g;for(f=a;f>=b;f--){d=avail_rsts.indexOf(f);if(d>-1){g=avail_rsts[d];break}}return e-ae?3600:(i=f(c),d>g&&i<900?900:d>h&&i<60?60:i)}var d={},e=this;auth_string="Basic "+btoa(a+":"+c),avail_rsts=[1,60,900,3600];var j=function(a){function d(b,d,e){var f="compose="+a+"&start_time="+b+"&end_time="+d+"&resolution="+g(b,d,e);return c+"?"+f}function e(a,b,c,d){var e=[];for(i=a;i<=b;i+=c){var f=[];while(d.length&&d[0].measure_time<=i)f.push(d.shift().value);var g;f.length?g=f.reduce(function(a,b){return a+b})/f.length:g=e.length?e[e.length-1]:0,e.push(g)}return e}var c="https://metrics-api.librato.com/v1/metrics";return request={},request.fire=function(a,c,f,g){function i(j){d3.json(j).header("X-Requested-With","XMLHttpRequest").header("Authorization",auth_string).header("Librato-User-Agent","cubism/"+b.version).get(function(b,j){if(!b){if(j.measurements.length===0)return;j.measurements[0].series.forEach(function(a){h.push(a)});var k="query"in j&&"next_time"in j.query;if(k)i(d(j.query.next_time,c,f));else{var l=e(a,c,f,h);g(l)}}})}var h=[];i(d(a,c,f))},request};return d.metric=function(a){return e.metric(function(b,c,d,e){j(a).fire(h(b),h(c),h(d),function(a){e(null,a)})},a+="")},d.toString=function(){return"librato"},d};var h=function(a){return Math.floor(a/1e3)};f.graphite=function(a){arguments.length||(a="");var b={},c=this;return b.metric=function(b){var d="sum",e=c.metric(function(c,e,f,g){var h=b;f!==1e4&&(h="summarize("+h+",'"+(f%36e5?f%6e4?f/1e3+"sec":f/6e4+"min":f/36e5+"hour")+"','"+d+"')"),d3.text(a+"/render?format=raw"+"&target="+encodeURIComponent("alias("+h+",'')")+"&from="+j(c-2*f)+"&until="+j(e-1e3),function(a){if(!a)return g(new Error("unable to load data"));g(null,k(a))})},b+="");return e.summarize=function(a){return d=a,e},e},b.find=function(b,c){d3.json(a+"/metrics/find?format=completer"+"&query="+encodeURIComponent(b),function(a){if(!a)return c(new Error("unable to find metrics"));c(null,a.metrics.map(function(a){return a.path}))})},b.toString=function(){return a},b},f.gangliaWeb=function(a){var b="",c="/ganglia2/";arguments.length&&(a.host&&(b=a.host),a.uriPathPrefix&&(c=a.uriPathPrefix,c[0]!="/"&&(c="/"+c),c[c.length-1]!="/"&&(c+="/")));var d={},e=this;return d.metric=function(a){var d=a.clusterName,f=a.metricName,g=a.hostName,h=a.isReport||!1,i=a.titleGenerator||function(a){return"clusterName:"+d+" metricName:"+f+(g?" hostName:"+g:"")},j=a.onChangeCallback,k=h?"g":"m",l=e.metric(function(a,e,h,i){function j(){return"c="+d+"&"+k+"="+f+(g?"&h="+g:"")+"&cs="+a/1e3+"&ce="+e/1e3+"&step="+h/1e3+"&graphlot=1"}d3.json(b+c+"graph.php?"+j(),function(a){if(!a)return i(new Error("Unable to fetch GangliaWeb data"));i(null,a[0].data)})},i(a));return l.toString=function(){return i(a)},j&&l.on("change",j),l},d.toString=function(){return b+c},d};var m=l.prototype;b.metric=l,m.valueAt=function(){return NaN},m.alias=function(a){return this.toString=function(){return a},this},m.extent=function(){var a=0,b=this.context.size(),c,d=Infinity,e=-Infinity;while(++ae&&(e=c);return[d,e]},m.on=function(a,b){return arguments.length<2?null:this},m.shift=function(){return this},m.on=function(){return arguments.length<2?null:this},f.metric=function(a,b){function r(b,c){var d=Math.min(j,Math.round((b-g)/i));if(!d||q)return;q=!0,d=Math.min(j,d+n);var f=new Date(c-d*i);a(f,c,i,function(a,b){q=!1;if(a)return console.warn(a);var d=isFinite(g)?Math.round((f-g)/i):0;for(var h=0,j=b.length;h1&&(e.toString=function(){return b}),e};var n=6,q=p.prototype=Object.create(l.prototype);q.valueAt=function(){return+this},q.extent=function(){return[+this,+this]},m.add=r("+",function(a,b){return a+b}),m.subtract=r("-",function(a,b){return a-b}),m.multiply=r("*",function(a,b){return a*b}),m.divide=r("/",function(a,b){return a/b}),f.horizon=function(){function o(o){o.on("mousemove.horizon",function(){a.focus(Math.round(d3.mouse(this)[0]))}).on("mouseout.horizon",function(){a.focus(null)}),o.append("canvas").attr("width",f).attr("height",g),o.append("span").attr("class","title").text(k),o.append("span").attr("class","value"),o.each(function(k,o){function B(c,d){w.save();var i=r.extent();A=i.every(isFinite),t!=null&&(i=t);var j=0,k=Math.max(-i[0],i[1]);if(this===a){if(k==y){j=f-n;var l=(c-u)/v;if(l=0)continue;w.fillRect(x,h(-C),1,q-h(-C))}}}w.restore()}function C(a){a==null&&(a=f-1);var b=r.valueAt(a);x.datum(b).text(isNaN(b)?null:l)}var p=this,q=++c,r=typeof i=="function"?i.call(p,k,o):i,s=typeof m=="function"?m.call(p,k,o):m,t=typeof j=="function"?j.call(p,k,o):j,u=-Infinity,v=a.step(),w=d3.select(p).select("canvas"),x=d3.select(p).select(".value"),y,z=s.length>>1,A;w.datum({id:q,metric:r}),w=w.node().getContext("2d"),a.on("change.horizon-"+q,B),a.on("focus.horizon-"+q,C),r.on("change.horizon-"+q,function(a,b){B(a,b),C(),A&&r.on("change.horizon-"+q,d)})})}var a=this,b="offset",e=document.createElement("canvas"),f=e.width=a.size(),g=e.height=30,h=d3.scale.linear().interpolate(d3.interpolateRound),i=d,j=null,k=d,l=d3.format(".2s"),m=["#08519c","#3182bd","#6baed6","#bdd7e7","#bae4b3","#74c476","#31a354","#006d2c"];return o.remove=function(b){function c(b){b.metric.on("change.horizon-"+b.id,null),a.on("change.horizon-"+b.id,null),a.on("focus.horizon-"+b.id,null)}b.on("mousemove.horizon",null).on("mouseout.horizon",null),b.selectAll("canvas").each(c).remove(),b.selectAll(".title,.value").remove()},o.mode=function(a){return arguments.length?(b=a+"",o):b},o.height=function(a){return arguments.length?(e.height=g=+a,o):g},o.metric=function(a){return arguments.length?(i=a,o):i},o.scale=function(a){return arguments.length?(h=a,o):h},o.extent=function(a){return arguments.length?(j=a,o):j},o.title=function(a){return arguments.length?(k=a,o):k},o.format=function(a){return arguments.length?(l=a,o):l},o.colors=function(a){return arguments.length?(m=a,o):m},o},f.comparison=function(){function o(o){o.on("mousemove.comparison",function(){a.focus(Math.round(d3.mouse(this)[0]))}).on("mouseout.comparison",function(){a.focus(null)}),o.append("canvas").attr("width",b).attr("height",e),o.append("span").attr("class","title").text(j),o.append("span").attr("class","value primary"),o.append("span").attr("class","value change"),o.each(function(j,o){function B(c,d){x.save(),x.clearRect(0,0,b,e);var g=r.extent(),h=s.extent(),i=t==null?g:t;f.domain(i).range([e,0]),A=g.concat(h).every(isFinite);var j=c/a.step()&1?v:u;x.fillStyle=m[2];for(var k=0,l=b;kp&&x.fillRect(j(k),p,1,o-p)}x.fillStyle=m[3];for(k=0;kp&&x.fillRect(j(k),o-n,1,n)}x.restore()}function C(a){a==null&&(a=b-1);var c=r.valueAt(a),d=s.valueAt(a),e=(c-d)/d;y.datum(c).text(isNaN(c)?null:k),z.datum(e).text(isNaN(e)?null:l).attr("class","value change "+(e>0?"positive":e<0?"negative":""))}function D(a,b){B(a,b),C(),A&&(r.on("change.comparison-"+q,d),s.on("change.comparison-"+q,d))}var p=this,q=++c,r=typeof g=="function"?g.call(p,j,o):g,s=typeof h=="function"?h.call(p,j,o):h,t=typeof i=="function"?i.call(p,j,o):i,w=d3.select(p),x=w.select("canvas"),y=w.select(".value.primary"),z=w.select(".value.change"),A;x.datum({id:q,primary:r,secondary:s}),x=x.node().getContext("2d"),r.on("change.comparison-"+q,D),s.on("change.comparison-"+q,D),a.on("change.comparison-"+q,B),a.on("focus.comparison-"+q,C)})}var a=this,b=a.size(),e=120,f=d3.scale.linear().interpolate(d3.interpolateRound),g=function(a){return a[0]},h=function(a){return a[1]},i=null,j=d,k=s,l=t,m=["#9ecae1","#225b84","#a1d99b","#22723a"],n=1.5;return o.remove=function(b){function c(b){b.primary.on("change.comparison-"+b.id,null),b.secondary.on("change.comparison-"+b.id,null),a.on("change.comparison-"+b.id,null),a.on("focus.comparison-"+b.id,null)}b.on("mousemove.comparison",null).on("mouseout.comparison",null),b.selectAll("canvas").each(c).remove(),b.selectAll(".title,.value").remove()},o.height=function(a){return arguments.length?(e=+a,o):e},o.primary=function(a){return arguments.length?(g=a,o):g},o.secondary=function(a){return arguments.length?(h=a,o):h},o.scale=function(a){return arguments.length?(f=a,o):f},o.extent=function(a){return arguments.length?(i=a,o):i},o.title=function(a){return arguments.length?(j=a,o):j},o.formatPrimary=function(a){return arguments.length?(k=a,o):k},o.formatChange=function(a){return arguments.length?(l=a,o):l},o.colors=function(a){return arguments.length?(m=a,o):m},o.strokeWidth=function(a){return arguments.length?(n=a,o):n},o};var s=d3.format(".2s"),t=d3.format("+.0%");f.axis=function(){function g(e){var h=++c,i,j=e.append("svg").datum({id:h}).attr("width",a.size()).attr("height",Math.max(28,-g.tickSize())).append("g").attr("transform","translate(0,"+(d.orient()==="top"?27:4)+")").call(d);a.on("change.axis-"+h,function(){j.call(d),i||(i=d3.select(j.node().appendChild(j.selectAll("text").node().cloneNode(!0))).style("display","none").text(null))}),a.on("focus.axis-"+h,function(a){if(i)if(a==null)i.style("display","none"),j.selectAll("text").style("fill-opacity",null);else{i.style("display",null).attr("x",a).text(f(b.invert(a)));var c=i.node().getComputedTextLength()+6;j.selectAll("text").style("fill-opacity",function(d){return Math.abs(b(d)-a)li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f3f3f3));background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-o-linear-gradient(top,#222 0,#282828 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#222),to(#282828));background-image:linear-gradient(to bottom,#222 0,#282828 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
--------------------------------------------------------------------------------
/static/css/bootstrap-theme.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"bootstrap-theme.css","sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAeA;;;;;;EAME,0CAAA;EC+CA,6FAAA;EACQ,qFAAA;EC5DT;AFiBC;;;;;;;;;;;;EC0CA,0DAAA;EACQ,kDAAA;EC7CT;AFqCC;;EAEE,wBAAA;EEnCH;AFwCD;EG/CI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EA+B2C,2BAAA;EAA2B,oBAAA;EE7BvE;AFAC;;EAEE,2BAAA;EACA,8BAAA;EEEH;AFCC;;EAEE,2BAAA;EACA,uBAAA;EECH;AFEC;;EAEE,2BAAA;EACA,wBAAA;EEAH;AFeD;EGhDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0BD;AFxBC;;EAEE,2BAAA;EACA,8BAAA;EE0BH;AFvBC;;EAEE,2BAAA;EACA,uBAAA;EEyBH;AFtBC;;EAEE,2BAAA;EACA,wBAAA;EEwBH;AFRD;EGjDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkDD;AFhDC;;EAEE,2BAAA;EACA,8BAAA;EEkDH;AF/CC;;EAEE,2BAAA;EACA,uBAAA;EEiDH;AF9CC;;EAEE,2BAAA;EACA,wBAAA;EEgDH;AF/BD;EGlDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0ED;AFxEC;;EAEE,2BAAA;EACA,8BAAA;EE0EH;AFvEC;;EAEE,2BAAA;EACA,uBAAA;EEyEH;AFtEC;;EAEE,2BAAA;EACA,wBAAA;EEwEH;AFtDD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkGD;AFhGC;;EAEE,2BAAA;EACA,8BAAA;EEkGH;AF/FC;;EAEE,2BAAA;EACA,uBAAA;EEiGH;AF9FC;;EAEE,2BAAA;EACA,wBAAA;EEgGH;AF7ED;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0HD;AFxHC;;EAEE,2BAAA;EACA,8BAAA;EE0HH;AFvHC;;EAEE,2BAAA;EACA,uBAAA;EEyHH;AFtHC;;EAEE,2BAAA;EACA,wBAAA;EEwHH;AF7FD;;ECbE,oDAAA;EACQ,4CAAA;EC8GT;AFvFD;;EGvEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHsEF,2BAAA;EE6FD;AF3FD;;;EG5EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4EF,2BAAA;EEiGD;AFvFD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ4GA,oBAAA;EC9CA,6FAAA;EACQ,qFAAA;EC4IT;AFlGD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECqJT;AF/FD;;EAEE,gDAAA;EEiGD;AF7FD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EFgOD;AFrGD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0KT;AF9GD;;EAWI,2CAAA;EEuGH;AFlGD;;;EAGE,kBAAA;EEoGD;AF1FD;EACE,+CAAA;EC3FA,4FAAA;EACQ,oFAAA;ECwLT;AFlFD;EGtJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8FD;AFzFD;EGvJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsGD;AFhGD;EGxJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8GD;AFvGD;EGzJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsHD;AFtGD;EGlKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2QH;AFnGD;EG5KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkRH;AFzGD;EG7KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDyRH;AF/GD;EG9KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDgSH;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AF3HD;EGhLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AF9HD;EGnJI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDoRH;AF1HD;EACE,oBAAA;EC/IA,oDAAA;EACQ,4CAAA;EC4QT;AF3HD;;;EAGE,+BAAA;EGpME,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHkMF,uBAAA;EEiID;AFvHD;ECjKE,mDAAA;EACQ,2CAAA;EC2RT;AFjHD;EG1NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8UH;AFvHD;EG3NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqVH;AF7HD;EG5NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4VH;AFnID;EG7NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmWH;AFzID;EG9NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0WH;AF/ID;EG/NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDiXH;AF9ID;EGvOI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHqOF,uBAAA;EC1LA,2FAAA;EACQ,mFAAA;EC+UT","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &:disabled,\n &[disabled] {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n",null,"// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]}
--------------------------------------------------------------------------------
/static/css/bootstrap-theme.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.2.0 (http://getbootstrap.com)
3 | * Copyright 2011-2014 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | .btn-default,
8 | .btn-primary,
9 | .btn-success,
10 | .btn-info,
11 | .btn-warning,
12 | .btn-danger {
13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
16 | }
17 | .btn-default:active,
18 | .btn-primary:active,
19 | .btn-success:active,
20 | .btn-info:active,
21 | .btn-warning:active,
22 | .btn-danger:active,
23 | .btn-default.active,
24 | .btn-primary.active,
25 | .btn-success.active,
26 | .btn-info.active,
27 | .btn-warning.active,
28 | .btn-danger.active {
29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
31 | }
32 | .btn:active,
33 | .btn.active {
34 | background-image: none;
35 | }
36 | .btn-default {
37 | text-shadow: 0 1px 0 #fff;
38 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
39 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
40 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
41 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
43 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
44 | background-repeat: repeat-x;
45 | border-color: #dbdbdb;
46 | border-color: #ccc;
47 | }
48 | .btn-default:hover,
49 | .btn-default:focus {
50 | background-color: #e0e0e0;
51 | background-position: 0 -15px;
52 | }
53 | .btn-default:active,
54 | .btn-default.active {
55 | background-color: #e0e0e0;
56 | border-color: #dbdbdb;
57 | }
58 | .btn-default:disabled,
59 | .btn-default[disabled] {
60 | background-color: #e0e0e0;
61 | background-image: none;
62 | }
63 | .btn-primary {
64 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
65 | background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
66 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2));
67 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
68 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
69 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
70 | background-repeat: repeat-x;
71 | border-color: #2b669a;
72 | }
73 | .btn-primary:hover,
74 | .btn-primary:focus {
75 | background-color: #2d6ca2;
76 | background-position: 0 -15px;
77 | }
78 | .btn-primary:active,
79 | .btn-primary.active {
80 | background-color: #2d6ca2;
81 | border-color: #2b669a;
82 | }
83 | .btn-primary:disabled,
84 | .btn-primary[disabled] {
85 | background-color: #2d6ca2;
86 | background-image: none;
87 | }
88 | .btn-success {
89 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
90 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
91 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
92 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
93 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
94 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
95 | background-repeat: repeat-x;
96 | border-color: #3e8f3e;
97 | }
98 | .btn-success:hover,
99 | .btn-success:focus {
100 | background-color: #419641;
101 | background-position: 0 -15px;
102 | }
103 | .btn-success:active,
104 | .btn-success.active {
105 | background-color: #419641;
106 | border-color: #3e8f3e;
107 | }
108 | .btn-success:disabled,
109 | .btn-success[disabled] {
110 | background-color: #419641;
111 | background-image: none;
112 | }
113 | .btn-info {
114 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
115 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
116 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
117 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
118 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
119 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
120 | background-repeat: repeat-x;
121 | border-color: #28a4c9;
122 | }
123 | .btn-info:hover,
124 | .btn-info:focus {
125 | background-color: #2aabd2;
126 | background-position: 0 -15px;
127 | }
128 | .btn-info:active,
129 | .btn-info.active {
130 | background-color: #2aabd2;
131 | border-color: #28a4c9;
132 | }
133 | .btn-info:disabled,
134 | .btn-info[disabled] {
135 | background-color: #2aabd2;
136 | background-image: none;
137 | }
138 | .btn-warning {
139 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
140 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
141 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
142 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
143 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
144 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
145 | background-repeat: repeat-x;
146 | border-color: #e38d13;
147 | }
148 | .btn-warning:hover,
149 | .btn-warning:focus {
150 | background-color: #eb9316;
151 | background-position: 0 -15px;
152 | }
153 | .btn-warning:active,
154 | .btn-warning.active {
155 | background-color: #eb9316;
156 | border-color: #e38d13;
157 | }
158 | .btn-warning:disabled,
159 | .btn-warning[disabled] {
160 | background-color: #eb9316;
161 | background-image: none;
162 | }
163 | .btn-danger {
164 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
165 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
166 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
167 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
168 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
169 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
170 | background-repeat: repeat-x;
171 | border-color: #b92c28;
172 | }
173 | .btn-danger:hover,
174 | .btn-danger:focus {
175 | background-color: #c12e2a;
176 | background-position: 0 -15px;
177 | }
178 | .btn-danger:active,
179 | .btn-danger.active {
180 | background-color: #c12e2a;
181 | border-color: #b92c28;
182 | }
183 | .btn-danger:disabled,
184 | .btn-danger[disabled] {
185 | background-color: #c12e2a;
186 | background-image: none;
187 | }
188 | .thumbnail,
189 | .img-thumbnail {
190 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
191 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
192 | }
193 | .dropdown-menu > li > a:hover,
194 | .dropdown-menu > li > a:focus {
195 | background-color: #e8e8e8;
196 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
197 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
198 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
199 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
200 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
201 | background-repeat: repeat-x;
202 | }
203 | .dropdown-menu > .active > a,
204 | .dropdown-menu > .active > a:hover,
205 | .dropdown-menu > .active > a:focus {
206 | background-color: #357ebd;
207 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
208 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
209 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
210 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
211 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
212 | background-repeat: repeat-x;
213 | }
214 | .navbar-default {
215 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
216 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
217 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
218 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
220 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
221 | background-repeat: repeat-x;
222 | border-radius: 4px;
223 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
224 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
225 | }
226 | .navbar-default .navbar-nav > .active > a {
227 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
228 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
229 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3));
230 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
231 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
232 | background-repeat: repeat-x;
233 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
234 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
235 | }
236 | .navbar-brand,
237 | .navbar-nav > li > a {
238 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
239 | }
240 | .navbar-inverse {
241 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
242 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
243 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
244 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
245 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
246 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
247 | background-repeat: repeat-x;
248 | }
249 | .navbar-inverse .navbar-nav > .active > a {
250 | background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);
251 | background-image: -o-linear-gradient(top, #222 0%, #282828 100%);
252 | background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828));
253 | background-image: linear-gradient(to bottom, #222 0%, #282828 100%);
254 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
255 | background-repeat: repeat-x;
256 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
257 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
258 | }
259 | .navbar-inverse .navbar-brand,
260 | .navbar-inverse .navbar-nav > li > a {
261 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
262 | }
263 | .navbar-static-top,
264 | .navbar-fixed-top,
265 | .navbar-fixed-bottom {
266 | border-radius: 0;
267 | }
268 | .alert {
269 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
270 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
271 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
272 | }
273 | .alert-success {
274 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
275 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
276 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
277 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
278 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
279 | background-repeat: repeat-x;
280 | border-color: #b2dba1;
281 | }
282 | .alert-info {
283 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
284 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
285 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
286 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
287 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
288 | background-repeat: repeat-x;
289 | border-color: #9acfea;
290 | }
291 | .alert-warning {
292 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
293 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
294 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
295 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
296 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
297 | background-repeat: repeat-x;
298 | border-color: #f5e79e;
299 | }
300 | .alert-danger {
301 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
302 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
303 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
304 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
305 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
306 | background-repeat: repeat-x;
307 | border-color: #dca7a7;
308 | }
309 | .progress {
310 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
311 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
312 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
313 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
314 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
315 | background-repeat: repeat-x;
316 | }
317 | .progress-bar {
318 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
319 | background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%);
320 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9));
321 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
322 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
323 | background-repeat: repeat-x;
324 | }
325 | .progress-bar-success {
326 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
327 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
328 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
329 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
330 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
331 | background-repeat: repeat-x;
332 | }
333 | .progress-bar-info {
334 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
335 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
336 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
337 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
338 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
339 | background-repeat: repeat-x;
340 | }
341 | .progress-bar-warning {
342 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
343 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
344 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
345 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
346 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
347 | background-repeat: repeat-x;
348 | }
349 | .progress-bar-danger {
350 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
351 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
352 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
353 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
354 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
355 | background-repeat: repeat-x;
356 | }
357 | .progress-bar-striped {
358 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
359 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
360 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
361 | }
362 | .list-group {
363 | border-radius: 4px;
364 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
365 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
366 | }
367 | .list-group-item.active,
368 | .list-group-item.active:hover,
369 | .list-group-item.active:focus {
370 | text-shadow: 0 -1px 0 #3071a9;
371 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
372 | background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%);
373 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3));
374 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
375 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
376 | background-repeat: repeat-x;
377 | border-color: #3278b3;
378 | }
379 | .panel {
380 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
381 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
382 | }
383 | .panel-default > .panel-heading {
384 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
385 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
386 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
387 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
388 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
389 | background-repeat: repeat-x;
390 | }
391 | .panel-primary > .panel-heading {
392 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
393 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
394 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
395 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
396 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
397 | background-repeat: repeat-x;
398 | }
399 | .panel-success > .panel-heading {
400 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
401 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
403 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
405 | background-repeat: repeat-x;
406 | }
407 | .panel-info > .panel-heading {
408 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
409 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
410 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
411 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
412 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
413 | background-repeat: repeat-x;
414 | }
415 | .panel-warning > .panel-heading {
416 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
417 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
418 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
419 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
420 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
421 | background-repeat: repeat-x;
422 | }
423 | .panel-danger > .panel-heading {
424 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
425 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
426 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
427 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
428 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
429 | background-repeat: repeat-x;
430 | }
431 | .well {
432 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
433 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
435 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
437 | background-repeat: repeat-x;
438 | border-color: #dcdcdc;
439 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
440 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
441 | }
442 | /*# sourceMappingURL=bootstrap-theme.css.map */
443 |
--------------------------------------------------------------------------------
/static/js/vendor/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.2.0 (http://getbootstrap.com)
3 | * Copyright 2011-2014 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('
').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j ').appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;e?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(150):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var f=function(){c.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",f).emulateTransitionEnd(150):f()}else b&&b()},c.prototype.checkScrollbar=function(){document.body.clientWidth>=window.innerWidth||(this.scrollbarWidth=this.scrollbarWidth||this.measureScrollbar())},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.scrollbarWidth&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right","")},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};c.VERSION="3.2.0",c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var c=a.contains(document.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!c)return;var d=this,e=this.tip(),f=this.getUID(this.type);this.setContent(),e.attr("id",f),this.$element.attr("aria-describedby",f),this.options.animation&&e.addClass("fade");var g="function"==typeof this.options.placement?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,h=/\s?auto?\s?/i,i=h.test(g);i&&(g=g.replace(h,"")||"top"),e.detach().css({top:0,left:0,display:"block"}).addClass(g).data("bs."+this.type,this),this.options.container?e.appendTo(this.options.container):e.insertAfter(this.$element);var j=this.getPosition(),k=e[0].offsetWidth,l=e[0].offsetHeight;if(i){var m=g,n=this.$element.parent(),o=this.getPosition(n);g="bottom"==g&&j.top+j.height+l-o.scroll>o.height?"top":"top"==g&&j.top-o.scroll-l<0?"bottom":"right"==g&&j.right+k>o.width?"left":"left"==g&&j.left-kg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.2.0",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").empty()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},c.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){var e=a.proxy(this.process,this);this.$body=a("body"),this.$scrollElement=a(a(c).is("body")?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",e),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.2.0",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b="offset",c=0;a.isWindow(this.$scrollElement[0])||(b="position",c=this.$scrollElement.scrollTop()),this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight();var d=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+c,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){d.offsets.push(this[0]),d.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.2.0",c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.closest("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},c.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one("bsTransitionEnd",e).emulateTransitionEnd(150):e(),f.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(c){c.preventDefault(),b.call(a(this),"show")})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.2.0",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=a(document).height(),d=this.$target.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=b-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){null!=this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:b-this.$element.height()-h}))}}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},d.offsetBottom&&(d.offset.bottom=d.offsetBottom),d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------